diff options
author | Waldemar Brodkorb <wbx@openadk.org> | 2014-04-24 16:15:29 +0200 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2014-04-24 16:15:29 +0200 |
commit | 94c82fcf15415a015b602a58a26880bb0ad97da4 (patch) | |
tree | 828a33bd363bfdbc58edbb45cdb2d8e45150d5d9 | |
parent | 839ae24b726ab65e1c4cff172f29e24e9f3ee5cd (diff) |
update 3.12 kernel
-rw-r--r-- | Config.in | 6 | ||||
-rw-r--r-- | mk/kernel-ver.mk | 6 | ||||
-rw-r--r-- | target/arm/raspberry-pi/patches/3.12.18/raspberry-pi.patch (renamed from target/linux/patches/3.12.14/raspberry.patch) | 12640 | ||||
-rw-r--r-- | target/linux/config/Config.in.netfilter.ip4 | 8 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/bsd-compatibility.patch (renamed from target/linux/patches/3.12.14/bsd-compatibility.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/defaults.patch (renamed from target/linux/patches/3.12.14/defaults.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/disable-netfilter.patch (renamed from target/linux/patches/3.12.14/disable-netfilter.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/export-symbol-for-exmap.patch (renamed from target/linux/patches/3.12.14/export-symbol-for-exmap.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/gemalto.patch (renamed from target/linux/patches/3.12.14/gemalto.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/lemote-rfkill.patch (renamed from target/linux/patches/3.12.14/lemote-rfkill.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/microblaze-ethernet.patch (renamed from target/linux/patches/3.12.14/microblaze-ethernet.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/microblaze-setup.patch (renamed from target/linux/patches/3.12.14/microblaze-setup.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/mips-lzo-fix.patch (renamed from target/linux/patches/3.12.14/mips-lzo-fix.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/mtd-rootfs.patch (renamed from target/linux/patches/3.12.14/mtd-rootfs.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/non-static.patch (renamed from target/linux/patches/3.12.14/non-static.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/ppc64-missing-zlib.patch (renamed from target/linux/patches/3.12.14/ppc64-missing-zlib.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/startup.patch (renamed from target/linux/patches/3.12.14/startup.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/usb-defaults-off.patch (renamed from target/linux/patches/3.12.14/usb-defaults-off.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/uuid.patch (renamed from target/linux/patches/3.12.14/uuid.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/vga-cons-default-off.patch (renamed from target/linux/patches/3.12.14/vga-cons-default-off.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/wlan-cf.patch (renamed from target/linux/patches/3.12.14/wlan-cf.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/xargs.patch (renamed from target/linux/patches/3.12.14/xargs.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.12.18/zlib-inflate.patch (renamed from target/linux/patches/3.12.14/zlib-inflate.patch) | 0 | ||||
-rw-r--r-- | toolchain/kernel-headers/patches/3.12.18/cleankernel.patch (renamed from toolchain/kernel-headers/patches/3.12.14/cleankernel.patch) | 0 | ||||
-rw-r--r-- | toolchain/kernel-headers/patches/3.12.18/mkpiggy.patch (renamed from toolchain/kernel-headers/patches/3.12.14/mkpiggy.patch) | 0 | ||||
-rw-r--r-- | toolchain/kernel-headers/patches/3.12.18/relocs.patch (renamed from toolchain/kernel-headers/patches/3.12.14/relocs.patch) | 0 | ||||
-rw-r--r-- | toolchain/kernel-headers/patches/3.12.18/sgidefs.patch (renamed from toolchain/kernel-headers/patches/3.12.14/sgidefs.patch) | 0 | ||||
-rw-r--r-- | toolchain/kernel-headers/patches/3.12.18/sortext.patch (renamed from toolchain/kernel-headers/patches/3.12.14/sortext.patch) | 0 |
28 files changed, 9167 insertions, 3493 deletions
@@ -115,8 +115,8 @@ config ADK_KERNEL_VERSION_3_13_11 prompt "3.13.11" boolean -config ADK_KERNEL_VERSION_3_12_14 - prompt "3.12.14" +config ADK_KERNEL_VERSION_3_12_18 + prompt "3.12.18" boolean config ADK_KERNEL_VERSION_3_11_10 @@ -138,7 +138,7 @@ config ADK_KERNEL_VERSION string default "3.14.1" if ADK_KERNEL_VERSION_3_14_1 default "3.13.11" if ADK_KERNEL_VERSION_3_13_11 - default "3.12.14" if ADK_KERNEL_VERSION_3_12_14 + default "3.12.18" if ADK_KERNEL_VERSION_3_12_18 default "3.11.10" if ADK_KERNEL_VERSION_3_11_10 default "3.10.36" if ADK_KERNEL_VERSION_3_10_36 default "3.4.84" if ADK_KERNEL_VERSION_3_4_84 diff --git a/mk/kernel-ver.mk b/mk/kernel-ver.mk index 602a3065e..5e9002792 100644 --- a/mk/kernel-ver.mk +++ b/mk/kernel-ver.mk @@ -16,11 +16,11 @@ KERNEL_MOD_VERSION:= $(KERNEL_VERSION) KERNEL_RELEASE:= 1 KERNEL_MD5SUM:= d4e06af8b674ac74ba745d52e4382bd3 endif -ifeq ($(ADK_KERNEL_VERSION_3_12_14),y) -KERNEL_VERSION:= 3.12.14 +ifeq ($(ADK_KERNEL_VERSION_3_12_18),y) +KERNEL_VERSION:= 3.12.18 KERNEL_MOD_VERSION:= $(KERNEL_VERSION) KERNEL_RELEASE:= 1 -KERNEL_MD5SUM:= 5575e68e287605ad63d3a1444e9b701d +KERNEL_MD5SUM:= ec32bc59a5feb46c74adb1df7d3e3e98 endif ifeq ($(ADK_KERNEL_VERSION_3_11_10),y) KERNEL_VERSION:= 3.11.10 diff --git a/target/linux/patches/3.12.14/raspberry.patch b/target/arm/raspberry-pi/patches/3.12.18/raspberry-pi.patch index c306f4faf..c5e93d3fb 100644 --- a/target/linux/patches/3.12.14/raspberry.patch +++ b/target/arm/raspberry-pi/patches/3.12.18/raspberry-pi.patch @@ -1,6 +1,57 @@ -diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_cutdown_defconfig linux-raspberry-pi/arch/arm/configs/bcmrpi_cutdown_defconfig ---- linux-3.12.13/arch/arm/configs/bcmrpi_cutdown_defconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/configs/bcmrpi_cutdown_defconfig 2014-03-11 17:51:00.000000000 +0100 +diff -Nur linux-3.12.18/arch/arc/boot/dts/nsimosci.dts linux-rpi/arch/arc/boot/dts/nsimosci.dts +--- linux-3.12.18/arch/arc/boot/dts/nsimosci.dts 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/arc/boot/dts/nsimosci.dts 2014-04-24 16:04:29.363023127 +0200 +@@ -11,16 +11,13 @@ + + / { + compatible = "snps,nsimosci"; +- clock-frequency = <20000000>; /* 20 MHZ */ ++ clock-frequency = <80000000>; /* 80 MHZ */ + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + + chosen { +- /* this is for console on PGU */ +- /* bootargs = "console=tty0 consoleblank=0"; */ +- /* this is for console on serial */ +- bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=ttyS0,115200n8 consoleblank=0 debug"; ++ bootargs = "console=tty0 consoleblank=0"; + }; + + aliases { +@@ -47,14 +44,15 @@ + }; + + uart0: serial@c0000000 { +- compatible = "ns8250"; ++ compatible = "snps,dw-apb-uart"; + reg = <0xc0000000 0x2000>; + interrupts = <11>; ++ #clock-frequency = <80000000>; + clock-frequency = <3686400>; + baud = <115200>; + reg-shift = <2>; + reg-io-width = <4>; +- no-loopback-test = <1>; ++ status = "okay"; + }; + + pgu0: pgu@c9000000 { +diff -Nur linux-3.12.18/arch/arc/configs/nsimosci_defconfig linux-rpi/arch/arc/configs/nsimosci_defconfig +--- linux-3.12.18/arch/arc/configs/nsimosci_defconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/arc/configs/nsimosci_defconfig 2014-04-24 16:04:29.363023127 +0200 +@@ -54,7 +54,6 @@ + CONFIG_SERIAL_8250=y + CONFIG_SERIAL_8250_CONSOLE=y + CONFIG_SERIAL_8250_DW=y +-CONFIG_SERIAL_OF_PLATFORM=y + CONFIG_SERIAL_ARC=y + CONFIG_SERIAL_ARC_CONSOLE=y + # CONFIG_HW_RANDOM is not set +diff -Nur linux-3.12.18/arch/arm/configs/bcmrpi_cutdown_defconfig linux-rpi/arch/arm/configs/bcmrpi_cutdown_defconfig +--- linux-3.12.18/arch/arm/configs/bcmrpi_cutdown_defconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/configs/bcmrpi_cutdown_defconfig 2014-04-24 16:04:30.011029397 +0200 @@ -0,0 +1,503 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set @@ -505,10 +556,10 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_cutdown_defconfig linux-raspberr +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_BCM2708=m -diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arch/arm/configs/bcmrpi_defconfig ---- linux-3.12.13/arch/arm/configs/bcmrpi_defconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/configs/bcmrpi_defconfig 2014-03-11 17:51:00.000000000 +0100 -@@ -0,0 +1,1094 @@ +diff -Nur linux-3.12.18/arch/arm/configs/bcmrpi_defconfig linux-rpi/arch/arm/configs/bcmrpi_defconfig +--- linux-3.12.18/arch/arm/configs/bcmrpi_defconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/configs/bcmrpi_defconfig 2014-04-24 16:04:30.011029397 +0200 +@@ -0,0 +1,1097 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y @@ -529,6 +580,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y ++CONFIG_MEMCG=y +CONFIG_BLK_CGROUP=y +CONFIG_NAMESPACES=y +CONFIG_SCHED_AUTOGROUP=y @@ -553,6 +605,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_AEABI=y +CONFIG_CLEANCACHE=y +CONFIG_FRONTSWAP=y ++CONFIG_CMA=y +CONFIG_UACCESS_WITH_MEMCPY=y +CONFIG_SECCOMP=y +CONFIG_CC_STACKPROTECTOR=y @@ -601,10 +654,10 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_LRO=m +CONFIG_INET_DIAG=m -+CONFIG_IPV6_PRIVACY=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y @@ -627,7 +680,6 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m -+CONFIG_NETFILTER_TPROXY=m +CONFIG_NETFILTER_XT_SET=m +CONFIG_NETFILTER_XT_TARGET_AUDIT=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m @@ -778,6 +830,9 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_SCTP_COOKIE_HMAC_SHA1=y +CONFIG_L2TP=m ++CONFIG_L2TP_V3=y ++CONFIG_L2TP_IP=m ++CONFIG_L2TP_ETH=m +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y @@ -888,7 +943,6 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_NFC_PN533=m +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y -+CONFIG_CMA=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_DRBD=m @@ -901,6 +955,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m ++CONFIG_CHR_DEV_SG=m +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_ISCSI_ATTRS=y +CONFIG_ISCSI_TCP=m @@ -912,8 +967,8 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m -+CONFIG_DM_RAID=m +CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_RAID=m +CONFIG_DM_ZERO=m +CONFIG_DM_DELAY=m +CONFIG_NETDEVICES=y @@ -923,6 +978,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_MACVLAN=m +CONFIG_NETCONSOLE=m +CONFIG_TUN=m ++CONFIG_VETH=m +CONFIG_MDIO_BITBANG=m +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m @@ -944,6 +1000,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_USB_RTL8152=m +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_AX88179_178A=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_CDC_NCM=m @@ -985,6 +1042,9 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_B43=m +# CONFIG_B43_PHY_N is not set +CONFIG_B43LEGACY=m ++CONFIG_BRCMFMAC=m ++# CONFIG_BRCMFMAC_SDIO is not set ++CONFIG_BRCMFMAC_USB=y +CONFIG_HOSTAP=m +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m @@ -995,7 +1055,9 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m ++CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y ++CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RTL8192CU=m +CONFIG_ZD1211RW=m @@ -1011,7 +1073,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y -+CONFIG_JOYSTICK_XPAD=y ++CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AD714X=m @@ -1029,7 +1091,6 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m -+CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_AMBA_PL011=y @@ -1146,8 +1207,6 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_TLG2300=m +CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160=m -+CONFIG_VIDEO_STK1160_AC97=y +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_ALSA=m @@ -1255,6 +1314,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_SND_SOC_I2C_AND_SPI=m +CONFIG_SND_SOC_PCM5102A=m +CONFIG_SND_SOC_PCM1794A=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m +CONFIG_SOUND_PRIME=m +CONFIG_HIDRAW=y +CONFIG_HID_A4TECH=m @@ -1303,6 +1363,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_HID_ZYDACRON=m +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y ++CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_MON=m +CONFIG_USB_DWCOTG=y @@ -1335,7 +1396,6 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m -+CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m @@ -1353,16 +1413,13 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m -+CONFIG_USB_SERIAL_MOTOROLA=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m -+CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m -+CONFIG_USB_SERIAL_SIEMENS_MPI=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m @@ -1371,9 +1428,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m -+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m +CONFIG_USB_SERIAL_XSENS_MT=m -+CONFIG_USB_SERIAL_ZIO=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_ZTE=m +CONFIG_USB_SERIAL_SSU100=m @@ -1416,6 +1471,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_CAMERA=m +CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1374=m +CONFIG_RTC_DRV_DS1672=m @@ -1451,7 +1507,6 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_DMA_ENGINE=y +CONFIG_DMA_VIRTUAL_CHANNELS=m +CONFIG_UIO=m -+CONFIG_UIO_PDRV=m +CONFIG_UIO_PDRV_GENIRQ=m +CONFIG_STAGING=y +CONFIG_W35UND=m @@ -1588,7 +1643,6 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +CONFIG_CRYPTO_USER=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_CRYPTD=m -+CONFIG_CRYPTO_SEQIV=m +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_XTS=m +CONFIG_CRYPTO_XCBC=m @@ -1603,9 +1657,9 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc +# CONFIG_CRYPTO_HW is not set +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y -diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_emergency_defconfig linux-raspberry-pi/arch/arm/configs/bcmrpi_emergency_defconfig ---- linux-3.12.13/arch/arm/configs/bcmrpi_emergency_defconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/configs/bcmrpi_emergency_defconfig 2014-03-11 17:31:42.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/configs/bcmrpi_emergency_defconfig linux-rpi/arch/arm/configs/bcmrpi_emergency_defconfig +--- linux-3.12.18/arch/arm/configs/bcmrpi_emergency_defconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/configs/bcmrpi_emergency_defconfig 2014-04-24 16:04:30.011029397 +0200 @@ -0,0 +1,532 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set @@ -2139,9 +2193,9 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_emergency_defconfig linux-raspbe +# CONFIG_CRYPTO_HW is not set +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y -diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_quick_defconfig linux-raspberry-pi/arch/arm/configs/bcmrpi_quick_defconfig ---- linux-3.12.13/arch/arm/configs/bcmrpi_quick_defconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/configs/bcmrpi_quick_defconfig 2014-03-11 17:31:42.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/configs/bcmrpi_quick_defconfig linux-rpi/arch/arm/configs/bcmrpi_quick_defconfig +--- linux-3.12.18/arch/arm/configs/bcmrpi_quick_defconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/configs/bcmrpi_quick_defconfig 2014-04-24 15:35:00.717527267 +0200 @@ -0,0 +1,197 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_LOCALVERSION="-quick" @@ -2340,20 +2394,38 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_quick_defconfig linux-raspberry- +# CONFIG_CRYPTO_HW is not set +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y -diff -Nur linux-3.12.13/arch/arm/include/asm/fiq.h linux-raspberry-pi/arch/arm/include/asm/fiq.h ---- linux-3.12.13/arch/arm/include/asm/fiq.h 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/include/asm/fiq.h 2014-03-11 17:31:42.000000000 +0100 -@@ -42,6 +42,7 @@ - /* helpers defined in fiqasm.S: */ - extern void __set_fiq_regs(unsigned long const *regs); - extern void __get_fiq_regs(unsigned long *regs); -+extern void __FIQ_Branch(unsigned long *regs); +diff -Nur linux-3.12.18/arch/arm/include/asm/irqflags.h linux-rpi/arch/arm/include/asm/irqflags.h +--- linux-3.12.18/arch/arm/include/asm/irqflags.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/arm/include/asm/irqflags.h 2014-04-24 16:04:30.027029552 +0200 +@@ -145,12 +145,22 @@ + } - static inline void set_fiq_regs(struct pt_regs const *regs) + /* +- * restore saved IRQ & FIQ state ++ * restore saved IRQ state + */ + static inline void arch_local_irq_restore(unsigned long flags) { -diff -Nur linux-3.12.13/arch/arm/Kconfig linux-raspberry-pi/arch/arm/Kconfig ---- linux-3.12.13/arch/arm/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/Kconfig 2014-03-11 17:51:00.000000000 +0100 +- asm volatile( +- " msr " IRQMASK_REG_NAME_W ", %0 @ local_irq_restore" ++ unsigned long temp = 0; ++ flags &= ~(1 << 6); ++ asm volatile ( ++ " mrs %0, cpsr" ++ : "=r" (temp) ++ : ++ : "memory", "cc"); ++ /* Preserve FIQ bit */ ++ temp &= (1 << 6); ++ flags = flags | temp; ++ asm volatile ( ++ " msr cpsr_c, %0 @ local_irq_restore" + : + : "r" (flags) + : "memory", "cc"); +diff -Nur linux-3.12.18/arch/arm/Kconfig linux-rpi/arch/arm/Kconfig +--- linux-3.12.18/arch/arm/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/arm/Kconfig 2014-04-24 16:04:29.515024597 +0200 @@ -368,6 +368,24 @@ This enables support for systems based on Atmel AT91RM9200 and AT91SAM9* processors. @@ -2387,9 +2459,9 @@ diff -Nur linux-3.12.13/arch/arm/Kconfig linux-raspberry-pi/arch/arm/Kconfig source "arch/arm/mach-zynq/Kconfig" -diff -Nur linux-3.12.13/arch/arm/Kconfig.debug linux-raspberry-pi/arch/arm/Kconfig.debug ---- linux-3.12.13/arch/arm/Kconfig.debug 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/Kconfig.debug 2014-03-11 17:51:00.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/Kconfig.debug linux-rpi/arch/arm/Kconfig.debug +--- linux-3.12.18/arch/arm/Kconfig.debug 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/arm/Kconfig.debug 2014-04-24 16:04:29.515024597 +0200 @@ -847,6 +847,14 @@ options; the platform specific options are deprecated and will be soon removed. @@ -2405,20 +2477,10 @@ diff -Nur linux-3.12.13/arch/arm/Kconfig.debug linux-raspberry-pi/arch/arm/Kconf endchoice config DEBUG_EXYNOS_UART -diff -Nur linux-3.12.13/arch/arm/kernel/fiqasm.S linux-raspberry-pi/arch/arm/kernel/fiqasm.S ---- linux-3.12.13/arch/arm/kernel/fiqasm.S 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/kernel/fiqasm.S 2014-03-11 17:31:43.000000000 +0100 -@@ -25,6 +25,9 @@ - ENTRY(__set_fiq_regs) - mov r2, #PSR_I_BIT | PSR_F_BIT | FIQ_MODE - mrs r1, cpsr -+@@@@@@@@@@@@@@@ hack: enable the fiq here to keep usb driver happy -+ and r1, #~PSR_F_BIT -+@@@@@@@@@@@@@@@ endhack: (need to find better place for this to happen) - msr cpsr_c, r2 @ select FIQ mode - mov r0, r0 @ avoid hazard prior to ARMv4 - ldmia r0!, {r8 - r12} -@@ -47,3 +50,7 @@ +diff -Nur linux-3.12.18/arch/arm/kernel/fiqasm.S linux-rpi/arch/arm/kernel/fiqasm.S +--- linux-3.12.18/arch/arm/kernel/fiqasm.S 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/arm/kernel/fiqasm.S 2014-04-24 16:04:30.039029668 +0200 +@@ -47,3 +47,7 @@ mov r0, r0 @ avoid hazard prior to ARMv4 mov pc, lr ENDPROC(__get_fiq_regs) @@ -2426,20 +2488,9 @@ diff -Nur linux-3.12.13/arch/arm/kernel/fiqasm.S linux-raspberry-pi/arch/arm/ker +ENTRY(__FIQ_Branch) + mov pc, r8 +ENDPROC(__FIQ_Branch) -diff -Nur linux-3.12.13/arch/arm/kernel/fiq.c linux-raspberry-pi/arch/arm/kernel/fiq.c ---- linux-3.12.13/arch/arm/kernel/fiq.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/kernel/fiq.c 2014-03-11 17:31:43.000000000 +0100 -@@ -142,6 +142,7 @@ - EXPORT_SYMBOL(set_fiq_handler); - EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */ - EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */ -+EXPORT_SYMBOL(__FIQ_Branch); /* defined in fiqasm.S */ - EXPORT_SYMBOL(claim_fiq); - EXPORT_SYMBOL(release_fiq); - EXPORT_SYMBOL(enable_fiq); -diff -Nur linux-3.12.13/arch/arm/kernel/process.c linux-raspberry-pi/arch/arm/kernel/process.c ---- linux-3.12.13/arch/arm/kernel/process.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/kernel/process.c 2014-03-11 17:51:02.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/kernel/process.c linux-rpi/arch/arm/kernel/process.c +--- linux-3.12.18/arch/arm/kernel/process.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/arm/kernel/process.c 2014-04-24 16:04:30.039029668 +0200 @@ -176,6 +176,16 @@ default_idle(); } @@ -2457,9 +2508,9 @@ diff -Nur linux-3.12.13/arch/arm/kernel/process.c linux-raspberry-pi/arch/arm/ke /* * Called by kexec, immediately prior to machine_kexec(). * -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/armctrl.c linux-raspberry-pi/arch/arm/mach-bcm2708/armctrl.c ---- linux-3.12.13/arch/arm/mach-bcm2708/armctrl.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/armctrl.c 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/armctrl.c linux-rpi/arch/arm/mach-bcm2708/armctrl.c +--- linux-3.12.18/arch/arm/mach-bcm2708/armctrl.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/armctrl.c 2014-04-24 15:35:00.773527891 +0200 @@ -0,0 +1,219 @@ +/* + * linux/arch/arm/mach-bcm2708/armctrl.c @@ -2680,9 +2731,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/armctrl.c linux-raspberry-pi/arch/ + init_FIQ(FIQ_START); + return 0; +} -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/armctrl.h linux-raspberry-pi/arch/arm/mach-bcm2708/armctrl.h ---- linux-3.12.13/arch/arm/mach-bcm2708/armctrl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/armctrl.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/armctrl.h linux-rpi/arch/arm/mach-bcm2708/armctrl.h +--- linux-3.12.18/arch/arm/mach-bcm2708/armctrl.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/armctrl.h 2014-04-24 15:35:00.773527891 +0200 @@ -0,0 +1,27 @@ +/* + * linux/arch/arm/mach-bcm2708/armctrl.h @@ -2711,10 +2762,10 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/armctrl.h linux-raspberry-pi/arch/ + u32 armctrl_sources, u32 resume_sources); + +#endif -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/arm/mach-bcm2708/bcm2708.c ---- linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/bcm2708.c 2014-03-11 17:51:02.000000000 +0100 -@@ -0,0 +1,1011 @@ +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/bcm2708.c linux-rpi/arch/arm/mach-bcm2708/bcm2708.c +--- linux-3.12.18/arch/arm/mach-bcm2708/bcm2708.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/bcm2708.c 2014-04-24 16:04:30.051029784 +0200 +@@ -0,0 +1,1017 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708.c + * @@ -2758,7 +2809,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/ +#include <asm/irq.h> +#include <linux/leds.h> +#include <asm/mach-types.h> -+#include <asm/sched_clock.h> ++#include <linux/sched_clock.h> + +#include <asm/mach/arch.h> +#include <asm/mach/flash.h> @@ -2803,6 +2854,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/ +static unsigned disk_led_gpio = 16; +static unsigned disk_led_active_low = 1; +static unsigned reboot_part = 0; ++static unsigned w1_gpio_pin = W1_GPIO; + +static void __init bcm2708_init_led(void); + @@ -3044,20 +3096,6 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/ + }, +}; + -+bool fiq_fix_enable = true; -+ -+static struct resource bcm2708_usb_resources_no_fiq_fix[] = { -+ [0] = { -+ .start = USB_BASE, -+ .end = USB_BASE + SZ_128K - 1, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_USB, -+ .end = IRQ_USB, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; + +static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + @@ -3401,6 +3439,22 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/ +}; +#endif + ++ ++#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) ++static struct platform_device snd_rpi_iqaudio_dac_device = { ++ .name = "snd-rpi-iqaudio-dac", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++// Use the actual device name rather than generic driver name ++static struct i2c_board_info __initdata snd_pcm512x_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("pcm5122", 0x4c) ++ }, ++}; ++#endif ++ +int __init bcm_register_device(struct platform_device *pdev) +{ + int ret; @@ -3500,15 +3554,11 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/ + bcm_register_device(&bcm2708_gpio_device); +#endif +#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) ++ w1_gpio_pdata.pin = w1_gpio_pin; + platform_device_register(&w1_device); +#endif + bcm_register_device(&bcm2708_systemtimer_device); + bcm_register_device(&bcm2708_fb_device); -+ if (!fiq_fix_enable) -+ { -+ bcm2708_usb_device.resource = bcm2708_usb_resources_no_fiq_fix; -+ bcm2708_usb_device.num_resources = ARRAY_SIZE(bcm2708_usb_resources_no_fiq_fix); -+ } + bcm_register_device(&bcm2708_usb_device); + bcm_register_device(&bcm2708_uart1_device); + bcm_register_device(&bcm2708_powerman_device); @@ -3546,6 +3596,12 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/ + bcm_register_device(&snd_pcm1794a_codec_device); +#endif + ++#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) ++ bcm_register_device(&snd_rpi_iqaudio_dac_device); ++ i2c_register_board_info(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); ++#endif ++ ++ + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; + amba_device_register(d, &iomem_resource); @@ -3726,10 +3782,11 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/ +module_param(disk_led_gpio, uint, 0644); +module_param(disk_led_active_low, uint, 0644); +module_param(reboot_part, uint, 0644); -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/arch/arm/mach-bcm2708/bcm2708_gpio.c ---- linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/bcm2708_gpio.c 2014-03-11 17:51:02.000000000 +0100 -@@ -0,0 +1,339 @@ ++module_param(w1_gpio_pin, uint, 0644); +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-rpi/arch/arm/mach-bcm2708/bcm2708_gpio.c +--- linux-3.12.18/arch/arm/mach-bcm2708/bcm2708_gpio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/bcm2708_gpio.c 2014-04-24 16:04:30.051029784 +0200 +@@ -0,0 +1,361 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708_gpio.c + * @@ -3790,6 +3847,8 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/ + struct gpio_chip gc; + unsigned long rising; + unsigned long falling; ++ unsigned long high; ++ unsigned long low; +}; + +static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset, @@ -3802,7 +3861,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/ + unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3; + +//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set_function %p (%d,%d)\n", gc, offset, function); -+ if (offset >= ARCH_NR_GPIOS) ++ if (offset >= BCM2708_NR_GPIOS) + return -EINVAL; + + spin_lock_irqsave(&lock, flags); @@ -3840,7 +3899,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/ + unsigned gpio_field_offset = (offset - 32 * gpio_bank); + unsigned lev; + -+ if (offset >= ARCH_NR_GPIOS) ++ if (offset >= BCM2708_NR_GPIOS) + return 0; + lev = readl(gpio->base + GPIOLEV(gpio_bank)); +//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_get %p (%d)=%d\n", gc, offset, 0x1 & (lev>>gpio_field_offset)); @@ -3853,7 +3912,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/ + unsigned gpio_bank = offset / 32; + unsigned gpio_field_offset = (offset - 32 * gpio_bank); +//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set %p (%d=%d)\n", gc, offset, value); -+ if (offset >= ARCH_NR_GPIOS) ++ if (offset >= BCM2708_NR_GPIOS) + return; + if (value) + writel(1 << gpio_field_offset, gpio->base + GPIOSET(gpio_bank)); @@ -3877,20 +3936,22 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/ + unsigned irq = d->irq; + struct bcm2708_gpio *gpio = irq_get_chip_data(irq); + -+ if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) ++ gpio->rising &= ~(1 << irq_to_gpio(irq)); ++ gpio->falling &= ~(1 << irq_to_gpio(irq)); ++ gpio->high &= ~(1 << irq_to_gpio(irq)); ++ gpio->low &= ~(1 << irq_to_gpio(irq)); ++ ++ if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) + return -EINVAL; + -+ if (type & IRQ_TYPE_EDGE_RISING) { ++ if (type & IRQ_TYPE_EDGE_RISING) + gpio->rising |= (1 << irq_to_gpio(irq)); -+ } else { -+ gpio->rising &= ~(1 << irq_to_gpio(irq)); -+ } -+ -+ if (type & IRQ_TYPE_EDGE_FALLING) { ++ if (type & IRQ_TYPE_EDGE_FALLING) + gpio->falling |= (1 << irq_to_gpio(irq)); -+ } else { -+ gpio->falling &= ~(1 << irq_to_gpio(irq)); -+ } ++ if (type & IRQ_TYPE_LEVEL_HIGH) ++ gpio->high |= (1 << irq_to_gpio(irq)); ++ if (type & IRQ_TYPE_LEVEL_LOW) ++ gpio->low |= (1 << irq_to_gpio(irq)); + return 0; +} + @@ -3900,13 +3961,17 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/ + struct bcm2708_gpio *gpio = irq_get_chip_data(irq); + unsigned gn = irq_to_gpio(irq); + unsigned gb = gn / 32; -+ unsigned long rising = readl(gpio->base + GPIOREN(gb)); ++ unsigned long rising = readl(gpio->base + GPIOREN(gb)); + unsigned long falling = readl(gpio->base + GPIOFEN(gb)); ++ unsigned long high = readl(gpio->base + GPIOHEN(gb)); ++ unsigned long low = readl(gpio->base + GPIOLEN(gb)); + + gn = gn % 32; + -+ writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb)); ++ writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb)); + writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb)); ++ writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb)); ++ writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb)); +} + +static void bcm2708_gpio_irq_unmask(struct irq_data *d) @@ -3915,24 +3980,38 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/ + struct bcm2708_gpio *gpio = irq_get_chip_data(irq); + unsigned gn = irq_to_gpio(irq); + unsigned gb = gn / 32; -+ unsigned long rising = readl(gpio->base + GPIOREN(gb)); ++ unsigned long rising = readl(gpio->base + GPIOREN(gb)); + unsigned long falling = readl(gpio->base + GPIOFEN(gb)); ++ unsigned long high = readl(gpio->base + GPIOHEN(gb)); ++ unsigned long low = readl(gpio->base + GPIOLEN(gb)); + + gn = gn % 32; + + writel(1 << gn, gpio->base + GPIOEDS(gb)); + + if (gpio->rising & (1 << gn)) { -+ writel(rising | (1 << gn), gpio->base + GPIOREN(gb)); ++ writel(rising | (1 << gn), gpio->base + GPIOREN(gb)); + } else { + writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb)); + } + + if (gpio->falling & (1 << gn)) { -+ writel(falling | (1 << gn), gpio->base + GPIOFEN(gb)); ++ writel(falling | (1 << gn), gpio->base + GPIOFEN(gb)); + } else { + writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb)); + } ++ ++ if (gpio->high & (1 << gn)) { ++ writel(high | (1 << gn), gpio->base + GPIOHEN(gb)); ++ } else { ++ writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb)); ++ } ++ ++ if (gpio->low & (1 << gn)) { ++ writel(low | (1 << gn), gpio->base + GPIOLEN(gb)); ++ } else { ++ writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb)); ++ } +} + +static struct irq_chip bcm2708_irqchip = { @@ -4012,7 +4091,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/ + + ucb->gc.label = "bcm2708_gpio"; + ucb->gc.base = 0; -+ ucb->gc.ngpio = ARCH_NR_GPIOS; ++ ucb->gc.ngpio = BCM2708_NR_GPIOS; + ucb->gc.owner = THIS_MODULE; + + ucb->gc.direction_input = bcm2708_gpio_dir_in; @@ -4069,10 +4148,10 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/ + +MODULE_DESCRIPTION("Broadcom BCM2708 GPIO driver"); +MODULE_LICENSE("GPL"); -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.h linux-raspberry-pi/arch/arm/mach-bcm2708/bcm2708.h ---- linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/bcm2708.h 2014-03-11 17:31:43.000000000 +0100 -@@ -0,0 +1,51 @@ +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/bcm2708.h linux-rpi/arch/arm/mach-bcm2708/bcm2708.h +--- linux-3.12.18/arch/arm/mach-bcm2708/bcm2708.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/bcm2708.h 2014-04-24 16:04:30.051029784 +0200 +@@ -0,0 +1,49 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708.h + * @@ -4118,15 +4197,13 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.h linux-raspberry-pi/arch/ + .end = (base##_BASE) + SZ_4K - 1,\ + .flags = IORESOURCE_MEM, \ + }, \ -+ .dma_mask = ~0, \ + .irq = base##_IRQ, \ -+ /* .dma = base##_DMA,*/ \ +} + +#endif -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/clock.c linux-raspberry-pi/arch/arm/mach-bcm2708/clock.c ---- linux-3.12.13/arch/arm/mach-bcm2708/clock.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/clock.c 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/clock.c linux-rpi/arch/arm/mach-bcm2708/clock.c +--- linux-3.12.18/arch/arm/mach-bcm2708/clock.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/clock.c 2014-04-24 15:35:00.773527891 +0200 @@ -0,0 +1,61 @@ +/* + * linux/arch/arm/mach-bcm2708/clock.c @@ -4189,9 +4266,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/clock.c linux-raspberry-pi/arch/ar + return -EIO; +} +EXPORT_SYMBOL(clk_set_rate); -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/clock.h linux-raspberry-pi/arch/arm/mach-bcm2708/clock.h ---- linux-3.12.13/arch/arm/mach-bcm2708/clock.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/clock.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/clock.h linux-rpi/arch/arm/mach-bcm2708/clock.h +--- linux-3.12.18/arch/arm/mach-bcm2708/clock.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/clock.h 2014-04-24 15:35:00.773527891 +0200 @@ -0,0 +1,24 @@ +/* + * linux/arch/arm/mach-bcm2708/clock.h @@ -4217,9 +4294,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/clock.h linux-raspberry-pi/arch/ar +struct clk { + unsigned long rate; +}; -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/dma.c linux-raspberry-pi/arch/arm/mach-bcm2708/dma.c ---- linux-3.12.13/arch/arm/mach-bcm2708/dma.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/dma.c 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/dma.c linux-rpi/arch/arm/mach-bcm2708/dma.c +--- linux-3.12.18/arch/arm/mach-bcm2708/dma.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/dma.c 2014-04-24 15:35:00.773527891 +0200 @@ -0,0 +1,407 @@ +/* + * linux/arch/arm/mach-bcm2708/dma.c @@ -4628,899 +4705,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/dma.c linux-raspberry-pi/arch/arm/ +MODULE_LICENSE("GPL"); + +MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM"); -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/dmaer.c linux-raspberry-pi/arch/arm/mach-bcm2708/dmaer.c ---- linux-3.12.13/arch/arm/mach-bcm2708/dmaer.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/dmaer.c 2014-03-11 17:51:02.000000000 +0100 -@@ -0,0 +1,886 @@ -+#include <linux/init.h> -+#include <linux/sched.h> -+#include <linux/module.h> -+#include <linux/types.h> -+#include <linux/kdev_t.h> -+#include <linux/fs.h> -+#include <linux/cdev.h> -+#include <linux/mm.h> -+#include <linux/slab.h> -+#include <linux/pagemap.h> -+#include <linux/device.h> -+#include <linux/jiffies.h> -+#include <linux/timex.h> -+#include <linux/dma-mapping.h> -+ -+#include <asm/uaccess.h> -+#include <asm/atomic.h> -+#include <asm/cacheflush.h> -+#include <asm/io.h> -+ -+#include <mach/dma.h> -+#include <mach/vc_support.h> -+ -+#ifdef ECLIPSE_IGNORE -+ -+#define __user -+#define __init -+#define __exit -+#define __iomem -+#define KERN_DEBUG -+#define KERN_ERR -+#define KERN_WARNING -+#define KERN_INFO -+#define _IOWR(a, b, c) b -+#define _IOW(a, b, c) b -+#define _IO(a, b) b -+ -+#endif -+ -+//#define inline -+ -+#define PRINTK(args...) printk(args) -+//#define PRINTK_VERBOSE(args...) printk(args) -+//#define PRINTK(args...) -+#define PRINTK_VERBOSE(args...) -+ -+/***** TYPES ****/ -+#define PAGES_PER_LIST 500 -+struct PageList -+{ -+ struct page *m_pPages[PAGES_PER_LIST]; -+ unsigned int m_used; -+ struct PageList *m_pNext; -+}; -+ -+struct VmaPageList -+{ -+ //each vma has a linked list of pages associated with it -+ struct PageList *m_pPageHead; -+ struct PageList *m_pPageTail; -+ unsigned int m_refCount; -+}; -+ -+struct DmaControlBlock -+{ -+ unsigned int m_transferInfo; -+ void __user *m_pSourceAddr; -+ void __user *m_pDestAddr; -+ unsigned int m_xferLen; -+ unsigned int m_tdStride; -+ struct DmaControlBlock *m_pNext; -+ unsigned int m_blank1, m_blank2; -+}; -+ -+/***** DEFINES ******/ -+//magic number defining the module -+#define DMA_MAGIC 0xdd -+ -+//do user virtual to physical translation of the CB chain -+#define DMA_PREPARE _IOWR(DMA_MAGIC, 0, struct DmaControlBlock *) -+ -+//kick the pre-prepared CB chain -+#define DMA_KICK _IOW(DMA_MAGIC, 1, struct DmaControlBlock *) -+ -+//prepare it, kick it, wait for it -+#define DMA_PREPARE_KICK_WAIT _IOWR(DMA_MAGIC, 2, struct DmaControlBlock *) -+ -+//prepare it, kick it, don't wait for it -+#define DMA_PREPARE_KICK _IOWR(DMA_MAGIC, 3, struct DmaControlBlock *) -+ -+//not currently implemented -+#define DMA_WAIT_ONE _IO(DMA_MAGIC, 4, struct DmaControlBlock *) -+ -+//wait on all kicked CB chains -+#define DMA_WAIT_ALL _IO(DMA_MAGIC, 5) -+ -+//in order to discover the largest AXI burst that should be programmed into the transfer params -+#define DMA_MAX_BURST _IO(DMA_MAGIC, 6) -+ -+//set the address range through which the user address is assumed to already by a physical address -+#define DMA_SET_MIN_PHYS _IOW(DMA_MAGIC, 7, unsigned long) -+#define DMA_SET_MAX_PHYS _IOW(DMA_MAGIC, 8, unsigned long) -+#define DMA_SET_PHYS_OFFSET _IOW(DMA_MAGIC, 9, unsigned long) -+ -+//used to define the size for the CMA-based allocation *in pages*, can only be done once once the file is opened -+#define DMA_CMA_SET_SIZE _IOW(DMA_MAGIC, 10, unsigned long) -+ -+//used to get the version of the module, to test for a capability -+#define DMA_GET_VERSION _IO(DMA_MAGIC, 99) -+ -+#define VERSION_NUMBER 1 -+ -+#define VIRT_TO_BUS_CACHE_SIZE 8 -+ -+/***** FILE OPS *****/ -+static int Open(struct inode *pInode, struct file *pFile); -+static int Release(struct inode *pInode, struct file *pFile); -+static long Ioctl(struct file *pFile, unsigned int cmd, unsigned long arg); -+static ssize_t Read(struct file *pFile, char __user *pUser, size_t count, loff_t *offp); -+static int Mmap(struct file *pFile, struct vm_area_struct *pVma); -+ -+/***** VMA OPS ****/ -+static void VmaOpen4k(struct vm_area_struct *pVma); -+static void VmaClose4k(struct vm_area_struct *pVma); -+static int VmaFault4k(struct vm_area_struct *pVma, struct vm_fault *pVmf); -+ -+/**** DMA PROTOTYPES */ -+static struct DmaControlBlock __user *DmaPrepare(struct DmaControlBlock __user *pUserCB, int *pError); -+static int DmaKick(struct DmaControlBlock __user *pUserCB); -+static void DmaWaitAll(void); -+ -+/**** GENERIC ****/ -+static int __init dmaer_init(void); -+static void __exit dmaer_exit(void); -+ -+/*** OPS ***/ -+static struct vm_operations_struct g_vmOps4k = { -+ .open = VmaOpen4k, -+ .close = VmaClose4k, -+ .fault = VmaFault4k, -+}; -+ -+static struct file_operations g_fOps = { -+ .owner = THIS_MODULE, -+ .llseek = 0, -+ .read = Read, -+ .write = 0, -+ .unlocked_ioctl = Ioctl, -+ .open = Open, -+ .release = Release, -+ .mmap = Mmap, -+}; -+ -+/***** GLOBALS ******/ -+static dev_t g_majorMinor; -+ -+//tracking usage of the two files -+static atomic_t g_oneLock4k = ATOMIC_INIT(1); -+ -+//device operations -+static struct cdev g_cDev; -+static int g_trackedPages = 0; -+ -+//dma control -+static unsigned int *g_pDmaChanBase; -+static int g_dmaIrq; -+static int g_dmaChan; -+ -+//cma allocation -+static int g_cmaHandle; -+ -+//user virtual to bus address translation acceleration -+static unsigned long g_virtAddr[VIRT_TO_BUS_CACHE_SIZE]; -+static unsigned long g_busAddr[VIRT_TO_BUS_CACHE_SIZE]; -+static unsigned long g_cbVirtAddr; -+static unsigned long g_cbBusAddr; -+static int g_cacheInsertAt; -+static int g_cacheHit, g_cacheMiss; -+ -+//off by default -+static void __user *g_pMinPhys; -+static void __user *g_pMaxPhys; -+static unsigned long g_physOffset; -+ -+/****** CACHE OPERATIONS ********/ -+static inline void FlushAddrCache(void) -+{ -+ int count = 0; -+ for (count = 0; count < VIRT_TO_BUS_CACHE_SIZE; count++) -+ g_virtAddr[count] = 0xffffffff; //never going to match as we always chop the bottom bits anyway -+ -+ g_cbVirtAddr = 0xffffffff; -+ -+ g_cacheInsertAt = 0; -+} -+ -+//translate from a user virtual address to a bus address by mapping the page -+//NB this won't lock a page in memory, so to avoid potential paging issues using kernel logical addresses -+static inline void __iomem *UserVirtualToBus(void __user *pUser) -+{ -+ int mapped; -+ struct page *pPage; -+ void *phys; -+ -+ //map it (requiring that the pointer points to something that does not hang off the page boundary) -+ mapped = get_user_pages(current, current->mm, -+ (unsigned long)pUser, 1, -+ 1, 0, -+ &pPage, -+ 0); -+ -+ if (mapped <= 0) //error -+ return 0; -+ -+ PRINTK_VERBOSE(KERN_DEBUG "user virtual %p arm phys %p bus %p\n", -+ pUser, page_address(pPage), (void __iomem *)__virt_to_bus(page_address(pPage))); -+ -+ //get the arm physical address -+ phys = page_address(pPage) + offset_in_page(pUser); -+ page_cache_release(pPage); -+ -+ //and now the bus address -+ return (void __iomem *)__virt_to_bus(phys); -+} -+ -+static inline void __iomem *UserVirtualToBusViaCbCache(void __user *pUser) -+{ -+ unsigned long virtual_page = (unsigned long)pUser & ~4095; -+ unsigned long page_offset = (unsigned long)pUser & 4095; -+ unsigned long bus_addr; -+ -+ if (g_cbVirtAddr == virtual_page) -+ { -+ bus_addr = g_cbBusAddr + page_offset; -+ g_cacheHit++; -+ return (void __iomem *)bus_addr; -+ } -+ else -+ { -+ bus_addr = (unsigned long)UserVirtualToBus(pUser); -+ -+ if (!bus_addr) -+ return 0; -+ -+ g_cbVirtAddr = virtual_page; -+ g_cbBusAddr = bus_addr & ~4095; -+ g_cacheMiss++; -+ -+ return (void __iomem *)bus_addr; -+ } -+} -+ -+//do the same as above, by query our virt->bus cache -+static inline void __iomem *UserVirtualToBusViaCache(void __user *pUser) -+{ -+ int count; -+ //get the page and its offset -+ unsigned long virtual_page = (unsigned long)pUser & ~4095; -+ unsigned long page_offset = (unsigned long)pUser & 4095; -+ unsigned long bus_addr; -+ -+ if (pUser >= g_pMinPhys && pUser < g_pMaxPhys) -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "user->phys passthrough on %p\n", pUser); -+ return (void __iomem *)((unsigned long)pUser + g_physOffset); -+ } -+ -+ //check the cache for our entry -+ for (count = 0; count < VIRT_TO_BUS_CACHE_SIZE; count++) -+ if (g_virtAddr[count] == virtual_page) -+ { -+ bus_addr = g_busAddr[count] + page_offset; -+ g_cacheHit++; -+ return (void __iomem *)bus_addr; -+ } -+ -+ //not found, look up manually and then insert its page address -+ bus_addr = (unsigned long)UserVirtualToBus(pUser); -+ -+ if (!bus_addr) -+ return 0; -+ -+ g_virtAddr[g_cacheInsertAt] = virtual_page; -+ g_busAddr[g_cacheInsertAt] = bus_addr & ~4095; -+ -+ //round robin -+ g_cacheInsertAt++; -+ if (g_cacheInsertAt == VIRT_TO_BUS_CACHE_SIZE) -+ g_cacheInsertAt = 0; -+ -+ g_cacheMiss++; -+ -+ return (void __iomem *)bus_addr; -+} -+ -+/***** FILE OPERATIONS ****/ -+static int Open(struct inode *pInode, struct file *pFile) -+{ -+ PRINTK(KERN_DEBUG "file opening: %d/%d\n", imajor(pInode), iminor(pInode)); -+ -+ //check which device we are -+ if (iminor(pInode) == 0) //4k -+ { -+ //only one at a time -+ if (!atomic_dec_and_test(&g_oneLock4k)) -+ { -+ atomic_inc(&g_oneLock4k); -+ return -EBUSY; -+ } -+ } -+ else -+ return -EINVAL; -+ -+ //todo there will be trouble if two different processes open the files -+ -+ //reset after any file is opened -+ g_pMinPhys = (void __user *)-1; -+ g_pMaxPhys = (void __user *)0; -+ g_physOffset = 0; -+ g_cmaHandle = 0; -+ -+ return 0; -+} -+ -+static int Release(struct inode *pInode, struct file *pFile) -+{ -+ PRINTK(KERN_DEBUG "file closing, %d pages tracked\n", g_trackedPages); -+ if (g_trackedPages) -+ PRINTK(KERN_ERR "we\'re leaking memory!\n"); -+ -+ //wait for any dmas to finish -+ DmaWaitAll(); -+ -+ //free this memory on the application closing the file or it crashing (implicitly closing the file) -+ if (g_cmaHandle) -+ { -+ PRINTK(KERN_DEBUG "unlocking vc memory\n"); -+ if (UnlockVcMemory(g_cmaHandle)) -+ PRINTK(KERN_ERR "uh-oh, unable to unlock vc memory!\n"); -+ PRINTK(KERN_DEBUG "releasing vc memory\n"); -+ if (ReleaseVcMemory(g_cmaHandle)) -+ PRINTK(KERN_ERR "uh-oh, unable to release vc memory!\n"); -+ } -+ -+ if (iminor(pInode) == 0) -+ atomic_inc(&g_oneLock4k); -+ else -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static struct DmaControlBlock __user *DmaPrepare(struct DmaControlBlock __user *pUserCB, int *pError) -+{ -+ struct DmaControlBlock kernCB; -+ struct DmaControlBlock __user *pUNext; -+ void __iomem *pSourceBus, __iomem *pDestBus; -+ -+ //get the control block into kernel memory so we can work on it -+ if (copy_from_user(&kernCB, pUserCB, sizeof(struct DmaControlBlock)) != 0) -+ { -+ PRINTK(KERN_ERR "copy_from_user failed for user cb %p\n", pUserCB); -+ *pError = 1; -+ return 0; -+ } -+ -+ if (kernCB.m_pSourceAddr == 0 || kernCB.m_pDestAddr == 0) -+ { -+ PRINTK(KERN_ERR "faulty source (%p) dest (%p) addresses for user cb %p\n", -+ kernCB.m_pSourceAddr, kernCB.m_pDestAddr, pUserCB); -+ *pError = 1; -+ return 0; -+ } -+ -+ pSourceBus = UserVirtualToBusViaCache(kernCB.m_pSourceAddr); -+ pDestBus = UserVirtualToBusViaCache(kernCB.m_pDestAddr); -+ -+ if (!pSourceBus || !pDestBus) -+ { -+ PRINTK(KERN_ERR "virtual to bus translation failure for source/dest %p/%p->%p/%p\n", -+ kernCB.m_pSourceAddr, kernCB.m_pDestAddr, -+ pSourceBus, pDestBus); -+ *pError = 1; -+ return 0; -+ } -+ -+ //update the user structure with the new bus addresses -+ kernCB.m_pSourceAddr = pSourceBus; -+ kernCB.m_pDestAddr = pDestBus; -+ -+ PRINTK_VERBOSE(KERN_DEBUG "final source %p dest %p\n", kernCB.m_pSourceAddr, kernCB.m_pDestAddr); -+ -+ //sort out the bus address for the next block -+ pUNext = kernCB.m_pNext; -+ -+ if (kernCB.m_pNext) -+ { -+ void __iomem *pNextBus; -+ pNextBus = UserVirtualToBusViaCbCache(kernCB.m_pNext); -+ -+ if (!pNextBus) -+ { -+ PRINTK(KERN_ERR "virtual to bus translation failure for m_pNext\n"); -+ *pError = 1; -+ return 0; -+ } -+ -+ //update the pointer with the bus address -+ kernCB.m_pNext = pNextBus; -+ } -+ -+ //write it back to user space -+ if (copy_to_user(pUserCB, &kernCB, sizeof(struct DmaControlBlock)) != 0) -+ { -+ PRINTK(KERN_ERR "copy_to_user failed for cb %p\n", pUserCB); -+ *pError = 1; -+ return 0; -+ } -+ -+ __cpuc_flush_dcache_area(pUserCB, 32); -+ -+ *pError = 0; -+ return pUNext; -+} -+ -+static int DmaKick(struct DmaControlBlock __user *pUserCB) -+{ -+ void __iomem *pBusCB; -+ -+ pBusCB = UserVirtualToBusViaCbCache(pUserCB); -+ if (!pBusCB) -+ { -+ PRINTK(KERN_ERR "virtual to bus translation failure for cb\n"); -+ return 1; -+ } -+ -+ //flush_cache_all(); -+ -+ bcm_dma_start(g_pDmaChanBase, (dma_addr_t)pBusCB); -+ -+ return 0; -+} -+ -+static void DmaWaitAll(void) -+{ -+ int counter = 0; -+ volatile int inner_count; -+ volatile unsigned int cs; -+ unsigned long time_before, time_after; -+ -+ time_before = jiffies; -+ //bcm_dma_wait_idle(g_pDmaChanBase); -+ dsb(); -+ -+ cs = readl(g_pDmaChanBase); -+ -+ while ((cs & 1) == 1) -+ { -+ cs = readl(g_pDmaChanBase); -+ counter++; -+ -+ for (inner_count = 0; inner_count < 32; inner_count++); -+ -+ asm volatile ("MCR p15,0,r0,c7,c0,4 \n"); -+ //cpu_do_idle(); -+ if (counter >= 1000000) -+ { -+ PRINTK(KERN_WARNING "DMA failed to finish in a timely fashion\n"); -+ break; -+ } -+ } -+ time_after = jiffies; -+ PRINTK_VERBOSE(KERN_DEBUG "done, counter %d, cs %08x", counter, cs); -+ PRINTK_VERBOSE(KERN_DEBUG "took %ld jiffies, %d HZ\n", time_after - time_before, HZ); -+} -+ -+static long Ioctl(struct file *pFile, unsigned int cmd, unsigned long arg) -+{ -+ int error = 0; -+ PRINTK_VERBOSE(KERN_DEBUG "ioctl cmd %x arg %lx\n", cmd, arg); -+ -+ switch (cmd) -+ { -+ case DMA_PREPARE: -+ case DMA_PREPARE_KICK: -+ case DMA_PREPARE_KICK_WAIT: -+ { -+ struct DmaControlBlock __user *pUCB = (struct DmaControlBlock *)arg; -+ int steps = 0; -+ unsigned long start_time = jiffies; -+ (void)start_time; -+ -+ //flush our address cache -+ FlushAddrCache(); -+ -+ PRINTK_VERBOSE(KERN_DEBUG "dma prepare\n"); -+ -+ //do virtual to bus translation for each entry -+ do -+ { -+ pUCB = DmaPrepare(pUCB, &error); -+ } while (error == 0 && ++steps && pUCB); -+ PRINTK_VERBOSE(KERN_DEBUG "prepare done in %d steps, %ld\n", steps, jiffies - start_time); -+ -+ //carry straight on if we want to kick too -+ if (cmd == DMA_PREPARE || error) -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "falling out\n"); -+ return error ? -EINVAL : 0; -+ } -+ } -+ case DMA_KICK: -+ PRINTK_VERBOSE(KERN_DEBUG "dma begin\n"); -+ -+ if (cmd == DMA_KICK) -+ FlushAddrCache(); -+ -+ DmaKick((struct DmaControlBlock __user *)arg); -+ -+ if (cmd != DMA_PREPARE_KICK_WAIT) -+ break; -+/* case DMA_WAIT_ONE: -+ //PRINTK(KERN_DEBUG "dma wait one\n"); -+ break;*/ -+ case DMA_WAIT_ALL: -+ //PRINTK(KERN_DEBUG "dma wait all\n"); -+ DmaWaitAll(); -+ break; -+ case DMA_MAX_BURST: -+ if (g_dmaChan == 0) -+ return 10; -+ else -+ return 5; -+ case DMA_SET_MIN_PHYS: -+ g_pMinPhys = (void __user *)arg; -+ PRINTK(KERN_DEBUG "min/max user/phys bypass set to %p %p\n", g_pMinPhys, g_pMaxPhys); -+ break; -+ case DMA_SET_MAX_PHYS: -+ g_pMaxPhys = (void __user *)arg; -+ PRINTK(KERN_DEBUG "min/max user/phys bypass set to %p %p\n", g_pMinPhys, g_pMaxPhys); -+ break; -+ case DMA_SET_PHYS_OFFSET: -+ g_physOffset = arg; -+ PRINTK(KERN_DEBUG "user/phys bypass offset set to %ld\n", g_physOffset); -+ break; -+ case DMA_CMA_SET_SIZE: -+ { -+ unsigned int pBusAddr; -+ -+ if (g_cmaHandle) -+ { -+ PRINTK(KERN_ERR "memory has already been allocated (handle %d)\n", g_cmaHandle); -+ return -EINVAL; -+ } -+ -+ PRINTK(KERN_INFO "allocating %ld bytes of VC memory\n", arg * 4096); -+ -+ //get the memory -+ if (AllocateVcMemory(&g_cmaHandle, arg * 4096, 4096, MEM_FLAG_L1_NONALLOCATING | MEM_FLAG_NO_INIT | MEM_FLAG_HINT_PERMALOCK)) -+ { -+ PRINTK(KERN_ERR "failed to allocate %ld bytes of VC memory\n", arg * 4096); -+ g_cmaHandle = 0; -+ return -EINVAL; -+ } -+ -+ //get an address for it -+ PRINTK(KERN_INFO "trying to map VC memory\n"); -+ -+ if (LockVcMemory(&pBusAddr, g_cmaHandle)) -+ { -+ PRINTK(KERN_ERR "failed to map CMA handle %d, releasing memory\n", g_cmaHandle); -+ ReleaseVcMemory(g_cmaHandle); -+ g_cmaHandle = 0; -+ } -+ -+ PRINTK(KERN_INFO "bus address for CMA memory is %x\n", pBusAddr); -+ return pBusAddr; -+ } -+ case DMA_GET_VERSION: -+ PRINTK(KERN_DEBUG "returning version number, %d\n", VERSION_NUMBER); -+ return VERSION_NUMBER; -+ default: -+ PRINTK(KERN_DEBUG "unknown ioctl: %d\n", cmd); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static ssize_t Read(struct file *pFile, char __user *pUser, size_t count, loff_t *offp) -+{ -+ return -EIO; -+} -+ -+static int Mmap(struct file *pFile, struct vm_area_struct *pVma) -+{ -+ struct PageList *pPages; -+ struct VmaPageList *pVmaList; -+ -+ PRINTK_VERBOSE(KERN_DEBUG "MMAP vma %p, length %ld (%s %d)\n", -+ pVma, pVma->vm_end - pVma->vm_start, -+ current->comm, current->pid); -+ PRINTK_VERBOSE(KERN_DEBUG "MMAP %p %d (tracked %d)\n", pVma, current->pid, g_trackedPages); -+ -+ //make a new page list -+ pPages = (struct PageList *)kmalloc(sizeof(struct PageList), GFP_KERNEL); -+ if (!pPages) -+ { -+ PRINTK(KERN_ERR "couldn\'t allocate a new page list (%s %d)\n", -+ current->comm, current->pid); -+ return -ENOMEM; -+ } -+ -+ //clear the page list -+ pPages->m_used = 0; -+ pPages->m_pNext = 0; -+ -+ //insert our vma and new page list somewhere -+ if (!pVma->vm_private_data) -+ { -+ struct VmaPageList *pList; -+ -+ PRINTK_VERBOSE(KERN_DEBUG "new vma list, making new one (%s %d)\n", -+ current->comm, current->pid); -+ -+ //make a new vma list -+ pList = (struct VmaPageList *)kmalloc(sizeof(struct VmaPageList), GFP_KERNEL); -+ if (!pList) -+ { -+ PRINTK(KERN_ERR "couldn\'t allocate vma page list (%s %d)\n", -+ current->comm, current->pid); -+ kfree(pPages); -+ return -ENOMEM; -+ } -+ -+ //clear this list -+ pVma->vm_private_data = (void *)pList; -+ pList->m_refCount = 0; -+ } -+ -+ pVmaList = (struct VmaPageList *)pVma->vm_private_data; -+ -+ //add it to the vma list -+ pVmaList->m_pPageHead = pPages; -+ pVmaList->m_pPageTail = pPages; -+ -+ pVma->vm_ops = &g_vmOps4k; -+ pVma->vm_flags |= VM_IO; -+ -+ VmaOpen4k(pVma); -+ -+ return 0; -+} -+ -+/****** VMA OPERATIONS ******/ -+ -+static void VmaOpen4k(struct vm_area_struct *pVma) -+{ -+ struct VmaPageList *pVmaList; -+ -+ PRINTK_VERBOSE(KERN_DEBUG "vma open %p private %p (%s %d), %d live pages\n", pVma, pVma->vm_private_data, current->comm, current->pid, g_trackedPages); -+ PRINTK_VERBOSE(KERN_DEBUG "OPEN %p %d %ld pages (tracked pages %d)\n", -+ pVma, current->pid, (pVma->vm_end - pVma->vm_start) >> 12, -+ g_trackedPages); -+ -+ pVmaList = (struct VmaPageList *)pVma->vm_private_data; -+ -+ if (pVmaList) -+ { -+ pVmaList->m_refCount++; -+ PRINTK_VERBOSE(KERN_DEBUG "ref count is now %d\n", pVmaList->m_refCount); -+ } -+ else -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "err, open but no vma page list\n"); -+ } -+} -+ -+static void VmaClose4k(struct vm_area_struct *pVma) -+{ -+ struct VmaPageList *pVmaList; -+ int freed = 0; -+ -+ PRINTK_VERBOSE(KERN_DEBUG "vma close %p private %p (%s %d)\n", pVma, pVma->vm_private_data, current->comm, current->pid); -+ -+ //wait for any dmas to finish -+ DmaWaitAll(); -+ -+ //find our vma in the list -+ pVmaList = (struct VmaPageList *)pVma->vm_private_data; -+ -+ //may be a fork -+ if (pVmaList) -+ { -+ struct PageList *pPages; -+ -+ pVmaList->m_refCount--; -+ -+ if (pVmaList->m_refCount == 0) -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "found vma, freeing pages (%s %d)\n", -+ current->comm, current->pid); -+ -+ pPages = pVmaList->m_pPageHead; -+ -+ if (!pPages) -+ { -+ PRINTK(KERN_ERR "no page list (%s %d)!\n", -+ current->comm, current->pid); -+ return; -+ } -+ -+ while (pPages) -+ { -+ struct PageList *next; -+ int count; -+ -+ PRINTK_VERBOSE(KERN_DEBUG "page list (%s %d)\n", -+ current->comm, current->pid); -+ -+ next = pPages->m_pNext; -+ for (count = 0; count < pPages->m_used; count++) -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "freeing page %p (%s %d)\n", -+ pPages->m_pPages[count], -+ current->comm, current->pid); -+ __free_pages(pPages->m_pPages[count], 0); -+ g_trackedPages--; -+ freed++; -+ } -+ -+ PRINTK_VERBOSE(KERN_DEBUG "freeing page list (%s %d)\n", -+ current->comm, current->pid); -+ kfree(pPages); -+ pPages = next; -+ } -+ -+ //remove our vma from the list -+ kfree(pVmaList); -+ pVma->vm_private_data = 0; -+ } -+ else -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "ref count is %d, not closing\n", pVmaList->m_refCount); -+ } -+ } -+ else -+ { -+ PRINTK_VERBOSE(KERN_ERR "uh-oh, vma %p not found (%s %d)!\n", pVma, current->comm, current->pid); -+ PRINTK_VERBOSE(KERN_ERR "CLOSE ERR\n"); -+ } -+ -+ PRINTK_VERBOSE(KERN_DEBUG "CLOSE %p %d %d pages (tracked pages %d)", -+ pVma, current->pid, freed, g_trackedPages); -+ -+ PRINTK_VERBOSE(KERN_DEBUG "%d pages open\n", g_trackedPages); -+} -+ -+static int VmaFault4k(struct vm_area_struct *pVma, struct vm_fault *pVmf) -+{ -+ PRINTK_VERBOSE(KERN_DEBUG "vma fault for vma %p private %p at offset %ld (%s %d)\n", pVma, pVma->vm_private_data, pVmf->pgoff, -+ current->comm, current->pid); -+ PRINTK_VERBOSE(KERN_DEBUG "FAULT\n"); -+ pVmf->page = alloc_page(GFP_KERNEL); -+ -+ if (pVmf->page) -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "alloc page virtual %p\n", page_address(pVmf->page)); -+ } -+ -+ if (!pVmf->page) -+ { -+ PRINTK(KERN_ERR "vma fault oom (%s %d)\n", current->comm, current->pid); -+ return VM_FAULT_OOM; -+ } -+ else -+ { -+ struct VmaPageList *pVmaList; -+ -+ get_page(pVmf->page); -+ g_trackedPages++; -+ -+ //find our vma in the list -+ pVmaList = (struct VmaPageList *)pVma->vm_private_data; -+ -+ if (pVmaList) -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "vma found (%s %d)\n", current->comm, current->pid); -+ -+ if (pVmaList->m_pPageTail->m_used == PAGES_PER_LIST) -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "making new page list (%s %d)\n", current->comm, current->pid); -+ //making a new page list -+ pVmaList->m_pPageTail->m_pNext = (struct PageList *)kmalloc(sizeof(struct PageList), GFP_KERNEL); -+ if (!pVmaList->m_pPageTail->m_pNext) -+ return -ENOMEM; -+ -+ //update the tail pointer -+ pVmaList->m_pPageTail = pVmaList->m_pPageTail->m_pNext; -+ pVmaList->m_pPageTail->m_used = 0; -+ pVmaList->m_pPageTail->m_pNext = 0; -+ } -+ -+ PRINTK_VERBOSE(KERN_DEBUG "adding page to list (%s %d)\n", current->comm, current->pid); -+ -+ pVmaList->m_pPageTail->m_pPages[pVmaList->m_pPageTail->m_used] = pVmf->page; -+ pVmaList->m_pPageTail->m_used++; -+ } -+ else -+ PRINTK(KERN_ERR "returned page for vma we don\'t know %p (%s %d)\n", pVma, current->comm, current->pid); -+ -+ return 0; -+ } -+} -+ -+/****** GENERIC FUNCTIONS ******/ -+static int __init dmaer_init(void) -+{ -+ int result = alloc_chrdev_region(&g_majorMinor, 0, 1, "dmaer"); -+ if (result < 0) -+ { -+ PRINTK(KERN_ERR "unable to get major device number\n"); -+ return result; -+ } -+ else -+ PRINTK(KERN_DEBUG "major device number %d\n", MAJOR(g_majorMinor)); -+ -+ PRINTK(KERN_DEBUG "vma list size %d, page list size %d, page size %ld\n", -+ sizeof(struct VmaPageList), sizeof(struct PageList), PAGE_SIZE); -+ -+ //get a dma channel to work with -+ result = bcm_dma_chan_alloc(BCM_DMA_FEATURE_FAST, (void **)&g_pDmaChanBase, &g_dmaIrq); -+ -+ //uncomment to force to channel 0 -+ //result = 0; -+ //g_pDmaChanBase = 0xce808000; -+ -+ if (result < 0) -+ { -+ PRINTK(KERN_ERR "failed to allocate dma channel\n"); -+ cdev_del(&g_cDev); -+ unregister_chrdev_region(g_majorMinor, 1); -+ } -+ -+ //reset the channel -+ PRINTK(KERN_DEBUG "allocated dma channel %d (%p), initial state %08x\n", result, g_pDmaChanBase, *g_pDmaChanBase); -+ *g_pDmaChanBase = 1 << 31; -+ PRINTK(KERN_DEBUG "post-reset %08x\n", *g_pDmaChanBase); -+ -+ g_dmaChan = result; -+ -+ //clear the cache stats -+ g_cacheHit = 0; -+ g_cacheMiss = 0; -+ -+ //register our device - after this we are go go go -+ cdev_init(&g_cDev, &g_fOps); -+ g_cDev.owner = THIS_MODULE; -+ g_cDev.ops = &g_fOps; -+ -+ result = cdev_add(&g_cDev, g_majorMinor, 1); -+ if (result < 0) -+ { -+ PRINTK(KERN_ERR "failed to add character device\n"); -+ unregister_chrdev_region(g_majorMinor, 1); -+ bcm_dma_chan_free(g_dmaChan); -+ return result; -+ } -+ -+ return 0; -+} -+ -+static void __exit dmaer_exit(void) -+{ -+ PRINTK(KERN_INFO "closing dmaer device, cache stats: %d hits %d misses\n", g_cacheHit, g_cacheMiss); -+ //unregister the device -+ cdev_del(&g_cDev); -+ unregister_chrdev_region(g_majorMinor, 1); -+ //free the dma channel -+ bcm_dma_chan_free(g_dmaChan); -+} -+ -+MODULE_LICENSE("Dual BSD/GPL"); -+MODULE_AUTHOR("Simon Hall"); -+module_init(dmaer_init); -+module_exit(dmaer_exit); -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/arm_control.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/arm_control.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/arm_control.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/arm_control.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/arm_control.h linux-rpi/arch/arm/mach-bcm2708/include/mach/arm_control.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/arm_control.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/arm_control.h 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,419 @@ +/* + * linux/arch/arm/mach-bcm2708/arm_control.h @@ -5941,9 +5128,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/arm_control.h linux-r +#define AJBTDO HW_REGISTER_RW(AJB_BASE+0x0c) + +#endif -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/arm_power.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/arm_power.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/arm_power.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/arm_power.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/arm_power.h linux-rpi/arch/arm/mach-bcm2708/include/mach/arm_power.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/arm_power.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/arm_power.h 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,60 @@ +/* + * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h @@ -6005,9 +5192,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/arm_power.h linux-ras +}; + +#endif -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/clkdev.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/clkdev.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/clkdev.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/clkdev.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/clkdev.h linux-rpi/arch/arm/mach-bcm2708/include/mach/clkdev.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/clkdev.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/clkdev.h 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H @@ -6016,9 +5203,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/clkdev.h linux-raspbe +#define __clk_put(clk) do { } while (0) + +#endif -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/debug-macro.S linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/debug-macro.S ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/debug-macro.S 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/debug-macro.S 2014-03-11 17:51:02.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/debug-macro.S linux-rpi/arch/arm/mach-bcm2708/include/mach/debug-macro.S +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/debug-macro.S 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/debug-macro.S 2014-04-24 16:04:30.051029784 +0200 @@ -0,0 +1,22 @@ +/* arch/arm/mach-bcm2708/include/mach/debug-macro.S + * @@ -6042,9 +5229,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/debug-macro.S linux-r + .endm + +#include <debug/pl01x.S> -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/dma.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/dma.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/dma.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/dma.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/dma.h linux-rpi/arch/arm/mach-bcm2708/include/mach/dma.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/dma.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/dma.h 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,90 @@ +/* + * linux/arch/arm/mach-bcm2708/include/mach/dma.h @@ -6136,9 +5323,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/dma.h linux-raspberry + + +#endif /* _MACH_BCM2708_DMA_H */ -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/entry-macro.S linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/entry-macro.S ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/entry-macro.S 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/entry-macro.S 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/entry-macro.S linux-rpi/arch/arm/mach-bcm2708/include/mach/entry-macro.S +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/entry-macro.S 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/entry-macro.S 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,69 @@ +/* + * arch/arm/mach-bcm2708/include/mach/entry-macro.S @@ -6209,9 +5396,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/entry-macro.S linux-r +1020: @ EQ will be set if no irqs pending + + .endm -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/frc.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/frc.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/frc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/frc.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/frc.h linux-rpi/arch/arm/mach-bcm2708/include/mach/frc.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/frc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/frc.h 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,38 @@ +/* + * arch/arm/mach-bcm2708/include/mach/timex.h @@ -6251,9 +5438,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/frc.h linux-raspberry +extern unsigned long long frc_clock_ticks63(void); + +#endif -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/gpio.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/gpio.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/gpio.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/gpio.h 2014-03-11 17:51:02.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/gpio.h linux-rpi/arch/arm/mach-bcm2708/include/mach/gpio.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/gpio.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/gpio.h 2014-04-24 16:04:30.051029784 +0200 @@ -0,0 +1,17 @@ +/* + * arch/arm/mach-bcm2708/include/mach/gpio.h @@ -6266,15 +5453,15 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/gpio.h linux-raspberr +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H + -+#define ARCH_NR_GPIOS 54 // number of gpio lines ++#define BCM2708_NR_GPIOS 54 // number of gpio lines + +#define gpio_to_irq(x) ((x) + GPIO_IRQ_START) +#define irq_to_gpio(x) ((x) - GPIO_IRQ_START) + +#endif -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/hardware.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/hardware.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/hardware.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/hardware.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/hardware.h linux-rpi/arch/arm/mach-bcm2708/include/mach/hardware.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/hardware.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/hardware.h 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-bcm2708/include/mach/hardware.h @@ -6304,9 +5491,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/hardware.h linux-rasp +#include <mach/platform.h> + +#endif -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/io.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/io.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/io.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/io.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/io.h linux-rpi/arch/arm/mach-bcm2708/include/mach/io.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/io.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/io.h 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,27 @@ +/* + * arch/arm/mach-bcm2708/include/mach/io.h @@ -6335,10 +5522,10 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/io.h linux-raspberry- +#define __io(a) __typesafe_io(a) + +#endif -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/irqs.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/irqs.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/irqs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/irqs.h 2014-03-11 17:31:43.000000000 +0100 -@@ -0,0 +1,199 @@ +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/irqs.h linux-rpi/arch/arm/mach-bcm2708/include/mach/irqs.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/irqs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/irqs.h 2014-04-24 16:04:30.051029784 +0200 +@@ -0,0 +1,200 @@ +/* + * arch/arm/mach-bcm2708/include/mach/irqs.h + * @@ -6533,14 +5720,15 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/irqs.h linux-raspberr +#define HARD_IRQS (64 + 21) +#define FIQ_IRQS (64 + 21) +#define GPIO_IRQS (32*5) ++#define SPARE_IRQS (64) + -+#define NR_IRQS HARD_IRQS+FIQ_IRQS+GPIO_IRQS ++#define NR_IRQS HARD_IRQS+FIQ_IRQS+GPIO_IRQS+SPARE_IRQS + + +#endif /* _BCM2708_IRQS_H_ */ -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/memory.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/memory.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/memory.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/memory.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/memory.h linux-rpi/arch/arm/mach-bcm2708/include/mach/memory.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/memory.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/memory.h 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,57 @@ +/* + * arch/arm/mach-bcm2708/include/mach/memory.h @@ -6599,9 +5787,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/memory.h linux-raspbe +#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PLAT_PHYS_OFFSET)) + +#endif -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/platform.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/platform.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/platform.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/platform.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/platform.h linux-rpi/arch/arm/mach-bcm2708/include/mach/platform.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/platform.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/platform.h 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,228 @@ +/* + * arch/arm/mach-bcm2708/include/mach/platform.h @@ -6831,9 +6019,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/platform.h linux-rasp +#endif + +/* END */ -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/power.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/power.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/power.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/power.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/power.h linux-rpi/arch/arm/mach-bcm2708/include/mach/power.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/power.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/power.h 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,26 @@ +/* + * linux/arch/arm/mach-bcm2708/power.h @@ -6861,9 +6049,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/power.h linux-raspber +extern int bcm_power_close(BCM_POWER_HANDLE_T handle); + +#endif -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/system.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/system.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/system.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/system.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/system.h linux-rpi/arch/arm/mach-bcm2708/include/mach/system.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/system.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/system.h 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,38 @@ +/* + * arch/arm/mach-bcm2708/include/mach/system.h @@ -6903,9 +6091,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/system.h linux-raspbe +} + +#endif -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/timex.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/timex.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/timex.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/timex.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/timex.h linux-rpi/arch/arm/mach-bcm2708/include/mach/timex.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/timex.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/timex.h 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,23 @@ +/* + * arch/arm/mach-bcm2708/include/mach/timex.h @@ -6930,9 +6118,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/timex.h linux-raspber + */ + +#define CLOCK_TICK_RATE (1000000) -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/uncompress.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/uncompress.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/uncompress.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/uncompress.h 2014-03-11 17:51:02.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/uncompress.h linux-rpi/arch/arm/mach-bcm2708/include/mach/uncompress.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/uncompress.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/uncompress.h 2014-04-24 16:04:30.051029784 +0200 @@ -0,0 +1,84 @@ +/* + * arch/arm/mach-bcn2708/include/mach/uncompress.h @@ -7018,9 +6206,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/uncompress.h linux-ra + * nothing to do + */ +#define arch_decomp_wdog() -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vcio.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vcio.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vcio.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vcio.h 2014-03-11 17:51:02.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/vcio.h linux-rpi/arch/arm/mach-bcm2708/include/mach/vcio.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/vcio.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/vcio.h 2014-04-24 16:04:30.051029784 +0200 @@ -0,0 +1,141 @@ +/* + * arch/arm/mach-bcm2708/include/mach/vcio.h @@ -7163,9 +6351,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vcio.h linux-raspberr +#define DEVICE_FILE_NAME "char_dev" + +#endif -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vc_mem.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vc_mem.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vc_mem.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vc_mem.h 2014-03-11 17:51:02.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/vc_mem.h linux-rpi/arch/arm/mach-bcm2708/include/mach/vc_mem.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/vc_mem.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/vc_mem.h 2014-04-24 16:04:30.051029784 +0200 @@ -0,0 +1,35 @@ +/***************************************************************************** +* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. @@ -7202,82 +6390,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vc_mem.h linux-raspbe +#endif + +#endif /* VC_MEM_H */ -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vc_support.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vc_support.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vc_support.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vc_support.h 2014-03-11 17:31:43.000000000 +0100 -@@ -0,0 +1,69 @@ -+#ifndef _VC_SUPPORT_H_ -+#define _VC_SUPPORT_H_ -+ -+/* -+ * vc_support.h -+ * -+ * Created on: 25 Nov 2012 -+ * Author: Simon -+ */ -+ -+enum { -+/* -+ If a MEM_HANDLE_T is discardable, the memory manager may resize it to size -+ 0 at any time when it is not locked or retained. -+ */ -+ MEM_FLAG_DISCARDABLE = 1 << 0, -+ -+ /* -+ If a MEM_HANDLE_T is allocating (or normal), its block of memory will be -+ accessed in an allocating fashion through the cache. -+ */ -+ MEM_FLAG_NORMAL = 0 << 2, -+ MEM_FLAG_ALLOCATING = MEM_FLAG_NORMAL, -+ -+ /* -+ If a MEM_HANDLE_T is direct, its block of memory will be accessed -+ directly, bypassing the cache. -+ */ -+ MEM_FLAG_DIRECT = 1 << 2, -+ -+ /* -+ If a MEM_HANDLE_T is coherent, its block of memory will be accessed in a -+ non-allocating fashion through the cache. -+ */ -+ MEM_FLAG_COHERENT = 2 << 2, -+ -+ /* -+ If a MEM_HANDLE_T is L1-nonallocating, its block of memory will be accessed by -+ the VPU in a fashion which is allocating in L2, but only coherent in L1. -+ */ -+ MEM_FLAG_L1_NONALLOCATING = (MEM_FLAG_DIRECT | MEM_FLAG_COHERENT), -+ -+ /* -+ If a MEM_HANDLE_T is zero'd, its contents are set to 0 rather than -+ MEM_HANDLE_INVALID on allocation and resize up. -+ */ -+ MEM_FLAG_ZERO = 1 << 4, -+ -+ /* -+ If a MEM_HANDLE_T is uninitialised, it will not be reset to a defined value -+ (either zero, or all 1's) on allocation. -+ */ -+ MEM_FLAG_NO_INIT = 1 << 5, -+ -+ /* -+ Hints. -+ */ -+ MEM_FLAG_HINT_PERMALOCK = 1 << 6, /* Likely to be locked for long periods of time. */ -+}; -+ -+unsigned int AllocateVcMemory(unsigned int *pHandle, unsigned int size, unsigned int alignment, unsigned int flags); -+unsigned int ReleaseVcMemory(unsigned int handle); -+unsigned int LockVcMemory(unsigned int *pBusAddress, unsigned int handle); -+unsigned int UnlockVcMemory(unsigned int handle); -+ -+unsigned int ExecuteVcCode(unsigned int code, -+ unsigned int r0, unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int r5); -+ -+#endif -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vmalloc.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vmalloc.h ---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vmalloc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vmalloc.h 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/vmalloc.h linux-rpi/arch/arm/mach-bcm2708/include/mach/vmalloc.h +--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/vmalloc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/vmalloc.h 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,20 @@ +/* + * arch/arm/mach-bcm2708/include/mach/vmalloc.h @@ -7299,10 +6414,10 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vmalloc.h linux-raspb + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#define VMALLOC_END (0xe8000000) -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/Kconfig linux-raspberry-pi/arch/arm/mach-bcm2708/Kconfig ---- linux-3.12.13/arch/arm/mach-bcm2708/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/Kconfig 2014-03-11 17:51:02.000000000 +0100 -@@ -0,0 +1,49 @@ +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/Kconfig linux-rpi/arch/arm/mach-bcm2708/Kconfig +--- linux-3.12.18/arch/arm/mach-bcm2708/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/Kconfig 2014-04-24 16:04:30.051029784 +0200 +@@ -0,0 +1,41 @@ +menu "Broadcom BCM2708 Implementations" + depends on ARCH_BCM2708 + @@ -7343,19 +6458,11 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/Kconfig linux-raspberry-pi/arch/ar + default y + help + Binds spidev driver to the SPI0 master -+ -+config BCM2708_DMAER -+ tristate "BCM2708 DMA helper" -+ depends on MACH_BCM2708 -+ default n -+ help -+ Enable DMA helper for accelerating X composition -+ +endmenu -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/Makefile linux-raspberry-pi/arch/arm/mach-bcm2708/Makefile ---- linux-3.12.13/arch/arm/mach-bcm2708/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/Makefile 2014-03-11 17:51:02.000000000 +0100 -@@ -0,0 +1,10 @@ +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/Makefile linux-rpi/arch/arm/mach-bcm2708/Makefile +--- linux-3.12.18/arch/arm/mach-bcm2708/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/Makefile 2014-04-24 16:04:30.051029784 +0200 +@@ -0,0 +1,7 @@ +# +# Makefile for the linux kernel. +# @@ -7363,19 +6470,16 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/Makefile linux-raspberry-pi/arch/a +obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o +obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o +obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -+ -+obj-$(CONFIG_BCM2708_DMAER) += dmaer_master.o -+dmaer_master-objs := dmaer.o vc_support.o -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/Makefile.boot linux-raspberry-pi/arch/arm/mach-bcm2708/Makefile.boot ---- linux-3.12.13/arch/arm/mach-bcm2708/Makefile.boot 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/Makefile.boot 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/Makefile.boot linux-rpi/arch/arm/mach-bcm2708/Makefile.boot +--- linux-3.12.18/arch/arm/mach-bcm2708/Makefile.boot 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/Makefile.boot 2014-04-24 15:35:00.773527891 +0200 @@ -0,0 +1,3 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00800000 -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/power.c linux-raspberry-pi/arch/arm/mach-bcm2708/power.c ---- linux-3.12.13/arch/arm/mach-bcm2708/power.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/power.c 2014-03-11 17:31:43.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/power.c linux-rpi/arch/arm/mach-bcm2708/power.c +--- linux-3.12.18/arch/arm/mach-bcm2708/power.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/power.c 2014-04-24 15:35:00.777527936 +0200 @@ -0,0 +1,194 @@ +/* + * linux/arch/arm/mach-bcm2708/power.c @@ -7571,9 +6675,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/power.c linux-raspberry-pi/arch/ar +MODULE_AUTHOR("Phil Elwell"); +MODULE_DESCRIPTION("Interface to BCM2708 power management"); +MODULE_LICENSE("GPL"); -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vcio.c linux-raspberry-pi/arch/arm/mach-bcm2708/vcio.c ---- linux-3.12.13/arch/arm/mach-bcm2708/vcio.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/vcio.c 2014-03-11 17:51:02.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/vcio.c linux-rpi/arch/arm/mach-bcm2708/vcio.c +--- linux-3.12.18/arch/arm/mach-bcm2708/vcio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/vcio.c 2014-04-24 16:04:30.051029784 +0200 @@ -0,0 +1,474 @@ +/* + * linux/arch/arm/mach-bcm2708/vcio.c @@ -8049,10 +7153,10 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vcio.c linux-raspberry-pi/arch/arm +MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:bcm-mbox"); -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/arm/mach-bcm2708/vc_mem.c ---- linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/vc_mem.c 2014-03-11 17:51:02.000000000 +0100 -@@ -0,0 +1,462 @@ +diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/vc_mem.c linux-rpi/arch/arm/mach-bcm2708/vc_mem.c +--- linux-3.12.18/arch/arm/mach-bcm2708/vc_mem.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/arch/arm/mach-bcm2708/vc_mem.c 2014-04-24 15:35:00.777527936 +0200 +@@ -0,0 +1,432 @@ +/***************************************************************************** +* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. +* @@ -8074,7 +7178,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a +#include <linux/cdev.h> +#include <linux/mm.h> +#include <linux/slab.h> -+#include <linux/proc_fs.h> ++#include <linux/debugfs.h> +#include <asm/uaccess.h> +#include <linux/dma-mapping.h> + @@ -8090,24 +7194,15 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a + +#define DRIVER_NAME "vc-mem" + -+// Uncomment to enable debug logging -+// #define ENABLE_DBG -+ -+#if defined(ENABLE_DBG) -+#define LOG_DBG( fmt, ... ) printk( KERN_INFO fmt "\n", ##__VA_ARGS__ ) -+#else -+#define LOG_DBG( fmt, ... ) -+#endif -+#define LOG_ERR( fmt, ... ) printk( KERN_ERR fmt "\n", ##__VA_ARGS__ ) -+ +// Device (/dev) related variables +static dev_t vc_mem_devnum = 0; +static struct class *vc_mem_class = NULL; +static struct cdev vc_mem_cdev; +static int vc_mem_inited = 0; + -+// Proc entry -+static struct proc_dir_entry *vc_mem_proc_entry; ++#ifdef CONFIG_DEBUG_FS ++static struct dentry *vc_mem_debugfs_entry; ++#endif + +/* + * Videocore memory addresses and size @@ -8149,7 +7244,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a + (void) inode; + (void) file; + -+ LOG_DBG("%s: called file = 0x%p", __func__, file); ++ pr_debug("%s: called file = 0x%p\n", __func__, file); + + return 0; +} @@ -8166,7 +7261,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a + (void) inode; + (void) file; + -+ LOG_DBG("%s: called file = 0x%p", __func__, file); ++ pr_debug("%s: called file = 0x%p\n", __func__, file); + + return 0; +} @@ -8221,12 +7316,12 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a + (void) cmd; + (void) arg; + -+ LOG_DBG("%s: called file = 0x%p", __func__, file); ++ pr_debug("%s: called file = 0x%p\n", __func__, file); + + switch (cmd) { + case VC_MEM_IOC_MEM_PHYS_ADDR: + { -+ LOG_DBG("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p", ++ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", + __func__, (void *) mm_vc_mem_phys_addr); + + if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, @@ -8240,7 +7335,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a + // Get the videocore memory size first + vc_mem_get_size(); + -+ LOG_DBG("%s: VC_MEM_IOC_MEM_SIZE=%u", __func__, ++ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, + mm_vc_mem_size); + + if (copy_to_user((void *) arg, &mm_vc_mem_size, @@ -8254,7 +7349,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a + // Get the videocore memory base + vc_mem_get_base(); + -+ LOG_DBG("%s: VC_MEM_IOC_MEM_BASE=%u", __func__, ++ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, + mm_vc_mem_base); + + if (copy_to_user((void *) arg, &mm_vc_mem_base, @@ -8268,7 +7363,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a + // Get the videocore memory base + vc_mem_get_base(); + -+ LOG_DBG("%s: VC_MEM_IOC_MEM_LOAD=%u", __func__, ++ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, + mm_vc_mem_base); + + if (copy_to_user((void *) arg, &mm_vc_mem_base, @@ -8282,7 +7377,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a + return -ENOTTY; + } + } -+ LOG_DBG("%s: file = 0x%p returning %d", __func__, file, rc); ++ pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); + + return rc; +} @@ -8300,12 +7395,12 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a + unsigned long length = vma->vm_end - vma->vm_start; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + -+ LOG_DBG("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx", ++ pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", + __func__, (long) vma->vm_start, (long) vma->vm_end, + (long) vma->vm_pgoff); + + if (offset + length > mm_vc_mem_size) { -+ LOG_ERR("%s: length %ld is too big", __func__, length); ++ pr_err("%s: length %ld is too big\n", __func__, length); + return -EINVAL; + } + // Do not cache the memory map @@ -8315,7 +7410,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a + (mm_vc_mem_phys_addr >> PAGE_SHIFT) + + vma->vm_pgoff, length, vma->vm_page_prot); + if (rc != 0) { -+ LOG_ERR("%s: remap_pfn_range failed (rc=%d)", __func__, rc); ++ pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); + } + + return rc; @@ -8335,75 +7430,60 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a + .mmap = vc_mem_mmap, +}; + -+/**************************************************************************** -+* -+* vc_mem_proc_read -+* -+***************************************************************************/ -+ -+static int -+vc_mem_proc_read(char *buf, char **start, off_t offset, int count, int *eof, -+ void *data) ++#ifdef CONFIG_DEBUG_FS ++static void vc_mem_debugfs_deinit(void) +{ -+ char *p = buf; -+ -+ (void) start; -+ (void) count; -+ (void) data; -+ -+ if (offset > 0) { -+ *eof = 1; -+ return 0; -+ } -+ // Get the videocore memory size first -+ vc_mem_get_size(); -+ -+ p += sprintf(p, "Videocore memory:\n"); -+ if (mm_vc_mem_phys_addr != 0) -+ p += sprintf(p, " Physical address: 0x%p\n", -+ (void *) mm_vc_mem_phys_addr); -+ else -+ p += sprintf(p, " Physical address: 0x00000000\n"); -+ p += sprintf(p, " Length (bytes): %u\n", mm_vc_mem_size); -+ -+ *eof = 1; -+ return p - buf; ++ debugfs_remove_recursive(vc_mem_debugfs_entry); ++ vc_mem_debugfs_entry = NULL; +} + -+/**************************************************************************** -+* -+* vc_mem_proc_write -+* -+***************************************************************************/ + -+static int -+vc_mem_proc_write(struct file *file, const char __user * buffer, -+ unsigned long count, void *data) ++static int vc_mem_debugfs_init( ++ struct device *dev) +{ -+ int rc = -EFAULT; -+ char input_str[10]; -+ -+ memset(input_str, 0, sizeof (input_str)); ++ vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); ++ if (!vc_mem_debugfs_entry) { ++ dev_warn(dev, "could not create debugfs entry\n"); ++ return -EFAULT; ++ } + -+ if (count > sizeof (input_str)) { -+ LOG_ERR("%s: input string length too long", __func__); -+ goto out; ++ if (!debugfs_create_x32("vc_mem_phys_addr", ++ 0444, ++ vc_mem_debugfs_entry, ++ (u32 *)&mm_vc_mem_phys_addr)) { ++ dev_warn(dev, "%s:could not create vc_mem_phys entry\n", ++ __func__); ++ goto fail; + } + -+ if (copy_from_user(input_str, buffer, count - 1)) { -+ LOG_ERR("%s: failed to get input string", __func__); -+ goto out; ++ if (!debugfs_create_x32("vc_mem_size", ++ 0444, ++ vc_mem_debugfs_entry, ++ (u32 *)&mm_vc_mem_size)) { ++ dev_warn(dev, "%s:could not create vc_mem_size entry\n", ++ __func__); ++ goto fail; + } + -+ if (strncmp(input_str, "connect", strlen("connect")) == 0) { -+ // Get the videocore memory size from the videocore -+ vc_mem_get_size(); ++ if (!debugfs_create_x32("vc_mem_base", ++ 0444, ++ vc_mem_debugfs_entry, ++ (u32 *)&mm_vc_mem_base)) { ++ dev_warn(dev, "%s:could not create vc_mem_base entry\n", ++ __func__); ++ goto fail; + } + -+ out: -+ return rc; ++ return 0; ++ ++fail: ++ vc_mem_debugfs_deinit(); ++ return -EFAULT; +} + ++#endif /* CONFIG_DEBUG_FS */ ++ ++ +/**************************************************************************** +* +* vc_mem_init @@ -8416,7 +7496,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a + int rc = -EFAULT; + struct device *dev; + -+ LOG_DBG("%s: called", __func__); ++ pr_debug("%s: called\n", __func__); + + mm_vc_mem_phys_addr = phys_addr; + mm_vc_mem_size = mem_size; @@ -8424,24 +7504,25 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a + + vc_mem_get_size(); + -+ printk("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", ++ pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", + mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); + + if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { -+ LOG_ERR("%s: alloc_chrdev_region failed (rc=%d)", __func__, rc); ++ pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", ++ __func__, rc); + goto out_err; + } + + cdev_init(&vc_mem_cdev, &vc_mem_fops); + if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { -+ LOG_ERR("%s: cdev_add failed (rc=%d)", __func__, rc); ++ pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); + goto out_unregister; + } + + vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); + if (IS_ERR(vc_mem_class)) { + rc = PTR_ERR(vc_mem_class); -+ LOG_ERR("%s: class_create failed (rc=%d)", __func__, rc); ++ pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); + goto out_cdev_del; + } + @@ -8449,25 +7530,18 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a + DRIVER_NAME); + if (IS_ERR(dev)) { + rc = PTR_ERR(dev); -+ LOG_ERR("%s: device_create failed (rc=%d)", __func__, rc); ++ pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); + goto out_class_destroy; + } + -+#if 0 -+ vc_mem_proc_entry = create_proc_entry(DRIVER_NAME, 0444, NULL); -+ if (vc_mem_proc_entry == NULL) { -+ rc = -EFAULT; -+ LOG_ERR("%s: create_proc_entry failed", __func__); -+ goto out_device_destroy; -+ } -+ vc_mem_proc_entry->read_proc = vc_mem_proc_read; -+ vc_mem_proc_entry->write_proc = vc_mem_proc_write; ++#ifdef CONFIG_DEBUG_FS ++ /* don't fail if the debug entries cannot be created */ ++ vc_mem_debugfs_init(dev); +#endif + + vc_mem_inited = 1; + return 0; + -+ out_device_destroy: + device_destroy(vc_mem_class, vc_mem_devnum); + + out_class_destroy: @@ -8493,11 +7567,11 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a +static void __exit +vc_mem_exit(void) +{ -+ LOG_DBG("%s: called", __func__); ++ pr_debug("%s: called\n", __func__); + + if (vc_mem_inited) { -+#if 0 -+ remove_proc_entry(vc_mem_proc_entry->name, NULL); ++#if CONFIG_DEBUG_FS ++ vc_mem_debugfs_deinit(); +#endif + device_destroy(vc_mem_class, vc_mem_devnum); + class_destroy(vc_mem_class); @@ -8515,331 +7589,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a +module_param(mem_size, uint, 0644); +module_param(mem_base, uint, 0644); + -diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_support.c linux-raspberry-pi/arch/arm/mach-bcm2708/vc_support.c ---- linux-3.12.13/arch/arm/mach-bcm2708/vc_support.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mach-bcm2708/vc_support.c 2014-03-11 17:51:02.000000000 +0100 -@@ -0,0 +1,318 @@ -+/* -+ * vc_support.c -+ * -+ * Created on: 25 Nov 2012 -+ * Author: Simon -+ */ -+ -+#include <linux/module.h> -+#include <mach/vcio.h> -+ -+#ifdef ECLIPSE_IGNORE -+ -+#define __user -+#define __init -+#define __exit -+#define __iomem -+#define KERN_DEBUG -+#define KERN_ERR -+#define KERN_WARNING -+#define KERN_INFO -+#define _IOWR(a, b, c) b -+#define _IOW(a, b, c) b -+#define _IO(a, b) b -+ -+#endif -+ -+/****** VC MAILBOX FUNCTIONALITY ******/ -+unsigned int AllocateVcMemory(unsigned int *pHandle, unsigned int size, unsigned int alignment, unsigned int flags) -+{ -+ struct vc_msg -+ { -+ unsigned int m_msgSize; -+ unsigned int m_response; -+ -+ struct vc_tag -+ { -+ unsigned int m_tagId; -+ unsigned int m_sendBufferSize; -+ union { -+ unsigned int m_sendDataSize; -+ unsigned int m_recvDataSize; -+ }; -+ -+ struct args -+ { -+ union { -+ unsigned int m_size; -+ unsigned int m_handle; -+ }; -+ unsigned int m_alignment; -+ unsigned int m_flags; -+ } m_args; -+ } m_tag; -+ -+ unsigned int m_endTag; -+ } msg; -+ int s; -+ -+ msg.m_msgSize = sizeof(msg); -+ msg.m_response = 0; -+ msg.m_endTag = 0; -+ -+ //fill in the tag for the allocation command -+ msg.m_tag.m_tagId = 0x3000c; -+ msg.m_tag.m_sendBufferSize = 12; -+ msg.m_tag.m_sendDataSize = 12; -+ -+ //fill in our args -+ msg.m_tag.m_args.m_size = size; -+ msg.m_tag.m_args.m_alignment = alignment; -+ msg.m_tag.m_args.m_flags = flags; -+ -+ //run the command -+ s = bcm_mailbox_property(&msg, sizeof(msg)); -+ -+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004) -+ { -+ *pHandle = msg.m_tag.m_args.m_handle; -+ return 0; -+ } -+ else -+ { -+ printk(KERN_ERR "failed to allocate vc memory: s=%d response=%08x recv data size=%08x\n", -+ s, msg.m_response, msg.m_tag.m_recvDataSize); -+ return 1; -+ } -+} -+ -+unsigned int ReleaseVcMemory(unsigned int handle) -+{ -+ struct vc_msg -+ { -+ unsigned int m_msgSize; -+ unsigned int m_response; -+ -+ struct vc_tag -+ { -+ unsigned int m_tagId; -+ unsigned int m_sendBufferSize; -+ union { -+ unsigned int m_sendDataSize; -+ unsigned int m_recvDataSize; -+ }; -+ -+ struct args -+ { -+ union { -+ unsigned int m_handle; -+ unsigned int m_error; -+ }; -+ } m_args; -+ } m_tag; -+ -+ unsigned int m_endTag; -+ } msg; -+ int s; -+ -+ msg.m_msgSize = sizeof(msg); -+ msg.m_response = 0; -+ msg.m_endTag = 0; -+ -+ //fill in the tag for the release command -+ msg.m_tag.m_tagId = 0x3000f; -+ msg.m_tag.m_sendBufferSize = 4; -+ msg.m_tag.m_sendDataSize = 4; -+ -+ //pass across the handle -+ msg.m_tag.m_args.m_handle = handle; -+ -+ s = bcm_mailbox_property(&msg, sizeof(msg)); -+ -+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004 && msg.m_tag.m_args.m_error == 0) -+ return 0; -+ else -+ { -+ printk(KERN_ERR "failed to release vc memory: s=%d response=%08x recv data size=%08x error=%08x\n", -+ s, msg.m_response, msg.m_tag.m_recvDataSize, msg.m_tag.m_args.m_error); -+ return 1; -+ } -+} -+ -+unsigned int LockVcMemory(unsigned int *pBusAddress, unsigned int handle) -+{ -+ struct vc_msg -+ { -+ unsigned int m_msgSize; -+ unsigned int m_response; -+ -+ struct vc_tag -+ { -+ unsigned int m_tagId; -+ unsigned int m_sendBufferSize; -+ union { -+ unsigned int m_sendDataSize; -+ unsigned int m_recvDataSize; -+ }; -+ -+ struct args -+ { -+ union { -+ unsigned int m_handle; -+ unsigned int m_busAddress; -+ }; -+ } m_args; -+ } m_tag; -+ -+ unsigned int m_endTag; -+ } msg; -+ int s; -+ -+ msg.m_msgSize = sizeof(msg); -+ msg.m_response = 0; -+ msg.m_endTag = 0; -+ -+ //fill in the tag for the lock command -+ msg.m_tag.m_tagId = 0x3000d; -+ msg.m_tag.m_sendBufferSize = 4; -+ msg.m_tag.m_sendDataSize = 4; -+ -+ //pass across the handle -+ msg.m_tag.m_args.m_handle = handle; -+ -+ s = bcm_mailbox_property(&msg, sizeof(msg)); -+ -+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004) -+ { -+ //pick out the bus address -+ *pBusAddress = msg.m_tag.m_args.m_busAddress; -+ return 0; -+ } -+ else -+ { -+ printk(KERN_ERR "failed to lock vc memory: s=%d response=%08x recv data size=%08x\n", -+ s, msg.m_response, msg.m_tag.m_recvDataSize); -+ return 1; -+ } -+} -+ -+unsigned int UnlockVcMemory(unsigned int handle) -+{ -+ struct vc_msg -+ { -+ unsigned int m_msgSize; -+ unsigned int m_response; -+ -+ struct vc_tag -+ { -+ unsigned int m_tagId; -+ unsigned int m_sendBufferSize; -+ union { -+ unsigned int m_sendDataSize; -+ unsigned int m_recvDataSize; -+ }; -+ -+ struct args -+ { -+ union { -+ unsigned int m_handle; -+ unsigned int m_error; -+ }; -+ } m_args; -+ } m_tag; -+ -+ unsigned int m_endTag; -+ } msg; -+ int s; -+ -+ msg.m_msgSize = sizeof(msg); -+ msg.m_response = 0; -+ msg.m_endTag = 0; -+ -+ //fill in the tag for the unlock command -+ msg.m_tag.m_tagId = 0x3000e; -+ msg.m_tag.m_sendBufferSize = 4; -+ msg.m_tag.m_sendDataSize = 4; -+ -+ //pass across the handle -+ msg.m_tag.m_args.m_handle = handle; -+ -+ s = bcm_mailbox_property(&msg, sizeof(msg)); -+ -+ //check the error code too -+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004 && msg.m_tag.m_args.m_error == 0) -+ return 0; -+ else -+ { -+ printk(KERN_ERR "failed to unlock vc memory: s=%d response=%08x recv data size=%08x error%08x\n", -+ s, msg.m_response, msg.m_tag.m_recvDataSize, msg.m_tag.m_args.m_error); -+ return 1; -+ } -+} -+ -+unsigned int ExecuteVcCode(unsigned int code, -+ unsigned int r0, unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int r5) -+{ -+ struct vc_msg -+ { -+ unsigned int m_msgSize; -+ unsigned int m_response; -+ -+ struct vc_tag -+ { -+ unsigned int m_tagId; -+ unsigned int m_sendBufferSize; -+ union { -+ unsigned int m_sendDataSize; -+ unsigned int m_recvDataSize; -+ }; -+ -+ struct args -+ { -+ union { -+ unsigned int m_pCode; -+ unsigned int m_return; -+ }; -+ unsigned int m_r0; -+ unsigned int m_r1; -+ unsigned int m_r2; -+ unsigned int m_r3; -+ unsigned int m_r4; -+ unsigned int m_r5; -+ } m_args; -+ } m_tag; -+ -+ unsigned int m_endTag; -+ } msg; -+ int s; -+ -+ msg.m_msgSize = sizeof(msg); -+ msg.m_response = 0; -+ msg.m_endTag = 0; -+ -+ //fill in the tag for the unlock command -+ msg.m_tag.m_tagId = 0x30010; -+ msg.m_tag.m_sendBufferSize = 28; -+ msg.m_tag.m_sendDataSize = 28; -+ -+ //pass across the handle -+ msg.m_tag.m_args.m_pCode = code; -+ msg.m_tag.m_args.m_r0 = r0; -+ msg.m_tag.m_args.m_r1 = r1; -+ msg.m_tag.m_args.m_r2 = r2; -+ msg.m_tag.m_args.m_r3 = r3; -+ msg.m_tag.m_args.m_r4 = r4; -+ msg.m_tag.m_args.m_r5 = r5; -+ -+ s = bcm_mailbox_property(&msg, sizeof(msg)); -+ -+ //check the error code too -+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004) -+ return msg.m_tag.m_args.m_return; -+ else -+ { -+ printk(KERN_ERR "failed to execute: s=%d response=%08x recv data size=%08x\n", -+ s, msg.m_response, msg.m_tag.m_recvDataSize); -+ return 1; -+ } -+} -diff -Nur linux-3.12.13/arch/arm/Makefile linux-raspberry-pi/arch/arm/Makefile ---- linux-3.12.13/arch/arm/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/Makefile 2014-03-11 17:51:00.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/Makefile linux-rpi/arch/arm/Makefile +--- linux-3.12.18/arch/arm/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/arm/Makefile 2014-04-24 16:04:29.515024597 +0200 @@ -146,6 +146,7 @@ # by CONFIG_* macro name. machine-$(CONFIG_ARCH_AT91) += at91 @@ -8848,9 +7600,9 @@ diff -Nur linux-3.12.13/arch/arm/Makefile linux-raspberry-pi/arch/arm/Makefile machine-$(CONFIG_ARCH_BCM2835) += bcm2835 machine-$(CONFIG_ARCH_CLPS711X) += clps711x machine-$(CONFIG_ARCH_CNS3XXX) += cns3xxx -diff -Nur linux-3.12.13/arch/arm/mm/Kconfig linux-raspberry-pi/arch/arm/mm/Kconfig ---- linux-3.12.13/arch/arm/mm/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mm/Kconfig 2014-03-11 17:51:03.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mm/Kconfig linux-rpi/arch/arm/mm/Kconfig +--- linux-3.12.18/arch/arm/mm/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/arm/mm/Kconfig 2014-04-24 16:04:31.615044915 +0200 @@ -358,7 +358,7 @@ # ARMv6 @@ -8860,9 +7612,9 @@ diff -Nur linux-3.12.13/arch/arm/mm/Kconfig linux-raspberry-pi/arch/arm/mm/Kconf select CPU_32v6 select CPU_ABRT_EV6 select CPU_CACHE_V6 -diff -Nur linux-3.12.13/arch/arm/mm/proc-v6.S linux-raspberry-pi/arch/arm/mm/proc-v6.S ---- linux-3.12.13/arch/arm/mm/proc-v6.S 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/mm/proc-v6.S 2014-03-11 17:51:03.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/mm/proc-v6.S linux-rpi/arch/arm/mm/proc-v6.S +--- linux-3.12.18/arch/arm/mm/proc-v6.S 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/arm/mm/proc-v6.S 2014-04-24 16:04:31.627045031 +0200 @@ -73,10 +73,19 @@ * * IRQs are already disabled. @@ -8886,9 +7638,9 @@ diff -Nur linux-3.12.13/arch/arm/mm/proc-v6.S linux-raspberry-pi/arch/arm/mm/pro mov pc, lr ENTRY(cpu_v6_dcache_clean_area) -diff -Nur linux-3.12.13/arch/arm/tools/mach-types linux-raspberry-pi/arch/arm/tools/mach-types ---- linux-3.12.13/arch/arm/tools/mach-types 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/arch/arm/tools/mach-types 2014-03-11 17:31:54.000000000 +0100 +diff -Nur linux-3.12.18/arch/arm/tools/mach-types linux-rpi/arch/arm/tools/mach-types +--- linux-3.12.18/arch/arm/tools/mach-types 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/arm/tools/mach-types 2014-04-24 15:35:00.985530254 +0200 @@ -522,6 +522,7 @@ prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 paz00 MACH_PAZ00 PAZ00 3128 @@ -8897,9 +7649,119 @@ diff -Nur linux-3.12.13/arch/arm/tools/mach-types linux-raspberry-pi/arch/arm/to ag5evm MACH_AG5EVM AG5EVM 3189 ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 -diff -Nur linux-3.12.13/Documentation/video4linux/bcm2835-v4l2.txt linux-raspberry-pi/Documentation/video4linux/bcm2835-v4l2.txt ---- linux-3.12.13/Documentation/video4linux/bcm2835-v4l2.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/Documentation/video4linux/bcm2835-v4l2.txt 2014-03-11 17:31:41.000000000 +0100 +diff -Nur linux-3.12.18/arch/m68k/Kconfig linux-rpi/arch/m68k/Kconfig +--- linux-3.12.18/arch/m68k/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/m68k/Kconfig 2014-04-24 16:04:32.771056098 +0200 +@@ -16,7 +16,6 @@ + select FPU if MMU + select ARCH_WANT_IPC_PARSE_VERSION + select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE +- select HAVE_FUTEX_CMPXCHG if MMU && FUTEX + select HAVE_MOD_ARCH_SPECIFIC + select MODULES_USE_ELF_REL + select MODULES_USE_ELF_RELA +diff -Nur linux-3.12.18/arch/s390/Kconfig linux-rpi/arch/s390/Kconfig +--- linux-3.12.18/arch/s390/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/s390/Kconfig 2014-04-24 16:04:33.891066931 +0200 +@@ -116,7 +116,6 @@ + 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 + select HAVE_KERNEL_LZ4 +diff -Nur linux-3.12.18/arch/x86/crypto/ghash-clmulni-intel_asm.S linux-rpi/arch/x86/crypto/ghash-clmulni-intel_asm.S +--- linux-3.12.18/arch/x86/crypto/ghash-clmulni-intel_asm.S 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/x86/crypto/ghash-clmulni-intel_asm.S 2014-04-24 16:04:34.051068479 +0200 +@@ -24,6 +24,10 @@ + .align 16 + .Lbswap_mask: + .octa 0x000102030405060708090a0b0c0d0e0f ++.Lpoly: ++ .octa 0xc2000000000000000000000000000001 ++.Ltwo_one: ++ .octa 0x00000001000000000000000000000001 + + #define DATA %xmm0 + #define SHASH %xmm1 +@@ -130,3 +134,28 @@ + .Lupdate_just_ret: + ret + ENDPROC(clmul_ghash_update) ++ ++/* ++ * void clmul_ghash_setkey(be128 *shash, const u8 *key); ++ * ++ * Calculate hash_key << 1 mod poly ++ */ ++ENTRY(clmul_ghash_setkey) ++ movaps .Lbswap_mask, BSWAP ++ movups (%rsi), %xmm0 ++ PSHUFB_XMM BSWAP %xmm0 ++ movaps %xmm0, %xmm1 ++ psllq $1, %xmm0 ++ psrlq $63, %xmm1 ++ movaps %xmm1, %xmm2 ++ pslldq $8, %xmm1 ++ psrldq $8, %xmm2 ++ por %xmm1, %xmm0 ++ # reduction ++ pshufd $0b00100100, %xmm2, %xmm1 ++ pcmpeqd .Ltwo_one, %xmm1 ++ pand .Lpoly, %xmm1 ++ pxor %xmm1, %xmm0 ++ movups %xmm0, (%rdi) ++ ret ++ENDPROC(clmul_ghash_setkey) +diff -Nur linux-3.12.18/arch/x86/crypto/ghash-clmulni-intel_glue.c linux-rpi/arch/x86/crypto/ghash-clmulni-intel_glue.c +--- linux-3.12.18/arch/x86/crypto/ghash-clmulni-intel_glue.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/arch/x86/crypto/ghash-clmulni-intel_glue.c 2014-04-24 16:04:34.051068479 +0200 +@@ -30,6 +30,8 @@ + void clmul_ghash_update(char *dst, const char *src, unsigned int srclen, + const be128 *shash); + ++void clmul_ghash_setkey(be128 *shash, const u8 *key); ++ + struct ghash_async_ctx { + struct cryptd_ahash *cryptd_tfm; + }; +@@ -56,23 +58,13 @@ + const u8 *key, unsigned int keylen) + { + struct ghash_ctx *ctx = crypto_shash_ctx(tfm); +- be128 *x = (be128 *)key; +- u64 a, b; + + if (keylen != GHASH_BLOCK_SIZE) { + crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + +- /* perform multiplication by 'x' in GF(2^128) */ +- a = be64_to_cpu(x->a); +- b = be64_to_cpu(x->b); +- +- ctx->shash.a = (__be64)((b << 1) | (a >> 63)); +- ctx->shash.b = (__be64)((a << 1) | (b >> 63)); +- +- if (a >> 63) +- ctx->shash.b ^= cpu_to_be64(0xc2); ++ clmul_ghash_setkey(&ctx->shash, key); + + return 0; + } +diff -Nur linux-3.12.18/Documentation/devicetree/bindings/net/micrel-ks8851.txt linux-rpi/Documentation/devicetree/bindings/net/micrel-ks8851.txt +--- linux-3.12.18/Documentation/devicetree/bindings/net/micrel-ks8851.txt 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/Documentation/devicetree/bindings/net/micrel-ks8851.txt 2014-04-24 16:04:28.323013063 +0200 +@@ -7,4 +7,3 @@ + + Optional properties: + - local-mac-address : Ethernet mac address to use +-- vdd-supply: supply for Ethernet mac +diff -Nur linux-3.12.18/Documentation/video4linux/bcm2835-v4l2.txt linux-rpi/Documentation/video4linux/bcm2835-v4l2.txt +--- linux-3.12.18/Documentation/video4linux/bcm2835-v4l2.txt 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/Documentation/video4linux/bcm2835-v4l2.txt 2014-04-24 15:35:00.565525573 +0200 @@ -0,0 +1,60 @@ + +BCM2835 (aka Raspberry Pi) V4L2 driver @@ -8961,9 +7823,96 @@ diff -Nur linux-3.12.13/Documentation/video4linux/bcm2835-v4l2.txt linux-raspber +List of available formats: + +$ v4l2-ctl --list-formats -diff -Nur linux-3.12.13/drivers/char/broadcom/Kconfig linux-raspberry-pi/drivers/char/broadcom/Kconfig ---- linux-3.12.13/drivers/char/broadcom/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/char/broadcom/Kconfig 2014-03-11 17:51:12.000000000 +0100 +diff -Nur linux-3.12.18/drivers/block/floppy.c linux-rpi/drivers/block/floppy.c +--- linux-3.12.18/drivers/block/floppy.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/block/floppy.c 2014-04-24 15:35:02.077542424 +0200 +@@ -3691,12 +3691,9 @@ + if (!(mode & FMODE_NDELAY)) { + if (mode & (FMODE_READ|FMODE_WRITE)) { + UDRS->last_checked = 0; +- clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); + check_disk_change(bdev); + if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) + goto out; +- if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) +- goto out; + } + res = -EROFS; + if ((mode & FMODE_WRITE) && +@@ -3749,29 +3746,17 @@ + * a disk in the drive, and whether that disk is writable. + */ + +-struct rb0_cbdata { +- int drive; +- struct completion complete; +-}; +- +-static void floppy_rb0_cb(struct bio *bio, int err) ++static void floppy_rb0_complete(struct bio *bio, int err) + { +- struct rb0_cbdata *cbdata = (struct rb0_cbdata *)bio->bi_private; +- int drive = cbdata->drive; +- +- if (err) { +- pr_info("floppy: error %d while reading block 0", err); +- set_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); +- } +- complete(&cbdata->complete); ++ complete((struct completion *)bio->bi_private); + } + +-static int __floppy_read_block_0(struct block_device *bdev, int drive) ++static int __floppy_read_block_0(struct block_device *bdev) + { + struct bio bio; + struct bio_vec bio_vec; ++ struct completion complete; + struct page *page; +- struct rb0_cbdata cbdata; + size_t size; + + page = alloc_page(GFP_NOIO); +@@ -3784,8 +3769,6 @@ + if (!size) + size = 1024; + +- cbdata.drive = drive; +- + bio_init(&bio); + bio.bi_io_vec = &bio_vec; + bio_vec.bv_page = page; +@@ -3796,14 +3779,13 @@ + bio.bi_bdev = bdev; + bio.bi_sector = 0; + bio.bi_flags = (1 << BIO_QUIET); +- bio.bi_private = &cbdata; +- bio.bi_end_io = floppy_rb0_cb; ++ init_completion(&complete); ++ bio.bi_private = &complete; ++ bio.bi_end_io = floppy_rb0_complete; + + submit_bio(READ, &bio); + process_fd_request(); +- +- init_completion(&cbdata.complete); +- wait_for_completion(&cbdata.complete); ++ wait_for_completion(&complete); + + __free_page(page); + +@@ -3845,7 +3827,7 @@ + UDRS->generation++; + if (drive_no_geom(drive)) { + /* auto-sensing */ +- res = __floppy_read_block_0(opened_bdev[drive], drive); ++ res = __floppy_read_block_0(opened_bdev[drive]); + } else { + if (cf) + poll_drive(false, FD_RAW_NEED_DISK); +diff -Nur linux-3.12.18/drivers/char/broadcom/Kconfig linux-rpi/drivers/char/broadcom/Kconfig +--- linux-3.12.18/drivers/char/broadcom/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/char/broadcom/Kconfig 2014-04-24 16:04:34.339071265 +0200 @@ -0,0 +1,16 @@ +# +# Broadcom char driver config @@ -8981,32 +7930,32 @@ diff -Nur linux-3.12.13/drivers/char/broadcom/Kconfig linux-raspberry-pi/drivers + help + Helper for videocore CMA access. + -diff -Nur linux-3.12.13/drivers/char/broadcom/Makefile linux-raspberry-pi/drivers/char/broadcom/Makefile ---- linux-3.12.13/drivers/char/broadcom/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/char/broadcom/Makefile 2014-03-11 17:51:12.000000000 +0100 +diff -Nur linux-3.12.18/drivers/char/broadcom/Makefile linux-rpi/drivers/char/broadcom/Makefile +--- linux-3.12.18/drivers/char/broadcom/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/char/broadcom/Makefile 2014-04-24 16:04:34.339071265 +0200 @@ -0,0 +1 @@ +obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ -diff -Nur linux-3.12.13/drivers/char/broadcom/vc_cma/Makefile linux-raspberry-pi/drivers/char/broadcom/vc_cma/Makefile ---- linux-3.12.13/drivers/char/broadcom/vc_cma/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/char/broadcom/vc_cma/Makefile 2014-03-11 17:51:12.000000000 +0100 +diff -Nur linux-3.12.18/drivers/char/broadcom/vc_cma/Makefile linux-rpi/drivers/char/broadcom/vc_cma/Makefile +--- linux-3.12.18/drivers/char/broadcom/vc_cma/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/char/broadcom/vc_cma/Makefile 2014-04-24 16:04:34.339071265 +0200 @@ -0,0 +1,14 @@ -+EXTRA_CFLAGS += -Wall -Wstrict-prototypes -Wno-trigraphs -+EXTRA_CFLAGS += -Werror -+EXTRA_CFLAGS += -I"include/linux/broadcom" -+EXTRA_CFLAGS += -I"drivers/misc/vc04_services" -+EXTRA_CFLAGS += -I"drivers/misc/vc04_services/interface/vchi" -+EXTRA_CFLAGS += -I"drivers/misc/vc04_services/interface/vchiq_arm" ++ccflags-y += -Wall -Wstrict-prototypes -Wno-trigraphs ++ccflags-y += -Werror ++ccflags-y += -Iinclude/linux/broadcom ++ccflags-y += -Idrivers/misc/vc04_services ++ccflags-y += -Idrivers/misc/vc04_services/interface/vchi ++ccflags-y += -Idrivers/misc/vc04_services/interface/vchiq_arm + -+EXTRA_CFLAGS += -D__KERNEL__ -+EXTRA_CFLAGS += -D__linux__ -+EXTRA_CFLAGS += -Werror ++ccflags-y += -D__KERNEL__ ++ccflags-y += -D__linux__ ++ccflags-y += -Werror + +obj-$(CONFIG_BCM_VC_CMA) += vc-cma.o + +vc-cma-objs := vc_cma.o -diff -Nur linux-3.12.13/drivers/char/broadcom/vc_cma/vc_cma.c linux-raspberry-pi/drivers/char/broadcom/vc_cma/vc_cma.c ---- linux-3.12.13/drivers/char/broadcom/vc_cma/vc_cma.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/char/broadcom/vc_cma/vc_cma.c 2014-03-11 17:51:12.000000000 +0100 +diff -Nur linux-3.12.18/drivers/char/broadcom/vc_cma/vc_cma.c linux-rpi/drivers/char/broadcom/vc_cma/vc_cma.c +--- linux-3.12.18/drivers/char/broadcom/vc_cma/vc_cma.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/char/broadcom/vc_cma/vc_cma.c 2014-04-24 16:04:34.339071265 +0200 @@ -0,0 +1,1143 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -10151,9 +9100,9 @@ diff -Nur linux-3.12.13/drivers/char/broadcom/vc_cma/vc_cma.c linux-raspberry-pi +module_exit(vc_cma_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Broadcom Corporation"); -diff -Nur linux-3.12.13/drivers/char/hw_random/bcm2708-rng.c linux-raspberry-pi/drivers/char/hw_random/bcm2708-rng.c ---- linux-3.12.13/drivers/char/hw_random/bcm2708-rng.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/char/hw_random/bcm2708-rng.c 2014-03-11 17:32:20.000000000 +0100 +diff -Nur linux-3.12.18/drivers/char/hw_random/bcm2708-rng.c linux-rpi/drivers/char/hw_random/bcm2708-rng.c +--- linux-3.12.18/drivers/char/hw_random/bcm2708-rng.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/char/hw_random/bcm2708-rng.c 2014-04-24 15:35:02.101542691 +0200 @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -10272,9 +9221,9 @@ diff -Nur linux-3.12.13/drivers/char/hw_random/bcm2708-rng.c linux-raspberry-pi/ + +MODULE_DESCRIPTION("BCM2708 H/W Random Number Generator (RNG) driver"); +MODULE_LICENSE("GPL and additional rights"); -diff -Nur linux-3.12.13/drivers/char/hw_random/Kconfig linux-raspberry-pi/drivers/char/hw_random/Kconfig ---- linux-3.12.13/drivers/char/hw_random/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/char/hw_random/Kconfig 2014-03-11 17:51:12.000000000 +0100 +diff -Nur linux-3.12.18/drivers/char/hw_random/Kconfig linux-rpi/drivers/char/hw_random/Kconfig +--- linux-3.12.18/drivers/char/hw_random/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/char/hw_random/Kconfig 2014-04-24 16:04:34.339071265 +0200 @@ -314,3 +314,14 @@ module will be called tpm-rng. @@ -10290,17 +9239,29 @@ diff -Nur linux-3.12.13/drivers/char/hw_random/Kconfig linux-raspberry-pi/driver + module will be called bcm2708-rng. + + If unsure, say N. -diff -Nur linux-3.12.13/drivers/char/hw_random/Makefile linux-raspberry-pi/drivers/char/hw_random/Makefile ---- linux-3.12.13/drivers/char/hw_random/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/char/hw_random/Makefile 2014-03-11 17:32:20.000000000 +0100 +diff -Nur linux-3.12.18/drivers/char/hw_random/Makefile linux-rpi/drivers/char/hw_random/Makefile +--- linux-3.12.18/drivers/char/hw_random/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/char/hw_random/Makefile 2014-04-24 15:35:02.101542691 +0200 @@ -27,3 +27,4 @@ obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o +obj-$(CONFIG_HW_RANDOM_BCM2708) += bcm2708-rng.o -diff -Nur linux-3.12.13/drivers/char/Kconfig linux-raspberry-pi/drivers/char/Kconfig ---- linux-3.12.13/drivers/char/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/char/Kconfig 2014-03-11 17:51:12.000000000 +0100 +diff -Nur linux-3.12.18/drivers/char/ipmi/ipmi_bt_sm.c linux-rpi/drivers/char/ipmi/ipmi_bt_sm.c +--- linux-3.12.18/drivers/char/ipmi/ipmi_bt_sm.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/char/ipmi/ipmi_bt_sm.c 2014-04-24 15:35:02.105542736 +0200 +@@ -352,7 +352,7 @@ + + static inline int read_all_bytes(struct si_sm_data *bt) + { +- unsigned int i; ++ unsigned char i; + + /* + * length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode. +diff -Nur linux-3.12.18/drivers/char/Kconfig linux-rpi/drivers/char/Kconfig +--- linux-3.12.18/drivers/char/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/char/Kconfig 2014-04-24 16:04:34.335071226 +0200 @@ -574,6 +574,8 @@ source "drivers/s390/char/Kconfig" @@ -10310,18 +9271,18 @@ diff -Nur linux-3.12.13/drivers/char/Kconfig linux-raspberry-pi/drivers/char/Kco config MSM_SMD_PKT bool "Enable device interface for some SMD packet ports" default n -diff -Nur linux-3.12.13/drivers/char/Makefile linux-raspberry-pi/drivers/char/Makefile ---- linux-3.12.13/drivers/char/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/char/Makefile 2014-03-11 17:51:12.000000000 +0100 +diff -Nur linux-3.12.18/drivers/char/Makefile linux-rpi/drivers/char/Makefile +--- linux-3.12.18/drivers/char/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/char/Makefile 2014-04-24 16:04:34.335071226 +0200 @@ -62,3 +62,5 @@ js-rtc-y = rtc.o obj-$(CONFIG_TILE_SROM) += tile-srom.o + +obj-$(CONFIG_BRCM_CHAR_DRIVERS) += broadcom/ -diff -Nur linux-3.12.13/drivers/cpufreq/bcm2835-cpufreq.c linux-raspberry-pi/drivers/cpufreq/bcm2835-cpufreq.c ---- linux-3.12.13/drivers/cpufreq/bcm2835-cpufreq.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/cpufreq/bcm2835-cpufreq.c 2014-03-11 17:51:13.000000000 +0100 +diff -Nur linux-3.12.18/drivers/cpufreq/bcm2835-cpufreq.c linux-rpi/drivers/cpufreq/bcm2835-cpufreq.c +--- linux-3.12.18/drivers/cpufreq/bcm2835-cpufreq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/cpufreq/bcm2835-cpufreq.c 2014-04-24 16:04:34.575073548 +0200 @@ -0,0 +1,239 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. @@ -10562,9 +9523,9 @@ diff -Nur linux-3.12.13/drivers/cpufreq/bcm2835-cpufreq.c linux-raspberry-pi/dri + +module_init(bcm2835_cpufreq_module_init); +module_exit(bcm2835_cpufreq_module_exit); -diff -Nur linux-3.12.13/drivers/cpufreq/Kconfig.arm linux-raspberry-pi/drivers/cpufreq/Kconfig.arm ---- linux-3.12.13/drivers/cpufreq/Kconfig.arm 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/cpufreq/Kconfig.arm 2014-03-11 17:51:13.000000000 +0100 +diff -Nur linux-3.12.18/drivers/cpufreq/Kconfig.arm linux-rpi/drivers/cpufreq/Kconfig.arm +--- linux-3.12.18/drivers/cpufreq/Kconfig.arm 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/cpufreq/Kconfig.arm 2014-04-24 16:04:34.575073548 +0200 @@ -228,6 +228,14 @@ help This adds the CPUFreq driver support for SPEAr SOCs. @@ -10580,9 +9541,9 @@ diff -Nur linux-3.12.13/drivers/cpufreq/Kconfig.arm linux-raspberry-pi/drivers/c config ARM_TEGRA_CPUFREQ bool "TEGRA CPUFreq support" depends on ARCH_TEGRA -diff -Nur linux-3.12.13/drivers/cpufreq/Makefile linux-raspberry-pi/drivers/cpufreq/Makefile ---- linux-3.12.13/drivers/cpufreq/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/cpufreq/Makefile 2014-03-11 17:51:13.000000000 +0100 +diff -Nur linux-3.12.18/drivers/cpufreq/Makefile linux-rpi/drivers/cpufreq/Makefile +--- linux-3.12.18/drivers/cpufreq/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/cpufreq/Makefile 2014-04-24 16:04:34.575073548 +0200 @@ -76,6 +76,7 @@ obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o @@ -10591,9 +9552,229 @@ diff -Nur linux-3.12.13/drivers/cpufreq/Makefile linux-raspberry-pi/drivers/cpuf obj-$(CONFIG_ARM_TEGRA_CPUFREQ) += tegra-cpufreq.o ################################################################################## -diff -Nur linux-3.12.13/drivers/dma/bcm2708-dmaengine.c linux-raspberry-pi/drivers/dma/bcm2708-dmaengine.c ---- linux-3.12.13/drivers/dma/bcm2708-dmaengine.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/dma/bcm2708-dmaengine.c 2014-03-11 17:51:13.000000000 +0100 +diff -Nur linux-3.12.18/drivers/cpufreq/powernow-k6.c linux-rpi/drivers/cpufreq/powernow-k6.c +--- linux-3.12.18/drivers/cpufreq/powernow-k6.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/cpufreq/powernow-k6.c 2014-04-24 16:04:34.587073663 +0200 +@@ -26,108 +26,41 @@ + static unsigned int busfreq; /* FSB, in 10 kHz */ + static unsigned int max_multiplier; + +-static unsigned int param_busfreq = 0; +-static unsigned int param_max_multiplier = 0; +- +-module_param_named(max_multiplier, param_max_multiplier, uint, S_IRUGO); +-MODULE_PARM_DESC(max_multiplier, "Maximum multiplier (allowed values: 20 30 35 40 45 50 55 60)"); +- +-module_param_named(bus_frequency, param_busfreq, uint, S_IRUGO); +-MODULE_PARM_DESC(bus_frequency, "Bus frequency in kHz"); + + /* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */ + static struct cpufreq_frequency_table clock_ratio[] = { +- {60, /* 110 -> 6.0x */ 0}, +- {55, /* 011 -> 5.5x */ 0}, +- {50, /* 001 -> 5.0x */ 0}, + {45, /* 000 -> 4.5x */ 0}, ++ {50, /* 001 -> 5.0x */ 0}, + {40, /* 010 -> 4.0x */ 0}, +- {35, /* 111 -> 3.5x */ 0}, +- {30, /* 101 -> 3.0x */ 0}, ++ {55, /* 011 -> 5.5x */ 0}, + {20, /* 100 -> 2.0x */ 0}, ++ {30, /* 101 -> 3.0x */ 0}, ++ {60, /* 110 -> 6.0x */ 0}, ++ {35, /* 111 -> 3.5x */ 0}, + {0, CPUFREQ_TABLE_END} + }; + +-static const u8 index_to_register[8] = { 6, 3, 1, 0, 2, 7, 5, 4 }; +-static const u8 register_to_index[8] = { 3, 2, 4, 1, 7, 6, 0, 5 }; +- +-static const struct { +- unsigned freq; +- unsigned mult; +-} usual_frequency_table[] = { +- { 400000, 40 }, // 100 * 4 +- { 450000, 45 }, // 100 * 4.5 +- { 475000, 50 }, // 95 * 5 +- { 500000, 50 }, // 100 * 5 +- { 506250, 45 }, // 112.5 * 4.5 +- { 533500, 55 }, // 97 * 5.5 +- { 550000, 55 }, // 100 * 5.5 +- { 562500, 50 }, // 112.5 * 5 +- { 570000, 60 }, // 95 * 6 +- { 600000, 60 }, // 100 * 6 +- { 618750, 55 }, // 112.5 * 5.5 +- { 660000, 55 }, // 120 * 5.5 +- { 675000, 60 }, // 112.5 * 6 +- { 720000, 60 }, // 120 * 6 +-}; +- +-#define FREQ_RANGE 3000 + + /** + * powernow_k6_get_cpu_multiplier - returns the current FSB multiplier + * +- * Returns the current setting of the frequency multiplier. Core clock ++ * Returns the current setting of the frequency multiplier. Core clock + * speed is frequency of the Front-Side Bus multiplied with this value. + */ + static int powernow_k6_get_cpu_multiplier(void) + { +- unsigned long invalue = 0; ++ u64 invalue = 0; + u32 msrval; + +- local_irq_disable(); +- + msrval = POWERNOW_IOPORT + 0x1; + wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ + invalue = inl(POWERNOW_IOPORT + 0x8); + msrval = POWERNOW_IOPORT + 0x0; + wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ + +- local_irq_enable(); +- +- return clock_ratio[register_to_index[(invalue >> 5)&7]].driver_data; ++ return clock_ratio[(invalue >> 5)&7].driver_data; + } + +-static void powernow_k6_set_cpu_multiplier(unsigned int best_i) +-{ +- unsigned long outvalue, invalue; +- unsigned long msrval; +- unsigned long cr0; +- +- /* we now need to transform best_i to the BVC format, see AMD#23446 */ +- +- /* +- * The processor doesn't respond to inquiry cycles while changing the +- * frequency, so we must disable cache. +- */ +- local_irq_disable(); +- cr0 = read_cr0(); +- write_cr0(cr0 | X86_CR0_CD); +- wbinvd(); +- +- outvalue = (1<<12) | (1<<10) | (1<<9) | (index_to_register[best_i]<<5); +- +- msrval = POWERNOW_IOPORT + 0x1; +- wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ +- invalue = inl(POWERNOW_IOPORT + 0x8); +- invalue = invalue & 0x1f; +- outvalue = outvalue | invalue; +- outl(outvalue, (POWERNOW_IOPORT + 0x8)); +- msrval = POWERNOW_IOPORT + 0x0; +- wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ +- +- write_cr0(cr0); +- local_irq_enable(); +-} + + /** + * powernow_k6_set_state - set the PowerNow! multiplier +@@ -138,6 +71,8 @@ + static void powernow_k6_set_state(struct cpufreq_policy *policy, + unsigned int best_i) + { ++ unsigned long outvalue = 0, invalue = 0; ++ unsigned long msrval; + struct cpufreq_freqs freqs; + + if (clock_ratio[best_i].driver_data > max_multiplier) { +@@ -150,7 +85,18 @@ + + cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); + +- powernow_k6_set_cpu_multiplier(best_i); ++ /* we now need to transform best_i to the BVC format, see AMD#23446 */ ++ ++ outvalue = (1<<12) | (1<<10) | (1<<9) | (best_i<<5); ++ ++ msrval = POWERNOW_IOPORT + 0x1; ++ wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ ++ invalue = inl(POWERNOW_IOPORT + 0x8); ++ invalue = invalue & 0xf; ++ outvalue = outvalue | invalue; ++ outl(outvalue , (POWERNOW_IOPORT + 0x8)); ++ msrval = POWERNOW_IOPORT + 0x0; ++ wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ + + cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); + +@@ -195,57 +141,18 @@ + return 0; + } + ++ + static int powernow_k6_cpu_init(struct cpufreq_policy *policy) + { + unsigned int i, f; + int result; +- unsigned khz; + + if (policy->cpu != 0) + return -ENODEV; + +- max_multiplier = 0; +- khz = cpu_khz; +- for (i = 0; i < ARRAY_SIZE(usual_frequency_table); i++) { +- if (khz >= usual_frequency_table[i].freq - FREQ_RANGE && +- khz <= usual_frequency_table[i].freq + FREQ_RANGE) { +- khz = usual_frequency_table[i].freq; +- max_multiplier = usual_frequency_table[i].mult; +- break; +- } +- } +- if (param_max_multiplier) { +- for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { +- if (clock_ratio[i].driver_data == param_max_multiplier) { +- max_multiplier = param_max_multiplier; +- goto have_max_multiplier; +- } +- } +- printk(KERN_ERR "powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n"); +- return -EINVAL; +- } +- +- if (!max_multiplier) { +- printk(KERN_WARNING "powernow-k6: unknown frequency %u, cannot determine current multiplier\n", khz); +- printk(KERN_WARNING "powernow-k6: use module parameters max_multiplier and bus_frequency\n"); +- return -EOPNOTSUPP; +- } +- +-have_max_multiplier: +- param_max_multiplier = max_multiplier; +- +- if (param_busfreq) { +- if (param_busfreq >= 50000 && param_busfreq <= 150000) { +- busfreq = param_busfreq / 10; +- goto have_busfreq; +- } +- printk(KERN_ERR "powernow-k6: invalid bus_frequency parameter, allowed range 50000 - 150000 kHz\n"); +- return -EINVAL; +- } +- +- busfreq = khz / max_multiplier; +-have_busfreq: +- param_busfreq = busfreq * 10; ++ /* get frequencies */ ++ max_multiplier = powernow_k6_get_cpu_multiplier(); ++ busfreq = cpu_khz / max_multiplier; + + /* table init */ + for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { +@@ -257,7 +164,7 @@ + } + + /* cpuinfo and default policy values */ +- policy->cpuinfo.transition_latency = 500000; ++ policy->cpuinfo.transition_latency = 200000; + policy->cur = busfreq * max_multiplier; + + result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio); +diff -Nur linux-3.12.18/drivers/dma/bcm2708-dmaengine.c linux-rpi/drivers/dma/bcm2708-dmaengine.c +--- linux-3.12.18/drivers/dma/bcm2708-dmaengine.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/dma/bcm2708-dmaengine.c 2014-04-24 16:04:34.615073934 +0200 @@ -0,0 +1,588 @@ +/* + * BCM2708 DMA engine support @@ -11183,12 +10364,12 @@ diff -Nur linux-3.12.13/drivers/dma/bcm2708-dmaengine.c linux-raspberry-pi/drive +MODULE_DESCRIPTION("BCM2708 DMA engine driver"); +MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>"); +MODULE_LICENSE("GPL v2"); -diff -Nur linux-3.12.13/drivers/dma/Kconfig linux-raspberry-pi/drivers/dma/Kconfig ---- linux-3.12.13/drivers/dma/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/dma/Kconfig 2014-03-11 17:51:13.000000000 +0100 -@@ -296,6 +296,12 @@ - The Communications Port Programming Interface (CPPI) 4.1 DMA engine - is currently used by the USB driver on AM335x platforms. +diff -Nur linux-3.12.18/drivers/dma/Kconfig linux-rpi/drivers/dma/Kconfig +--- linux-3.12.18/drivers/dma/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/dma/Kconfig 2014-04-24 16:04:34.615073934 +0200 +@@ -288,6 +288,12 @@ + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS +config DMA_BCM2708 + tristate "BCM2708 DMA engine support" @@ -11196,12 +10377,12 @@ diff -Nur linux-3.12.13/drivers/dma/Kconfig linux-raspberry-pi/drivers/dma/Kconf + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + - config MMP_PDMA - bool "MMP PDMA support" - depends on (ARCH_MMP || ARCH_PXA) -diff -Nur linux-3.12.13/drivers/dma/Makefile linux-raspberry-pi/drivers/dma/Makefile ---- linux-3.12.13/drivers/dma/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/dma/Makefile 2014-03-11 17:51:13.000000000 +0100 + config TI_CPPI41 + tristate "AM33xx CPPI41 DMA support" + depends on ARCH_OMAP +diff -Nur linux-3.12.18/drivers/dma/Makefile linux-rpi/drivers/dma/Makefile +--- linux-3.12.18/drivers/dma/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/dma/Makefile 2014-04-24 16:04:34.615073934 +0200 @@ -37,6 +37,7 @@ obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o @@ -11210,9 +10391,309 @@ diff -Nur linux-3.12.13/drivers/dma/Makefile linux-raspberry-pi/drivers/dma/Make obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o obj-$(CONFIG_TI_CPPI41) += cppi41.o -diff -Nur linux-3.12.13/drivers/hwmon/bcm2835-hwmon.c linux-raspberry-pi/drivers/hwmon/bcm2835-hwmon.c ---- linux-3.12.13/drivers/hwmon/bcm2835-hwmon.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/hwmon/bcm2835-hwmon.c 2014-03-11 17:32:22.000000000 +0100 +diff -Nur linux-3.12.18/drivers/gpu/drm/cirrus/cirrus_fbdev.c linux-rpi/drivers/gpu/drm/cirrus/cirrus_fbdev.c +--- linux-3.12.18/drivers/gpu/drm/cirrus/cirrus_fbdev.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/gpu/drm/cirrus/cirrus_fbdev.c 2014-04-24 16:04:34.791075636 +0200 +@@ -233,9 +233,6 @@ + info->apertures->ranges[0].base = cdev->dev->mode_config.fb_base; + info->apertures->ranges[0].size = cdev->mc.vram_size; + +- info->fix.smem_start = cdev->dev->mode_config.fb_base; +- info->fix.smem_len = cdev->mc.vram_size; +- + info->screen_base = sysram; + info->screen_size = size; + +diff -Nur linux-3.12.18/drivers/gpu/drm/cirrus/cirrus_mode.c linux-rpi/drivers/gpu/drm/cirrus/cirrus_mode.c +--- linux-3.12.18/drivers/gpu/drm/cirrus/cirrus_mode.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/gpu/drm/cirrus/cirrus_mode.c 2014-04-24 15:35:02.193543716 +0200 +@@ -494,12 +494,13 @@ + + int cirrus_vga_get_modes(struct drm_connector *connector) + { +- int count; +- + /* Just add a static list of modes */ +- count = drm_add_modes_noedid(connector, 1280, 1024); +- drm_set_preferred_mode(connector, 1024, 768); +- return count; ++ drm_add_modes_noedid(connector, 640, 480); ++ drm_add_modes_noedid(connector, 800, 600); ++ drm_add_modes_noedid(connector, 1024, 768); ++ drm_add_modes_noedid(connector, 1280, 1024); ++ ++ return 4; + } + + static int cirrus_vga_mode_valid(struct drm_connector *connector, +diff -Nur linux-3.12.18/drivers/gpu/drm/drm_edid.c linux-rpi/drivers/gpu/drm/drm_edid.c +--- linux-3.12.18/drivers/gpu/drm/drm_edid.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/gpu/drm/drm_edid.c 2014-04-24 16:04:34.795075675 +0200 +@@ -3296,19 +3296,6 @@ + } + EXPORT_SYMBOL(drm_add_modes_noedid); + +-void drm_set_preferred_mode(struct drm_connector *connector, +- int hpref, int vpref) +-{ +- struct drm_display_mode *mode; +- +- list_for_each_entry(mode, &connector->probed_modes, head) { +- if (drm_mode_width(mode) == hpref && +- drm_mode_height(mode) == vpref) +- mode->type |= DRM_MODE_TYPE_PREFERRED; +- } +-} +-EXPORT_SYMBOL(drm_set_preferred_mode); +- + /** + * drm_hdmi_avi_infoframe_from_display_mode() - fill an HDMI AVI infoframe with + * data from a DRM display mode +diff -Nur linux-3.12.18/drivers/gpu/drm/drm_fb_helper.c linux-rpi/drivers/gpu/drm/drm_fb_helper.c +--- linux-3.12.18/drivers/gpu/drm/drm_fb_helper.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/gpu/drm/drm_fb_helper.c 2014-04-24 16:04:34.795075675 +0200 +@@ -1163,7 +1163,6 @@ + { + struct drm_cmdline_mode *cmdline_mode; + struct drm_display_mode *mode = NULL; +- bool prefer_non_interlace; + + cmdline_mode = &fb_helper_conn->cmdline_mode; + if (cmdline_mode->specified == false) +@@ -1175,8 +1174,6 @@ + if (cmdline_mode->rb || cmdline_mode->margins) + goto create_mode; + +- prefer_non_interlace = !cmdline_mode->interlace; +- again: + list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) { + /* check width/height */ + if (mode->hdisplay != cmdline_mode->xres || +@@ -1191,18 +1188,10 @@ + if (cmdline_mode->interlace) { + if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) + continue; +- } else if (prefer_non_interlace) { +- if (mode->flags & DRM_MODE_FLAG_INTERLACE) +- continue; + } + return mode; + } + +- if (prefer_non_interlace) { +- prefer_non_interlace = false; +- goto again; +- } +- + create_mode: + mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev, + cmdline_mode); +diff -Nur linux-3.12.18/drivers/gpu/drm/i915/intel_display.c linux-rpi/drivers/gpu/drm/i915/intel_display.c +--- linux-3.12.18/drivers/gpu/drm/i915/intel_display.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/gpu/drm/i915/intel_display.c 2014-04-24 16:04:34.827075985 +0200 +@@ -10073,7 +10073,8 @@ + /* ThinkPad T60 needs pipe A force quirk (bug #16494) */ + { 0x2782, 0x17aa, 0x201a, quirk_pipea_force }, + +- /* 830 needs to leave pipe A & dpll A up */ ++ /* 830/845 need to leave pipe A & dpll A up */ ++ { 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, + { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, + + /* Lenovo U160 cannot use SSC on LVDS */ +diff -Nur linux-3.12.18/drivers/gpu/drm/radeon/dce6_afmt.c linux-rpi/drivers/gpu/drm/radeon/dce6_afmt.c +--- linux-3.12.18/drivers/gpu/drm/radeon/dce6_afmt.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/gpu/drm/radeon/dce6_afmt.c 2014-04-24 16:04:34.959077261 +0200 +@@ -226,15 +226,13 @@ + return !ASIC_IS_NODCE(rdev); + } + +-void dce6_audio_enable(struct radeon_device *rdev, +- struct r600_audio_pin *pin, +- bool enable) ++static void dce6_audio_enable(struct radeon_device *rdev, ++ struct r600_audio_pin *pin, ++ bool enable) + { +- if (!pin) +- return; +- + WREG32_ENDPOINT(pin->offset, AZ_F0_CODEC_PIN_CONTROL_HOTPLUG_CONTROL, + enable ? AUDIO_ENABLED : 0); ++ DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id); + } + + static const u32 pin_offsets[7] = +@@ -271,8 +269,7 @@ + rdev->audio.pin[i].connected = false; + rdev->audio.pin[i].offset = pin_offsets[i]; + rdev->audio.pin[i].id = i; +- /* disable audio. it will be set up later */ +- dce6_audio_enable(rdev, &rdev->audio.pin[i], false); ++ dce6_audio_enable(rdev, &rdev->audio.pin[i], true); + } + + return 0; +diff -Nur linux-3.12.18/drivers/gpu/drm/radeon/evergreen_hdmi.c linux-rpi/drivers/gpu/drm/radeon/evergreen_hdmi.c +--- linux-3.12.18/drivers/gpu/drm/radeon/evergreen_hdmi.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/gpu/drm/radeon/evergreen_hdmi.c 2014-04-24 16:04:34.959077261 +0200 +@@ -257,15 +257,6 @@ + return; + offset = dig->afmt->offset; + +- /* disable audio prior to setting up hw */ +- if (ASIC_IS_DCE6(rdev)) { +- dig->afmt->pin = dce6_audio_get_pin(rdev); +- dce6_audio_enable(rdev, dig->afmt->pin, false); +- } else { +- dig->afmt->pin = r600_audio_get_pin(rdev); +- r600_audio_enable(rdev, dig->afmt->pin, false); +- } +- + evergreen_audio_set_dto(encoder, mode->clock); + + WREG32(HDMI_VBI_PACKET_CONTROL + offset, +@@ -367,16 +358,12 @@ + WREG32(AFMT_RAMP_CONTROL1 + offset, 0x007FFFFF); + WREG32(AFMT_RAMP_CONTROL2 + offset, 0x00000001); + WREG32(AFMT_RAMP_CONTROL3 + offset, 0x00000001); +- +- /* enable audio after to setting up hw */ +- if (ASIC_IS_DCE6(rdev)) +- dce6_audio_enable(rdev, dig->afmt->pin, true); +- else +- r600_audio_enable(rdev, dig->afmt->pin, true); + } + + void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) + { ++ struct drm_device *dev = encoder->dev; ++ struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + +@@ -389,6 +376,15 @@ + if (!enable && !dig->afmt->enabled) + return; + ++ if (enable) { ++ if (ASIC_IS_DCE6(rdev)) ++ dig->afmt->pin = dce6_audio_get_pin(rdev); ++ else ++ dig->afmt->pin = r600_audio_get_pin(rdev); ++ } else { ++ dig->afmt->pin = NULL; ++ } ++ + dig->afmt->enabled = enable; + + DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n", +diff -Nur linux-3.12.18/drivers/gpu/drm/radeon/r600_audio.c linux-rpi/drivers/gpu/drm/radeon/r600_audio.c +--- linux-3.12.18/drivers/gpu/drm/radeon/r600_audio.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/gpu/drm/radeon/r600_audio.c 2014-04-24 16:04:34.967077338 +0200 +@@ -142,15 +142,12 @@ + } + + /* enable the audio stream */ +-void r600_audio_enable(struct radeon_device *rdev, +- struct r600_audio_pin *pin, +- bool enable) ++static void r600_audio_enable(struct radeon_device *rdev, ++ struct r600_audio_pin *pin, ++ bool enable) + { + u32 value = 0; + +- if (!pin) +- return; +- + if (ASIC_IS_DCE4(rdev)) { + if (enable) { + value |= 0x81000000; /* Required to enable audio */ +@@ -161,6 +158,7 @@ + WREG32_P(R600_AUDIO_ENABLE, + enable ? 0x81000000 : 0x0, ~0x81000000); + } ++ DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id); + } + + /* +@@ -180,8 +178,8 @@ + rdev->audio.pin[0].status_bits = 0; + rdev->audio.pin[0].category_code = 0; + rdev->audio.pin[0].id = 0; +- /* disable audio. it will be set up later */ +- r600_audio_enable(rdev, &rdev->audio.pin[0], false); ++ ++ r600_audio_enable(rdev, &rdev->audio.pin[0], true); + + return 0; + } +diff -Nur linux-3.12.18/drivers/gpu/drm/radeon/r600_hdmi.c linux-rpi/drivers/gpu/drm/radeon/r600_hdmi.c +--- linux-3.12.18/drivers/gpu/drm/radeon/r600_hdmi.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/gpu/drm/radeon/r600_hdmi.c 2014-04-24 16:04:34.967077338 +0200 +@@ -329,6 +329,9 @@ + u8 *sadb; + int sad_count; + ++ /* XXX: setting this register causes hangs on some asics */ ++ return; ++ + list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { + if (connector->encoder == encoder) + radeon_connector = to_radeon_connector(connector); +@@ -443,10 +446,6 @@ + return; + offset = dig->afmt->offset; + +- /* disable audio prior to setting up hw */ +- dig->afmt->pin = r600_audio_get_pin(rdev); +- r600_audio_enable(rdev, dig->afmt->pin, false); +- + r600_audio_set_dto(encoder, mode->clock); + + WREG32(HDMI0_VBI_PACKET_CONTROL + offset, +@@ -518,9 +517,6 @@ + WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001); + + r600_hdmi_audio_workaround(encoder); +- +- /* enable audio after to setting up hw */ +- r600_audio_enable(rdev, dig->afmt->pin, true); + } + + /* +@@ -641,6 +637,11 @@ + if (!enable && !dig->afmt->enabled) + return; + ++ if (enable) ++ dig->afmt->pin = r600_audio_get_pin(rdev); ++ else ++ dig->afmt->pin = NULL; ++ + /* Older chipsets require setting HDMI and routing manually */ + if (!ASIC_IS_DCE3(rdev)) { + if (enable) +diff -Nur linux-3.12.18/drivers/gpu/drm/radeon/radeon.h linux-rpi/drivers/gpu/drm/radeon/radeon.h +--- linux-3.12.18/drivers/gpu/drm/radeon/radeon.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/gpu/drm/radeon/radeon.h 2014-04-24 16:04:34.971077377 +0200 +@@ -2717,12 +2717,6 @@ + void r600_audio_update_hdmi(struct work_struct *work); + struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev); + struct r600_audio_pin *dce6_audio_get_pin(struct radeon_device *rdev); +-void r600_audio_enable(struct radeon_device *rdev, +- struct r600_audio_pin *pin, +- bool enable); +-void dce6_audio_enable(struct radeon_device *rdev, +- struct r600_audio_pin *pin, +- bool enable); + + /* + * R600 vram scratch functions +diff -Nur linux-3.12.18/drivers/hwmon/bcm2835-hwmon.c linux-rpi/drivers/hwmon/bcm2835-hwmon.c +--- linux-3.12.18/drivers/hwmon/bcm2835-hwmon.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/hwmon/bcm2835-hwmon.c 2014-04-24 15:35:02.349545454 +0200 @@ -0,0 +1,219 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. @@ -11433,9 +10914,9 @@ diff -Nur linux-3.12.13/drivers/hwmon/bcm2835-hwmon.c linux-raspberry-pi/drivers +MODULE_DESCRIPTION("HW Monitor driver for bcm2835 chip"); + +module_platform_driver(bcm2835_hwmon_driver); -diff -Nur linux-3.12.13/drivers/hwmon/Kconfig linux-raspberry-pi/drivers/hwmon/Kconfig ---- linux-3.12.13/drivers/hwmon/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/hwmon/Kconfig 2014-03-11 17:51:14.000000000 +0100 +diff -Nur linux-3.12.18/drivers/hwmon/Kconfig linux-rpi/drivers/hwmon/Kconfig +--- linux-3.12.18/drivers/hwmon/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/hwmon/Kconfig 2014-04-24 16:04:35.299080549 +0200 @@ -1553,6 +1553,16 @@ help Support for the A/D converter on MC13783 and MC13892 PMIC. @@ -11453,9 +10934,9 @@ diff -Nur linux-3.12.13/drivers/hwmon/Kconfig linux-raspberry-pi/drivers/hwmon/K if ACPI comment "ACPI drivers" -diff -Nur linux-3.12.13/drivers/hwmon/Makefile linux-raspberry-pi/drivers/hwmon/Makefile ---- linux-3.12.13/drivers/hwmon/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/hwmon/Makefile 2014-03-11 17:51:14.000000000 +0100 +diff -Nur linux-3.12.18/drivers/hwmon/Makefile linux-rpi/drivers/hwmon/Makefile +--- linux-3.12.18/drivers/hwmon/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/hwmon/Makefile 2014-04-24 16:04:35.299080549 +0200 @@ -142,6 +142,7 @@ obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o @@ -11464,9 +10945,9 @@ diff -Nur linux-3.12.13/drivers/hwmon/Makefile linux-raspberry-pi/drivers/hwmon/ obj-$(CONFIG_PMBUS) += pmbus/ -diff -Nur linux-3.12.13/drivers/i2c/busses/i2c-bcm2708.c linux-raspberry-pi/drivers/i2c/busses/i2c-bcm2708.c ---- linux-3.12.13/drivers/i2c/busses/i2c-bcm2708.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/i2c/busses/i2c-bcm2708.c 2014-03-11 17:51:14.000000000 +0100 +diff -Nur linux-3.12.18/drivers/i2c/busses/i2c-bcm2708.c linux-rpi/drivers/i2c/busses/i2c-bcm2708.c +--- linux-3.12.18/drivers/i2c/busses/i2c-bcm2708.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/i2c/busses/i2c-bcm2708.c 2014-04-24 16:04:35.311080666 +0200 @@ -0,0 +1,408 @@ +/* + * Driver for Broadcom BCM2708 BSC Controllers @@ -11876,10 +11357,10 @@ diff -Nur linux-3.12.13/drivers/i2c/busses/i2c-bcm2708.c linux-raspberry-pi/driv +MODULE_AUTHOR("Chris Boot <bootc@bootc.net>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -diff -Nur linux-3.12.13/drivers/i2c/busses/Kconfig linux-raspberry-pi/drivers/i2c/busses/Kconfig ---- linux-3.12.13/drivers/i2c/busses/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/i2c/busses/Kconfig 2014-03-11 17:51:14.000000000 +0100 -@@ -346,6 +346,25 @@ +diff -Nur linux-3.12.18/drivers/i2c/busses/Kconfig linux-rpi/drivers/i2c/busses/Kconfig +--- linux-3.12.18/drivers/i2c/busses/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/i2c/busses/Kconfig 2014-04-24 16:04:35.311080666 +0200 +@@ -347,6 +347,25 @@ This support is also available as a module. If so, the module will be called i2c-bcm2835. @@ -11892,22 +11373,22 @@ diff -Nur linux-3.12.13/drivers/i2c/busses/Kconfig linux-raspberry-pi/drivers/i2 + with I2C/TWI/SMBus. + +config I2C_BCM2708_BAUDRATE -+ prompt "BCM2708 I2C baudrate" ++ prompt "BCM2708 I2C baudrate" + depends on I2C_BCM2708 -+ int -+ default 100000 -+ help -+ Set the I2C baudrate. This will alter the default value. A -+ different baudrate can be set by using a module parameter as well. If -+ no parameter is provided when loading, this is the value that will be -+ used. ++ int ++ default 100000 ++ help ++ Set the I2C baudrate. This will alter the default value. A ++ different baudrate can be set by using a module parameter as well. If ++ no parameter is provided when loading, this is the value that will be ++ used. + config I2C_BLACKFIN_TWI tristate "Blackfin TWI I2C support" depends on BLACKFIN -diff -Nur linux-3.12.13/drivers/i2c/busses/Makefile linux-raspberry-pi/drivers/i2c/busses/Makefile ---- linux-3.12.13/drivers/i2c/busses/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/i2c/busses/Makefile 2014-03-11 17:51:14.000000000 +0100 +diff -Nur linux-3.12.18/drivers/i2c/busses/Makefile linux-rpi/drivers/i2c/busses/Makefile +--- linux-3.12.18/drivers/i2c/busses/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/i2c/busses/Makefile 2014-04-24 16:04:35.311080666 +0200 @@ -32,6 +32,7 @@ obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o @@ -11916,21 +11397,79 @@ diff -Nur linux-3.12.13/drivers/i2c/busses/Makefile linux-raspberry-pi/drivers/i obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o -diff -Nur linux-3.12.13/drivers/media/dvb-core/dvb-usb-ids.h linux-raspberry-pi/drivers/media/dvb-core/dvb-usb-ids.h ---- linux-3.12.13/drivers/media/dvb-core/dvb-usb-ids.h 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/dvb-core/dvb-usb-ids.h 2014-03-11 17:51:15.000000000 +0100 -@@ -366,6 +366,7 @@ - #define USB_PID_TERRATEC_DVBS2CI_V2 0x10ac - #define USB_PID_TECHNISAT_USB2_HDCI_V1 0x0001 - #define USB_PID_TECHNISAT_USB2_HDCI_V2 0x0002 -+#define USB_PID_TECHNISAT_USB2_CABLESTAR_HDCI 0x0003 - #define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2 0x0004 - #define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500 - #define USB_PID_CPYTO_REDI_PC50A 0xa803 -diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-raspberry-pi/drivers/media/platform/bcm2835/bcm2835-camera.c ---- linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/bcm2835/bcm2835-camera.c 2014-03-11 17:51:15.000000000 +0100 -@@ -0,0 +1,1622 @@ +diff -Nur linux-3.12.18/drivers/isdn/isdnloop/isdnloop.c linux-rpi/drivers/isdn/isdnloop/isdnloop.c +--- linux-3.12.18/drivers/isdn/isdnloop/isdnloop.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/isdn/isdnloop/isdnloop.c 2014-04-24 16:04:36.039087706 +0200 +@@ -518,9 +518,9 @@ + static void + isdnloop_fake_err(isdnloop_card *card) + { +- char buf[64]; ++ char buf[60]; + +- snprintf(buf, sizeof(buf), "E%s", card->omsg); ++ sprintf(buf, "E%s", card->omsg); + isdnloop_fake(card, buf, -1); + isdnloop_fake(card, "NAK", -1); + } +@@ -903,8 +903,6 @@ + case 7: + /* 0x;EAZ */ + p += 3; +- if (strlen(p) >= sizeof(card->eazlist[0])) +- break; + strcpy(card->eazlist[ch - 1], p); + break; + case 8: +@@ -1072,12 +1070,6 @@ + return -EBUSY; + if (copy_from_user((char *) &sdef, (char *) sdefp, sizeof(sdef))) + return -EFAULT; +- +- for (i = 0; i < 3; i++) { +- if (!memchr(sdef.num[i], 0, sizeof(sdef.num[i]))) +- return -EINVAL; +- } +- + spin_lock_irqsave(&card->isdnloop_lock, flags); + switch (sdef.ptype) { + case ISDN_PTYPE_EURO: +@@ -1135,7 +1127,7 @@ + { + ulong a; + int i; +- char cbuf[80]; ++ char cbuf[60]; + isdn_ctrl cmd; + isdnloop_cdef cdef; + +@@ -1200,6 +1192,7 @@ + break; + if ((c->arg & 255) < ISDNLOOP_BCH) { + char *p; ++ char dial[50]; + char dcode[4]; + + a = c->arg; +@@ -1211,10 +1204,10 @@ + } else + /* Normal Dial */ + strcpy(dcode, "CAL"); +- snprintf(cbuf, sizeof(cbuf), +- "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), +- dcode, p, c->parm.setup.si1, +- c->parm.setup.si2, c->parm.setup.eazmsn); ++ strcpy(dial, p); ++ sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), ++ dcode, dial, c->parm.setup.si1, ++ c->parm.setup.si2, c->parm.setup.eazmsn); + i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); + } + break; +diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/bcm2835-camera.c linux-rpi/drivers/media/platform/bcm2835/bcm2835-camera.c +--- linux-3.12.18/drivers/media/platform/bcm2835/bcm2835-camera.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/media/platform/bcm2835/bcm2835-camera.c 2014-04-24 16:04:36.447091651 +0200 +@@ -0,0 +1,1719 @@ +/* + * Broadcom BM2835 V4L2 driver + * @@ -11969,7 +11508,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + +#define BM2835_MMAL_VERSION "0.0.2" +#define BM2835_MMAL_MODULE_NAME "bcm2835-v4l2" -+ ++#define MIN_WIDTH 16 ++#define MIN_HEIGHT 16 +#define MAX_WIDTH 2592 +#define MAX_HEIGHT 1944 +#define MIN_BUFFER_SIZE (80*1024) @@ -11989,7 +11529,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra +static struct bm2835_mmal_dev *gdev; /* global device data */ + +#define FPS_MIN 1 -+#define FPS_MAX 30 ++#define FPS_MAX 90 + +/* timeperframe: min/max and default */ +static const struct v4l2_fract @@ -12002,6 +11542,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + { + .name = "4:2:0, packed YUV", + .fourcc = V4L2_PIX_FMT_YUV420, ++ .flags = 0, + .mmal = MMAL_ENCODING_I420, + .depth = 12, + .mmal_component = MMAL_COMPONENT_CAMERA, @@ -12009,13 +11550,15 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + { + .name = "4:2:2, packed, YUYV", + .fourcc = V4L2_PIX_FMT_YUYV, ++ .flags = 0, + .mmal = MMAL_ENCODING_YUYV, + .depth = 16, + .mmal_component = MMAL_COMPONENT_CAMERA, + }, + { -+ .name = "RGB24 (BE)", -+ .fourcc = V4L2_PIX_FMT_BGR24, ++ .name = "RGB24 (LE)", ++ .fourcc = V4L2_PIX_FMT_RGB24, ++ .flags = 0, + .mmal = MMAL_ENCODING_BGR24, + .depth = 24, + .mmal_component = MMAL_COMPONENT_CAMERA, @@ -12023,6 +11566,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + { + .name = "JPEG", + .fourcc = V4L2_PIX_FMT_JPEG, ++ .flags = V4L2_FMT_FLAG_COMPRESSED, + .mmal = MMAL_ENCODING_JPEG, + .depth = 8, + .mmal_component = MMAL_COMPONENT_IMAGE_ENCODE, @@ -12030,10 +11574,75 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + { + .name = "H264", + .fourcc = V4L2_PIX_FMT_H264, ++ .flags = V4L2_FMT_FLAG_COMPRESSED, + .mmal = MMAL_ENCODING_H264, + .depth = 8, + .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE, -+ } ++ }, ++ { ++ .name = "MJPEG", ++ .fourcc = V4L2_PIX_FMT_MJPEG, ++ .flags = V4L2_FMT_FLAG_COMPRESSED, ++ .mmal = MMAL_ENCODING_MJPEG, ++ .depth = 8, ++ .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE, ++ }, ++ { ++ .name = "4:2:2, packed, YVYU", ++ .fourcc = V4L2_PIX_FMT_YVYU, ++ .flags = 0, ++ .mmal = MMAL_ENCODING_YVYU, ++ .depth = 16, ++ .mmal_component = MMAL_COMPONENT_CAMERA, ++ }, ++ { ++ .name = "4:2:2, packed, VYUY", ++ .fourcc = V4L2_PIX_FMT_VYUY, ++ .flags = 0, ++ .mmal = MMAL_ENCODING_VYUY, ++ .depth = 16, ++ .mmal_component = MMAL_COMPONENT_CAMERA, ++ }, ++ { ++ .name = "4:2:2, packed, UYVY", ++ .fourcc = V4L2_PIX_FMT_UYVY, ++ .flags = 0, ++ .mmal = MMAL_ENCODING_UYVY, ++ .depth = 16, ++ .mmal_component = MMAL_COMPONENT_CAMERA, ++ }, ++ { ++ .name = "4:2:0, packed, NV12", ++ .fourcc = V4L2_PIX_FMT_NV12, ++ .flags = 0, ++ .mmal = MMAL_ENCODING_NV12, ++ .depth = 12, ++ .mmal_component = MMAL_COMPONENT_CAMERA, ++ }, ++ { ++ .name = "RGB24 (BE)", ++ .fourcc = V4L2_PIX_FMT_BGR24, ++ .flags = 0, ++ .mmal = MMAL_ENCODING_RGB24, ++ .depth = 24, ++ .mmal_component = MMAL_COMPONENT_CAMERA, ++ }, ++ { ++ .name = "4:2:0, packed YVU", ++ .fourcc = V4L2_PIX_FMT_YVU420, ++ .flags = 0, ++ .mmal = MMAL_ENCODING_YV12, ++ .depth = 12, ++ .mmal_component = MMAL_COMPONENT_CAMERA, ++ }, ++ { ++ .name = "4:2:0, packed, NV21", ++ .fourcc = V4L2_PIX_FMT_NV21, ++ .flags = 0, ++ .mmal = MMAL_ENCODING_NV21, ++ .depth = 12, ++ .mmal_component = MMAL_COMPONENT_CAMERA, ++ }, +}; + +static struct mmal_fmt *get_format(struct v4l2_format *f) @@ -12481,6 +12090,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + + strlcpy(f->description, fmt->name, sizeof(f->description)); + f->pixelformat = fmt->fourcc; ++ f->flags = fmt->flags; + + return 0; +} @@ -12609,7 +12219,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + a->fmt.bytesperline = (preview_port->es.video.width * 3)>>1; + a->fmt.sizeimage = (preview_port->es.video.width * + preview_port->es.video.height * 3)>>1; -+ a->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M; ++ a->fmt.colorspace = V4L2_COLORSPACE_JPEG; + + return 0; +} @@ -12676,6 +12286,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + + strlcpy(f->description, fmt->name, sizeof(f->description)); + f->pixelformat = fmt->fourcc; ++ f->flags = fmt->flags; ++ + return 0; +} + @@ -12820,10 +12432,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + camera_port->es.video.crop.y = 0; + camera_port->es.video.crop.width = f->fmt.pix.width; + camera_port->es.video.crop.height = f->fmt.pix.height; -+ camera_port->es.video.frame_rate.num = -+ dev->capture.timeperframe.denominator; -+ camera_port->es.video.frame_rate.den = -+ dev->capture.timeperframe.numerator; ++ camera_port->es.video.frame_rate.num = 0; ++ camera_port->es.video.frame_rate.den = 1; + + ret = vchiq_mmal_port_set_format(dev->instance, camera_port); + @@ -12857,8 +12467,10 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + preview_port->es.video.crop.y = 0; + preview_port->es.video.crop.width = f->fmt.pix.width; + preview_port->es.video.crop.height = f->fmt.pix.height; -+ preview_port->es.video.frame_rate.num = 30; -+ preview_port->es.video.frame_rate.den = 1; ++ preview_port->es.video.frame_rate.num = ++ dev->capture.timeperframe.denominator; ++ preview_port->es.video.frame_rate.den = ++ dev->capture.timeperframe.numerator; + ret = vchiq_mmal_port_set_format(dev->instance, preview_port); + if (overlay_enabled) { + ret = vchiq_mmal_port_connect_tunnel( @@ -13033,22 +12645,56 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + } + + ret = mmal_setup_components(dev, f); -+ if (ret != 0) ++ if (ret != 0) { + v4l2_err(&dev->v4l2_dev, + "%s: failed to setup mmal components: %d\n", + __func__, ret); ++ ret = -EINVAL; ++ } + + return ret; +} + ++int vidioc_enum_framesizes(struct file *file, void *fh, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ static const struct v4l2_frmsize_stepwise sizes = { ++ MIN_WIDTH, MAX_WIDTH, 2, ++ MIN_HEIGHT, MAX_HEIGHT, 2 ++ }; ++ int i; ++ ++ if (fsize->index) ++ return -EINVAL; ++ for (i = 0; i < ARRAY_SIZE(formats); i++) ++ if (formats[i].fourcc == fsize->pixel_format) ++ break; ++ if (i == ARRAY_SIZE(formats)) ++ return -EINVAL; ++ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; ++ fsize->stepwise = sizes; ++ return 0; ++} ++ +/* timeperframe is arbitrary and continous */ +static int vidioc_enum_frameintervals(struct file *file, void *priv, + struct v4l2_frmivalenum *fival) +{ ++ int i; ++ + if (fival->index) + return -EINVAL; + -+ /* regarding width & height - we support any */ ++ for (i = 0; i < ARRAY_SIZE(formats); i++) ++ if (formats[i].fourcc == fival->pixel_format) ++ break; ++ if (i == ARRAY_SIZE(formats)) ++ return -EINVAL; ++ ++ /* regarding width & height - we support any within range */ ++ if (fival->width < MIN_WIDTH || fival->width > MAX_WIDTH || ++ fival->height < MIN_HEIGHT || fival->height > MAX_HEIGHT) ++ return -EINVAL; + + fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS; + @@ -13084,7 +12730,6 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + struct bm2835_mmal_dev *dev = video_drvdata(file); + struct v4l2_fract tpf; + struct mmal_parameter_rational fps_param; -+ int ret; + + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; @@ -13100,27 +12745,11 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + parm->parm.capture.timeperframe = tpf; + parm->parm.capture.readbuffers = 1; + -+ fps_param.num = dev->capture.timeperframe.denominator; -+ fps_param.den = dev->capture.timeperframe.numerator; -+ ret = vchiq_mmal_port_parameter_set(dev->instance, -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_PREVIEW], -+ MMAL_PARAMETER_VIDEO_FRAME_RATE, -+ &fps_param, sizeof(fps_param)); -+ ret += vchiq_mmal_port_parameter_set(dev->instance, -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_VIDEO], -+ MMAL_PARAMETER_VIDEO_FRAME_RATE, -+ &fps_param, sizeof(fps_param)); -+ ret += vchiq_mmal_port_parameter_set(dev->instance, -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_CAPTURE], -+ MMAL_PARAMETER_VIDEO_FRAME_RATE, -+ &fps_param, sizeof(fps_param)); -+ if (ret) -+ v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Failed to set fps ret %d\n", -+ ret); ++ fps_param.num = 0; /* Select variable fps, and then use ++ * FPS_RANGE to select the actual limits. ++ */ ++ fps_param.den = 1; ++ set_framerate_params(dev); + + return 0; +} @@ -13153,6 +12782,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, ++ .vidioc_enum_framesizes = vidioc_enum_framesizes, + .vidioc_enum_frameintervals = vidioc_enum_frameintervals, + .vidioc_g_parm = vidioc_g_parm, + .vidioc_s_parm = vidioc_s_parm, @@ -13248,10 +12878,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + format->es->video.crop.y = 0; + format->es->video.crop.width = 1024; + format->es->video.crop.height = 768; -+ format->es->video.frame_rate.num = -+ dev->capture.timeperframe.denominator; -+ format->es->video.frame_rate.den = -+ dev->capture.timeperframe.numerator; ++ format->es->video.frame_rate.num = 0; /* Rely on fps_range */ ++ format->es->video.frame_rate.den = 1; + + format = + &dev->component[MMAL_COMPONENT_CAMERA]-> @@ -13266,10 +12894,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + format->es->video.crop.y = 0; + format->es->video.crop.width = 1024; + format->es->video.crop.height = 768; -+ format->es->video.frame_rate.num = -+ dev->capture.timeperframe.denominator; -+ format->es->video.frame_rate.den = -+ dev->capture.timeperframe.numerator; ++ format->es->video.frame_rate.num = 0; /* Rely on fps_range */ ++ format->es->video.frame_rate.den = 1; + + format = + &dev->component[MMAL_COMPONENT_CAMERA]-> @@ -13283,7 +12909,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + format->es->video.crop.y = 0; + format->es->video.crop.width = 2592; + format->es->video.crop.height = 1944; -+ format->es->video.frame_rate.num = 30; ++ format->es->video.frame_rate.num = 0; /* Rely on fps_range */ + format->es->video.frame_rate.den = 1; + + dev->capture.width = format->es->video.width; @@ -13291,6 +12917,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + dev->capture.fmt = &formats[0]; + dev->capture.encode_component = NULL; + dev->capture.timeperframe = tpf_default; ++ dev->capture.enc_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH; ++ dev->capture.enc_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0; + + /* get the preview component ready */ + ret = vchiq_mmal_component_init( @@ -13337,6 +12965,14 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + } + + { ++ struct vchiq_mmal_port *encoder_port = ++ &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0]; ++ encoder_port->format.encoding = MMAL_ENCODING_H264; ++ ret = vchiq_mmal_port_set_format(dev->instance, ++ encoder_port); ++ } ++ ++ { + unsigned int enable = 1; + vchiq_mmal_port_parameter_set( + dev->instance, @@ -13553,10 +13189,10 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra + +module_init(bm2835_mmal_init); +module_exit(bm2835_mmal_exit); -diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.h linux-raspberry-pi/drivers/media/platform/bcm2835/bcm2835-camera.h ---- linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/bcm2835/bcm2835-camera.h 2014-03-11 17:51:15.000000000 +0100 -@@ -0,0 +1,113 @@ +diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/bcm2835-camera.h linux-rpi/drivers/media/platform/bcm2835/bcm2835-camera.h +--- linux-3.12.18/drivers/media/platform/bcm2835/bcm2835-camera.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/media/platform/bcm2835/bcm2835-camera.h 2014-04-24 15:35:02.713549510 +0200 +@@ -0,0 +1,125 @@ +/* + * Broadcom BM2835 V4L2 driver + * @@ -13574,7 +13210,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.h linux-ra + * core driver device + */ + -+#define V4L2_CTRL_COUNT 21 /* number of v4l controls */ ++#define V4L2_CTRL_COUNT 27 /* number of v4l controls */ + +enum { + MMAL_COMPONENT_CAMERA = 0, @@ -13604,11 +13240,19 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.h linux-ra + /* controls */ + struct v4l2_ctrl_handler ctrl_handler; + struct v4l2_ctrl *ctrls[V4L2_CTRL_COUNT]; ++ enum v4l2_scene_mode scene_mode; + struct mmal_colourfx colourfx; + int hflip; + int vflip; -+ enum mmal_parameter_exposuremode exposure_mode; ++ int red_gain; ++ int blue_gain; ++ enum mmal_parameter_exposuremode exposure_mode_user; ++ enum v4l2_exposure_auto_type exposure_mode_v4l2_user; ++ /* active exposure mode may differ if selected via a scene mode */ ++ enum mmal_parameter_exposuremode exposure_mode_active; ++ enum mmal_parameter_exposuremeteringmode metering_mode; + unsigned int manual_shutter_speed; ++ bool exp_auto_priority; + + /* allocated mmal instance and components */ + struct vchiq_mmal_instance *instance; @@ -13622,12 +13266,16 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.h linux-ra + unsigned int height; /* height */ + unsigned int stride; /* stride */ + struct mmal_fmt *fmt; -+ struct v4l2_fract timeperframe; ++ struct v4l2_fract timeperframe; + + /* H264 encode bitrate */ + int encode_bitrate; + /* H264 bitrate mode. CBR/VBR */ + int encode_bitrate_mode; ++ /* H264 profile */ ++ enum v4l2_mpeg_video_h264_profile enc_profile; ++ /* H264 level */ ++ enum v4l2_mpeg_video_h264_level enc_level; + /* JPEG Q-factor */ + int q_factor; + @@ -13657,7 +13305,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.h linux-ra + struct v4l2_ctrl_handler *hdl); + +int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev); -+ ++int set_framerate_params(struct bm2835_mmal_dev *dev); + +/* Debug helpers */ + @@ -13670,10 +13318,10 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.h linux-ra + (pix_fmt)->pixelformat, (pix_fmt)->bytesperline, \ + (pix_fmt)->sizeimage, (pix_fmt)->colorspace, (pix_fmt)->priv); \ +} -diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberry-pi/drivers/media/platform/bcm2835/controls.c ---- linux-3.12.13/drivers/media/platform/bcm2835/controls.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/bcm2835/controls.c 2014-03-11 17:51:15.000000000 +0100 -@@ -0,0 +1,902 @@ +diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/controls.c linux-rpi/drivers/media/platform/bcm2835/controls.c +--- linux-3.12.18/drivers/media/platform/bcm2835/controls.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/media/platform/bcm2835/controls.c 2014-04-24 15:35:02.713549510 +0200 +@@ -0,0 +1,1315 @@ +/* + * Broadcom BM2835 V4L2 driver + * @@ -13745,7 +13393,6 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, +}; + -+ +enum bm2835_mmal_ctrl_type { + MMAL_CONTROL_TYPE_STD, + MMAL_CONTROL_TYPE_STD_MENU, @@ -13822,6 +13469,25 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + 1, 1, 0, 0, 0, {0, 0, 0, 0, 0} } +}; + ++struct v4l2_mmal_scene_config { ++ enum v4l2_scene_mode v4l2_scene; ++ enum mmal_parameter_exposuremode exposure_mode; ++ enum mmal_parameter_exposuremeteringmode metering_mode; ++}; ++ ++static const struct v4l2_mmal_scene_config scene_configs[] = { ++ /* V4L2_SCENE_MODE_NONE automatically added */ ++ { ++ V4L2_SCENE_MODE_NIGHT, ++ MMAL_PARAM_EXPOSUREMODE_NIGHT, ++ MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE ++ }, ++ { ++ V4L2_SCENE_MODE_SPORTS, ++ MMAL_PARAM_EXPOSUREMODE_SPORTS, ++ MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE ++ }, ++}; + +/* control handlers*/ + @@ -13973,7 +13639,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) +{ -+ enum mmal_parameter_exposuremode exp_mode = dev->exposure_mode; ++ enum mmal_parameter_exposuremode exp_mode = dev->exposure_mode_user; + u32 shutter_speed = 0; + struct vchiq_mmal_port *control; + int ret = 0; @@ -13994,28 +13660,34 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + case V4L2_EXPOSURE_MANUAL: + exp_mode = MMAL_PARAM_EXPOSUREMODE_OFF; + break; -+ -+ case V4L2_EXPOSURE_SHUTTER_PRIORITY: -+ exp_mode = MMAL_PARAM_EXPOSUREMODE_SPORTS; -+ break; -+ -+ case V4L2_EXPOSURE_APERTURE_PRIORITY: -+ exp_mode = MMAL_PARAM_EXPOSUREMODE_NIGHT; -+ break; -+ + } -+ dev->exposure_mode = exp_mode; -+ } -+ -+ if (dev->exposure_mode == MMAL_PARAM_EXPOSUREMODE_OFF) -+ shutter_speed = dev->manual_shutter_speed; ++ dev->exposure_mode_user = exp_mode; ++ dev->exposure_mode_v4l2_user = ctrl->val; ++ } else if (mmal_ctrl->id == V4L2_CID_EXPOSURE_AUTO_PRIORITY) { ++ dev->exp_auto_priority = ctrl->val; ++ } ++ ++ if (dev->scene_mode == V4L2_SCENE_MODE_NONE) { ++ if (exp_mode == MMAL_PARAM_EXPOSUREMODE_OFF) ++ shutter_speed = dev->manual_shutter_speed; ++ ++ ret = vchiq_mmal_port_parameter_set(dev->instance, ++ control, ++ MMAL_PARAMETER_SHUTTER_SPEED, ++ &shutter_speed, ++ sizeof(shutter_speed)); ++ ret += vchiq_mmal_port_parameter_set(dev->instance, ++ control, ++ MMAL_PARAMETER_EXPOSURE_MODE, ++ &exp_mode, ++ sizeof(u32)); ++ dev->exposure_mode_active = exp_mode; ++ } ++ /* exposure_dynamic_framerate (V4L2_CID_EXPOSURE_AUTO_PRIORITY) should ++ * always apply irrespective of scene mode. ++ */ ++ ret += set_framerate_params(dev); + -+ ret = vchiq_mmal_port_parameter_set(dev->instance, control, -+ MMAL_PARAMETER_SHUTTER_SPEED, -+ &shutter_speed, sizeof(shutter_speed)); -+ ret += vchiq_mmal_port_parameter_set(dev->instance, control, -+ MMAL_PARAMETER_EXPOSURE_MODE, -+ &exp_mode, sizeof(u32)); + return ret; +} + @@ -14023,35 +13695,38 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) +{ -+ u32 u32_value; -+ struct vchiq_mmal_port *control; -+ -+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; -+ + switch (ctrl->val) { + case V4L2_EXPOSURE_METERING_AVERAGE: -+ u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE; ++ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE; + break; + + case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED: -+ u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT; ++ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT; + break; + + case V4L2_EXPOSURE_METERING_SPOT: -+ u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT; ++ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT; + break; + + /* todo matrix weighting not added to Linux API till 3.9 + case V4L2_EXPOSURE_METERING_MATRIX: -+ u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX; ++ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX; + break; + */ + + } + -+ return vchiq_mmal_port_parameter_set(dev->instance, control, ++ if (dev->scene_mode == V4L2_SCENE_MODE_NONE) { ++ struct vchiq_mmal_port *control; ++ u32 u32_value = dev->metering_mode; ++ ++ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; ++ ++ return vchiq_mmal_port_parameter_set(dev->instance, control, + mmal_ctrl->mmal_id, + &u32_value, sizeof(u32_value)); ++ } else ++ return 0; +} + +static int ctrl_set_flicker_avoidance(struct bm2835_mmal_dev *dev, @@ -14140,6 +13815,29 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + &u32_value, sizeof(u32_value)); +} + ++static int ctrl_set_awb_gains(struct bm2835_mmal_dev *dev, ++ struct v4l2_ctrl *ctrl, ++ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) ++{ ++ struct vchiq_mmal_port *control; ++ struct mmal_parameter_awbgains gains; ++ ++ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; ++ ++ if (ctrl->id == V4L2_CID_RED_BALANCE) ++ dev->red_gain = ctrl->val; ++ else if (ctrl->id == V4L2_CID_BLUE_BALANCE) ++ dev->blue_gain = ctrl->val; ++ ++ gains.r_gain.num = dev->red_gain; ++ gains.b_gain.num = dev->blue_gain; ++ gains.r_gain.den = gains.b_gain.den = 1000; ++ ++ return vchiq_mmal_port_parameter_set(dev->instance, control, ++ mmal_ctrl->mmal_id, ++ &gains, sizeof(gains)); ++} ++ +static int ctrl_set_image_effect(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) @@ -14216,8 +13914,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + &dev->colourfx, sizeof(dev->colourfx)); + + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n", -+ mmal_ctrl, ctrl->id, ctrl->val, ret, ++ "%s: After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n", ++ __func__, mmal_ctrl, ctrl->id, ctrl->val, ret, + (ret == 0 ? 0 : -EINVAL)); + return (ret == 0 ? 0 : EINVAL); +} @@ -14299,6 +13997,224 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + &u32_value, sizeof(u32_value)); +} + ++static int ctrl_set_video_encode_profile_level(struct bm2835_mmal_dev *dev, ++ struct v4l2_ctrl *ctrl, ++ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) ++{ ++ struct mmal_parameter_video_profile param; ++ int ret = 0; ++ ++ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) { ++ switch (ctrl->val) { ++ case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: ++ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: ++ case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: ++ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: ++ dev->capture.enc_profile = ctrl->val; ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ } else if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) { ++ switch (ctrl->val) { ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1B: ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: ++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: ++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: ++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: ++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: ++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: ++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: ++ case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: ++ dev->capture.enc_level = ctrl->val; ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ } ++ ++ if (!ret) { ++ switch (dev->capture.enc_profile) { ++ case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: ++ param.profile = MMAL_VIDEO_PROFILE_H264_BASELINE; ++ break; ++ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: ++ param.profile = ++ MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE; ++ break; ++ case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: ++ param.profile = MMAL_VIDEO_PROFILE_H264_MAIN; ++ break; ++ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: ++ param.profile = MMAL_VIDEO_PROFILE_H264_HIGH; ++ break; ++ default: ++ /* Should never get here */ ++ break; ++ } ++ ++ switch (dev->capture.enc_level) { ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: ++ param.level = MMAL_VIDEO_LEVEL_H264_1; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1B: ++ param.level = MMAL_VIDEO_LEVEL_H264_1b; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: ++ param.level = MMAL_VIDEO_LEVEL_H264_11; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: ++ param.level = MMAL_VIDEO_LEVEL_H264_12; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: ++ param.level = MMAL_VIDEO_LEVEL_H264_13; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: ++ param.level = MMAL_VIDEO_LEVEL_H264_2; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: ++ param.level = MMAL_VIDEO_LEVEL_H264_21; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: ++ param.level = MMAL_VIDEO_LEVEL_H264_22; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: ++ param.level = MMAL_VIDEO_LEVEL_H264_3; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: ++ param.level = MMAL_VIDEO_LEVEL_H264_31; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: ++ param.level = MMAL_VIDEO_LEVEL_H264_32; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: ++ param.level = MMAL_VIDEO_LEVEL_H264_4; ++ break; ++ default: ++ /* Should never get here */ ++ break; ++ } ++ ++ ret = vchiq_mmal_port_parameter_set(dev->instance, ++ &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0], ++ mmal_ctrl->mmal_id, ++ ¶m, sizeof(param)); ++ } ++ return ret; ++} ++ ++static int ctrl_set_scene_mode(struct bm2835_mmal_dev *dev, ++ struct v4l2_ctrl *ctrl, ++ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) ++{ ++ int ret = 0; ++ int shutter_speed; ++ struct vchiq_mmal_port *control; ++ ++ v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev, ++ "scene mode selected %d, was %d\n", ctrl->val, ++ dev->scene_mode); ++ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; ++ ++ if (ctrl->val == dev->scene_mode) ++ return 0; ++ ++ if (ctrl->val == V4L2_SCENE_MODE_NONE) { ++ /* Restore all user selections */ ++ dev->scene_mode = V4L2_SCENE_MODE_NONE; ++ ++ if (dev->exposure_mode_user == MMAL_PARAM_EXPOSUREMODE_OFF) ++ shutter_speed = dev->manual_shutter_speed; ++ else ++ shutter_speed = 0; ++ ++ v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev, ++ "%s: scene mode none: shut_speed %d, exp_mode %d, metering %d\n", ++ __func__, shutter_speed, dev->exposure_mode_user, ++ dev->metering_mode); ++ ret = vchiq_mmal_port_parameter_set(dev->instance, ++ control, ++ MMAL_PARAMETER_SHUTTER_SPEED, ++ &shutter_speed, ++ sizeof(shutter_speed)); ++ ret += vchiq_mmal_port_parameter_set(dev->instance, ++ control, ++ MMAL_PARAMETER_EXPOSURE_MODE, ++ &dev->exposure_mode_user, ++ sizeof(u32)); ++ dev->exposure_mode_active = dev->exposure_mode_user; ++ ret += vchiq_mmal_port_parameter_set(dev->instance, ++ control, ++ MMAL_PARAMETER_EXP_METERING_MODE, ++ &dev->metering_mode, ++ sizeof(u32)); ++ ret += set_framerate_params(dev); ++ } else { ++ /* Set up scene mode */ ++ int i; ++ const struct v4l2_mmal_scene_config *scene = NULL; ++ int shutter_speed; ++ enum mmal_parameter_exposuremode exposure_mode; ++ enum mmal_parameter_exposuremeteringmode metering_mode; ++ ++ for (i = 0; i < ARRAY_SIZE(scene_configs); i++) { ++ if (scene_configs[i].v4l2_scene == ++ ctrl->val) { ++ scene = &scene_configs[i]; ++ break; ++ } ++ } ++ if (i >= ARRAY_SIZE(scene_configs)) ++ return -EINVAL; ++ ++ /* Set all the values */ ++ dev->scene_mode = ctrl->val; ++ ++ if (scene->exposure_mode == MMAL_PARAM_EXPOSUREMODE_OFF) ++ shutter_speed = dev->manual_shutter_speed; ++ else ++ shutter_speed = 0; ++ exposure_mode = scene->exposure_mode; ++ metering_mode = scene->metering_mode; ++ ++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, ++ "%s: scene mode none: shut_speed %d, exp_mode %d, metering %d\n", ++ __func__, shutter_speed, exposure_mode, metering_mode); ++ ++ ret = vchiq_mmal_port_parameter_set(dev->instance, control, ++ MMAL_PARAMETER_SHUTTER_SPEED, ++ &shutter_speed, ++ sizeof(shutter_speed)); ++ ret += vchiq_mmal_port_parameter_set(dev->instance, ++ control, ++ MMAL_PARAMETER_EXPOSURE_MODE, ++ &exposure_mode, ++ sizeof(u32)); ++ dev->exposure_mode_active = exposure_mode; ++ ret += vchiq_mmal_port_parameter_set(dev->instance, control, ++ MMAL_PARAMETER_EXPOSURE_MODE, ++ &exposure_mode, ++ sizeof(u32)); ++ ret += vchiq_mmal_port_parameter_set(dev->instance, control, ++ MMAL_PARAMETER_EXP_METERING_MODE, ++ &metering_mode, ++ sizeof(u32)); ++ ret += set_framerate_params(dev); ++ } ++ if (ret) { ++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, ++ "%s: Setting scene to %d, ret=%d\n", ++ __func__, ctrl->val, ret); ++ ret = -EINVAL; ++ } ++ return 0; ++} ++ +static int bm2835_mmal_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct bm2835_mmal_dev *dev = @@ -14315,6 +14231,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + } + + ret = mmal_ctrl->setter(dev, ctrl, mmal_ctrl); ++ if (ret) ++ pr_warn("ctrl id:%d/MMAL param %08X- returned ret %d\n", ++ ctrl->id, mmal_ctrl->mmal_id, ret); + if (mmal_ctrl->ignore_errors) + ret = 0; + return ret; @@ -14401,6 +14320,14 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + false + }, + { ++ V4L2_CID_EXPOSURE_AUTO_PRIORITY, MMAL_CONTROL_TYPE_STD, ++ 0, 1, ++ 0, 1, NULL, ++ 0, /* Dummy MMAL ID as it gets mapped into FPS range*/ ++ &ctrl_set_exposure, ++ false ++ }, ++ { + V4L2_CID_EXPOSURE_METERING, + MMAL_CONTROL_TYPE_STD_MENU, + ~0x7, 2, V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL, @@ -14411,12 +14338,26 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + { + V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, + MMAL_CONTROL_TYPE_STD_MENU, -+ ~0x3fe, 9, V4L2_WHITE_BALANCE_AUTO, 0, NULL, ++ ~0x3ff, 9, V4L2_WHITE_BALANCE_AUTO, 0, NULL, + MMAL_PARAMETER_AWB_MODE, + &ctrl_set_awb_mode, + false + }, + { ++ V4L2_CID_RED_BALANCE, MMAL_CONTROL_TYPE_STD, ++ 1, 7999, 1000, 1, NULL, ++ MMAL_PARAMETER_CUSTOM_AWB_GAINS, ++ &ctrl_set_awb_gains, ++ false ++ }, ++ { ++ V4L2_CID_BLUE_BALANCE, MMAL_CONTROL_TYPE_STD, ++ 1, 7999, 1000, 1, NULL, ++ MMAL_PARAMETER_CUSTOM_AWB_GAINS, ++ &ctrl_set_awb_gains, ++ false ++ }, ++ { + V4L2_CID_COLORFX, MMAL_CONTROL_TYPE_STD_MENU, + 0, 15, V4L2_COLORFX_NONE, 0, NULL, + MMAL_PARAMETER_IMAGE_EFFECT, @@ -14490,6 +14431,48 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + &ctrl_set_video_encode_param_output, + true /* Errors ignored as requires latest firmware to work */ + }, ++ { ++ V4L2_CID_MPEG_VIDEO_H264_PROFILE, ++ MMAL_CONTROL_TYPE_STD_MENU, ++ ~((1<<V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | ++ (1<<V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | ++ (1<<V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | ++ (1<<V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)), ++ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, ++ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, 1, NULL, ++ MMAL_PARAMETER_PROFILE, ++ &ctrl_set_video_encode_profile_level, ++ false ++ }, ++ { ++ V4L2_CID_MPEG_VIDEO_H264_LEVEL, MMAL_CONTROL_TYPE_STD_MENU, ++ ~((1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | ++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1B) | ++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | ++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | ++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | ++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | ++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | ++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | ++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | ++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | ++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | ++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_4_0)), ++ V4L2_MPEG_VIDEO_H264_LEVEL_4_0, ++ V4L2_MPEG_VIDEO_H264_LEVEL_4_0, 1, NULL, ++ MMAL_PARAMETER_PROFILE, ++ &ctrl_set_video_encode_profile_level, ++ false ++ }, ++ { ++ V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU, ++ -1, /* Min is computed at runtime */ ++ V4L2_SCENE_MODE_TEXT, ++ V4L2_SCENE_MODE_NONE, 1, NULL, ++ MMAL_PARAMETER_PROFILE, ++ &ctrl_set_scene_mode, ++ false ++ }, +}; + +int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev) @@ -14501,13 +14484,71 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + if ((dev->ctrls[c]) && (v4l2_ctrls[c].setter)) { + ret = v4l2_ctrls[c].setter(dev, dev->ctrls[c], + &v4l2_ctrls[c]); -+ if (!v4l2_ctrls[c]. ignore_errors && ret) ++ if (!v4l2_ctrls[c].ignore_errors && ret) { ++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, ++ "Failed when setting default values for ctrl %d\n", ++ c); + break; ++ } + } + } + return ret; +} + ++int set_framerate_params(struct bm2835_mmal_dev *dev) ++{ ++ struct mmal_parameter_fps_range fps_range; ++ int ret; ++ ++ if ((dev->exposure_mode_active != MMAL_PARAM_EXPOSUREMODE_OFF) && ++ (dev->exp_auto_priority)) { ++ /* Variable FPS. Define min FPS as 1fps. ++ * Max as max defined FPS. ++ */ ++ fps_range.fps_low.num = 1; ++ fps_range.fps_low.den = 1; ++ fps_range.fps_high.num = dev->capture.timeperframe.denominator; ++ fps_range.fps_high.den = dev->capture.timeperframe.numerator; ++ } else { ++ /* Fixed FPS - set min and max to be the same */ ++ fps_range.fps_low.num = fps_range.fps_high.num = ++ dev->capture.timeperframe.denominator; ++ fps_range.fps_low.den = fps_range.fps_high.den = ++ dev->capture.timeperframe.numerator; ++ } ++ ++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, ++ "Set fps range to %d/%d to %d/%d\n", ++ fps_range.fps_low.num, ++ fps_range.fps_low.den, ++ fps_range.fps_high.num, ++ fps_range.fps_high.den ++ ); ++ ++ ret = vchiq_mmal_port_parameter_set(dev->instance, ++ &dev->component[MMAL_COMPONENT_CAMERA]-> ++ output[MMAL_CAMERA_PORT_PREVIEW], ++ MMAL_PARAMETER_FPS_RANGE, ++ &fps_range, sizeof(fps_range)); ++ ret += vchiq_mmal_port_parameter_set(dev->instance, ++ &dev->component[MMAL_COMPONENT_CAMERA]-> ++ output[MMAL_CAMERA_PORT_VIDEO], ++ MMAL_PARAMETER_FPS_RANGE, ++ &fps_range, sizeof(fps_range)); ++ ret += vchiq_mmal_port_parameter_set(dev->instance, ++ &dev->component[MMAL_COMPONENT_CAMERA]-> ++ output[MMAL_CAMERA_PORT_CAPTURE], ++ MMAL_PARAMETER_FPS_RANGE, ++ &fps_range, sizeof(fps_range)); ++ if (ret) ++ v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev, ++ "Failed to set fps ret %d\n", ++ ret); ++ ++ return ret; ++ ++} ++ +int bm2835_mmal_init_controls(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl_handler *hdl) +{ @@ -14527,10 +14568,30 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + break; + + case MMAL_CONTROL_TYPE_STD_MENU: ++ { ++ int mask = ctrl->min; ++ ++ if (ctrl->id == V4L2_CID_SCENE_MODE) { ++ /* Special handling to work out the mask ++ * value based on the scene_configs array ++ * at runtime. Reduces the chance of ++ * mismatches. ++ */ ++ int i; ++ mask = 1<<V4L2_SCENE_MODE_NONE; ++ for (i = 0; ++ i < ARRAY_SIZE(scene_configs); ++ i++) { ++ mask |= 1<<scene_configs[i].v4l2_scene; ++ } ++ mask = ~mask; ++ } ++ + dev->ctrls[c] = v4l2_ctrl_new_std_menu(hdl, + &bm2835_mmal_ctrl_ops, ctrl->id, -+ ctrl->max, ctrl->min, ctrl->def); ++ ctrl->max, mask, ctrl->def); + break; ++ } + + case MMAL_CONTROL_TYPE_INT_MENU: + dev->ctrls[c] = v4l2_ctrl_new_int_menu(hdl, @@ -14576,9 +14637,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr + + return 0; +} -diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/Kconfig linux-raspberry-pi/drivers/media/platform/bcm2835/Kconfig ---- linux-3.12.13/drivers/media/platform/bcm2835/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/bcm2835/Kconfig 2014-03-11 17:32:31.000000000 +0100 +diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/Kconfig linux-rpi/drivers/media/platform/bcm2835/Kconfig +--- linux-3.12.18/drivers/media/platform/bcm2835/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/media/platform/bcm2835/Kconfig 2014-04-24 15:35:02.713549510 +0200 @@ -0,0 +1,25 @@ +# Broadcom VideoCore IV v4l2 camera support + @@ -14605,19 +14666,19 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/Kconfig linux-raspberry-p + + +endif # VIDEO_BM2835 -diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/Makefile linux-raspberry-pi/drivers/media/platform/bcm2835/Makefile ---- linux-3.12.13/drivers/media/platform/bcm2835/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/bcm2835/Makefile 2014-03-11 17:32:31.000000000 +0100 +diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/Makefile linux-rpi/drivers/media/platform/bcm2835/Makefile +--- linux-3.12.18/drivers/media/platform/bcm2835/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/media/platform/bcm2835/Makefile 2014-04-24 15:35:02.713549510 +0200 @@ -0,0 +1,5 @@ +bcm2835-v4l2-objs := bcm2835-camera.o controls.o mmal-vchiq.o + +obj-$(CONFIG_VIDEO_BCM2835_MMAL) += bcm2835-v4l2.o + +ccflags-$(CONFIG_VIDEO_BCM2835) += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 -diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-common.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-common.h ---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-common.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-common.h 2014-03-11 17:51:15.000000000 +0100 -@@ -0,0 +1,52 @@ +diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-common.h linux-rpi/drivers/media/platform/bcm2835/mmal-common.h +--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-common.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/media/platform/bcm2835/mmal-common.h 2014-04-24 15:35:02.713549510 +0200 +@@ -0,0 +1,53 @@ +/* + * Broadcom BM2835 V4L2 driver + * @@ -14646,6 +14707,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-common.h linux-raspb +struct mmal_fmt { + char *name; + u32 fourcc; /* v4l2 format id */ ++ int flags; /* v4l2 flags field */ + u32 mmal; + int depth; + u32 mmal_component; /* MMAL component index to be used to encode */ @@ -14670,10 +14732,10 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-common.h linux-raspb + u32 v; +}; + -diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-encodings.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-encodings.h ---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-encodings.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-encodings.h 2014-03-11 17:51:15.000000000 +0100 -@@ -0,0 +1,93 @@ +diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-encodings.h linux-rpi/drivers/media/platform/bcm2835/mmal-encodings.h +--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-encodings.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/media/platform/bcm2835/mmal-encodings.h 2014-04-24 15:35:02.713549510 +0200 +@@ -0,0 +1,94 @@ +/* + * Broadcom BM2835 V4L2 driver + * @@ -14703,6 +14765,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-encodings.h linux-ra +#define MMAL_ENCODING_VP6 MMAL_FOURCC('V', 'P', '6', ' ') +#define MMAL_ENCODING_THEORA MMAL_FOURCC('T', 'H', 'E', 'O') +#define MMAL_ENCODING_SPARK MMAL_FOURCC('S', 'P', 'R', 'K') ++#define MMAL_ENCODING_MJPEG MMAL_FOURCC('M', 'J', 'P', 'G') + +#define MMAL_ENCODING_JPEG MMAL_FOURCC('J', 'P', 'E', 'G') +#define MMAL_ENCODING_GIF MMAL_FOURCC('G', 'I', 'F', ' ') @@ -14767,9 +14830,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-encodings.h linux-ra +#define MMAL_ENCODING_VARIANT_H264_AVC1 MMAL_FOURCC('A', 'V', 'C', '1') +/** Implicitly delineated NAL units without emulation prevention */ +#define MMAL_ENCODING_VARIANT_H264_RAW MMAL_FOURCC('R', 'A', 'W', ' ') -diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-common.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg-common.h ---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-common.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg-common.h 2014-03-11 17:32:31.000000000 +0100 +diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg-common.h linux-rpi/drivers/media/platform/bcm2835/mmal-msg-common.h +--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg-common.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/media/platform/bcm2835/mmal-msg-common.h 2014-04-24 15:35:02.713549510 +0200 @@ -0,0 +1,50 @@ +/* + * Broadcom BM2835 V4L2 driver @@ -14821,9 +14884,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-common.h linux-r +}; + +#endif /* MMAL_MSG_COMMON_H */ -diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-format.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg-format.h ---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-format.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg-format.h 2014-03-11 17:32:31.000000000 +0100 +diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg-format.h linux-rpi/drivers/media/platform/bcm2835/mmal-msg-format.h +--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg-format.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/media/platform/bcm2835/mmal-msg-format.h 2014-04-24 15:35:02.713549510 +0200 @@ -0,0 +1,81 @@ +/* + * Broadcom BM2835 V4L2 driver @@ -14906,9 +14969,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-format.h linux-r +}; + +#endif /* MMAL_MSG_FORMAT_H */ -diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg.h ---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg.h 2014-03-11 17:32:31.000000000 +0100 +diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg.h linux-rpi/drivers/media/platform/bcm2835/mmal-msg.h +--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/media/platform/bcm2835/mmal-msg.h 2014-04-24 15:35:02.713549510 +0200 @@ -0,0 +1,404 @@ +/* + * Broadcom BM2835 V4L2 driver @@ -15314,9 +15377,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg.h linux-raspberr + u8 payload[MMAL_MSG_MAX_PAYLOAD]; + } u; +}; -diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-port.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg-port.h ---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-port.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg-port.h 2014-03-11 17:32:31.000000000 +0100 +diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg-port.h linux-rpi/drivers/media/platform/bcm2835/mmal-msg-port.h +--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg-port.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/media/platform/bcm2835/mmal-msg-port.h 2014-04-24 15:35:02.713549510 +0200 @@ -0,0 +1,107 @@ +/* + * Broadcom BM2835 V4L2 driver @@ -15425,10 +15488,10 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-port.h linux-ras + */ + +}; -diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-parameters.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-parameters.h ---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-parameters.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-parameters.h 2014-03-11 17:51:15.000000000 +0100 -@@ -0,0 +1,562 @@ +diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-parameters.h linux-rpi/drivers/media/platform/bcm2835/mmal-parameters.h +--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-parameters.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/media/platform/bcm2835/mmal-parameters.h 2014-04-24 15:35:02.713549510 +0200 +@@ -0,0 +1,655 @@ +/* + * Broadcom BM2835 V4L2 driver + * @@ -15592,7 +15655,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-parameters.h linux-r + MMAL_PARAMETER_SW_SHARPEN_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_FLASH_REQUIRED, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_SW_SATURATION_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_SHUTTER_SPEED /**< Takes a @ref MMAL_PARAMETER_UINT32_T */ ++ MMAL_PARAMETER_SHUTTER_SPEED, /**< Takes a @ref MMAL_PARAMETER_UINT32_T */ ++ MMAL_PARAMETER_CUSTOM_AWB_GAINS, /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */ +}; + +struct mmal_parameter_rational { @@ -15613,6 +15677,14 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-parameters.h linux-r + */ +}; + ++struct mmal_parameter_fps_range { ++ /**< Low end of the permitted framerate range */ ++ struct mmal_parameter_rational fps_low; ++ /**< High end of the permitted framerate range */ ++ struct mmal_parameter_rational fps_high; ++}; ++ ++ +/* camera configuration parameter */ +struct mmal_parameter_camera_config { + /* Parameters for setting up the image pools */ @@ -15715,6 +15787,11 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-parameters.h linux-r + MMAL_PARAM_FLICKERAVOID_MAX = 0x7FFFFFFF +}; + ++struct mmal_parameter_awbgains { ++ struct mmal_parameter_rational r_gain; /**< Red gain */ ++ struct mmal_parameter_rational b_gain; /**< Blue gain */ ++}; ++ +/** Manner of video rate control */ +enum mmal_parameter_rate_control_mode { + MMAL_VIDEO_RATECONTROL_DEFAULT, @@ -15724,6 +15801,85 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-parameters.h linux-r + MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES +}; + ++enum mmal_video_profile { ++ MMAL_VIDEO_PROFILE_H263_BASELINE, ++ MMAL_VIDEO_PROFILE_H263_H320CODING, ++ MMAL_VIDEO_PROFILE_H263_BACKWARDCOMPATIBLE, ++ MMAL_VIDEO_PROFILE_H263_ISWV2, ++ MMAL_VIDEO_PROFILE_H263_ISWV3, ++ MMAL_VIDEO_PROFILE_H263_HIGHCOMPRESSION, ++ MMAL_VIDEO_PROFILE_H263_INTERNET, ++ MMAL_VIDEO_PROFILE_H263_INTERLACE, ++ MMAL_VIDEO_PROFILE_H263_HIGHLATENCY, ++ MMAL_VIDEO_PROFILE_MP4V_SIMPLE, ++ MMAL_VIDEO_PROFILE_MP4V_SIMPLESCALABLE, ++ MMAL_VIDEO_PROFILE_MP4V_CORE, ++ MMAL_VIDEO_PROFILE_MP4V_MAIN, ++ MMAL_VIDEO_PROFILE_MP4V_NBIT, ++ MMAL_VIDEO_PROFILE_MP4V_SCALABLETEXTURE, ++ MMAL_VIDEO_PROFILE_MP4V_SIMPLEFACE, ++ MMAL_VIDEO_PROFILE_MP4V_SIMPLEFBA, ++ MMAL_VIDEO_PROFILE_MP4V_BASICANIMATED, ++ MMAL_VIDEO_PROFILE_MP4V_HYBRID, ++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDREALTIME, ++ MMAL_VIDEO_PROFILE_MP4V_CORESCALABLE, ++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCODING, ++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCORE, ++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSCALABLE, ++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSIMPLE, ++ MMAL_VIDEO_PROFILE_H264_BASELINE, ++ MMAL_VIDEO_PROFILE_H264_MAIN, ++ MMAL_VIDEO_PROFILE_H264_EXTENDED, ++ MMAL_VIDEO_PROFILE_H264_HIGH, ++ MMAL_VIDEO_PROFILE_H264_HIGH10, ++ MMAL_VIDEO_PROFILE_H264_HIGH422, ++ MMAL_VIDEO_PROFILE_H264_HIGH444, ++ MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE, ++ MMAL_VIDEO_PROFILE_DUMMY = 0x7FFFFFFF ++}; ++ ++enum mmal_video_level { ++ MMAL_VIDEO_LEVEL_H263_10, ++ MMAL_VIDEO_LEVEL_H263_20, ++ MMAL_VIDEO_LEVEL_H263_30, ++ MMAL_VIDEO_LEVEL_H263_40, ++ MMAL_VIDEO_LEVEL_H263_45, ++ MMAL_VIDEO_LEVEL_H263_50, ++ MMAL_VIDEO_LEVEL_H263_60, ++ MMAL_VIDEO_LEVEL_H263_70, ++ MMAL_VIDEO_LEVEL_MP4V_0, ++ MMAL_VIDEO_LEVEL_MP4V_0b, ++ MMAL_VIDEO_LEVEL_MP4V_1, ++ MMAL_VIDEO_LEVEL_MP4V_2, ++ MMAL_VIDEO_LEVEL_MP4V_3, ++ MMAL_VIDEO_LEVEL_MP4V_4, ++ MMAL_VIDEO_LEVEL_MP4V_4a, ++ MMAL_VIDEO_LEVEL_MP4V_5, ++ MMAL_VIDEO_LEVEL_MP4V_6, ++ MMAL_VIDEO_LEVEL_H264_1, ++ MMAL_VIDEO_LEVEL_H264_1b, ++ MMAL_VIDEO_LEVEL_H264_11, ++ MMAL_VIDEO_LEVEL_H264_12, ++ MMAL_VIDEO_LEVEL_H264_13, ++ MMAL_VIDEO_LEVEL_H264_2, ++ MMAL_VIDEO_LEVEL_H264_21, ++ MMAL_VIDEO_LEVEL_H264_22, ++ MMAL_VIDEO_LEVEL_H264_3, ++ MMAL_VIDEO_LEVEL_H264_31, ++ MMAL_VIDEO_LEVEL_H264_32, ++ MMAL_VIDEO_LEVEL_H264_4, ++ MMAL_VIDEO_LEVEL_H264_41, ++ MMAL_VIDEO_LEVEL_H264_42, ++ MMAL_VIDEO_LEVEL_H264_5, ++ MMAL_VIDEO_LEVEL_H264_51, ++ MMAL_VIDEO_LEVEL_DUMMY = 0x7FFFFFFF ++}; ++ ++struct mmal_parameter_video_profile { ++ enum mmal_video_profile profile; ++ enum mmal_video_level level; ++}; ++ +/* video parameters */ + +enum mmal_parameter_video_type { @@ -15991,9 +16147,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-parameters.h linux-r + u32 num_effect_params; + u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS]; +}; -diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-vchiq.c linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-vchiq.c ---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-vchiq.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-vchiq.c 2014-03-11 17:51:15.000000000 +0100 +diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-vchiq.c linux-rpi/drivers/media/platform/bcm2835/mmal-vchiq.c +--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-vchiq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/media/platform/bcm2835/mmal-vchiq.c 2014-04-24 16:04:36.447091651 +0200 @@ -0,0 +1,1916 @@ +/* + * Broadcom BM2835 V4L2 driver @@ -17323,7 +17479,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-vchiq.c linux-raspbe + memcpy(value, &rmsg->u.port_parameter_get_reply.value, + rmsg->u.port_parameter_get_reply.size); + -+ pr_info("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__, ++ pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__, + ret, port->component->handle, port->handle, parameter_id); + +release_msg: @@ -17911,9 +18067,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-vchiq.c linux-raspbe + kfree(instance); + return -ENODEV; +} -diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-vchiq.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-vchiq.h ---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-vchiq.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-vchiq.h 2014-03-11 17:32:31.000000000 +0100 +diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-vchiq.h linux-rpi/drivers/media/platform/bcm2835/mmal-vchiq.h +--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-vchiq.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/media/platform/bcm2835/mmal-vchiq.h 2014-04-24 15:35:02.713549510 +0200 @@ -0,0 +1,178 @@ +/* + * Broadcom BM2835 V4L2 driver @@ -18093,9 +18249,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-vchiq.h linux-raspbe + struct mmal_buffer *buf); + +#endif /* MMAL_VCHIQ_H */ -diff -Nur linux-3.12.13/drivers/media/platform/Kconfig linux-raspberry-pi/drivers/media/platform/Kconfig ---- linux-3.12.13/drivers/media/platform/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/Kconfig 2014-03-11 17:51:15.000000000 +0100 +diff -Nur linux-3.12.18/drivers/media/platform/Kconfig linux-rpi/drivers/media/platform/Kconfig +--- linux-3.12.18/drivers/media/platform/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/media/platform/Kconfig 2014-04-24 16:04:36.447091651 +0200 @@ -124,6 +124,7 @@ source "drivers/media/platform/soc_camera/Kconfig" source "drivers/media/platform/exynos4-is/Kconfig" @@ -18104,9 +18260,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/Kconfig linux-raspberry-pi/driver endif # V4L_PLATFORM_DRIVERS -diff -Nur linux-3.12.13/drivers/media/platform/Makefile linux-raspberry-pi/drivers/media/platform/Makefile ---- linux-3.12.13/drivers/media/platform/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/platform/Makefile 2014-03-11 17:51:15.000000000 +0100 +diff -Nur linux-3.12.18/drivers/media/platform/Makefile linux-rpi/drivers/media/platform/Makefile +--- linux-3.12.18/drivers/media/platform/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/media/platform/Makefile 2014-04-24 16:04:36.447091651 +0200 @@ -52,4 +52,6 @@ obj-$(CONFIG_ARCH_OMAP) += omap/ @@ -18114,99 +18270,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/Makefile linux-raspberry-pi/drive +obj-$(CONFIG_VIDEO_BCM2835) += bcm2835/ + ccflags-y += -I$(srctree)/drivers/media/i2c -diff -Nur linux-3.12.13/drivers/media/usb/dvb-usb-v2/az6007.c linux-raspberry-pi/drivers/media/usb/dvb-usb-v2/az6007.c ---- linux-3.12.13/drivers/media/usb/dvb-usb-v2/az6007.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/usb/dvb-usb-v2/az6007.c 2014-03-11 17:32:32.000000000 +0100 -@@ -68,6 +68,19 @@ - .microcode_name = "dvb-usb-terratec-h7-drxk.fw", - }; - -+static struct drxk_config cablestar_hdci_drxk = { -+ .adr = 0x29, -+ .parallel_ts = true, -+ .dynamic_clk = true, -+ .single_master = true, -+ .enable_merr_cfg = true, -+ .no_i2c_bridge = false, -+ .chunk_size = 64, -+ .mpeg_out_clk_strength = 0x02, -+ .qam_demod_parameter_count = 2, -+ .microcode_name = "dvb-usb-technisat-cablestar-hdci-drxk.fw", -+}; -+ - static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) - { - struct az6007_device_state *st = fe_to_priv(fe); -@@ -630,6 +643,27 @@ - return 0; - } - -+static int az6007_cablestar_hdci_frontend_attach(struct dvb_usb_adapter *adap) -+{ -+ struct az6007_device_state *st = adap_to_priv(adap); -+ struct dvb_usb_device *d = adap_to_d(adap); -+ -+ pr_debug("attaching demod drxk\n"); -+ -+ adap->fe[0] = dvb_attach(drxk_attach, &cablestar_hdci_drxk, -+ &d->i2c_adap); -+ if (!adap->fe[0]) -+ return -EINVAL; -+ -+ adap->fe[0]->sec_priv = adap; -+ st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl; -+ adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; -+ -+ az6007_ci_init(adap); -+ -+ return 0; -+} -+ - static int az6007_tuner_attach(struct dvb_usb_adapter *adap) - { - struct dvb_usb_device *d = adap_to_d(adap); -@@ -868,6 +902,29 @@ - } - }; - -+static struct dvb_usb_device_properties az6007_cablestar_hdci_props = { -+ .driver_name = KBUILD_MODNAME, -+ .owner = THIS_MODULE, -+ .firmware = AZ6007_FIRMWARE, -+ -+ .adapter_nr = adapter_nr, -+ .size_of_priv = sizeof(struct az6007_device_state), -+ .i2c_algo = &az6007_i2c_algo, -+ .tuner_attach = az6007_tuner_attach, -+ .frontend_attach = az6007_cablestar_hdci_frontend_attach, -+ .streaming_ctrl = az6007_streaming_ctrl, -+/* ditch get_rc_config as it can't work (TS35 remote, I believe it's rc5) */ -+ .get_rc_config = NULL, -+ .read_mac_address = az6007_read_mac_addr, -+ .download_firmware = az6007_download_firmware, -+ .identify_state = az6007_identify_state, -+ .power_ctrl = az6007_power_ctrl, -+ .num_adapters = 1, -+ .adapter = { -+ { .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), } -+ } -+}; -+ - static struct usb_device_id az6007_usb_table[] = { - {DVB_USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007, - &az6007_props, "Azurewave 6007", RC_MAP_EMPTY)}, -@@ -875,6 +932,8 @@ - &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)}, - {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2, - &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)}, -+ {DVB_USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_CABLESTAR_HDCI, -+ &az6007_cablestar_hdci_props, "Technisat CableStar Combo HD CI", RC_MAP_EMPTY)}, - {0}, - }; - -diff -Nur linux-3.12.13/drivers/media/usb/dvb-usb-v2/rtl28xxu.c linux-raspberry-pi/drivers/media/usb/dvb-usb-v2/rtl28xxu.c ---- linux-3.12.13/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 2014-03-11 17:51:16.000000000 +0100 +diff -Nur linux-3.12.18/drivers/media/usb/dvb-usb-v2/rtl28xxu.c linux-rpi/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +--- linux-3.12.18/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 2014-04-24 16:04:36.559092734 +0200 @@ -1384,6 +1384,10 @@ &rtl2832u_props, "Compro VideoMate U620F", NULL) }, { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394, @@ -18218,26 +18284,26 @@ diff -Nur linux-3.12.13/drivers/media/usb/dvb-usb-v2/rtl28xxu.c linux-raspberry- { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03, &rtl2832u_props, "Leadtek WinFast DTV Dongle mini", NULL) }, { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_CPYTO_REDI_PC50A, -diff -Nur linux-3.12.13/drivers/misc/Kconfig linux-raspberry-pi/drivers/misc/Kconfig ---- linux-3.12.13/drivers/misc/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/Kconfig 2014-03-11 17:51:16.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/Kconfig linux-rpi/drivers/misc/Kconfig +--- linux-3.12.18/drivers/misc/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/misc/Kconfig 2014-04-24 16:04:36.711094204 +0200 @@ -537,4 +537,5 @@ source "drivers/misc/altera-stapl/Kconfig" source "drivers/misc/mei/Kconfig" source "drivers/misc/vmw_vmci/Kconfig" +source "drivers/misc/vc04_services/Kconfig" endmenu -diff -Nur linux-3.12.13/drivers/misc/Makefile linux-raspberry-pi/drivers/misc/Makefile ---- linux-3.12.13/drivers/misc/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/Makefile 2014-03-11 17:32:36.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/Makefile linux-rpi/drivers/misc/Makefile +--- linux-3.12.18/drivers/misc/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/misc/Makefile 2014-04-24 15:35:02.873551293 +0200 @@ -53,3 +53,4 @@ obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/ obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o obj-$(CONFIG_SRAM) += sram.o +obj-$(CONFIG_BCM2708_VCHIQ) += vc04_services/ -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/connections/connection.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/connections/connection.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchi/connections/connection.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/connections/connection.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchi/connections/connection.h linux-rpi/drivers/misc/vc04_services/interface/vchi/connections/connection.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchi/connections/connection.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchi/connections/connection.h 2014-04-24 15:35:02.889551471 +0200 @@ -0,0 +1,328 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -18567,9 +18633,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/connections/co +#endif /* CONNECTION_H_ */ + +/****************************** End of file **********************************/ -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h linux-rpi/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h 2014-04-24 15:35:02.889551471 +0200 @@ -0,0 +1,204 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -18775,9 +18841,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/message_driver +#endif // _VCHI_MESSAGE_H_ + +/****************************** End of file ***********************************/ -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h 2014-04-24 15:35:02.889551471 +0200 @@ -0,0 +1,224 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -19003,9 +19069,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h lin +#endif /* VCHI_CFG_H_ */ + +/****************************** End of file **********************************/ -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h 2014-04-24 15:35:02.889551471 +0200 @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -19078,9 +19144,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_cfg_inter +//#define VCHI_RX_NANOLOCKS + +#endif /*VCHI_CFG_INTERNAL_H_*/ -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_common.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_common.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_common.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_common.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_common.h linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_common.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_common.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_common.h 2014-04-24 15:35:02.889551471 +0200 @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -19245,9 +19311,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_common.h + + +#endif // VCHI_COMMON_H_ -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi.h linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi.h 2014-04-24 15:35:02.889551471 +0200 @@ -0,0 +1,373 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -19622,9 +19688,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi.h linux-r +#endif /* VCHI_H_ */ + +/****************************** End of file **********************************/ -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_mh.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_mh.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_mh.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_mh.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_mh.h linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_mh.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_mh.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_mh.h 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -19668,9 +19734,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_mh.h linu +#define VCHI_MEM_HANDLE_INVALID 0 + +#endif -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,561 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -20233,9 +20299,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_283 + + kfree(pagelist); +} -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -20279,9 +20345,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_283 +#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1 + +#endif /* VCHIQ_2835_H */ -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,2813 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -23096,9 +23162,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm +module_exit(vchiq_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Broadcom Corporation"); -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -23312,9 +23378,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm + + +#endif /* VCHIQ_ARM_H */ -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -23353,9 +23419,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_bui +const char *vchiq_get_build_version(void); +const char *vchiq_get_build_time(void); +const char *vchiq_get_build_date(void); -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -23417,9 +23483,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg +#endif + +#endif /* VCHIQ_CFG_H */ -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -23540,9 +23606,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_con + mutex_unlock(&g_connected_mutex); +} +EXPORT_SYMBOL(vchiq_add_connected_callback); -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h 2014-03-11 17:51:16.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h 2014-04-24 16:04:36.831095364 +0200 @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -23594,9 +23660,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_con +void vchiq_call_connected_callbacks(void); + +#endif /* VCHIQ_CONNECTED_H */ -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,3824 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -27422,9 +27488,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cor + numBytes = 0; + } +} -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,706 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -28132,9 +28198,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cor + size_t numBytes); + +#endif -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion 2014-03-11 17:51:16.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion 2014-04-24 16:04:36.831095364 +0200 @@ -0,0 +1,87 @@ +#!/usr/bin/perl -w + @@ -28223,9 +28289,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_gen + return vchiq_build_time; +} +EOF -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h 2014-03-11 17:51:16.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h 2014-04-24 16:04:36.831095364 +0200 @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -28267,9 +28333,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h l +#include "vchiq_util.h" + +#endif -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,188 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -28459,9 +28525,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if. + short *peer_version); + +#endif /* VCHIQ_IF_H */ -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,129 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -28592,9 +28658,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioc +#define VCHIQ_IOC_MAX 15 + +#endif -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,456 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -29052,9 +29118,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ker + + return status; +} -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -29127,9 +29193,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_mem + const VCHIQ_PLATFORM_DATA_T * platform_data); + +#endif -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -29189,9 +29255,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pag +} FRAGMENTS_T; + +#endif /* VCHIQ_PAGELIST_H */ -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c 2014-03-11 17:51:16.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c 2014-04-24 16:04:36.831095364 +0200 @@ -0,0 +1,253 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -29446,9 +29512,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pro +} + +#endif -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,828 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -30278,9 +30344,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shi + return ret; +} +EXPORT_SYMBOL(vchi_service_release); -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,151 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -30433,9 +30499,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_uti + + return header; +} -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h 2014-03-11 17:51:16.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h 2014-04-24 16:04:36.831095364 +0200 @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -30518,9 +30584,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_uti +extern VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue); + +#endif -diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c ---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c 2014-03-11 17:32:37.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c +--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c 2014-04-24 15:35:02.893551516 +0200 @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -30581,9 +30647,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ver +{ + return vchiq_build_time; +} -diff -Nur linux-3.12.13/drivers/misc/vc04_services/Kconfig linux-raspberry-pi/drivers/misc/vc04_services/Kconfig ---- linux-3.12.13/drivers/misc/vc04_services/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/Kconfig 2014-03-11 17:51:16.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/Kconfig linux-rpi/drivers/misc/vc04_services/Kconfig +--- linux-3.12.18/drivers/misc/vc04_services/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/Kconfig 2014-04-24 16:04:36.831095364 +0200 @@ -0,0 +1,9 @@ +config BCM2708_VCHIQ + tristate "Videocore VCHIQ" @@ -30594,9 +30660,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/Kconfig linux-raspberry-pi/dr + BCM2708 family of products. + Defaults to Y when the Broadcom Videocore services + are included in the build, N otherwise. -diff -Nur linux-3.12.13/drivers/misc/vc04_services/Makefile linux-raspberry-pi/drivers/misc/vc04_services/Makefile ---- linux-3.12.13/drivers/misc/vc04_services/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/misc/vc04_services/Makefile 2014-03-11 17:51:16.000000000 +0100 +diff -Nur linux-3.12.18/drivers/misc/vc04_services/Makefile linux-rpi/drivers/misc/vc04_services/Makefile +--- linux-3.12.18/drivers/misc/vc04_services/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/misc/vc04_services/Makefile 2014-04-24 16:04:36.831095364 +0200 @@ -0,0 +1,17 @@ +ifeq ($(CONFIG_MACH_BCM2708),y) + @@ -30612,12 +30678,12 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/Makefile linux-raspberry-pi/d + interface/vchiq_arm/vchiq_util.o \ + interface/vchiq_arm/vchiq_connected.o \ + -+EXTRA_CFLAGS += -DVCOS_VERIFY_BKPTS=1 -Idrivers/misc/vc04_services -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 ++ccflags-y += -DVCOS_VERIFY_BKPTS=1 -Idrivers/misc/vc04_services -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 + +endif -diff -Nur linux-3.12.13/drivers/mmc/card/block.c linux-raspberry-pi/drivers/mmc/card/block.c ---- linux-3.12.13/drivers/mmc/card/block.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/mmc/card/block.c 2014-03-11 17:51:16.000000000 +0100 +diff -Nur linux-3.12.18/drivers/mmc/card/block.c linux-rpi/drivers/mmc/card/block.c +--- linux-3.12.18/drivers/mmc/card/block.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/mmc/card/block.c 2014-04-24 16:04:36.835095403 +0200 @@ -1361,7 +1361,7 @@ brq->data.blocks = 1; } @@ -30627,9 +30693,9 @@ diff -Nur linux-3.12.13/drivers/mmc/card/block.c linux-raspberry-pi/drivers/mmc/ /* SPI multiblock writes terminate using a special * token, not a STOP_TRANSMISSION request. */ -diff -Nur linux-3.12.13/drivers/mmc/core/sd.c linux-raspberry-pi/drivers/mmc/core/sd.c ---- linux-3.12.13/drivers/mmc/core/sd.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/mmc/core/sd.c 2014-03-11 17:51:16.000000000 +0100 +diff -Nur linux-3.12.18/drivers/mmc/core/sd.c linux-rpi/drivers/mmc/core/sd.c +--- linux-3.12.18/drivers/mmc/core/sd.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/mmc/core/sd.c 2014-04-24 16:04:36.839095442 +0200 @@ -14,6 +14,8 @@ #include <linux/sizes.h> #include <linux/slab.h> @@ -30784,9 +30850,9 @@ diff -Nur linux-3.12.13/drivers/mmc/core/sd.c linux-raspberry-pi/drivers/mmc/cor return err; /* -diff -Nur linux-3.12.13/drivers/mmc/host/Kconfig linux-raspberry-pi/drivers/mmc/host/Kconfig ---- linux-3.12.13/drivers/mmc/host/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/mmc/host/Kconfig 2014-03-11 17:51:16.000000000 +0100 +diff -Nur linux-3.12.18/drivers/mmc/host/Kconfig linux-rpi/drivers/mmc/host/Kconfig +--- linux-3.12.18/drivers/mmc/host/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/mmc/host/Kconfig 2014-04-24 16:04:36.839095442 +0200 @@ -260,6 +260,27 @@ If you have a controller with this interface, say Y or M here. @@ -30815,9 +30881,9 @@ diff -Nur linux-3.12.13/drivers/mmc/host/Kconfig linux-raspberry-pi/drivers/mmc/ config MMC_SDHCI_BCM2835 tristate "SDHCI platform support for the BCM2835 SD/MMC Controller" depends on ARCH_BCM2835 -diff -Nur linux-3.12.13/drivers/mmc/host/Makefile linux-raspberry-pi/drivers/mmc/host/Makefile ---- linux-3.12.13/drivers/mmc/host/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/mmc/host/Makefile 2014-03-11 17:51:16.000000000 +0100 +diff -Nur linux-3.12.18/drivers/mmc/host/Makefile linux-rpi/drivers/mmc/host/Makefile +--- linux-3.12.18/drivers/mmc/host/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/mmc/host/Makefile 2014-04-24 16:04:36.839095442 +0200 @@ -15,6 +15,7 @@ obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o @@ -30826,9 +30892,9 @@ diff -Nur linux-3.12.13/drivers/mmc/host/Makefile linux-raspberry-pi/drivers/mmc obj-$(CONFIG_MMC_WBSD) += wbsd.o obj-$(CONFIG_MMC_AU1X) += au1xmmc.o obj-$(CONFIG_MMC_OMAP) += omap.o -diff -Nur linux-3.12.13/drivers/mmc/host/sdhci-bcm2708.c linux-raspberry-pi/drivers/mmc/host/sdhci-bcm2708.c ---- linux-3.12.13/drivers/mmc/host/sdhci-bcm2708.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/mmc/host/sdhci-bcm2708.c 2014-03-11 17:51:21.000000000 +0100 +diff -Nur linux-3.12.18/drivers/mmc/host/sdhci-bcm2708.c linux-rpi/drivers/mmc/host/sdhci-bcm2708.c +--- linux-3.12.18/drivers/mmc/host/sdhci-bcm2708.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/mmc/host/sdhci-bcm2708.c 2014-04-24 16:04:36.847095519 +0200 @@ -0,0 +1,1410 @@ +/* + * sdhci-bcm2708.c Support for SDHCI device on BCM2708 @@ -31095,7 +31161,7 @@ diff -Nur linux-3.12.13/drivers/mmc/host/sdhci-bcm2708.c linux-raspberry-pi/driv + { + /* we must have waited at least this many ns: */ + unsigned int ns_wait = HPTIME_CLK_NS * -+ (last_write_hpt - now - 1); ++ (now - last_write_hpt - 1); + if (ns_wait < ns_2clk) + ndelay(ns_2clk - ns_wait); + } @@ -31909,7 +31975,7 @@ diff -Nur linux-3.12.13/drivers/mmc/host/sdhci-bcm2708.c linux-raspberry-pi/driv + int ret = 0; + + if (host->mmc) { -+ ret = mmc_suspend_host(host->mmc); ++ //ret = mmc_suspend_host(host->mmc); + } + + return ret; @@ -31922,7 +31988,7 @@ diff -Nur linux-3.12.13/drivers/mmc/host/sdhci-bcm2708.c linux-raspberry-pi/driv + int ret = 0; + + if (host->mmc) { -+ ret = mmc_resume_host(host->mmc); ++ //ret = mmc_resume_host(host->mmc); + } + + return ret; @@ -32240,9 +32306,9 @@ diff -Nur linux-3.12.13/drivers/mmc/host/sdhci-bcm2708.c linux-raspberry-pi/driv +MODULE_PARM_DESC(extra_messages, "Enable more sdcard warning messages"); + + -diff -Nur linux-3.12.13/drivers/mmc/host/sdhci.c linux-raspberry-pi/drivers/mmc/host/sdhci.c ---- linux-3.12.13/drivers/mmc/host/sdhci.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/mmc/host/sdhci.c 2014-03-11 17:51:21.000000000 +0100 +diff -Nur linux-3.12.18/drivers/mmc/host/sdhci.c linux-rpi/drivers/mmc/host/sdhci.c +--- linux-3.12.18/drivers/mmc/host/sdhci.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/mmc/host/sdhci.c 2014-04-24 16:04:36.851095558 +0200 @@ -28,6 +28,7 @@ #include <linux/mmc/mmc.h> #include <linux/mmc/host.h> @@ -33084,9 +33150,9 @@ diff -Nur linux-3.12.13/drivers/mmc/host/sdhci.c linux-raspberry-pi/drivers/mmc/ } sdhci_disable_card_detection(host); -diff -Nur linux-3.12.13/drivers/mmc/host/sdhci.h linux-raspberry-pi/drivers/mmc/host/sdhci.h ---- linux-3.12.13/drivers/mmc/host/sdhci.h 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/mmc/host/sdhci.h 2014-03-11 17:51:21.000000000 +0100 +diff -Nur linux-3.12.18/drivers/mmc/host/sdhci.h linux-rpi/drivers/mmc/host/sdhci.h +--- linux-3.12.18/drivers/mmc/host/sdhci.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/mmc/host/sdhci.h 2014-04-24 16:04:36.851095558 +0200 @@ -289,6 +289,18 @@ void (*platform_reset_enter)(struct sdhci_host *host, u8 mask); void (*platform_reset_exit)(struct sdhci_host *host, u8 mask); @@ -33145,9 +33211,234 @@ diff -Nur linux-3.12.13/drivers/mmc/host/sdhci.h linux-raspberry-pi/drivers/mmc/ + + #endif /* __SDHCI_HW_H */ -diff -Nur linux-3.12.13/drivers/net/usb/smsc95xx.c linux-raspberry-pi/drivers/net/usb/smsc95xx.c ---- linux-3.12.13/drivers/net/usb/smsc95xx.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/net/usb/smsc95xx.c 2014-03-11 17:51:24.000000000 +0100 +diff -Nur linux-3.12.18/drivers/net/bonding/bond_alb.c linux-rpi/drivers/net/bonding/bond_alb.c +--- linux-3.12.18/drivers/net/bonding/bond_alb.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/net/bonding/bond_alb.c 2014-04-24 16:04:36.879095829 +0200 +@@ -694,7 +694,7 @@ + client_info->ntt = 0; + } + +- if (vlan_get_tag(skb, &client_info->vlan_id)) ++ if (!vlan_get_tag(skb, &client_info->vlan_id)) + client_info->vlan_id = 0; + + if (!client_info->assigned) { +diff -Nur linux-3.12.18/drivers/net/ethernet/broadcom/bnx2.c linux-rpi/drivers/net/ethernet/broadcom/bnx2.c +--- linux-3.12.18/drivers/net/ethernet/broadcom/bnx2.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/net/ethernet/broadcom/bnx2.c 2014-04-24 16:04:36.911096138 +0200 +@@ -2490,7 +2490,6 @@ + + bp->fw_wr_seq++; + msg_data |= bp->fw_wr_seq; +- bp->fw_last_msg = msg_data; + + bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data); + +@@ -3983,23 +3982,8 @@ + wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; + } + +- if (!(bp->flags & BNX2_FLAG_NO_WOL)) { +- u32 val; +- +- wol_msg |= BNX2_DRV_MSG_DATA_WAIT3; +- if (bp->fw_last_msg || BNX2_CHIP(bp) != BNX2_CHIP_5709) { +- bnx2_fw_sync(bp, wol_msg, 1, 0); +- return; +- } +- /* Tell firmware not to power down the PHY yet, otherwise +- * the chip will take a long time to respond to MMIO reads. +- */ +- val = bnx2_shmem_rd(bp, BNX2_PORT_FEATURE); +- bnx2_shmem_wr(bp, BNX2_PORT_FEATURE, +- val | BNX2_PORT_FEATURE_ASF_ENABLED); +- bnx2_fw_sync(bp, wol_msg, 1, 0); +- bnx2_shmem_wr(bp, BNX2_PORT_FEATURE, val); +- } ++ if (!(bp->flags & BNX2_FLAG_NO_WOL)) ++ bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg, 1, 0); + + } + +@@ -4031,22 +4015,9 @@ + + if (bp->wol) + pci_set_power_state(bp->pdev, PCI_D3hot); +- break; +- +- } +- if (!bp->fw_last_msg && BNX2_CHIP(bp) == BNX2_CHIP_5709) { +- u32 val; +- +- /* Tell firmware not to power down the PHY yet, +- * otherwise the other port may not respond to +- * MMIO reads. +- */ +- val = bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION); +- val &= ~BNX2_CONDITION_PM_STATE_MASK; +- val |= BNX2_CONDITION_PM_STATE_UNPREP; +- bnx2_shmem_wr(bp, BNX2_BC_STATE_CONDITION, val); ++ } else { ++ pci_set_power_state(bp->pdev, PCI_D3hot); + } +- pci_set_power_state(bp->pdev, PCI_D3hot); + + /* No more memory access after this point until + * device is brought back to D0. +diff -Nur linux-3.12.18/drivers/net/ethernet/broadcom/bnx2.h linux-rpi/drivers/net/ethernet/broadcom/bnx2.h +--- linux-3.12.18/drivers/net/ethernet/broadcom/bnx2.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/net/ethernet/broadcom/bnx2.h 2014-04-24 16:04:36.915096177 +0200 +@@ -6890,7 +6890,6 @@ + + u16 fw_wr_seq; + u16 fw_drv_pulse_wr_seq; +- u32 fw_last_msg; + + int rx_max_ring; + int rx_ring_size; +@@ -7397,10 +7396,6 @@ + #define BNX2_CONDITION_MFW_RUN_NCSI 0x00006000 + #define BNX2_CONDITION_MFW_RUN_NONE 0x0000e000 + #define BNX2_CONDITION_MFW_RUN_MASK 0x0000e000 +-#define BNX2_CONDITION_PM_STATE_MASK 0x00030000 +-#define BNX2_CONDITION_PM_STATE_FULL 0x00030000 +-#define BNX2_CONDITION_PM_STATE_PREP 0x00020000 +-#define BNX2_CONDITION_PM_STATE_UNPREP 0x00010000 + + #define BNX2_BC_STATE_DEBUG_CMD 0x1dc + #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE 0x42440000 +diff -Nur linux-3.12.18/drivers/net/ethernet/broadcom/tg3.c linux-rpi/drivers/net/ethernet/broadcom/tg3.c +--- linux-3.12.18/drivers/net/ethernet/broadcom/tg3.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/net/ethernet/broadcom/tg3.c 2014-04-24 16:04:36.935096370 +0200 +@@ -17480,6 +17480,8 @@ + + tg3_init_bufmgr_config(tp); + ++ features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; ++ + /* 5700 B0 chips do not support checksumming correctly due + * to hardware bugs. + */ +@@ -17511,8 +17513,7 @@ + features |= NETIF_F_TSO_ECN; + } + +- dev->features |= features | NETIF_F_HW_VLAN_CTAG_TX | +- NETIF_F_HW_VLAN_CTAG_RX; ++ dev->features |= features; + dev->vlan_features |= features; + + /* +diff -Nur linux-3.12.18/drivers/net/ethernet/freescale/fec_main.c linux-rpi/drivers/net/ethernet/freescale/fec_main.c +--- linux-3.12.18/drivers/net/ethernet/freescale/fec_main.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/net/ethernet/freescale/fec_main.c 2014-04-24 16:04:37.143098381 +0200 +@@ -525,6 +525,13 @@ + /* Clear any outstanding interrupt. */ + writel(0xffc00000, fep->hwp + FEC_IEVENT); + ++ /* Setup multicast filter. */ ++ set_multicast_list(ndev); ++#ifndef CONFIG_M5272 ++ writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); ++ writel(0, fep->hwp + FEC_HASH_TABLE_LOW); ++#endif ++ + /* Set maximum receive buffer size. */ + writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE); + +@@ -645,13 +652,6 @@ + + writel(rcntl, fep->hwp + FEC_R_CNTRL); + +- /* Setup multicast filter. */ +- set_multicast_list(ndev); +-#ifndef CONFIG_M5272 +- writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); +- writel(0, fep->hwp + FEC_HASH_TABLE_LOW); +-#endif +- + if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { + /* enable ENET endian swap */ + ecntl |= (1 << 8); +diff -Nur linux-3.12.18/drivers/net/ethernet/micrel/ks8851.c linux-rpi/drivers/net/ethernet/micrel/ks8851.c +--- linux-3.12.18/drivers/net/ethernet/micrel/ks8851.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/net/ethernet/micrel/ks8851.c 2014-04-24 15:35:03.105553878 +0200 +@@ -23,7 +23,6 @@ + #include <linux/crc32.h> + #include <linux/mii.h> + #include <linux/eeprom_93cx6.h> +-#include <linux/regulator/consumer.h> + + #include <linux/spi/spi.h> + +@@ -84,7 +83,6 @@ + * @rc_rxqcr: Cached copy of KS_RXQCR. + * @eeprom_size: Companion eeprom size in Bytes, 0 if no eeprom + * @eeprom: 93CX6 EEPROM state for accessing on-board EEPROM. +- * @vdd_reg: Optional regulator supplying the chip + * + * The @lock ensures that the chip is protected when certain operations are + * in progress. When the read or write packet transfer is in progress, most +@@ -132,7 +130,6 @@ + struct spi_transfer spi_xfer2[2]; + + struct eeprom_93cx6 eeprom; +- struct regulator *vdd_reg; + }; + + static int msg_enable; +@@ -1417,21 +1414,6 @@ + ks->spidev = spi; + ks->tx_space = 6144; + +- ks->vdd_reg = regulator_get_optional(&spi->dev, "vdd"); +- if (IS_ERR(ks->vdd_reg)) { +- ret = PTR_ERR(ks->vdd_reg); +- if (ret == -EPROBE_DEFER) +- goto err_reg; +- } else { +- ret = regulator_enable(ks->vdd_reg); +- if (ret) { +- dev_err(&spi->dev, "regulator enable fail: %d\n", +- ret); +- goto err_reg_en; +- } +- } +- +- + mutex_init(&ks->lock); + spin_lock_init(&ks->statelock); + +@@ -1526,14 +1508,8 @@ + err_netdev: + free_irq(ndev->irq, ks); + +-err_irq: + err_id: +- if (!IS_ERR(ks->vdd_reg)) +- regulator_disable(ks->vdd_reg); +-err_reg_en: +- if (!IS_ERR(ks->vdd_reg)) +- regulator_put(ks->vdd_reg); +-err_reg: ++err_irq: + free_netdev(ndev); + return ret; + } +@@ -1547,10 +1523,6 @@ + + unregister_netdev(priv->netdev); + free_irq(spi->irq, priv); +- if (!IS_ERR(priv->vdd_reg)) { +- regulator_disable(priv->vdd_reg); +- regulator_put(priv->vdd_reg); +- } + free_netdev(priv->netdev); + + return 0; +diff -Nur linux-3.12.18/drivers/net/usb/smsc95xx.c linux-rpi/drivers/net/usb/smsc95xx.c +--- linux-3.12.18/drivers/net/usb/smsc95xx.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/net/usb/smsc95xx.c 2014-04-24 15:35:03.209555036 +0200 @@ -61,6 +61,7 @@ #define SUSPEND_SUSPEND3 (0x08) #define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \ @@ -33227,9 +33518,448 @@ diff -Nur linux-3.12.13/drivers/net/usb/smsc95xx.c linux-raspberry-pi/drivers/ne /* try reading mac address from EEPROM */ if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, dev->net->dev_addr) == 0) { -diff -Nur linux-3.12.13/drivers/spi/Kconfig linux-raspberry-pi/drivers/spi/Kconfig ---- linux-3.12.13/drivers/spi/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/spi/Kconfig 2014-03-11 17:51:25.000000000 +0100 +diff -Nur linux-3.12.18/drivers/net/usb/usbnet.c linux-rpi/drivers/net/usb/usbnet.c +--- linux-3.12.18/drivers/net/usb/usbnet.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/net/usb/usbnet.c 2014-04-24 16:04:37.631103100 +0200 +@@ -753,12 +753,14 @@ + // precondition: never called in_interrupt + static void usbnet_terminate_urbs(struct usbnet *dev) + { ++ DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup); + DECLARE_WAITQUEUE(wait, current); + int temp; + + /* ensure there are no more active urbs */ +- add_wait_queue(&dev->wait, &wait); ++ add_wait_queue(&unlink_wakeup, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); ++ dev->wait = &unlink_wakeup; + temp = unlink_urbs(dev, &dev->txq) + + unlink_urbs(dev, &dev->rxq); + +@@ -772,14 +774,15 @@ + "waited for %d urb completions\n", temp); + } + set_current_state(TASK_RUNNING); +- remove_wait_queue(&dev->wait, &wait); ++ dev->wait = NULL; ++ remove_wait_queue(&unlink_wakeup, &wait); + } + + int usbnet_stop (struct net_device *net) + { + struct usbnet *dev = netdev_priv(net); + struct driver_info *info = dev->driver_info; +- int retval, pm; ++ int retval; + + clear_bit(EVENT_DEV_OPEN, &dev->flags); + netif_stop_queue (net); +@@ -789,8 +792,6 @@ + net->stats.rx_packets, net->stats.tx_packets, + net->stats.rx_errors, net->stats.tx_errors); + +- /* to not race resume */ +- pm = usb_autopm_get_interface(dev->intf); + /* allow minidriver to stop correctly (wireless devices to turn off + * radio etc) */ + if (info->stop) { +@@ -817,9 +818,6 @@ + dev->flags = 0; + del_timer_sync (&dev->delay); + tasklet_kill (&dev->bh); +- if (!pm) +- usb_autopm_put_interface(dev->intf); +- + if (info->manage_power && + !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags)) + info->manage_power(dev, 0); +@@ -1440,12 +1438,11 @@ + /* restart RX again after disabling due to high error rate */ + clear_bit(EVENT_RX_KILL, &dev->flags); + +- /* waiting for all pending urbs to complete? +- * only then can we forgo submitting anew +- */ +- if (waitqueue_active(&dev->wait)) { +- if (dev->txq.qlen + dev->rxq.qlen + dev->done.qlen == 0) +- wake_up_all(&dev->wait); ++ // waiting for all pending urbs to complete? ++ if (dev->wait) { ++ if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) { ++ wake_up (dev->wait); ++ } + + // or are we maybe short a few urbs? + } else if (netif_running (dev->net) && +@@ -1584,7 +1581,6 @@ + dev->driver_name = name; + dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV + | NETIF_MSG_PROBE | NETIF_MSG_LINK); +- init_waitqueue_head(&dev->wait); + skb_queue_head_init (&dev->rxq); + skb_queue_head_init (&dev->txq); + skb_queue_head_init (&dev->done); +@@ -1796,10 +1792,9 @@ + spin_unlock_irq(&dev->txq.lock); + + if (test_bit(EVENT_DEV_OPEN, &dev->flags)) { +- /* handle remote wakeup ASAP +- * we cannot race against stop +- */ +- if (netif_device_present(dev->net) && ++ /* handle remote wakeup ASAP */ ++ if (!dev->wait && ++ netif_device_present(dev->net) && + !timer_pending(&dev->delay) && + !test_bit(EVENT_RX_HALT, &dev->flags)) + rx_alloc_submit(dev, GFP_NOIO); +diff -Nur linux-3.12.18/drivers/net/vxlan.c linux-rpi/drivers/net/vxlan.c +--- linux-3.12.18/drivers/net/vxlan.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/net/vxlan.c 2014-04-24 16:04:37.631103100 +0200 +@@ -781,9 +781,6 @@ + if (err) + return err; + +- if (vxlan->default_dst.remote_ip.sa.sa_family != ip.sa.sa_family) +- return -EAFNOSUPPORT; +- + spin_lock_bh(&vxlan->hash_lock); + err = vxlan_fdb_create(vxlan, addr, &ip, ndm->ndm_state, flags, + port, vni, ifindex, ndm->ndm_flags); +@@ -1215,9 +1212,6 @@ + + neigh_release(n); + +- if (reply == NULL) +- goto out; +- + skb_reset_mac_header(reply); + __skb_pull(reply, skb_network_offset(reply)); + reply->ip_summed = CHECKSUM_UNNECESSARY; +@@ -1239,103 +1233,15 @@ + } + + #if IS_ENABLED(CONFIG_IPV6) +- +-static struct sk_buff *vxlan_na_create(struct sk_buff *request, +- struct neighbour *n, bool isrouter) +-{ +- struct net_device *dev = request->dev; +- struct sk_buff *reply; +- struct nd_msg *ns, *na; +- struct ipv6hdr *pip6; +- u8 *daddr; +- int na_olen = 8; /* opt hdr + ETH_ALEN for target */ +- int ns_olen; +- int i, len; +- +- if (dev == NULL) +- return NULL; +- +- len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) + +- sizeof(*na) + na_olen + dev->needed_tailroom; +- reply = alloc_skb(len, GFP_ATOMIC); +- if (reply == NULL) +- return NULL; +- +- reply->protocol = htons(ETH_P_IPV6); +- reply->dev = dev; +- skb_reserve(reply, LL_RESERVED_SPACE(request->dev)); +- skb_push(reply, sizeof(struct ethhdr)); +- skb_set_mac_header(reply, 0); +- +- ns = (struct nd_msg *)skb_transport_header(request); +- +- daddr = eth_hdr(request)->h_source; +- ns_olen = request->len - skb_transport_offset(request) - sizeof(*ns); +- for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) { +- if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) { +- daddr = ns->opt + i + sizeof(struct nd_opt_hdr); +- break; +- } +- } +- +- /* Ethernet header */ +- memcpy(eth_hdr(reply)->h_dest, daddr, ETH_ALEN); +- memcpy(eth_hdr(reply)->h_source, n->ha, ETH_ALEN); +- eth_hdr(reply)->h_proto = htons(ETH_P_IPV6); +- reply->protocol = htons(ETH_P_IPV6); +- +- skb_pull(reply, sizeof(struct ethhdr)); +- skb_set_network_header(reply, 0); +- skb_put(reply, sizeof(struct ipv6hdr)); +- +- /* IPv6 header */ +- +- pip6 = ipv6_hdr(reply); +- memset(pip6, 0, sizeof(struct ipv6hdr)); +- pip6->version = 6; +- pip6->priority = ipv6_hdr(request)->priority; +- pip6->nexthdr = IPPROTO_ICMPV6; +- pip6->hop_limit = 255; +- pip6->daddr = ipv6_hdr(request)->saddr; +- pip6->saddr = *(struct in6_addr *)n->primary_key; +- +- skb_pull(reply, sizeof(struct ipv6hdr)); +- skb_set_transport_header(reply, 0); +- +- na = (struct nd_msg *)skb_put(reply, sizeof(*na) + na_olen); +- +- /* Neighbor Advertisement */ +- memset(na, 0, sizeof(*na)+na_olen); +- na->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; +- na->icmph.icmp6_router = isrouter; +- na->icmph.icmp6_override = 1; +- na->icmph.icmp6_solicited = 1; +- na->target = ns->target; +- memcpy(&na->opt[2], n->ha, ETH_ALEN); +- na->opt[0] = ND_OPT_TARGET_LL_ADDR; +- na->opt[1] = na_olen >> 3; +- +- na->icmph.icmp6_cksum = csum_ipv6_magic(&pip6->saddr, +- &pip6->daddr, sizeof(*na)+na_olen, IPPROTO_ICMPV6, +- csum_partial(na, sizeof(*na)+na_olen, 0)); +- +- pip6->payload_len = htons(sizeof(*na)+na_olen); +- +- skb_push(reply, sizeof(struct ipv6hdr)); +- +- reply->ip_summed = CHECKSUM_UNNECESSARY; +- +- return reply; +-} +- + static int neigh_reduce(struct net_device *dev, struct sk_buff *skb) + { + struct vxlan_dev *vxlan = netdev_priv(dev); +- struct nd_msg *msg; ++ struct neighbour *n; ++ union vxlan_addr ipa; + const struct ipv6hdr *iphdr; + const struct in6_addr *saddr, *daddr; +- struct neighbour *n; +- struct inet6_dev *in6_dev; ++ struct nd_msg *msg; ++ struct inet6_dev *in6_dev = NULL; + + in6_dev = __in6_dev_get(dev); + if (!in6_dev) +@@ -1348,20 +1254,19 @@ + saddr = &iphdr->saddr; + daddr = &iphdr->daddr; + ++ if (ipv6_addr_loopback(daddr) || ++ ipv6_addr_is_multicast(daddr)) ++ goto out; ++ + msg = (struct nd_msg *)skb_transport_header(skb); + if (msg->icmph.icmp6_code != 0 || + msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION) + goto out; + +- if (ipv6_addr_loopback(daddr) || +- ipv6_addr_is_multicast(&msg->target)) +- goto out; +- +- n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, dev); ++ n = neigh_lookup(ipv6_stub->nd_tbl, daddr, dev); + + if (n) { + struct vxlan_fdb *f; +- struct sk_buff *reply; + + if (!(n->nud_state & NUD_CONNECTED)) { + neigh_release(n); +@@ -1375,23 +1280,13 @@ + goto out; + } + +- reply = vxlan_na_create(skb, n, +- !!(f ? f->flags & NTF_ROUTER : 0)); +- ++ ipv6_stub->ndisc_send_na(dev, n, saddr, &msg->target, ++ !!in6_dev->cnf.forwarding, ++ true, false, false); + neigh_release(n); +- +- if (reply == NULL) +- goto out; +- +- if (netif_rx_ni(reply) == NET_RX_DROP) +- dev->stats.rx_dropped++; +- + } else if (vxlan->flags & VXLAN_F_L3MISS) { +- union vxlan_addr ipa = { +- .sin6.sin6_addr = msg->target, +- .sa.sa_family = AF_INET6, +- }; +- ++ ipa.sin6.sin6_addr = *daddr; ++ ipa.sa.sa_family = AF_INET6; + vxlan_ip_miss(dev, &ipa); + } + +@@ -2488,10 +2383,9 @@ + vni = nla_get_u32(data[IFLA_VXLAN_ID]); + dst->remote_vni = vni; + +- /* Unless IPv6 is explicitly requested, assume IPv4 */ +- dst->remote_ip.sa.sa_family = AF_INET; + if (data[IFLA_VXLAN_GROUP]) { + dst->remote_ip.sin.sin_addr.s_addr = nla_get_be32(data[IFLA_VXLAN_GROUP]); ++ dst->remote_ip.sa.sa_family = AF_INET; + } else if (data[IFLA_VXLAN_GROUP6]) { + if (!IS_ENABLED(CONFIG_IPV6)) + return -EPFNOSUPPORT; +diff -Nur linux-3.12.18/drivers/net/xen-netback/common.h linux-rpi/drivers/net/xen-netback/common.h +--- linux-3.12.18/drivers/net/xen-netback/common.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/net/xen-netback/common.h 2014-04-24 16:04:37.763104376 +0200 +@@ -102,11 +102,6 @@ + domid_t domid; + unsigned int handle; + +- /* Is this interface disabled? True when backend discovers +- * frontend is rogue. +- */ +- bool disabled; +- + /* Use NAPI for guest TX */ + struct napi_struct napi; + /* When feature-split-event-channels = 0, tx_irq = rx_irq. */ +diff -Nur linux-3.12.18/drivers/net/xen-netback/interface.c linux-rpi/drivers/net/xen-netback/interface.c +--- linux-3.12.18/drivers/net/xen-netback/interface.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/net/xen-netback/interface.c 2014-04-24 16:04:37.763104376 +0200 +@@ -66,15 +66,6 @@ + struct xenvif *vif = container_of(napi, struct xenvif, napi); + int work_done; + +- /* This vif is rogue, we pretend we've there is nothing to do +- * for this vif to deschedule it from NAPI. But this interface +- * will be turned off in thread context later. +- */ +- if (unlikely(vif->disabled)) { +- napi_complete(napi); +- return 0; +- } +- + work_done = xenvif_tx_action(vif, budget); + + if (work_done < budget) { +@@ -318,8 +309,6 @@ + vif->csum = 1; + vif->dev = dev; + +- vif->disabled = false; +- + vif->credit_bytes = vif->remaining_credit = ~0UL; + vif->credit_usec = 0UL; + init_timer(&vif->credit_timeout); +diff -Nur linux-3.12.18/drivers/net/xen-netback/netback.c linux-rpi/drivers/net/xen-netback/netback.c +--- linux-3.12.18/drivers/net/xen-netback/netback.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/net/xen-netback/netback.c 2014-04-24 16:04:37.763104376 +0200 +@@ -206,8 +206,8 @@ + * into multiple copies tend to give large frags their + * own buffers as before. + */ +- BUG_ON(size > MAX_BUFFER_OFFSET); +- if ((offset + size > MAX_BUFFER_OFFSET) && offset && !head) ++ if ((offset + size > MAX_BUFFER_OFFSET) && ++ (size <= MAX_BUFFER_OFFSET) && offset && !head) + return true; + + return false; +@@ -731,8 +731,7 @@ + static void xenvif_fatal_tx_err(struct xenvif *vif) + { + netdev_err(vif->dev, "fatal error; disabling device\n"); +- vif->disabled = true; +- xenvif_kick_thread(vif); ++ xenvif_carrier_off(vif); + } + + static int xenvif_count_requests(struct xenvif *vif, +@@ -1243,7 +1242,7 @@ + vif->tx.sring->req_prod, vif->tx.req_cons, + XEN_NETIF_TX_RING_SIZE); + xenvif_fatal_tx_err(vif); +- break; ++ continue; + } + + RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do); +@@ -1643,18 +1642,7 @@ + while (!kthread_should_stop()) { + wait_event_interruptible(vif->wq, + rx_work_todo(vif) || +- vif->disabled || + kthread_should_stop()); +- +- /* 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, +- * but we cannot disable the interface in softirq +- * context so we defer it here. +- */ +- if (unlikely(vif->disabled && netif_carrier_ok(vif->dev))) +- xenvif_carrier_off(vif); +- + if (kthread_should_stop()) + break; + +diff -Nur linux-3.12.18/drivers/pci/host/pci-mvebu.c linux-rpi/drivers/pci/host/pci-mvebu.c +--- linux-3.12.18/drivers/pci/host/pci-mvebu.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/pci/host/pci-mvebu.c 2014-04-24 16:04:37.847105188 +0200 +@@ -866,23 +866,11 @@ + continue; + } + +- port->clk = of_clk_get_by_name(child, NULL); +- if (IS_ERR(port->clk)) { +- dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n", +- port->port, port->lane); +- continue; +- } +- +- ret = clk_prepare_enable(port->clk); +- if (ret) +- continue; +- + port->base = mvebu_pcie_map_registers(pdev, child, port); + if (IS_ERR(port->base)) { + dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n", + port->port, port->lane); + port->base = NULL; +- clk_disable_unprepare(port->clk); + continue; + } + +@@ -898,9 +886,22 @@ + port->port, port->lane); + } + ++ port->clk = of_clk_get_by_name(child, NULL); ++ if (IS_ERR(port->clk)) { ++ dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n", ++ port->port, port->lane); ++ iounmap(port->base); ++ port->haslink = 0; ++ continue; ++ } ++ + port->dn = child; ++ ++ clk_prepare_enable(port->clk); + spin_lock_init(&port->conf_lock); ++ + mvebu_sw_pci_bridge_init(port); ++ + i++; + } + +diff -Nur linux-3.12.18/drivers/spi/Kconfig linux-rpi/drivers/spi/Kconfig +--- linux-3.12.18/drivers/spi/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/spi/Kconfig 2014-04-24 16:04:38.875115127 +0200 @@ -85,6 +85,14 @@ is for the regular SPI controller. Slave mode operation is not also not supported. @@ -33245,9 +33975,9 @@ diff -Nur linux-3.12.13/drivers/spi/Kconfig linux-raspberry-pi/drivers/spi/Kconf config SPI_BFIN5XX tristate "SPI controller driver for ADI Blackfin5xx" depends on BLACKFIN && !BF60x -diff -Nur linux-3.12.13/drivers/spi/Makefile linux-raspberry-pi/drivers/spi/Makefile ---- linux-3.12.13/drivers/spi/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/spi/Makefile 2014-03-11 17:51:25.000000000 +0100 +diff -Nur linux-3.12.18/drivers/spi/Makefile linux-rpi/drivers/spi/Makefile +--- linux-3.12.18/drivers/spi/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/spi/Makefile 2014-04-24 16:04:38.875115127 +0200 @@ -18,6 +18,7 @@ obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o @@ -33256,9 +33986,9 @@ diff -Nur linux-3.12.13/drivers/spi/Makefile linux-raspberry-pi/drivers/spi/Make obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o -diff -Nur linux-3.12.13/drivers/spi/spi-bcm2708.c linux-raspberry-pi/drivers/spi/spi-bcm2708.c ---- linux-3.12.13/drivers/spi/spi-bcm2708.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/spi/spi-bcm2708.c 2014-03-11 17:33:04.000000000 +0100 +diff -Nur linux-3.12.18/drivers/spi/spi-bcm2708.c linux-rpi/drivers/spi/spi-bcm2708.c +--- linux-3.12.18/drivers/spi/spi-bcm2708.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/spi/spi-bcm2708.c 2014-04-24 15:35:03.781561409 +0200 @@ -0,0 +1,626 @@ +/* + * Driver for Broadcom BCM2708 SPI Controllers @@ -33886,9 +34616,9 @@ diff -Nur linux-3.12.13/drivers/spi/spi-bcm2708.c linux-raspberry-pi/drivers/spi +MODULE_AUTHOR("Chris Boot <bootc@bootc.net>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -diff -Nur linux-3.12.13/drivers/staging/media/lirc/Kconfig linux-raspberry-pi/drivers/staging/media/lirc/Kconfig ---- linux-3.12.13/drivers/staging/media/lirc/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/staging/media/lirc/Kconfig 2014-03-11 17:33:05.000000000 +0100 +diff -Nur linux-3.12.18/drivers/staging/media/lirc/Kconfig linux-rpi/drivers/staging/media/lirc/Kconfig +--- linux-3.12.18/drivers/staging/media/lirc/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/staging/media/lirc/Kconfig 2014-04-24 15:35:03.925563013 +0200 @@ -38,6 +38,12 @@ help Driver for Homebrew Parallel Port Receivers @@ -33902,9 +34632,9 @@ diff -Nur linux-3.12.13/drivers/staging/media/lirc/Kconfig linux-raspberry-pi/dr config LIRC_SASEM tristate "Sasem USB IR Remote" depends on LIRC && USB -diff -Nur linux-3.12.13/drivers/staging/media/lirc/lirc_rpi.c linux-raspberry-pi/drivers/staging/media/lirc/lirc_rpi.c ---- linux-3.12.13/drivers/staging/media/lirc/lirc_rpi.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/staging/media/lirc/lirc_rpi.c 2014-03-11 17:33:05.000000000 +0100 +diff -Nur linux-3.12.18/drivers/staging/media/lirc/lirc_rpi.c linux-rpi/drivers/staging/media/lirc/lirc_rpi.c +--- linux-3.12.18/drivers/staging/media/lirc/lirc_rpi.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/staging/media/lirc/lirc_rpi.c 2014-04-24 15:35:03.925563013 +0200 @@ -0,0 +1,693 @@ +/* + * lirc_rpi.c @@ -33988,8 +34718,8 @@ diff -Nur linux-3.12.13/drivers/staging/media/lirc/lirc_rpi.c linux-raspberry-pi +static void send_space(long length); +static void lirc_rpi_exit(void); + -+int valid_gpio_pins[] = { 0, 1, 4, 8, 7, 9, 10, 11, 14, 15, 17, 18, 21, 22, 23, -+ 24, 25 }; ++int valid_gpio_pins[] = { 0, 1, 2, 3, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 21, ++ 22, 23, 24, 25 ,27, 28, 29, 30, 31 }; + +static struct platform_device *lirc_rpi_dev; +static struct timeval lasttv = { 0, 0 }; @@ -34599,9 +35329,9 @@ diff -Nur linux-3.12.13/drivers/staging/media/lirc/lirc_rpi.c linux-raspberry-pi + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging messages"); -diff -Nur linux-3.12.13/drivers/staging/media/lirc/Makefile linux-raspberry-pi/drivers/staging/media/lirc/Makefile ---- linux-3.12.13/drivers/staging/media/lirc/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/staging/media/lirc/Makefile 2014-03-11 17:33:05.000000000 +0100 +diff -Nur linux-3.12.18/drivers/staging/media/lirc/Makefile linux-rpi/drivers/staging/media/lirc/Makefile +--- linux-3.12.18/drivers/staging/media/lirc/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/staging/media/lirc/Makefile 2014-04-24 15:35:03.925563013 +0200 @@ -7,6 +7,7 @@ obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o obj-$(CONFIG_LIRC_IMON) += lirc_imon.o @@ -34610,9 +35340,9 @@ diff -Nur linux-3.12.13/drivers/staging/media/lirc/Makefile linux-raspberry-pi/d obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o obj-$(CONFIG_LIRC_SIR) += lirc_sir.o -diff -Nur linux-3.12.13/drivers/thermal/bcm2835-thermal.c linux-raspberry-pi/drivers/thermal/bcm2835-thermal.c ---- linux-3.12.13/drivers/thermal/bcm2835-thermal.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/thermal/bcm2835-thermal.c 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/thermal/bcm2835-thermal.c linux-rpi/drivers/thermal/bcm2835-thermal.c +--- linux-3.12.18/drivers/thermal/bcm2835-thermal.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/thermal/bcm2835-thermal.c 2014-04-24 15:35:04.089564840 +0200 @@ -0,0 +1,184 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. @@ -34798,9 +35528,9 @@ diff -Nur linux-3.12.13/drivers/thermal/bcm2835-thermal.c linux-raspberry-pi/dri +MODULE_DESCRIPTION("Thermal driver for bcm2835 chip"); + +module_platform_driver(bcm2835_thermal_driver); -diff -Nur linux-3.12.13/drivers/thermal/Kconfig linux-raspberry-pi/drivers/thermal/Kconfig ---- linux-3.12.13/drivers/thermal/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/thermal/Kconfig 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/thermal/Kconfig linux-rpi/drivers/thermal/Kconfig +--- linux-3.12.18/drivers/thermal/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/thermal/Kconfig 2014-04-24 16:04:39.655122669 +0200 @@ -181,6 +181,12 @@ enforce idle time which results in more package C-state residency. The user interface is exposed via generic thermal framework. @@ -34814,9 +35544,9 @@ diff -Nur linux-3.12.13/drivers/thermal/Kconfig linux-raspberry-pi/drivers/therm config X86_PKG_TEMP_THERMAL tristate "X86 package temperature thermal driver" depends on X86_THERMAL_VECTOR -diff -Nur linux-3.12.13/drivers/thermal/Makefile linux-raspberry-pi/drivers/thermal/Makefile ---- linux-3.12.13/drivers/thermal/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/thermal/Makefile 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/thermal/Makefile linux-rpi/drivers/thermal/Makefile +--- linux-3.12.18/drivers/thermal/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/thermal/Makefile 2014-04-24 16:04:39.655122669 +0200 @@ -27,5 +27,6 @@ obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o @@ -34824,9 +35554,9 @@ diff -Nur linux-3.12.13/drivers/thermal/Makefile linux-raspberry-pi/drivers/ther +obj-$(CONFIG_THERMAL_BCM2835) += bcm2835-thermal.o obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ -diff -Nur linux-3.12.13/drivers/tty/serial/amba-pl011.c linux-raspberry-pi/drivers/tty/serial/amba-pl011.c ---- linux-3.12.13/drivers/tty/serial/amba-pl011.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/tty/serial/amba-pl011.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/tty/serial/amba-pl011.c linux-rpi/drivers/tty/serial/amba-pl011.c +--- linux-3.12.18/drivers/tty/serial/amba-pl011.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/tty/serial/amba-pl011.c 2014-04-24 16:04:39.667122784 +0200 @@ -84,7 +84,7 @@ static unsigned int get_fifosize_arm(struct amba_device *dev) @@ -34836,9 +35566,9 @@ diff -Nur linux-3.12.13/drivers/tty/serial/amba-pl011.c linux-raspberry-pi/drive } static struct vendor_data vendor_arm = { -diff -Nur linux-3.12.13/drivers/usb/core/generic.c linux-raspberry-pi/drivers/usb/core/generic.c ---- linux-3.12.13/drivers/usb/core/generic.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/core/generic.c 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/core/generic.c linux-rpi/drivers/usb/core/generic.c +--- linux-3.12.18/drivers/usb/core/generic.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/usb/core/generic.c 2014-04-24 15:35:04.137565375 +0200 @@ -152,6 +152,7 @@ dev_warn(&udev->dev, "no configuration chosen from %d choice%s\n", @@ -34847,9 +35577,9 @@ diff -Nur linux-3.12.13/drivers/usb/core/generic.c linux-raspberry-pi/drivers/us } return i; } -diff -Nur linux-3.12.13/drivers/usb/core/message.c linux-raspberry-pi/drivers/usb/core/message.c ---- linux-3.12.13/drivers/usb/core/message.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/core/message.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/core/message.c linux-rpi/drivers/usb/core/message.c +--- linux-3.12.18/drivers/usb/core/message.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/usb/core/message.c 2014-04-24 16:04:39.763123712 +0200 @@ -1885,6 +1885,85 @@ if (cp->string == NULL && !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) @@ -34936,9 +35666,9 @@ diff -Nur linux-3.12.13/drivers/usb/core/message.c linux-raspberry-pi/drivers/us /* Now that the interfaces are installed, re-enable LPM. */ usb_unlocked_enable_lpm(dev); -diff -Nur linux-3.12.13/drivers/usb/core/otg_whitelist.h linux-raspberry-pi/drivers/usb/core/otg_whitelist.h ---- linux-3.12.13/drivers/usb/core/otg_whitelist.h 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/core/otg_whitelist.h 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/core/otg_whitelist.h linux-rpi/drivers/usb/core/otg_whitelist.h +--- linux-3.12.18/drivers/usb/core/otg_whitelist.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/usb/core/otg_whitelist.h 2014-04-24 16:04:39.763123712 +0200 @@ -19,33 +19,82 @@ static struct usb_device_id whitelist_table [] = { @@ -35154,9 +35884,9 @@ diff -Nur linux-3.12.13/drivers/usb/core/otg_whitelist.h linux-raspberry-pi/driv #endif } -diff -Nur linux-3.12.13/drivers/usb/gadget/file_storage.c linux-raspberry-pi/drivers/usb/gadget/file_storage.c ---- linux-3.12.13/drivers/usb/gadget/file_storage.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/gadget/file_storage.c 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/gadget/file_storage.c linux-rpi/drivers/usb/gadget/file_storage.c +--- linux-3.12.18/drivers/usb/gadget/file_storage.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/gadget/file_storage.c 2014-04-24 15:35:04.153565553 +0200 @@ -0,0 +1,3676 @@ +/* + * file_storage.c -- File-backed USB Storage Gadget, for USB development @@ -38834,9 +39564,9 @@ diff -Nur linux-3.12.13/drivers/usb/gadget/file_storage.c linux-raspberry-pi/dri + kref_put(&fsg->ref, fsg_release); +} +module_exit(fsg_cleanup); -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/changes.txt linux-raspberry-pi/drivers/usb/host/dwc_common_port/changes.txt ---- linux-3.12.13/drivers/usb/host/dwc_common_port/changes.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/changes.txt 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/changes.txt linux-rpi/drivers/usb/host/dwc_common_port/changes.txt +--- linux-3.12.18/drivers/usb/host/dwc_common_port/changes.txt 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/changes.txt 2014-04-24 15:35:04.169565731 +0200 @@ -0,0 +1,174 @@ + +dwc_read_reg32() and friends now take an additional parameter, a pointer to an @@ -39012,9 +39742,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/changes.txt linux-raspb +A DWC_LIBMODULE #define has also been added. If this is not defined, then the +module code in dwc_common_linux.c is not compiled in. This allows linking the +library code directly into a driver module, instead of as a standalone module. -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/doc/doxygen.cfg linux-raspberry-pi/drivers/usb/host/dwc_common_port/doc/doxygen.cfg ---- linux-3.12.13/drivers/usb/host/dwc_common_port/doc/doxygen.cfg 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/doc/doxygen.cfg 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/doc/doxygen.cfg linux-rpi/drivers/usb/host/dwc_common_port/doc/doxygen.cfg +--- linux-3.12.18/drivers/usb/host/dwc_common_port/doc/doxygen.cfg 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/doc/doxygen.cfg 2014-04-24 16:04:39.811124176 +0200 @@ -0,0 +1,270 @@ +# Doxyfile 1.4.5 + @@ -39286,9 +40016,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/doc/doxygen.cfg linux-r +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_cc.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_cc.c ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_cc.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_cc.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_cc.c +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_cc.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_cc.c 2014-04-24 16:04:39.811124176 +0200 @@ -0,0 +1,532 @@ +/* ========================================================================= + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $ @@ -39822,9 +40552,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_cc.c linux-raspberr +} + +#endif /* DWC_CCLIB */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_cc.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_cc.h ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_cc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_cc.h 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_cc.h linux-rpi/drivers/usb/host/dwc_common_port/dwc_cc.h +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_cc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_cc.h 2014-04-24 16:04:39.811124176 +0200 @@ -0,0 +1,224 @@ +/* ========================================================================= + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $ @@ -40050,9 +40780,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_cc.h linux-raspberr +#endif + +#endif /* _DWC_CC_H_ */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c 2014-04-24 15:35:04.169565731 +0200 @@ -0,0 +1,1308 @@ +#include "dwc_os.h" +#include "dwc_list.h" @@ -41362,10 +42092,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c linux +{ + return wq->pending; +} -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_linux.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_common_linux.c ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_linux.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_common_linux.c 2014-03-11 17:33:06.000000000 +0100 -@@ -0,0 +1,1431 @@ +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_common_linux.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_common_linux.c +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_common_linux.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_common_linux.c 2014-04-24 16:04:39.811124176 +0200 +@@ -0,0 +1,1432 @@ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> @@ -41953,6 +42683,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu + local_irq_save(flags); + local_fiq_disable(); + writel((readl(reg) & ~clear_mask) | set_mask, reg); ++ local_fiq_enable(); + local_irq_restore(flags); +} + @@ -42797,9 +43528,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu +MODULE_LICENSE ("GPL"); + +#endif /* DWC_LIBMODULE */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c 2014-04-24 15:35:04.169565731 +0200 @@ -0,0 +1,1275 @@ +#include "dwc_os.h" +#include "dwc_list.h" @@ -44076,9 +44807,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c linux +{ + return wq->pending; +} -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_crypto.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_crypto.c ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_crypto.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_crypto.c 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_crypto.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_crypto.c +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_crypto.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_crypto.c 2014-04-24 15:35:04.169565731 +0200 @@ -0,0 +1,308 @@ +/* ========================================================================= + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $ @@ -44388,9 +45119,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_crypto.c linux-rasp +} + +#endif /* DWC_CRYPTOLIB */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_crypto.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_crypto.h ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_crypto.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_crypto.h 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_crypto.h linux-rpi/drivers/usb/host/dwc_common_port/dwc_crypto.h +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_crypto.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_crypto.h 2014-04-24 15:35:04.169565731 +0200 @@ -0,0 +1,111 @@ +/* ========================================================================= + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $ @@ -44503,9 +45234,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_crypto.h linux-rasp +#endif + +#endif /* _DWC_CRYPTO_H_ */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_dh.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_dh.c ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_dh.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_dh.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_dh.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_dh.c +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_dh.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_dh.c 2014-04-24 16:04:39.811124176 +0200 @@ -0,0 +1,291 @@ +/* ========================================================================= + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $ @@ -44798,9 +45529,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_dh.c linux-raspberr +#endif /* !CONFIG_MACH_IPMATE */ + +#endif /* DWC_CRYPTOLIB */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_dh.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_dh.h ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_dh.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_dh.h 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_dh.h linux-rpi/drivers/usb/host/dwc_common_port/dwc_dh.h +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_dh.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_dh.h 2014-04-24 15:35:04.169565731 +0200 @@ -0,0 +1,106 @@ +/* ========================================================================= + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.h $ @@ -44908,9 +45639,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_dh.h linux-raspberr +#endif + +#endif /* _DWC_DH_H_ */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_list.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_list.h ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_list.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_list.h 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi/drivers/usb/host/dwc_common_port/dwc_list.h +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_list.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_list.h 2014-04-24 15:35:04.169565731 +0200 @@ -0,0 +1,594 @@ +/* $OpenBSD: queue.h,v 1.26 2004/05/04 16:59:32 grange Exp $ */ +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ @@ -45506,9 +46237,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_list.h linux-raspbe +#endif + +#endif /* _DWC_LIST_H_ */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_mem.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_mem.c ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_mem.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_mem.c 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_mem.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_mem.c +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_mem.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_mem.c 2014-04-24 15:35:04.169565731 +0200 @@ -0,0 +1,245 @@ +/* Memory Debugging */ +#ifdef DWC_DEBUG_MEMORY @@ -45755,9 +46486,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_mem.c linux-raspber +} + +#endif /* DWC_DEBUG_MEMORY */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_modpow.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_modpow.c ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_modpow.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_modpow.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_modpow.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_modpow.c +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_modpow.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_modpow.c 2014-04-24 16:04:39.811124176 +0200 @@ -0,0 +1,636 @@ +/* Bignum routines adapted from PUTTY sources. PuTTY copyright notice follows. + * @@ -46395,9 +47126,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_modpow.c linux-rasp +#endif /* CONFIG_MACH_IPMATE */ + +#endif /*DWC_CRYPTOLIB */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_modpow.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_modpow.h ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_modpow.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_modpow.h 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_modpow.h linux-rpi/drivers/usb/host/dwc_common_port/dwc_modpow.h +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_modpow.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_modpow.h 2014-04-24 15:35:04.169565731 +0200 @@ -0,0 +1,34 @@ +/* + * dwc_modpow.h @@ -46433,9 +47164,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_modpow.h linux-rasp +#endif + +#endif /* _LINUX_BIGNUM_H */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_notifier.c ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_notifier.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_notifier.c 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_notifier.c +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_notifier.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_notifier.c 2014-04-24 15:35:04.169565731 +0200 @@ -0,0 +1,319 @@ +#ifdef DWC_NOTIFYLIB + @@ -46756,9 +47487,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-ra +} + +#endif /* DWC_NOTIFYLIB */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_notifier.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_notifier.h ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_notifier.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_notifier.h 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_notifier.h linux-rpi/drivers/usb/host/dwc_common_port/dwc_notifier.h +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_notifier.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_notifier.h 2014-04-24 15:35:04.169565731 +0200 @@ -0,0 +1,122 @@ + +#ifndef __DWC_NOTIFIER_H__ @@ -46882,9 +47613,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_notifier.h linux-ra +#endif + +#endif /* __DWC_NOTIFIER_H__ */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_os.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_os.h ---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_os.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_os.h 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi/drivers/usb/host/dwc_common_port/dwc_os.h +--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_os.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_os.h 2014-04-24 16:04:39.815124215 +0200 @@ -0,0 +1,1262 @@ +/* ========================================================================= + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $ @@ -48148,9 +48879,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_os.h linux-raspberr +#endif + +#endif /* _DWC_OS_H_ */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile linux-raspberry-pi/drivers/usb/host/dwc_common_port/Makefile ---- linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/Makefile 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/Makefile linux-rpi/drivers/usb/host/dwc_common_port/Makefile +--- linux-3.12.18/drivers/usb/host/dwc_common_port/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/Makefile 2014-04-24 16:04:39.811124176 +0200 @@ -0,0 +1,58 @@ +# +# Makefile for DWC_common library @@ -48158,16 +48889,16 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile linux-raspberr + +ifneq ($(KERNELRELEASE),) + -+EXTRA_CFLAGS += -DDWC_LINUX -+#EXTRA_CFLAGS += -DDEBUG -+#EXTRA_CFLAGS += -DDWC_DEBUG_REGS -+#EXTRA_CFLAGS += -DDWC_DEBUG_MEMORY ++ccflags-y += -DDWC_LINUX ++#ccflags-y += -DDEBUG ++#ccflags-y += -DDWC_DEBUG_REGS ++#ccflags-y += -DDWC_DEBUG_MEMORY + -+EXTRA_CFLAGS += -DDWC_LIBMODULE -+EXTRA_CFLAGS += -DDWC_CCLIB -+#EXTRA_CFLAGS += -DDWC_CRYPTOLIB -+EXTRA_CFLAGS += -DDWC_NOTIFYLIB -+EXTRA_CFLAGS += -DDWC_UTFLIB ++ccflags-y += -DDWC_LIBMODULE ++ccflags-y += -DDWC_CCLIB ++#ccflags-y += -DDWC_CRYPTOLIB ++ccflags-y += -DDWC_NOTIFYLIB ++ccflags-y += -DDWC_UTFLIB + +obj-$(CONFIG_USB_DWCOTG) += dwc_common_port_lib.o +dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \ @@ -48178,8 +48909,8 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile linux-raspberr +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd)) + +ifneq ($(kernrel3),2.6.20) -+# grayg - I only know that we use EXTRA_CFLAGS in 2.6.31 actually -+EXTRA_CFLAGS += $(CPPFLAGS) ++# grayg - I only know that we use ccflags-y in 2.6.31 actually ++ccflags-y += $(CPPFLAGS) +endif + +else @@ -48210,9 +48941,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile linux-raspberr + +clean: + rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile.fbsd linux-raspberry-pi/drivers/usb/host/dwc_common_port/Makefile.fbsd ---- linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile.fbsd 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/Makefile.fbsd 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/Makefile.fbsd linux-rpi/drivers/usb/host/dwc_common_port/Makefile.fbsd +--- linux-3.12.18/drivers/usb/host/dwc_common_port/Makefile.fbsd 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/Makefile.fbsd 2014-04-24 15:35:04.169565731 +0200 @@ -0,0 +1,17 @@ +CFLAGS += -I/sys/i386/compile/GENERIC -I/sys/i386/include -I/usr/include +CFLAGS += -DDWC_FREEBSD @@ -48231,25 +48962,25 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile.fbsd linux-ras + dwc_common_fbsd.c dwc_mem.c + +.include <bsd.kmod.mk> -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile.linux linux-raspberry-pi/drivers/usb/host/dwc_common_port/Makefile.linux ---- linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile.linux 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/Makefile.linux 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/Makefile.linux linux-rpi/drivers/usb/host/dwc_common_port/Makefile.linux +--- linux-3.12.18/drivers/usb/host/dwc_common_port/Makefile.linux 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/Makefile.linux 2014-04-24 15:35:04.169565731 +0200 @@ -0,0 +1,49 @@ +# +# Makefile for DWC_common library +# +ifneq ($(KERNELRELEASE),) + -+EXTRA_CFLAGS += -DDWC_LINUX -+#EXTRA_CFLAGS += -DDEBUG -+#EXTRA_CFLAGS += -DDWC_DEBUG_REGS -+#EXTRA_CFLAGS += -DDWC_DEBUG_MEMORY ++ccflags-y += -DDWC_LINUX ++#ccflags-y += -DDEBUG ++#ccflags-y += -DDWC_DEBUG_REGS ++#ccflags-y += -DDWC_DEBUG_MEMORY + -+EXTRA_CFLAGS += -DDWC_LIBMODULE -+EXTRA_CFLAGS += -DDWC_CCLIB -+EXTRA_CFLAGS += -DDWC_CRYPTOLIB -+EXTRA_CFLAGS += -DDWC_NOTIFYLIB -+EXTRA_CFLAGS += -DDWC_UTFLIB ++ccflags-y += -DDWC_LIBMODULE ++ccflags-y += -DDWC_CCLIB ++ccflags-y += -DDWC_CRYPTOLIB ++ccflags-y += -DDWC_NOTIFYLIB ++ccflags-y += -DDWC_UTFLIB + +obj-m := dwc_common_port_lib.o +dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \ @@ -48284,9 +49015,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile.linux linux-ra + +clean: + rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/usb.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/usb.h ---- linux-3.12.13/drivers/usb/host/dwc_common_port/usb.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/usb.h 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/usb.h linux-rpi/drivers/usb/host/dwc_common_port/usb.h +--- linux-3.12.18/drivers/usb/host/dwc_common_port/usb.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_common_port/usb.h 2014-04-24 15:35:04.169565731 +0200 @@ -0,0 +1,946 @@ +/* + * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -49234,9 +49965,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/usb.h linux-raspberry-p +#endif + +#endif /* _USB_H_ */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/doc/doxygen.cfg linux-raspberry-pi/drivers/usb/host/dwc_otg/doc/doxygen.cfg ---- linux-3.12.13/drivers/usb/host/dwc_otg/doc/doxygen.cfg 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/doc/doxygen.cfg 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/doc/doxygen.cfg linux-rpi/drivers/usb/host/dwc_otg/doc/doxygen.cfg +--- linux-3.12.18/drivers/usb/host/dwc_otg/doc/doxygen.cfg 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/doc/doxygen.cfg 2014-04-24 16:04:39.815124215 +0200 @@ -0,0 +1,224 @@ +# Doxyfile 1.3.9.1 + @@ -49462,9 +50193,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/doc/doxygen.cfg linux-raspberry +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dummy_audio.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dummy_audio.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dummy_audio.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dummy_audio.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dummy_audio.c linux-rpi/drivers/usb/host/dwc_otg/dummy_audio.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dummy_audio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dummy_audio.c 2014-04-24 16:04:39.815124215 +0200 @@ -0,0 +1,1575 @@ +/* + * zero.c -- Gadget Zero, for USB development @@ -51041,9 +51772,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dummy_audio.c linux-raspberry-p + remove_proc_entry("isoc_test", NULL); +} +module_exit (cleanup); -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_cfi_common.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_cfi_common.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_cfi_common.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_cfi_common.h 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_cfi_common.h linux-rpi/drivers/usb/host/dwc_otg/dwc_cfi_common.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_cfi_common.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_cfi_common.h 2014-04-24 16:04:39.815124215 +0200 @@ -0,0 +1,142 @@ +/* ========================================================================== + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, @@ -51187,9 +51918,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_cfi_common.h linux-raspberr +typedef struct cfi_string cfi_string_t; + +#endif -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_adp.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_adp.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_adp.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_adp.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_adp.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_adp.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_adp.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_adp.c 2014-04-24 16:04:39.815124215 +0200 @@ -0,0 +1,854 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $ @@ -52045,9 +52776,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_adp.c linux-raspberry-p +#endif + return 1; +} -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_adp.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_adp.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_adp.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_adp.h 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_adp.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_adp.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_adp.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_adp.h 2014-04-24 16:04:39.815124215 +0200 @@ -0,0 +1,80 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $ @@ -52129,9 +52860,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_adp.h linux-raspberry-p +extern int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if); + +#endif //__DWC_OTG_ADP_H__ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_attr.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_attr.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_attr.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_attr.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_attr.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_attr.c 2014-04-24 16:04:39.815124215 +0200 @@ -0,0 +1,1210 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $ @@ -53343,9 +54074,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-raspberry- + device_remove_file(&dev->dev, &dev_attr_sleep_status); +#endif +} -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_attr.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_attr.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_attr.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_attr.h 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_attr.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_attr.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_attr.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_attr.h 2014-04-24 16:04:39.815124215 +0200 @@ -0,0 +1,89 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $ @@ -53436,9 +54167,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_attr.h linux-raspberry- +#endif + ); +#endif -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cfi.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cfi.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 2014-04-24 16:04:39.815124215 +0200 @@ -0,0 +1,1876 @@ +/* ========================================================================== + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, @@ -55316,9 +56047,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-raspberry-p +} + +#endif //DWC_UTE_CFI -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cfi.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cfi.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 2014-04-24 16:04:39.815124215 +0200 @@ -0,0 +1,320 @@ +/* ========================================================================== + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, @@ -55640,9 +56371,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-raspberry-p +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl); + +#endif /* (__DWC_OTG_CFI_H__) */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cil.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cil.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cil.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil.c 2014-04-24 16:04:39.815124215 +0200 @@ -0,0 +1,7151 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $ @@ -62795,9 +63526,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-raspberry-p + dwc_otg_pcd_start_srp_timer(core_if); + return; +} -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cil.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cil.h 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cil.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil.h 2014-04-24 16:04:39.815124215 +0200 @@ -0,0 +1,1464 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $ @@ -64263,10 +64994,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-raspberry-p +////////////////////////////////////////////////////////////////////// + +#endif -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 2014-03-11 17:51:27.000000000 +0100 -@@ -0,0 +1,1588 @@ +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 2014-04-24 16:04:39.815124215 +0200 +@@ -0,0 +1,1595 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $ + * $Revision: #32 $ @@ -64314,7 +65045,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe +#include "dwc_otg_driver.h" +#include "dwc_otg_pcd.h" +#include "dwc_otg_hcd.h" -+#include "dwc_otg_mphi_fix.h" + +#ifdef DEBUG +inline const char *op_state_str(dwc_otg_core_if_t * core_if) @@ -65588,7 +66318,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe +/** + * This function returns the Core Interrupt register. + */ -+static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gintmsk_data_t *reenable_gintmsk) ++static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gintmsk_data_t *reenable_gintmsk, dwc_otg_hcd_t *hcd) +{ + gahbcfg_data_t gahbcfg = {.d32 = 0 }; + gintsts_data_t gintsts; @@ -65614,16 +66344,15 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe + } + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); + gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); -+ { -+ unsigned long flags; -+ -+ // Re-enable the saved interrupts -+ local_irq_save(flags); ++ if(fiq_enable) { + local_fiq_disable(); -+ gintmsk.d32 |= gintmsk_common.d32; -+ gintsts_saved.d32 &= ~gintmsk_common.d32; -+ reenable_gintmsk->d32 = gintmsk.d32; -+ local_irq_restore(flags); ++ /* Pull in the interrupts that the FIQ has masked */ ++ gintmsk.d32 |= ~(hcd->fiq_state->gintmsk_saved.d32); ++ /* for the upstairs function to reenable - have to read it here in case FIQ triggers again */ ++ reenable_gintmsk->d32 |= gintmsk.d32; ++ reenable_gintmsk->d32 |= ~(hcd->fiq_state->gintmsk_saved.d32); ++ reenable_gintmsk->d32 &= gintmsk_common.d32; ++ local_fiq_enable(); + } + + gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg); @@ -65635,13 +66364,15 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe + gintsts.d32, gintmsk.d32); + } +#endif -+ if (!fiq_fix_enable){ ++ if (!fiq_enable){ + if (gahbcfg.b.glblintrmsk) + return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32); + else + return 0; -+ } -+ else { ++ } else { ++ /* Our IRQ kicker is no longer the USB hardware, it's the MPHI interface. ++ * Can't trust the global interrupt mask bit in this case. ++ */ + return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32); + } + @@ -65675,7 +66406,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe +{ + int retval = 0; + gintsts_data_t gintsts; -+ gintmsk_data_t reenable_gintmsk; ++ gintmsk_data_t gintmsk_reenable = { .d32 = 0 }; + gpwrdn_data_t gpwrdn = {.d32 = 0 }; + dwc_otg_device_t *otg_dev = dev; + dwc_otg_core_if_t *core_if = otg_dev->core_if; @@ -65697,7 +66428,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe + } + + if (core_if->hibernation_suspend <= 0) { -+ gintsts.d32 = dwc_otg_read_common_intr(core_if, &reenable_gintmsk); ++ /* read_common will have to poke the FIQ's saved mask. We must then clear this mask at the end ++ * of this handler - god only knows why it's done like this ++ */ ++ gintsts.d32 = dwc_otg_read_common_intr(core_if, &gintmsk_reenable, otg_dev->hcd); + + if (gintsts.b.modemismatch) { + retval |= dwc_otg_handle_mode_mismatch_intr(core_if); @@ -65794,11 +66528,16 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe + gintsts.b.portintr = 1; + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); + retval |= 1; -+ reenable_gintmsk.b.portintr = 1; ++ gintmsk_reenable.b.portintr = 1; + + } -+ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, reenable_gintmsk.d32); ++ /* Did we actually handle anything? if so, unmask the interrupt */ ++// fiq_print(FIQDBG_INT, otg_dev->hcd->fiq_state, "CILOUT %1d", retval); ++// fiq_print(FIQDBG_INT, otg_dev->hcd->fiq_state, "%08x", gintsts.d32); ++// fiq_print(FIQDBG_INT, otg_dev->hcd->fiq_state, "%08x", gintmsk_reenable.d32); ++ if (retval) { ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_reenable.d32); ++ } + + } else { + DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32); @@ -65852,12 +66591,11 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe + } + if (core_if->lock) + DWC_SPINUNLOCK(core_if->lock); -+ + return retval; +} -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_core_if.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_core_if.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 2014-04-24 16:04:39.815124215 +0200 @@ -0,0 +1,705 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $ @@ -66564,9 +67302,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-raspber +/** @} */ + +#endif /* __DWC_CORE_IF_H__ */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_dbg.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_dbg.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 2014-04-24 16:04:39.815124215 +0200 @@ -0,0 +1,117 @@ +/* ========================================================================== + * @@ -66685,10 +67423,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-raspberry-p + +#endif /*DEBUG*/ +#endif -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_driver.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_driver.c 2014-03-11 17:51:27.000000000 +0100 -@@ -0,0 +1,1742 @@ +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_driver.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_driver.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_driver.c 2014-04-24 16:04:39.815124215 +0200 +@@ -0,0 +1,1749 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $ + * $Revision: #92 $ @@ -66747,6 +67485,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr +#include "dwc_otg_core_if.h" +#include "dwc_otg_pcd_if.h" +#include "dwc_otg_hcd_if.h" ++#include "dwc_otg_fiq_fsm.h" + +#define DWC_DRIVER_VERSION "3.00a 10-AUG-2012" +#define DWC_DRIVER_DESC "HS OTG USB Controller driver" @@ -66755,7 +67494,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr + +static const char dwc_driver_name[] = "dwc_otg"; + -+extern void* dummy_send; + +extern int pcd_init( +#ifdef LM_INTERFACE @@ -66931,13 +67669,14 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr + .adp_enable = -1, +}; + -+//Global variable to switch the fiq fix on or off (declared in bcm2708.c) -+extern bool fiq_fix_enable; ++//Global variable to switch the fiq fix on or off ++bool fiq_enable = 1; +// Global variable to enable the split transaction fix -+bool fiq_split_enable = true; -+//Global variable to switch the nak holdoff on or off -+bool nak_holdoff_enable = true; ++bool fiq_fsm_enable = false; ++//Bulk split-transaction NAK holdoff in microframes ++uint16_t nak_holdoff = 8; + ++unsigned short fiq_fsm_mask = 0x01; + +/** + * This function shows the Driver Version. @@ -67491,7 +68230,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr + dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource[0].start, + _dev->resource[0].end - + _dev->resource[0].start+1); -+ if (fiq_fix_enable) ++ if (fiq_enable) + { + if (!request_mem_region(_dev->resource[1].start, + _dev->resource[1].end - _dev->resource[1].start + 1, @@ -67504,7 +68243,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr + dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start, + _dev->resource[1].end - + _dev->resource[1].start + 1); -+ dummy_send = (void *) kmalloc(16, GFP_ATOMIC); + } + +#else @@ -67762,9 +68500,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr + int error; + struct device_driver *drv; + -+ if(fiq_split_enable && !fiq_fix_enable) { -+ printk(KERN_WARNING "dwc_otg: fiq_split_enable was set without fiq_fix_enable! Correcting.\n"); -+ fiq_fix_enable = 1; ++ if(fiq_fsm_enable && !fiq_enable) { ++ printk(KERN_WARNING "dwc_otg: fiq_fsm_enable was set without fiq_enable! Correcting.\n"); ++ fiq_enable = 1; + } + + printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name, @@ -67786,9 +68524,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr + printk(KERN_ERR "%s retval=%d\n", __func__, retval); + return retval; + } -+ printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_fix_enable ? "enabled":"disabled"); -+ printk(KERN_DEBUG "dwc_otg: NAK holdoff %s\n", nak_holdoff_enable ? "enabled":"disabled"); -+ printk(KERN_DEBUG "dwc_otg: FIQ split fix %s\n", fiq_split_enable ? "enabled":"disabled"); ++ printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_enable ? "enabled":"disabled"); ++ printk(KERN_DEBUG "dwc_otg: NAK holdoff %s\n", nak_holdoff ? "enabled":"disabled"); ++ printk(KERN_DEBUG "dwc_otg: FIQ split-transaction FSM %s\n", fiq_fsm_enable ? "enabled":"disabled"); + + error = driver_create_file(drv, &driver_attr_version); +#ifdef DEBUG @@ -68069,12 +68807,19 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr +module_param(microframe_schedule, bool, 0444); +MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler"); + -+module_param(fiq_fix_enable, bool, 0444); -+MODULE_PARM_DESC(fiq_fix_enable, "Enable the fiq fix"); -+module_param(nak_holdoff_enable, bool, 0444); -+MODULE_PARM_DESC(nak_holdoff_enable, "Enable the NAK holdoff"); -+module_param(fiq_split_enable, bool, 0444); -+MODULE_PARM_DESC(fiq_split_enable, "Enable the FIQ fix on split transactions"); ++module_param(fiq_enable, bool, 0444); ++MODULE_PARM_DESC(fiq_enable, "Enable the FIQ"); ++module_param(nak_holdoff, ushort, 0644); ++MODULE_PARM_DESC(nak_holdoff, "Throttle duration for bulk split-transaction endpoints on a NAK. Default 8"); ++module_param(fiq_fsm_enable, bool, 0444); ++MODULE_PARM_DESC(fiq_fsm_enable, "Enable the FIQ to perform split transactions as defined by fiq_fsm_mask"); ++module_param(fiq_fsm_mask, ushort, 0444); ++MODULE_PARM_DESC(fiq_fsm_mask, "Bitmask of transactions to perform in the FIQ.\n" ++ "Bit 0 : Non-periodic split transactions\n" ++ "Bit 1 : Periodic split transactions\n" ++ "Bit 2 : High-speed multi-transfer isochronous\n" ++ "All other bits should be set 0."); ++ + +/** @page "Module Parameters" + * @@ -68431,9 +69176,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr + </td></tr> + +*/ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_driver.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_driver.h 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_driver.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_driver.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_driver.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_driver.h 2014-04-24 16:04:39.819124254 +0200 @@ -0,0 +1,86 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $ @@ -68521,10 +69266,1745 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.h linux-raspberr +#endif + +#endif -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 2014-03-11 17:51:27.000000000 +0100 -@@ -0,0 +1,3685 @@ +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c 2014-04-24 16:04:39.819124254 +0200 +@@ -0,0 +1,1289 @@ ++/* ++ * dwc_otg_fiq_fsm.c - The finite state machine FIQ ++ * ++ * Copyright (c) 2013 Raspberry Pi Foundation ++ * ++ * Author: Jonathan Bell <jonathan@raspberrypi.org> ++ * 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 Raspberry Pi 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 FIQ implements functionality that performs split transactions on ++ * the dwc_otg hardware without any outside intervention. A split transaction ++ * is "queued" by nominating a specific host channel to perform the entirety ++ * of a split transaction. This FIQ will then perform the microframe-precise ++ * scheduling required in each phase of the transaction until completion. ++ * ++ * The FIQ functionality is glued into the Synopsys driver via the entry point ++ * in the FSM enqueue function, and at the exit point in handling a HC interrupt ++ * for a FSM-enabled channel. ++ * ++ * NB: Large parts of this implementation have architecture-specific code. ++ * For porting this functionality to other ARM machines, the minimum is required: ++ * - An interrupt controller allowing the top-level dwc USB interrupt to be routed ++ * to the FIQ ++ * - A method of forcing a software generated interrupt from FIQ mode that then ++ * triggers an IRQ entry (with the dwc USB handler called by this IRQ number) ++ * - Guaranteed interrupt routing such that both the FIQ and SGI occur on the same ++ * processor core - there is no locking between the FIQ and IRQ (aside from ++ * local_fiq_disable) ++ * ++ */ ++ ++#include "dwc_otg_fiq_fsm.h" ++ ++ ++char buffer[1000*16]; ++int wptr; ++void notrace _fiq_print(enum fiq_debug_level dbg_lvl, volatile struct fiq_state *state, char *fmt, ...) ++{ ++ enum fiq_debug_level dbg_lvl_req = FIQDBG_ERR; ++ va_list args; ++ char text[17]; ++ hfnum_data_t hfnum = { .d32 = FIQ_READ(state->dwc_regs_base + 0x408) }; ++ ++ if((dbg_lvl & dbg_lvl_req) || dbg_lvl == FIQDBG_ERR) ++ { ++ snprintf(text, 9, " %4d:%1u ", hfnum.b.frnum/8, hfnum.b.frnum & 7); ++ va_start(args, fmt); ++ vsnprintf(text+8, 9, fmt, args); ++ va_end(args); ++ ++ memcpy(buffer + wptr, text, 16); ++ wptr = (wptr + 16) % sizeof(buffer); ++ } ++} ++ ++/** ++ * fiq_fsm_restart_channel() - Poke channel enable bit for a split transaction ++ * @channel: channel to re-enable ++ */ ++static void fiq_fsm_restart_channel(struct fiq_state *st, int n, int force) ++{ ++ hcchar_data_t hcchar = { .d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR) }; ++ ++ hcchar.b.chen = 0; ++ if (st->channel[n].hcchar_copy.b.eptype & 0x1) { ++ hfnum_data_t hfnum = { .d32 = FIQ_READ(st->dwc_regs_base + HFNUM) }; ++ /* Hardware bug workaround: update the ssplit index */ ++ if (st->channel[n].hcsplt_copy.b.spltena) ++ st->channel[n].expected_uframe = (hfnum.b.frnum + 1) & 0x3FFF; ++ ++ hcchar.b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1; ++ } ++ ++ FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR, hcchar.d32); ++ hcchar.d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR); ++ hcchar.b.chen = 1; ++ ++ FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR, hcchar.d32); ++ fiq_print(FIQDBG_INT, st, "HCGO %01d %01d", n, force); ++} ++ ++/** ++ * fiq_fsm_setup_csplit() - Prepare a host channel for a CSplit transaction stage ++ * @st: Pointer to the channel's state ++ * @n : channel number ++ * ++ * Change host channel registers to perform a complete-split transaction. Being mindful of the ++ * endpoint direction, set control regs up correctly. ++ */ ++static void notrace fiq_fsm_setup_csplit(struct fiq_state *st, int n) ++{ ++ hcsplt_data_t hcsplt = { .d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCSPLT) }; ++ hctsiz_data_t hctsiz = { .d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ) }; ++ ++ hcsplt.b.compsplt = 1; ++ if (st->channel[n].hcchar_copy.b.epdir == 1) { ++ // If IN, the CSPLIT result contains the data or a hub handshake. hctsiz = maxpacket. ++ hctsiz.b.xfersize = st->channel[n].hctsiz_copy.b.xfersize; ++ } else { ++ // If OUT, the CSPLIT result contains handshake only. ++ hctsiz.b.xfersize = 0; ++ } ++ FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCSPLT, hcsplt.d32); ++ FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ, hctsiz.d32); ++ mb(); ++} ++ ++static inline int notrace fiq_get_xfer_len(struct fiq_state *st, int n) ++{ ++ /* The xfersize register is a bit wonky. For IN transfers, it decrements by the packet size. */ ++ hctsiz_data_t hctsiz = { .d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ) }; ++ ++ if (st->channel[n].hcchar_copy.b.epdir == 0) { ++ return st->channel[n].hctsiz_copy.b.xfersize; ++ } else { ++ return st->channel[n].hctsiz_copy.b.xfersize - hctsiz.b.xfersize; ++ } ++ ++} ++ ++ ++/** ++ * fiq_increment_dma_buf() - update DMA address for bounce buffers after a CSPLIT ++ * ++ * Of use only for IN periodic transfers. ++ */ ++static int notrace fiq_increment_dma_buf(struct fiq_state *st, int num_channels, int n) ++{ ++ hcdma_data_t hcdma; ++ int i = st->channel[n].dma_info.index; ++ int len; ++ struct fiq_dma_blob *blob = (struct fiq_dma_blob *) st->dma_base; ++ ++ len = fiq_get_xfer_len(st, n); ++ fiq_print(FIQDBG_INT, st, "LEN: %03d", len); ++ st->channel[n].dma_info.slot_len[i] = len; ++ i++; ++ if (i > 6) ++ BUG(); ++ ++ hcdma.d32 = (dma_addr_t) &blob->channel[n].index[i].buf[0]; ++ FIQ_WRITE(st->dwc_regs_base + HC_DMA + (HC_OFFSET * n), hcdma.d32); ++ st->channel[n].dma_info.index = i; ++ return 0; ++} ++ ++/** ++ * fiq_reload_hctsiz() - for IN transactions, reset HCTSIZ ++ */ ++static void notrace fiq_fsm_reload_hctsiz(struct fiq_state *st, int n) ++{ ++ hctsiz_data_t hctsiz = { .d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ) }; ++ hctsiz.b.xfersize = st->channel[n].hctsiz_copy.b.xfersize; ++ hctsiz.b.pktcnt = 1; ++ FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ, hctsiz.d32); ++} ++ ++/** ++ * fiq_iso_out_advance() - update DMA address and split position bits ++ * for isochronous OUT transactions. ++ * ++ * Returns 1 if this is the last packet queued, 0 otherwise. Split-ALL and ++ * Split-BEGIN states are not handled - this is done when the transaction was queued. ++ * ++ * This function must only be called from the FIQ_ISO_OUT_ACTIVE state. ++ */ ++static int notrace fiq_iso_out_advance(struct fiq_state *st, int num_channels, int n) ++{ ++ hcsplt_data_t hcsplt; ++ hctsiz_data_t hctsiz; ++ hcdma_data_t hcdma; ++ struct fiq_dma_blob *blob = (struct fiq_dma_blob *) st->dma_base; ++ int last = 0; ++ int i = st->channel[n].dma_info.index; ++ ++ fiq_print(FIQDBG_INT, st, "ADV %01d %01d ", n, i); ++ i++; ++ if (i == 4) ++ last = 1; ++ if (st->channel[n].dma_info.slot_len[i+1] == 255) ++ last = 1; ++ ++ /* New DMA address - address of bounce buffer referred to in index */ ++ hcdma.d32 = (uint32_t) &blob->channel[n].index[i].buf[0]; ++ //hcdma.d32 = FIQ_READ(st->dwc_regs_base + HC_DMA + (HC_OFFSET * n)); ++ //hcdma.d32 += st->channel[n].dma_info.slot_len[i]; ++ fiq_print(FIQDBG_INT, st, "LAST: %01d ", last); ++ fiq_print(FIQDBG_INT, st, "LEN: %03d", st->channel[n].dma_info.slot_len[i]); ++ hcsplt.d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCSPLT); ++ hctsiz.d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ); ++ hcsplt.b.xactpos = (last) ? ISOC_XACTPOS_END : ISOC_XACTPOS_MID; ++ /* Set up new packet length */ ++ hctsiz.b.pktcnt = 1; ++ hctsiz.b.xfersize = st->channel[n].dma_info.slot_len[i]; ++ fiq_print(FIQDBG_INT, st, "%08x", hctsiz.d32); ++ ++ st->channel[n].dma_info.index++; ++ FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCSPLT, hcsplt.d32); ++ FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ, hctsiz.d32); ++ FIQ_WRITE(st->dwc_regs_base + HC_DMA + (HC_OFFSET * n), hcdma.d32); ++ return last; ++} ++ ++/** ++ * fiq_fsm_tt_next_isoc() - queue next pending isochronous out start-split on a TT ++ * ++ * Despite the limitations of the DWC core, we can force a microframe pipeline of ++ * isochronous OUT start-split transactions while waiting for a corresponding other-type ++ * of endpoint to finish its CSPLITs. TTs have big periodic buffers therefore it ++ * is very unlikely that filling the start-split FIFO will cause data loss. ++ * This allows much better interleaving of transactions in an order-independent way- ++ * there is no requirement to prioritise isochronous, just a state-space search has ++ * to be performed on each periodic start-split complete interrupt. ++ */ ++static int notrace fiq_fsm_tt_next_isoc(struct fiq_state *st, int num_channels, int n) ++{ ++ int hub_addr = st->channel[n].hub_addr; ++ int port_addr = st->channel[n].port_addr; ++ int i, poked = 0; ++ for (i = 0; i < num_channels; i++) { ++ if (i == n || st->channel[i].fsm == FIQ_PASSTHROUGH) ++ continue; ++ if (st->channel[i].hub_addr == hub_addr && ++ st->channel[i].port_addr == port_addr) { ++ switch (st->channel[i].fsm) { ++ case FIQ_PER_ISO_OUT_PENDING: ++ if (st->channel[i].nrpackets == 1) { ++ st->channel[i].fsm = FIQ_PER_ISO_OUT_LAST; ++ } else { ++ st->channel[i].fsm = FIQ_PER_ISO_OUT_ACTIVE; ++ } ++ fiq_fsm_restart_channel(st, i, 0); ++ poked = 1; ++ break; ++ ++ default: ++ break; ++ } ++ } ++ if (poked) ++ break; ++ } ++ return poked; ++} ++ ++/** ++ * fiq_fsm_tt_in_use() - search for host channels using this TT ++ * @n: Channel to use as reference ++ * ++ */ ++int notrace noinline fiq_fsm_tt_in_use(struct fiq_state *st, int num_channels, int n) ++{ ++ int hub_addr = st->channel[n].hub_addr; ++ int port_addr = st->channel[n].port_addr; ++ int i, in_use = 0; ++ for (i = 0; i < num_channels; i++) { ++ if (i == n || st->channel[i].fsm == FIQ_PASSTHROUGH) ++ continue; ++ switch (st->channel[i].fsm) { ++ /* TT is reserved for channels that are in the middle of a periodic ++ * split transaction. ++ */ ++ case FIQ_PER_SSPLIT_STARTED: ++ case FIQ_PER_CSPLIT_WAIT: ++ case FIQ_PER_CSPLIT_NYET1: ++ //case FIQ_PER_CSPLIT_POLL: ++ case FIQ_PER_ISO_OUT_ACTIVE: ++ if (st->channel[i].hub_addr == hub_addr && ++ st->channel[i].port_addr == port_addr) { ++ in_use = 1; ++ } ++ break; ++ default: ++ break; ++ } ++ if (in_use) ++ break; ++ } ++ return in_use; ++} ++ ++/** ++ * fiq_fsm_more_csplits() - determine whether additional CSPLITs need ++ * to be issued for this IN transaction. ++ * ++ * We cannot tell the inbound PID of a data packet due to hardware limitations. ++ * we need to make an educated guess as to whether we need to queue another CSPLIT ++ * or not. A no-brainer is when we have received enough data to fill the endpoint ++ * size, but for endpoints that give variable-length data then we have to resort ++ * to heuristics. ++ * ++ * We also return whether this is the last CSPLIT to be queued, again based on ++ * heuristics. This is to allow a 1-uframe overlap of periodic split transactions. ++ * Note: requires at least 1 CSPLIT to have been performed prior to being called. ++ */ ++ ++/* ++ * We need some way of guaranteeing if a returned periodic packet of size X ++ * has a DATA0 PID. ++ * The heuristic value of 144 bytes assumes that the received data has maximal ++ * bit-stuffing and the clock frequency of the transmitting device is at the lowest ++ * permissible limit. If the transfer length results in a final packet size ++ * 144 < p <= 188, then an erroneous CSPLIT will be issued. ++ * Also used to ensure that an endpoint will nominally only return a single ++ * complete-split worth of data. ++ */ ++#define DATA0_PID_HEURISTIC 144 ++ ++static int notrace noinline fiq_fsm_more_csplits(struct fiq_state *state, int n, int *probably_last) ++{ ++ ++ int i; ++ int total_len = 0; ++ int more_needed = 1; ++ struct fiq_channel_state *st = &state->channel[n]; ++ ++ for (i = 0; i < st->dma_info.index; i++) { ++ total_len += st->dma_info.slot_len[i]; ++ } ++ ++ *probably_last = 0; ++ ++ if (st->hcchar_copy.b.eptype == 0x3) { ++ /* ++ * An interrupt endpoint will take max 2 CSPLITs. if we are receiving data ++ * then this is definitely the last CSPLIT. ++ */ ++ *probably_last = 1; ++ } else { ++ /* Isoc IN. This is a bit risky if we are the first transaction: ++ * we may have been held off slightly. */ ++ if (i > 1 && st->dma_info.slot_len[st->dma_info.index-1] <= DATA0_PID_HEURISTIC) { ++ more_needed = 0; ++ } ++ /* If in the next uframe we will receive enough data to fill the endpoint, ++ * then only issue 1 more csplit. ++ */ ++ if (st->hctsiz_copy.b.xfersize - total_len <= DATA0_PID_HEURISTIC) ++ *probably_last = 1; ++ } ++ ++ if (total_len >= st->hctsiz_copy.b.xfersize || ++ i == 6 || total_len == 0) ++ /* Note: due to bit stuffing it is possible to have > 6 CSPLITs for ++ * a single endpoint. Accepting more would completely break our scheduling mechanism though ++ * - in these extreme cases we will pass through a truncated packet. ++ */ ++ more_needed = 0; ++ ++ return more_needed; ++} ++ ++/** ++ * fiq_fsm_too_late() - Test transaction for lateness ++ * ++ * If a SSPLIT for a large IN transaction is issued too late in a frame, ++ * the hub will disable the port to the device and respond with ERR handshakes. ++ * The hub status endpoint will not reflect this change. ++ * Returns 1 if we will issue a SSPLIT that will result in a device babble. ++ */ ++int notrace fiq_fsm_too_late(struct fiq_state *st, int n) ++{ ++ int uframe; ++ hfnum_data_t hfnum = { .d32 = FIQ_READ(st->dwc_regs_base + HFNUM) }; ++ uframe = hfnum.b.frnum & 0x7; ++ if ((uframe < 6) && (st->channel[n].nrpackets + 1 + uframe > 7)) { ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ ++ ++/** ++ * fiq_fsm_start_next_periodic() - A half-arsed attempt at a microframe pipeline ++ * ++ * Search pending transactions in the start-split pending state and queue them. ++ * Don't queue packets in uframe .5 (comes out in .6) (USB2.0 11.18.4). ++ * Note: we specifically don't do isochronous OUT transactions first because better ++ * use of the TT's start-split fifo can be achieved by pipelining an IN before an OUT. ++ */ ++static void notrace noinline fiq_fsm_start_next_periodic(struct fiq_state *st, int num_channels) ++{ ++ int n; ++ hfnum_data_t hfnum = { .d32 = FIQ_READ(st->dwc_regs_base + HFNUM) }; ++ if ((hfnum.b.frnum & 0x7) == 5) ++ return; ++ for (n = 0; n < num_channels; n++) { ++ if (st->channel[n].fsm == FIQ_PER_SSPLIT_QUEUED) { ++ /* Check to see if any other transactions are using this TT */ ++ if(!fiq_fsm_tt_in_use(st, num_channels, n)) { ++ if (!fiq_fsm_too_late(st, n)) { ++ st->channel[n].fsm = FIQ_PER_SSPLIT_STARTED; ++ fiq_print(FIQDBG_INT, st, "NEXTPER "); ++ fiq_fsm_restart_channel(st, n, 0); ++ } else { ++ st->channel[n].fsm = FIQ_PER_SPLIT_TIMEOUT; ++ } ++ break; ++ } ++ } ++ } ++ for (n = 0; n < num_channels; n++) { ++ if (st->channel[n].fsm == FIQ_PER_ISO_OUT_PENDING) { ++ if (!fiq_fsm_tt_in_use(st, num_channels, n)) { ++ fiq_print(FIQDBG_INT, st, "NEXTISO "); ++ st->channel[n].fsm = FIQ_PER_ISO_OUT_ACTIVE; ++ fiq_fsm_restart_channel(st, n, 0); ++ break; ++ } ++ } ++ } ++} ++ ++/** ++ * fiq_fsm_update_hs_isoc() - update isochronous frame and transfer data ++ * @state: Pointer to fiq_state ++ * @n: Channel transaction is active on ++ * @hcint: Copy of host channel interrupt register ++ * ++ * Returns 0 if there are no more transactions for this HC to do, 1 ++ * otherwise. ++ */ ++static int notrace noinline fiq_fsm_update_hs_isoc(struct fiq_state *state, int n, hcint_data_t hcint) ++{ ++ struct fiq_channel_state *st = &state->channel[n]; ++ int xfer_len = 0, nrpackets = 0; ++ hcdma_data_t hcdma; ++ fiq_print(FIQDBG_INT, state, "HSISO %02d", n); ++ ++ xfer_len = fiq_get_xfer_len(state, n); ++ st->hs_isoc_info.iso_desc[st->hs_isoc_info.index].actual_length = xfer_len; ++ ++ st->hs_isoc_info.iso_desc[st->hs_isoc_info.index].status = hcint.d32; ++ ++ st->hs_isoc_info.index++; ++ if (st->hs_isoc_info.index == st->hs_isoc_info.nrframes) { ++ return 0; ++ } ++ ++ /* grab the next DMA address offset from the array */ ++ hcdma.d32 = st->hcdma_copy.d32 + st->hs_isoc_info.iso_desc[st->hs_isoc_info.index].offset; ++ FIQ_WRITE(state->dwc_regs_base + HC_DMA + (HC_OFFSET * n), hcdma.d32); ++ ++ /* We need to set multi_count. This is a bit tricky - has to be set per-transaction as ++ * the core needs to be told to send the correct number. Caution: for IN transfers, ++ * this is always set to the maximum size of the endpoint. */ ++ xfer_len = st->hs_isoc_info.iso_desc[st->hs_isoc_info.index].length; ++ /* Integer divide in a FIQ: fun. FIXME: make this not suck */ ++ nrpackets = (xfer_len + st->hcchar_copy.b.mps - 1) / st->hcchar_copy.b.mps; ++ if (nrpackets == 0) ++ nrpackets = 1; ++ st->hcchar_copy.b.multicnt = nrpackets; ++ st->hctsiz_copy.b.pktcnt = nrpackets; ++ ++ /* Initial PID also needs to be set */ ++ if (st->hcchar_copy.b.epdir == 0) { ++ st->hctsiz_copy.b.xfersize = xfer_len; ++ switch (st->hcchar_copy.b.multicnt) { ++ case 1: ++ st->hctsiz_copy.b.pid = DWC_PID_DATA0; ++ break; ++ case 2: ++ case 3: ++ st->hctsiz_copy.b.pid = DWC_PID_MDATA; ++ break; ++ } ++ ++ } else { ++ switch (st->hcchar_copy.b.multicnt) { ++ st->hctsiz_copy.b.xfersize = nrpackets * st->hcchar_copy.b.mps; ++ case 1: ++ st->hctsiz_copy.b.pid = DWC_PID_DATA0; ++ break; ++ case 2: ++ st->hctsiz_copy.b.pid = DWC_PID_DATA1; ++ break; ++ case 3: ++ st->hctsiz_copy.b.pid = DWC_PID_DATA2; ++ break; ++ } ++ } ++ FIQ_WRITE(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ, st->hctsiz_copy.d32); ++ FIQ_WRITE(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR, st->hcchar_copy.d32); ++ /* Channel is enabled on hcint handler exit */ ++ fiq_print(FIQDBG_INT, state, "HSISOOUT"); ++ return 1; ++} ++ ++ ++/** ++ * fiq_fsm_do_sof() - FSM start-of-frame interrupt handler ++ * @state: Pointer to the state struct passed from banked FIQ mode registers. ++ * @num_channels: set according to the DWC hardware configuration ++ * ++ * The SOF handler in FSM mode has two functions ++ * 1. Hold off SOF from causing schedule advancement in IRQ context if there's ++ * nothing to do ++ * 2. Advance certain FSM states that require either a microframe delay, or a microframe ++ * of holdoff. ++ * ++ * The second part is architecture-specific to mach-bcm2835 - ++ * a sane interrupt controller would have a mask register for ARM interrupt sources ++ * to be promoted to the nFIQ line, but it doesn't. Instead a single interrupt ++ * number (USB) can be enabled. This means that certain parts of the USB specification ++ * that require "wait a little while, then issue another packet" cannot be fulfilled with ++ * the timing granularity required to achieve optimal throughout. The workaround is to use ++ * the SOF "timer" (125uS) to perform this task. ++ */ ++static int notrace noinline fiq_fsm_do_sof(struct fiq_state *state, int num_channels) ++{ ++ hfnum_data_t hfnum = { .d32 = FIQ_READ(state->dwc_regs_base + HFNUM) }; ++ int n; ++ int kick_irq = 0; ++ ++ if ((hfnum.b.frnum & 0x7) == 1) { ++ /* We cannot issue csplits for transactions in the last frame past (n+1).1 ++ * Check to see if there are any transactions that are stale. ++ * Boot them out. ++ */ ++ for (n = 0; n < num_channels; n++) { ++ switch (state->channel[n].fsm) { ++ case FIQ_PER_CSPLIT_WAIT: ++ case FIQ_PER_CSPLIT_NYET1: ++ case FIQ_PER_CSPLIT_POLL: ++ case FIQ_PER_CSPLIT_LAST: ++ /* Check if we are no longer in the same full-speed frame. */ ++ if (((state->channel[n].expected_uframe & 0x3FFF) & ~0x7) < ++ (hfnum.b.frnum & ~0x7)) ++ state->channel[n].fsm = FIQ_PER_SPLIT_TIMEOUT; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ ++ for (n = 0; n < num_channels; n++) { ++ switch (state->channel[n].fsm) { ++ ++ case FIQ_NP_SSPLIT_RETRY: ++ case FIQ_NP_IN_CSPLIT_RETRY: ++ case FIQ_NP_OUT_CSPLIT_RETRY: ++ fiq_fsm_restart_channel(state, n, 0); ++ break; ++ ++ case FIQ_HS_ISOC_SLEEPING: ++ state->channel[n].fsm = FIQ_HS_ISOC_TURBO; ++ fiq_fsm_restart_channel(state, n, 0); ++ break; ++ ++ case FIQ_PER_SSPLIT_QUEUED: ++ if ((hfnum.b.frnum & 0x7) == 5) ++ break; ++ if(!fiq_fsm_tt_in_use(state, num_channels, n)) { ++ if (!fiq_fsm_too_late(state, n)) { ++ fiq_print(FIQDBG_INT, st, "SOF GO %01d", n); ++ fiq_fsm_restart_channel(state, n, 0); ++ state->channel[n].fsm = FIQ_PER_SSPLIT_STARTED; ++ } else { ++ state->channel[n].fsm = FIQ_PER_SPLIT_TIMEOUT; ++ state->haintmsk_saved.b2.chint &= ~(1 << n); ++ kick_irq |= 1; ++ } ++ } ++ break; ++ ++ case FIQ_PER_ISO_OUT_PENDING: ++ /* Ordinarily, this should be poked after the SSPLIT ++ * complete interrupt for a competing transfer on the same ++ * TT. Doesn't happen for aborted transactions though. ++ */ ++ if ((hfnum.b.frnum & 0x7) >= 5) ++ break; ++ if (!fiq_fsm_tt_in_use(state, num_channels, n)) { ++ /* Hardware bug. SOF can sometimes occur after the channel halt interrupt ++ * that caused this. ++ */ ++ fiq_fsm_restart_channel(state, n, 0); ++ fiq_print(FIQDBG_INT, state, "SOF ISOC"); ++ if (state->channel[n].nrpackets == 1) { ++ state->channel[n].fsm = FIQ_PER_ISO_OUT_LAST; ++ } else { ++ state->channel[n].fsm = FIQ_PER_ISO_OUT_ACTIVE; ++ } ++ } ++ break; ++ ++ case FIQ_PER_CSPLIT_WAIT: ++ /* we are guaranteed to be in this state if and only if the SSPLIT interrupt ++ * occurred when the bus transaction occurred. The SOF interrupt reversal bug ++ * will utterly bugger this up though. ++ */ ++ if (hfnum.b.frnum != state->channel[n].expected_uframe) { ++ fiq_print(FIQDBG_INT, state, "SOFCS %d ", n); ++ state->channel[n].fsm = FIQ_PER_CSPLIT_POLL; ++ fiq_fsm_restart_channel(state, n, 0); ++ fiq_fsm_start_next_periodic(state, num_channels); ++ ++ } ++ break; ++ ++ case FIQ_PER_SPLIT_TIMEOUT: ++ /* Ugly: we have to force a HCD interrupt. ++ * Poke the mask for the channel in question. ++ * We will take a fake SOF because of this, but ++ * that's OK. ++ */ ++ state->haintmsk_saved.b2.chint &= ~(1 << n); ++ kick_irq |= 1; ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ if (state->kick_np_queues || ++ dwc_frame_num_le(state->next_sched_frame, hfnum.b.frnum)) ++ kick_irq |= 1; ++ ++ return !kick_irq; ++} ++ ++ ++/** ++ * fiq_fsm_do_hcintr() - FSM host channel interrupt handler ++ * @state: Pointer to the FIQ state struct ++ * @num_channels: Number of channels as per hardware config ++ * @n: channel for which HAINT(i) was raised ++ * ++ * An important property is that only the CHHLT interrupt is unmasked. Unfortunately, AHBerr is as well. ++ */ ++static int notrace noinline fiq_fsm_do_hcintr(struct fiq_state *state, int num_channels, int n) ++{ ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ hcint_data_t hcint_probe; ++ hcchar_data_t hcchar; ++ int handled = 0; ++ int restart = 0; ++ int last_csplit = 0; ++ int start_next_periodic = 0; ++ struct fiq_channel_state *st = &state->channel[n]; ++ hfnum_data_t hfnum; ++ ++ hcint.d32 = FIQ_READ(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCINT); ++ hcintmsk.d32 = FIQ_READ(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCINTMSK); ++ hcint_probe.d32 = hcint.d32 & hcintmsk.d32; ++ ++ if (st->fsm != FIQ_PASSTHROUGH) { ++ fiq_print(FIQDBG_INT, state, "HC%01d ST%02d", n, st->fsm); ++ fiq_print(FIQDBG_INT, state, "%08x", hcint.d32); ++ } ++ ++ switch (st->fsm) { ++ ++ case FIQ_PASSTHROUGH: ++ case FIQ_DEQUEUE_ISSUED: ++ /* doesn't belong to us, kick it upstairs */ ++ break; ++ ++ case FIQ_PASSTHROUGH_ERRORSTATE: ++ /* We are here to emulate the error recovery mechanism of the dwc HCD. ++ * Several interrupts are unmasked if a previous transaction failed - it's ++ * death for the FIQ to attempt to handle them as the channel isn't halted. ++ * Emulate what the HCD does in this situation: mask and continue. ++ * The FSM has no other state setup so this has to be handled out-of-band. ++ */ ++ fiq_print(FIQDBG_ERR, state, "ERRST %02d", n); ++ if (hcint_probe.b.nak || hcint_probe.b.ack || hcint_probe.b.datatglerr) { ++ fiq_print(FIQDBG_ERR, state, "RESET %02d", n); ++ st->nr_errors = 0; ++ hcintmsk.b.nak = 0; ++ hcintmsk.b.ack = 0; ++ hcintmsk.b.datatglerr = 0; ++ FIQ_WRITE(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCINTMSK, hcintmsk.d32); ++ return 1; ++ } ++ if (hcint_probe.b.chhltd) { ++ fiq_print(FIQDBG_ERR, state, "CHHLT %02d", n); ++ fiq_print(FIQDBG_ERR, state, "%08x", hcint.d32); ++ return 0; ++ } ++ break; ++ ++ /* Non-periodic state groups */ ++ case FIQ_NP_SSPLIT_STARTED: ++ case FIQ_NP_SSPLIT_RETRY: ++ /* Got a HCINT for a NP SSPLIT. Expected ACK / NAK / fail */ ++ if (hcint.b.ack) { ++ /* SSPLIT complete. For OUT, the data has been sent. For IN, the LS transaction ++ * will start shortly. SOF needs to kick the transaction to prevent a NYET flood. ++ */ ++ if(st->hcchar_copy.b.epdir == 1) ++ st->fsm = FIQ_NP_IN_CSPLIT_RETRY; ++ else ++ st->fsm = FIQ_NP_OUT_CSPLIT_RETRY; ++ st->nr_errors = 0; ++ handled = 1; ++ fiq_fsm_setup_csplit(state, n); ++ } else if (hcint.b.nak) { ++ // No buffer space in TT. Retry on a uframe boundary. ++ st->fsm = FIQ_NP_SSPLIT_RETRY; ++ handled = 1; ++ } else if (hcint.b.xacterr) { ++ // The only other one we care about is xacterr. This implies HS bus error - retry. ++ st->nr_errors++; ++ st->fsm = FIQ_NP_SSPLIT_RETRY; ++ if (st->nr_errors >= 3) { ++ st->fsm = FIQ_NP_SPLIT_HS_ABORTED; ++ } else { ++ handled = 1; ++ restart = 1; ++ } ++ } else { ++ st->fsm = FIQ_NP_SPLIT_LS_ABORTED; ++ handled = 0; ++ restart = 0; ++ } ++ break; ++ ++ case FIQ_NP_IN_CSPLIT_RETRY: ++ /* Received a CSPLIT done interrupt. ++ * Expected Data/NAK/STALL/NYET for IN. ++ */ ++ if (hcint.b.xfercomp) { ++ /* For IN, data is present. */ ++ st->fsm = FIQ_NP_SPLIT_DONE; ++ } else if (hcint.b.nak) { ++ /* no endpoint data. Punt it upstairs */ ++ st->fsm = FIQ_NP_SPLIT_DONE; ++ } else if (hcint.b.nyet) { ++ /* CSPLIT NYET - retry on a uframe boundary. */ ++ handled = 1; ++ st->nr_errors = 0; ++ } else if (hcint.b.datatglerr) { ++ /* data toggle errors do not set the xfercomp bit. */ ++ st->fsm = FIQ_NP_SPLIT_LS_ABORTED; ++ } else if (hcint.b.xacterr) { ++ /* HS error. Retry immediate */ ++ st->fsm = FIQ_NP_IN_CSPLIT_RETRY; ++ st->nr_errors++; ++ if (st->nr_errors >= 3) { ++ st->fsm = FIQ_NP_SPLIT_HS_ABORTED; ++ } else { ++ handled = 1; ++ restart = 1; ++ } ++ } else if (hcint.b.stall) { ++ /* A STALL implies either a LS bus error or a genuine STALL. */ ++ st->fsm = FIQ_NP_SPLIT_LS_ABORTED; ++ } else { ++ /* Hardware bug. It's possible in some cases to ++ * get a channel halt with nothing else set when ++ * the response was a NYET. Treat as local 3-strikes retry. ++ */ ++ hcint_data_t hcint_test = hcint; ++ hcint_test.b.chhltd = 0; ++ if (!hcint_test.d32) { ++ st->nr_errors++; ++ if (st->nr_errors >= 3) { ++ st->fsm = FIQ_NP_SPLIT_HS_ABORTED; ++ } else { ++ handled = 1; ++ } ++ } else { ++ /* Bail out if something unexpected happened */ ++ st->fsm = FIQ_NP_SPLIT_HS_ABORTED; ++ } ++ } ++ break; ++ ++ case FIQ_NP_OUT_CSPLIT_RETRY: ++ /* Received a CSPLIT done interrupt. ++ * Expected ACK/NAK/STALL/NYET/XFERCOMP for OUT.*/ ++ if (hcint.b.xfercomp) { ++ st->fsm = FIQ_NP_SPLIT_DONE; ++ } else if (hcint.b.nak) { ++ // The HCD will implement the holdoff on frame boundaries. ++ st->fsm = FIQ_NP_SPLIT_DONE; ++ } else if (hcint.b.nyet) { ++ // Hub still processing. ++ st->fsm = FIQ_NP_OUT_CSPLIT_RETRY; ++ handled = 1; ++ st->nr_errors = 0; ++ //restart = 1; ++ } else if (hcint.b.xacterr) { ++ /* HS error. retry immediate */ ++ st->fsm = FIQ_NP_OUT_CSPLIT_RETRY; ++ st->nr_errors++; ++ if (st->nr_errors >= 3) { ++ st->fsm = FIQ_NP_SPLIT_HS_ABORTED; ++ } else { ++ handled = 1; ++ restart = 1; ++ } ++ } else if (hcint.b.stall) { ++ /* LS bus error or genuine stall */ ++ st->fsm = FIQ_NP_SPLIT_LS_ABORTED; ++ } else { ++ /* ++ * Hardware bug. It's possible in some cases to get a ++ * channel halt with nothing else set when the response was a NYET. ++ * Treat as local 3-strikes retry. ++ */ ++ hcint_data_t hcint_test = hcint; ++ hcint_test.b.chhltd = 0; ++ if (!hcint_test.d32) { ++ st->nr_errors++; ++ if (st->nr_errors >= 3) { ++ st->fsm = FIQ_NP_SPLIT_HS_ABORTED; ++ } else { ++ handled = 1; ++ } ++ } else { ++ // Something unexpected happened. AHBerror or babble perhaps. Let the IRQ deal with it. ++ st->fsm = FIQ_NP_SPLIT_HS_ABORTED; ++ } ++ } ++ break; ++ ++ /* Periodic split states (except isoc out) */ ++ case FIQ_PER_SSPLIT_STARTED: ++ /* Expect an ACK or failure for SSPLIT */ ++ if (hcint.b.ack) { ++ /* ++ * SSPLIT transfer complete interrupt - the generation of this interrupt is fraught with bugs. ++ * For a packet queued in microframe n-3 to appear in n-2, if the channel is enabled near the EOF1 ++ * point for microframe n-3, the packet will not appear on the bus until microframe n. ++ * Additionally, the generation of the actual interrupt is dodgy. For a packet appearing on the bus ++ * in microframe n, sometimes the interrupt is generated immediately. Sometimes, it appears in n+1 ++ * coincident with SOF for n+1. ++ * SOF is also buggy. It can sometimes be raised AFTER the first bus transaction has taken place. ++ * These appear to be caused by timing/clock crossing bugs within the core itself. ++ * State machine workaround. ++ */ ++ hfnum.d32 = FIQ_READ(state->dwc_regs_base + HFNUM); ++ hcchar.d32 = FIQ_READ(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR); ++ fiq_fsm_setup_csplit(state, n); ++ /* Poke the oddfrm bit. If we are equivalent, we received the interrupt at the correct ++ * time. If not, then we're in the next SOF. ++ */ ++ if ((hfnum.b.frnum & 0x1) == hcchar.b.oddfrm) { ++ fiq_print(FIQDBG_INT, state, "CSWAIT %01d", n); ++ st->expected_uframe = hfnum.b.frnum; ++ st->fsm = FIQ_PER_CSPLIT_WAIT; ++ } else { ++ fiq_print(FIQDBG_INT, state, "CSPOL %01d", n); ++ /* For isochronous IN endpoints, ++ * we need to hold off if we are expecting a lot of data */ ++ if (st->hcchar_copy.b.mps < DATA0_PID_HEURISTIC) { ++ start_next_periodic = 1; ++ } ++ /* Danger will robinson: we are in a broken state. If our first interrupt after ++ * this is a NYET, it will be delayed by 1 uframe and result in an unrecoverable ++ * lag. Unmask the NYET interrupt. ++ */ ++ st->expected_uframe = (hfnum.b.frnum + 1) & 0x3FFF; ++ st->fsm = FIQ_PER_CSPLIT_BROKEN_NYET1; ++ restart = 1; ++ } ++ handled = 1; ++ } else if (hcint.b.xacterr) { ++ /* 3-strikes retry is enabled, we have hit our max nr_errors */ ++ st->fsm = FIQ_PER_SPLIT_HS_ABORTED; ++ start_next_periodic = 1; ++ } else { ++ st->fsm = FIQ_PER_SPLIT_HS_ABORTED; ++ start_next_periodic = 1; ++ } ++ /* We can now queue the next isochronous OUT transaction, if one is pending. */ ++ if(fiq_fsm_tt_next_isoc(state, num_channels, n)) { ++ fiq_print(FIQDBG_INT, state, "NEXTISO "); ++ } ++ break; ++ ++ case FIQ_PER_CSPLIT_NYET1: ++ /* First CSPLIT attempt was a NYET. If we get a subsequent NYET, ++ * we are too late and the TT has dropped its CSPLIT fifo. ++ */ ++ hfnum.d32 = FIQ_READ(state->dwc_regs_base + HFNUM); ++ hcchar.d32 = FIQ_READ(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR); ++ start_next_periodic = 1; ++ if (hcint.b.nak) { ++ st->fsm = FIQ_PER_SPLIT_DONE; ++ } else if (hcint.b.xfercomp) { ++ fiq_increment_dma_buf(state, num_channels, n); ++ st->fsm = FIQ_PER_CSPLIT_POLL; ++ st->nr_errors = 0; ++ if (fiq_fsm_more_csplits(state, n, &last_csplit)) { ++ handled = 1; ++ restart = 1; ++ if (!last_csplit) ++ start_next_periodic = 0; ++ } else { ++ st->fsm = FIQ_PER_SPLIT_DONE; ++ } ++ } else if (hcint.b.nyet) { ++ /* Doh. Data lost. */ ++ st->fsm = FIQ_PER_SPLIT_NYET_ABORTED; ++ } else if (hcint.b.xacterr || hcint.b.stall) { ++ st->fsm = FIQ_PER_SPLIT_LS_ABORTED; ++ } else { ++ st->fsm = FIQ_PER_SPLIT_HS_ABORTED; ++ } ++ break; ++ ++ case FIQ_PER_CSPLIT_BROKEN_NYET1: ++ /* ++ * we got here because our host channel is in the delayed-interrupt ++ * state and we cannot take a NYET interrupt any later than when it ++ * occurred. Disable then re-enable the channel if this happens to force ++ * CSPLITs to occur at the right time. ++ */ ++ hfnum.d32 = FIQ_READ(state->dwc_regs_base + HFNUM); ++ hcchar.d32 = FIQ_READ(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR); ++ fiq_print(FIQDBG_INT, state, "BROK: %01d ", n); ++ if (hcint.b.nak) { ++ st->fsm = FIQ_PER_SPLIT_DONE; ++ start_next_periodic = 1; ++ } else if (hcint.b.xfercomp) { ++ fiq_increment_dma_buf(state, num_channels, n); ++ if (fiq_fsm_more_csplits(state, n, &last_csplit)) { ++ st->fsm = FIQ_PER_CSPLIT_POLL; ++ handled = 1; ++ restart = 1; ++ start_next_periodic = 1; ++ /* Reload HCTSIZ for the next transfer */ ++ fiq_fsm_reload_hctsiz(state, n); ++ if (!last_csplit) ++ start_next_periodic = 0; ++ } else { ++ st->fsm = FIQ_PER_SPLIT_DONE; ++ } ++ } else if (hcint.b.nyet) { ++ st->fsm = FIQ_PER_SPLIT_NYET_ABORTED; ++ start_next_periodic = 1; ++ } else if (hcint.b.xacterr) { ++ /* Local 3-strikes retry is handled by the core. This is a ERR response.*/ ++ st->fsm = FIQ_PER_SPLIT_LS_ABORTED; ++ } else { ++ fiq_print(FIQDBG_INT, state, "TOGGLES"); ++ BUG(); ++ } ++ break; ++ ++ case FIQ_PER_CSPLIT_POLL: ++ hfnum.d32 = FIQ_READ(state->dwc_regs_base + HFNUM); ++ hcchar.d32 = FIQ_READ(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR); ++ start_next_periodic = 1; ++ if (hcint.b.nak) { ++ st->fsm = FIQ_PER_SPLIT_DONE; ++ } else if (hcint.b.xfercomp) { ++ fiq_increment_dma_buf(state, num_channels, n); ++ if (fiq_fsm_more_csplits(state, n, &last_csplit)) { ++ handled = 1; ++ restart = 1; ++ /* Reload HCTSIZ for the next transfer */ ++ fiq_fsm_reload_hctsiz(state, n); ++ if (!last_csplit) ++ start_next_periodic = 0; ++ } else { ++ st->fsm = FIQ_PER_SPLIT_DONE; ++ } ++ } else if (hcint.b.nyet) { ++ /* Are we a NYET after the first data packet? */ ++ if (st->nrpackets == 0) { ++ st->fsm = FIQ_PER_CSPLIT_NYET1; ++ handled = 1; ++ restart = 1; ++ } else { ++ /* We got a NYET when polling CSPLITs. Can happen ++ * if our heuristic fails, or if someone disables us ++ * for any significant length of time. ++ */ ++ if (st->nr_errors >= 3) { ++ st->fsm = FIQ_PER_SPLIT_NYET_ABORTED; ++ } else { ++ st->fsm = FIQ_PER_SPLIT_DONE; ++ } ++ } ++ } else if (hcint.b.xacterr || hcint.b.stall) { ++ /* For xacterr, Local 3-strikes retry is handled by the core. This is a ERR response.*/ ++ st->fsm = FIQ_PER_SPLIT_LS_ABORTED; ++ } else if (hcint.b.datatglerr) { ++ fiq_print(FIQDBG_INT, state, "TOGGLES"); ++ BUG(); ++ } else { ++ st->fsm = FIQ_PER_SPLIT_HS_ABORTED; ++ } ++ break; ++ ++ case FIQ_HS_ISOC_TURBO: ++ if (fiq_fsm_update_hs_isoc(state, n, hcint)) { ++ /* more transactions to come */ ++ handled = 1; ++ restart = 1; ++ fiq_print(FIQDBG_INT, state, "HSISO M "); ++ } else { ++ st->fsm = FIQ_HS_ISOC_DONE; ++ fiq_print(FIQDBG_INT, state, "HSISO F "); ++ } ++ break; ++ ++ case FIQ_HS_ISOC_ABORTED: ++ /* This abort is called by the driver rewriting the state mid-transaction ++ * which allows the dequeue mechanism to work more effectively. ++ */ ++ break; ++ ++ case FIQ_PER_ISO_OUT_ACTIVE: ++ if (hcint.b.ack) { ++ if(fiq_iso_out_advance(state, num_channels, n)) { ++ /* last OUT transfer */ ++ st->fsm = FIQ_PER_ISO_OUT_LAST; ++ /* ++ * Assuming the periodic FIFO in the dwc core ++ * actually does its job properly, we can queue ++ * the next ssplit now and in theory, the wire ++ * transactions will be in-order. ++ */ ++ // No it doesn't. It appears to process requests in host channel order. ++ //start_next_periodic = 1; ++ } ++ handled = 1; ++ restart = 1; ++ } else { ++ /* ++ * Isochronous transactions carry on regardless. Log the error ++ * and continue. ++ */ ++ //explode += 1; ++ st->nr_errors++; ++ if(fiq_iso_out_advance(state, num_channels, n)) { ++ st->fsm = FIQ_PER_ISO_OUT_LAST; ++ //start_next_periodic = 1; ++ } ++ handled = 1; ++ restart = 1; ++ } ++ break; ++ ++ case FIQ_PER_ISO_OUT_LAST: ++ if (hcint.b.ack) { ++ /* All done here */ ++ st->fsm = FIQ_PER_ISO_OUT_DONE; ++ } else { ++ st->fsm = FIQ_PER_ISO_OUT_DONE; ++ st->nr_errors++; ++ } ++ start_next_periodic = 1; ++ break; ++ ++ case FIQ_PER_SPLIT_TIMEOUT: ++ /* SOF kicked us because we overran. */ ++ start_next_periodic = 1; ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (handled) { ++ FIQ_WRITE(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCINT, hcint.d32); ++ } else { ++ /* Copy the regs into the state so the IRQ knows what to do */ ++ st->hcint_copy.d32 = hcint.d32; ++ } ++ ++ if (restart) { ++ /* Restart always implies handled. */ ++ if (restart == 2) { ++ /* For complete-split INs, the show must go on. ++ * Force a channel restart */ ++ fiq_fsm_restart_channel(state, n, 1); ++ } else { ++ fiq_fsm_restart_channel(state, n, 0); ++ } ++ } ++ if (start_next_periodic) { ++ fiq_fsm_start_next_periodic(state, num_channels); ++ } ++ if (st->fsm != FIQ_PASSTHROUGH) ++ fiq_print(FIQDBG_INT, state, "FSMOUT%02d", st->fsm); ++ ++ return handled; ++} ++ ++ ++/** ++ * dwc_otg_fiq_fsm() - Flying State Machine (monster) FIQ ++ * @state: pointer to state struct passed from the banked FIQ mode registers. ++ * @num_channels: set according to the DWC hardware configuration ++ * @dma: pointer to DMA bounce buffers for split transaction slots ++ * ++ * The FSM FIQ performs the low-level tasks that normally would be performed by the microcode ++ * inside an EHCI or similar host controller regarding split transactions. The DWC core ++ * interrupts each and every time a split transaction packet is received or sent successfully. ++ * This results in either an interrupt storm when everything is working "properly", or ++ * the interrupt latency of the system in general breaks time-sensitive periodic split ++ * transactions. Pushing the low-level, but relatively easy state machine work into the FIQ ++ * solves these problems. ++ * ++ * Return: void ++ */ ++void notrace dwc_otg_fiq_fsm(struct fiq_state *state, int num_channels) ++{ ++ gintsts_data_t gintsts, gintsts_handled; ++ gintmsk_data_t gintmsk; ++ //hfnum_data_t hfnum; ++ haint_data_t haint, haint_handled; ++ haintmsk_data_t haintmsk; ++ int kick_irq = 0; ++ ++ gintsts_handled.d32 = 0; ++ haint_handled.d32 = 0; ++ ++ gintsts.d32 = FIQ_READ(state->dwc_regs_base + GINTSTS); ++ gintmsk.d32 = FIQ_READ(state->dwc_regs_base + GINTMSK); ++ gintsts.d32 &= gintmsk.d32; ++ ++ if (gintsts.b.sofintr) { ++ /* For FSM mode, SOF is required to keep the state machine advance for ++ * certain stages of the periodic pipeline. It's death to mask this ++ * interrupt in that case. ++ */ ++ ++ if (!fiq_fsm_do_sof(state, num_channels)) { ++ /* Kick IRQ once. Queue advancement means that all pending transactions ++ * will get serviced when the IRQ finally executes. ++ */ ++ if (state->gintmsk_saved.b.sofintr == 1) ++ kick_irq |= 1; ++ state->gintmsk_saved.b.sofintr = 0; ++ } ++ gintsts_handled.b.sofintr = 1; ++ } ++ ++ if (gintsts.b.hcintr) { ++ int i; ++ haint.d32 = FIQ_READ(state->dwc_regs_base + HAINT); ++ haintmsk.d32 = FIQ_READ(state->dwc_regs_base + HAINTMSK); ++ haint.d32 &= haintmsk.d32; ++ haint_handled.d32 = 0; ++ for (i=0; i<num_channels; i++) { ++ if (haint.b2.chint & (1 << i)) { ++ if(!fiq_fsm_do_hcintr(state, num_channels, i)) { ++ /* HCINT was not handled in FIQ ++ * HAINT is level-sensitive, leading to level-sensitive ginststs.b.hcint bit. ++ * Mask HAINT(i) but keep top-level hcint unmasked. ++ */ ++ state->haintmsk_saved.b2.chint &= ~(1 << i); ++ } else { ++ /* do_hcintr cleaned up after itself, but clear haint */ ++ haint_handled.b2.chint |= (1 << i); ++ } ++ } ++ } ++ ++ if (haint_handled.b2.chint) { ++ FIQ_WRITE(state->dwc_regs_base + HAINT, haint_handled.d32); ++ } ++ ++ if (haintmsk.d32 != (haintmsk.d32 & state->haintmsk_saved.d32)) { ++ /* ++ * This is necessary to avoid multiple retriggers of the MPHI in the case ++ * where interrupts are held off and HCINTs start to pile up. ++ * Only wake up the IRQ if a new interrupt came in, was not handled and was ++ * masked. ++ */ ++ haintmsk.d32 &= state->haintmsk_saved.d32; ++ FIQ_WRITE(state->dwc_regs_base + HAINTMSK, haintmsk.d32); ++ kick_irq |= 1; ++ } ++ /* Top-Level interrupt - always handled because it's level-sensitive */ ++ gintsts_handled.b.hcintr = 1; ++ } ++ ++ ++ /* Clear the bits in the saved register that were not handled but were triggered. */ ++ state->gintmsk_saved.d32 &= ~(gintsts.d32 & ~gintsts_handled.d32); ++ ++ /* FIQ didn't handle something - mask has changed - write new mask */ ++ if (gintmsk.d32 != (gintmsk.d32 & state->gintmsk_saved.d32)) { ++ gintmsk.d32 &= state->gintmsk_saved.d32; ++ gintmsk.b.sofintr = 1; ++ FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32); ++// fiq_print(FIQDBG_INT, state, "KICKGINT"); ++// fiq_print(FIQDBG_INT, state, "%08x", gintmsk.d32); ++// fiq_print(FIQDBG_INT, state, "%08x", state->gintmsk_saved.d32); ++ kick_irq |= 1; ++ } ++ ++ if (gintsts_handled.d32) { ++ /* Only applies to edge-sensitive bits in GINTSTS */ ++ FIQ_WRITE(state->dwc_regs_base + GINTSTS, gintsts_handled.d32); ++ } ++ ++ /* We got an interrupt, didn't handle it. */ ++ if (kick_irq) { ++ state->mphi_int_count++; ++ FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send); ++ FIQ_WRITE(state->mphi_regs.outddb, (1<<29)); ++ ++ } ++ state->fiq_done++; ++ mb(); ++} ++ ++ ++/** ++ * dwc_otg_fiq_nop() - FIQ "lite" ++ * @state: pointer to state struct passed from the banked FIQ mode registers. ++ * ++ * The "nop" handler does not intervene on any interrupts other than SOF. ++ * It is limited in scope to deciding at each SOF if the IRQ SOF handler (which deals ++ * with non-periodic/periodic queues) needs to be kicked. ++ * ++ * This is done to hold off the SOF interrupt, which occurs at a rate of 8000 per second. ++ * ++ * Return: void ++ */ ++void notrace dwc_otg_fiq_nop(struct fiq_state *state) ++{ ++ gintsts_data_t gintsts, gintsts_handled; ++ gintmsk_data_t gintmsk; ++ hfnum_data_t hfnum; ++ ++ hfnum.d32 = FIQ_READ(state->dwc_regs_base + HFNUM); ++ gintsts.d32 = FIQ_READ(state->dwc_regs_base + GINTSTS); ++ gintmsk.d32 = FIQ_READ(state->dwc_regs_base + GINTMSK); ++ gintsts.d32 &= gintmsk.d32; ++ gintsts_handled.d32 = 0; ++ ++ if (gintsts.b.sofintr) { ++ if (!state->kick_np_queues && ++ dwc_frame_num_gt(state->next_sched_frame, hfnum.b.frnum)) { ++ /* SOF handled, no work to do, just ACK interrupt */ ++ gintsts_handled.b.sofintr = 1; ++ } else { ++ /* Kick IRQ */ ++ state->gintmsk_saved.b.sofintr = 0; ++ } ++ } ++ ++ /* Reset handled interrupts */ ++ if(gintsts_handled.d32) { ++ FIQ_WRITE(state->dwc_regs_base + GINTSTS, gintsts_handled.d32); ++ } ++ ++ /* Clear the bits in the saved register that were not handled but were triggered. */ ++ state->gintmsk_saved.d32 &= ~(gintsts.d32 & ~gintsts_handled.d32); ++ ++ /* We got an interrupt, didn't handle it and want to mask it */ ++ if (~(state->gintmsk_saved.d32)) { ++ state->mphi_int_count++; ++ gintmsk.d32 &= state->gintmsk_saved.d32; ++ FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32); ++ /* Force a clear before another dummy send */ ++ FIQ_WRITE(state->mphi_regs.intstat, (1<<29)); ++ FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send); ++ FIQ_WRITE(state->mphi_regs.outddb, (1<<29)); ++ ++ } ++ state->fiq_done++; ++ mb(); ++} +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h 2014-04-24 16:04:39.819124254 +0200 +@@ -0,0 +1,353 @@ ++/* ++ * dwc_otg_fiq_fsm.h - Finite state machine FIQ header definitions ++ * ++ * Copyright (c) 2013 Raspberry Pi Foundation ++ * ++ * Author: Jonathan Bell <jonathan@raspberrypi.org> ++ * 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 Raspberry Pi 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 FIQ implements functionality that performs split transactions on ++ * the dwc_otg hardware without any outside intervention. A split transaction ++ * is "queued" by nominating a specific host channel to perform the entirety ++ * of a split transaction. This FIQ will then perform the microframe-precise ++ * scheduling required in each phase of the transaction until completion. ++ * ++ * The FIQ functionality has been surgically implanted into the Synopsys ++ * vendor-provided driver. ++ * ++ */ ++ ++#ifndef DWC_OTG_FIQ_FSM_H_ ++#define DWC_OTG_FIQ_FSM_H_ ++ ++#include "dwc_otg_regs.h" ++#include "dwc_otg_cil.h" ++#include "dwc_otg_hcd.h" ++#include <linux/kernel.h> ++#include <linux/irqflags.h> ++#include <linux/string.h> ++#include <asm/barrier.h> ++ ++#if 0 ++#define FLAME_ON(x) \ ++do { \ ++ int gpioreg; \ ++ \ ++ gpioreg = readl(__io_address(0x20200000+0x8)); \ ++ gpioreg &= ~(7 << (x-20)*3); \ ++ gpioreg |= 0x1 << (x-20)*3; \ ++ writel(gpioreg, __io_address(0x20200000+0x8)); \ ++ \ ++ writel(1<<x, __io_address(0x20200000+(0x1C))); \ ++} while (0) ++ ++#define FLAME_OFF(x) \ ++do { \ ++ writel(1<<x, __io_address(0x20200000+(0x28))); \ ++} while (0) ++#else ++#define FLAME_ON(x) do { } while (0) ++#define FLAME_OFF(X) do { } while (0) ++#endif ++ ++/* This is a quick-and-dirty arch-specific register read/write. We know that ++ * writes to a peripheral on BCM2835 will always arrive in-order, also that ++ * reads and writes are executed in-order therefore the need for memory barriers ++ * is obviated if we're only talking to USB. ++ */ ++#define FIQ_WRITE(_addr_,_data_) (*(volatile unsigned int *) (_addr_) = (_data_)) ++#define FIQ_READ(_addr_) (*(volatile unsigned int *) (_addr_)) ++ ++/* FIQ-ified register definitions. Offsets are from dwc_regs_base. */ ++#define GINTSTS 0x014 ++#define GINTMSK 0x018 ++/* Debug register. Poll the top of the received packets FIFO. */ ++#define GRXSTSR 0x01C ++#define HFNUM 0x408 ++#define HAINT 0x414 ++#define HAINTMSK 0x418 ++#define HPRT0 0x440 ++ ++/* HC_regs start from an offset of 0x500 */ ++#define HC_START 0x500 ++#define HC_OFFSET 0x020 ++ ++#define HC_DMA 0x514 ++ ++#define HCCHAR 0x00 ++#define HCSPLT 0x04 ++#define HCINT 0x08 ++#define HCINTMSK 0x0C ++#define HCTSIZ 0x10 ++ ++#define ISOC_XACTPOS_ALL 0b11 ++#define ISOC_XACTPOS_BEGIN 0b10 ++#define ISOC_XACTPOS_MID 0b00 ++#define ISOC_XACTPOS_END 0b01 ++ ++#define DWC_PID_DATA2 0b01 ++#define DWC_PID_MDATA 0b11 ++#define DWC_PID_DATA1 0b10 ++#define DWC_PID_DATA0 0b00 ++ ++typedef struct { ++ volatile void* base; ++ volatile void* ctrl; ++ volatile void* outdda; ++ volatile void* outddb; ++ volatile void* intstat; ++} mphi_regs_t; ++ ++ ++enum fiq_debug_level { ++ FIQDBG_SCHED = (1 << 0), ++ FIQDBG_INT = (1 << 1), ++ FIQDBG_ERR = (1 << 2), ++ FIQDBG_PORTHUB = (1 << 3), ++}; ++ ++struct fiq_state; ++ ++extern void _fiq_print (enum fiq_debug_level dbg_lvl, volatile struct fiq_state *state, char *fmt, ...); ++#if 0 ++#define fiq_print _fiq_print ++#else ++#define fiq_print(x, y, ...) ++#endif ++ ++extern bool fiq_enable, fiq_fsm_enable; ++extern ushort nak_holdoff; ++ ++/** ++ * enum fiq_fsm_state - The FIQ FSM states. ++ * ++ * This is the "core" of the FIQ FSM. Broadly, the FSM states follow the ++ * USB2.0 specification for host responses to various transaction states. ++ * There are modifications to this host state machine because of a variety of ++ * quirks and limitations in the dwc_otg hardware. ++ * ++ * The fsm state is also used to communicate back to the driver on completion of ++ * a split transaction. The end states are used in conjunction with the interrupts ++ * raised by the final transaction. ++ */ ++enum fiq_fsm_state { ++ /* FIQ isn't enabled for this host channel */ ++ FIQ_PASSTHROUGH = 0, ++ /* For the first interrupt received for this channel, ++ * the FIQ has to ack any interrupts indicating success. */ ++ FIQ_PASSTHROUGH_ERRORSTATE = 31, ++ /* Nonperiodic state groups */ ++ FIQ_NP_SSPLIT_STARTED = 1, ++ FIQ_NP_SSPLIT_RETRY = 2, ++ FIQ_NP_OUT_CSPLIT_RETRY = 3, ++ FIQ_NP_IN_CSPLIT_RETRY = 4, ++ FIQ_NP_SPLIT_DONE = 5, ++ FIQ_NP_SPLIT_LS_ABORTED = 6, ++ /* This differentiates a HS transaction error from a LS one ++ * (handling the hub state is different) */ ++ FIQ_NP_SPLIT_HS_ABORTED = 7, ++ ++ /* Periodic state groups */ ++ /* Periodic transactions are either started directly by the IRQ handler ++ * or deferred if the TT is already in use. ++ */ ++ FIQ_PER_SSPLIT_QUEUED = 8, ++ FIQ_PER_SSPLIT_STARTED = 9, ++ FIQ_PER_SSPLIT_LAST = 10, ++ ++ ++ FIQ_PER_ISO_OUT_PENDING = 11, ++ FIQ_PER_ISO_OUT_ACTIVE = 12, ++ FIQ_PER_ISO_OUT_LAST = 13, ++ FIQ_PER_ISO_OUT_DONE = 27, ++ ++ FIQ_PER_CSPLIT_WAIT = 14, ++ FIQ_PER_CSPLIT_NYET1 = 15, ++ FIQ_PER_CSPLIT_BROKEN_NYET1 = 28, ++ FIQ_PER_CSPLIT_NYET_FAFF = 29, ++ /* For multiple CSPLITs (large isoc IN, or delayed interrupt) */ ++ FIQ_PER_CSPLIT_POLL = 16, ++ /* The last CSPLIT for a transaction has been issued, differentiates ++ * for the state machine to queue the next packet. ++ */ ++ FIQ_PER_CSPLIT_LAST = 17, ++ ++ FIQ_PER_SPLIT_DONE = 18, ++ FIQ_PER_SPLIT_LS_ABORTED = 19, ++ FIQ_PER_SPLIT_HS_ABORTED = 20, ++ FIQ_PER_SPLIT_NYET_ABORTED = 21, ++ /* Frame rollover has occurred without the transaction finishing. */ ++ FIQ_PER_SPLIT_TIMEOUT = 22, ++ ++ /* FIQ-accelerated HS Isochronous state groups */ ++ FIQ_HS_ISOC_TURBO = 23, ++ /* For interval > 1, SOF wakes up the isochronous FSM */ ++ FIQ_HS_ISOC_SLEEPING = 24, ++ FIQ_HS_ISOC_DONE = 25, ++ FIQ_HS_ISOC_ABORTED = 26, ++ FIQ_DEQUEUE_ISSUED = 30, ++ FIQ_TEST = 32, ++}; ++ ++struct fiq_stack { ++ int magic1; ++ uint8_t stack[2048]; ++ int magic2; ++}; ++ ++ ++/** ++ * struct fiq_dma_info - DMA bounce buffer utilisation information (per-channel) ++ * @index: Number of slots reported used for IN transactions / number of slots ++ * transmitted for an OUT transaction ++ * @slot_len[6]: Number of actual transfer bytes in each slot (255 if unused) ++ * ++ * Split transaction transfers can have variable length depending on other bus ++ * traffic. The OTG core DMA engine requires 4-byte aligned addresses therefore ++ * each transaction needs a guaranteed aligned address. A maximum of 6 split transfers ++ * can happen per-frame. ++ */ ++struct fiq_dma_info { ++ u8 index; ++ u8 slot_len[6]; ++}; ++ ++struct __attribute__((packed)) fiq_split_dma_slot { ++ u8 buf[188]; ++}; ++ ++struct fiq_dma_channel { ++ struct __attribute__((packed)) fiq_split_dma_slot index[6]; ++}; ++ ++struct fiq_dma_blob { ++ struct __attribute__((packed)) fiq_dma_channel channel[0]; ++}; ++ ++/** ++ * struct fiq_hs_isoc_info - USB2.0 isochronous data ++ * @iso_frame: Pointer to the array of OTG URB iso_frame_descs. ++ * @nrframes: Total length of iso_frame_desc array ++ * @index: Current index (FIQ-maintained) ++ * ++ */ ++struct fiq_hs_isoc_info { ++ struct dwc_otg_hcd_iso_packet_desc *iso_desc; ++ unsigned int nrframes; ++ unsigned int index; ++}; ++ ++/** ++ * struct fiq_channel_state - FIQ state machine storage ++ * @fsm: Current state of the channel as understood by the FIQ ++ * @nr_errors: Number of transaction errors on this split-transaction ++ * @hub_addr: SSPLIT/CSPLIT destination hub ++ * @port_addr: SSPLIT/CSPLIT destination port - always 1 if single TT hub ++ * @nrpackets: For isoc OUT, the number of split-OUT packets to transmit. For ++ * split-IN, number of CSPLIT data packets that were received. ++ * @hcchar_copy: ++ * @hcsplt_copy: ++ * @hcintmsk_copy: ++ * @hctsiz_copy: Copies of the host channel registers. ++ * For use as scratch, or for returning state. ++ * ++ * The fiq_channel_state is state storage between interrupts for a host channel. The ++ * FSM state is stored here. Members of this structure must only be set up by the ++ * driver prior to enabling the FIQ for this host channel, and not touched until the FIQ ++ * has updated the state to either a COMPLETE state group or ABORT state group. ++ */ ++ ++struct fiq_channel_state { ++ enum fiq_fsm_state fsm; ++ unsigned int nr_errors; ++ unsigned int hub_addr; ++ unsigned int port_addr; ++ /* Hardware bug workaround: sometimes channel halt interrupts are ++ * delayed until the next SOF. Keep track of when we expected to get interrupted. */ ++ unsigned int expected_uframe; ++ /* in/out for communicating number of dma buffers used, or number of ISOC to do */ ++ unsigned int nrpackets; ++ struct fiq_dma_info dma_info; ++ struct fiq_hs_isoc_info hs_isoc_info; ++ /* Copies of HC registers - in/out communication from/to IRQ handler ++ * and for ease of channel setup. A bit of mungeing is performed - for ++ * example the hctsiz.b.maxp is _always_ the max packet size of the endpoint. ++ */ ++ hcchar_data_t hcchar_copy; ++ hcsplt_data_t hcsplt_copy; ++ hcint_data_t hcint_copy; ++ hcintmsk_data_t hcintmsk_copy; ++ hctsiz_data_t hctsiz_copy; ++ hcdma_data_t hcdma_copy; ++}; ++ ++/** ++ * struct fiq_state - top-level FIQ state machine storage ++ * @mphi_regs: virtual address of the MPHI peripheral register file ++ * @dwc_regs_base: virtual address of the base of the DWC core register file ++ * @dma_base: physical address for the base of the DMA bounce buffers ++ * @dummy_send: Scratch area for sending a fake message to the MPHI peripheral ++ * @gintmsk_saved: Top-level mask of interrupts that the FIQ has not handled. ++ * Used for determining which interrupts fired to set off the IRQ handler. ++ * @haintmsk_saved: Mask of interrupts from host channels that the FIQ did not handle internally. ++ * @np_count: Non-periodic transactions in the active queue ++ * @np_sent: Count of non-periodic transactions that have completed ++ * @next_sched_frame: For periodic transactions handled by the driver's SOF-driven queuing mechanism, ++ * this is the next frame on which a SOF interrupt is required. Used to hold off ++ * passing SOF through to the driver until necessary. ++ * @channel[n]: Per-channel FIQ state. Allocated during init depending on the number of host ++ * channels configured into the core logic. ++ * ++ * This is passed as the first argument to the dwc_otg_fiq_fsm top-level FIQ handler from the asm stub. ++ * It contains top-level state information. ++ */ ++struct fiq_state { ++ mphi_regs_t mphi_regs; ++ void *dwc_regs_base; ++ dma_addr_t dma_base; ++ struct fiq_dma_blob *fiq_dmab; ++ void *dummy_send; ++ gintmsk_data_t gintmsk_saved; ++ haintmsk_data_t haintmsk_saved; ++ int mphi_int_count; ++ unsigned int fiq_done; ++ unsigned int kick_np_queues; ++ unsigned int next_sched_frame; ++#ifdef FIQ_DEBUG ++ char * buffer; ++ unsigned int bufsiz; ++#endif ++ struct fiq_channel_state channel[0]; ++}; ++ ++extern int fiq_fsm_too_late(struct fiq_state *st, int n); ++ ++extern int fiq_fsm_tt_in_use(struct fiq_state *st, int num_channels, int n); ++ ++extern void dwc_otg_fiq_fsm(struct fiq_state *state, int num_channels); ++ ++extern void dwc_otg_fiq_nop(struct fiq_state *state); ++ ++#endif /* DWC_OTG_FIQ_FSM_H_ */ +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S 2014-04-24 16:04:39.819124254 +0200 +@@ -0,0 +1,81 @@ ++/* ++ * dwc_otg_fiq_fsm.S - assembly stub for the FSM FIQ ++ * ++ * Copyright (c) 2013 Raspberry Pi Foundation ++ * ++ * Author: Jonathan Bell <jonathan@raspberrypi.org> ++ * 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 Raspberry Pi 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. ++ */ ++ ++ ++#include <asm/assembler.h> ++#include <linux/linkage.h> ++ ++ ++.text ++ ++.global _dwc_otg_fiq_stub_end; ++ ++/** ++ * _dwc_otg_fiq_stub() - entry copied to the FIQ vector page to allow ++ * a C-style function call with arguments from the FIQ banked registers. ++ * r0 = &hcd->fiq_state ++ * r1 = &hcd->num_channels ++ * r2 = &hcd->dma_buffers ++ * Tramples: r0, r1, r2, r4, fp, ip ++ */ ++ ++ENTRY(_dwc_otg_fiq_stub) ++ /* Stash unbanked regs - SP will have been set up for us */ ++ mov ip, sp; ++ stmdb sp!, {r0-r12, lr}; ++#ifdef FIQ_DEBUG ++ // Cycle profiling - read cycle counter at start ++ mrc p15, 0, r5, c15, c12, 1; ++#endif ++ /* r11 = fp, don't trample it */ ++ mov r4, fp; ++ /* set EABI frame size */ ++ sub fp, ip, #512; ++ ++ /* for fiq NOP mode - just need state */ ++ mov r0, r8; ++ /* r9 = num_channels */ ++ mov r1, r9; ++ /* r10 = struct *dma_bufs */ ++// mov r2, r10; ++ ++ /* r4 = &fiq_c_function */ ++ blx r4; ++#ifdef FIQ_DEBUG ++ mrc p15, 0, r4, c15, c12, 1; ++ subs r5, r5, r4; ++ // r5 is now the cycle count time for executing the FIQ. Store it somewhere? ++#endif ++ ldmia sp!, {r0-r12, lr}; ++ subs pc, lr, #4; ++_dwc_otg_fiq_stub_end: ++END(_dwc_otg_fiq_stub) ++ +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 2014-04-24 16:04:39.819124254 +0200 +@@ -0,0 +1,4188 @@ + +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $ @@ -68572,9 +71052,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + +#include "dwc_otg_hcd.h" +#include "dwc_otg_regs.h" -+#include "dwc_otg_mphi_fix.h" ++#include "dwc_otg_fiq_fsm.h" + -+extern bool microframe_schedule, nak_holdoff_enable; ++extern bool microframe_schedule; ++extern uint16_t fiq_fsm_mask, nak_holdoff; + +//#define DEBUG_HOST_CHANNELS +#ifdef DEBUG_HOST_CHANNELS @@ -68584,12 +71065,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p +static int last_sel_trans_num_avail_hc_at_end = 0; +#endif /* DEBUG_HOST_CHANNELS */ + -+extern int g_next_sched_frame, g_np_count, g_np_sent; -+ -+extern haint_data_t haint_saved; -+extern hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS]; -+extern hcint_data_t hcint_saved[MAX_EPS_CHANNELS]; -+extern gintsts_data_t ginsts_saved; + +dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void) +{ @@ -68822,7 +71297,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + */ + dwc_otg_hcd->flags.b.port_connect_status_change = 1; + dwc_otg_hcd->flags.b.port_connect_status = 0; -+ if(fiq_fix_enable) ++ if(fiq_enable) + local_fiq_disable(); + /* + * Shutdown any transfers in process by clearing the Tx FIFO Empty @@ -68919,20 +71394,15 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + channel->qh = NULL; + } + } -+ if(fiq_split_enable) { ++ if(fiq_fsm_enable) { + for(i=0; i < 128; i++) { + dwc_otg_hcd->hub_port[i] = 0; + } -+ haint_saved.d32 = 0; -+ for(i=0; i < MAX_EPS_CHANNELS; i++) { -+ hcint_saved[i].d32 = 0; -+ hcintmsk_saved[i].d32 = 0; -+ } + } + + } + -+ if(fiq_fix_enable) ++ if(fiq_enable) + local_fiq_enable(); + + if (dwc_otg_hcd->fops->disconnect) { @@ -69069,7 +71539,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + } +#endif + intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk); -+ if(!intr_mask.b.sofintr) needs_scheduling = 1; ++ if(!intr_mask.b.sofintr || fiq_enable) needs_scheduling = 1; + if((((dwc_otg_qh_t *)ep_handle)->ep_type == UE_BULK) && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) + /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */ + needs_scheduling = 0; @@ -69140,6 +71610,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + if (urb_qtd->in_process && qh->channel) { + /* The QTD is in process (it has been assigned to a channel). */ + if (hcd->flags.b.port_connect_status) { ++ int n = qh->channel->hc_num; + /* + * If still connected (i.e. in host mode), halt the + * channel so it can be used for other transfers. If @@ -69147,10 +71618,14 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + * written to halt the channel since the core is in + * device mode. + */ ++ /* In FIQ FSM mode, we need to shut down carefully. ++ * The FIQ may attempt to restart a disabled channel */ ++ if (fiq_fsm_enable && (hcd->fiq_state->channel[n].fsm != FIQ_PASSTHROUGH)) { ++ hcd->fiq_state->channel[n].fsm = FIQ_DEQUEUE_ISSUED; ++ } + dwc_otg_hc_halt(hcd->core_if, qh->channel, + DWC_OTG_HC_XFER_URB_DEQUEUE); + -+ dwc_otg_hcd_release_port(hcd, qh); + } + } + @@ -69286,7 +71761,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + + usb_hcd_giveback_urb(hcd->priv, urb, urb->status); + -+ fiq_print(FIQDBG_PORTHUB, "COMPLETE"); + + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); + } @@ -69381,6 +71855,34 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + cil_hcd_start(core_if); +} + ++void dwc_otg_cleanup_fiq_channel(dwc_otg_hcd_t *hcd, uint32_t num) ++{ ++ struct fiq_channel_state *st = &hcd->fiq_state->channel[num]; ++ struct fiq_dma_blob *blob = hcd->fiq_dmab; ++ int i; ++ ++ st->fsm = FIQ_PASSTHROUGH; ++ st->hcchar_copy.d32 = 0; ++ st->hcsplt_copy.d32 = 0; ++ st->hcint_copy.d32 = 0; ++ st->hcintmsk_copy.d32 = 0; ++ st->hctsiz_copy.d32 = 0; ++ st->hcdma_copy.d32 = 0; ++ st->nr_errors = 0; ++ st->hub_addr = 0; ++ st->port_addr = 0; ++ st->expected_uframe = 0; ++ st->nrpackets = 0; ++ st->dma_info.index = 0; ++ for (i = 0; i < 6; i++) ++ st->dma_info.slot_len[i] = 255; ++ st->hs_isoc_info.index = 0; ++ st->hs_isoc_info.iso_desc = NULL; ++ st->hs_isoc_info.nrframes = 0; ++ ++ DWC_MEMSET(&blob->channel[num].index[0], 0x6b, 1128); ++} ++ +/** + * Frees secondary storage associated with the dwc_otg_hcd structure contained + * in the struct usb_hcd field. @@ -69434,6 +71936,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + DWC_TIMER_FREE(dwc_otg_hcd->conn_timer); + DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet); + DWC_TASK_FREE(dwc_otg_hcd->completion_tasklet); ++ DWC_FREE(dwc_otg_hcd->fiq_state); + +#ifdef DWC_DEV_SRPCAP + if (dwc_otg_hcd->core_if->power_down == 2 && @@ -69506,6 +72009,59 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + channel); + } + ++ if (fiq_enable) { ++ hcd->fiq_state = DWC_ALLOC(sizeof(struct fiq_state) + (sizeof(struct fiq_channel_state) * num_channels)); ++ if (!hcd->fiq_state) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: cannot allocate fiq_state structure\n", __func__); ++ dwc_otg_hcd_free(hcd); ++ goto out; ++ } ++ DWC_MEMSET(hcd->fiq_state, 0, (sizeof(struct fiq_state) + (sizeof(struct fiq_channel_state) * num_channels))); ++ ++ for (i = 0; i < num_channels; i++) { ++ hcd->fiq_state->channel[i].fsm = FIQ_PASSTHROUGH; ++ } ++ hcd->fiq_state->dummy_send = DWC_ALLOC_ATOMIC(16); ++ ++ hcd->fiq_stack = DWC_ALLOC(sizeof(struct fiq_stack)); ++ if (!hcd->fiq_stack) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: cannot allocate fiq_stack structure\n", __func__); ++ dwc_otg_hcd_free(hcd); ++ goto out; ++ } ++ hcd->fiq_stack->magic1 = 0xDEADBEEF; ++ hcd->fiq_stack->magic2 = 0xD00DFEED; ++ hcd->fiq_state->gintmsk_saved.d32 = ~0; ++ hcd->fiq_state->haintmsk_saved.b2.chint = ~0; ++ ++ /* This bit is terrible and uses no API, but necessary. The FIQ has no concept of DMA pools ++ * (and if it did, would be a lot slower). This allocates a chunk of memory (~9kiB for 8 host channels) ++ * for use as transaction bounce buffers in a 2-D array. Our access into this chunk is done by some ++ * moderately readable array casts. ++ */ ++ hcd->fiq_dmab = DWC_DMA_ALLOC((sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base); ++ DWC_WARN("FIQ DMA bounce buffers: virt = 0x%08x dma = 0x%08x len=%d", ++ (unsigned int)hcd->fiq_dmab, (unsigned int)hcd->fiq_state->dma_base, ++ sizeof(struct fiq_dma_channel) * num_channels); ++ ++ DWC_MEMSET(hcd->fiq_dmab, 0x6b, 9024); ++ ++ /* pointer for debug in fiq_print */ ++ hcd->fiq_state->fiq_dmab = hcd->fiq_dmab; ++ if (fiq_fsm_enable) { ++ int i; ++ for (i=0; i < hcd->core_if->core_params->host_channels; i++) { ++ dwc_otg_cleanup_fiq_channel(hcd, i); ++ } ++ DWC_PRINTF("FIQ FSM acceleration enabled for :\n%s%s%s", ++ (fiq_fsm_mask & 0x1) ? "Non-periodic Split Transactions\n" : "", ++ (fiq_fsm_mask & 0x2) ? "Periodic Split Transactions\n" : "", ++ (fiq_fsm_mask & 0x4) ? "High-Speed Isochronous Endpoints\n" : ""); ++ } ++ } ++ + /* Initialize the Connection timeout timer. */ + hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer", + dwc_otg_hcd_connect_timeout, 0); @@ -69703,7 +72259,8 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + hc->do_split = 1; + hc->xact_pos = qtd->isoc_split_pos; + /* We don't need to do complete splits anymore */ -+ if(fiq_split_enable) ++// if(fiq_fsm_enable) ++ if (0) + hc->complete_split = qtd->complete_split = 0; + else + hc->complete_split = qtd->complete_split; @@ -69854,62 +72411,487 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + hc->qh = qh; +} + -+/* -+** Check the transaction to see if the port / hub has already been assigned for -+** a split transaction -+** -+** Return 0 - Port is already in use -+*/ -+int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh) ++ ++/** ++ * fiq_fsm_transaction_suitable() - Test a QH for compatibility with the FIQ ++ * @qh: pointer to the endpoint's queue head ++ * ++ * Transaction start/end control flow is grafted onto the existing dwc_otg ++ * mechanisms, to avoid spaghettifying the functions more than they already are. ++ * This function's eligibility check is altered by debug parameter. ++ * ++ * Returns: 0 for unsuitable, 1 implies the FIQ can be enabled for this transaction. ++ */ ++ ++int fiq_fsm_transaction_suitable(dwc_otg_qh_t *qh) +{ -+ uint32_t hub_addr, port_addr; ++ if (qh->do_split) { ++ switch (qh->ep_type) { ++ case UE_CONTROL: ++ case UE_BULK: ++ if (fiq_fsm_mask & (1 << 0)) ++ return 1; ++ break; ++ case UE_INTERRUPT: ++ case UE_ISOCHRONOUS: ++ if (fiq_fsm_mask & (1 << 1)) ++ return 1; ++ break; ++ default: ++ break; ++ } ++ } else if (qh->ep_type == UE_ISOCHRONOUS) { ++ if (fiq_fsm_mask & (1 << 2)) { ++ /* HS ISOCH support. We test for compatibility: ++ * - DWORD aligned buffers ++ * - Must be at least 2 transfers (otherwise pointless to use the FIQ) ++ * If yes, then the fsm enqueue function will handle the state machine setup. ++ */ ++ dwc_otg_qtd_t *qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ struct dwc_otg_hcd_iso_packet_desc (*iso_descs)[0] = &urb->iso_descs; ++ int nr_iso_frames = urb->packet_count; ++ int i; ++ uint32_t ptr; + -+ if(!fiq_split_enable) -+ return 0; ++ if (nr_iso_frames < 2) ++ return 0; ++ for (i = 0; i < nr_iso_frames; i++) { ++ ptr = urb->dma + iso_descs[i]->offset; ++ if (ptr & 0x3) { ++ printk_ratelimited("%s: Non-Dword aligned isochronous frame offset." ++ " Cannot queue FIQ-accelerated transfer to device %d endpoint %d\n", ++ __FUNCTION__, qh->channel->dev_addr, qh->channel->ep_num); ++ return 0; ++ } ++ } ++ return 1; ++ } ++ } ++ return 0; ++} + -+ hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr); ++/** ++ * fiq_fsm_setup_periodic_dma() - Set up DMA bounce buffers ++ * @hcd: Pointer to the dwc_otg_hcd struct ++ * @qh: Pointer to the endpoint's queue head ++ * ++ * Periodic split transactions are transmitted modulo 188 bytes. ++ * This necessitates slicing data up into buckets for isochronous out ++ * and fixing up the DMA address for all IN transfers. ++ * ++ * Returns 1 if the DMA bounce buffers have been used, 0 if the default ++ * HC buffer has been used. ++ */ ++int fiq_fsm_setup_periodic_dma(dwc_otg_hcd_t *hcd, struct fiq_channel_state *st, dwc_otg_qh_t *qh) ++ { ++ int frame_length, i = 0; ++ uint8_t *ptr = NULL; ++ dwc_hc_t *hc = qh->channel; ++ struct fiq_dma_blob *blob; ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; + -+ if(hcd->hub_port[hub_addr] & (1 << port_addr)) -+ { -+ fiq_print(FIQDBG_PORTHUB, "H%dP%d:S%02d", hub_addr, port_addr, qh->skip_count); ++ for (i = 0; i < 6; i++) { ++ st->dma_info.slot_len[i] = 255; ++ } ++ st->dma_info.index = 0; ++ i = 0; ++ if (hc->ep_is_in) { ++ /* ++ * Set dma_regs to bounce buffer. FIQ will update the ++ * state depending on transaction progress. ++ */ ++ blob = (struct fiq_dma_blob *) hcd->fiq_state->dma_base; ++ st->hcdma_copy.d32 = (uint32_t) &blob->channel[hc->hc_num].index[0].buf[0]; ++ /* Calculate the max number of CSPLITS such that the FIQ can time out ++ * a transaction if it fails. ++ */ ++ frame_length = st->hcchar_copy.b.mps; ++ do { ++ i++; ++ frame_length -= 188; ++ } while (frame_length >= 0); ++ st->nrpackets = i; ++ return 1; ++ } else { ++ if (qh->ep_type == UE_ISOCHRONOUS) { + -+ qh->skip_count++; ++ dwc_otg_qtd_t *qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); + -+ if(qh->skip_count > 40000) -+ { -+ printk_once(KERN_ERR "Error: Having to skip port allocation"); -+ local_fiq_disable(); -+ BUG(); ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; ++ frame_length = frame_desc->length; ++ ++ /* Virtual address for bounce buffers */ ++ blob = hcd->fiq_dmab; ++ ++ ptr = qtd->urb->buf + frame_desc->offset; ++ if (frame_length == 0) { ++ /* ++ * for isochronous transactions, we must still transmit a packet ++ * even if the length is zero. ++ */ ++ st->dma_info.slot_len[0] = 0; ++ st->nrpackets = 1; ++ } else { ++ do { ++ if (frame_length <= 188) { ++ dwc_memcpy(&blob->channel[hc->hc_num].index[i].buf[0], ptr, frame_length); ++ st->dma_info.slot_len[i] = frame_length; ++ ptr += frame_length; ++ } else { ++ dwc_memcpy(&blob->channel[hc->hc_num].index[i].buf[0], ptr, 188); ++ st->dma_info.slot_len[i] = 188; ++ ptr += 188; ++ } ++ i++; ++ frame_length -= 188; ++ } while (frame_length > 0); ++ st->nrpackets = i; ++ } ++ ptr = qtd->urb->buf + frame_desc->offset; ++ /* Point the HC at the DMA address of the bounce buffers */ ++ blob = (struct fiq_dma_blob *) hcd->fiq_state->dma_base; ++ st->hcdma_copy.d32 = (uint32_t) &blob->channel[hc->hc_num].index[0].buf[0]; ++ ++ /* fixup xfersize to the actual packet size */ ++ st->hctsiz_copy.b.pid = 0; ++ st->hctsiz_copy.b.xfersize = st->dma_info.slot_len[0]; ++ return 1; ++ } else { ++ /* For interrupt, single OUT packet required, goes in the SSPLIT from hc_buff. */ + return 0; + } -+ return 1; + } -+ else -+ { -+ qh->skip_count = 0; -+ hcd->hub_port[hub_addr] |= 1 << port_addr; -+ fiq_print(FIQDBG_PORTHUB, "H%dP%d:A %d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num); -+#ifdef FIQ_DEBUG -+ hcd->hub_port_alloc[hub_addr * 16 + port_addr] = dwc_otg_hcd_get_frame_number(hcd); -+#endif ++} ++ ++/* ++ * Pushing a periodic request into the queue near the EOF1 point ++ * in a microframe causes erroneous behaviour (frmovrun) interrupt. ++ * Usually, the request goes out on the bus causing a transfer but ++ * the core does not transfer the data to memory. ++ * This guard interval (in number of 60MHz clocks) is required which ++ * must cater for CPU latency between reading the value and enabling ++ * the channel. ++ */ ++#define PERIODIC_FRREM_BACKOFF 1000 ++ ++int fiq_fsm_queue_isoc_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) ++{ ++ dwc_hc_t *hc = qh->channel; ++ dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; ++ dwc_otg_qtd_t *qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); ++ int frame; ++ struct fiq_channel_state *st = &hcd->fiq_state->channel[hc->hc_num]; ++ int xfer_len, nrpackets; ++ hcdma_data_t hcdma; ++ hfnum_data_t hfnum; ++ ++ if (st->fsm != FIQ_PASSTHROUGH) + return 0; ++ ++ st->nr_errors = 0; ++ ++ st->hcchar_copy.d32 = 0; ++ st->hcchar_copy.b.mps = hc->max_packet; ++ st->hcchar_copy.b.epdir = hc->ep_is_in; ++ st->hcchar_copy.b.devaddr = hc->dev_addr; ++ st->hcchar_copy.b.epnum = hc->ep_num; ++ st->hcchar_copy.b.eptype = hc->ep_type; ++ ++ st->hcintmsk_copy.b.chhltd = 1; ++ ++ frame = dwc_otg_hcd_get_frame_number(hcd); ++ st->hcchar_copy.b.oddfrm = (frame & 0x1) ? 0 : 1; ++ ++ st->hcchar_copy.b.lspddev = 0; ++ /* Enable the channel later as a final register write. */ ++ ++ st->hcsplt_copy.d32 = 0; ++ ++ st->hs_isoc_info.iso_desc = (struct dwc_otg_hcd_iso_packet_desc *) &qtd->urb->iso_descs; ++ st->hs_isoc_info.nrframes = qtd->urb->packet_count; ++ /* grab the next DMA address offset from the array */ ++ st->hcdma_copy.d32 = qtd->urb->dma; ++ hcdma.d32 = st->hcdma_copy.d32 + st->hs_isoc_info.iso_desc[0].offset; ++ ++ /* We need to set multi_count. This is a bit tricky - has to be set per-transaction as ++ * the core needs to be told to send the correct number. Caution: for IN transfers, ++ * this is always set to the maximum size of the endpoint. */ ++ xfer_len = st->hs_isoc_info.iso_desc[0].length; ++ nrpackets = (xfer_len + st->hcchar_copy.b.mps - 1) / st->hcchar_copy.b.mps; ++ if (nrpackets == 0) ++ nrpackets = 1; ++ st->hcchar_copy.b.multicnt = nrpackets; ++ st->hctsiz_copy.b.pktcnt = nrpackets; ++ ++ /* Initial PID also needs to be set */ ++ if (st->hcchar_copy.b.epdir == 0) { ++ st->hctsiz_copy.b.xfersize = xfer_len; ++ switch (st->hcchar_copy.b.multicnt) { ++ case 1: ++ st->hctsiz_copy.b.pid = DWC_PID_DATA0; ++ break; ++ case 2: ++ case 3: ++ st->hctsiz_copy.b.pid = DWC_PID_MDATA; ++ break; ++ } ++ ++ } else { ++ st->hctsiz_copy.b.xfersize = nrpackets * st->hcchar_copy.b.mps; ++ switch (st->hcchar_copy.b.multicnt) { ++ case 1: ++ st->hctsiz_copy.b.pid = DWC_PID_DATA0; ++ break; ++ case 2: ++ st->hctsiz_copy.b.pid = DWC_PID_DATA1; ++ break; ++ case 3: ++ st->hctsiz_copy.b.pid = DWC_PID_DATA2; ++ break; ++ } + } ++ ++ fiq_print(FIQDBG_INT, hcd->fiq_state, "FSMQ %01d ", hc->hc_num); ++ fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hcchar_copy.d32); ++ fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hctsiz_copy.d32); ++ fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hcdma_copy.d32); ++ hfnum.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum); ++ local_fiq_disable(); ++ DWC_WRITE_REG32(&hc_regs->hctsiz, st->hctsiz_copy.d32); ++ DWC_WRITE_REG32(&hc_regs->hcsplt, st->hcsplt_copy.d32); ++ DWC_WRITE_REG32(&hc_regs->hcdma, st->hcdma_copy.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32); ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, st->hcintmsk_copy.d32); ++ if (hfnum.b.frrem < PERIODIC_FRREM_BACKOFF) { ++ /* Prevent queueing near EOF1. Bad things happen if a periodic ++ * split transaction is queued very close to EOF. ++ */ ++ st->fsm = FIQ_HS_ISOC_SLEEPING; ++ } else { ++ st->fsm = FIQ_HS_ISOC_TURBO; ++ st->hcchar_copy.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32); ++ } ++ mb(); ++ st->hcchar_copy.b.chen = 0; ++ local_fiq_enable(); ++ return 0; +} -+void dwc_otg_hcd_release_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh) ++ ++ ++/** ++ * fiq_fsm_queue_split_transaction() - Set up a host channel and FIQ state ++ * @hcd: Pointer to the dwc_otg_hcd struct ++ * @qh: Pointer to the endpoint's queue head ++ * ++ * This overrides the dwc_otg driver's normal method of queueing a transaction. ++ * Called from dwc_otg_hcd_queue_transactions(), this performs specific setup ++ * for the nominated host channel. ++ * ++ * For periodic transfers, it also peeks at the FIQ state to see if an immediate ++ * start is possible. If not, then the FIQ is left to start the transfer. ++ */ ++int fiq_fsm_queue_split_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) +{ -+ uint32_t hub_addr, port_addr; ++ int start_immediate = 1, i; ++ hfnum_data_t hfnum; ++ dwc_hc_t *hc = qh->channel; ++ dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; ++ /* Program HC registers, setup FIQ_state, examine FIQ if periodic, start transfer (not if uframe 5) */ ++ int hub_addr, port_addr, frame, uframe; ++ struct fiq_channel_state *st = &hcd->fiq_state->channel[hc->hc_num]; + -+ if(!fiq_split_enable) -+ return; ++ if (st->fsm != FIQ_PASSTHROUGH) ++ return 0; ++ st->nr_errors = 0; ++ ++ st->hcchar_copy.d32 = 0; ++ st->hcchar_copy.b.mps = hc->max_packet; ++ st->hcchar_copy.b.epdir = hc->ep_is_in; ++ st->hcchar_copy.b.devaddr = hc->dev_addr; ++ st->hcchar_copy.b.epnum = hc->ep_num; ++ st->hcchar_copy.b.eptype = hc->ep_type; ++ if (hc->ep_type & 0x1) { ++ if (hc->ep_is_in) ++ st->hcchar_copy.b.multicnt = 3; ++ else ++ /* Docs say set this to 1, but driver sets to 0! */ ++ st->hcchar_copy.b.multicnt = 0; ++ } else { ++ st->hcchar_copy.b.multicnt = 1; ++ st->hcchar_copy.b.oddfrm = 0; ++ } ++ st->hcchar_copy.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW) ? 1 : 0; ++ /* Enable the channel later as a final register write. */ ++ ++ st->hcsplt_copy.d32 = 0; ++ if(qh->do_split) { ++ hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr); ++ st->hcsplt_copy.b.compsplt = 0; ++ st->hcsplt_copy.b.spltena = 1; ++ // XACTPOS is for isoc-out only but needs initialising anyway. ++ st->hcsplt_copy.b.xactpos = ISOC_XACTPOS_ALL; ++ if((qh->ep_type == DWC_OTG_EP_TYPE_ISOC) && (!qh->ep_is_in)) { ++ /* For packetsize 0 < L < 188, ISOC_XACTPOS_ALL. ++ * for longer than this, ISOC_XACTPOS_BEGIN and the FIQ ++ * will update as necessary. ++ */ ++ if (hc->xfer_len > 188) { ++ st->hcsplt_copy.b.xactpos = ISOC_XACTPOS_BEGIN; ++ } ++ } ++ st->hcsplt_copy.b.hubaddr = (uint8_t) hub_addr; ++ st->hcsplt_copy.b.prtaddr = (uint8_t) port_addr; ++ st->hub_addr = hub_addr; ++ st->port_addr = port_addr; ++ } + -+ hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr); ++ st->hctsiz_copy.d32 = 0; ++ st->hctsiz_copy.b.dopng = 0; ++ st->hctsiz_copy.b.pid = hc->data_pid_start; + -+ hcd->hub_port[hub_addr] &= ~(1 << port_addr); -+#ifdef FIQ_DEBUG -+ hcd->hub_port_alloc[hub_addr * 16 + port_addr] = -1; -+#endif -+ fiq_print(FIQDBG_PORTHUB, "H%dP%d:RO%d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num); ++ if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) { ++ hc->xfer_len = hc->max_packet; ++ } else if (!hc->ep_is_in && (hc->xfer_len > 188)) { ++ hc->xfer_len = 188; ++ } ++ st->hctsiz_copy.b.xfersize = hc->xfer_len; ++ ++ st->hctsiz_copy.b.pktcnt = 1; ++ ++ if (hc->ep_type & 0x1) { ++ /* ++ * For potentially multi-packet transfers, must use the DMA bounce buffers. For IN transfers, ++ * the DMA address is the address of the first 188byte slot buffer in the bounce buffer array. ++ * For multi-packet OUT transfers, we need to copy the data into the bounce buffer array so the FIQ can punt ++ * the right address out as necessary. hc->xfer_buff and hc->xfer_len have already been set ++ * in assign_and_init_hc(), but this is for the eventual transaction completion only. The FIQ ++ * must not touch internal driver state. ++ */ ++ if(!fiq_fsm_setup_periodic_dma(hcd, st, qh)) { ++ if (hc->align_buff) { ++ st->hcdma_copy.d32 = hc->align_buff; ++ } else { ++ st->hcdma_copy.d32 = ((unsigned long) hc->xfer_buff & 0xFFFFFFFF); ++ } ++ } ++ } else { ++ if (hc->align_buff) { ++ st->hcdma_copy.d32 = hc->align_buff; ++ } else { ++ st->hcdma_copy.d32 = ((unsigned long) hc->xfer_buff & 0xFFFFFFFF); ++ } ++ } ++ /* The FIQ depends upon no other interrupts being enabled except channel halt. ++ * Fixup channel interrupt mask. */ ++ st->hcintmsk_copy.d32 = 0; ++ st->hcintmsk_copy.b.chhltd = 1; ++ st->hcintmsk_copy.b.ahberr = 1; ++ ++ DWC_WRITE_REG32(&hc_regs->hcdma, st->hcdma_copy.d32); ++ DWC_WRITE_REG32(&hc_regs->hctsiz, st->hctsiz_copy.d32); ++ DWC_WRITE_REG32(&hc_regs->hcsplt, st->hcsplt_copy.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32); ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, st->hcintmsk_copy.d32); ++ ++ local_fiq_disable(); ++ mb(); + ++ if (hc->ep_type & 0x1) { ++ hfnum.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum); ++ frame = (hfnum.b.frnum & ~0x7) >> 3; ++ uframe = hfnum.b.frnum & 0x7; ++ if (hfnum.b.frrem < PERIODIC_FRREM_BACKOFF) { ++ /* Prevent queueing near EOF1. Bad things happen if a periodic ++ * split transaction is queued very close to EOF. ++ */ ++ start_immediate = 0; ++ } else if (uframe == 5) { ++ start_immediate = 0; ++ } else if (hc->ep_type == UE_ISOCHRONOUS && !hc->ep_is_in) { ++ start_immediate = 0; ++ } else if (hc->ep_is_in && fiq_fsm_too_late(hcd->fiq_state, hc->hc_num)) { ++ start_immediate = 0; ++ } else { ++ /* Search through all host channels to determine if a transaction ++ * is currently in progress */ ++ for (i = 0; i < hcd->core_if->core_params->host_channels; i++) { ++ if (i == hc->hc_num || hcd->fiq_state->channel[i].fsm == FIQ_PASSTHROUGH) ++ continue; ++ switch (hcd->fiq_state->channel[i].fsm) { ++ /* TT is reserved for channels that are in the middle of a periodic ++ * split transaction. ++ */ ++ case FIQ_PER_SSPLIT_STARTED: ++ case FIQ_PER_CSPLIT_WAIT: ++ case FIQ_PER_CSPLIT_NYET1: ++ case FIQ_PER_CSPLIT_POLL: ++ case FIQ_PER_ISO_OUT_ACTIVE: ++ case FIQ_PER_ISO_OUT_LAST: ++ if (hcd->fiq_state->channel[i].hub_addr == hub_addr && ++ hcd->fiq_state->channel[i].port_addr == port_addr) { ++ start_immediate = 0; ++ } ++ break; ++ default: ++ break; ++ } ++ if (!start_immediate) ++ break; ++ } ++ } ++ } ++ fiq_print(FIQDBG_INT, hcd->fiq_state, "FSMQ %01d %01d", hc->hc_num, start_immediate); ++ fiq_print(FIQDBG_INT, hcd->fiq_state, "%08d", hfnum.b.frrem); ++ //fiq_print(FIQDBG_INT, hcd->fiq_state, "H:%02dP:%02d", hub_addr, port_addr); ++ //fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hctsiz_copy.d32); ++ //fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hcdma_copy.d32); ++ switch (hc->ep_type) { ++ case UE_CONTROL: ++ case UE_BULK: ++ st->fsm = FIQ_NP_SSPLIT_STARTED; ++ break; ++ case UE_ISOCHRONOUS: ++ if (hc->ep_is_in) { ++ if (start_immediate) { ++ st->fsm = FIQ_PER_SSPLIT_STARTED; ++ } else { ++ st->fsm = FIQ_PER_SSPLIT_QUEUED; ++ } ++ } else { ++ if (start_immediate) { ++ /* Single-isoc OUT packets don't require FIQ involvement */ ++ if (st->nrpackets == 1) { ++ st->fsm = FIQ_PER_ISO_OUT_LAST; ++ } else { ++ st->fsm = FIQ_PER_ISO_OUT_ACTIVE; ++ } ++ } else { ++ st->fsm = FIQ_PER_ISO_OUT_PENDING; ++ } ++ } ++ break; ++ case UE_INTERRUPT: ++ if (start_immediate) { ++ st->fsm = FIQ_PER_SSPLIT_STARTED; ++ } else { ++ st->fsm = FIQ_PER_SSPLIT_QUEUED; ++ } ++ default: ++ break; ++ } ++ if (start_immediate) { ++ /* Set the oddfrm bit as close as possible to actual queueing */ ++ frame = dwc_otg_hcd_get_frame_number(hcd); ++ st->expected_uframe = (frame + 1) & 0x3FFF; ++ st->hcchar_copy.b.oddfrm = (frame & 0x1) ? 0 : 1; ++ st->hcchar_copy.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32); ++ } ++ mb(); ++ local_fiq_enable(); ++ return 0; +} + + @@ -69926,16 +72908,11 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p +{ + dwc_list_link_t *qh_ptr; + dwc_otg_qh_t *qh; -+ dwc_otg_qtd_t *qtd; + int num_channels; + dwc_irqflags_t flags; + dwc_spinlock_t *channel_lock = hcd->channel_lock; + dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE; + -+#ifdef DEBUG_SOF -+ DWC_DEBUGPL(DBG_HCD, " Select Transactions\n"); -+#endif -+ +#ifdef DEBUG_HOST_CHANNELS + last_sel_trans_num_per_scheduled = 0; + last_sel_trans_num_nonper_scheduled = 0; @@ -69950,26 +72927,11 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); + -+ if(qh->do_split) { -+ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); -+ if(!(qh->ep_type == UE_ISOCHRONOUS && -+ (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID || -+ qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END))) { -+ if(dwc_otg_hcd_allocate_port(hcd, qh)) -+ { -+ qh_ptr = DWC_LIST_NEXT(qh_ptr); -+ g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1); -+ continue; -+ } -+ } -+ } -+ + if (microframe_schedule) { + // Make sure we leave one channel for non periodic transactions. + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); + if (hcd->available_host_channels <= 1) { + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); -+ if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh); + break; + } + hcd->available_host_channels--; @@ -70005,27 +72967,24 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { + + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); -+ + /* + * Check to see if this is a NAK'd retransmit, in which case ignore for retransmission + * we hold off on bulk retransmissions to reduce NAK interrupt overhead for full-speed + * cheeky devices that just hold off using NAKs + */ -+ if (nak_holdoff_enable && qh->do_split) { -+ if (qh->nak_frame != 0xffff && -+ dwc_full_frame_num(qh->nak_frame) == -+ dwc_full_frame_num(dwc_otg_hcd_get_frame_number(hcd))) { -+ /* -+ * Revisit: Need to avoid trampling on periodic scheduling. -+ * Currently we are safe because g_np_count != g_np_sent whenever we hit this, -+ * but if this behaviour is changed then periodic endpoints will get a slower -+ * polling rate. -+ */ -+ g_next_sched_frame = ((qh->nak_frame + 8) & ~7) & DWC_HFNUM_MAX_FRNUM; -+ qh_ptr = DWC_LIST_NEXT(qh_ptr); -+ continue; -+ } else { -+ qh->nak_frame = 0xffff; ++ if (nak_holdoff && qh->do_split) { ++ if (qh->nak_frame != 0xffff) { ++ uint16_t next_frame = dwc_frame_num_inc(qh->nak_frame, (qh->ep_type == UE_BULK) ? nak_holdoff : 8); ++ uint16_t frame = dwc_otg_hcd_get_frame_number(hcd); ++ if (dwc_frame_num_le(frame, next_frame)) { ++ if(dwc_frame_num_le(next_frame, hcd->fiq_state->next_sched_frame)) { ++ hcd->fiq_state->next_sched_frame = next_frame; ++ } ++ qh_ptr = DWC_LIST_NEXT(qh_ptr); ++ continue; ++ } else { ++ qh->nak_frame = 0xFFFF; ++ } + } + } + @@ -70054,12 +73013,29 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + &qh->qh_list_entry); + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); + -+ g_np_sent++; + + if (!microframe_schedule) + hcd->non_periodic_channels++; + } -+ ++ /* we moved a non-periodic QH to the active schedule. If the inactive queue is empty, ++ * stop the FIQ from kicking us. We could potentially still have elements here if we ++ * ran out of host channels. ++ */ ++ if (DWC_LIST_EMPTY(&hcd->non_periodic_sched_inactive)) { ++ hcd->fiq_state->kick_np_queues = 0; ++ } else { ++ /* For each entry remaining in the NP inactive queue, ++ * if this a NAK'd retransmit then don't set the kick flag. ++ */ ++ if(nak_holdoff) { ++ DWC_LIST_FOREACH(qh_ptr, &hcd->non_periodic_sched_inactive) { ++ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); ++ if (qh->nak_frame == 0xFFFF) { ++ hcd->fiq_state->kick_np_queues = 1; ++ } ++ } ++ } ++ } + if(!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) + ret_val |= DWC_OTG_TRANSACTION_PERIODIC; + @@ -70104,6 +73080,12 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + hc->qh->ping_state = 0; + } + } else if (!hc->xfer_started) { ++ if (fiq_fsm_enable && hc->error_state) { ++ hcd->fiq_state->channel[hc->hc_num].nr_errors = ++ DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list)->error_count; ++ hcd->fiq_state->channel[hc->hc_num].fsm = ++ FIQ_PASSTHROUGH_ERRORSTATE; ++ } + dwc_otg_hc_start_transfer(hcd->core_if, hc); + hc->qh->ping_state = 0; + } @@ -70156,7 +73138,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + hptxsts_data_t tx_status; + dwc_list_link_t *qh_ptr; + dwc_otg_qh_t *qh; -+ int status; ++ int status = 0; + int no_queue_space = 0; + int no_fifo_space = 0; + @@ -70185,27 +73167,34 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + + // Do not send a split start transaction any later than frame .6 + // Note, we have to schedule a periodic in .5 to make it go in .6 -+ if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6) ++ if(fiq_fsm_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6) + { + qh_ptr = qh_ptr->next; -+ g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7; ++ hcd->fiq_state->next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7; + continue; + } + -+ /* -+ * Set a flag if we're queuing high-bandwidth in slave mode. -+ * The flag prevents any halts to get into the request queue in -+ * the middle of multiple high-bandwidth packets getting queued. -+ */ -+ if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) { -+ hcd->core_if->queuing_high_bandwidth = 1; -+ } -+ status = -+ queue_transaction(hcd, qh->channel, -+ tx_status.b.ptxfspcavail); -+ if (status < 0) { -+ no_fifo_space = 1; -+ break; ++ if (fiq_fsm_enable && fiq_fsm_transaction_suitable(qh)) { ++ if (qh->do_split) ++ fiq_fsm_queue_split_transaction(hcd, qh); ++ else ++ fiq_fsm_queue_isoc_transaction(hcd, qh); ++ } else { ++ ++ /* ++ * Set a flag if we're queueing high-bandwidth in slave mode. ++ * The flag prevents any halts to get into the request queue in ++ * the middle of multiple high-bandwidth packets getting queued. ++ */ ++ if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) { ++ hcd->core_if->queuing_high_bandwidth = 1; ++ } ++ status = queue_transaction(hcd, qh->channel, ++ tx_status.b.ptxfspcavail); ++ if (status < 0) { ++ no_fifo_space = 1; ++ break; ++ } + } + + /* @@ -70322,25 +73311,19 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p + qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t, + qh_list_entry); + -+ // Do not send a split start transaction any later than frame .5 -+ // non periodic transactions will start immediately in this uframe -+ if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6) -+ { -+ g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7; -+ break; -+ } -+ -+ status = -+ queue_transaction(hcd, qh->channel, -+ tx_status.b.nptxfspcavail); ++ if(fiq_fsm_enable && fiq_fsm_transaction_suitable(qh)) { ++ fiq_fsm_queue_split_transaction(hcd, qh); ++ } else { ++ status = queue_transaction(hcd, qh->channel, ++ tx_status.b.nptxfspcavail); + -+ if (status > 0) { -+ more_to_do = 1; -+ } else if (status < 0) { -+ no_fifo_space = 1; -+ break; ++ if (status > 0) { ++ more_to_do = 1; ++ } else if (status < 0) { ++ no_fifo_space = 1; ++ break; ++ } + } -+ + /* Advance to next QH, skipping start-of-list entry. */ + hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; + if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) { @@ -72210,9 +75193,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p +} + +#endif /* DWC_DEVICE_ONLY */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 2014-04-24 16:04:39.819124254 +0200 @@ -0,0 +1,1132 @@ +/*========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $ @@ -73346,10 +76329,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c linux-raspbe +} + +#endif /* DWC_DEVICE_ONLY */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 2014-03-11 17:51:27.000000000 +0100 -@@ -0,0 +1,851 @@ +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 2014-04-24 16:04:39.819124254 +0200 +@@ -0,0 +1,862 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $ + * $Revision: #58 $ @@ -73392,6 +76375,8 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-raspberry-p +#include "dwc_otg_core_if.h" +#include "dwc_list.h" +#include "dwc_otg_cil.h" ++#include "dwc_otg_fiq_fsm.h" ++ + +/** + * @file @@ -73937,6 +76922,12 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-raspberry-p + /** Frame List DMA address */ + dma_addr_t frame_list_dma; + ++ struct fiq_stack *fiq_stack; ++ struct fiq_state *fiq_state; ++ ++ /** Virtual address for split transaction DMA bounce buffers */ ++ struct fiq_dma_blob *fiq_dmab; ++ +#ifdef DEBUG + uint32_t frrem_samples; + uint64_t frrem_accum; @@ -73967,6 +76958,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-raspberry-p +int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh); +void dwc_otg_hcd_release_port(dwc_otg_hcd_t * dwc_otg_hcd, dwc_otg_qh_t *qh); + ++extern int fiq_fsm_queue_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh); ++extern int fiq_fsm_transaction_suitable(dwc_otg_qh_t *qh); ++extern void dwc_otg_cleanup_fiq_channel(dwc_otg_hcd_t *hcd, uint32_t num); + +/** @} */ + @@ -74201,9 +77195,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-raspberry-p +#endif +#endif +#endif /* DWC_DEVICE_ONLY */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 2014-04-24 16:04:39.819124254 +0200 @@ -0,0 +1,417 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $ @@ -74622,10 +77616,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-raspberr + +#endif /* __DWC_HCD_IF_H__ */ +#endif /* DWC_DEVICE_ONLY */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 2014-03-11 17:51:27.000000000 +0100 -@@ -0,0 +1,2741 @@ +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 2014-04-24 16:04:39.819124254 +0200 +@@ -0,0 +1,2681 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $ + * $Revision: #89 $ @@ -74662,7 +77656,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + +#include "dwc_otg_hcd.h" +#include "dwc_otg_regs.h" -+#include "dwc_otg_mphi_fix.h" + +#include <linux/jiffies.h> +#include <mach/hardware.h> @@ -74675,33 +77668,8 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + * This file contains the implementation of the HCD Interrupt handlers. + */ + -+/* -+ * Some globals to communicate between the FIQ and INTERRUPT -+ */ -+ -+void * dummy_send; -+mphi_regs_t c_mphi_regs; -+volatile void *dwc_regs_base; +int fiq_done, int_done; + -+gintsts_data_t gintsts_saved = {.d32 = 0}; -+hcint_data_t hcint_saved[MAX_EPS_CHANNELS]; -+hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS]; -+int split_out_xfersize[MAX_EPS_CHANNELS]; -+haint_data_t haint_saved; -+ -+int g_next_sched_frame, g_np_count, g_np_sent; -+static int mphi_int_count = 0 ; -+ -+hcchar_data_t nak_hcchar; -+hctsiz_data_t nak_hctsiz; -+hcsplt_data_t nak_hcsplt; -+int nak_count; -+ -+int complete_sched[MAX_EPS_CHANNELS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; -+int split_start_frame[MAX_EPS_CHANNELS]; -+int queued_port[MAX_EPS_CHANNELS]; -+ +#ifdef FIQ_DEBUG +char buffer[1000*16]; +int wptr; @@ -74711,12 +77679,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + va_list args; + char text[17]; + hfnum_data_t hfnum = { .d32 = FIQ_READ(dwc_regs_base + 0x408) }; -+ unsigned long flags; + -+ local_irq_save(flags); -+ local_fiq_disable(); + if(dbg_lvl & dbg_lvl_req || dbg_lvl == FIQDBG_ERR) + { ++ local_fiq_disable(); + snprintf(text, 9, "%4d%d:%d ", hfnum.b.frnum/8, hfnum.b.frnum%8, 8 - hfnum.b.frrem/937); + va_start(args, fmt); + vsnprintf(text+8, 9, fmt, args); @@ -74724,410 +77690,21 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + + memcpy(buffer + wptr, text, 16); + wptr = (wptr + 16) % sizeof(buffer); ++ local_fiq_enable(); + } -+ local_irq_restore(flags); +} +#endif + -+void notrace fiq_queue_request(int channel, int odd_frame) -+{ -+ hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) }; -+ hcsplt_data_t hcsplt = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) }; -+ hctsiz_data_t hctsiz = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10) }; -+ -+ if(hcsplt.b.spltena == 0) -+ { -+ fiq_print(FIQDBG_ERR, "SPLTENA "); -+ BUG(); -+ } -+ -+ if(hcchar.b.epdir == 1) -+ { -+ fiq_print(FIQDBG_SCHED, "IN Ch %d", channel); -+ } -+ else -+ { -+ hctsiz.b.xfersize = 0; -+ fiq_print(FIQDBG_SCHED, "OUT Ch %d", channel); -+ } -+ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x10), hctsiz.d32); -+ -+ hcsplt.b.compsplt = 1; -+ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x4), hcsplt.d32); -+ -+ // Send the Split complete -+ hcchar.b.chen = 1; -+ hcchar.b.oddfrm = odd_frame ? 1 : 0; -+ -+ // Post this for transmit on the next frame for periodic or this frame for non-periodic -+ fiq_print(FIQDBG_SCHED, "SND_%s", odd_frame ? "ODD " : "EVEN"); -+ -+ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x0), hcchar.d32); -+} -+ -+static int last_sof = -1; -+ -+/* -+** Function to handle the start of frame interrupt, choose whether we need to do anything and -+** therefore trigger the main interrupt -+** -+** returns int != 0 - interrupt has been handled -+*/ -+int diff; -+ -+int notrace fiq_sof_handle(hfnum_data_t hfnum) -+{ -+ int handled = 0; -+ int i; -+ -+ // Just check that once we're running we don't miss a SOF -+ /*if(last_sof != -1 && (hfnum.b.frnum != ((last_sof + 1) & 0x3fff))) -+ { -+ fiq_print(FIQDBG_ERR, "LASTSOF "); -+ fiq_print(FIQDBG_ERR, "%4d%d ", last_sof / 8, last_sof & 7); -+ fiq_print(FIQDBG_ERR, "%4d%d ", hfnum.b.frnum / 8, hfnum.b.frnum & 7); -+ BUG(); -+ }*/ -+ -+ // Only start remembering the last sof when the interrupt has been -+ // enabled (we don't check the mask to come in here...) -+ if(last_sof != -1 || FIQ_READ(dwc_regs_base + 0x18) & (1<<3)) -+ last_sof = hfnum.b.frnum; -+ -+ for(i = 0; i < MAX_EPS_CHANNELS; i++) -+ { -+ if(complete_sched[i] != -1) -+ { -+ if(complete_sched[i] <= hfnum.b.frnum || (complete_sched[i] > 0x3f00 && hfnum.b.frnum < 0xf0)) -+ { -+ fiq_queue_request(i, hfnum.b.frnum & 1); -+ complete_sched[i] = -1; -+ } -+ } -+ -+ if(complete_sched[i] != -1) -+ { -+ // This is because we've seen a split complete occur with no start... -+ // most likely because missed the complete 0x3fff frames ago! -+ -+ diff = (hfnum.b.frnum + 0x3fff - complete_sched[i]) & 0x3fff ; -+ if(diff > 32 && diff < 0x3f00) -+ { -+ fiq_print(FIQDBG_ERR, "SPLTMISS"); -+ BUG(); -+ } -+ } -+ } -+ -+ if(g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum)) -+ { -+ /* -+ * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet -+ * g_next_sched_frame is the next frame we have periodic packets for -+ * -+ * if neither of these are required for this frame then just clear the interrupt -+ */ -+ handled = 1; -+ -+ } -+ -+ return handled; -+} -+ -+int notrace port_id(hcsplt_data_t hcsplt) -+{ -+ return hcsplt.b.prtaddr + (hcsplt.b.hubaddr << 8); -+} -+ -+int notrace fiq_hcintr_handle(int channel, hfnum_data_t hfnum) -+{ -+ hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) }; -+ hcsplt_data_t hcsplt = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) }; -+ hcint_data_t hcint = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x8) }; -+ hcintmsk_data_t hcintmsk = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0xc) }; -+ hctsiz_data_t hctsiz = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10)}; -+ -+ hcint_saved[channel].d32 |= hcint.d32; -+ hcintmsk_saved[channel].d32 = hcintmsk.d32; -+ -+ if(hcsplt.b.spltena) -+ { -+ fiq_print(FIQDBG_PORTHUB, "ph: %4x", port_id(hcsplt)); -+ if(hcint.b.chhltd) -+ { -+ fiq_print(FIQDBG_SCHED, "CH HLT %d", channel); -+ fiq_print(FIQDBG_SCHED, "%08x", hcint_saved[channel]); -+ } -+ if(hcint.b.stall || hcint.b.xacterr || hcint.b.bblerr || hcint.b.frmovrun || hcint.b.datatglerr) -+ { -+ queued_port[channel] = 0; -+ fiq_print(FIQDBG_ERR, "CHAN ERR"); -+ } -+ if(hcint.b.xfercomp) -+ { -+ // Clear the port allocation and transmit anything also on this port -+ queued_port[channel] = 0; -+ fiq_print(FIQDBG_SCHED, "XFERCOMP"); -+ } -+ if(hcint.b.nak) -+ { -+ queued_port[channel] = 0; -+ fiq_print(FIQDBG_SCHED, "NAK"); -+ } -+ if(hcint.b.ack && !hcsplt.b.compsplt) -+ { -+ int i; -+ -+ // Do not complete isochronous out transactions -+ if(hcchar.b.eptype == 1 && hcchar.b.epdir == 0) -+ { -+ queued_port[channel] = 0; -+ fiq_print(FIQDBG_SCHED, "ISOC_OUT"); -+ } -+ else -+ { -+ // Make sure we check the port / hub combination that we sent this split on. -+ // Do not queue a second request to the same port -+ for(i = 0; i < MAX_EPS_CHANNELS; i++) -+ { -+ if(port_id(hcsplt) == queued_port[i]) -+ { -+ fiq_print(FIQDBG_ERR, "PORTERR "); -+ //BUG(); -+ } -+ } -+ -+ split_start_frame[channel] = (hfnum.b.frnum + 1) & ~7; -+ -+ // Note, the size of an OUT is in the start split phase, not -+ // the complete split -+ split_out_xfersize[channel] = hctsiz.b.xfersize; -+ -+ hcint_saved[channel].b.chhltd = 0; -+ hcint_saved[channel].b.ack = 0; -+ -+ queued_port[channel] = port_id(hcsplt); -+ -+ if(hcchar.b.eptype & 1) -+ { -+ // Send the periodic complete in the same oddness frame as the ACK went... -+ fiq_queue_request(channel, !(hfnum.b.frnum & 1)); -+ // complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1); -+ } -+ else -+ { -+ // Schedule the split complete to occur later -+ complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 2); -+ fiq_print(FIQDBG_SCHED, "ACK%04d%d", complete_sched[channel]/8, complete_sched[channel]%8); -+ } -+ } -+ } -+ if(hcint.b.nyet) -+ { -+ fiq_print(FIQDBG_ERR, "NYETERR1"); -+ //BUG(); -+ // Can transmit a split complete up to uframe .0 of the next frame -+ if(hfnum.b.frnum <= dwc_frame_num_inc(split_start_frame[channel], 8)) -+ { -+ // Send it next frame -+ if(hcchar.b.eptype & 1) // type 1 & 3 are interrupt & isoc -+ { -+ fiq_print(FIQDBG_SCHED, "NYT:SEND"); -+ fiq_queue_request(channel, !(hfnum.b.frnum & 1)); -+ } -+ else -+ { -+ // Schedule non-periodic access for next frame (the odd-even bit doesn't effect NP) -+ complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1); -+ fiq_print(FIQDBG_SCHED, "NYT%04d%d", complete_sched[channel]/8, complete_sched[channel]%8); -+ } -+ hcint_saved[channel].b.chhltd = 0; -+ hcint_saved[channel].b.nyet = 0; -+ } -+ else -+ { -+ queued_port[channel] = 0; -+ fiq_print(FIQDBG_ERR, "NYETERR2"); -+ //BUG(); -+ } -+ } -+ } -+ else -+ { -+ /* -+ * If we have any of NAK, ACK, Datatlgerr active on a -+ * non-split channel, the sole reason is to reset error -+ * counts for a previously broken transaction. The FIQ -+ * will thrash on NAK IN and ACK OUT in particular so -+ * handle it "once" and allow the IRQ to do the rest. -+ */ -+ hcint.d32 &= hcintmsk.d32; -+ if(hcint.b.nak) -+ { -+ hcintmsk.b.nak = 0; -+ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0xc), hcintmsk.d32); -+ } -+ if (hcint.b.ack) -+ { -+ hcintmsk.b.ack = 0; -+ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0xc), hcintmsk.d32); -+ } -+ } -+ -+ // Clear the interrupt, this will also clear the HAINT bit -+ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x8), hcint.d32); -+ return hcint_saved[channel].d32 == 0; -+} -+ -+gintsts_data_t gintsts; -+gintmsk_data_t gintmsk; -+// triggered: The set of interrupts that were triggered -+// handled: The set of interrupts that have been handled (no IRQ is -+// required) -+// keep: The set of interrupts we want to keep unmasked even though we -+// want to trigger an IRQ to handle it (SOF and HCINTR) -+gintsts_data_t triggered, handled, keep; -+hfnum_data_t hfnum; -+ -+void __attribute__ ((naked)) notrace dwc_otg_hcd_handle_fiq(void) -+{ -+ -+ /* entry takes care to store registers we will be treading on here */ -+ asm __volatile__ ( -+ "mov ip, sp ;" -+ /* stash FIQ and normal regs */ -+ "stmdb sp!, {r0-r12, lr};" -+ /* !! THIS SETS THE FRAME, adjust to > sizeof locals */ -+ "sub fp, ip, #512 ;" -+ ); -+ -+ // Cannot put local variables at the beginning of the function -+ // because otherwise 'C' will play with the stack pointer. any locals -+ // need to be inside the following block -+ do -+ { -+ fiq_done++; -+ gintsts.d32 = FIQ_READ(dwc_regs_base + 0x14); -+ gintmsk.d32 = FIQ_READ(dwc_regs_base + 0x18); -+ hfnum.d32 = FIQ_READ(dwc_regs_base + 0x408); -+ triggered.d32 = gintsts.d32 & gintmsk.d32; -+ handled.d32 = 0; -+ keep.d32 = 0; -+ fiq_print(FIQDBG_INT, "FIQ "); -+ fiq_print(FIQDBG_INT, "%08x", gintsts.d32); -+ fiq_print(FIQDBG_INT, "%08x", gintmsk.d32); -+ if(gintsts.d32) -+ { -+ // If port enabled -+ if((FIQ_READ(dwc_regs_base + 0x440) & 0xf) == 0x5) -+ { -+ if(gintsts.b.sofintr) -+ { -+ if(fiq_sof_handle(hfnum)) -+ { -+ handled.b.sofintr = 1; /* Handled in FIQ */ -+ } -+ else -+ { -+ /* Keer interrupt unmasked */ -+ keep.b.sofintr = 1; -+ } -+ { -+ // Need to make sure the read and clearing of the SOF interrupt is as close as possible to avoid the possibility of missing -+ // a start of frame interrupt -+ gintsts_data_t gintsts = { .b.sofintr = 1 }; -+ FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32); -+ } -+ } -+ -+ if(fiq_split_enable && gintsts.b.hcintr) -+ { -+ int i; -+ haint_data_t haint; -+ haintmsk_data_t haintmsk; -+ -+ haint.d32 = FIQ_READ(dwc_regs_base + 0x414); -+ haintmsk.d32 = FIQ_READ(dwc_regs_base + 0x418); -+ haint.d32 &= haintmsk.d32; -+ haint_saved.d32 |= haint.d32; -+ -+ fiq_print(FIQDBG_INT, "hcintr"); -+ fiq_print(FIQDBG_INT, "%08x", FIQ_READ(dwc_regs_base + 0x414)); -+ -+ // Go through each channel that has an enabled interrupt -+ for(i = 0; i < 16; i++) -+ if((haint.d32 >> i) & 1) -+ if(fiq_hcintr_handle(i, hfnum)) -+ haint_saved.d32 &= ~(1 << i); /* this was handled */ -+ -+ /* If we've handled all host channel interrupts then don't trigger the interrupt */ -+ if(haint_saved.d32 == 0) -+ { -+ handled.b.hcintr = 1; -+ } -+ else -+ { -+ /* Make sure we keep the channel interrupt unmasked when triggering the IRQ */ -+ keep.b.hcintr = 1; -+ } -+ -+ { -+ gintsts_data_t gintsts = { .b.hcintr = 1 }; -+ -+ // Always clear the channel interrupt -+ FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32); -+ } -+ } -+ } -+ else -+ { -+ last_sof = -1; -+ } -+ } -+ -+ // Mask out the interrupts triggered - those handled - don't mask out the ones we want to keep -+ gintmsk.d32 = keep.d32 | (gintmsk.d32 & ~(triggered.d32 & ~handled.d32)); -+ // Save those that were triggered but not handled -+ gintsts_saved.d32 |= triggered.d32 & ~handled.d32; -+ FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32); -+ -+ // Clear and save any unhandled interrupts and trigger the interrupt -+ if(gintsts_saved.d32) -+ { -+ /* To enable the MPHI interrupt (INT 32) -+ */ -+ FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send); -+ FIQ_WRITE( c_mphi_regs.outddb, (1 << 29)); -+ -+ mphi_int_count++; -+ } -+ } -+ while(0); -+ -+ mb(); -+ -+ /* exit back to normal mode restoring everything */ -+ asm __volatile__ ( -+ /* return FIQ regs back to pristine state -+ * and get normal regs back -+ */ -+ "ldmia sp!, {r0-r12, lr};" -+ -+ /* return */ -+ "subs pc, lr, #4;" -+ ); -+} -+ +/** This function handles interrupts for the HCD. */ +int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) +{ + int retval = 0; + static int last_time; -+ + dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; + gintsts_data_t gintsts; + gintmsk_data_t gintmsk; + hfnum_data_t hfnum; ++ haintmsk_data_t haintmsk; + +#ifdef DEBUG + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; @@ -75145,14 +77722,25 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + /* Check if HOST Mode */ + if (dwc_otg_is_host_mode(core_if)) { + local_fiq_disable(); -+ gintmsk.d32 |= gintsts_saved.d32; -+ gintsts.d32 |= gintsts_saved.d32; -+ gintsts_saved.d32 = 0; ++ /* Pull in from the FIQ's disabled mask */ ++ gintmsk.d32 = gintmsk.d32 | ~(dwc_otg_hcd->fiq_state->gintmsk_saved.d32); ++ dwc_otg_hcd->fiq_state->gintmsk_saved.d32 = ~0; ++ ++ ++ if (fiq_fsm_enable && ( 0x0000FFFF & ~(dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint))) { ++ gintsts.b.hcintr = 1; ++ } ++ ++ /* Danger will robinson: fake a SOF if necessary */ ++ if (fiq_fsm_enable && (dwc_otg_hcd->fiq_state->gintmsk_saved.b.sofintr == 1)) { ++ gintsts.b.sofintr = 1; ++ } ++ gintsts.d32 &= gintmsk.d32; ++ + local_fiq_enable(); + if (!gintsts.d32) { + goto exit_handler_routine; + } -+ gintsts.d32 &= gintmsk.d32; + +#ifdef DEBUG + // We should be OK doing this because the common interrupts should already have been serviced @@ -75172,12 +77760,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + gintsts.d32, core_if); +#endif + hfnum.d32 = DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->hfnum); -+ if (gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum)) -+ { -+ /* Note, we should never get here if the FIQ is doing it's job properly*/ -+ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd); -+ } -+ else if (gintsts.b.sofintr) { ++ if (gintsts.b.sofintr) { + retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd); + } + @@ -75232,37 +77815,43 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + } + +exit_handler_routine: -+ -+ if (fiq_fix_enable) -+ { ++ if (fiq_enable) { ++ gintmsk_data_t gintmsk_new; ++ haintmsk_data_t haintmsk_new; + local_fiq_disable(); -+ // Make sure that we don't clear the interrupt if we've still got pending work to do -+ if(gintsts_saved.d32 == 0) -+ { -+ /* Clear the MPHI interrupt */ -+ DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16)); -+ if (mphi_int_count >= 60) -+ { -+ DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16))); -+ while(!(DWC_READ_REG32(c_mphi_regs.ctrl) & (1 << 17))) -+ ; -+ DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31)); -+ mphi_int_count = 0; -+ } -+ int_done++; ++ gintmsk_new.d32 = *(volatile uint32_t *)&dwc_otg_hcd->fiq_state->gintmsk_saved.d32; ++ if(fiq_fsm_enable) ++ haintmsk_new.d32 = *(volatile uint32_t *)&dwc_otg_hcd->fiq_state->haintmsk_saved.d32; ++ else ++ haintmsk_new.d32 = 0x0000FFFF; ++ ++ /* The FIQ could have sneaked another interrupt in. If so, don't clear MPHI */ ++ if ((gintmsk_new.d32 == ~0) && (haintmsk_new.d32 == 0x0000FFFF)) { ++ DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.intstat, (1<<16)); ++ if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) { ++ fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR"); ++ DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, ((1<<31) + (1<<16))); ++ while (!(DWC_READ_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & (1 << 17))) ++ ; ++ DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, (1<<31)); ++ dwc_otg_hcd->fiq_state->mphi_int_count = 0; ++ } ++ int_done++; + } -+ -+ // Unmask handled interrupts -+ FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32); -+ //DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1); -+ ++ haintmsk.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk); ++ /* Re-enable interrupts that the FIQ masked (first time round) */ ++ FIQ_WRITE(dwc_otg_hcd->fiq_state->dwc_regs_base + GINTMSK, gintmsk.d32); + local_fiq_enable(); + -+ if((jiffies / HZ) > last_time) -+ { ++ if ((jiffies / HZ) > last_time) { ++ //dwc_otg_qh_t *qh; ++ //dwc_list_link_t *cur; + /* Once a second output the fiq and irq numbers, useful for debug */ + last_time = jiffies / HZ; -+ DWC_DEBUGPL(DBG_USER, "int_done = %d fiq_done = %d\n", int_done, fiq_done); ++ // DWC_WARN("np_kick=%d AHC=%d sched_frame=%d cur_frame=%d int_done=%d fiq_done=%d", ++ // dwc_otg_hcd->fiq_state->kick_np_queues, dwc_otg_hcd->available_host_channels, ++ // dwc_otg_hcd->fiq_state->next_sched_frame, hfnum.b.frnum, int_done, dwc_otg_hcd->fiq_state->fiq_done); ++ //printk(KERN_WARNING "Periodic queues:\n"); + } + } + @@ -75314,6 +77903,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe +int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd) +{ + hfnum_data_t hfnum; ++ gintsts_data_t gintsts = { .d32 = 0 }; + dwc_list_link_t *qh_entry; + dwc_otg_qh_t *qh; + dwc_otg_transaction_type_e tr_type; @@ -75361,7 +77951,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + } + } + -+ g_next_sched_frame = next_sched_frame; ++ hcd->fiq_state->next_sched_frame = next_sched_frame; + + tr_type = dwc_otg_hcd_select_transactions(hcd); + if (tr_type != DWC_OTG_TRANSACTION_NONE) { @@ -75369,10 +77959,11 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + did_something = 1; + } + -+ /* Clear interrupt */ -+ gintsts.b.sofintr = 1; -+ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); -+ ++ /* Clear interrupt - but do not trample on the FIQ sof */ ++ if (!fiq_fsm_enable) { ++ gintsts.b.sofintr = 1; ++ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); ++ } + return 1; +} + @@ -75648,19 +78239,21 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe +{ + int i; + int retval = 0; -+ haint_data_t haint; ++ haint_data_t haint = { .d32 = 0 } ; + + /* Clear appropriate bits in HCINTn to clear the interrupt bit in + * GINTSTS */ + -+ haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if); ++ if (!fiq_fsm_enable) ++ haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if); + + // Overwrite with saved interrupts from fiq handler -+ if(fiq_split_enable) ++ if(fiq_fsm_enable) + { ++ /* check the mask? */ + local_fiq_disable(); -+ haint.d32 = haint_saved.d32; -+ haint_saved.d32 = 0; ++ haint.b2.chint |= ~(dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint); ++ dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint = ~0; + local_fiq_enable(); + } + @@ -75704,9 +78297,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + *short_read = (hctsiz.b.xfersize != 0); + } + } else if (hc->qh->do_split) { -+ if(fiq_split_enable) -+ length = split_out_xfersize[hc->hc_num]; -+ else ++ //length = split_out_xfersize[hc->hc_num]; + length = qtd->ssplit_out_xfer_count; + } else { + length = hc->xfer_len; @@ -75953,19 +78544,17 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + int free_qtd; + dwc_irqflags_t flags; + dwc_spinlock_t *channel_lock = hcd->channel_lock; -+#ifdef FIQ_DEBUG -+ int endp = qtd->urb ? qtd->urb->pipe_info.ep_num : 0; -+#endif ++ + int hog_port = 0; + + DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n", + __func__, hc->hc_num, halt_status, hc->xfer_len); + -+ if(fiq_split_enable && hc->do_split) { ++ if(fiq_fsm_enable && hc->do_split) { + if(!hc->ep_is_in && hc->ep_type == UE_ISOCHRONOUS) { + if(hc->xact_pos == DWC_HCSPLIT_XACTPOS_MID || + hc->xact_pos == DWC_HCSPLIT_XACTPOS_BEGIN) { -+ hog_port = 1; ++ hog_port = 0; + } + } + } @@ -76022,6 +78611,8 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + * function clears the channel interrupt enables and conditions, so + * there's no need to clear the Channel Halted interrupt separately. + */ ++ if (fiq_fsm_enable && hcd->fiq_state->channel[hc->hc_num].fsm != FIQ_PASSTHROUGH) ++ dwc_otg_cleanup_fiq_channel(hcd, hc->hc_num); + dwc_otg_hc_cleanup(hcd->core_if, hc); + DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); + @@ -76044,27 +78635,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); + hcd->available_host_channels++; -+ fiq_print(FIQDBG_PORTHUB, "AHC = %d ", hcd->available_host_channels); ++ fiq_print(FIQDBG_INT, hcd->fiq_state, "AHC = %d ", hcd->available_host_channels); + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); + } + -+ if(fiq_split_enable && hc->do_split) -+ { -+ if(!(hcd->hub_port[hc->hub_addr] & (1 << hc->port_addr))) -+ { -+ fiq_print(FIQDBG_ERR, "PRTNOTAL"); -+ //BUG(); -+ } -+ if(!hog_port && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC || -+ hc->ep_type == DWC_OTG_EP_TYPE_INTR)) { -+ hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr); -+#ifdef FIQ_DEBUG -+ hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1; -+#endif -+ fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp); -+ } -+ } -+ + /* Try to queue more transfers now that there's a free channel. */ + tr_type = dwc_otg_hcd_select_transactions(hcd); + if (tr_type != DWC_OTG_TRANSACTION_NONE) { @@ -76486,7 +79060,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + switch(dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { + case UE_BULK: + case UE_CONTROL: -+ if (nak_holdoff_enable) ++ if (nak_holdoff && qtd->qh->do_split) + hc->qh->nak_frame = dwc_otg_hcd_get_frame_number(hcd); + } + @@ -76702,7 +79276,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + // With the FIQ running we only ever see the failed NYET + if (dwc_full_frame_num(frnum) != + dwc_full_frame_num(hc->qh->sched_frame) || -+ fiq_split_enable) { ++ fiq_fsm_enable) { + /* + * No longer in the same full speed frame. + * Treat this as a transaction error. @@ -77088,12 +79662,11 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe +static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, + dwc_hc_t * hc, + dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd, -+ hcint_data_t hcint, -+ hcintmsk_data_t hcintmsk) ++ dwc_otg_qtd_t * qtd) +{ + int out_nak_enh = 0; -+ ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; + /* For core with OUT NAK enhancement, the flow for high- + * speed CONTROL/BULK OUT is handled a little differently. + */ @@ -77123,11 +79696,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + } + + /* Read the HCINTn register to determine the cause for the halt. */ -+ if(!fiq_split_enable) -+ { -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); -+ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); -+ } ++ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); + + if (hcint.b.xfercomp) { + /** @todo This is here because of a possible hardware bug. Spec @@ -77252,15 +79823,13 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe +static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd, + dwc_hc_t * hc, + dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd, -+ hcint_data_t hcint, -+ hcintmsk_data_t hcintmsk) ++ dwc_otg_qtd_t * qtd) +{ + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " + "Channel Halted--\n", hc->hc_num); + + if (hcd->core_if->dma_enable) { -+ handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd, hcint, hcintmsk); ++ handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd); + } else { +#ifdef DEBUG + if (!halt_status_ok(hcd, hc, hc_regs, qtd)) { @@ -77273,11 +79842,368 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + return 1; +} + ++ ++/** ++ * dwc_otg_fiq_unmangle_isoc() - Update the iso_frame_desc structure on ++ * FIQ transfer completion ++ * @hcd: Pointer to dwc_otg_hcd struct ++ * @num: Host channel number ++ * ++ * 1. Un-mangle the status as recorded in each iso_frame_desc status ++ * 2. Copy it from the dwc_otg_urb into the real URB ++ */ ++void dwc_otg_fiq_unmangle_isoc(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, dwc_otg_qtd_t *qtd, uint32_t num) ++{ ++ struct dwc_otg_hcd_urb *dwc_urb = qtd->urb; ++ int nr_frames = dwc_urb->packet_count; ++ int i; ++ hcint_data_t frame_hcint; ++ ++ for (i = 0; i < nr_frames; i++) { ++ frame_hcint.d32 = dwc_urb->iso_descs[i].status; ++ if (frame_hcint.b.xfercomp) { ++ dwc_urb->iso_descs[i].status = 0; ++ dwc_urb->actual_length += dwc_urb->iso_descs[i].actual_length; ++ } else if (frame_hcint.b.frmovrun) { ++ if (qh->ep_is_in) ++ dwc_urb->iso_descs[i].status = -DWC_E_NO_STREAM_RES; ++ else ++ dwc_urb->iso_descs[i].status = -DWC_E_COMMUNICATION; ++ dwc_urb->error_count++; ++ dwc_urb->iso_descs[i].actual_length = 0; ++ } else if (frame_hcint.b.xacterr) { ++ dwc_urb->iso_descs[i].status = -DWC_E_PROTOCOL; ++ dwc_urb->error_count++; ++ dwc_urb->iso_descs[i].actual_length = 0; ++ } else if (frame_hcint.b.bblerr) { ++ dwc_urb->iso_descs[i].status = -DWC_E_OVERFLOW; ++ dwc_urb->error_count++; ++ dwc_urb->iso_descs[i].actual_length = 0; ++ } else { ++ /* Something went wrong */ ++ dwc_urb->iso_descs[i].status = -1; ++ dwc_urb->iso_descs[i].actual_length = 0; ++ dwc_urb->error_count++; ++ } ++ } ++ //printk_ratelimited(KERN_INFO "%s: HS isochronous of %d/%d frames with %d errors complete\n", ++ // __FUNCTION__, i, dwc_urb->packet_count, dwc_urb->error_count); ++ hcd->fops->complete(hcd, dwc_urb->priv, dwc_urb, 0); ++ release_channel(hcd, qh->channel, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); ++} ++ ++/** ++ * dwc_otg_fiq_unsetup_per_dma() - Remove data from bounce buffers for split transactions ++ * @hcd: Pointer to dwc_otg_hcd struct ++ * @num: Host channel number ++ * ++ * Copies data from the FIQ bounce buffers into the URB's transfer buffer. Does not modify URB state. ++ * Returns total length of data or -1 if the buffers were not used. ++ * ++ */ ++int dwc_otg_fiq_unsetup_per_dma(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, dwc_otg_qtd_t *qtd, uint32_t num) ++{ ++ dwc_hc_t *hc = qh->channel; ++ struct fiq_dma_blob *blob = hcd->fiq_dmab; ++ struct fiq_channel_state *st = &hcd->fiq_state->channel[num]; ++ uint8_t *ptr = NULL; ++ int index = 0, len = 0; ++ int i = 0; ++ if (hc->ep_is_in) { ++ /* Copy data out of the DMA bounce buffers to the URB's buffer. ++ * The align_buf is ignored as this is ignored on FSM enqueue. */ ++ ptr = qtd->urb->buf; ++ if (qh->ep_type == UE_ISOCHRONOUS) { ++ /* Isoc IN transactions - grab the offset of the iso_frame_desc into the URB transfer buffer */ ++ index = qtd->isoc_frame_index; ++ ptr += qtd->urb->iso_descs[index].offset; ++ } else { ++ /* Need to increment by actual_length for interrupt IN */ ++ ptr += qtd->urb->actual_length; ++ } ++ ++ for (i = 0; i < st->dma_info.index; i++) { ++ len += st->dma_info.slot_len[i]; ++ dwc_memcpy(ptr, &blob->channel[num].index[i].buf[0], st->dma_info.slot_len[i]); ++ ptr += st->dma_info.slot_len[i]; ++ } ++ return len; ++ } else { ++ /* OUT endpoints - nothing to do. */ ++ return -1; ++ } ++ ++} ++/** ++ * dwc_otg_hcd_handle_hc_fsm() - handle an unmasked channel interrupt ++ * from a channel handled in the FIQ ++ * @hcd: Pointer to dwc_otg_hcd struct ++ * @num: Host channel number ++ * ++ * If a host channel interrupt was received by the IRQ and this was a channel ++ * used by the FIQ, the execution flow for transfer completion is substantially ++ * different from the normal (messy) path. This function and its friends handles ++ * channel cleanup and transaction completion from a FIQ transaction. ++ */ ++int32_t dwc_otg_hcd_handle_hc_fsm(dwc_otg_hcd_t *hcd, uint32_t num) ++{ ++ struct fiq_channel_state *st = &hcd->fiq_state->channel[num]; ++ dwc_hc_t *hc = hcd->hc_ptr_array[num]; ++ dwc_otg_qtd_t *qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list); ++ dwc_otg_qh_t *qh = hc->qh; ++ dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[num]; ++ hcint_data_t hcint = hcd->fiq_state->channel[num].hcint_copy; ++ int hostchannels = 0; ++ int ret = 0; ++ fiq_print(FIQDBG_INT, hcd->fiq_state, "OUT %01d %01d ", num , st->fsm); ++ ++ hostchannels = hcd->available_host_channels; ++ switch (st->fsm) { ++ case FIQ_TEST: ++ break; ++ ++ case FIQ_DEQUEUE_ISSUED: ++ /* hc_halt was called. QTD no longer exists. */ ++ /* TODO: for a nonperiodic split transaction, need to issue a ++ * CLEAR_TT_BUFFER hub command if we were in the start-split phase. ++ */ ++ release_channel(hcd, hc, NULL, hc->halt_status); ++ ret = 1; ++ break; ++ ++ case FIQ_NP_SPLIT_DONE: ++ /* Nonperiodic transaction complete. */ ++ if (!hc->ep_is_in) { ++ qtd->ssplit_out_xfer_count = hc->xfer_len; ++ } ++ if (hcint.b.xfercomp) { ++ handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.nak) { ++ handle_hc_nak_intr(hcd, hc, hc_regs, qtd); ++ } ++ ret = 1; ++ break; ++ ++ case FIQ_NP_SPLIT_HS_ABORTED: ++ /* A HS abort is a 3-strikes on the HS bus at any point in the transaction. ++ * Normally a CLEAR_TT_BUFFER hub command would be required: we can't do that ++ * because there's no guarantee which order a non-periodic split happened in. ++ * We could end up clearing a perfectly good transaction out of the buffer. ++ */ ++ if (hcint.b.xacterr) { ++ qtd->error_count += st->nr_errors; ++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.ahberr) { ++ handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd); ++ } else { ++ local_fiq_disable(); ++ BUG(); ++ } ++ break; ++ ++ case FIQ_NP_SPLIT_LS_ABORTED: ++ /* A few cases can cause this - either an unknown state on a SSPLIT or ++ * STALL/data toggle error response on a CSPLIT */ ++ if (hcint.b.stall) { ++ handle_hc_stall_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.datatglerr) { ++ handle_hc_datatglerr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.ahberr) { ++ handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd); ++ } else { ++ local_fiq_disable(); ++ BUG(); ++ } ++ break; ++ ++ case FIQ_PER_SPLIT_DONE: ++ /* Isoc IN or Interrupt IN/OUT */ ++ ++ /* Flow control here is different from the normal execution by the driver. ++ * We need to completely ignore most of the driver's method of handling ++ * split transactions and do it ourselves. ++ */ ++ if (hc->ep_type == UE_INTERRUPT) { ++ if (hcint.b.nak) { ++ handle_hc_nak_intr(hcd, hc, hc_regs, qtd); ++ } else if (hc->ep_is_in) { ++ int len; ++ len = dwc_otg_fiq_unsetup_per_dma(hcd, hc->qh, qtd, num); ++ //printk(KERN_NOTICE "FIQ Transaction: hc=%d len=%d urb_len = %d\n", num, len, qtd->urb->length); ++ qtd->urb->actual_length += len; ++ if (qtd->urb->actual_length >= qtd->urb->length) { ++ qtd->urb->status = 0; ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, qtd->urb->status); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); ++ } else { ++ /* Interrupt transfer not complete yet - is it a short read? */ ++ if (len < hc->max_packet) { ++ /* Interrupt transaction complete */ ++ qtd->urb->status = 0; ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, qtd->urb->status); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); ++ } else { ++ /* Further transactions required */ ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE); ++ } ++ } ++ } else { ++ /* Interrupt OUT complete. */ ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ qtd->urb->actual_length += hc->xfer_len; ++ if (qtd->urb->actual_length >= qtd->urb->length) { ++ qtd->urb->status = 0; ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, qtd->urb->status); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); ++ } else { ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE); ++ } ++ } ++ } else { ++ /* ISOC IN complete. */ ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; ++ int len = 0; ++ /* Record errors, update qtd. */ ++ if (st->nr_errors) { ++ frame_desc->actual_length = 0; ++ frame_desc->status = -DWC_E_PROTOCOL; ++ } else { ++ frame_desc->status = 0; ++ /* Unswizzle dma */ ++ len = dwc_otg_fiq_unsetup_per_dma(hcd, qh, qtd, num); ++ frame_desc->actual_length = len; ++ } ++ qtd->isoc_frame_index++; ++ if (qtd->isoc_frame_index == qtd->urb->packet_count) { ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); ++ } else { ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE); ++ } ++ } ++ break; ++ ++ case FIQ_PER_ISO_OUT_DONE: { ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; ++ /* Record errors, update qtd. */ ++ if (st->nr_errors) { ++ frame_desc->actual_length = 0; ++ frame_desc->status = -DWC_E_PROTOCOL; ++ } else { ++ frame_desc->status = 0; ++ frame_desc->actual_length = frame_desc->length; ++ } ++ qtd->isoc_frame_index++; ++ qtd->isoc_split_offset = 0; ++ if (qtd->isoc_frame_index == qtd->urb->packet_count) { ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); ++ } else { ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE); ++ } ++ } ++ break; ++ ++ case FIQ_PER_SPLIT_NYET_ABORTED: ++ /* Doh. lost the data. */ ++ printk_ratelimited(KERN_INFO "Transfer to device %d endpoint 0x%x frame %d failed " ++ "- FIQ reported NYET. Data may have been lost.\n", ++ hc->dev_addr, hc->ep_num, dwc_otg_hcd_get_frame_number(hcd) >> 3); ++ if (hc->ep_type == UE_ISOCHRONOUS) { ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; ++ /* Record errors, update qtd. */ ++ frame_desc->actual_length = 0; ++ frame_desc->status = -DWC_E_PROTOCOL; ++ qtd->isoc_frame_index++; ++ qtd->isoc_split_offset = 0; ++ if (qtd->isoc_frame_index == qtd->urb->packet_count) { ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); ++ } else { ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE); ++ } ++ } else { ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS); ++ } ++ break; ++ ++ case FIQ_HS_ISOC_DONE: ++ /* The FIQ has performed a whole pile of isochronous transactions. ++ * The status is recorded as the interrupt state should the transaction ++ * fail. ++ */ ++ dwc_otg_fiq_unmangle_isoc(hcd, qh, qtd, num); ++ break; ++ ++ case FIQ_PER_SPLIT_LS_ABORTED: ++ if (hcint.b.xacterr) { ++ /* Hub has responded with an ERR packet. Device ++ * has been unplugged or the port has been disabled. ++ * TODO: need to issue a reset to the hub port. */ ++ qtd->error_count += 3; ++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.stall) { ++ handle_hc_stall_intr(hcd, hc, hc_regs, qtd); ++ } else { ++ printk_ratelimited(KERN_INFO "Transfer to device %d endpoint 0x%x failed " ++ "- FIQ reported FSM=%d. Data may have been lost.\n", ++ st->fsm, hc->dev_addr, hc->ep_num); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS); ++ } ++ break; ++ ++ case FIQ_PER_SPLIT_HS_ABORTED: ++ /* Either the SSPLIT phase suffered transaction errors or something ++ * unexpected happened. ++ */ ++ qtd->error_count += 3; ++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS); ++ break; ++ ++ case FIQ_PER_SPLIT_TIMEOUT: ++ /* Couldn't complete in the nominated frame */ ++ printk(KERN_INFO "Transfer to device %d endpoint 0x%x frame %d failed " ++ "- FIQ timed out. Data may have been lost.\n", ++ hc->dev_addr, hc->ep_num, dwc_otg_hcd_get_frame_number(hcd) >> 3); ++ if (hc->ep_type == UE_ISOCHRONOUS) { ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; ++ /* Record errors, update qtd. */ ++ frame_desc->actual_length = 0; ++ if (hc->ep_is_in) { ++ frame_desc->status = -DWC_E_NO_STREAM_RES; ++ } else { ++ frame_desc->status = -DWC_E_COMMUNICATION; ++ } ++ qtd->isoc_frame_index++; ++ if (qtd->isoc_frame_index == qtd->urb->packet_count) { ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); ++ } else { ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE); ++ } ++ } else { ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS); ++ } ++ break; ++ ++ default: ++ local_fiq_disable(); ++ DWC_WARN("unexpected state received on hc=%d fsm=%d", hc->hc_num, st->fsm); ++ BUG(); ++ } ++ //if (hostchannels != hcd->available_host_channels) { ++ /* should have incremented by now! */ ++ // BUG(); ++// } ++ return ret; ++} ++ +/** Handles interrupt for a specific Host Channel */ +int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num) +{ + int retval = 0; -+ hcint_data_t hcint, hcint_orig; ++ hcint_data_t hcint; + hcintmsk_data_t hcintmsk; + dwc_hc_t *hc; + dwc_otg_hc_regs_t *hc_regs; @@ -77296,24 +80222,32 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + } + qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list); + ++ /* ++ * FSM mode: Check to see if this is a HC interrupt from a channel handled by the FIQ. ++ * Execution path is fundamentally different for the channels after a FIQ has completed ++ * a split transaction. ++ */ ++ if (fiq_fsm_enable) { ++ switch (dwc_otg_hcd->fiq_state->channel[num].fsm) { ++ case FIQ_PASSTHROUGH: ++ break; ++ case FIQ_PASSTHROUGH_ERRORSTATE: ++ /* Hook into the error count */ ++ fiq_print(FIQDBG_ERR, dwc_otg_hcd->fiq_state, "HCDERR%02d", num); ++ if (dwc_otg_hcd->fiq_state->channel[num].nr_errors) { ++ qtd->error_count = 0; ++ fiq_print(FIQDBG_ERR, dwc_otg_hcd->fiq_state, "RESET "); ++ } ++ break; ++ default: ++ dwc_otg_hcd_handle_hc_fsm(dwc_otg_hcd, num); ++ return 1; ++ } ++ } ++ + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); -+ hcint_orig = hcint; + hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); -+ DWC_DEBUGPL(DBG_HCDV, -+ " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n", -+ hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32)); + hcint.d32 = hcint.d32 & hcintmsk.d32; -+ -+ if(fiq_split_enable) -+ { -+ // replace with the saved interrupts from the fiq handler -+ local_fiq_disable(); -+ hcint_orig.d32 = hcint_saved[num].d32; -+ hcint.d32 = hcint_orig.d32 & hcintmsk_saved[num].d32; -+ hcint_saved[num].d32 = 0; -+ local_fiq_enable(); -+ } -+ + if (!dwc_otg_hcd->core_if->dma_enable) { + if (hcint.b.chhltd && hcint.d32 != 0x2) { + hcint.b.chhltd = 0; @@ -77331,7 +80265,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + hcint.b.nyet = 0; + } + if (hcint.b.chhltd) { -+ retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd, hcint_orig, hcintmsk_saved[num]); ++ retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd); + } + if (hcint.b.ahberr) { + retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd); @@ -77367,10 +80301,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe + return retval; +} +#endif /* DWC_DEVICE_ONLY */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 2014-03-11 17:51:27.000000000 +0100 -@@ -0,0 +1,972 @@ +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 2014-04-24 16:04:39.819124254 +0200 +@@ -0,0 +1,985 @@ + +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $ @@ -77431,6 +80365,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb +#else +#include <linux/usb/hcd.h> +#endif ++#include <asm/bug.h> + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) +#define USB_URB_EP_LINKING 1 @@ -77442,7 +80377,8 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb +#include "dwc_otg_dbg.h" +#include "dwc_otg_driver.h" +#include "dwc_otg_hcd.h" -+#include "dwc_otg_mphi_fix.h" ++ ++extern unsigned char _dwc_otg_fiq_stub, _dwc_otg_fiq_stub_end; + +/** + * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is @@ -77453,7 +80389,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb + +static const char dwc_otg_hcd_name[] = "dwc_otg_hcd"; + -+extern bool fiq_fix_enable; ++extern bool fiq_enable; + +/** @name Linux HC Driver API Functions */ +/** @{ */ @@ -77724,7 +80660,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb + urb); + } + } -+ + DWC_FREE(dwc_otg_urb); + if (!new_entry) { + DWC_ERROR("dwc_otg_hcd: complete: cannot allocate URB TQ entry\n"); @@ -77768,13 +80703,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb +static struct fiq_handler fh = { + .name = "usb_fiq", +}; -+struct fiq_stack_s { -+ int magic1; -+ uint8_t stack[2048]; -+ int magic2; -+} fiq_stack; + -+extern mphi_regs_t c_mphi_regs; ++ ++ +/** + * Initializes the HCD. This function allocates memory for and initializes the + * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the @@ -77806,20 +80737,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb + pci_set_consistent_dma_mask(_dev, dmamask); +#endif + -+ if (fiq_fix_enable) -+ { -+ // Set up fiq -+ claim_fiq(&fh); -+ set_fiq_handler(__FIQ_Branch, 4); -+ memset(®s,0,sizeof(regs)); -+ regs.ARM_r8 = (long)dwc_otg_hcd_handle_fiq; -+ regs.ARM_r9 = (long)0; -+ regs.ARM_sp = (long)fiq_stack.stack + sizeof(fiq_stack.stack) - 4; -+ set_fiq_regs(®s); -+ fiq_stack.magic1 = 0xdeadbeef; -+ fiq_stack.magic2 = 0xaa995566; -+ } -+ + /* + * Allocate memory for the base HCD plus the DWC OTG HCD. + * Initialize the base HCD. @@ -77839,30 +80756,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb + + hcd->regs = otg_dev->os_dep.base; + -+ if (fiq_fix_enable) -+ { -+ volatile extern void *dwc_regs_base; -+ -+ //Set the mphi periph to the required registers -+ c_mphi_regs.base = otg_dev->os_dep.mphi_base; -+ c_mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c; -+ c_mphi_regs.outdda = otg_dev->os_dep.mphi_base + 0x28; -+ c_mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c; -+ c_mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50; + -+ dwc_regs_base = otg_dev->os_dep.base; -+ -+ //Enable mphi peripheral -+ writel((1<<31),c_mphi_regs.ctrl); -+#ifdef DEBUG -+ if (readl(c_mphi_regs.ctrl) & 0x80000000) -+ DWC_DEBUGPL(DBG_USER, "MPHI periph has been enabled\n"); -+ else -+ DWC_DEBUGPL(DBG_USER, "MPHI periph has NOT been enabled\n"); -+#endif -+ // Enable FIQ interrupt from USB peripheral -+ enable_fiq(INTERRUPT_VC_USB); -+ } + /* Initialize the DWC OTG HCD. */ + dwc_otg_hcd = dwc_otg_hcd_alloc_hcd(); + if (!dwc_otg_hcd) { @@ -77876,6 +80770,55 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb + goto error2; + } + ++ if (fiq_enable) ++ { ++ if (claim_fiq(&fh)) { ++ DWC_ERROR("Can't claim FIQ"); ++ goto error2; ++ } ++ ++ DWC_WARN("FIQ at 0x%08x", (fiq_fsm_enable ? (int)&dwc_otg_fiq_fsm : (int)&dwc_otg_fiq_nop)); ++ DWC_WARN("FIQ ASM at 0x%08x length %d", (int)&_dwc_otg_fiq_stub, (int)(&_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub)); ++ ++ set_fiq_handler((void *) &_dwc_otg_fiq_stub, &_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub); ++ memset(®s,0,sizeof(regs)); ++ ++ regs.ARM_r8 = (long) dwc_otg_hcd->fiq_state; ++ if (fiq_fsm_enable) { ++ regs.ARM_r9 = dwc_otg_hcd->core_if->core_params->host_channels; ++ //regs.ARM_r10 = dwc_otg_hcd->dma; ++ regs.ARM_fp = (long) dwc_otg_fiq_fsm; ++ } else { ++ regs.ARM_fp = (long) dwc_otg_fiq_nop; ++ } ++ ++ regs.ARM_sp = (long) dwc_otg_hcd->fiq_stack + (sizeof(struct fiq_stack) - 4); ++ ++// __show_regs(®s); ++ set_fiq_regs(®s); ++ ++ //Set the mphi periph to the required registers ++ dwc_otg_hcd->fiq_state->mphi_regs.base = otg_dev->os_dep.mphi_base; ++ dwc_otg_hcd->fiq_state->mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c; ++ dwc_otg_hcd->fiq_state->mphi_regs.outdda = otg_dev->os_dep.mphi_base + 0x28; ++ dwc_otg_hcd->fiq_state->mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c; ++ dwc_otg_hcd->fiq_state->mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50; ++ dwc_otg_hcd->fiq_state->dwc_regs_base = otg_dev->os_dep.base; ++ DWC_WARN("MPHI regs_base at 0x%08x", (int)dwc_otg_hcd->fiq_state->mphi_regs.base); ++ //Enable mphi peripheral ++ writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl); ++#ifdef DEBUG ++ if (readl(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & 0x80000000) ++ DWC_WARN("MPHI periph has been enabled"); ++ else ++ DWC_WARN("MPHI periph has NOT been enabled"); ++#endif ++ // Enable FIQ interrupt from USB peripheral ++ enable_fiq(INTERRUPT_VC_USB); ++ local_fiq_enable(); ++ } ++ ++ + otg_dev->hcd->otg_dev = otg_dev; + hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel) @@ -77990,9 +80933,13 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb +/** Returns the current frame number. */ +static int get_frame_number(struct usb_hcd *hcd) +{ ++ hprt0_data_t hprt0; + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ -+ return dwc_otg_hcd_get_frame_number(dwc_otg_hcd); ++ hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0); ++ if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) ++ return dwc_otg_hcd_get_frame_number(dwc_otg_hcd) >> 3; ++ else ++ return dwc_otg_hcd_get_frame_number(dwc_otg_hcd); +} + +#ifdef DEBUG @@ -78343,10 +81290,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb +} + +#endif /* DWC_DEVICE_ONLY */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 2014-03-11 17:51:27.000000000 +0100 -@@ -0,0 +1,959 @@ +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 2014-04-24 16:04:39.819124254 +0200 +@@ -0,0 +1,942 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $ + * $Revision: #44 $ @@ -78390,7 +81337,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb + +#include "dwc_otg_hcd.h" +#include "dwc_otg_regs.h" -+#include "dwc_otg_mphi_fix.h" + +extern bool microframe_schedule; + @@ -78925,7 +81871,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb +} + + -+extern int g_next_sched_frame, g_np_count, g_np_sent; + +/** + * Schedules an interrupt or isochronous transfer in the periodic schedule. @@ -78985,9 +81930,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb + DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry); + } + else { -+ if(DWC_LIST_EMPTY(&hcd->periodic_sched_inactive) || dwc_frame_num_le(qh->sched_frame, g_next_sched_frame)) ++ if(DWC_LIST_EMPTY(&hcd->periodic_sched_inactive) || dwc_frame_num_le(qh->sched_frame, hcd->fiq_state->next_sched_frame)) + { -+ g_next_sched_frame = qh->sched_frame; ++ hcd->fiq_state->next_sched_frame = qh->sched_frame; + + } + /* Always start in the inactive schedule. */ @@ -79028,7 +81973,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb + /* Always start in the inactive schedule. */ + DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive, + &qh->qh_list_entry); -+ g_np_count++; ++ //hcd->fiq_state->kick_np_queues = 1; + } else { + status = schedule_periodic(hcd, qh); + if ( !hcd->periodic_qh_count ) { @@ -79088,13 +82033,12 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb + hcd->non_periodic_qh_ptr->next; + } + DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); -+ -+ // If we've removed the last non-periodic entry then there are none left! -+ g_np_count = g_np_sent; ++ //if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_inactive)) ++ // hcd->fiq_state->kick_np_queues = 1; + } else { + deschedule_periodic(hcd, qh); + hcd->periodic_qh_count--; -+ if( !hcd->periodic_qh_count ) { ++ if( !hcd->periodic_qh_count && !fiq_fsm_enable ) { + intr_mask.b.sofintr = 1; + DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, + intr_mask.d32, 0); @@ -79119,28 +82063,11 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb + int sched_next_periodic_split) +{ + if (dwc_qh_is_non_per(qh)) { -+ -+ dwc_otg_qh_t *qh_tmp; -+ dwc_list_link_t *qh_list; -+ DWC_LIST_FOREACH(qh_list, &hcd->non_periodic_sched_inactive) -+ { -+ qh_tmp = DWC_LIST_ENTRY(qh_list, struct dwc_otg_qh, qh_list_entry); -+ if(qh_tmp == qh) -+ { -+ /* -+ * FIQ is being disabled because this one nevers gets a np_count increment -+ * This is still not absolutely correct, but it should fix itself with -+ * just an unnecessary extra interrupt -+ */ -+ g_np_sent = g_np_count; -+ } -+ } -+ -+ + dwc_otg_hcd_qh_remove(hcd, qh); + if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { + /* Add back to inactive non-periodic schedule. */ + dwc_otg_hcd_qh_add(hcd, qh); ++ //hcd->fiq_state->kick_np_queues = 1; + } + } else { + uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd); @@ -79199,9 +82126,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, + &qh->qh_list_entry); + } else { -+ if(!dwc_frame_num_le(g_next_sched_frame, qh->sched_frame)) ++ if(!dwc_frame_num_le(hcd->fiq_state->next_sched_frame, qh->sched_frame)) + { -+ g_next_sched_frame = qh->sched_frame; ++ hcd->fiq_state->next_sched_frame = qh->sched_frame; + } + + DWC_LIST_MOVE_HEAD @@ -79292,6 +82219,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb + if (*qh == NULL) { + retval = -DWC_E_NO_MEMORY; + goto done; ++ } else { ++ if (fiq_enable) ++ hcd->fiq_state->kick_np_queues = 1; + } + } + retval = dwc_otg_hcd_qh_add(hcd, *qh); @@ -79306,178 +82236,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb +} + +#endif /* DWC_DEVICE_ONLY */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c 2014-03-11 17:51:27.000000000 +0100 -@@ -0,0 +1,113 @@ -+#include "dwc_otg_regs.h" -+#include "dwc_otg_dbg.h" -+ -+void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name) -+{ -+ DWC_DEBUGPL(DBG_USER, "*** Debugging from within the %s function: ***\n" -+ "curmode: %1i Modemismatch: %1i otgintr: %1i sofintr: %1i\n" -+ "rxstsqlvl: %1i nptxfempty : %1i ginnakeff: %1i goutnakeff: %1i\n" -+ "ulpickint: %1i i2cintr: %1i erlysuspend:%1i usbsuspend: %1i\n" -+ "usbreset: %1i enumdone: %1i isooutdrop: %1i eopframe: %1i\n" -+ "restoredone: %1i epmismatch: %1i inepint: %1i outepintr: %1i\n" -+ "incomplisoin:%1i incomplisoout:%1i fetsusp: %1i resetdet: %1i\n" -+ "portintr: %1i hcintr: %1i ptxfempty: %1i lpmtranrcvd:%1i\n" -+ "conidstschng:%1i disconnect: %1i sessreqintr:%1i wkupintr: %1i\n", -+ function_name, -+ gintsts.b.curmode, -+ gintsts.b.modemismatch, -+ gintsts.b.otgintr, -+ gintsts.b.sofintr, -+ gintsts.b.rxstsqlvl, -+ gintsts.b.nptxfempty, -+ gintsts.b.ginnakeff, -+ gintsts.b.goutnakeff, -+ gintsts.b.ulpickint, -+ gintsts.b.i2cintr, -+ gintsts.b.erlysuspend, -+ gintsts.b.usbsuspend, -+ gintsts.b.usbreset, -+ gintsts.b.enumdone, -+ gintsts.b.isooutdrop, -+ gintsts.b.eopframe, -+ gintsts.b.restoredone, -+ gintsts.b.epmismatch, -+ gintsts.b.inepint, -+ gintsts.b.outepintr, -+ gintsts.b.incomplisoin, -+ gintsts.b.incomplisoout, -+ gintsts.b.fetsusp, -+ gintsts.b.resetdet, -+ gintsts.b.portintr, -+ gintsts.b.hcintr, -+ gintsts.b.ptxfempty, -+ gintsts.b.lpmtranrcvd, -+ gintsts.b.conidstschng, -+ gintsts.b.disconnect, -+ gintsts.b.sessreqintr, -+ gintsts.b.wkupintr); -+ return; -+} -+ -+void dwc_debug_core_int_mask(gintmsk_data_t gintmsk, const char* function_name) -+{ -+ DWC_DEBUGPL(DBG_USER, "Interrupt Mask status (called from %s) :\n" -+ "modemismatch: %1i otgintr: %1i sofintr: %1i rxstsqlvl: %1i\n" -+ "nptxfempty: %1i ginnakeff: %1i goutnakeff: %1i ulpickint: %1i\n" -+ "i2cintr: %1i erlysuspend:%1i usbsuspend: %1i usbreset: %1i\n" -+ "enumdone: %1i isooutdrop: %1i eopframe: %1i restoredone: %1i\n" -+ "epmismatch: %1i inepintr: %1i outepintr: %1i incomplisoin:%1i\n" -+ "incomplisoout:%1i fetsusp: %1i resetdet: %1i portintr: %1i\n" -+ "hcintr: %1i ptxfempty: %1i lpmtranrcvd:%1i conidstschng:%1i\n" -+ "disconnect: %1i sessreqintr:%1i wkupintr: %1i\n", -+ function_name, -+ gintmsk.b.modemismatch, -+ gintmsk.b.otgintr, -+ gintmsk.b.sofintr, -+ gintmsk.b.rxstsqlvl, -+ gintmsk.b.nptxfempty, -+ gintmsk.b.ginnakeff, -+ gintmsk.b.goutnakeff, -+ gintmsk.b.ulpickint, -+ gintmsk.b.i2cintr, -+ gintmsk.b.erlysuspend, -+ gintmsk.b.usbsuspend, -+ gintmsk.b.usbreset, -+ gintmsk.b.enumdone, -+ gintmsk.b.isooutdrop, -+ gintmsk.b.eopframe, -+ gintmsk.b.restoredone, -+ gintmsk.b.epmismatch, -+ gintmsk.b.inepintr, -+ gintmsk.b.outepintr, -+ gintmsk.b.incomplisoin, -+ gintmsk.b.incomplisoout, -+ gintmsk.b.fetsusp, -+ gintmsk.b.resetdet, -+ gintmsk.b.portintr, -+ gintmsk.b.hcintr, -+ gintmsk.b.ptxfempty, -+ gintmsk.b.lpmtranrcvd, -+ gintmsk.b.conidstschng, -+ gintmsk.b.disconnect, -+ gintmsk.b.sessreqintr, -+ gintmsk.b.wkupintr); -+ return; -+} -+ -+void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name) -+{ -+ DWC_DEBUGPL(DBG_USER, "otg int register (from %s function):\n" -+ "sesenddet:%1i sesreqsucstschung:%2i hstnegsucstschng:%1i\n" -+ "hstnegdet:%1i adevtoutchng: %2i debdone: %1i\n" -+ "mvic: %1i\n", -+ function_name, -+ gotgint.b.sesenddet, -+ gotgint.b.sesreqsucstschng, -+ gotgint.b.hstnegsucstschng, -+ gotgint.b.hstnegdet, -+ gotgint.b.adevtoutchng, -+ gotgint.b.debdone, -+ gotgint.b.mvic); -+ -+ return; -+} -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h 2014-03-11 17:33:06.000000000 +0100 -@@ -0,0 +1,48 @@ -+#ifndef __DWC_OTG_MPHI_FIX_H__ -+#define __DWC_OTG_MPHI_FIX_H__ -+#define FIQ_WRITE(_addr_,_data_) (*(volatile uint32_t *) (_addr_) = (_data_)) -+#define FIQ_READ(_addr_) (*(volatile uint32_t *) (_addr_)) -+ -+typedef struct { -+ volatile void* base; -+ volatile void* ctrl; -+ volatile void* outdda; -+ volatile void* outddb; -+ volatile void* intstat; -+} mphi_regs_t; -+ -+void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name); -+void dwc_debug_core_int_mask(gintsts_data_t gintmsk, const char* function_name); -+void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name); -+ -+extern gintsts_data_t gintsts_saved; -+ -+#ifdef DEBUG -+#define DWC_DBG_PRINT_CORE_INT(_arg_) dwc_debug_print_core_int_reg(_arg_,__func__) -+#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_) dwc_debug_core_int_mask(_arg_,__func__) -+#define DWC_DBG_PRINT_OTG_INT(_arg_) dwc_debug_otg_int(_arg_,__func__) -+ -+#else -+#define DWC_DBG_PRINT_CORE_INT(_arg_) -+#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_) -+#define DWC_DBG_PRINT_OTG_INT(_arg_) -+ -+#endif -+ -+typedef enum { -+ FIQDBG_SCHED = (1 << 0), -+ FIQDBG_INT = (1 << 1), -+ FIQDBG_ERR = (1 << 2), -+ FIQDBG_PORTHUB = (1 << 3), -+} FIQDBG_T; -+ -+void _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...); -+#ifdef FIQ_DEBUG -+#define fiq_print _fiq_print -+#else -+#define fiq_print(x, y, ...) -+#endif -+ -+extern bool fiq_fix_enable, nak_holdoff_enable, fiq_split_enable; -+ -+#endif -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h 2014-04-24 16:04:39.819124254 +0200 @@ -0,0 +1,188 @@ +#ifndef _DWC_OS_DEP_H_ +#define _DWC_OS_DEP_H_ @@ -79667,9 +82428,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h linux-raspberr + + +#endif /* _DWC_OS_DEP_H_ */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 2014-04-24 16:04:39.819124254 +0200 @@ -0,0 +1,2708 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $ @@ -82379,9 +85140,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-raspberry-p +} + +#endif /* DWC_HOST_ONLY */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 2014-04-24 15:35:04.177565820 +0200 @@ -0,0 +1,266 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $ @@ -82649,9 +85410,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-raspberry-p +extern void do_test_mode(void *data); +#endif +#endif /* DWC_HOST_ONLY */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 2014-04-24 15:35:04.177565820 +0200 @@ -0,0 +1,360 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $ @@ -83013,9 +85774,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-raspberr +#endif /* __DWC_PCD_IF_H__ */ + +#endif /* DWC_HOST_ONLY */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 2014-04-24 16:04:39.823124292 +0200 @@ -0,0 +1,5147 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $ @@ -88164,9 +90925,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-raspbe +} + +#endif /* DWC_HOST_ONLY */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 2014-04-24 16:04:39.823124292 +0200 @@ -0,0 +1,1358 @@ + /* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $ @@ -89526,9 +92287,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-raspb +EXPORT_SYMBOL(usb_gadget_unregister_driver); + +#endif /* DWC_HOST_ONLY */ -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_regs.h ---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_regs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_regs.h 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_regs.h +--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_regs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_regs.h 2014-04-24 16:04:39.823124292 +0200 @@ -0,0 +1,2550 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $ @@ -92080,10 +94841,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-raspberry- +} gpwrdn_data_t; + +#endif -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/Makefile linux-raspberry-pi/drivers/usb/host/dwc_otg/Makefile ---- linux-3.12.13/drivers/usb/host/dwc_otg/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/Makefile 2014-03-11 17:51:27.000000000 +0100 -@@ -0,0 +1,81 @@ +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/Makefile linux-rpi/drivers/usb/host/dwc_otg/Makefile +--- linux-3.12.18/drivers/usb/host/dwc_otg/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/Makefile 2014-04-24 16:04:39.815124215 +0200 +@@ -0,0 +1,82 @@ +# +# Makefile for DWC_otg Highspeed USB controller driver +# @@ -92098,22 +94859,22 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/Makefile linux-raspberry-pi/dri + BUS_INTERFACE = -DPLATFORM_INTERFACE +endif + -+#EXTRA_CFLAGS += -DDEBUG -+#EXTRA_CFLAGS += -DDWC_OTG_DEBUGLEV=1 # reduce common debug msgs ++#ccflags-y += -DDEBUG ++#ccflags-y += -DDWC_OTG_DEBUGLEV=1 # reduce common debug msgs + +# Use one of the following flags to compile the software in host-only or +# device-only mode. -+#EXTRA_CFLAGS += -DDWC_HOST_ONLY -+#EXTRA_CFLAGS += -DDWC_DEVICE_ONLY -+ -+EXTRA_CFLAGS += -Dlinux -DDWC_HS_ELECT_TST -+#EXTRA_CFLAGS += -DDWC_EN_ISOC -+EXTRA_CFLAGS += -I$(obj)/../dwc_common_port -+#EXTRA_CFLAGS += -I$(PORTLIB) -+EXTRA_CFLAGS += -DDWC_LINUX -+EXTRA_CFLAGS += $(CFI) -+EXTRA_CFLAGS += $(BUS_INTERFACE) -+#EXTRA_CFLAGS += -DDWC_DEV_SRPCAP ++#ccflags-y += -DDWC_HOST_ONLY ++#ccflags-y += -DDWC_DEVICE_ONLY ++ ++ccflags-y += -Dlinux -DDWC_HS_ELECT_TST ++#ccflags-y += -DDWC_EN_ISOC ++ccflags-y += -I$(obj)/../dwc_common_port ++#ccflags-y += -I$(PORTLIB) ++ccflags-y += -DDWC_LINUX ++ccflags-y += $(CFI) ++ccflags-y += $(BUS_INTERFACE) ++#ccflags-y += -DDWC_DEV_SRPCAP + +obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o + @@ -92122,7 +94883,8 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/Makefile linux-raspberry-pi/dri +dwc_otg-objs += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o +dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o +dwc_otg-objs += dwc_otg_adp.o -+dwc_otg-objs += dwc_otg_mphi_fix.o ++dwc_otg-objs += dwc_otg_fiq_fsm.o ++dwc_otg-objs += dwc_otg_fiq_stub.o +ifneq ($(CFI),) +dwc_otg-objs += dwc_otg_cfi.o +endif @@ -92131,7 +94893,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/Makefile linux-raspberry-pi/dri +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd)) + +ifneq ($(kernrel3),2.6.20) -+EXTRA_CFLAGS += $(CPPFLAGS) ++ccflags-y += $(CPPFLAGS) +endif + +else @@ -92165,9 +94927,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/Makefile linux-raspberry-pi/dri + rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers + +endif -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm linux-raspberry-pi/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm ---- linux-3.12.13/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm linux-rpi/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm +--- linux-3.12.18/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 2014-04-24 16:04:39.823124292 +0200 @@ -0,0 +1,337 @@ +package dwc_otg_test; + @@ -92506,9 +95268,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm linux-rasp +); + +1; -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/Makefile linux-raspberry-pi/drivers/usb/host/dwc_otg/test/Makefile ---- linux-3.12.13/drivers/usb/host/dwc_otg/test/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/test/Makefile 2014-03-11 17:33:06.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/test/Makefile linux-rpi/drivers/usb/host/dwc_otg/test/Makefile +--- linux-3.12.18/drivers/usb/host/dwc_otg/test/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/test/Makefile 2014-04-24 15:35:04.177565820 +0200 @@ -0,0 +1,16 @@ + +PERL=/usr/bin/perl @@ -92526,9 +95288,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/Makefile linux-raspberry-p + else echo "=======> $$test, FAILED" ; \ + fi \ + done -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/test_mod_param.pl linux-raspberry-pi/drivers/usb/host/dwc_otg/test/test_mod_param.pl ---- linux-3.12.13/drivers/usb/host/dwc_otg/test/test_mod_param.pl 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/test/test_mod_param.pl 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/test/test_mod_param.pl linux-rpi/drivers/usb/host/dwc_otg/test/test_mod_param.pl +--- linux-3.12.18/drivers/usb/host/dwc_otg/test/test_mod_param.pl 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/test/test_mod_param.pl 2014-04-24 16:04:39.823124292 +0200 @@ -0,0 +1,133 @@ +#!/usr/bin/perl -w +# @@ -92663,9 +95425,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/test_mod_param.pl linux-ra + +test_main(); +0; -diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/test_sysfs.pl linux-raspberry-pi/drivers/usb/host/dwc_otg/test/test_sysfs.pl ---- linux-3.12.13/drivers/usb/host/dwc_otg/test/test_sysfs.pl 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/test/test_sysfs.pl 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/test/test_sysfs.pl linux-rpi/drivers/usb/host/dwc_otg/test/test_sysfs.pl +--- linux-3.12.18/drivers/usb/host/dwc_otg/test/test_sysfs.pl 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/usb/host/dwc_otg/test/test_sysfs.pl 2014-04-24 16:04:39.823124292 +0200 @@ -0,0 +1,193 @@ +#!/usr/bin/perl -w +# @@ -92860,9 +95622,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/test_sysfs.pl linux-raspbe + +test_main(); +0; -diff -Nur linux-3.12.13/drivers/usb/host/Kconfig linux-raspberry-pi/drivers/usb/host/Kconfig ---- linux-3.12.13/drivers/usb/host/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/Kconfig 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/Kconfig linux-rpi/drivers/usb/host/Kconfig +--- linux-3.12.18/drivers/usb/host/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/usb/host/Kconfig 2014-04-24 16:04:39.811124176 +0200 @@ -650,6 +650,19 @@ To compile this driver a module, choose M here: the module will be called "hwa-hc". @@ -92883,9 +95645,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/Kconfig linux-raspberry-pi/drivers/usb/ config USB_IMX21_HCD tristate "i.MX21 HCD support" depends on ARM && ARCH_MXC -diff -Nur linux-3.12.13/drivers/usb/host/Makefile linux-raspberry-pi/drivers/usb/host/Makefile ---- linux-3.12.13/drivers/usb/host/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/host/Makefile 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/host/Makefile linux-rpi/drivers/usb/host/Makefile +--- linux-3.12.18/drivers/usb/host/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/usb/host/Makefile 2014-04-24 16:04:39.811124176 +0200 @@ -56,6 +56,8 @@ obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o @@ -92895,9 +95657,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/Makefile linux-raspberry-pi/drivers/usb obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o -diff -Nur linux-3.12.13/drivers/usb/Makefile linux-raspberry-pi/drivers/usb/Makefile ---- linux-3.12.13/drivers/usb/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/usb/Makefile 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/usb/Makefile linux-rpi/drivers/usb/Makefile +--- linux-3.12.18/drivers/usb/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/usb/Makefile 2014-04-24 16:04:39.695123055 +0200 @@ -23,6 +23,7 @@ obj-$(CONFIG_USB_R8A66597_HCD) += host/ obj-$(CONFIG_USB_HWA_HCD) += host/ @@ -92906,10 +95668,56 @@ diff -Nur linux-3.12.13/drivers/usb/Makefile linux-raspberry-pi/drivers/usb/Make obj-$(CONFIG_USB_IMX21_HCD) += host/ obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/ obj-$(CONFIG_USB_FUSBH200_HCD) += host/ -diff -Nur linux-3.12.13/drivers/video/bcm2708_fb.c linux-raspberry-pi/drivers/video/bcm2708_fb.c ---- linux-3.12.13/drivers/video/bcm2708_fb.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/video/bcm2708_fb.c 2014-03-11 17:51:27.000000000 +0100 -@@ -0,0 +1,765 @@ +diff -Nur linux-3.12.18/drivers/vhost/net.c linux-rpi/drivers/vhost/net.c +--- linux-3.12.18/drivers/vhost/net.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/vhost/net.c 2014-04-24 16:04:39.911125143 +0200 +@@ -501,13 +501,9 @@ + r = -ENOBUFS; + goto err; + } +- r = vhost_get_vq_desc(vq->dev, vq, vq->iov + seg, ++ d = vhost_get_vq_desc(vq->dev, vq, vq->iov + seg, + ARRAY_SIZE(vq->iov) - seg, &out, + &in, log, log_num); +- if (unlikely(r < 0)) +- goto err; +- +- d = r; + if (d == vq->num) { + r = 0; + goto err; +@@ -532,12 +528,6 @@ + *iovcount = seg; + if (unlikely(log)) + *log_num = nlogs; +- +- /* Detect overrun */ +- if (unlikely(datalen > 0)) { +- r = UIO_MAXIOV + 1; +- goto err; +- } + return headcount; + err: + vhost_discard_vq_desc(vq, headcount); +@@ -593,14 +583,6 @@ + /* On error, stop handling until the next kick. */ + if (unlikely(headcount < 0)) + break; +- /* On overrun, truncate and discard */ +- if (unlikely(headcount > UIO_MAXIOV)) { +- msg.msg_iovlen = 1; +- err = sock->ops->recvmsg(NULL, sock, &msg, +- 1, MSG_DONTWAIT | MSG_TRUNC); +- pr_debug("Discarded rx packet: len %zd\n", sock_len); +- continue; +- } + /* OK, now we need to know about added descriptors. */ + if (!headcount) { + if (unlikely(vhost_enable_notify(&net->dev, vq))) { +diff -Nur linux-3.12.18/drivers/video/bcm2708_fb.c linux-rpi/drivers/video/bcm2708_fb.c +--- linux-3.12.18/drivers/video/bcm2708_fb.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/video/bcm2708_fb.c 2014-04-24 16:04:39.919125220 +0200 +@@ -0,0 +1,762 @@ +/* + * linux/drivers/video/bcm2708_fb.c + * @@ -93563,9 +96371,6 @@ diff -Nur linux-3.12.13/drivers/video/bcm2708_fb.c linux-raspberry-pi/drivers/vi + + bcm2708_fb_debugfs_init(fb); + -+ -+ bcm2708_fb_debugfs_init(fb); -+ + fb->cb_base = dma_alloc_writecombine(&dev->dev, SZ_64K, + &fb->cb_handle, GFP_KERNEL); + if (!fb->cb_base) { @@ -93675,9 +96480,9 @@ diff -Nur linux-3.12.13/drivers/video/bcm2708_fb.c linux-raspberry-pi/drivers/vi +MODULE_PARM_DESC(fbheight, "Height of ARM Framebuffer"); +MODULE_PARM_DESC(fbdepth, "Bit depth of ARM Framebuffer"); +MODULE_PARM_DESC(fbswap, "Swap order of red and blue in 24 and 32 bit modes"); -diff -Nur linux-3.12.13/drivers/video/cfbimgblt.c linux-raspberry-pi/drivers/video/cfbimgblt.c ---- linux-3.12.13/drivers/video/cfbimgblt.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/video/cfbimgblt.c 2014-03-11 17:33:07.000000000 +0100 +diff -Nur linux-3.12.18/drivers/video/cfbimgblt.c linux-rpi/drivers/video/cfbimgblt.c +--- linux-3.12.18/drivers/video/cfbimgblt.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/video/cfbimgblt.c 2014-04-24 15:35:04.265566801 +0200 @@ -28,6 +28,11 @@ * * Also need to add code to deal with cards endians that are different than @@ -93851,9 +96656,9 @@ diff -Nur linux-3.12.13/drivers/video/cfbimgblt.c linux-raspberry-pi/drivers/vid slow_imageblit(image, p, dst1, fgcolor, bgcolor, start_index, pitch_index); } else -diff -Nur linux-3.12.13/drivers/video/fbmem.c linux-raspberry-pi/drivers/video/fbmem.c ---- linux-3.12.13/drivers/video/fbmem.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/video/fbmem.c 2014-03-11 17:51:27.000000000 +0100 +diff -Nur linux-3.12.18/drivers/video/fbmem.c linux-rpi/drivers/video/fbmem.c +--- linux-3.12.18/drivers/video/fbmem.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/video/fbmem.c 2014-04-24 16:04:39.923125259 +0200 @@ -1083,6 +1083,25 @@ } EXPORT_SYMBOL(fb_blank); @@ -93888,9 +96693,75 @@ diff -Nur linux-3.12.13/drivers/video/fbmem.c linux-raspberry-pi/drivers/video/f void __user *argp = (void __user *)arg; long ret = 0; -@@ -1202,6 +1222,15 @@ +@@ -1108,16 +1128,14 @@ + case FBIOPUT_VSCREENINFO: + if (copy_from_user(&var, argp, sizeof(var))) + return -EFAULT; +- console_lock(); +- if (!lock_fb_info(info)) { +- console_unlock(); ++ if (!lock_fb_info(info)) + return -ENODEV; +- } ++ console_lock(); + info->flags |= FBINFO_MISC_USEREVENT; + ret = fb_set_var(info, &var); + info->flags &= ~FBINFO_MISC_USEREVENT; +- unlock_fb_info(info); + console_unlock(); ++ unlock_fb_info(info); + if (!ret && copy_to_user(argp, &var, sizeof(var))) + ret = -EFAULT; + break; +@@ -1146,14 +1164,12 @@ + case FBIOPAN_DISPLAY: + if (copy_from_user(&var, argp, sizeof(var))) + return -EFAULT; +- console_lock(); +- if (!lock_fb_info(info)) { +- console_unlock(); ++ if (!lock_fb_info(info)) + return -ENODEV; +- } ++ console_lock(); + ret = fb_pan_display(info, &var); +- unlock_fb_info(info); console_unlock(); - unlock_fb_info(info); ++ unlock_fb_info(info); + if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) + return -EFAULT; + break; +@@ -1188,28 +1204,33 @@ + break; + } + event.data = &con2fb; +- console_lock(); +- if (!lock_fb_info(info)) { +- console_unlock(); ++ if (!lock_fb_info(info)) + return -ENODEV; +- } ++ console_lock(); + event.info = info; + ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); +- unlock_fb_info(info); + console_unlock(); ++ unlock_fb_info(info); + break; + case FBIOBLANK: +- console_lock(); +- if (!lock_fb_info(info)) { +- console_unlock(); ++ if (!lock_fb_info(info)) + return -ENODEV; +- } ++ console_lock(); + info->flags |= FBINFO_MISC_USEREVENT; + ret = fb_blank(info, arg); + info->flags &= ~FBINFO_MISC_USEREVENT; +- unlock_fb_info(info); + console_unlock(); ++ unlock_fb_info(info); break; + case FBIOCOPYAREA: + if (info->flags & FBINFO_HWACCEL_COPYAREA) { @@ -93904,7 +96775,7 @@ diff -Nur linux-3.12.13/drivers/video/fbmem.c linux-raspberry-pi/drivers/video/f default: if (!lock_fb_info(info)) return -ENODEV; -@@ -1356,6 +1385,7 @@ +@@ -1364,6 +1385,7 @@ case FBIOPAN_DISPLAY: case FBIOGET_CON2FBMAP: case FBIOPUT_CON2FBMAP: @@ -93912,9 +96783,168 @@ diff -Nur linux-3.12.13/drivers/video/fbmem.c linux-raspberry-pi/drivers/video/f arg = (unsigned long) compat_ptr(arg); case FBIOBLANK: ret = do_fb_ioctl(info, cmd, arg); -diff -Nur linux-3.12.13/drivers/video/Kconfig linux-raspberry-pi/drivers/video/Kconfig ---- linux-3.12.13/drivers/video/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/video/Kconfig 2014-03-11 17:51:27.000000000 +0100 +@@ -1577,10 +1599,10 @@ + static int do_unregister_framebuffer(struct fb_info *fb_info); + + #define VGA_FB_PHYS 0xA0000 +-static int do_remove_conflicting_framebuffers(struct apertures_struct *a, +- const char *name, bool primary) ++static void do_remove_conflicting_framebuffers(struct apertures_struct *a, ++ const char *name, bool primary) + { +- int i, ret; ++ int i; + + /* check all firmware fbs and kick off if the base addr overlaps */ + for (i = 0 ; i < FB_MAX; i++) { +@@ -1596,31 +1618,25 @@ + (primary && gen_aper && gen_aper->count && + gen_aper->ranges[0].base == VGA_FB_PHYS)) { + +- printk(KERN_INFO "fb: switching to %s from %s\n", ++ printk(KERN_INFO "fb: conflicting fb hw usage " ++ "%s vs %s - removing generic driver\n", + name, registered_fb[i]->fix.id); +- ret = do_unregister_framebuffer(registered_fb[i]); +- if (ret) +- return ret; ++ do_unregister_framebuffer(registered_fb[i]); + } + } +- +- return 0; + } + + static int do_register_framebuffer(struct fb_info *fb_info) + { +- int i, ret; ++ int i; + struct fb_event event; + struct fb_videomode mode; + + if (fb_check_foreignness(fb_info)) + return -ENOSYS; + +- ret = do_remove_conflicting_framebuffers(fb_info->apertures, +- fb_info->fix.id, +- fb_is_primary_device(fb_info)); +- if (ret) +- return ret; ++ do_remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, ++ fb_is_primary_device(fb_info)); + + if (num_registered_fb == FB_MAX) + return -ENXIO; +@@ -1674,15 +1690,12 @@ + registered_fb[i] = fb_info; + + event.info = fb_info; +- console_lock(); +- if (!lock_fb_info(fb_info)) { +- console_unlock(); ++ if (!lock_fb_info(fb_info)) + return -ENODEV; +- } +- ++ console_lock(); + fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); +- unlock_fb_info(fb_info); + console_unlock(); ++ unlock_fb_info(fb_info); + return 0; + } + +@@ -1695,16 +1708,13 @@ + if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) + return -EINVAL; + +- console_lock(); +- if (!lock_fb_info(fb_info)) { +- console_unlock(); ++ if (!lock_fb_info(fb_info)) + return -ENODEV; +- } +- ++ console_lock(); + event.info = fb_info; + ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); +- unlock_fb_info(fb_info); + console_unlock(); ++ unlock_fb_info(fb_info); + + if (ret) + return -EINVAL; +@@ -1745,16 +1755,12 @@ + } + EXPORT_SYMBOL(unlink_framebuffer); + +-int remove_conflicting_framebuffers(struct apertures_struct *a, +- const char *name, bool primary) ++void remove_conflicting_framebuffers(struct apertures_struct *a, ++ const char *name, bool primary) + { +- int ret; +- + mutex_lock(®istration_lock); +- ret = do_remove_conflicting_framebuffers(a, name, primary); ++ do_remove_conflicting_framebuffers(a, name, primary); + mutex_unlock(®istration_lock); +- +- return ret; + } + EXPORT_SYMBOL(remove_conflicting_framebuffers); + +diff -Nur linux-3.12.18/drivers/video/fbsysfs.c linux-rpi/drivers/video/fbsysfs.c +--- linux-3.12.18/drivers/video/fbsysfs.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/video/fbsysfs.c 2014-04-24 15:35:04.277566935 +0200 +@@ -177,12 +177,9 @@ + if (i * sizeof(struct fb_videomode) != count) + return -EINVAL; + +- console_lock(); +- if (!lock_fb_info(fb_info)) { +- console_unlock(); ++ if (!lock_fb_info(fb_info)) + return -ENODEV; +- } +- ++ console_lock(); + list_splice(&fb_info->modelist, &old_list); + fb_videomode_to_modelist((const struct fb_videomode *)buf, i, + &fb_info->modelist); +@@ -192,8 +189,8 @@ + } else + fb_destroy_modelist(&old_list); + +- unlock_fb_info(fb_info); + console_unlock(); ++ unlock_fb_info(fb_info); + + return 0; + } +@@ -407,16 +404,12 @@ + + state = simple_strtoul(buf, &last, 0); + +- console_lock(); +- if (!lock_fb_info(fb_info)) { +- console_unlock(); ++ if (!lock_fb_info(fb_info)) + return -ENODEV; +- } +- ++ console_lock(); + fb_set_suspend(fb_info, (int)state); +- +- unlock_fb_info(fb_info); + console_unlock(); ++ unlock_fb_info(fb_info); + + return count; + } +diff -Nur linux-3.12.18/drivers/video/Kconfig linux-rpi/drivers/video/Kconfig +--- linux-3.12.18/drivers/video/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/video/Kconfig 2014-04-24 16:04:39.911125143 +0200 @@ -310,6 +310,20 @@ help Support the Permedia2 FIFO disconnect feature. @@ -93936,9 +96966,9 @@ diff -Nur linux-3.12.13/drivers/video/Kconfig linux-raspberry-pi/drivers/video/K config FB_ARMCLCD tristate "ARM PrimeCell PL110 support" depends on FB && ARM && ARM_AMBA -diff -Nur linux-3.12.13/drivers/video/logo/logo_linux_clut224.ppm linux-raspberry-pi/drivers/video/logo/logo_linux_clut224.ppm ---- linux-3.12.13/drivers/video/logo/logo_linux_clut224.ppm 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/video/logo/logo_linux_clut224.ppm 2014-03-11 17:33:08.000000000 +0100 +diff -Nur linux-3.12.18/drivers/video/logo/logo_linux_clut224.ppm linux-rpi/drivers/video/logo/logo_linux_clut224.ppm +--- linux-3.12.18/drivers/video/logo/logo_linux_clut224.ppm 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/video/logo/logo_linux_clut224.ppm 2014-04-24 15:35:04.285567024 +0200 @@ -1,1604 +1,883 @@ P3 -# Standard 224-color Linux logo @@ -96425,9 +99455,9 @@ diff -Nur linux-3.12.13/drivers/video/logo/logo_linux_clut224.ppm linux-raspberr +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 -diff -Nur linux-3.12.13/drivers/video/Makefile linux-raspberry-pi/drivers/video/Makefile ---- linux-3.12.13/drivers/video/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/video/Makefile 2014-03-11 17:33:07.000000000 +0100 +diff -Nur linux-3.12.18/drivers/video/Makefile linux-rpi/drivers/video/Makefile +--- linux-3.12.18/drivers/video/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/video/Makefile 2014-04-24 15:35:04.249566623 +0200 @@ -100,6 +100,7 @@ obj-$(CONFIG_FB_VOODOO1) += sstfb.o obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o @@ -96436,9 +99466,47 @@ diff -Nur linux-3.12.13/drivers/video/Makefile linux-raspberry-pi/drivers/video/ obj-$(CONFIG_FB_68328) += 68328fb.o obj-$(CONFIG_FB_GBE) += gbefb.o obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o -diff -Nur linux-3.12.13/drivers/w1/masters/w1-gpio.c linux-raspberry-pi/drivers/w1/masters/w1-gpio.c ---- linux-3.12.13/drivers/w1/masters/w1-gpio.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/w1/masters/w1-gpio.c 2014-03-11 17:51:32.000000000 +0100 +diff -Nur linux-3.12.18/drivers/video/sh_mobile_lcdcfb.c linux-rpi/drivers/video/sh_mobile_lcdcfb.c +--- linux-3.12.18/drivers/video/sh_mobile_lcdcfb.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/video/sh_mobile_lcdcfb.c 2014-04-24 15:35:04.325567469 +0200 +@@ -574,9 +574,8 @@ + switch (event) { + case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT: + /* HDMI plug in */ +- console_lock(); + if (lock_fb_info(info)) { +- ++ console_lock(); + + ch->display.width = monspec->max_x * 10; + ch->display.height = monspec->max_y * 10; +@@ -595,20 +594,19 @@ + fb_set_suspend(info, 0); + } + +- ++ console_unlock(); + unlock_fb_info(info); + } +- console_unlock(); + break; + + case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT: + /* HDMI disconnect */ +- console_lock(); + if (lock_fb_info(info)) { ++ console_lock(); + fb_set_suspend(info, 1); ++ console_unlock(); + unlock_fb_info(info); + } +- console_unlock(); + break; + + case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE: +diff -Nur linux-3.12.18/drivers/w1/masters/w1-gpio.c linux-rpi/drivers/w1/masters/w1-gpio.c +--- linux-3.12.18/drivers/w1/masters/w1-gpio.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/w1/masters/w1-gpio.c 2014-04-24 16:04:39.951125530 +0200 @@ -22,6 +22,9 @@ #include "../w1.h" #include "../w1_int.h" @@ -96480,9 +99548,9 @@ diff -Nur linux-3.12.13/drivers/w1/masters/w1-gpio.c linux-raspberry-pi/drivers/ err = w1_add_master_device(master); if (err) { dev_err(&pdev->dev, "w1_add_master device failed\n"); -diff -Nur linux-3.12.13/drivers/w1/w1.h linux-raspberry-pi/drivers/w1/w1.h ---- linux-3.12.13/drivers/w1/w1.h 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/w1/w1.h 2014-03-11 17:33:12.000000000 +0100 +diff -Nur linux-3.12.18/drivers/w1/w1.h linux-rpi/drivers/w1/w1.h +--- linux-3.12.18/drivers/w1/w1.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/w1/w1.h 2014-04-24 15:35:04.349567736 +0200 @@ -148,6 +148,12 @@ */ u8 (*set_pullup)(void *, int); @@ -96496,29 +99564,21 @@ diff -Nur linux-3.12.13/drivers/w1/w1.h linux-raspberry-pi/drivers/w1/w1.h /** Really nice hardware can handles the different types of ROM search * w1_master* is passed to the slave found callback. */ -diff -Nur linux-3.12.13/drivers/w1/w1_int.c linux-raspberry-pi/drivers/w1/w1_int.c ---- linux-3.12.13/drivers/w1/w1_int.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/w1/w1_int.c 2014-03-11 17:33:12.000000000 +0100 -@@ -117,19 +117,21 @@ - printk(KERN_ERR "w1_add_master_device: invalid function set\n"); - return(-EINVAL); - } -- /* While it would be electrically possible to make a device that -- * generated a strong pullup in bit bang mode, only hardware that -- * controls 1-wire time frames are even expected to support a strong -- * pullup. w1_io.c would need to support calling set_pullup before -- * the last write_bit operation of a w1_write_8 which it currently -- * doesn't. -- */ -+ -+ /* bitbanging hardware uses bitbang_pullup, other hardware uses set_pullup -+ * and takes care of timing itself */ - if (!master->write_byte && !master->touch_bit && master->set_pullup) { - printk(KERN_ERR "w1_add_master_device: set_pullup requires " - "write_byte or touch_bit, disabling\n"); +diff -Nur linux-3.12.18/drivers/w1/w1_int.c linux-rpi/drivers/w1/w1_int.c +--- linux-3.12.18/drivers/w1/w1_int.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/w1/w1_int.c 2014-04-24 16:04:39.955125569 +0200 +@@ -130,6 +130,20 @@ master->set_pullup = NULL; } ++ /* bitbanging hardware uses bitbang_pullup, other hardware uses set_pullup ++ * and takes care of timing itself */ ++ if (!master->write_byte && !master->touch_bit && master->set_pullup) { ++ printk(KERN_ERR "w1_add_master_device: set_pullup requires " ++ "write_byte or touch_bit, disabling\n"); ++ master->set_pullup = NULL; ++ } ++ + if (master->set_pullup && master->bitbang_pullup) { + printk(KERN_ERR "w1_add_master_device: set_pullup should not " + "be set when bitbang_pullup is used, disabling\n"); @@ -96528,9 +99588,9 @@ diff -Nur linux-3.12.13/drivers/w1/w1_int.c linux-raspberry-pi/drivers/w1/w1_int /* Lock until the device is added (or not) to w1_masters. */ mutex_lock(&w1_mlock); /* Search for the first available id (starting at 1). */ -diff -Nur linux-3.12.13/drivers/w1/w1_io.c linux-raspberry-pi/drivers/w1/w1_io.c ---- linux-3.12.13/drivers/w1/w1_io.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/w1/w1_io.c 2014-03-11 17:33:12.000000000 +0100 +diff -Nur linux-3.12.18/drivers/w1/w1_io.c linux-rpi/drivers/w1/w1_io.c +--- linux-3.12.18/drivers/w1/w1_io.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/w1/w1_io.c 2014-04-24 15:35:04.349567736 +0200 @@ -127,10 +127,22 @@ static void w1_post_write(struct w1_master *dev) { @@ -96557,9 +99617,9 @@ diff -Nur linux-3.12.13/drivers/w1/w1_io.c linux-raspberry-pi/drivers/w1/w1_io.c dev->pullup_duration = 0; } } -diff -Nur linux-3.12.13/drivers/watchdog/bcm2708_wdog.c linux-raspberry-pi/drivers/watchdog/bcm2708_wdog.c ---- linux-3.12.13/drivers/watchdog/bcm2708_wdog.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/drivers/watchdog/bcm2708_wdog.c 2014-03-11 17:51:32.000000000 +0100 +diff -Nur linux-3.12.18/drivers/watchdog/bcm2708_wdog.c linux-rpi/drivers/watchdog/bcm2708_wdog.c +--- linux-3.12.18/drivers/watchdog/bcm2708_wdog.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/drivers/watchdog/bcm2708_wdog.c 2014-04-24 16:04:39.955125569 +0200 @@ -0,0 +1,384 @@ +/* + * Broadcom BCM2708 watchdog driver. @@ -96945,9 +100005,9 @@ diff -Nur linux-3.12.13/drivers/watchdog/bcm2708_wdog.c linux-raspberry-pi/drive +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +MODULE_ALIAS_MISCDEV(TEMP_MINOR); +MODULE_LICENSE("GPL"); -diff -Nur linux-3.12.13/drivers/watchdog/Kconfig linux-raspberry-pi/drivers/watchdog/Kconfig ---- linux-3.12.13/drivers/watchdog/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/watchdog/Kconfig 2014-03-11 17:51:32.000000000 +0100 +diff -Nur linux-3.12.18/drivers/watchdog/Kconfig linux-rpi/drivers/watchdog/Kconfig +--- linux-3.12.18/drivers/watchdog/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/watchdog/Kconfig 2014-04-24 16:04:39.955125569 +0200 @@ -392,6 +392,12 @@ To compile this driver as a module, choose M here: the module will be called retu_wdt. @@ -96961,9 +100021,9 @@ diff -Nur linux-3.12.13/drivers/watchdog/Kconfig linux-raspberry-pi/drivers/watc # AVR32 Architecture config AT32AP700X_WDT -diff -Nur linux-3.12.13/drivers/watchdog/Makefile linux-raspberry-pi/drivers/watchdog/Makefile ---- linux-3.12.13/drivers/watchdog/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/drivers/watchdog/Makefile 2014-03-11 17:51:32.000000000 +0100 +diff -Nur linux-3.12.18/drivers/watchdog/Makefile linux-rpi/drivers/watchdog/Makefile +--- linux-3.12.18/drivers/watchdog/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/drivers/watchdog/Makefile 2014-04-24 16:04:39.955125569 +0200 @@ -54,6 +54,7 @@ obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o @@ -96972,9 +100032,102 @@ diff -Nur linux-3.12.13/drivers/watchdog/Makefile linux-raspberry-pi/drivers/wat obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o # AVR32 Architecture -diff -Nur linux-3.12.13/include/linux/broadcom/vc_cma.h linux-raspberry-pi/include/linux/broadcom/vc_cma.h ---- linux-3.12.13/include/linux/broadcom/vc_cma.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/include/linux/broadcom/vc_cma.h 2014-03-11 17:51:38.000000000 +0100 +diff -Nur linux-3.12.18/fs/ext4/inode.c linux-rpi/fs/ext4/inode.c +--- linux-3.12.18/fs/ext4/inode.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/fs/ext4/inode.c 2014-04-24 16:04:40.039126380 +0200 +@@ -4447,12 +4447,7 @@ + return -EIO; + } + +- /* +- * No need to force transaction in WB_SYNC_NONE mode. Also +- * ext4_sync_fs() will force the commit after everything is +- * written. +- */ +- if (wbc->sync_mode != WB_SYNC_ALL || wbc->for_sync) ++ if (wbc->sync_mode != WB_SYNC_ALL) + return 0; + + err = ext4_force_commit(inode->i_sb); +@@ -4462,11 +4457,7 @@ + err = __ext4_get_inode_loc(inode, &iloc, 0); + if (err) + return err; +- /* +- * sync(2) will flush the whole buffer cache. No need to do +- * it here separately for each inode. +- */ +- if (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync) ++ if (wbc->sync_mode == WB_SYNC_ALL) + sync_dirty_buffer(iloc.bh); + if (buffer_req(iloc.bh) && !buffer_uptodate(iloc.bh)) { + EXT4_ERROR_INODE_BLOCK(inode, iloc.bh->b_blocknr, +diff -Nur linux-3.12.18/fs/nfs/nfs3acl.c linux-rpi/fs/nfs/nfs3acl.c +--- linux-3.12.18/fs/nfs/nfs3acl.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/fs/nfs/nfs3acl.c 2014-04-24 15:35:04.557570053 +0200 +@@ -289,8 +289,8 @@ + return acl; + } + +-static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, +- struct posix_acl *dfacl) ++static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, ++ struct posix_acl *dfacl) + { + struct nfs_server *server = NFS_SERVER(inode); + struct nfs_fattr *fattr; +@@ -373,15 +373,6 @@ + return status; + } + +-int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, +- struct posix_acl *dfacl) +-{ +- int ret; +- ret = __nfs3_proc_setacls(inode, acl, dfacl); +- return (ret == -EOPNOTSUPP) ? 0 : ret; +- +-} +- + int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl) + { + struct posix_acl *alloc = NULL, *dfacl = NULL; +@@ -415,7 +406,7 @@ + if (IS_ERR(alloc)) + goto fail; + } +- status = __nfs3_proc_setacls(inode, acl, dfacl); ++ status = nfs3_proc_setacls(inode, acl, dfacl); + posix_acl_release(alloc); + return status; + +diff -Nur linux-3.12.18/fs/nfs/nfs4xdr.c linux-rpi/fs/nfs/nfs4xdr.c +--- linux-3.12.18/fs/nfs/nfs4xdr.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/fs/nfs/nfs4xdr.c 2014-04-24 16:04:40.091126883 +0200 +@@ -3405,7 +3405,7 @@ + { + __be32 *p; + +- *res = 0; ++ *res = ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL; + if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U))) + return -EIO; + if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) { +diff -Nur linux-3.12.18/include/drm/drm_crtc.h linux-rpi/include/drm/drm_crtc.h +--- linux-3.12.18/include/drm/drm_crtc.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/include/drm/drm_crtc.h 2014-04-24 16:04:40.179127734 +0200 +@@ -1108,8 +1108,6 @@ + int GTF_2C, int GTF_K, int GTF_2J); + extern int drm_add_modes_noedid(struct drm_connector *connector, + int hdisplay, int vdisplay); +-extern void drm_set_preferred_mode(struct drm_connector *connector, +- int hpref, int vpref); + + extern int drm_edid_header_is_valid(const u8 *raw_edid); + extern bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid); +diff -Nur linux-3.12.18/include/linux/broadcom/vc_cma.h linux-rpi/include/linux/broadcom/vc_cma.h +--- linux-3.12.18/include/linux/broadcom/vc_cma.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/include/linux/broadcom/vc_cma.h 2014-04-24 16:04:40.687132644 +0200 @@ -0,0 +1,29 @@ +/***************************************************************************** +* Copyright 2012 Broadcom Corporation. All rights reserved. @@ -97005,9 +100158,38 @@ diff -Nur linux-3.12.13/include/linux/broadcom/vc_cma.h linux-raspberry-pi/inclu +#endif + +#endif /* VC_CMA_H */ -diff -Nur linux-3.12.13/include/linux/mmc/host.h linux-raspberry-pi/include/linux/mmc/host.h ---- linux-3.12.13/include/linux/mmc/host.h 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/include/linux/mmc/host.h 2014-03-11 17:51:40.000000000 +0100 +diff -Nur linux-3.12.18/include/linux/fb.h linux-rpi/include/linux/fb.h +--- linux-3.12.18/include/linux/fb.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/include/linux/fb.h 2014-04-24 16:04:40.731133070 +0200 +@@ -613,8 +613,8 @@ + extern int register_framebuffer(struct fb_info *fb_info); + extern int unregister_framebuffer(struct fb_info *fb_info); + extern int unlink_framebuffer(struct fb_info *fb_info); +-extern int remove_conflicting_framebuffers(struct apertures_struct *a, +- const char *name, bool primary); ++extern void remove_conflicting_framebuffers(struct apertures_struct *a, ++ const char *name, bool primary); + extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); + extern int fb_show_logo(struct fb_info *fb_info, int rotate); + extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); +diff -Nur linux-3.12.18/include/linux/futex.h linux-rpi/include/linux/futex.h +--- linux-3.12.18/include/linux/futex.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/include/linux/futex.h 2014-04-24 16:04:40.751133263 +0200 +@@ -55,11 +55,7 @@ + #ifdef CONFIG_FUTEX + extern void exit_robust_list(struct task_struct *curr); + extern void exit_pi_state_list(struct task_struct *curr); +-#ifdef CONFIG_HAVE_FUTEX_CMPXCHG +-#define futex_cmpxchg_enabled 1 +-#else + extern int futex_cmpxchg_enabled; +-#endif + #else + static inline void exit_robust_list(struct task_struct *curr) + { +diff -Nur linux-3.12.18/include/linux/mmc/host.h linux-rpi/include/linux/mmc/host.h +--- linux-3.12.18/include/linux/mmc/host.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/include/linux/mmc/host.h 2014-04-24 16:04:40.819133921 +0200 @@ -281,6 +281,7 @@ MMC_CAP2_PACKED_WR) #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */ @@ -97016,9 +100198,9 @@ diff -Nur linux-3.12.13/include/linux/mmc/host.h linux-raspberry-pi/include/linu mmc_pm_flag_t pm_caps; /* supported pm features */ -diff -Nur linux-3.12.13/include/linux/mmc/sdhci.h linux-raspberry-pi/include/linux/mmc/sdhci.h ---- linux-3.12.13/include/linux/mmc/sdhci.h 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/include/linux/mmc/sdhci.h 2014-03-11 17:51:40.000000000 +0100 +diff -Nur linux-3.12.18/include/linux/mmc/sdhci.h linux-rpi/include/linux/mmc/sdhci.h +--- linux-3.12.18/include/linux/mmc/sdhci.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/include/linux/mmc/sdhci.h 2014-04-24 16:04:40.819133921 +0200 @@ -100,6 +100,7 @@ #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5) @@ -97043,9 +100225,66 @@ diff -Nur linux-3.12.13/include/linux/mmc/sdhci.h linux-raspberry-pi/include/lin struct mmc_data *data; /* Current data request */ unsigned int data_early:1; /* Data finished before cmd */ -diff -Nur linux-3.12.13/include/sound/soc-dai.h linux-raspberry-pi/include/sound/soc-dai.h ---- linux-3.12.13/include/sound/soc-dai.h 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/include/sound/soc-dai.h 2014-03-11 17:33:22.000000000 +0100 +diff -Nur linux-3.12.18/include/linux/usb/usbnet.h linux-rpi/include/linux/usb/usbnet.h +--- linux-3.12.18/include/linux/usb/usbnet.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/include/linux/usb/usbnet.h 2014-04-24 16:04:40.871134423 +0200 +@@ -30,7 +30,7 @@ + struct driver_info *driver_info; + const char *driver_name; + void *driver_priv; +- wait_queue_head_t wait; ++ wait_queue_head_t *wait; + struct mutex phy_mutex; + unsigned char suspend_count; + unsigned char pkt_cnt, pkt_err; +diff -Nur linux-3.12.18/include/net/sock.h linux-rpi/include/net/sock.h +--- linux-3.12.18/include/net/sock.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/include/net/sock.h 2014-04-24 16:04:41.511140609 +0200 +@@ -1459,11 +1459,6 @@ + */ + #define sock_owned_by_user(sk) ((sk)->sk_lock.owned) + +-static inline void sock_release_ownership(struct sock *sk) +-{ +- sk->sk_lock.owned = 0; +-} +- + /* + * Macro so as to not evaluate some arguments when + * lockdep is not enabled. +diff -Nur linux-3.12.18/include/net/tcp.h linux-rpi/include/net/tcp.h +--- linux-3.12.18/include/net/tcp.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/include/net/tcp.h 2014-04-24 16:04:41.511140609 +0200 +@@ -484,21 +484,20 @@ + #ifdef CONFIG_SYN_COOKIES + #include <linux/ktime.h> + +-/* Syncookies use a monotonic timer which increments every 60 seconds. ++/* Syncookies use a monotonic timer which increments every 64 seconds. + * This counter is used both as a hash input and partially encoded into + * the cookie value. A cookie is only validated further if the delta + * between the current counter value and the encoded one is less than this, +- * i.e. a sent cookie is valid only at most for 2*60 seconds (or less if ++ * i.e. a sent cookie is valid only at most for 128 seconds (or less if + * the counter advances immediately after a cookie is generated). + */ + #define MAX_SYNCOOKIE_AGE 2 + + static inline u32 tcp_cookie_time(void) + { +- u64 val = get_jiffies_64(); +- +- do_div(val, 60 * HZ); +- return val; ++ struct timespec now; ++ getnstimeofday(&now); ++ return now.tv_sec >> 6; /* 64 seconds granularity */ + } + + extern u32 __cookie_v4_init_sequence(const struct iphdr *iph, +diff -Nur linux-3.12.18/include/sound/soc-dai.h linux-rpi/include/sound/soc-dai.h +--- linux-3.12.18/include/sound/soc-dai.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/include/sound/soc-dai.h 2014-04-24 15:35:04.921574108 +0200 @@ -105,6 +105,8 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, unsigned int freq_in, unsigned int freq_out); @@ -97063,9 +100302,9 @@ diff -Nur linux-3.12.13/include/sound/soc-dai.h linux-raspberry-pi/include/sound /* * DAI format configuration -diff -Nur linux-3.12.13/include/uapi/linux/fb.h linux-raspberry-pi/include/uapi/linux/fb.h ---- linux-3.12.13/include/uapi/linux/fb.h 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/include/uapi/linux/fb.h 2014-03-11 17:33:22.000000000 +0100 +diff -Nur linux-3.12.18/include/uapi/linux/fb.h linux-rpi/include/uapi/linux/fb.h +--- linux-3.12.18/include/uapi/linux/fb.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/include/uapi/linux/fb.h 2014-04-24 15:35:04.941574330 +0200 @@ -34,6 +34,11 @@ #define FBIOPUT_MODEINFO 0x4617 #define FBIOGET_DISPINFO 0x4618 @@ -97078,10 +100317,1198 @@ diff -Nur linux-3.12.13/include/uapi/linux/fb.h linux-raspberry-pi/include/uapi/ #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ #define FB_TYPE_PLANES 1 /* Non interleaved planes */ -diff -Nur linux-3.12.13/sound/arm/bcm2835.c linux-raspberry-pi/sound/arm/bcm2835.c ---- linux-3.12.13/sound/arm/bcm2835.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/sound/arm/bcm2835.c 2014-03-11 17:51:48.000000000 +0100 -@@ -0,0 +1,413 @@ +diff -Nur linux-3.12.18/include/uapi/linux/fd.h linux-rpi/include/uapi/linux/fd.h +--- linux-3.12.18/include/uapi/linux/fd.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/include/uapi/linux/fd.h 2014-04-24 15:35:04.945574375 +0200 +@@ -185,8 +185,7 @@ + * to clear media change status */ + FD_UNUSED_BIT, + FD_DISK_CHANGED_BIT, /* disk has been changed since last i/o */ +- FD_DISK_WRITABLE_BIT, /* disk is writable */ +- FD_OPEN_SHOULD_FAIL_BIT ++ FD_DISK_WRITABLE_BIT /* disk is writable */ + }; + + #define FDSETDRVPRM _IOW(2, 0x90, struct floppy_drive_params) +diff -Nur linux-3.12.18/init/Kconfig linux-rpi/init/Kconfig +--- linux-3.12.18/init/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/init/Kconfig 2014-04-24 16:04:41.543140918 +0200 +@@ -1406,13 +1406,6 @@ + support for "fast userspace mutexes". The resulting kernel may not + run glibc-based applications correctly. + +-config HAVE_FUTEX_CMPXCHG +- bool +- help +- Architectures should select this if futex_atomic_cmpxchg_inatomic() +- is implemented and always working. This removes a couple of runtime +- checks. +- + config EPOLL + bool "Enable eventpoll support" if EXPERT + default y +diff -Nur linux-3.12.18/kernel/cgroup.c linux-rpi/kernel/cgroup.c +--- linux-3.12.18/kernel/cgroup.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/kernel/cgroup.c 2014-04-24 16:04:41.547140957 +0200 +@@ -5558,6 +5558,33 @@ + } + __setup("cgroup_disable=", cgroup_disable); + ++static int __init cgroup_enable(char *str) ++{ ++ struct cgroup_subsys *ss; ++ char *token; ++ int i; ++ ++ while ((token = strsep(&str, ",")) != NULL) { ++ if (!*token) ++ continue; ++ ++ /* ++ * cgroup_disable, being at boot time, can't know about ++ * module subsystems, so we don't worry about them. ++ */ ++ for_each_builtin_subsys(ss, i) { ++ if (!strcmp(token, ss->name)) { ++ ss->disabled = 0; ++ printk(KERN_INFO "Disabling %s control group" ++ " subsystem\n", ss->name); ++ break; ++ } ++ } ++ } ++ return 1; ++} ++__setup("cgroup_enable=", cgroup_enable); ++ + /* + * Functons for CSS ID. + */ +diff -Nur linux-3.12.18/kernel/futex.c linux-rpi/kernel/futex.c +--- linux-3.12.18/kernel/futex.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/kernel/futex.c 2014-04-24 16:04:41.551140996 +0200 +@@ -68,9 +68,7 @@ + + #include "rtmutex_common.h" + +-#ifndef CONFIG_HAVE_FUTEX_CMPXCHG + int __read_mostly futex_cmpxchg_enabled; +-#endif + + #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8) + +@@ -2733,10 +2731,10 @@ + return do_futex(uaddr, op, val, tp, uaddr2, val2, val3); + } + +-static void __init futex_detect_cmpxchg(void) ++static int __init futex_init(void) + { +-#ifndef CONFIG_HAVE_FUTEX_CMPXCHG + u32 curval; ++ int i; + + /* + * This will fail and we want it. Some arch implementations do +@@ -2750,14 +2748,6 @@ + */ + if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT) + futex_cmpxchg_enabled = 1; +-#endif +-} +- +-static int __init futex_init(void) +-{ +- int i; +- +- futex_detect_cmpxchg(); + + for (i = 0; i < ARRAY_SIZE(futex_queues); i++) { + plist_head_init(&futex_queues[i].chain); +diff -Nur linux-3.12.18/lib/nlattr.c linux-rpi/lib/nlattr.c +--- linux-3.12.18/lib/nlattr.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/lib/nlattr.c 2014-04-24 16:04:41.611141576 +0200 +@@ -303,15 +303,9 @@ + */ + int nla_strcmp(const struct nlattr *nla, const char *str) + { +- int len = strlen(str); +- char *buf = nla_data(nla); +- int attrlen = nla_len(nla); +- int d; ++ int len = strlen(str) + 1; ++ int d = nla_len(nla) - len; + +- if (attrlen > 0 && buf[attrlen - 1] == '\0') +- attrlen--; +- +- d = attrlen - len; + if (d == 0) + d = memcmp(nla_data(nla), str, len); + +diff -Nur linux-3.12.18/mm/memcontrol.c linux-rpi/mm/memcontrol.c +--- linux-3.12.18/mm/memcontrol.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/mm/memcontrol.c 2014-04-24 16:04:41.619141653 +0200 +@@ -7030,6 +7030,7 @@ + .base_cftypes = mem_cgroup_files, + .early_init = 0, + .use_id = 1, ++ .disabled = 1, + }; + + #ifdef CONFIG_MEMCG_SWAP +diff -Nur linux-3.12.18/net/8021q/vlan.c linux-rpi/net/8021q/vlan.c +--- linux-3.12.18/net/8021q/vlan.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/8021q/vlan.c 2014-04-24 16:04:41.635141808 +0200 +@@ -307,11 +307,9 @@ + static void vlan_transfer_features(struct net_device *dev, + struct net_device *vlandev) + { +- struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev); +- + vlandev->gso_max_size = dev->gso_max_size; + +- if (vlan_hw_offload_capable(dev->features, vlan->vlan_proto)) ++ if (dev->features & NETIF_F_HW_VLAN_CTAG_TX) + vlandev->hard_header_len = dev->hard_header_len; + else + vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN; +diff -Nur linux-3.12.18/net/8021q/vlan_dev.c linux-rpi/net/8021q/vlan_dev.c +--- linux-3.12.18/net/8021q/vlan_dev.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/8021q/vlan_dev.c 2014-04-24 16:04:41.635141808 +0200 +@@ -557,9 +557,6 @@ + struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct net_device *real_dev = vlan->real_dev; + +- if (saddr == NULL) +- saddr = dev->dev_addr; +- + return dev_hard_header(skb, real_dev, type, daddr, saddr, len); + } + +@@ -611,8 +608,7 @@ + #endif + + dev->needed_headroom = real_dev->needed_headroom; +- if (vlan_hw_offload_capable(real_dev->features, +- vlan_dev_priv(dev)->vlan_proto)) { ++ if (real_dev->features & NETIF_F_HW_VLAN_CTAG_TX) { + dev->header_ops = &vlan_passthru_header_ops; + dev->hard_header_len = real_dev->hard_header_len; + } else { +diff -Nur linux-3.12.18/net/bridge/br_multicast.c linux-rpi/net/bridge/br_multicast.c +--- linux-3.12.18/net/bridge/br_multicast.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/bridge/br_multicast.c 2014-04-24 16:04:41.647141924 +0200 +@@ -1129,10 +1129,9 @@ + struct net_bridge_port *port, + struct bridge_mcast_querier *querier, + int saddr, +- bool is_general_query, + unsigned long max_delay) + { +- if (saddr && is_general_query) ++ if (saddr) + br_multicast_update_querier_timer(br, querier, max_delay); + else if (timer_pending(&querier->timer)) + return; +@@ -1184,16 +1183,8 @@ + IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1; + } + +- /* RFC2236+RFC3376 (IGMPv2+IGMPv3) require the multicast link layer +- * all-systems destination addresses (224.0.0.1) for general queries +- */ +- if (!group && iph->daddr != htonl(INADDR_ALLHOSTS_GROUP)) { +- err = -EINVAL; +- goto out; +- } +- + br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr, +- !group, max_delay); ++ max_delay); + + if (!group) + goto out; +@@ -1239,7 +1230,6 @@ + unsigned long max_delay; + unsigned long now = jiffies; + const struct in6_addr *group = NULL; +- bool is_general_query; + int err = 0; + u16 vid = 0; + +@@ -1248,12 +1238,6 @@ + (port && port->state == BR_STATE_DISABLED)) + goto out; + +- /* RFC2710+RFC3810 (MLDv1+MLDv2) require link-local source addresses */ +- if (!(ipv6_addr_type(&ip6h->saddr) & IPV6_ADDR_LINKLOCAL)) { +- err = -EINVAL; +- goto out; +- } +- + if (skb->len == sizeof(*mld)) { + if (!pskb_may_pull(skb, sizeof(*mld))) { + err = -EINVAL; +@@ -1275,19 +1259,8 @@ + max_delay = max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL); + } + +- is_general_query = group && ipv6_addr_any(group); +- +- /* RFC2710+RFC3810 (MLDv1+MLDv2) require the multicast link layer +- * all-nodes destination address (ff02::1) for general queries +- */ +- if (is_general_query && !ipv6_addr_is_ll_all_nodes(&ip6h->daddr)) { +- err = -EINVAL; +- goto out; +- } +- + br_multicast_query_received(br, port, &br->ip6_querier, +- !ipv6_addr_any(&ip6h->saddr), +- is_general_query, max_delay); ++ !ipv6_addr_any(&ip6h->saddr), max_delay); + + if (!group) + goto out; +diff -Nur linux-3.12.18/net/core/netpoll.c linux-rpi/net/core/netpoll.c +--- linux-3.12.18/net/core/netpoll.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/core/netpoll.c 2014-04-24 16:04:41.659142040 +0200 +@@ -740,7 +740,7 @@ + struct nd_msg *msg; + struct ipv6hdr *hdr; + +- if (skb->protocol != htons(ETH_P_IPV6)) ++ if (skb->protocol != htons(ETH_P_ARP)) + return false; + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + sizeof(struct nd_msg))) + return false; +diff -Nur linux-3.12.18/net/core/rtnetlink.c linux-rpi/net/core/rtnetlink.c +--- linux-3.12.18/net/core/rtnetlink.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/core/rtnetlink.c 2014-04-24 16:04:41.659142040 +0200 +@@ -2014,13 +2014,12 @@ + static int nlmsg_populate_fdb_fill(struct sk_buff *skb, + struct net_device *dev, + u8 *addr, u32 pid, u32 seq, +- int type, unsigned int flags, +- int nlflags) ++ int type, unsigned int flags) + { + struct nlmsghdr *nlh; + struct ndmsg *ndm; + +- nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), nlflags); ++ nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), NLM_F_MULTI); + if (!nlh) + return -EMSGSIZE; + +@@ -2058,7 +2057,7 @@ + if (!skb) + goto errout; + +- err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF, 0); ++ err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF); + if (err < 0) { + kfree_skb(skb); + goto errout; +@@ -2283,8 +2282,7 @@ + + err = nlmsg_populate_fdb_fill(skb, dev, ha->addr, + portid, seq, +- RTM_NEWNEIGH, NTF_SELF, +- NLM_F_MULTI); ++ RTM_NEWNEIGH, NTF_SELF); + if (err < 0) + return err; + skip: +diff -Nur linux-3.12.18/net/core/sock.c linux-rpi/net/core/sock.c +--- linux-3.12.18/net/core/sock.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/core/sock.c 2014-04-24 16:04:41.659142040 +0200 +@@ -2359,13 +2359,10 @@ + if (sk->sk_backlog.tail) + __release_sock(sk); + +- /* Warning : release_cb() might need to release sk ownership, +- * ie call sock_release_ownership(sk) before us. +- */ + if (sk->sk_prot->release_cb) + sk->sk_prot->release_cb(sk); + +- sock_release_ownership(sk); ++ sk->sk_lock.owned = 0; + if (waitqueue_active(&sk->sk_lock.wq)) + wake_up(&sk->sk_lock.wq); + spin_unlock_bh(&sk->sk_lock.slock); +diff -Nur linux-3.12.18/net/ipv4/gre_demux.c linux-rpi/net/ipv4/gre_demux.c +--- linux-3.12.18/net/ipv4/gre_demux.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/ipv4/gre_demux.c 2014-04-24 16:04:41.667142117 +0200 +@@ -211,14 +211,6 @@ + int i; + bool csum_err = false; + +-#ifdef CONFIG_NET_IPGRE_BROADCAST +- if (ipv4_is_multicast(ip_hdr(skb)->daddr)) { +- /* Looped back packet, drop it! */ +- if (rt_is_output_route(skb_rtable(skb))) +- goto drop; +- } +-#endif +- + if (parse_gre_header(skb, &tpi, &csum_err) < 0) + goto drop; + +diff -Nur linux-3.12.18/net/ipv4/inet_fragment.c linux-rpi/net/ipv4/inet_fragment.c +--- linux-3.12.18/net/ipv4/inet_fragment.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/ipv4/inet_fragment.c 2014-04-24 16:04:41.667142117 +0200 +@@ -211,7 +211,7 @@ + } + + work = frag_mem_limit(nf) - nf->low_thresh; +- while (work > 0 || force) { ++ while (work > 0) { + spin_lock(&nf->lru_lock); + + if (list_empty(&nf->lru_list)) { +@@ -281,10 +281,9 @@ + + atomic_inc(&qp->refcnt); + hlist_add_head(&qp->list, &hb->chain); +- inet_frag_lru_add(nf, qp); + spin_unlock(&hb->chain_lock); + read_unlock(&f->lock); +- ++ inet_frag_lru_add(nf, qp); + return qp; + } + +diff -Nur linux-3.12.18/net/ipv4/ipmr.c linux-rpi/net/ipv4/ipmr.c +--- linux-3.12.18/net/ipv4/ipmr.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/ipv4/ipmr.c 2014-04-24 16:04:41.671142156 +0200 +@@ -2253,14 +2253,13 @@ + } + + static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, +- u32 portid, u32 seq, struct mfc_cache *c, int cmd, +- int flags) ++ u32 portid, u32 seq, struct mfc_cache *c, int cmd) + { + struct nlmsghdr *nlh; + struct rtmsg *rtm; + int err; + +- nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags); ++ nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), NLM_F_MULTI); + if (nlh == NULL) + return -EMSGSIZE; + +@@ -2328,7 +2327,7 @@ + if (skb == NULL) + goto errout; + +- err = ipmr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0); ++ err = ipmr_fill_mroute(mrt, skb, 0, 0, mfc, cmd); + if (err < 0) + goto errout; + +@@ -2367,8 +2366,7 @@ + if (ipmr_fill_mroute(mrt, skb, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, +- mfc, RTM_NEWROUTE, +- NLM_F_MULTI) < 0) ++ mfc, RTM_NEWROUTE) < 0) + goto done; + next_entry: + e++; +@@ -2382,8 +2380,7 @@ + if (ipmr_fill_mroute(mrt, skb, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, +- mfc, RTM_NEWROUTE, +- NLM_F_MULTI) < 0) { ++ mfc, RTM_NEWROUTE) < 0) { + spin_unlock_bh(&mfc_unres_lock); + goto done; + } +diff -Nur linux-3.12.18/net/ipv4/ip_tunnel.c linux-rpi/net/ipv4/ip_tunnel.c +--- linux-3.12.18/net/ipv4/ip_tunnel.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/ipv4/ip_tunnel.c 2014-04-24 16:04:41.667142117 +0200 +@@ -411,6 +411,9 @@ + + #ifdef CONFIG_NET_IPGRE_BROADCAST + if (ipv4_is_multicast(iph->daddr)) { ++ /* Looped back packet, drop it! */ ++ if (rt_is_output_route(skb_rtable(skb))) ++ goto drop; + tunnel->dev->stats.multicast++; + skb->pkt_type = PACKET_BROADCAST; + } +diff -Nur linux-3.12.18/net/ipv4/ip_tunnel_core.c linux-rpi/net/ipv4/ip_tunnel_core.c +--- linux-3.12.18/net/ipv4/ip_tunnel_core.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/ipv4/ip_tunnel_core.c 2014-04-24 16:04:41.671142156 +0200 +@@ -109,7 +109,6 @@ + secpath_reset(skb); + if (!skb->l4_rxhash) + skb->rxhash = 0; +- skb_dst_drop(skb); + skb->vlan_tci = 0; + skb_set_queue_mapping(skb, 0); + skb->pkt_type = PACKET_HOST; +diff -Nur linux-3.12.18/net/ipv4/tcp_output.c linux-rpi/net/ipv4/tcp_output.c +--- linux-3.12.18/net/ipv4/tcp_output.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/ipv4/tcp_output.c 2014-04-24 16:04:41.683142272 +0200 +@@ -765,17 +765,6 @@ + if (flags & (1UL << TCP_TSQ_DEFERRED)) + tcp_tsq_handler(sk); + +- /* Here begins the tricky part : +- * We are called from release_sock() with : +- * 1) BH disabled +- * 2) sk_lock.slock spinlock held +- * 3) socket owned by us (sk->sk_lock.owned == 1) +- * +- * But following code is meant to be called from BH handlers, +- * so we should keep BH disabled, but early release socket ownership +- */ +- sock_release_ownership(sk); +- + if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) { + tcp_write_timer_handler(sk); + __sock_put(sk); +diff -Nur linux-3.12.18/net/ipv6/addrconf.c linux-rpi/net/ipv6/addrconf.c +--- linux-3.12.18/net/ipv6/addrconf.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/ipv6/addrconf.c 2014-04-24 16:04:41.687142311 +0200 +@@ -1079,11 +1079,8 @@ + * Lifetime is greater than REGEN_ADVANCE time units. In particular, + * an implementation must not create a temporary address with a zero + * Preferred Lifetime. +- * Use age calculation as in addrconf_verify to avoid unnecessary +- * temporary addresses being generated. + */ +- age = (now - tmp_tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ; +- if (tmp_prefered_lft <= regen_advance + age) { ++ if (tmp_prefered_lft <= regen_advance) { + in6_ifa_put(ifp); + in6_dev_put(idev); + ret = -1; +diff -Nur linux-3.12.18/net/ipv6/exthdrs_offload.c linux-rpi/net/ipv6/exthdrs_offload.c +--- linux-3.12.18/net/ipv6/exthdrs_offload.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/ipv6/exthdrs_offload.c 2014-04-24 16:04:41.687142311 +0200 +@@ -25,11 +25,11 @@ + int ret; + + ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING); +- if (ret) ++ if (!ret) + goto out; + + ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS); +- if (ret) ++ if (!ret) + goto out_rt; + + out: +diff -Nur linux-3.12.18/net/ipv6/icmp.c linux-rpi/net/ipv6/icmp.c +--- linux-3.12.18/net/ipv6/icmp.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/ipv6/icmp.c 2014-04-24 16:04:41.687142311 +0200 +@@ -516,7 +516,7 @@ + np->tclass, NULL, &fl6, (struct rt6_info *)dst, + MSG_DONTWAIT, np->dontfrag); + if (err) { +- ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS); ++ ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); + ip6_flush_pending_frames(sk); + } else { + err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, +diff -Nur linux-3.12.18/net/ipv6/ip6mr.c linux-rpi/net/ipv6/ip6mr.c +--- linux-3.12.18/net/ipv6/ip6mr.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/ipv6/ip6mr.c 2014-04-24 16:04:41.691142349 +0200 +@@ -2349,14 +2349,13 @@ + } + + static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, +- u32 portid, u32 seq, struct mfc6_cache *c, int cmd, +- int flags) ++ u32 portid, u32 seq, struct mfc6_cache *c, int cmd) + { + struct nlmsghdr *nlh; + struct rtmsg *rtm; + int err; + +- nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags); ++ nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), NLM_F_MULTI); + if (nlh == NULL) + return -EMSGSIZE; + +@@ -2424,7 +2423,7 @@ + if (skb == NULL) + goto errout; + +- err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0); ++ err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd); + if (err < 0) + goto errout; + +@@ -2463,8 +2462,7 @@ + if (ip6mr_fill_mroute(mrt, skb, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, +- mfc, RTM_NEWROUTE, +- NLM_F_MULTI) < 0) ++ mfc, RTM_NEWROUTE) < 0) + goto done; + next_entry: + e++; +@@ -2478,8 +2476,7 @@ + if (ip6mr_fill_mroute(mrt, skb, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, +- mfc, RTM_NEWROUTE, +- NLM_F_MULTI) < 0) { ++ mfc, RTM_NEWROUTE) < 0) { + spin_unlock_bh(&mfc_unres_lock); + goto done; + } +diff -Nur linux-3.12.18/net/ipv6/ip6_output.c linux-rpi/net/ipv6/ip6_output.c +--- linux-3.12.18/net/ipv6/ip6_output.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/ipv6/ip6_output.c 2014-04-24 16:04:41.691142349 +0200 +@@ -1088,19 +1088,21 @@ + unsigned int fragheaderlen, + struct sk_buff *skb, + struct rt6_info *rt, +- unsigned int orig_mtu) ++ bool pmtuprobe) + { + if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { + if (skb == NULL) { + /* first fragment, reserve header_len */ +- *mtu = orig_mtu - rt->dst.header_len; ++ *mtu = *mtu - rt->dst.header_len; + + } else { + /* + * this fragment is not first, the headers + * space is regarded as data space. + */ +- *mtu = orig_mtu; ++ *mtu = min(*mtu, pmtuprobe ? ++ rt->dst.dev->mtu : ++ dst_mtu(rt->dst.path)); + } + *maxfraglen = ((*mtu - fragheaderlen) & ~7) + + fragheaderlen - sizeof(struct frag_hdr); +@@ -1117,7 +1119,7 @@ + struct ipv6_pinfo *np = inet6_sk(sk); + struct inet_cork *cork; + struct sk_buff *skb, *skb_prev = NULL; +- unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu; ++ unsigned int maxfraglen, fragheaderlen, mtu; + int exthdrlen; + int dst_exthdrlen; + int hh_len; +@@ -1199,7 +1201,6 @@ + dst_exthdrlen = 0; + mtu = cork->fragsize; + } +- orig_mtu = mtu; + + hh_len = LL_RESERVED_SPACE(rt->dst.dev); + +@@ -1279,7 +1280,8 @@ + if (skb == NULL || skb_prev == NULL) + ip6_append_data_mtu(&mtu, &maxfraglen, + fragheaderlen, skb, rt, +- orig_mtu); ++ np->pmtudisc == ++ IPV6_PMTUDISC_PROBE); + + skb_prev = skb; + +@@ -1535,8 +1537,8 @@ + if (proto == IPPROTO_ICMPV6) { + struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); + +- ICMP6MSGOUT_INC_STATS(net, idev, icmp6_hdr(skb)->icmp6_type); +- ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); ++ ICMP6MSGOUT_INC_STATS_BH(net, idev, icmp6_hdr(skb)->icmp6_type); ++ ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); + } + + err = ip6_local_out(skb); +diff -Nur linux-3.12.18/net/ipv6/mcast.c linux-rpi/net/ipv6/mcast.c +--- linux-3.12.18/net/ipv6/mcast.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/ipv6/mcast.c 2014-04-24 16:04:41.691142349 +0200 +@@ -1620,12 +1620,11 @@ + dst_output); + out: + if (!err) { +- ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT); +- ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); +- IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, payload_len); +- } else { +- IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); +- } ++ ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT); ++ ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); ++ IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_OUTMCAST, payload_len); ++ } else ++ IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS); + + rcu_read_unlock(); + return; +diff -Nur linux-3.12.18/net/ipv6/ping.c linux-rpi/net/ipv6/ping.c +--- linux-3.12.18/net/ipv6/ping.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/ipv6/ping.c 2014-04-24 16:04:41.695142388 +0200 +@@ -182,8 +182,8 @@ + MSG_DONTWAIT, np->dontfrag); + + if (err) { +- ICMP6_INC_STATS(sock_net(sk), rt->rt6i_idev, +- ICMP6_MIB_OUTERRORS); ++ ICMP6_INC_STATS_BH(sock_net(sk), rt->rt6i_idev, ++ ICMP6_MIB_OUTERRORS); + ip6_flush_pending_frames(sk); + } else { + err = icmpv6_push_pending_frames(sk, &fl6, +diff -Nur linux-3.12.18/net/ipv6/route.c linux-rpi/net/ipv6/route.c +--- linux-3.12.18/net/ipv6/route.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/ipv6/route.c 2014-04-24 16:04:41.699142427 +0200 +@@ -1500,7 +1500,7 @@ + if (!table) + goto out; + +- rt = ip6_dst_alloc(net, NULL, (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT, table); ++ rt = ip6_dst_alloc(net, NULL, DST_NOCOUNT, table); + + if (!rt) { + err = -ENOMEM; +diff -Nur linux-3.12.18/net/rds/iw.c linux-rpi/net/rds/iw.c +--- linux-3.12.18/net/rds/iw.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/rds/iw.c 2014-04-24 16:04:42.255147800 +0200 +@@ -239,8 +239,7 @@ + ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin); + /* due to this, we will claim to support IB devices unless we + check node_type. */ +- if (ret || !cm_id->device || +- cm_id->device->node_type != RDMA_NODE_RNIC) ++ if (ret || cm_id->device->node_type != RDMA_NODE_RNIC) + ret = -EADDRNOTAVAIL; + + rdsdebug("addr %pI4 ret %d node type %d\n", +diff -Nur linux-3.12.18/net/sched/sch_fq.c linux-rpi/net/sched/sch_fq.c +--- linux-3.12.18/net/sched/sch_fq.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/sched/sch_fq.c 2014-04-24 16:04:42.255147800 +0200 +@@ -577,11 +577,9 @@ + q->stat_gc_flows += fcnt; + } + +-static int fq_resize(struct Qdisc *sch, u32 log) ++static int fq_resize(struct fq_sched_data *q, u32 log) + { +- struct fq_sched_data *q = qdisc_priv(sch); + struct rb_root *array; +- void *old_fq_root; + u32 idx; + + if (q->fq_root && log == q->fq_trees_log) +@@ -594,19 +592,13 @@ + for (idx = 0; idx < (1U << log); idx++) + array[idx] = RB_ROOT; + +- sch_tree_lock(sch); +- +- old_fq_root = q->fq_root; +- if (old_fq_root) +- fq_rehash(q, old_fq_root, q->fq_trees_log, array, log); +- ++ if (q->fq_root) { ++ fq_rehash(q, q->fq_root, q->fq_trees_log, array, log); ++ kfree(q->fq_root); ++ } + q->fq_root = array; + q->fq_trees_log = log; + +- sch_tree_unlock(sch); +- +- kfree(old_fq_root); +- + return 0; + } + +@@ -682,11 +674,9 @@ + q->flow_refill_delay = usecs_to_jiffies(usecs_delay); + } + +- if (!err) { +- sch_tree_unlock(sch); +- err = fq_resize(sch, fq_log); +- sch_tree_lock(sch); +- } ++ if (!err) ++ err = fq_resize(q, fq_log); ++ + while (sch->q.qlen > sch->limit) { + struct sk_buff *skb = fq_dequeue(sch); + +@@ -732,7 +722,7 @@ + if (opt) + err = fq_change(sch, opt); + else +- err = fq_resize(sch, q->fq_trees_log); ++ err = fq_resize(q, q->fq_trees_log); + + return err; + } +diff -Nur linux-3.12.18/net/sctp/sm_make_chunk.c linux-rpi/net/sctp/sm_make_chunk.c +--- linux-3.12.18/net/sctp/sm_make_chunk.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/sctp/sm_make_chunk.c 2014-04-24 16:04:42.263147878 +0200 +@@ -1433,8 +1433,8 @@ + BUG_ON(!list_empty(&chunk->list)); + list_del_init(&chunk->transmitted_list); + +- consume_skb(chunk->skb); +- consume_skb(chunk->auth_chunk); ++ /* Free the chunk skb data and the SCTP_chunk stub itself. */ ++ dev_kfree_skb(chunk->skb); + + SCTP_DBG_OBJCNT_DEC(chunk); + kmem_cache_free(sctp_chunk_cachep, chunk); +diff -Nur linux-3.12.18/net/sctp/sm_statefuns.c linux-rpi/net/sctp/sm_statefuns.c +--- linux-3.12.18/net/sctp/sm_statefuns.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/sctp/sm_statefuns.c 2014-04-24 16:04:42.263147878 +0200 +@@ -761,6 +761,7 @@ + + /* Make sure that we and the peer are AUTH capable */ + if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) { ++ kfree_skb(chunk->auth_chunk); + sctp_association_free(new_asoc); + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + } +@@ -775,6 +776,10 @@ + auth.transport = chunk->transport; + + ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth); ++ ++ /* We can now safely free the auth_chunk clone */ ++ kfree_skb(chunk->auth_chunk); ++ + if (ret != SCTP_IERROR_NO_ERROR) { + sctp_association_free(new_asoc); + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); +diff -Nur linux-3.12.18/net/socket.c linux-rpi/net/socket.c +--- linux-3.12.18/net/socket.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/socket.c 2014-04-24 16:04:42.275147994 +0200 +@@ -1972,10 +1972,6 @@ + { + if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) + return -EFAULT; +- +- if (kmsg->msg_namelen < 0) +- return -EINVAL; +- + if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) + kmsg->msg_namelen = sizeof(struct sockaddr_storage); + return 0; +diff -Nur linux-3.12.18/net/sunrpc/backchannel_rqst.c linux-rpi/net/sunrpc/backchannel_rqst.c +--- linux-3.12.18/net/sunrpc/backchannel_rqst.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/sunrpc/backchannel_rqst.c 2014-04-24 15:35:05.273578028 +0200 +@@ -64,6 +64,7 @@ + free_page((unsigned long)xbufp->head[0].iov_base); + xbufp = &req->rq_snd_buf; + free_page((unsigned long)xbufp->head[0].iov_base); ++ list_del(&req->rq_bc_pa_list); + kfree(req); + } + +@@ -167,10 +168,8 @@ + /* + * Memory allocation failed, free the temporary list + */ +- list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) { +- list_del(&req->rq_bc_pa_list); ++ list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) + xprt_free_allocation(req); +- } + + dprintk("RPC: setup backchannel transport failed\n"); + return -ENOMEM; +@@ -199,7 +198,6 @@ + xprt_dec_alloc_count(xprt, max_reqs); + list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) { + dprintk("RPC: req=%p\n", req); +- list_del(&req->rq_bc_pa_list); + xprt_free_allocation(req); + if (--max_reqs == 0) + break; +diff -Nur linux-3.12.18/net/tipc/config.c linux-rpi/net/tipc/config.c +--- linux-3.12.18/net/tipc/config.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/tipc/config.c 2014-04-24 16:04:42.275147994 +0200 +@@ -376,6 +376,7 @@ + struct tipc_cfg_msg_hdr *req_hdr; + struct tipc_cfg_msg_hdr *rep_hdr; + struct sk_buff *rep_buf; ++ int ret; + + /* Validate configuration message header (ignore invalid message) */ + req_hdr = (struct tipc_cfg_msg_hdr *)buf; +@@ -397,8 +398,12 @@ + memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); + rep_hdr->tcm_len = htonl(rep_buf->len); + rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); +- tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data, +- rep_buf->len); ++ ++ ret = tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data, ++ rep_buf->len); ++ if (ret < 0) ++ pr_err("Sending cfg reply message failed, no memory\n"); ++ + kfree_skb(rep_buf); + } + } +diff -Nur linux-3.12.18/net/tipc/handler.c linux-rpi/net/tipc/handler.c +--- linux-3.12.18/net/tipc/handler.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/tipc/handler.c 2014-04-24 15:35:05.285578162 +0200 +@@ -57,6 +57,7 @@ + struct queue_item *item; + + if (!handler_enabled) { ++ pr_err("Signal request ignored by handler\n"); + return -ENOPROTOOPT; + } + +diff -Nur linux-3.12.18/net/tipc/name_table.c linux-rpi/net/tipc/name_table.c +--- linux-3.12.18/net/tipc/name_table.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/tipc/name_table.c 2014-04-24 16:04:42.275147994 +0200 +@@ -942,51 +942,20 @@ + return 0; + } + +-/** +- * tipc_purge_publications - remove all publications for a given type +- * +- * tipc_nametbl_lock must be held when calling this function +- */ +-static void tipc_purge_publications(struct name_seq *seq) +-{ +- struct publication *publ, *safe; +- struct sub_seq *sseq; +- struct name_info *info; +- +- if (!seq->sseqs) { +- nameseq_delete_empty(seq); +- return; +- } +- sseq = seq->sseqs; +- info = sseq->info; +- list_for_each_entry_safe(publ, safe, &info->zone_list, zone_list) { +- tipc_nametbl_remove_publ(publ->type, publ->lower, publ->node, +- publ->ref, publ->key); +- } +-} +- + void tipc_nametbl_stop(void) + { + u32 i; +- struct name_seq *seq; +- struct hlist_head *seq_head; +- struct hlist_node *safe; + + if (!table.types) + return; + +- /* Verify name table is empty and purge any lingering +- * publications, then release the name table +- */ ++ /* Verify name table is empty, then release it */ + write_lock_bh(&tipc_nametbl_lock); + for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { + if (hlist_empty(&table.types[i])) + continue; +- seq_head = &table.types[i]; +- hlist_for_each_entry_safe(seq, safe, seq_head, ns_list) { +- tipc_purge_publications(seq); +- } +- continue; ++ pr_err("nametbl_stop(): orphaned hash chain detected\n"); ++ break; + } + kfree(table.types); + table.types = NULL; +diff -Nur linux-3.12.18/net/tipc/server.c linux-rpi/net/tipc/server.c +--- linux-3.12.18/net/tipc/server.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/tipc/server.c 2014-04-24 16:04:42.279148031 +0200 +@@ -87,6 +87,7 @@ + static void tipc_conn_kref_release(struct kref *kref) + { + struct tipc_conn *con = container_of(kref, struct tipc_conn, kref); ++ struct tipc_server *s = con->server; + + if (con->sock) { + tipc_sock_release_local(con->sock); +@@ -94,6 +95,10 @@ + } + + tipc_clean_outqueues(con); ++ ++ if (con->conid) ++ s->tipc_conn_shutdown(con->conid, con->usr_data); ++ + kfree(con); + } + +@@ -176,9 +181,6 @@ + struct tipc_server *s = con->server; + + if (test_and_clear_bit(CF_CONNECTED, &con->flags)) { +- if (con->conid) +- s->tipc_conn_shutdown(con->conid, con->usr_data); +- + spin_lock_bh(&s->idr_lock); + idr_remove(&s->conn_idr, con->conid); + s->idr_in_use--; +@@ -427,12 +429,10 @@ + list_add_tail(&e->list, &con->outqueue); + spin_unlock_bh(&con->outqueue_lock); + +- if (test_bit(CF_CONNECTED, &con->flags)) { ++ if (test_bit(CF_CONNECTED, &con->flags)) + if (!queue_work(s->send_wq, &con->swork)) + conn_put(con); +- } else { +- conn_put(con); +- } ++ + return 0; + } + +diff -Nur linux-3.12.18/net/tipc/subscr.c linux-rpi/net/tipc/subscr.c +--- linux-3.12.18/net/tipc/subscr.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/tipc/subscr.c 2014-04-24 16:04:42.279148031 +0200 +@@ -96,16 +96,20 @@ + { + struct tipc_subscriber *subscriber = sub->subscriber; + struct kvec msg_sect; ++ int ret; + + msg_sect.iov_base = (void *)&sub->evt; + msg_sect.iov_len = sizeof(struct tipc_event); ++ + sub->evt.event = htohl(event, sub->swap); + sub->evt.found_lower = htohl(found_lower, sub->swap); + sub->evt.found_upper = htohl(found_upper, sub->swap); + sub->evt.port.ref = htohl(port_ref, sub->swap); + sub->evt.port.node = htohl(node, sub->swap); +- tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, msg_sect.iov_base, +- msg_sect.iov_len); ++ ret = tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, ++ msg_sect.iov_base, msg_sect.iov_len); ++ if (ret < 0) ++ pr_err("Sending subscription event failed, no memory\n"); + } + + /** +@@ -149,6 +153,14 @@ + /* The spin lock per subscriber is used to protect its members */ + spin_lock_bh(&subscriber->lock); + ++ /* Validate if the connection related to the subscriber is ++ * closed (in case subscriber is terminating) ++ */ ++ if (subscriber->conid == 0) { ++ spin_unlock_bh(&subscriber->lock); ++ return; ++ } ++ + /* Validate timeout (in case subscription is being cancelled) */ + if (sub->timeout == TIPC_WAIT_FOREVER) { + spin_unlock_bh(&subscriber->lock); +@@ -203,6 +215,9 @@ + + spin_lock_bh(&subscriber->lock); + ++ /* Invalidate subscriber reference */ ++ subscriber->conid = 0; ++ + /* Destroy any existing subscriptions for subscriber */ + list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, + subscription_list) { +@@ -263,9 +278,9 @@ + * + * Called with subscriber lock held. + */ +-static int subscr_subscribe(struct tipc_subscr *s, +- struct tipc_subscriber *subscriber, +- struct tipc_subscription **sub_p) { ++static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, ++ struct tipc_subscriber *subscriber) ++{ + struct tipc_subscription *sub; + int swap; + +@@ -276,21 +291,23 @@ + if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { + s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); + subscr_cancel(s, subscriber); +- return 0; ++ return NULL; + } + + /* Refuse subscription if global limit exceeded */ + if (atomic_read(&subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { + pr_warn("Subscription rejected, limit reached (%u)\n", + TIPC_MAX_SUBSCRIPTIONS); +- return -EINVAL; ++ subscr_terminate(subscriber); ++ return NULL; + } + + /* Allocate subscription object */ + sub = kmalloc(sizeof(*sub), GFP_ATOMIC); + if (!sub) { + pr_warn("Subscription rejected, no memory\n"); +- return -ENOMEM; ++ subscr_terminate(subscriber); ++ return NULL; + } + + /* Initialize subscription object */ +@@ -304,7 +321,8 @@ + (sub->seq.lower > sub->seq.upper)) { + pr_warn("Subscription rejected, illegal request\n"); + kfree(sub); +- return -EINVAL; ++ subscr_terminate(subscriber); ++ return NULL; + } + INIT_LIST_HEAD(&sub->nameseq_list); + list_add(&sub->subscription_list, &subscriber->subscription_list); +@@ -317,8 +335,8 @@ + (Handler)subscr_timeout, (unsigned long)sub); + k_start_timer(&sub->timer, sub->timeout); + } +- *sub_p = sub; +- return 0; ++ ++ return sub; + } + + /* Handle one termination request for the subscriber */ +@@ -332,14 +350,10 @@ + void *usr_data, void *buf, size_t len) + { + struct tipc_subscriber *subscriber = usr_data; +- struct tipc_subscription *sub = NULL; ++ struct tipc_subscription *sub; + + spin_lock_bh(&subscriber->lock); +- if (subscr_subscribe((struct tipc_subscr *)buf, subscriber, &sub) < 0) { +- spin_unlock_bh(&subscriber->lock); +- subscr_terminate(subscriber); +- return; +- } ++ sub = subscr_subscribe((struct tipc_subscr *)buf, subscriber); + if (sub) + tipc_nametbl_subscribe(sub); + spin_unlock_bh(&subscriber->lock); +diff -Nur linux-3.12.18/net/unix/af_unix.c linux-rpi/net/unix/af_unix.c +--- linux-3.12.18/net/unix/af_unix.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/net/unix/af_unix.c 2014-04-24 16:04:42.279148031 +0200 +@@ -1785,11 +1785,8 @@ + goto out; + + err = mutex_lock_interruptible(&u->readlock); +- if (unlikely(err)) { +- /* recvmsg() in non blocking mode is supposed to return -EAGAIN +- * sk_rcvtimeo is not honored by mutex_lock_interruptible() +- */ +- err = noblock ? -EAGAIN : -ERESTARTSYS; ++ if (err) { ++ err = sock_intr_errno(sock_rcvtimeo(sk, noblock)); + goto out; + } + +@@ -1914,7 +1911,6 @@ + struct unix_sock *u = unix_sk(sk); + struct sockaddr_un *sunaddr = msg->msg_name; + int copied = 0; +- int noblock = flags & MSG_DONTWAIT; + int check_creds = 0; + int target; + int err = 0; +@@ -1930,7 +1926,7 @@ + goto out; + + target = sock_rcvlowat(sk, flags&MSG_WAITALL, size); +- timeo = sock_rcvtimeo(sk, noblock); ++ timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT); + + /* Lock the socket to prevent queue disordering + * while sleeps in memcpy_tomsg +@@ -1942,11 +1938,8 @@ + } + + err = mutex_lock_interruptible(&u->readlock); +- if (unlikely(err)) { +- /* recvmsg() in non blocking mode is supposed to return -EAGAIN +- * sk_rcvtimeo is not honored by mutex_lock_interruptible() +- */ +- err = noblock ? -EAGAIN : -ERESTARTSYS; ++ if (err) { ++ err = sock_intr_errno(timeo); + goto out; + } + +diff -Nur linux-3.12.18/security/selinux/hooks.c linux-rpi/security/selinux/hooks.c +--- linux-3.12.18/security/selinux/hooks.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/security/selinux/hooks.c 2014-04-24 16:04:42.731152400 +0200 +@@ -1386,33 +1386,15 @@ + isec->sid = sbsec->sid; + + if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) { +- /* We must have a dentry to determine the label on +- * procfs inodes */ +- if (opt_dentry) +- /* Called from d_instantiate or +- * d_splice_alias. */ +- dentry = dget(opt_dentry); +- else +- /* Called from selinux_complete_init, try to +- * find a dentry. */ +- dentry = d_find_alias(inode); +- /* +- * This can be hit on boot when a file is accessed +- * before the policy is loaded. When we load policy we +- * may find inodes that have no dentry on the +- * sbsec->isec_head list. No reason to complain as +- * these will get fixed up the next time we go through +- * inode_doinit() with a dentry, before these inodes +- * could be used again by userspace. +- */ +- if (!dentry) +- goto out_unlock; +- isec->sclass = inode_mode_to_security_class(inode->i_mode); +- rc = selinux_proc_get_sid(dentry, isec->sclass, &sid); +- dput(dentry); +- if (rc) +- goto out_unlock; +- isec->sid = sid; ++ if (opt_dentry) { ++ isec->sclass = inode_mode_to_security_class(inode->i_mode); ++ rc = selinux_proc_get_sid(opt_dentry, ++ isec->sclass, ++ &sid); ++ if (rc) ++ goto out_unlock; ++ isec->sid = sid; ++ } + } + break; + } +diff -Nur linux-3.12.18/sound/arm/bcm2835.c linux-rpi/sound/arm/bcm2835.c +--- linux-3.12.18/sound/arm/bcm2835.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/arm/bcm2835.c 2014-04-24 16:04:42.735152438 +0200 +@@ -0,0 +1,420 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* @@ -97188,7 +101615,7 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.c linux-raspberry-pi/sound/arm/bcm2835 + goto out; + + snd_card_set_dev(g_card, &pdev->dev); -+ strcpy(g_card->driver, "BRCM bcm2835 ALSA Driver"); ++ strcpy(g_card->driver, "bcm2835"); + strcpy(g_card->shortname, "bcm2835 ALSA"); + sprintf(g_card->longname, "%s", g_card->shortname); + @@ -97205,6 +101632,12 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.c linux-raspberry-pi/sound/arm/bcm2835 + goto out_bcm2835_new_pcm; + } + ++ err = snd_bcm2835_new_spdif_pcm(chip); ++ if (err < 0) { ++ dev_err(&pdev->dev, "Failed to create new BCM2835 spdif pcm device\n"); ++ goto out_bcm2835_new_spdif; ++ } ++ + err = snd_bcm2835_new_ctl(chip); + if (err < 0) { + dev_err(&pdev->dev, "Failed to create new BCM2835 ctl\n"); @@ -97240,6 +101673,7 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.c linux-raspberry-pi/sound/arm/bcm2835 + +out_card_register: +out_bcm2835_new_ctl: ++out_bcm2835_new_spdif: +out_bcm2835_new_pcm: +out_bcm2835_create: + BUG_ON(!g_card); @@ -97495,10 +101929,10 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.c linux-raspberry-pi/sound/arm/bcm2835 +MODULE_DESCRIPTION("Alsa driver for BCM2835 chip"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:bcm2835_alsa"); -diff -Nur linux-3.12.13/sound/arm/bcm2835-ctl.c linux-raspberry-pi/sound/arm/bcm2835-ctl.c ---- linux-3.12.13/sound/arm/bcm2835-ctl.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/sound/arm/bcm2835-ctl.c 2014-03-11 17:51:48.000000000 +0100 -@@ -0,0 +1,200 @@ +diff -Nur linux-3.12.18/sound/arm/bcm2835-ctl.c linux-rpi/sound/arm/bcm2835-ctl.c +--- linux-3.12.18/sound/arm/bcm2835-ctl.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/arm/bcm2835-ctl.c 2014-04-24 16:04:42.735152438 +0200 +@@ -0,0 +1,323 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* @@ -97531,6 +101965,7 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-ctl.c linux-raspberry-pi/sound/arm/bcm +#include <sound/rawmidi.h> +#include <sound/initval.h> +#include <sound/tlv.h> ++#include <sound/asoundef.h> + +#include "bcm2835.h" + @@ -97684,6 +102119,122 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-ctl.c linux-raspberry-pi/sound/arm/bcm + }, +}; + ++static int snd_bcm2835_spdif_default_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; ++ uinfo->count = 1; ++ return 0; ++} ++ ++static int snd_bcm2835_spdif_default_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); ++ int i; ++ ++ for (i = 0; i < 4; i++) ++ ucontrol->value.iec958.status[i] = ++ (chip->spdif_status >> (i * 8)) && 0xff; ++ ++ return 0; ++} ++ ++static int snd_bcm2835_spdif_default_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); ++ unsigned int val = 0; ++ int i, change; ++ ++ for (i = 0; i < 4; i++) ++ val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8); ++ ++ change = val != chip->spdif_status; ++ chip->spdif_status = val; ++ ++ return change; ++} ++ ++static int snd_bcm2835_spdif_mask_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; ++ uinfo->count = 1; ++ return 0; ++} ++ ++static int snd_bcm2835_spdif_mask_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ /* bcm2835 supports only consumer mode and sets all other format flags ++ * automatically. So the only thing left is signalling non-audio ++ * content */ ++ ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO; ++ return 0; ++} ++ ++static int snd_bcm2835_spdif_stream_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; ++ uinfo->count = 1; ++ return 0; ++} ++ ++static int snd_bcm2835_spdif_stream_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); ++ int i; ++ ++ for (i = 0; i < 4; i++) ++ ucontrol->value.iec958.status[i] = ++ (chip->spdif_status >> (i * 8)) & 0xff; ++ return 0; ++} ++ ++static int snd_bcm2835_spdif_stream_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); ++ unsigned int val = 0; ++ int i, change; ++ ++ for (i = 0; i < 4; i++) ++ val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8); ++ change = val != chip->spdif_status; ++ chip->spdif_status = val; ++ ++ return change; ++} ++ ++static struct snd_kcontrol_new snd_bcm2835_spdif[] = { ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_PCM, ++ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), ++ .info = snd_bcm2835_spdif_default_info, ++ .get = snd_bcm2835_spdif_default_get, ++ .put = snd_bcm2835_spdif_default_put ++ }, ++ { ++ .access = SNDRV_CTL_ELEM_ACCESS_READ, ++ .iface = SNDRV_CTL_ELEM_IFACE_PCM, ++ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), ++ .info = snd_bcm2835_spdif_mask_info, ++ .get = snd_bcm2835_spdif_mask_get, ++ }, ++ { ++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | ++ SNDRV_CTL_ELEM_ACCESS_INACTIVE, ++ .iface = SNDRV_CTL_ELEM_IFACE_PCM, ++ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM), ++ .info = snd_bcm2835_spdif_stream_info, ++ .get = snd_bcm2835_spdif_stream_get, ++ .put = snd_bcm2835_spdif_stream_put, ++ }, ++}; ++ +int snd_bcm2835_new_ctl(bcm2835_chip_t * chip) +{ + int err; @@ -97697,12 +102248,18 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-ctl.c linux-raspberry-pi/sound/arm/bcm + if (err < 0) + return err; + } ++ for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_spdif); idx++) { ++ err = snd_ctl_add(chip->card, ++ snd_ctl_new1(&snd_bcm2835_spdif[idx], chip)); ++ if (err < 0) ++ return err; ++ } + return 0; +} -diff -Nur linux-3.12.13/sound/arm/bcm2835.h linux-raspberry-pi/sound/arm/bcm2835.h ---- linux-3.12.13/sound/arm/bcm2835.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/sound/arm/bcm2835.h 2014-03-11 17:51:48.000000000 +0100 -@@ -0,0 +1,157 @@ +diff -Nur linux-3.12.18/sound/arm/bcm2835.h linux-rpi/sound/arm/bcm2835.h +--- linux-3.12.18/sound/arm/bcm2835.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/arm/bcm2835.h 2014-04-24 16:04:42.735152438 +0200 +@@ -0,0 +1,166 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* @@ -97802,6 +102359,7 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.h linux-raspberry-pi/sound/arm/bcm2835 +typedef struct bcm2835_chip { + struct snd_card *card; + struct snd_pcm *pcm; ++ struct snd_pcm *pcm_spdif; + /* Bitmat for valid reg_base and irq numbers */ + uint32_t avail_substreams; + struct platform_device *pdev[MAX_SUBSTREAMS]; @@ -97811,6 +102369,9 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.h linux-raspberry-pi/sound/arm/bcm2835 + int old_volume; /* stores the volume value whist muted */ + int dest; + int mute; ++ ++ unsigned int opened; ++ unsigned int spdif_status; +} bcm2835_chip_t; + +typedef struct bcm2835_alsa_stream { @@ -97828,6 +102389,10 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.h linux-raspberry-pi/sound/arm/bcm2835 + int running; + int draining; + ++ int channels; ++ int params_rate; ++ int pcm_format_width; ++ + unsigned int pos; + unsigned int buffer_size; + unsigned int period_size; @@ -97843,6 +102408,7 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.h linux-raspberry-pi/sound/arm/bcm2835 + +int snd_bcm2835_new_ctl(bcm2835_chip_t * chip); +int snd_bcm2835_new_pcm(bcm2835_chip_t * chip); ++int snd_bcm2835_new_spdif_pcm(bcm2835_chip_t * chip); + +int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream); +int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream); @@ -97860,10 +102426,10 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.h linux-raspberry-pi/sound/arm/bcm2835 +void bcm2835_audio_flush_playback_buffers(bcm2835_alsa_stream_t * alsa_stream); + +#endif /* __SOUND_ARM_BCM2835_H */ -diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm2835-pcm.c ---- linux-3.12.13/sound/arm/bcm2835-pcm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/sound/arm/bcm2835-pcm.c 2014-03-11 17:51:48.000000000 +0100 -@@ -0,0 +1,426 @@ +diff -Nur linux-3.12.18/sound/arm/bcm2835-pcm.c linux-rpi/sound/arm/bcm2835-pcm.c +--- linux-3.12.18/sound/arm/bcm2835-pcm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/arm/bcm2835-pcm.c 2014-04-24 16:04:42.735152438 +0200 +@@ -0,0 +1,518 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* @@ -97881,6 +102447,8 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm +#include <linux/interrupt.h> +#include <linux/slab.h> + ++#include <sound/asoundef.h> ++ +#include "bcm2835.h" + +/* hardware definition */ @@ -97900,6 +102468,23 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm + .periods_max = 128, +}; + ++static struct snd_pcm_hardware snd_bcm2835_playback_spdif_hw = { ++ .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | ++ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID), ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 | ++ SNDRV_PCM_RATE_48000, ++ .rate_min = 44100, ++ .rate_max = 48000, ++ .channels_min = 2, ++ .channels_max = 2, ++ .buffer_bytes_max = 128 * 1024, ++ .period_bytes_min = 1 * 1024, ++ .period_bytes_max = 128 * 1024, ++ .periods_min = 1, ++ .periods_max = 128, ++}; ++ +static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime) +{ + audio_info("Freeing up alsa stream here ..\n"); @@ -97955,7 +102540,8 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm +} + +/* open callback */ -+static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream) ++static int snd_bcm2835_playback_open_generic( ++ struct snd_pcm_substream *substream, int spdif) +{ + bcm2835_chip_t *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; @@ -97968,6 +102554,11 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm + audio_info("Alsa open (%d)\n", substream->number); + idx = substream->number; + ++ if (spdif && chip->opened != 0) ++ return -EBUSY; ++ else if (!spdif && (chip->opened & (1 << idx))) ++ return -EBUSY; ++ + if (idx > MAX_SUBSTREAMS) { + audio_error + ("substream(%d) device doesn't exist max(%d) substreams allowed\n", @@ -97993,7 +102584,6 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm + alsa_stream->chip = chip; + alsa_stream->substream = substream; + alsa_stream->idx = idx; -+ chip->alsa_stream[idx] = alsa_stream; + + sema_init(&alsa_stream->buffers_update_sem, 0); + sema_init(&alsa_stream->control_sem, 0); @@ -98005,7 +102595,13 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm + + runtime->private_data = alsa_stream; + runtime->private_free = snd_bcm2835_playback_free; -+ runtime->hw = snd_bcm2835_playback_hw; ++ if (spdif) { ++ runtime->hw = snd_bcm2835_playback_spdif_hw; ++ } else { ++ /* clear spdif status, as we are not in spdif mode */ ++ chip->spdif_status = 0; ++ runtime->hw = snd_bcm2835_playback_hw; ++ } + /* minimum 16 bytes alignment (for vchiq bulk transfers) */ + snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, + 16); @@ -98015,7 +102611,9 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm + kfree(alsa_stream); + return err; + } ++ chip->alsa_stream[idx] = alsa_stream; + ++ chip->opened |= (1 << idx); + alsa_stream->open = 1; + alsa_stream->draining = 1; + @@ -98025,6 +102623,16 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm + return err; +} + ++static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream) ++{ ++ return snd_bcm2835_playback_open_generic(substream, 0); ++} ++ ++static int snd_bcm2835_playback_spdif_open(struct snd_pcm_substream *substream) ++{ ++ return snd_bcm2835_playback_open_generic(substream, 1); ++} ++ +/* close callback */ +static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream) +{ @@ -98032,6 +102640,7 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm + + struct snd_pcm_runtime *runtime = substream->runtime; + bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; ++ bcm2835_chip_t *chip = snd_pcm_substream_chip(substream); + + audio_info(" .. IN\n"); + audio_info("Alsa close\n"); @@ -98062,6 +102671,8 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm + * runtime->private_free callback we registered in *_open above + */ + ++ chip->opened &= ~(1 << substream->number); ++ + audio_info(" .. OUT\n"); + + return 0; @@ -98071,10 +102682,9 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm +static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ -+ int err; + struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream = -+ (bcm2835_alsa_stream_t *) runtime->private_data; ++ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; ++ int err; + + audio_info(" .. IN\n"); + @@ -98085,19 +102695,9 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm + return err; + } + -+ err = bcm2835_audio_set_params(alsa_stream, params_channels(params), -+ params_rate(params), -+ snd_pcm_format_width(params_format -+ (params))); -+ if (err < 0) { -+ audio_error(" error setting hw params\n"); -+ } -+ -+ bcm2835_audio_setup(alsa_stream); -+ -+ /* in preparation of the stream, set the controls (volume level) of the stream */ -+ bcm2835_audio_set_ctls(alsa_stream->chip); -+ ++ alsa_stream->channels = params_channels(params); ++ alsa_stream->params_rate = params_rate(params); ++ alsa_stream->pcm_format_width = snd_pcm_format_width(params_format (params)); + audio_info(" .. OUT\n"); + + return err; @@ -98113,11 +102713,35 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm +/* prepare callback */ +static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream) +{ ++ bcm2835_chip_t *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; ++ int channels; ++ int err; + + audio_info(" .. IN\n"); + ++ /* notify the vchiq that it should enter spdif passthrough mode by ++ * setting channels=0 (see ++ * https://github.com/raspberrypi/linux/issues/528) */ ++ if (chip->spdif_status & IEC958_AES0_NONAUDIO) ++ channels = 0; ++ else ++ channels = alsa_stream->channels; ++ ++ err = bcm2835_audio_set_params(alsa_stream, channels, ++ alsa_stream->params_rate, ++ alsa_stream->pcm_format_width); ++ if (err < 0) { ++ audio_error(" error setting hw params\n"); ++ } ++ ++ bcm2835_audio_setup(alsa_stream); ++ ++ /* in preparation of the stream, set the controls (volume level) of the stream */ ++ bcm2835_audio_set_ctls(alsa_stream->chip); ++ ++ + memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect)); + + alsa_stream->pcm_indirect.hw_buffer_size = @@ -98258,6 +102882,18 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm + .ack = snd_bcm2835_pcm_ack, +}; + ++static struct snd_pcm_ops snd_bcm2835_playback_spdif_ops = { ++ .open = snd_bcm2835_playback_spdif_open, ++ .close = snd_bcm2835_playback_close, ++ .ioctl = snd_bcm2835_pcm_lib_ioctl, ++ .hw_params = snd_bcm2835_pcm_hw_params, ++ .hw_free = snd_bcm2835_pcm_hw_free, ++ .prepare = snd_bcm2835_pcm_prepare, ++ .trigger = snd_bcm2835_pcm_trigger, ++ .pointer = snd_bcm2835_pcm_pointer, ++ .ack = snd_bcm2835_pcm_ack, ++}; ++ +/* create a pcm device */ +int snd_bcm2835_new_pcm(bcm2835_chip_t * chip) +{ @@ -98290,9 +102926,31 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm + + return 0; +} -diff -Nur linux-3.12.13/sound/arm/bcm2835-vchiq.c linux-raspberry-pi/sound/arm/bcm2835-vchiq.c ---- linux-3.12.13/sound/arm/bcm2835-vchiq.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/sound/arm/bcm2835-vchiq.c 2014-03-11 17:51:48.000000000 +0100 ++ ++int snd_bcm2835_new_spdif_pcm(bcm2835_chip_t * chip) ++{ ++ struct snd_pcm *pcm; ++ int err; ++ ++ err = snd_pcm_new(chip->card, "bcm2835 ALSA", 1, 1, 0, &pcm); ++ if (err < 0) ++ return err; ++ ++ pcm->private_data = chip; ++ strcpy(pcm->name, "bcm2835 IEC958/HDMI"); ++ chip->pcm_spdif = pcm; ++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, ++ &snd_bcm2835_playback_spdif_ops); ++ ++ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, ++ snd_dma_continuous_data (GFP_KERNEL), ++ 64 * 1024, 64 * 1024); ++ ++ return 0; ++} +diff -Nur linux-3.12.18/sound/arm/bcm2835-vchiq.c linux-rpi/sound/arm/bcm2835-vchiq.c +--- linux-3.12.18/sound/arm/bcm2835-vchiq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/arm/bcm2835-vchiq.c 2014-04-24 16:04:42.735152438 +0200 @@ -0,0 +1,879 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. @@ -98474,7 +103132,7 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-vchiq.c linux-raspberry-pi/sound/arm/b + +void my_workqueue_init(bcm2835_alsa_stream_t * alsa_stream) +{ -+ alsa_stream->my_wq = create_workqueue("my_queue"); ++ alsa_stream->my_wq = alloc_workqueue("my_queue", WQ_HIGHPRI, 1); + return; +} + @@ -99173,9 +103831,9 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-vchiq.c linux-raspberry-pi/sound/arm/b + +module_param(force_bulk, bool, 0444); +MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio"); -diff -Nur linux-3.12.13/sound/arm/Kconfig linux-raspberry-pi/sound/arm/Kconfig ---- linux-3.12.13/sound/arm/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/sound/arm/Kconfig 2014-03-11 17:33:39.000000000 +0100 +diff -Nur linux-3.12.18/sound/arm/Kconfig linux-rpi/sound/arm/Kconfig +--- linux-3.12.18/sound/arm/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/sound/arm/Kconfig 2014-04-24 15:35:05.357578964 +0200 @@ -39,5 +39,12 @@ Say Y or M if you want to support any AC97 codec attached to the PXA2xx AC97 interface. @@ -99189,9 +103847,9 @@ diff -Nur linux-3.12.13/sound/arm/Kconfig linux-raspberry-pi/sound/arm/Kconfig + endif # SND_ARM -diff -Nur linux-3.12.13/sound/arm/Makefile linux-raspberry-pi/sound/arm/Makefile ---- linux-3.12.13/sound/arm/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/sound/arm/Makefile 2014-03-11 17:51:47.000000000 +0100 +diff -Nur linux-3.12.18/sound/arm/Makefile linux-rpi/sound/arm/Makefile +--- linux-3.12.18/sound/arm/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/sound/arm/Makefile 2014-04-24 16:04:42.735152438 +0200 @@ -14,3 +14,8 @@ obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o @@ -99200,10 +103858,10 @@ diff -Nur linux-3.12.13/sound/arm/Makefile linux-raspberry-pi/sound/arm/Makefile +obj-$(CONFIG_SND_BCM2835) += snd-bcm2835.o +snd-bcm2835-objs := bcm2835.o bcm2835-ctl.o bcm2835-pcm.o bcm2835-vchiq.o + -+EXTRA_CFLAGS += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 -diff -Nur linux-3.12.13/sound/arm/vc_vchi_audioserv_defs.h linux-raspberry-pi/sound/arm/vc_vchi_audioserv_defs.h ---- linux-3.12.13/sound/arm/vc_vchi_audioserv_defs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/sound/arm/vc_vchi_audioserv_defs.h 2014-03-11 17:33:39.000000000 +0100 ++ccflags-y += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 +diff -Nur linux-3.12.18/sound/arm/vc_vchi_audioserv_defs.h linux-rpi/sound/arm/vc_vchi_audioserv_defs.h +--- linux-3.12.18/sound/arm/vc_vchi_audioserv_defs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/arm/vc_vchi_audioserv_defs.h 2014-04-24 15:35:05.365579053 +0200 @@ -0,0 +1,116 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. @@ -99321,9 +103979,9 @@ diff -Nur linux-3.12.13/sound/arm/vc_vchi_audioserv_defs.h linux-raspberry-pi/so +} VC_AUDIO_MSG_T; + +#endif // _VC_AUDIO_DEFS_H_ -diff -Nur linux-3.12.13/sound/soc/bcm/bcm2708-i2s.c linux-raspberry-pi/sound/soc/bcm/bcm2708-i2s.c ---- linux-3.12.13/sound/soc/bcm/bcm2708-i2s.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/bcm/bcm2708-i2s.c 2014-03-11 17:33:43.000000000 +0100 +diff -Nur linux-3.12.18/sound/soc/bcm/bcm2708-i2s.c linux-rpi/sound/soc/bcm/bcm2708-i2s.c +--- linux-3.12.18/sound/soc/bcm/bcm2708-i2s.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/soc/bcm/bcm2708-i2s.c 2014-04-24 16:04:43.363158508 +0200 @@ -0,0 +1,945 @@ +/* + * ALSA SoC I2S Audio Layer for Broadcom BCM2708 SoC @@ -100045,7 +104703,7 @@ diff -Nur linux-3.12.13/sound/soc/bcm/bcm2708-i2s.c linux-raspberry-pi/sound/soc + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE -+ | SNDRV_PCM_FMTBIT_S24_LE ++ // | SNDRV_PCM_FMTBIT_S24_LE : disable for now, it causes white noise with xbmc + | SNDRV_PCM_FMTBIT_S32_LE + }, + .capture = { @@ -100270,9 +104928,9 @@ diff -Nur linux-3.12.13/sound/soc/bcm/bcm2708-i2s.c linux-raspberry-pi/sound/soc +MODULE_DESCRIPTION("BCM2708 I2S interface"); +MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>"); +MODULE_LICENSE("GPL v2"); -diff -Nur linux-3.12.13/sound/soc/bcm/hifiberry_dac.c linux-raspberry-pi/sound/soc/bcm/hifiberry_dac.c ---- linux-3.12.13/sound/soc/bcm/hifiberry_dac.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/bcm/hifiberry_dac.c 2014-03-11 17:33:43.000000000 +0100 +diff -Nur linux-3.12.18/sound/soc/bcm/hifiberry_dac.c linux-rpi/sound/soc/bcm/hifiberry_dac.c +--- linux-3.12.18/sound/soc/bcm/hifiberry_dac.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/soc/bcm/hifiberry_dac.c 2014-04-24 15:35:05.481580345 +0200 @@ -0,0 +1,100 @@ +/* + * ASoC Driver for HifiBerry DAC @@ -100374,9 +105032,9 @@ diff -Nur linux-3.12.13/sound/soc/bcm/hifiberry_dac.c linux-raspberry-pi/sound/s +MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>"); +MODULE_DESCRIPTION("ASoC Driver for HifiBerry DAC"); +MODULE_LICENSE("GPL v2"); -diff -Nur linux-3.12.13/sound/soc/bcm/hifiberry_digi.c linux-raspberry-pi/sound/soc/bcm/hifiberry_digi.c ---- linux-3.12.13/sound/soc/bcm/hifiberry_digi.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/bcm/hifiberry_digi.c 2014-03-11 17:51:48.000000000 +0100 +diff -Nur linux-3.12.18/sound/soc/bcm/hifiberry_digi.c linux-rpi/sound/soc/bcm/hifiberry_digi.c +--- linux-3.12.18/sound/soc/bcm/hifiberry_digi.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/soc/bcm/hifiberry_digi.c 2014-04-24 16:04:43.363158508 +0200 @@ -0,0 +1,153 @@ +/* + * ASoC Driver for HifiBerry Digi @@ -100531,10 +105189,125 @@ diff -Nur linux-3.12.13/sound/soc/bcm/hifiberry_digi.c linux-raspberry-pi/sound/ +MODULE_AUTHOR("Daniel Matuschek <info@crazy-audio.com>"); +MODULE_DESCRIPTION("ASoC Driver for HifiBerry Digi"); +MODULE_LICENSE("GPL v2"); -diff -Nur linux-3.12.13/sound/soc/bcm/Kconfig linux-raspberry-pi/sound/soc/bcm/Kconfig ---- linux-3.12.13/sound/soc/bcm/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/bcm/Kconfig 2014-03-11 17:33:43.000000000 +0100 -@@ -0,0 +1,31 @@ +diff -Nur linux-3.12.18/sound/soc/bcm/iqaudio-dac.c linux-rpi/sound/soc/bcm/iqaudio-dac.c +--- linux-3.12.18/sound/soc/bcm/iqaudio-dac.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/soc/bcm/iqaudio-dac.c 2014-04-24 16:04:43.363158508 +0200 +@@ -0,0 +1,111 @@ ++/* ++ * ASoC Driver for IQaudIO DAC ++ * ++ * Author: Florian Meier <florian.meier@koalo.de> ++ * Copyright 2013 ++ * ++ * This program is free software; you can 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/module.h> ++#include <linux/platform_device.h> ++ ++#include <sound/core.h> ++#include <sound/pcm.h> ++#include <sound/pcm_params.h> ++#include <sound/soc.h> ++#include <sound/jack.h> ++ ++static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd) ++{ ++// NOT USED struct snd_soc_codec *codec = rtd->codec; ++ ++ return 0; ++} ++ ++static int snd_rpi_iqaudio_dac_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++// NOT USED struct snd_soc_dai *codec_dai = rtd->codec_dai; ++// NOT USED struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ unsigned int sample_bits = ++ snd_pcm_format_physical_width(params_format(params)); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_iqaudio_dac_ops = { ++ .hw_params = snd_rpi_iqaudio_dac_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_iqaudio_dac_dai[] = { ++{ ++ .name = "IQaudIO DAC", ++ .stream_name = "IQaudIO DAC HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm512x-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm512x.1-004c", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_iqaudio_dac_ops, ++ .init = snd_rpi_iqaudio_dac_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_iqaudio_dac = { ++ .name = "snd_rpi_iqaudio_dac", ++ .dai_link = snd_rpi_iqaudio_dac_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_dac_dai), ++}; ++ ++static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_iqaudio_dac.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); ++ if (ret) ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_iqaudio_dac_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_iqaudio_dac); ++} ++ ++static const struct of_device_id iqaudio_of_match[] = { ++ { .compatible = "iqaudio,iqaudio-dac", }, ++ {}, ++}; ++ ++static struct platform_driver snd_rpi_iqaudio_dac_driver = { ++ .driver = { ++ .name = "snd-rpi-iqaudio-dac", ++ .owner = THIS_MODULE, ++ .of_match_table = iqaudio_of_match, ++ }, ++ .probe = snd_rpi_iqaudio_dac_probe, ++ .remove = snd_rpi_iqaudio_dac_remove, ++}; ++ ++module_platform_driver(snd_rpi_iqaudio_dac_driver); ++ ++MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>"); ++MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); ++MODULE_LICENSE("GPL v2"); +diff -Nur linux-3.12.18/sound/soc/bcm/Kconfig linux-rpi/sound/soc/bcm/Kconfig +--- linux-3.12.18/sound/soc/bcm/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/soc/bcm/Kconfig 2014-04-24 15:35:05.481580345 +0200 +@@ -0,0 +1,38 @@ +config SND_BCM2708_SOC_I2S + tristate "SoC Audio support for the Broadcom BCM2708 I2S module" + depends on MACH_BCM2708 @@ -100566,10 +105339,17 @@ diff -Nur linux-3.12.13/sound/soc/bcm/Kconfig linux-raspberry-pi/sound/soc/bcm/K + select SND_SOC_PCM1794A + help + Say Y or M if you want to add support for RPi-DAC. -diff -Nur linux-3.12.13/sound/soc/bcm/Makefile linux-raspberry-pi/sound/soc/bcm/Makefile ---- linux-3.12.13/sound/soc/bcm/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/bcm/Makefile 2014-03-11 17:33:43.000000000 +0100 -@@ -0,0 +1,13 @@ ++ ++config SND_BCM2708_SOC_IQAUDIO_DAC ++ tristate "Support for IQaudIO-DAC" ++ depends on SND_BCM2708_SOC_I2S ++ select SND_SOC_PCM512x ++ help ++ Say Y or M if you want to add support for IQaudIO-DAC. +diff -Nur linux-3.12.18/sound/soc/bcm/Makefile linux-rpi/sound/soc/bcm/Makefile +--- linux-3.12.18/sound/soc/bcm/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/soc/bcm/Makefile 2014-04-24 16:04:43.363158508 +0200 +@@ -0,0 +1,15 @@ +# BCM2708 Platform Support +snd-soc-bcm2708-i2s-objs := bcm2708-i2s.o + @@ -100579,13 +105359,15 @@ diff -Nur linux-3.12.13/sound/soc/bcm/Makefile linux-raspberry-pi/sound/soc/bcm/ +snd-soc-hifiberry-dac-objs := hifiberry_dac.o +snd-soc-hifiberry-digi-objs := hifiberry_digi.o +snd-soc-rpi-dac-objs := rpi-dac.o ++snd-soc-iqaudio-dac-objs := iqaudio-dac.o + +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o +obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o -diff -Nur linux-3.12.13/sound/soc/bcm/rpi-dac.c linux-raspberry-pi/sound/soc/bcm/rpi-dac.c ---- linux-3.12.13/sound/soc/bcm/rpi-dac.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/bcm/rpi-dac.c 2014-03-11 17:33:43.000000000 +0100 ++obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff -Nur linux-3.12.18/sound/soc/bcm/rpi-dac.c linux-rpi/sound/soc/bcm/rpi-dac.c +--- linux-3.12.18/sound/soc/bcm/rpi-dac.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/soc/bcm/rpi-dac.c 2014-04-24 15:35:05.481580345 +0200 @@ -0,0 +1,97 @@ +/* + * ASoC Driver for RPi-DAC. @@ -100684,19 +105466,20 @@ diff -Nur linux-3.12.13/sound/soc/bcm/rpi-dac.c linux-raspberry-pi/sound/soc/bcm +MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>"); +MODULE_DESCRIPTION("ASoC Driver for RPi-DAC"); +MODULE_LICENSE("GPL v2"); -diff -Nur linux-3.12.13/sound/soc/codecs/Kconfig linux-raspberry-pi/sound/soc/codecs/Kconfig ---- linux-3.12.13/sound/soc/codecs/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/codecs/Kconfig 2014-03-11 17:51:48.000000000 +0100 -@@ -59,6 +59,8 @@ +diff -Nur linux-3.12.18/sound/soc/codecs/Kconfig linux-rpi/sound/soc/codecs/Kconfig +--- linux-3.12.18/sound/soc/codecs/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/sound/soc/codecs/Kconfig 2014-04-24 16:04:43.367158547 +0200 +@@ -59,6 +59,9 @@ select SND_SOC_PCM1681 if I2C select SND_SOC_PCM1792A if SPI_MASTER select SND_SOC_PCM3008 + select SND_SOC_PCM1794A + select SND_SOC_PCM5102A ++ select SND_SOC_PCM512x if SND_SOC_I2C_AND_SPI select SND_SOC_RT5631 if I2C select SND_SOC_RT5640 if I2C select SND_SOC_SGTL5000 if I2C -@@ -311,6 +313,12 @@ +@@ -311,6 +314,15 @@ config SND_SOC_PCM3008 tristate @@ -100706,33 +105489,38 @@ diff -Nur linux-3.12.13/sound/soc/codecs/Kconfig linux-raspberry-pi/sound/soc/co +config SND_SOC_PCM5102A + tristate + ++config SND_SOC_PCM512x ++ tristate ++ config SND_SOC_RT5631 tristate -diff -Nur linux-3.12.13/sound/soc/codecs/Makefile linux-raspberry-pi/sound/soc/codecs/Makefile ---- linux-3.12.13/sound/soc/codecs/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/codecs/Makefile 2014-03-11 17:51:48.000000000 +0100 -@@ -46,6 +46,8 @@ +diff -Nur linux-3.12.18/sound/soc/codecs/Makefile linux-rpi/sound/soc/codecs/Makefile +--- linux-3.12.18/sound/soc/codecs/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/sound/soc/codecs/Makefile 2014-04-24 16:04:43.367158547 +0200 +@@ -46,6 +46,9 @@ snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm1792a-codec-objs := pcm1792a.o snd-soc-pcm3008-objs := pcm3008.o +snd-soc-pcm1794a-objs := pcm1794a.o +snd-soc-pcm5102a-objs := pcm5102a.o ++snd-soc-pcm512x-objs := pcm512x.o snd-soc-rt5631-objs := rt5631.o snd-soc-rt5640-objs := rt5640.o snd-soc-sgtl5000-objs := sgtl5000.o -@@ -179,6 +181,8 @@ +@@ -179,6 +182,9 @@ obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o +obj-$(CONFIG_SND_SOC_PCM1794A) += snd-soc-pcm1794a.o +obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o ++obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o -diff -Nur linux-3.12.13/sound/soc/codecs/pcm1794a.c linux-raspberry-pi/sound/soc/codecs/pcm1794a.c ---- linux-3.12.13/sound/soc/codecs/pcm1794a.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/codecs/pcm1794a.c 2014-03-11 17:33:43.000000000 +0100 +diff -Nur linux-3.12.18/sound/soc/codecs/pcm1794a.c linux-rpi/sound/soc/codecs/pcm1794a.c +--- linux-3.12.18/sound/soc/codecs/pcm1794a.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/soc/codecs/pcm1794a.c 2014-04-24 15:35:05.493580478 +0200 @@ -0,0 +1,62 @@ +/* + * Driver for the PCM1794A codec @@ -100796,9 +105584,9 @@ diff -Nur linux-3.12.13/sound/soc/codecs/pcm1794a.c linux-raspberry-pi/sound/soc +MODULE_DESCRIPTION("ASoC PCM1794A codec driver"); +MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>"); +MODULE_LICENSE("GPL v2"); -diff -Nur linux-3.12.13/sound/soc/codecs/pcm5102a.c linux-raspberry-pi/sound/soc/codecs/pcm5102a.c ---- linux-3.12.13/sound/soc/codecs/pcm5102a.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/codecs/pcm5102a.c 2014-03-11 17:51:49.000000000 +0100 +diff -Nur linux-3.12.18/sound/soc/codecs/pcm5102a.c linux-rpi/sound/soc/codecs/pcm5102a.c +--- linux-3.12.18/sound/soc/codecs/pcm5102a.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/soc/codecs/pcm5102a.c 2014-04-24 15:35:05.493580478 +0200 @@ -0,0 +1,63 @@ +/* + * Driver for the PCM5102A codec @@ -100830,7 +105618,7 @@ diff -Nur linux-3.12.13/sound/soc/codecs/pcm5102a.c linux-raspberry-pi/sound/soc + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE | ++ // SNDRV_PCM_FMTBIT_S24_LE | : disable for now, it causes white noise with xbmc + SNDRV_PCM_FMTBIT_S32_LE + }, +}; @@ -100863,9 +105651,837 @@ diff -Nur linux-3.12.13/sound/soc/codecs/pcm5102a.c linux-raspberry-pi/sound/soc +MODULE_DESCRIPTION("ASoC PCM5102A codec driver"); +MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>"); +MODULE_LICENSE("GPL v2"); -diff -Nur linux-3.12.13/sound/soc/codecs/wm8804.c linux-raspberry-pi/sound/soc/codecs/wm8804.c ---- linux-3.12.13/sound/soc/codecs/wm8804.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/codecs/wm8804.c 2014-03-11 17:33:43.000000000 +0100 +diff -Nur linux-3.12.18/sound/soc/codecs/pcm512x.c linux-rpi/sound/soc/codecs/pcm512x.c +--- linux-3.12.18/sound/soc/codecs/pcm512x.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/soc/codecs/pcm512x.c 2014-04-24 16:04:43.375158625 +0200 +@@ -0,0 +1,678 @@ ++/* ++ * Driver for the PCM512x CODECs ++ * ++ * Author: Mark Brown <broonie@linaro.org> ++ * Copyright 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. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ */ ++ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/clk.h> ++#include <linux/i2c.h> ++#include <linux/pm_runtime.h> ++#include <linux/regmap.h> ++#include <linux/regulator/consumer.h> ++#include <linux/spi/spi.h> ++#include <sound/soc.h> ++#include <sound/soc-dapm.h> ++#include <sound/tlv.h> ++ ++#include "pcm512x.h" ++ ++#define PCM512x_NUM_SUPPLIES 3 ++static const char *pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = { ++ "AVDD", ++ "DVDD", ++ "CPVDD", ++}; ++ ++struct pcm512x_priv { ++ struct regmap *regmap; ++ struct clk *sclk; ++ struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES]; ++ struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES]; ++}; ++ ++/* ++ * We can't use the same notifier block for more than one supply and ++ * there's no way I can see to get from a callback to the caller ++ * except container_of(). ++ */ ++#define PCM512x_REGULATOR_EVENT(n) \ ++static int pcm512x_regulator_event_##n(struct notifier_block *nb, \ ++ unsigned long event, void *data) \ ++{ \ ++ struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \ ++ supply_nb[n]); \ ++ if (event & REGULATOR_EVENT_DISABLE) { \ ++ regcache_mark_dirty(pcm512x->regmap); \ ++ regcache_cache_only(pcm512x->regmap, true); \ ++ } \ ++ return 0; \ ++} ++ ++PCM512x_REGULATOR_EVENT(0) ++PCM512x_REGULATOR_EVENT(1) ++PCM512x_REGULATOR_EVENT(2) ++ ++static const struct reg_default pcm512x_reg_defaults[] = { ++ { PCM512x_RESET, 0x00 }, ++ { PCM512x_POWER, 0x00 }, ++ { PCM512x_MUTE, 0x00 }, ++ { PCM512x_DSP, 0x00 }, ++ { PCM512x_PLL_REF, 0x00 }, ++ { PCM512x_DAC_ROUTING, 0x11 }, ++ { PCM512x_DSP_PROGRAM, 0x01 }, ++ { PCM512x_CLKDET, 0x00 }, ++ { PCM512x_AUTO_MUTE, 0x00 }, ++ { PCM512x_ERROR_DETECT, 0x00 }, ++ { PCM512x_DIGITAL_VOLUME_1, 0x00 }, ++ { PCM512x_DIGITAL_VOLUME_2, 0x30 }, ++ { PCM512x_DIGITAL_VOLUME_3, 0x30 }, ++ { PCM512x_DIGITAL_MUTE_1, 0x22 }, ++ { PCM512x_DIGITAL_MUTE_2, 0x00 }, ++ { PCM512x_DIGITAL_MUTE_3, 0x07 }, ++}; ++ ++static bool pcm512x_readable(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case PCM512x_RESET: ++ case PCM512x_POWER: ++ case PCM512x_MUTE: ++ case PCM512x_PLL_EN: ++ case PCM512x_SPI_MISO_FUNCTION: ++ case PCM512x_DSP: ++ case PCM512x_GPIO_EN: ++ case PCM512x_BCLK_LRCLK_CFG: ++ case PCM512x_DSP_GPIO_INPUT: ++ case PCM512x_MASTER_MODE: ++ case PCM512x_PLL_REF: ++ case PCM512x_PLL_COEFF_0: ++ case PCM512x_PLL_COEFF_1: ++ case PCM512x_PLL_COEFF_2: ++ case PCM512x_PLL_COEFF_3: ++ case PCM512x_PLL_COEFF_4: ++ case PCM512x_DSP_CLKDIV: ++ case PCM512x_DAC_CLKDIV: ++ case PCM512x_NCP_CLKDIV: ++ case PCM512x_OSR_CLKDIV: ++ case PCM512x_MASTER_CLKDIV_1: ++ case PCM512x_MASTER_CLKDIV_2: ++ case PCM512x_FS_SPEED_MODE: ++ case PCM512x_IDAC_1: ++ case PCM512x_IDAC_2: ++ case PCM512x_ERROR_DETECT: ++ case PCM512x_I2S_1: ++ case PCM512x_I2S_2: ++ case PCM512x_DAC_ROUTING: ++ case PCM512x_DSP_PROGRAM: ++ case PCM512x_CLKDET: ++ case PCM512x_AUTO_MUTE: ++ case PCM512x_DIGITAL_VOLUME_1: ++ case PCM512x_DIGITAL_VOLUME_2: ++ case PCM512x_DIGITAL_VOLUME_3: ++ case PCM512x_DIGITAL_MUTE_1: ++ case PCM512x_DIGITAL_MUTE_2: ++ case PCM512x_DIGITAL_MUTE_3: ++ case PCM512x_GPIO_OUTPUT_1: ++ case PCM512x_GPIO_OUTPUT_2: ++ case PCM512x_GPIO_OUTPUT_3: ++ case PCM512x_GPIO_OUTPUT_4: ++ case PCM512x_GPIO_OUTPUT_5: ++ case PCM512x_GPIO_OUTPUT_6: ++ case PCM512x_GPIO_CONTROL_1: ++ case PCM512x_GPIO_CONTROL_2: ++ case PCM512x_OVERFLOW: ++ case PCM512x_RATE_DET_1: ++ case PCM512x_RATE_DET_2: ++ case PCM512x_RATE_DET_3: ++ case PCM512x_RATE_DET_4: ++ case PCM512x_ANALOG_MUTE_DET: ++ case PCM512x_GPIN: ++ case PCM512x_DIGITAL_MUTE_DET: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static bool pcm512x_volatile(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case PCM512x_PLL_EN: ++ case PCM512x_OVERFLOW: ++ case PCM512x_RATE_DET_1: ++ case PCM512x_RATE_DET_2: ++ case PCM512x_RATE_DET_3: ++ case PCM512x_RATE_DET_4: ++ case PCM512x_ANALOG_MUTE_DET: ++ case PCM512x_GPIN: ++ case PCM512x_DIGITAL_MUTE_DET: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1); ++ ++static const char *pcm512x_dsp_program_texts[] = { ++ "FIR interpolation with de-emphasis", ++ "Low latency IIR with de-emphasis", ++ "High attenuation with de-emphasis", ++ "Ringing-less low latency FIR", ++}; ++ ++static const unsigned int pcm512x_dsp_program_values[] = { ++ 1, ++ 2, ++ 3, ++ 5, ++ 7, ++}; ++ ++static const SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program, ++ PCM512x_DSP_PROGRAM, 0, 0x1f, ++ pcm512x_dsp_program_texts, ++ pcm512x_dsp_program_values); ++ ++static const char *pcm512x_clk_missing_text[] = { ++ "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s" ++}; ++ ++static const struct soc_enum pcm512x_clk_missing = ++ SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 7, pcm512x_clk_missing_text); ++ ++static const char *pcm512x_autom_text[] = { ++ "21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s" ++}; ++ ++static const struct soc_enum pcm512x_autom_l = ++ SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 7, ++ pcm512x_autom_text); ++ ++static const struct soc_enum pcm512x_autom_r = ++ SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 7, ++ pcm512x_autom_text); ++ ++static const char *pcm512x_ramp_rate_text[] = { ++ "1 sample/update", "2 samples/update", "4 samples/update", ++ "Immediate" ++}; ++ ++static const struct soc_enum pcm512x_vndf = ++ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4, ++ pcm512x_ramp_rate_text); ++ ++static const struct soc_enum pcm512x_vnuf = ++ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4, ++ pcm512x_ramp_rate_text); ++ ++static const struct soc_enum pcm512x_vedf = ++ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4, ++ pcm512x_ramp_rate_text); ++ ++static const char *pcm512x_ramp_step_text[] = { ++ "4dB/step", "2dB/step", "1dB/step", "0.5dB/step" ++}; ++ ++static const struct soc_enum pcm512x_vnds = ++ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4, ++ pcm512x_ramp_step_text); ++ ++static const struct soc_enum pcm512x_vnus = ++ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4, ++ pcm512x_ramp_step_text); ++ ++static const struct soc_enum pcm512x_veds = ++ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4, ++ pcm512x_ramp_step_text); ++ ++/* Don't let the DAC go into clipping by limiting the alsa volume control range */ ++static const struct snd_kcontrol_new pcm512x_controls[] = { ++SOC_DOUBLE_R_RANGE_TLV("Playback Digital Volume", PCM512x_DIGITAL_VOLUME_2, ++ PCM512x_DIGITAL_VOLUME_3, 0, 40, 255, 1, digital_tlv), ++SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT, ++ PCM512x_RQMR_SHIFT, 1, 1), ++ ++SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1), ++SOC_VALUE_ENUM("DSP Program", pcm512x_dsp_program), ++ ++SOC_ENUM("Clock Missing Period", pcm512x_clk_missing), ++SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l), ++SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r), ++SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3, ++ PCM512x_ACTL_SHIFT, 1, 0), ++SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT, ++ PCM512x_AMLR_SHIFT, 1, 0), ++ ++SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf), ++SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds), ++SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf), ++SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus), ++SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf), ++SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds), ++}; ++ ++static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = { ++SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), ++SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), ++ ++SND_SOC_DAPM_OUTPUT("OUTL"), ++SND_SOC_DAPM_OUTPUT("OUTR"), ++}; ++ ++static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = { ++ { "DACL", NULL, "Playback" }, ++ { "DACR", NULL, "Playback" }, ++ ++ { "OUTL", NULL, "DACL" }, ++ { "OUTR", NULL, "DACR" }, ++}; ++ ++static int pcm512x_set_bias_level(struct snd_soc_codec *codec, ++ enum snd_soc_bias_level level) ++{ ++ struct pcm512x_priv *pcm512x = dev_get_drvdata(codec->dev); ++ int ret; ++ ++ switch (level) { ++ case SND_SOC_BIAS_ON: ++ case SND_SOC_BIAS_PREPARE: ++ break; ++ ++ case SND_SOC_BIAS_STANDBY: ++ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, ++ PCM512x_RQST, 0); ++ if (ret != 0) { ++ dev_err(codec->dev, "Failed to remove standby: %d\n", ++ ret); ++ return ret; ++ } ++ break; ++ ++ case SND_SOC_BIAS_OFF: ++ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, ++ PCM512x_RQST, PCM512x_RQST); ++ if (ret != 0) { ++ dev_err(codec->dev, "Failed to request standby: %d\n", ++ ret); ++ return ret; ++ } ++ break; ++ } ++ ++ codec->dapm.bias_level = level; ++ ++ return 0; ++} ++ ++static struct snd_soc_dai_driver pcm512x_dai = { ++ .name = "pcm512x-hifi", ++ .playback = { ++ .stream_name = "Playback", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S24_LE | ++ SNDRV_PCM_FMTBIT_S32_LE ++ }, ++}; ++ ++static struct snd_soc_codec_driver pcm512x_codec_driver = { ++ .set_bias_level = pcm512x_set_bias_level, ++ .idle_bias_off = true, ++ ++ .controls = pcm512x_controls, ++ .num_controls = ARRAY_SIZE(pcm512x_controls), ++ .dapm_widgets = pcm512x_dapm_widgets, ++ .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets), ++ .dapm_routes = pcm512x_dapm_routes, ++ .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes), ++}; ++ ++static const struct regmap_config pcm512x_regmap = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ ++ .readable_reg = pcm512x_readable, ++ .volatile_reg = pcm512x_volatile, ++ ++ .max_register = PCM512x_MAX_REGISTER, ++ .reg_defaults = pcm512x_reg_defaults, ++ .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults), ++ .cache_type = REGCACHE_RBTREE, ++}; ++ ++static const struct of_device_id pcm512x_of_match[] = { ++ { .compatible = "ti,pcm5121", }, ++ { .compatible = "ti,pcm5122", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, pcm512x_of_match); ++ ++static int pcm512x_probe(struct device *dev, struct regmap *regmap) ++{ ++ struct pcm512x_priv *pcm512x; ++ int i, ret; ++ ++ pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL); ++ if (!pcm512x) ++ return -ENOMEM; ++ ++ dev_set_drvdata(dev, pcm512x); ++ pcm512x->regmap = regmap; ++ ++ for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) ++ pcm512x->supplies[i].supply = pcm512x_supply_names[i]; ++ ++ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies), ++ pcm512x->supplies); ++ if (ret != 0) { ++ dev_err(dev, "Failed to get supplies: %d\n", ret); ++ return ret; ++ } ++ ++ pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0; ++ pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1; ++ pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2; ++ ++ for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) { ++ ret = regulator_register_notifier(pcm512x->supplies[i].consumer, ++ &pcm512x->supply_nb[i]); ++ if (ret != 0) { ++ dev_err(dev, ++ "Failed to register regulator notifier: %d\n", ++ ret); ++ } ++ } ++ ++ ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies), ++ pcm512x->supplies); ++ if (ret != 0) { ++ dev_err(dev, "Failed to enable supplies: %d\n", ret); ++ return ret; ++ } ++ ++ /* Reset the device, verifying I/O in the process for I2C */ ++ ret = regmap_write(regmap, PCM512x_RESET, ++ PCM512x_RSTM | PCM512x_RSTR); ++ if (ret != 0) { ++ dev_err(dev, "Failed to reset device: %d\n", ret); ++ goto err; ++ } ++ ++ ret = regmap_write(regmap, PCM512x_RESET, 0); ++ if (ret != 0) { ++ dev_err(dev, "Failed to reset device: %d\n", ret); ++ goto err; ++ } ++ ++ pcm512x->sclk = devm_clk_get(dev, NULL); ++ if (IS_ERR(pcm512x->sclk)) { ++ if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ ++ dev_info(dev, "No SCLK, using BCLK: %ld\n", ++ PTR_ERR(pcm512x->sclk)); ++ ++ /* Disable reporting of missing SCLK as an error */ ++ regmap_update_bits(regmap, PCM512x_ERROR_DETECT, ++ PCM512x_IDCH, PCM512x_IDCH); ++ ++ /* Switch PLL input to BCLK */ ++ regmap_update_bits(regmap, PCM512x_PLL_REF, ++ PCM512x_SREF, PCM512x_SREF); ++ } else { ++ ret = clk_prepare_enable(pcm512x->sclk); ++ if (ret != 0) { ++ dev_err(dev, "Failed to enable SCLK: %d\n", ret); ++ return ret; ++ } ++ } ++ ++ /* Default to standby mode */ ++ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, ++ PCM512x_RQST, PCM512x_RQST); ++ if (ret != 0) { ++ dev_err(dev, "Failed to request standby: %d\n", ++ ret); ++ goto err_clk; ++ } ++ ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ pm_runtime_idle(dev); ++ ++ ret = snd_soc_register_codec(dev, &pcm512x_codec_driver, ++ &pcm512x_dai, 1); ++ if (ret != 0) { ++ dev_err(dev, "Failed to register CODEC: %d\n", ret); ++ goto err_pm; ++ } ++ ++ dev_info(dev, "Completed initialisation - pcm512x_probe"); ++ ++ return 0; ++ ++err_pm: ++ pm_runtime_disable(dev); ++err_clk: ++ if (!IS_ERR(pcm512x->sclk)) ++ clk_disable_unprepare(pcm512x->sclk); ++err: ++ regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), ++ pcm512x->supplies); ++ return ret; ++} ++ ++static void pcm512x_remove(struct device *dev) ++{ ++ struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); ++ ++ snd_soc_unregister_codec(dev); ++ pm_runtime_disable(dev); ++ if (!IS_ERR(pcm512x->sclk)) ++ clk_disable_unprepare(pcm512x->sclk); ++ regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), ++ pcm512x->supplies); ++} ++ ++/* TODO ++static int pcm512x_suspend(struct device *dev) ++{ ++ struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, ++ PCM512x_RQPD, PCM512x_RQPD); ++ if (ret != 0) { ++ dev_err(dev, "Failed to request power down: %d\n", ret); ++ return ret; ++ } ++ ++ ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), ++ pcm512x->supplies); ++ if (ret != 0) { ++ dev_err(dev, "Failed to disable supplies: %d\n", ret); ++ return ret; ++ } ++ ++ if (!IS_ERR(pcm512x->sclk)) ++ clk_disable_unprepare(pcm512x->sclk); ++ ++ return 0; ++} ++ ++static int pcm512x_resume(struct device *dev) ++{ ++ struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); ++ int ret; ++ ++ if (!IS_ERR(pcm512x->sclk)) { ++ ret = clk_prepare_enable(pcm512x->sclk); ++ if (ret != 0) { ++ dev_err(dev, "Failed to enable SCLK: %d\n", ret); ++ return ret; ++ } ++ } ++ ++ ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies), ++ pcm512x->supplies); ++ if (ret != 0) { ++ dev_err(dev, "Failed to enable supplies: %d\n", ret); ++ return ret; ++ } ++ ++ regcache_cache_only(pcm512x->regmap, false); ++ ret = regcache_sync(pcm512x->regmap); ++ if (ret != 0) { ++ dev_err(dev, "Failed to sync cache: %d\n", ret); ++ return ret; ++ } ++ ++ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, ++ PCM512x_RQPD, 0); ++ if (ret != 0) { ++ dev_err(dev, "Failed to remove power down: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++// END OF PCM512x_suspend and resume calls TODO ++*/ ++ ++static const struct dev_pm_ops pcm512x_pm_ops = { ++ SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL) ++}; ++ ++#if IS_ENABLED(CONFIG_I2C) ++static int pcm512x_i2c_probe(struct i2c_client *i2c, ++ const struct i2c_device_id *id) ++{ ++ struct regmap *regmap; ++ ++ regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap); ++ if (IS_ERR(regmap)) ++ return PTR_ERR(regmap); ++ ++ return pcm512x_probe(&i2c->dev, regmap); ++} ++ ++static int pcm512x_i2c_remove(struct i2c_client *i2c) ++{ ++ pcm512x_remove(&i2c->dev); ++ return 0; ++} ++ ++static const struct i2c_device_id pcm512x_i2c_id[] = { ++ { "pcm5121", }, ++ { "pcm5122", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); ++ ++static struct i2c_driver pcm512x_i2c_driver = { ++ .probe = pcm512x_i2c_probe, ++ .remove = pcm512x_i2c_remove, ++ .id_table = pcm512x_i2c_id, ++ .driver = { ++ .name = "pcm512x", ++ .owner = THIS_MODULE, ++ .of_match_table = pcm512x_of_match, ++ .pm = &pcm512x_pm_ops, ++ }, ++}; ++#endif ++ ++#if defined(CONFIG_SPI_MASTER) ++static int pcm512x_spi_probe(struct spi_device *spi) ++{ ++ struct regmap *regmap; ++ int ret; ++ ++ regmap = devm_regmap_init_spi(spi, &pcm512x_regmap); ++ if (IS_ERR(regmap)) { ++ ret = PTR_ERR(regmap); ++ return ret; ++ } ++ ++ return pcm512x_probe(&spi->dev, regmap); ++} ++ ++static int pcm512x_spi_remove(struct spi_device *spi) ++{ ++ pcm512x_remove(&spi->dev); ++ return 0; ++} ++ ++static const struct spi_device_id pcm512x_spi_id[] = { ++ { "pcm5121", }, ++ { "pcm5122", }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(spi, pcm512x_spi_id); ++ ++static struct spi_driver pcm512x_spi_driver = { ++ .probe = pcm512x_spi_probe, ++ .remove = pcm512x_spi_remove, ++ .id_table = pcm512x_spi_id, ++ .driver = { ++ .name = "pcm512x", ++ .owner = THIS_MODULE, ++ .of_match_table = pcm512x_of_match, ++ .pm = &pcm512x_pm_ops, ++ }, ++}; ++#endif ++ ++static int __init pcm512x_modinit(void) ++{ ++ int ret = 0; ++ ++#if IS_ENABLED(CONFIG_I2C) ++ ret = i2c_add_driver(&pcm512x_i2c_driver); ++ if (ret) { ++ printk(KERN_ERR "Failed to register pcm512x I2C driver: %d\n", ++ ret); ++ } ++#endif ++#if defined(CONFIG_SPI_MASTER) ++ ret = spi_register_driver(&pcm512x_spi_driver); ++ if (ret != 0) { ++ printk(KERN_ERR "Failed to register pcm512x SPI driver: %d\n", ++ ret); ++ } ++#endif ++ return ret; ++} ++module_init(pcm512x_modinit); ++ ++static void __exit pcm512x_exit(void) ++{ ++#if IS_ENABLED(CONFIG_I2C) ++ i2c_del_driver(&pcm512x_i2c_driver); ++#endif ++#if defined(CONFIG_SPI_MASTER) ++ spi_unregister_driver(&pcm512x_spi_driver); ++#endif ++} ++module_exit(pcm512x_exit); ++ ++MODULE_DESCRIPTION("ASoC PCM512x codec driver"); ++MODULE_AUTHOR("Mark Brown <broonie@linaro.org>"); ++MODULE_LICENSE("GPL v2"); +diff -Nur linux-3.12.18/sound/soc/codecs/pcm512x.h linux-rpi/sound/soc/codecs/pcm512x.h +--- linux-3.12.18/sound/soc/codecs/pcm512x.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-rpi/sound/soc/codecs/pcm512x.h 2014-04-24 15:35:05.493580478 +0200 +@@ -0,0 +1,142 @@ ++/* ++ * Driver for the PCM512x CODECs ++ * ++ * Author: Mark Brown <broonie@linaro.org> ++ * Copyright 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. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT 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 _SND_SOC_PCM512X ++#define _SND_SOC_PCM512X ++ ++#define PCM512x_PAGE_0_BASE 0 ++ ++#define PCM512x_PAGE 0 ++ ++#define PCM512x_RESET (PCM512x_PAGE_0_BASE + 1) ++#define PCM512x_POWER (PCM512x_PAGE_0_BASE + 2) ++#define PCM512x_MUTE (PCM512x_PAGE_0_BASE + 3) ++#define PCM512x_PLL_EN (PCM512x_PAGE_0_BASE + 4) ++#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_0_BASE + 6) ++#define PCM512x_DSP (PCM512x_PAGE_0_BASE + 7) ++#define PCM512x_GPIO_EN (PCM512x_PAGE_0_BASE + 8) ++#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_0_BASE + 9) ++#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_0_BASE + 10) ++#define PCM512x_MASTER_MODE (PCM512x_PAGE_0_BASE + 12) ++#define PCM512x_PLL_REF (PCM512x_PAGE_0_BASE + 13) ++#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_0_BASE + 20) ++#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_0_BASE + 21) ++#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_0_BASE + 22) ++#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_0_BASE + 23) ++#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_0_BASE + 24) ++#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_0_BASE + 27) ++#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_0_BASE + 28) ++#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_0_BASE + 29) ++#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_0_BASE + 30) ++#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_0_BASE + 32) ++#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_0_BASE + 33) ++#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_0_BASE + 34) ++#define PCM512x_IDAC_1 (PCM512x_PAGE_0_BASE + 35) ++#define PCM512x_IDAC_2 (PCM512x_PAGE_0_BASE + 36) ++#define PCM512x_ERROR_DETECT (PCM512x_PAGE_0_BASE + 37) ++#define PCM512x_I2S_1 (PCM512x_PAGE_0_BASE + 40) ++#define PCM512x_I2S_2 (PCM512x_PAGE_0_BASE + 41) ++#define PCM512x_DAC_ROUTING (PCM512x_PAGE_0_BASE + 42) ++#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_0_BASE + 43) ++#define PCM512x_CLKDET (PCM512x_PAGE_0_BASE + 44) ++#define PCM512x_AUTO_MUTE (PCM512x_PAGE_0_BASE + 59) ++#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_0_BASE + 60) ++#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_0_BASE + 61) ++#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_0_BASE + 62) ++#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_0_BASE + 63) ++#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_0_BASE + 64) ++#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_0_BASE + 65) ++#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_0_BASE + 80) ++#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_0_BASE + 81) ++#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_0_BASE + 82) ++#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_0_BASE + 83) ++#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_0_BASE + 84) ++#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_0_BASE + 85) ++#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_0_BASE + 86) ++#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_0_BASE + 87) ++#define PCM512x_OVERFLOW (PCM512x_PAGE_0_BASE + 90) ++#define PCM512x_RATE_DET_1 (PCM512x_PAGE_0_BASE + 91) ++#define PCM512x_RATE_DET_2 (PCM512x_PAGE_0_BASE + 92) ++#define PCM512x_RATE_DET_3 (PCM512x_PAGE_0_BASE + 93) ++#define PCM512x_RATE_DET_4 (PCM512x_PAGE_0_BASE + 94) ++#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_0_BASE + 108) ++#define PCM512x_GPIN (PCM512x_PAGE_0_BASE + 119) ++#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_0_BASE + 120) ++ ++#define PCM512x_MAX_REGISTER (PCM512x_PAGE_0_BASE + 120) ++ ++/* Page 0, Register 1 - reset */ ++#define PCM512x_RSTR (1 << 0) ++#define PCM512x_RSTM (1 << 4) ++ ++/* Page 0, Register 2 - power */ ++#define PCM512x_RQPD (1 << 0) ++#define PCM512x_RQPD_SHIFT 0 ++#define PCM512x_RQST (1 << 4) ++#define PCM512x_RQST_SHIFT 4 ++ ++/* Page 0, Register 3 - mute */ ++#define PCM512x_RQMR_SHIFT 0 ++#define PCM512x_RQML_SHIFT 4 ++ ++/* Page 0, Register 4 - PLL */ ++#define PCM512x_PLCE (1 << 0) ++#define PCM512x_RLCE_SHIFT 0 ++#define PCM512x_PLCK (1 << 4) ++#define PCM512x_PLCK_SHIFT 4 ++ ++/* Page 0, Register 7 - DSP */ ++#define PCM512x_SDSL (1 << 0) ++#define PCM512x_SDSL_SHIFT 0 ++#define PCM512x_DEMP (1 << 4) ++#define PCM512x_DEMP_SHIFT 4 ++ ++/* Page 0, Register 13 - PLL reference */ ++#define PCM512x_SREF (1 << 4) ++ ++/* Page 0, Register 37 - Error detection */ ++#define PCM512x_IPLK (1 << 0) ++#define PCM512x_DCAS (1 << 1) ++#define PCM512x_IDCM (1 << 2) ++#define PCM512x_IDCH (1 << 3) ++#define PCM512x_IDSK (1 << 4) ++#define PCM512x_IDBK (1 << 5) ++#define PCM512x_IDFS (1 << 6) ++ ++/* Page 0, Register 42 - DAC routing */ ++#define PCM512x_AUPR_SHIFT 0 ++#define PCM512x_AUPL_SHIFT 4 ++ ++/* Page 0, Register 59 - auto mute */ ++#define PCM512x_ATMR_SHIFT 0 ++#define PCM512x_ATML_SHIFT 4 ++ ++/* Page 0, Register 63 - ramp rates */ ++#define PCM512x_VNDF_SHIFT 6 ++#define PCM512x_VNDS_SHIFT 4 ++#define PCM512x_VNUF_SHIFT 2 ++#define PCM512x_VNUS_SHIFT 0 ++ ++/* Page 0, Register 64 - emergency ramp rates */ ++#define PCM512x_VEDF_SHIFT 6 ++#define PCM512x_VEDS_SHIFT 4 ++ ++/* Page 0, Register 65 - Digital mute enables */ ++#define PCM512x_ACTL_SHIFT 2 ++#define PCM512x_AMLE_SHIFT 1 ++#define PCM512x_AMLR_SHIFT 0 ++ ++#endif +diff -Nur linux-3.12.18/sound/soc/codecs/wm8804.c linux-rpi/sound/soc/codecs/wm8804.c +--- linux-3.12.18/sound/soc/codecs/wm8804.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/sound/soc/codecs/wm8804.c 2014-04-24 15:35:05.509580657 +0200 @@ -63,6 +63,7 @@ struct regmap *regmap; struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES]; @@ -100951,9 +106567,9 @@ diff -Nur linux-3.12.13/sound/soc/codecs/wm8804.c linux-raspberry-pi/sound/soc/c .controls = wm8804_snd_controls, .num_controls = ARRAY_SIZE(wm8804_snd_controls), -diff -Nur linux-3.12.13/sound/soc/codecs/wm8804.h linux-raspberry-pi/sound/soc/codecs/wm8804.h ---- linux-3.12.13/sound/soc/codecs/wm8804.h 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/codecs/wm8804.h 2014-03-11 17:33:43.000000000 +0100 +diff -Nur linux-3.12.18/sound/soc/codecs/wm8804.h linux-rpi/sound/soc/codecs/wm8804.h +--- linux-3.12.18/sound/soc/codecs/wm8804.h 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/sound/soc/codecs/wm8804.h 2014-04-24 15:35:05.509580657 +0200 @@ -57,5 +57,9 @@ #define WM8804_CLKOUT_SRC_OSCCLK 4 @@ -100964,9 +106580,9 @@ diff -Nur linux-3.12.13/sound/soc/codecs/wm8804.h linux-raspberry-pi/sound/soc/c +#define WM8804_MCLKDIV_128FS 1 #endif /* _WM8804_H */ -diff -Nur linux-3.12.13/sound/soc/Kconfig linux-raspberry-pi/sound/soc/Kconfig ---- linux-3.12.13/sound/soc/Kconfig 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/Kconfig 2014-03-11 17:51:48.000000000 +0100 +diff -Nur linux-3.12.18/sound/soc/Kconfig linux-rpi/sound/soc/Kconfig +--- linux-3.12.18/sound/soc/Kconfig 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/sound/soc/Kconfig 2014-04-24 16:04:42.783152901 +0200 @@ -33,6 +33,7 @@ # All the supported SoCs source "sound/soc/atmel/Kconfig" @@ -100975,9 +106591,9 @@ diff -Nur linux-3.12.13/sound/soc/Kconfig linux-raspberry-pi/sound/soc/Kconfig source "sound/soc/blackfin/Kconfig" source "sound/soc/cirrus/Kconfig" source "sound/soc/davinci/Kconfig" -diff -Nur linux-3.12.13/sound/soc/Makefile linux-raspberry-pi/sound/soc/Makefile ---- linux-3.12.13/sound/soc/Makefile 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/Makefile 2014-03-11 17:51:48.000000000 +0100 +diff -Nur linux-3.12.18/sound/soc/Makefile linux-rpi/sound/soc/Makefile +--- linux-3.12.18/sound/soc/Makefile 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/sound/soc/Makefile 2014-04-24 16:04:42.783152901 +0200 @@ -10,6 +10,7 @@ obj-$(CONFIG_SND_SOC) += generic/ obj-$(CONFIG_SND_SOC) += atmel/ @@ -100986,10 +106602,68 @@ diff -Nur linux-3.12.13/sound/soc/Makefile linux-raspberry-pi/sound/soc/Makefile obj-$(CONFIG_SND_SOC) += blackfin/ obj-$(CONFIG_SND_SOC) += cirrus/ obj-$(CONFIG_SND_SOC) += davinci/ -diff -Nur linux-3.12.13/sound/soc/soc-core.c linux-raspberry-pi/sound/soc/soc-core.c ---- linux-3.12.13/sound/soc/soc-core.c 2014-02-22 22:32:50.000000000 +0100 -+++ linux-raspberry-pi/sound/soc/soc-core.c 2014-03-11 17:51:55.000000000 +0100 -@@ -3576,6 +3576,22 @@ +diff -Nur linux-3.12.18/sound/soc/soc-core.c linux-rpi/sound/soc/soc-core.c +--- linux-3.12.18/sound/soc/soc-core.c 2014-04-18 11:14:28.000000000 +0200 ++++ linux-rpi/sound/soc/soc-core.c 2014-04-24 16:04:54.819269165 +0200 +@@ -3038,8 +3038,8 @@ + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; +- uinfo->value.integer.min = 0; +- uinfo->value.integer.max = platform_max - min; ++ uinfo->value.integer.min = min; ++ uinfo->value.integer.max = platform_max; + + return 0; + } +@@ -3070,9 +3070,10 @@ + unsigned int val, val_mask; + int ret; + +- val = ((ucontrol->value.integer.value[0] + min) & mask); + if (invert) +- val = max - val; ++ val = ((max - ucontrol->value.integer.value[0] + min) & mask); ++ else ++ val = (ucontrol->value.integer.value[0] & mask); + val_mask = mask << shift; + val = val << shift; + +@@ -3081,9 +3082,10 @@ + return ret; + + if (snd_soc_volsw_is_stereo(mc)) { +- val = ((ucontrol->value.integer.value[1] + min) & mask); + if (invert) +- val = max - val; ++ val = ((max - ucontrol->value.integer.value[1] + min) & mask); ++ else ++ val = (ucontrol->value.integer.value[1] & mask); + val_mask = mask << shift; + val = val << shift; + +@@ -3121,18 +3123,14 @@ + (snd_soc_read(codec, reg) >> shift) & mask; + if (invert) + ucontrol->value.integer.value[0] = +- max - ucontrol->value.integer.value[0]; +- ucontrol->value.integer.value[0] = +- ucontrol->value.integer.value[0] - min; ++ max - ucontrol->value.integer.value[0] + min; + + if (snd_soc_volsw_is_stereo(mc)) { + ucontrol->value.integer.value[1] = + (snd_soc_read(codec, rreg) >> shift) & mask; + if (invert) + ucontrol->value.integer.value[1] = +- max - ucontrol->value.integer.value[1]; +- ucontrol->value.integer.value[1] = +- ucontrol->value.integer.value[1] - min; ++ max - ucontrol->value.integer.value[1] + min; + } + + return 0; +@@ -3576,6 +3574,22 @@ EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll); /** diff --git a/target/linux/config/Config.in.netfilter.ip4 b/target/linux/config/Config.in.netfilter.ip4 index 7b898ba9b..019c5890c 100644 --- a/target/linux/config/Config.in.netfilter.ip4 +++ b/target/linux/config/Config.in.netfilter.ip4 @@ -39,8 +39,8 @@ config ADK_KPACKAGE_KMOD_FULL_NAT select ADK_KPACKAGE_KMOD_NF_NAT if ADK_KERNEL_VERSION_3_4_84 select ADK_KPACKAGE_KMOD_NF_NAT_IPV4 if ADK_KERNEL_VERSION_3_10_36 select ADK_KPACKAGE_KMOD_NF_NAT_IPV4 if ADK_KERNEL_VERSION_3_11_10 - select ADK_KPACKAGE_KMOD_NF_NAT_IPV4 if ADK_KERNEL_VERSION_3_12_14 - select ADK_KPACKAGE_KMOD_NF_NAT_IPV4 if ADK_KERNEL_VERSION_3_13_7 + select ADK_KPACKAGE_KMOD_NF_NAT_IPV4 if ADK_KERNEL_VERSION_3_12_18 + select ADK_KPACKAGE_KMOD_NF_NAT_IPV4 if ADK_KERNEL_VERSION_3_13_11 select ADK_KPACKAGE_KMOD_NF_NAT_IPV4 if ADK_KERNEL_VERSION_3_14_1 config ADK_KPACKAGE_KMOD_NF_NAT @@ -57,8 +57,8 @@ config ADK_KPACKAGE_KMOD_NF_NAT_IPV4 depends on ADK_KPACKAGE_KMOD_IP_NF_IPTABLES depends on ADK_KERNEL_VERSION_3_10_36 \ || ADK_KERNEL_VERSION_3_11_10 \ - || ADK_KERNEL_VERSION_3_12_14 \ - || ADK_KERNEL_VERSION_3_13_7 \ + || ADK_KERNEL_VERSION_3_12_18 \ + || ADK_KERNEL_VERSION_3_13_11 \ || ADK_KERNEL_VERSION_3_14_1 help The Full NAT option allows masquerading, port forwarding and other diff --git a/target/linux/patches/3.12.14/bsd-compatibility.patch b/target/linux/patches/3.12.18/bsd-compatibility.patch index b954b658f..b954b658f 100644 --- a/target/linux/patches/3.12.14/bsd-compatibility.patch +++ b/target/linux/patches/3.12.18/bsd-compatibility.patch diff --git a/target/linux/patches/3.12.14/defaults.patch b/target/linux/patches/3.12.18/defaults.patch index 6cdca084e..6cdca084e 100644 --- a/target/linux/patches/3.12.14/defaults.patch +++ b/target/linux/patches/3.12.18/defaults.patch diff --git a/target/linux/patches/3.12.14/disable-netfilter.patch b/target/linux/patches/3.12.18/disable-netfilter.patch index 7b1ca013a..7b1ca013a 100644 --- a/target/linux/patches/3.12.14/disable-netfilter.patch +++ b/target/linux/patches/3.12.18/disable-netfilter.patch diff --git a/target/linux/patches/3.12.14/export-symbol-for-exmap.patch b/target/linux/patches/3.12.18/export-symbol-for-exmap.patch index 4f0fc8449..4f0fc8449 100644 --- a/target/linux/patches/3.12.14/export-symbol-for-exmap.patch +++ b/target/linux/patches/3.12.18/export-symbol-for-exmap.patch diff --git a/target/linux/patches/3.12.14/gemalto.patch b/target/linux/patches/3.12.18/gemalto.patch index 65f7af1d7..65f7af1d7 100644 --- a/target/linux/patches/3.12.14/gemalto.patch +++ b/target/linux/patches/3.12.18/gemalto.patch diff --git a/target/linux/patches/3.12.14/lemote-rfkill.patch b/target/linux/patches/3.12.18/lemote-rfkill.patch index a61488434..a61488434 100644 --- a/target/linux/patches/3.12.14/lemote-rfkill.patch +++ b/target/linux/patches/3.12.18/lemote-rfkill.patch diff --git a/target/linux/patches/3.12.14/microblaze-ethernet.patch b/target/linux/patches/3.12.18/microblaze-ethernet.patch index 742ab477e..742ab477e 100644 --- a/target/linux/patches/3.12.14/microblaze-ethernet.patch +++ b/target/linux/patches/3.12.18/microblaze-ethernet.patch diff --git a/target/linux/patches/3.12.14/microblaze-setup.patch b/target/linux/patches/3.12.18/microblaze-setup.patch index 43815f274..43815f274 100644 --- a/target/linux/patches/3.12.14/microblaze-setup.patch +++ b/target/linux/patches/3.12.18/microblaze-setup.patch diff --git a/target/linux/patches/3.12.14/mips-lzo-fix.patch b/target/linux/patches/3.12.18/mips-lzo-fix.patch index 0740bdc6a..0740bdc6a 100644 --- a/target/linux/patches/3.12.14/mips-lzo-fix.patch +++ b/target/linux/patches/3.12.18/mips-lzo-fix.patch diff --git a/target/linux/patches/3.12.14/mtd-rootfs.patch b/target/linux/patches/3.12.18/mtd-rootfs.patch index 775d5fc80..775d5fc80 100644 --- a/target/linux/patches/3.12.14/mtd-rootfs.patch +++ b/target/linux/patches/3.12.18/mtd-rootfs.patch diff --git a/target/linux/patches/3.12.14/non-static.patch b/target/linux/patches/3.12.18/non-static.patch index a967703d0..a967703d0 100644 --- a/target/linux/patches/3.12.14/non-static.patch +++ b/target/linux/patches/3.12.18/non-static.patch diff --git a/target/linux/patches/3.12.14/ppc64-missing-zlib.patch b/target/linux/patches/3.12.18/ppc64-missing-zlib.patch index c6e0616be..c6e0616be 100644 --- a/target/linux/patches/3.12.14/ppc64-missing-zlib.patch +++ b/target/linux/patches/3.12.18/ppc64-missing-zlib.patch diff --git a/target/linux/patches/3.12.14/startup.patch b/target/linux/patches/3.12.18/startup.patch index 4cd477da1..4cd477da1 100644 --- a/target/linux/patches/3.12.14/startup.patch +++ b/target/linux/patches/3.12.18/startup.patch diff --git a/target/linux/patches/3.12.14/usb-defaults-off.patch b/target/linux/patches/3.12.18/usb-defaults-off.patch index 54dff2bd4..54dff2bd4 100644 --- a/target/linux/patches/3.12.14/usb-defaults-off.patch +++ b/target/linux/patches/3.12.18/usb-defaults-off.patch diff --git a/target/linux/patches/3.12.14/uuid.patch b/target/linux/patches/3.12.18/uuid.patch index ca23accdf..ca23accdf 100644 --- a/target/linux/patches/3.12.14/uuid.patch +++ b/target/linux/patches/3.12.18/uuid.patch diff --git a/target/linux/patches/3.12.14/vga-cons-default-off.patch b/target/linux/patches/3.12.18/vga-cons-default-off.patch index 08a57f783..08a57f783 100644 --- a/target/linux/patches/3.12.14/vga-cons-default-off.patch +++ b/target/linux/patches/3.12.18/vga-cons-default-off.patch diff --git a/target/linux/patches/3.12.14/wlan-cf.patch b/target/linux/patches/3.12.18/wlan-cf.patch index fc20759e2..fc20759e2 100644 --- a/target/linux/patches/3.12.14/wlan-cf.patch +++ b/target/linux/patches/3.12.18/wlan-cf.patch diff --git a/target/linux/patches/3.12.14/xargs.patch b/target/linux/patches/3.12.18/xargs.patch index 2c7b3df59..2c7b3df59 100644 --- a/target/linux/patches/3.12.14/xargs.patch +++ b/target/linux/patches/3.12.18/xargs.patch diff --git a/target/linux/patches/3.12.14/zlib-inflate.patch b/target/linux/patches/3.12.18/zlib-inflate.patch index 58e1f6d21..58e1f6d21 100644 --- a/target/linux/patches/3.12.14/zlib-inflate.patch +++ b/target/linux/patches/3.12.18/zlib-inflate.patch diff --git a/toolchain/kernel-headers/patches/3.12.14/cleankernel.patch b/toolchain/kernel-headers/patches/3.12.18/cleankernel.patch index d8c055dc3..d8c055dc3 100644 --- a/toolchain/kernel-headers/patches/3.12.14/cleankernel.patch +++ b/toolchain/kernel-headers/patches/3.12.18/cleankernel.patch diff --git a/toolchain/kernel-headers/patches/3.12.14/mkpiggy.patch b/toolchain/kernel-headers/patches/3.12.18/mkpiggy.patch index d4e815cd2..d4e815cd2 100644 --- a/toolchain/kernel-headers/patches/3.12.14/mkpiggy.patch +++ b/toolchain/kernel-headers/patches/3.12.18/mkpiggy.patch diff --git a/toolchain/kernel-headers/patches/3.12.14/relocs.patch b/toolchain/kernel-headers/patches/3.12.18/relocs.patch index 649b9e73e..649b9e73e 100644 --- a/toolchain/kernel-headers/patches/3.12.14/relocs.patch +++ b/toolchain/kernel-headers/patches/3.12.18/relocs.patch diff --git a/toolchain/kernel-headers/patches/3.12.14/sgidefs.patch b/toolchain/kernel-headers/patches/3.12.18/sgidefs.patch index f00a284d9..f00a284d9 100644 --- a/toolchain/kernel-headers/patches/3.12.14/sgidefs.patch +++ b/toolchain/kernel-headers/patches/3.12.18/sgidefs.patch diff --git a/toolchain/kernel-headers/patches/3.12.14/sortext.patch b/toolchain/kernel-headers/patches/3.12.18/sortext.patch index 8fd4e1d6b..8fd4e1d6b 100644 --- a/toolchain/kernel-headers/patches/3.12.14/sortext.patch +++ b/toolchain/kernel-headers/patches/3.12.18/sortext.patch |