diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/bcm2708_common.dtsi raspilinux/arch/arm/boot/dts/bcm2708_common.dtsi --- linux-stable/arch/arm/boot/dts/bcm2708_common.dtsi 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/bcm2708_common.dtsi 2015-12-26 19:08:30.232751804 +0100 @@ -0,0 +1,327 @@ +/include/ "skeleton.dtsi" + +/ { + interrupt-parent = <&intc>; + + aliases { + audio = &audio; + sound = &sound; + soc = &soc; + dma = &dma; + intc = &intc; + watchdog = &watchdog; + random = &random; + mailbox = &mailbox; + gpio = &gpio; + uart0 = &uart0; + sdhost = &sdhost; + i2s = &i2s; + spi0 = &spi0; + i2c0 = &i2c0; + uart1 = &uart1; + mmc = &mmc; + i2c1 = &i2c1; + i2c2 = &i2c2; + usb = &usb; + leds = &leds; + fb = &fb; + vchiq = &vchiq; + thermal = &thermal; + clocks = &clocks; + }; + + /* Onboard audio */ + audio: audio { + compatible = "brcm,bcm2835-audio"; + brcm,pwm-channels = <8>; + status = "disabled"; + }; + + /* External sound card */ + sound: sound { + }; + + soc: soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + dma: dma@7e007000 { + compatible = "brcm,bcm2835-dma"; + reg = <0x7e007000 0xf00>; + interrupts = <1 16>, + <1 17>, + <1 18>, + <1 19>, + <1 20>, + <1 21>, + <1 22>, + <1 23>, + <1 24>, + <1 25>, + <1 26>, + <1 27>; + + #dma-cells = <1>; + brcm,dma-channel-mask = <0x0f35>; + }; + + intc: interrupt-controller { + compatible = "brcm,bcm2708-armctrl-ic"; + reg = <0x7e00b200 0x200>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + mailbox: mailbox@7e00b800 { + compatible = "brcm,bcm2835-mbox"; + reg = <0x7e00b880 0x40>; + interrupts = <0 1>; + #mbox-cells = <0>; + }; + + watchdog: watchdog@7e100000 { + compatible = "brcm,bcm2835-pm-wdt"; + reg = <0x7e100000 0x28>; + status = "disabled"; + }; + + random: rng@7e104000 { + compatible = "brcm,bcm2835-rng"; + reg = <0x7e104000 0x10>; + status = "disabled"; + }; + + gpio: gpio@7e200000 { + compatible = "brcm,bcm2835-gpio"; + reg = <0x7e200000 0xb4>; + interrupts = <2 17>, <2 18>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + uart0: uart@7e201000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x7e201000 0x1000>; + interrupts = <2 25>; + clocks = <&clk_uart0 &clk_apb_p>; + clock-names = "uartclk","apb_pclk"; + arm,primecell-periphid = <0x00241011>; // For an explanation, see + // https://github.com/raspberrypi/linux/commit/13731d862cf5219216533a3b0de052cee4cc5038 + status = "disabled"; + }; + + sdhost: sdhost@7e202000 { + compatible = "brcm,bcm2835-sdhost"; + reg = <0x7e202000 0x100>; + interrupts = <2 24>; + clocks = <&clk_core>; + dmas = <&dma 13>, + <&dma 13>; + dma-names = "tx", "rx"; + brcm,pio-limit = <1>; + status = "disabled"; + }; + + i2s: i2s@7e203000 { + compatible = "brcm,bcm2708-i2s"; + reg = <0x7e203000 0x24>, + <0x7e101098 0x08>; + + //dmas = <&dma 2>, + // <&dma 3>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + spi0: spi@7e204000 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204000 0x1000>; + interrupts = <2 22>; + clocks = <&clk_core>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + /* the dma channels */ + dmas = <&dma 6>, <&dma 7>; + dma-names = "tx", "rx"; + /* the chipselects used - <0> means native GPIO + * add more gpios if necessary as <&gpio 6 1> + * (but do not forget to make them output!) + */ + cs-gpios = <0>, <0>; + }; + + i2c0: i2c@7e205000 { + compatible = "brcm,bcm2708-i2c"; + reg = <0x7e205000 0x1000>; + interrupts = <2 21>; + clocks = <&clk_core>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + pwm: pwm@7e20c000 { + compatible = "brcm,bcm2835-pwm"; + reg = <0x7e20c000 0x28>; + clocks = <&clk_pwm>; + #pwm-cells = <2>; + status = "disabled"; + }; + + uart1: uart@7e215040 { + compatible = "brcm,bcm2835-aux-uart", "ns16550"; + reg = <0x7e215040 0x40>; + interrupts = <1 29>; + clocks = <&clk_uart1>; + reg-shift = <2>; + no-loopback-test; + status = "disabled"; + }; + + mmc: mmc@7e300000 { + compatible = "brcm,bcm2835-mmc"; + reg = <0x7e300000 0x100>; + interrupts = <2 30>; + clocks = <&clk_mmc>; + dmas = <&dma 11>, + <&dma 11>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + i2c1: i2c@7e804000 { + compatible = "brcm,bcm2708-i2c"; + reg = <0x7e804000 0x1000>; + interrupts = <2 21>; + clocks = <&clk_core>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@7e805000 { + // Beware - this is shared with the HDMI module. + // Careless use may break (really) your display. + // Caveat emptor. + compatible = "brcm,bcm2708-i2c"; + reg = <0x7e805000 0x1000>; + interrupts = <2 21>; + clocks = <&clk_core>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + smi: smi@7e600000 { + compatible = "brcm,bcm2835-smi"; + reg = <0x7e600000 0x44>, <0x7e1010b0 0x8>; + interrupts = <2 16>; + brcm,smi-clock-source = <6>; + brcm,smi-clock-divisor = <4>; + dmas = <&dma 4>; + dma-names = "rx-tx"; + status = "disabled"; + }; + + usb: usb@7e980000 { + compatible = "brcm,bcm2708-usb"; + reg = <0x7e980000 0x10000>, + <0x7e006000 0x1000>; + interrupts = <2 0>, + <1 9>; + }; + + firmware: firmware { + compatible = "raspberrypi,bcm2835-firmware"; + mboxes = <&mailbox>; + }; + + leds: leds { + compatible = "gpio-leds"; + }; + + fb: fb { + compatible = "brcm,bcm2708-fb"; + firmware = <&firmware>; + status = "disabled"; + }; + + vchiq: vchiq { + compatible = "brcm,bcm2835-vchiq"; + reg = <0x7e00b840 0xf>; + interrupts = <0 2>; + cache-line-size = <32>; + firmware = <&firmware>; + }; + + thermal: thermal { + compatible = "brcm,bcm2835-thermal"; + firmware = <&firmware>; + }; + }; + + clocks: clocks { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + clk_core: clock@0 { + compatible = "fixed-clock"; + reg = <0>; + #clock-cells = <0>; + clock-output-names = "core"; + clock-frequency = <250000000>; + }; + + clk_mmc: clock@1 { + compatible = "fixed-clock"; + reg = <1>; + #clock-cells = <0>; + clock-output-names = "mmc"; + clock-frequency = <250000000>; + }; + + clk_uart0: clock@2 { + compatible = "fixed-clock"; + reg = <2>; + #clock-cells = <0>; + clock-output-names = "uart0_pclk"; + clock-frequency = <3000000>; + }; + + clk_apb_p: clock@3 { + compatible = "fixed-clock"; + reg = <3>; + #clock-cells = <0>; + clock-output-names = "apb_pclk"; + clock-frequency = <126000000>; + }; + + clk_pwm: clock@4 { + compatible = "fixed-clock"; + reg = <4>; + #clock-cells = <0>; + clock-output-names = "pwm"; + clock-frequency = <100000000>; + }; + + clk_uart1: clock@5 { + compatible = "fixed-factor-clock"; + reg = <5>; + clocks = <&clk_core>; + #clock-cells = <0>; + clock-div = <1>; + clock-mult = <2>; + }; + }; + + __overrides__ { + cache_line_size = <&vchiq>, "cache-line-size:0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/bcm2708.dtsi raspilinux/arch/arm/boot/dts/bcm2708.dtsi --- linux-stable/arch/arm/boot/dts/bcm2708.dtsi 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/bcm2708.dtsi 2015-12-26 19:08:30.232751804 +0100 @@ -0,0 +1,25 @@ +/include/ "bcm2708_common.dtsi" + +/ { + compatible = "brcm,bcm2708"; + model = "BCM2708"; + + chosen { + /* No padding required - the boot loader can do that. */ + bootargs = ""; + }; + + soc { + ranges = <0x7e000000 0x20000000 0x01000000>; + + arm-pmu { + compatible = "arm,arm1176-pmu"; + }; + + gpiomem { + compatible = "brcm,bcm2835-gpiomem"; + reg = <0x7e200000 0x1000>; + status = "okay"; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/bcm2708-rpi-b.dts raspilinux/arch/arm/boot/dts/bcm2708-rpi-b.dts --- linux-stable/arch/arm/boot/dts/bcm2708-rpi-b.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/bcm2708-rpi-b.dts 2015-12-26 19:08:30.232751804 +0100 @@ -0,0 +1,125 @@ +/dts-v1/; + +/include/ "bcm2708.dtsi" + +/ { + compatible = "brcm,bcm2708"; + model = "Raspberry Pi Model B"; +}; + +&gpio { + sdhost_pins: sdhost_pins { + brcm,pins = <48 49 50 51 52 53>; + brcm,function = <4>; /* alt0 */ + }; + + spi0_pins: spi0_pins { + brcm,pins = <7 8 9 10 11>; + brcm,function = <4>; /* alt0 */ + }; + + i2c0_pins: i2c0 { + brcm,pins = <0 1>; + brcm,function = <4>; + }; + + i2c1_pins: i2c1 { + brcm,pins = <2 3>; + brcm,function = <4>; + }; + + i2s_pins: i2s { + brcm,pins = <28 29 30 31>; + brcm,function = <6>; /* alt2 */ + }; +}; + +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_pins>; + bus-width = <4>; + status = "okay"; +}; + +&fb { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins>; + + spidev@0{ + compatible = "spidev"; + reg = <0>; /* CE0 */ + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <500000>; + }; + + spidev@1{ + compatible = "spidev"; + reg = <1>; /* CE1 */ + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <500000>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + clock-frequency = <100000>; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + clock-frequency = <100000>; +}; + +&i2c2 { + clock-frequency = <100000>; +}; + +&i2s { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + +&leds { + act_led: act { + label = "led0"; + linux,default-trigger = "mmc0"; + gpios = <&gpio 16 1>; + }; +}; + +/ { + __overrides__ { + uart0 = <&uart0>,"status"; + uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; + i2s = <&i2s>,"status"; + spi = <&spi0>,"status"; + i2c0 = <&i2c0>,"status"; + i2c1 = <&i2c1>,"status"; + i2c2_iknowwhatimdoing = <&i2c2>,"status"; + i2c0_baudrate = <&i2c0>,"clock-frequency:0"; + i2c1_baudrate = <&i2c1>,"clock-frequency:0"; + i2c2_baudrate = <&i2c2>,"clock-frequency:0"; + core_freq = <&clk_core>,"clock-frequency:0"; + + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; + act_led_trigger = <&act_led>,"linux,default-trigger"; + + audio = <&audio>,"status"; + watchdog = <&watchdog>,"status"; + random = <&random>,"status"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts raspilinux/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts --- linux-stable/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts 2015-12-26 19:08:30.232751804 +0100 @@ -0,0 +1,135 @@ +/dts-v1/; + +/include/ "bcm2708.dtsi" + +/ { + compatible = "brcm,bcm2708"; + model = "Raspberry Pi Model B+"; +}; + +&gpio { + sdhost_pins: sdhost_pins { + brcm,pins = <48 49 50 51 52 53>; + brcm,function = <4>; /* alt0 */ + }; + + spi0_pins: spi0_pins { + brcm,pins = <7 8 9 10 11>; + brcm,function = <4>; /* alt0 */ + }; + + i2c0_pins: i2c0 { + brcm,pins = <0 1>; + brcm,function = <4>; + }; + + i2c1_pins: i2c1 { + brcm,pins = <2 3>; + brcm,function = <4>; + }; + + i2s_pins: i2s { + brcm,pins = <18 19 20 21>; + brcm,function = <4>; /* alt0 */ + }; +}; + +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_pins>; + bus-width = <4>; + status = "okay"; +}; + +&fb { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins>; + + spidev@0{ + compatible = "spidev"; + reg = <0>; /* CE0 */ + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <500000>; + }; + + spidev@1{ + compatible = "spidev"; + reg = <1>; /* CE1 */ + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <500000>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + clock-frequency = <100000>; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + clock-frequency = <100000>; +}; + +&i2c2 { + clock-frequency = <100000>; +}; + +&i2s { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + +&leds { + act_led: act { + label = "led0"; + linux,default-trigger = "mmc0"; + gpios = <&gpio 47 0>; + }; + + pwr_led: pwr { + label = "led1"; + linux,default-trigger = "input"; + gpios = <&gpio 35 0>; + }; +}; + +/ { + __overrides__ { + uart0 = <&uart0>,"status"; + uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; + i2s = <&i2s>,"status"; + spi = <&spi0>,"status"; + i2c0 = <&i2c0>,"status"; + i2c1 = <&i2c1>,"status"; + i2c2_iknowwhatimdoing = <&i2c2>,"status"; + i2c0_baudrate = <&i2c0>,"clock-frequency:0"; + i2c1_baudrate = <&i2c1>,"clock-frequency:0"; + i2c2_baudrate = <&i2c2>,"clock-frequency:0"; + core_freq = <&clk_core>,"clock-frequency:0"; + + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; + act_led_trigger = <&act_led>,"linux,default-trigger"; + + pwr_led_gpio = <&pwr_led>,"gpios:4"; + pwr_led_activelow = <&pwr_led>,"gpios:8"; + pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; + + audio = <&audio>,"status"; + watchdog = <&watchdog>,"status"; + random = <&random>,"status"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/bcm2708-rpi-cm.dts raspilinux/arch/arm/boot/dts/bcm2708-rpi-cm.dts --- linux-stable/arch/arm/boot/dts/bcm2708-rpi-cm.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/bcm2708-rpi-cm.dts 2015-12-26 19:08:30.232751804 +0100 @@ -0,0 +1,92 @@ +/dts-v1/; + +/include/ "bcm2708-rpi-cm.dtsi" + +/ { + model = "Raspberry Pi Compute Module"; +}; + +&uart0 { + status = "okay"; +}; + +&gpio { + spi0_pins: spi0_pins { + brcm,pins = <7 8 9 10 11>; + brcm,function = <4>; /* alt0 */ + }; + + i2c0_pins: i2c0 { + brcm,pins = <0 1>; + brcm,function = <4>; + }; + + i2c1_pins: i2c1 { + brcm,pins = <2 3>; + brcm,function = <4>; + }; + + i2s_pins: i2s { + brcm,pins = <18 19 20 21>; + brcm,function = <4>; /* alt0 */ + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins>; + + spidev@0{ + compatible = "spidev"; + reg = <0>; /* CE0 */ + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <500000>; + }; + + spidev@1{ + compatible = "spidev"; + reg = <1>; /* CE1 */ + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <500000>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + clock-frequency = <100000>; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + clock-frequency = <100000>; +}; + +&i2c2 { + clock-frequency = <100000>; +}; + +&i2s { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + +/ { + __overrides__ { + uart0 = <&uart0>,"status"; + uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; + i2s = <&i2s>,"status"; + spi = <&spi0>,"status"; + i2c0 = <&i2c0>,"status"; + i2c1 = <&i2c1>,"status"; + i2c2_iknowwhatimdoing = <&i2c2>,"status"; + i2c0_baudrate = <&i2c0>,"clock-frequency:0"; + i2c1_baudrate = <&i2c1>,"clock-frequency:0"; + i2c2_baudrate = <&i2c2>,"clock-frequency:0"; + core_freq = <&clk_core>,"clock-frequency:0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi raspilinux/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi --- linux-stable/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/bcm2708-rpi-cm.dtsi 2015-12-26 19:08:30.232751804 +0100 @@ -0,0 +1,40 @@ +/include/ "bcm2708.dtsi" + +&gpio { + sdhost_pins: sdhost_pins { + brcm,pins = <48 49 50 51 52 53>; + brcm,function = <4>; /* alt0 */ + }; +}; + +&leds { + act_led: act { + label = "led0"; + linux,default-trigger = "mmc0"; + gpios = <&gpio 47 0>; + }; +}; + +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_pins>; + bus-width = <4>; + non-removable; + status = "okay"; +}; + +&fb { + status = "okay"; +}; + +/ { + __overrides__ { + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; + act_led_trigger = <&act_led>,"linux,default-trigger"; + + audio = <&audio>,"status"; + watchdog = <&watchdog>,"status"; + random = <&random>,"status"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/bcm2709.dtsi raspilinux/arch/arm/boot/dts/bcm2709.dtsi --- linux-stable/arch/arm/boot/dts/bcm2709.dtsi 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/bcm2709.dtsi 2015-12-26 19:08:30.232751804 +0100 @@ -0,0 +1,76 @@ +/include/ "bcm2708_common.dtsi" + +/ { + compatible = "brcm,bcm2709"; + model = "BCM2709"; + + chosen { + /* No padding required - the boot loader can do that. */ + bootargs = ""; + }; + + soc { + ranges = <0x7e000000 0x3f000000 0x01000000>; + + arm-pmu { + compatible = "arm,cortex-a7-pmu"; + interrupts = <3 9>; + }; + + gpiomem { + compatible = "brcm,bcm2835-gpiomem"; + reg = <0x7e200000 0x1000>; + status = "okay"; + }; + }; + + timer { + compatible = "arm,armv7-timer"; + clock-frequency = <19200000>; + interrupts = <3 0>, // PHYS_SECURE_PPI + <3 1>, // PHYS_NONSECURE_PPI + <3 3>, // VIRT_PPI + <3 2>; // HYP_PPI + always-on; + }; + + cpus: cpus { + #address-cells = <1>; + #size-cells = <0>; + + v7_cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0xf00>; + clock-frequency = <800000000>; + }; + + v7_cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0xf01>; + clock-frequency = <800000000>; + }; + + v7_cpu2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0xf02>; + clock-frequency = <800000000>; + }; + + v7_cpu3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0xf03>; + clock-frequency = <800000000>; + }; + }; + + __overrides__ { + arm_freq = <&v7_cpu0>, "clock-frequency:0", + <&v7_cpu1>, "clock-frequency:0", + <&v7_cpu2>, "clock-frequency:0", + <&v7_cpu3>, "clock-frequency:0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/bcm2709-rpi-2-b.dts raspilinux/arch/arm/boot/dts/bcm2709-rpi-2-b.dts --- linux-stable/arch/arm/boot/dts/bcm2709-rpi-2-b.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/bcm2709-rpi-2-b.dts 2015-12-26 19:08:30.232751804 +0100 @@ -0,0 +1,135 @@ +/dts-v1/; + +/include/ "bcm2709.dtsi" + +/ { + compatible = "brcm,bcm2709"; + model = "Raspberry Pi 2 Model B"; +}; + +&gpio { + sdhost_pins: sdhost_pins { + brcm,pins = <48 49 50 51 52 53>; + brcm,function = <4>; /* alt0 */ + }; + + spi0_pins: spi0_pins { + brcm,pins = <7 8 9 10 11>; + brcm,function = <4>; /* alt0 */ + }; + + i2c0_pins: i2c0 { + brcm,pins = <0 1>; + brcm,function = <4>; + }; + + i2c1_pins: i2c1 { + brcm,pins = <2 3>; + brcm,function = <4>; + }; + + i2s_pins: i2s { + brcm,pins = <18 19 20 21>; + brcm,function = <4>; /* alt0 */ + }; +}; + +&sdhost { + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_pins>; + bus-width = <4>; + status = "okay"; +}; + +&fb { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins>; + + spidev@0{ + compatible = "spidev"; + reg = <0>; /* CE0 */ + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <500000>; + }; + + spidev@1{ + compatible = "spidev"; + reg = <1>; /* CE1 */ + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <500000>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + clock-frequency = <100000>; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + clock-frequency = <100000>; +}; + +&i2c2 { + clock-frequency = <100000>; +}; + +&i2s { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + +&leds { + act_led: act { + label = "led0"; + linux,default-trigger = "mmc0"; + gpios = <&gpio 47 0>; + }; + + pwr_led: pwr { + label = "led1"; + linux,default-trigger = "input"; + gpios = <&gpio 35 0>; + }; +}; + +/ { + __overrides__ { + uart0 = <&uart0>,"status"; + uart0_clkrate = <&clk_uart0>,"clock-frequency:0"; + i2s = <&i2s>,"status"; + spi = <&spi0>,"status"; + i2c0 = <&i2c0>,"status"; + i2c1 = <&i2c1>,"status"; + i2c2_iknowwhatimdoing = <&i2c2>,"status"; + i2c0_baudrate = <&i2c0>,"clock-frequency:0"; + i2c1_baudrate = <&i2c1>,"clock-frequency:0"; + i2c2_baudrate = <&i2c2>,"clock-frequency:0"; + core_freq = <&clk_core>,"clock-frequency:0"; + + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; + act_led_trigger = <&act_led>,"linux,default-trigger"; + + pwr_led_gpio = <&pwr_led>,"gpios:4"; + pwr_led_activelow = <&pwr_led>,"gpios:8"; + pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; + + audio = <&audio>,"status"; + watchdog = <&watchdog>,"status"; + random = <&random>,"status"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/bcm2835.dtsi raspilinux/arch/arm/boot/dts/bcm2835.dtsi --- linux-stable/arch/arm/boot/dts/bcm2835.dtsi 2015-12-26 20:44:59.624055164 +0100 +++ raspilinux/arch/arm/boot/dts/bcm2835.dtsi 2015-12-26 19:08:30.232751804 +0100 @@ -6,14 +6,15 @@ interrupt-parent = <&intc>; chosen { - bootargs = "earlyprintk console=ttyAMA0"; + bootargs = ""; }; - soc { + soc: soc { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges = <0x7e000000 0x20000000 0x02000000>; + dma-ranges = <0x40000000 0x00000000 0x20000000>; timer@7e003000 { compatible = "brcm,bcm2835-system-timer"; @@ -50,16 +51,23 @@ #interrupt-cells = <2>; }; - watchdog@7e100000 { + watchdog: watchdog@7e100000 { compatible = "brcm,bcm2835-pm-wdt"; reg = <0x7e100000 0x28>; }; - rng@7e104000 { + random: rng@7e104000 { compatible = "brcm,bcm2835-rng"; reg = <0x7e104000 0x10>; }; + mailbox: mailbox@7e00b800 { + compatible = "brcm,bcm2835-mbox"; + reg = <0x7e00b880 0x40>; + interrupts = <0 1>; + #mbox-cells = <0>; + }; + gpio: gpio@7e200000 { compatible = "brcm,bcm2835-gpio"; reg = <0x7e200000 0xb4>; @@ -83,7 +91,7 @@ #interrupt-cells = <2>; }; - uart@7e201000 { + uart0: uart@7e201000 { compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell"; reg = <0x7e201000 0x1000>; interrupts = <2 25>; @@ -93,8 +101,8 @@ i2s: i2s@7e203000 { compatible = "brcm,bcm2835-i2s"; - reg = <0x7e203000 0x20>, - <0x7e101098 0x02>; + reg = <0x7e203000 0x24>, + <0x7e101098 0x08>; dmas = <&dma 2>, <&dma 3>; @@ -102,7 +110,7 @@ status = "disabled"; }; - spi: spi@7e204000 { + spi0: spi@7e204000 { compatible = "brcm,bcm2835-spi"; reg = <0x7e204000 0x1000>; interrupts = <2 22>; @@ -122,11 +130,14 @@ status = "disabled"; }; - sdhci: sdhci@7e300000 { - compatible = "brcm,bcm2835-sdhci"; + mmc: mmc@7e300000 { + compatible = "brcm,bcm2835-mmc"; reg = <0x7e300000 0x100>; interrupts = <2 30>; clocks = <&clk_mmc>; + dmas = <&dma 11>, + <&dma 11>; + dma-names = "tx", "rx"; status = "disabled"; }; @@ -140,10 +151,12 @@ status = "disabled"; }; - usb@7e980000 { - compatible = "brcm,bcm2835-usb"; - reg = <0x7e980000 0x10000>; - interrupts = <1 9>; + usb: usb@7e980000 { + compatible = "brcm,bcm2708-usb"; + reg = <0x7e980000 0x10000>, + <0x7e006000 0x1000>; + interrupts = <2 0>, + <1 9>; }; arm-pmu { @@ -161,7 +174,7 @@ reg = <0>; #clock-cells = <0>; clock-output-names = "mmc"; - clock-frequency = <100000000>; + clock-frequency = <250000000>; }; clk_i2c: clock@1 { diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/bcm2835-rpi-b.dts raspilinux/arch/arm/boot/dts/bcm2835-rpi-b.dts --- linux-stable/arch/arm/boot/dts/bcm2835-rpi-b.dts 2015-12-26 20:44:59.624055164 +0100 +++ raspilinux/arch/arm/boot/dts/bcm2835-rpi-b.dts 2015-12-26 19:08:30.232751804 +0100 @@ -5,19 +5,28 @@ compatible = "raspberrypi,model-b", "brcm,bcm2835"; model = "Raspberry Pi Model B"; - leds { - act { - gpios = <&gpio 16 1>; - }; - }; }; &gpio { - pinctrl-0 = <&gpioout &alt0 &i2s_alt2 &alt3>; - - /* I2S interface */ - i2s_alt2: i2s_alt2 { + i2s_pins: i2s { brcm,pins = <28 29 30 31>; - brcm,function = <6>; /* alt2 */ + brcm,function = <4>; /* alt0 */ + }; +}; + +&i2s { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + +&act_led { + gpios = <&gpio 16 1>; +}; + +/ { + __overrides__ { + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; }; }; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts raspilinux/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts --- linux-stable/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts 2015-12-26 20:44:59.624055164 +0100 +++ raspilinux/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts 2015-12-26 19:08:30.232751804 +0100 @@ -4,27 +4,40 @@ / { compatible = "raspberrypi,model-b-plus", "brcm,bcm2835"; model = "Raspberry Pi Model B+"; - - leds { - act { - gpios = <&gpio 47 0>; - }; - - pwr { - label = "PWR"; - gpios = <&gpio 35 0>; - default-state = "keep"; - linux,default-trigger = "default-on"; - }; - }; }; &gpio { - pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>; - - /* I2S interface */ - i2s_alt0: i2s_alt0 { + i2s_pins: i2s { brcm,pins = <18 19 20 21>; brcm,function = <4>; /* alt0 */ }; }; + +&i2s { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + +&act_led { + gpios = <&gpio 47 0>; +}; + +&leds { + pwr_led: pwr { + label = "led1"; + linux,default-trigger = "input"; + gpios = <&gpio 35 0>; + }; +}; + +/ { + __overrides__ { + act_led_gpio = <&act_led>,"gpios:4"; + act_led_activelow = <&act_led>,"gpios:8"; + + pwr_led_gpio = <&pwr_led>,"gpios:4"; + pwr_led_activelow = <&pwr_led>,"gpios:8"; + pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/bcm2835-rpi.dtsi raspilinux/arch/arm/boot/dts/bcm2835-rpi.dtsi --- linux-stable/arch/arm/boot/dts/bcm2835-rpi.dtsi 2015-12-26 20:44:59.624055164 +0100 +++ raspilinux/arch/arm/boot/dts/bcm2835-rpi.dtsi 2015-12-26 19:08:30.232751804 +0100 @@ -1,51 +1,133 @@ /include/ "bcm2835.dtsi" / { + /* This is left here in case u-boot needs it */ memory { reg = <0 0x10000000>; }; - leds { + aliases { + soc = &soc; + spi0 = &spi0; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2s = &i2s; + gpio = &gpio; + intc = &intc; + leds = &leds; + sound = &sound; + }; + + leds: leds { compatible = "gpio-leds"; - act { - label = "ACT"; - default-state = "keep"; - linux,default-trigger = "heartbeat"; + act_led: act { + label = "led0"; + linux,default-trigger = "mmc0"; + }; + }; + + soc { + firmware: firmware { + compatible = "raspberrypi,bcm2835-firmware"; + mboxes = <&mailbox>; + }; + + fb: fb { + compatible = "brcm,bcm2708-fb"; + firmware = <&firmware>; + }; + + thermal: thermal { + compatible = "brcm,bcm2835-thermal"; + firmware = <&firmware>; + }; + + vchiq: vchiq { + compatible = "brcm,bcm2835-vchiq"; + reg = <0x7e00b840 0xf>; + interrupts = <0 2>; + cache-line-size = <32>; + firmware = <&firmware>; }; }; + + /* Onboard audio */ + audio: audio { + compatible = "brcm,bcm2835-audio"; + brcm,pwm-channels = <8>; + status = "disabled"; + }; + + /* External sound card */ + sound: sound { + }; }; &gpio { - pinctrl-names = "default"; + spi0_pins: spi0_pins { + brcm,pins = <7 8 9 10 11>; + brcm,function = <4>; /* alt0 */ + }; - gpioout: gpioout { - brcm,pins = <6>; - brcm,function = <1>; /* GPIO out */ + i2c0_pins: i2c0 { + brcm,pins = <0 1>; + brcm,function = <4>; }; - alt0: alt0 { - brcm,pins = <0 1 2 3 4 5 7 8 9 10 11 14 15 40 45>; - brcm,function = <4>; /* alt0 */ + i2c1_pins: i2c1 { + brcm,pins = <2 3>; + brcm,function = <4>; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins>; + + spidev@0{ + compatible = "spidev"; + reg = <0>; /* CE0 */ + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <500000>; }; - alt3: alt3 { - brcm,pins = <48 49 50 51 52 53>; - brcm,function = <7>; /* alt3 */ + spidev@1{ + compatible = "spidev"; + reg = <1>; /* CE1 */ + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <500000>; }; }; &i2c0 { - status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; clock-frequency = <100000>; }; &i2c1 { - status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; clock-frequency = <100000>; }; -&sdhci { +&mmc { status = "okay"; bus-width = <4>; }; + +/ { + __overrides__ { + i2s = <&i2s>,"status"; + spi = <&spi0>,"status"; + i2c0 = <&i2c0>,"status"; + i2c1 = <&i2c1>,"status"; + i2c0_baudrate = <&i2c0>,"clock-frequency:0"; + i2c1_baudrate = <&i2c1>,"clock-frequency:0"; + act_led_trigger = <&act_led>,"linux,default-trigger"; + audio = <&audio>,"status"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/Makefile raspilinux/arch/arm/boot/dts/Makefile --- linux-stable/arch/arm/boot/dts/Makefile 2015-12-26 20:44:59.612056270 +0100 +++ raspilinux/arch/arm/boot/dts/Makefile 2015-12-26 19:08:30.224752550 +0100 @@ -1,5 +1,24 @@ ifeq ($(CONFIG_OF),y) +dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b.dtb +dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b-plus.dtb +dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-cm.dtb +dtb-$(CONFIG_BCM2709_DT) += bcm2709-rpi-2-b.dtb + +# Raspberry Pi +ifeq ($(CONFIG_BCM2708_DT),y) + RPI_DT_OVERLAYS=y +endif +ifeq ($(CONFIG_BCM2709_DT),y) + RPI_DT_OVERLAYS=y +endif +ifeq ($(CONFIG_ARCH_BCM2835),y) + RPI_DT_OVERLAYS=y +endif +ifeq ($(RPI_DT_OVERLAYS),y) + dts-dirs += overlays +endif + dtb-$(CONFIG_ARCH_ALPINE) += \ alpine-db.dtb dtb-$(CONFIG_MACH_ASM9260) += \ @@ -660,7 +679,17 @@ mt6592-evb.dtb \ mt8127-moose.dtb \ mt8135-evbp1.dtb + +targets += dtbs dtbs_install +targets += $(dtb-y) + endif always := $(dtb-y) +subdir-y := $(dts-dirs) clean-files := *.dtb + +# Enable fixups to support overlays on BCM2708 platforms +ifeq ($(RPI_DT_OVERLAYS),y) + DTC_FLAGS ?= -@ +endif diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/ads7846-overlay.dts raspilinux/arch/arm/boot/dts/overlays/ads7846-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/ads7846-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/ads7846-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,83 @@ +/* + * Generic Device Tree overlay for the ADS7846 touch controller + * + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + + spidev@0{ + status = "disabled"; + }; + + spidev@1{ + status = "disabled"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + ads7846_pins: ads7846_pins { + brcm,pins = <255>; /* illegal default value */ + brcm,function = <0>; /* in */ + brcm,pull = <0>; /* none */ + }; + }; + }; + + fragment@2 { + target = <&spi0>; + __overlay__ { + /* needed to avoid dtc warning */ + #address-cells = <1>; + #size-cells = <0>; + + ads7846: ads7846@1 { + compatible = "ti,ads7846"; + reg = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&ads7846_pins>; + + spi-max-frequency = <2000000>; + interrupts = <255 2>; /* high-to-low edge triggered */ + interrupt-parent = <&gpio>; + pendown-gpio = <&gpio 255 0>; + + /* driver defaults */ + ti,x-min = /bits/ 16 <0>; + ti,y-min = /bits/ 16 <0>; + ti,x-max = /bits/ 16 <0x0FFF>; + ti,y-max = /bits/ 16 <0x0FFF>; + ti,pressure-min = /bits/ 16 <0>; + ti,pressure-max = /bits/ 16 <0xFFFF>; + ti,x-plate-ohms = /bits/ 16 <400>; + }; + }; + }; + __overrides__ { + cs = <&ads7846>,"reg:0"; + speed = <&ads7846>,"spi-max-frequency:0"; + penirq = <&ads7846_pins>,"brcm,pins:0", /* REQUIRED */ + <&ads7846>,"interrupts:0", + <&ads7846>,"pendown-gpio:4"; + penirq_pull = <&ads7846_pins>,"brcm,pull:0"; + swapxy = <&ads7846>,"ti,swap-xy?"; + xmin = <&ads7846>,"ti,x-min;0"; + ymin = <&ads7846>,"ti,y-min;0"; + xmax = <&ads7846>,"ti,x-max;0"; + ymax = <&ads7846>,"ti,y-max;0"; + pmin = <&ads7846>,"ti,pressure-min;0"; + pmax = <&ads7846>,"ti,pressure-max;0"; + xohms = <&ads7846>,"ti,x-plate-ohms;0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/at86rf233-overlay.dts raspilinux/arch/arm/boot/dts/overlays/at86rf233-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/at86rf233-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/at86rf233-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,54 @@ +/dts-v1/; +/plugin/; + +/* Overlay for Atmel AT86RF233 IEEE 802.15.4 WPAN transceiver on spi0.0 */ + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + + status = "okay"; + + spidev@0{ + status = "disabled"; + }; + + lowpan0: at86rf233@0 { + compatible = "atmel,at86rf233"; + reg = <0>; + interrupt-parent = <&gpio>; + interrupts = <23 4>; /* active high */ + reset-gpio = <&gpio 24 1>; + sleep-gpio = <&gpio 25 1>; + spi-max-frequency = <6000000>; + xtal-trim = /bits/ 8 <0xf>; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + lowpan0_pins: lowpan0_pins { + brcm,pins = <23 24 25>; + brcm,function = <0 1 1>; /* in out out */ + }; + }; + }; + + __overrides__ { + interrupt = <&lowpan0>, "interrupts:0", + <&lowpan0_pins>, "brcm,pins:0"; + reset = <&lowpan0>, "reset-gpio:4", + <&lowpan0_pins>, "brcm,pins:4"; + sleep = <&lowpan0>, "sleep-gpio:4", + <&lowpan0_pins>, "brcm,pins:8"; + speed = <&lowpan0>, "spi-max-frequency:0"; + trim = <&lowpan0>, "xtal-trim.0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts raspilinux/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,23 @@ +// Definitions for BMP085/BMP180 digital barometric pressure and temperature sensors from Bosch Sensortec +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&i2c_arm>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + bmp085@77 { + compatible = "bosch,bmp085"; + reg = <0x77>; + default-oversampling = <3>; + status = "okay"; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/dht11-overlay.dts raspilinux/arch/arm/boot/dts/overlays/dht11-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/dht11-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/dht11-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,39 @@ +/* + * Overlay for the DHT11/21/22 humidity/temperature sensor modules. + */ +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target-path = "/"; + __overlay__ { + + dht11: dht11@0 { + compatible = "dht11"; + pinctrl-names = "default"; + pinctrl-0 = <&dht11_pins>; + gpios = <&gpio 4 0>; + status = "okay"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + dht11_pins: dht11_pins { + brcm,pins = <4>; + brcm,function = <0>; // in + brcm,pull = <0>; // off + }; + }; + }; + + __overrides__ { + gpiopin = <&dht11_pins>,"brcm,pins:0", + <&dht11>,"gpios:4"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/enc28j60-overlay.dts raspilinux/arch/arm/boot/dts/overlays/enc28j60-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/enc28j60-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/enc28j60-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,50 @@ +// Overlay for the Microchip ENC28J60 Ethernet Controller +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + /* needed to avoid dtc warning */ + #address-cells = <1>; + #size-cells = <0>; + + status = "okay"; + + spidev@0{ + status = "disabled"; + }; + + eth1: enc28j60@0{ + compatible = "microchip,enc28j60"; + reg = <0>; /* CE0 */ + pinctrl-names = "default"; + pinctrl-0 = <ð1_pins>; + interrupt-parent = <&gpio>; + interrupts = <25 0x2>; /* falling edge */ + spi-max-frequency = <12000000>; + status = "okay"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + eth1_pins: eth1_pins { + brcm,pins = <25>; + brcm,function = <0>; /* in */ + brcm,pull = <0>; /* none */ + }; + }; + }; + + __overrides__ { + int_pin = <ð1>, "interrupts:0", + <ð1_pins>, "brcm,pins:0"; + speed = <ð1>, "spi-max-frequency:0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts raspilinux/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,45 @@ +// Definitions for ir-gpio module +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target-path = "/"; + __overlay__ { + gpio_ir: ir-receiver { + compatible = "gpio-ir-receiver"; + + // pin number, high or low + gpios = <&gpio 18 1>; + + // parameter for keymap name + linux,rc-map-name = "rc-rc6-mce"; + + status = "okay"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + gpio_ir_pins: gpio_ir_pins { + brcm,pins = <18>; // pin 18 + brcm,function = <0>; // in + brcm,pull = <1>; // down + }; + }; + }; + + __overrides__ { + // parameters + gpio_pin = <&gpio_ir>,"gpios:4", + <&gpio_ir_pins>,"brcm,pins:0", + <&gpio_ir_pins>,"brcm,pull:0"; // pin number + gpio_pull = <&gpio_ir_pins>,"brcm,pull:0"; // pull-up/down state + + rc-map-name = <&gpio_ir>,"linux,rc-map-name"; // default rc map + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts raspilinux/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,34 @@ +// Definitions for gpio-poweroff module +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target-path = "/"; + __overlay__ { + power_ctrl: power_ctrl { + compatible = "gpio-poweroff"; + gpios = <&gpio 26 0>; + force; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + power_ctrl_pins: power_ctrl_pins { + brcm,pins = <26>; + brcm,function = <1>; // out + }; + }; + }; + + __overrides__ { + gpiopin = <&power_ctrl>,"gpios:4", + <&power_ctrl_pins>,"brcm,pins:0"; + active_low = <&power_ctrl>,"gpios:8"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts raspilinux/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,39 @@ +// Definitions for HiFiBerry Amp/Amp+ +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-amp"; + i2s-controller = <&i2s>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@2 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + tas5713@1b { + #sound-dai-cells = <0>; + compatible = "ti,tas5713"; + reg = <0x1b>; + status = "okay"; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts raspilinux/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,34 @@ +// Definitions for HiFiBerry DAC +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-dac"; + i2s-controller = <&i2s>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@2 { + target-path = "/"; + __overlay__ { + pcm5102a-codec { + #sound-dai-cells = <0>; + compatible = "ti,pcm5102a"; + status = "okay"; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts raspilinux/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,50 @@ +// Definitions for HiFiBerry DAC+ +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target-path = "/clocks"; + __overlay__ { + dacpro_osc: dacpro_osc { + compatible = "hifiberry,dacpro-clk"; + #clock-cells = <0>; + }; + }; + }; + + fragment@1 { + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-dacplus"; + i2s-controller = <&i2s>; + status = "okay"; + }; + }; + + fragment@2 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@3 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + pcm5122@4d { + #sound-dai-cells = <0>; + compatible = "ti,pcm5122"; + reg = <0x4d>; + clocks = <&dacpro_osc>; + status = "okay"; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts raspilinux/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,39 @@ +// Definitions for HiFiBerry Digi +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-digi"; + i2s-controller = <&i2s>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@2 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + wm8804@3b { + #sound-dai-cells = <0>; + compatible = "wlf,wm8804"; + reg = <0x3b>; + status = "okay"; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/hy28a-overlay.dts raspilinux/arch/arm/boot/dts/overlays/hy28a-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/hy28a-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/hy28a-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,87 @@ +/* + * Device Tree overlay for HY28A display + * + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + + spidev@0{ + status = "disabled"; + }; + + spidev@1{ + status = "disabled"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + hy28a_pins: hy28a_pins { + brcm,pins = <17 25 18>; + brcm,function = <0 1 1>; /* in out out */ + }; + }; + }; + + fragment@2 { + target = <&spi0>; + __overlay__ { + /* needed to avoid dtc warning */ + #address-cells = <1>; + #size-cells = <0>; + + hy28a: hy28a@0{ + compatible = "ilitek,ili9320"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hy28a_pins>; + + spi-max-frequency = <32000000>; + spi-cpol; + spi-cpha; + rotate = <270>; + bgr; + fps = <50>; + buswidth = <8>; + startbyte = <0x70>; + reset-gpios = <&gpio 25 0>; + led-gpios = <&gpio 18 1>; + debug = <0>; + }; + + hy28a_ts: hy28a-ts@1 { + compatible = "ti,ads7846"; + reg = <1>; + + spi-max-frequency = <2000000>; + interrupts = <17 2>; /* high-to-low edge triggered */ + interrupt-parent = <&gpio>; + pendown-gpio = <&gpio 17 0>; + ti,x-plate-ohms = /bits/ 16 <100>; + ti,pressure-max = /bits/ 16 <255>; + }; + }; + }; + __overrides__ { + speed = <&hy28a>,"spi-max-frequency:0"; + rotate = <&hy28a>,"rotate:0"; + fps = <&hy28a>,"fps:0"; + debug = <&hy28a>,"debug:0"; + xohms = <&hy28a_ts>,"ti,x-plate-ohms;0"; + resetgpio = <&hy28a>,"reset-gpios:4", + <&hy28a_pins>, "brcm,pins:1"; + ledgpio = <&hy28a>,"led-gpios:4", + <&hy28a_pins>, "brcm,pins:2"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/hy28b-overlay.dts raspilinux/arch/arm/boot/dts/overlays/hy28b-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/hy28b-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/hy28b-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,142 @@ +/* + * Device Tree overlay for HY28b display shield by Texy + * + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + + spidev@0{ + status = "disabled"; + }; + + spidev@1{ + status = "disabled"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + hy28b_pins: hy28b_pins { + brcm,pins = <17 25 18>; + brcm,function = <0 1 1>; /* in out out */ + }; + }; + }; + + fragment@2 { + target = <&spi0>; + __overlay__ { + /* needed to avoid dtc warning */ + #address-cells = <1>; + #size-cells = <0>; + + hy28b: hy28b@0{ + compatible = "ilitek,ili9325"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hy28b_pins>; + + spi-max-frequency = <48000000>; + spi-cpol; + spi-cpha; + rotate = <270>; + bgr; + fps = <50>; + buswidth = <8>; + startbyte = <0x70>; + reset-gpios = <&gpio 25 0>; + led-gpios = <&gpio 18 1>; + + gamma = "04 1F 4 7 7 0 7 7 6 0\n0F 00 1 7 4 0 0 0 6 7"; + + init = <0x10000e7 0x0010 + 0x1000000 0x0001 + 0x1000001 0x0100 + 0x1000002 0x0700 + 0x1000003 0x1030 + 0x1000004 0x0000 + 0x1000008 0x0207 + 0x1000009 0x0000 + 0x100000a 0x0000 + 0x100000c 0x0001 + 0x100000d 0x0000 + 0x100000f 0x0000 + 0x1000010 0x0000 + 0x1000011 0x0007 + 0x1000012 0x0000 + 0x1000013 0x0000 + 0x2000032 + 0x1000010 0x1590 + 0x1000011 0x0227 + 0x2000032 + 0x1000012 0x009c + 0x2000032 + 0x1000013 0x1900 + 0x1000029 0x0023 + 0x100002b 0x000e + 0x2000032 + 0x1000020 0x0000 + 0x1000021 0x0000 + 0x2000032 + 0x1000050 0x0000 + 0x1000051 0x00ef + 0x1000052 0x0000 + 0x1000053 0x013f + 0x1000060 0xa700 + 0x1000061 0x0001 + 0x100006a 0x0000 + 0x1000080 0x0000 + 0x1000081 0x0000 + 0x1000082 0x0000 + 0x1000083 0x0000 + 0x1000084 0x0000 + 0x1000085 0x0000 + 0x1000090 0x0010 + 0x1000092 0x0000 + 0x1000093 0x0003 + 0x1000095 0x0110 + 0x1000097 0x0000 + 0x1000098 0x0000 + 0x1000007 0x0133 + 0x1000020 0x0000 + 0x1000021 0x0000 + 0x2000064>; + debug = <0>; + }; + + hy28b_ts: hy28b-ts@1 { + compatible = "ti,ads7846"; + reg = <1>; + + spi-max-frequency = <2000000>; + interrupts = <17 2>; /* high-to-low edge triggered */ + interrupt-parent = <&gpio>; + pendown-gpio = <&gpio 17 0>; + ti,x-plate-ohms = /bits/ 16 <100>; + ti,pressure-max = /bits/ 16 <255>; + }; + }; + }; + __overrides__ { + speed = <&hy28b>,"spi-max-frequency:0"; + rotate = <&hy28b>,"rotate:0"; + fps = <&hy28b>,"fps:0"; + debug = <&hy28b>,"debug:0"; + xohms = <&hy28b_ts>,"ti,x-plate-ohms;0"; + resetgpio = <&hy28b>,"reset-gpios:4", + <&hy28b_pins>, "brcm,pins:1"; + ledgpio = <&hy28b>,"led-gpios:4", + <&hy28b_pins>, "brcm,pins:2"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts raspilinux/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,28 @@ +// Overlay for i2c_gpio bitbanging host bus. +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target-path = "/"; + __overlay__ { + i2c_gpio: i2c@0 { + compatible = "i2c-gpio"; + gpios = <&gpio 23 0 /* sda */ + &gpio 24 0 /* scl */ + >; + i2c-gpio,delay-us = <2>; /* ~100 kHz */ + #address-cells = <1>; + #size-cells = <0>; + }; + }; + }; + __overrides__ { + i2c_gpio_sda = <&i2c_gpio>,"gpios:4"; + i2c_gpio_scl = <&i2c_gpio>,"gpios:16"; + i2c_gpio_delay_us = <&i2c_gpio>,"i2c-gpio,delay-us:0"; + }; +}; + diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts raspilinux/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,55 @@ +// Definitions for several I2C based Real Time Clocks +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&i2c_arm>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + ds1307: ds1307@68 { + compatible = "maxim,ds1307"; + reg = <0x68>; + status = "disable"; + }; + mcp7941x: mcp7941x@6f { + compatible = "microchip,mcp7941x"; + reg = <0x6f>; + status = "disable"; + }; + ds3231: ds3231@68 { + compatible = "maxim,ds3231"; + reg = <0x68>; + status = "disable"; + }; + pcf2127: pcf2127@51 { + compatible = "nxp,pcf2127"; + reg = <0x51>; + status = "disable"; + }; + pcf8523: pcf8523@68 { + compatible = "nxp,pcf8523"; + reg = <0x68>; + status = "disable"; + }; + pcf8563: pcf8563@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + status = "disable"; + }; + }; + }; + __overrides__ { + ds1307 = <&ds1307>,"status"; + ds3231 = <&ds3231>,"status"; + mcp7941x = <&mcp7941x>,"status"; + pcf2127 = <&pcf2127>,"status"; + pcf8523 = <&pcf8523>,"status"; + pcf8563 = <&pcf8563>,"status"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts raspilinux/arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/{ + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&i2s>; + __overlay__ { + brcm,enable-mmap; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts raspilinux/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,39 @@ +// Definitions for IQaudIO DAC +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&sound>; + __overlay__ { + compatible = "iqaudio,iqaudio-dac"; + i2s-controller = <&i2s>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@2 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + pcm5122@4c { + #sound-dai-cells = <0>; + compatible = "ti,pcm5122"; + reg = <0x4c>; + status = "okay"; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts raspilinux/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,39 @@ +// Definitions for IQaudIO DAC+ +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&sound>; + __overlay__ { + compatible = "iqaudio,iqaudio-dac"; + i2s-controller = <&i2s>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@2 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + pcm5122@4c { + #sound-dai-cells = <0>; + compatible = "ti,pcm5122"; + reg = <0x4c>; + status = "okay"; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts raspilinux/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,57 @@ +// Definitions for lirc-rpi module +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target-path = "/"; + __overlay__ { + lirc_rpi: lirc_rpi { + compatible = "rpi,lirc-rpi"; + pinctrl-names = "default"; + pinctrl-0 = <&lirc_pins>; + status = "okay"; + + // Override autodetection of IR receiver circuit + // (0 = active high, 1 = active low, -1 = no override ) + rpi,sense = <0xffffffff>; + + // Software carrier + // (0 = off, 1 = on) + rpi,softcarrier = <1>; + + // Invert output + // (0 = off, 1 = on) + rpi,invert = <0>; + + // Enable debugging messages + // (0 = off, 1 = on) + rpi,debug = <0>; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + lirc_pins: lirc_pins { + brcm,pins = <17 18>; + brcm,function = <1 0>; // out in + brcm,pull = <0 1>; // off down + }; + }; + }; + + __overrides__ { + gpio_out_pin = <&lirc_pins>,"brcm,pins:0"; + gpio_in_pin = <&lirc_pins>,"brcm,pins:4"; + gpio_in_pull = <&lirc_pins>,"brcm,pull:4"; + + sense = <&lirc_rpi>,"rpi,sense:0"; + softcarrier = <&lirc_rpi>,"rpi,softcarrier:0"; + invert = <&lirc_rpi>,"rpi,invert:0"; + debug = <&lirc_rpi>,"rpi,debug:0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/Makefile raspilinux/arch/arm/boot/dts/overlays/Makefile --- linux-stable/arch/arm/boot/dts/overlays/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/Makefile 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,77 @@ +ifeq ($(CONFIG_OF),y) + +# Overlays for the Raspberry Pi platform + +ifeq ($(CONFIG_BCM2708_DT),y) + RPI_DT_OVERLAYS=y +endif +ifeq ($(CONFIG_BCM2709_DT),y) + RPI_DT_OVERLAYS=y +endif +ifeq ($(CONFIG_ARCH_BCM2835),y) + RPI_DT_OVERLAYS=y +endif + +dtb-$(RPI_DT_OVERLAYS) += ads7846-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += at86rf233-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += dht11-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += enc28j60-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += gpio-ir-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += gpio-poweroff-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += hifiberry-amp-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += hifiberry-dac-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += hifiberry-dacplus-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += hifiberry-digi-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += hy28a-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += hy28b-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += i2c-rtc-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += i2c-gpio-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += i2s-mmap-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += iqaudio-dac-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += iqaudio-dacplus-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += lirc-rpi-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += mcp2515-can0-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += mcp2515-can1-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += mmc-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += mz61581-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += piscreen-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += piscreen2r-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += pitft28-capacitive-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += pitft28-resistive-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += pwm-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += pwm-2chan-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += raspidac3-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += rpi-backlight-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += rpi-dac-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += rpi-ft5406-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += rpi-proto-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += rpi-sense-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += sdhost-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += sdio-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += smi-dev-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += smi-nand-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += smi-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += spi-bcm2708-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += spi-bcm2835-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += spi-dma-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += tinylcd35-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += uart1-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += vga666-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += w1-gpio-overlay.dtb +dtb-$(RPI_DT_OVERLAYS) += w1-gpio-pullup-overlay.dtb + +targets += dtbs dtbs_install +targets += $(dtb-y) + +endif + +always := $(dtb-y) +clean-files := *.dtb + +# Enable fixups to support overlays on BCM2708 platforms +ifeq ($(RPI_DT_OVERLAYS),y) + DTC_FLAGS ?= -@ +endif diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts raspilinux/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,69 @@ +/* + * Device tree overlay for mcp251x/can0 on spi0.0 + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; + /* disable spi-dev for spi0.0 */ + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + spidev@0{ + status = "disabled"; + }; + }; + }; + + /* the interrupt pin of the can-controller */ + fragment@1 { + target = <&gpio>; + __overlay__ { + can0_pins: can0_pins { + brcm,pins = <25>; + brcm,function = <0>; /* input */ + }; + }; + }; + + /* the clock/oscillator of the can-controller */ + fragment@2 { + target-path = "/clocks"; + __overlay__ { + /* external oscillator of mcp2515 on SPI0.0 */ + can0_osc: can0_osc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <16000000>; + }; + }; + }; + + /* the spi config of the can-controller itself binding everything together */ + fragment@3 { + target = <&spi0>; + __overlay__ { + /* needed to avoid dtc warning */ + #address-cells = <1>; + #size-cells = <0>; + can0: mcp2515@0 { + reg = <0>; + compatible = "microchip,mcp2515"; + pinctrl-names = "default"; + pinctrl-0 = <&can0_pins>; + spi-max-frequency = <10000000>; + interrupt-parent = <&gpio>; + interrupts = <25 0x2>; + clocks = <&can0_osc>; + }; + }; + }; + __overrides__ { + oscillator = <&can0_osc>,"clock-frequency:0"; + spimaxfrequency = <&can0>,"spi-max-frequency:0"; + interrupt = <&can0_pins>,"brcm,pins:0",<&can0>,"interrupts:0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts raspilinux/arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,69 @@ +/* + * Device tree overlay for mcp251x/can1 on spi0.1 edited by petit_miner + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; + /* disable spi-dev for spi0.1 */ + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + spidev@1{ + status = "disabled"; + }; + }; + }; + + /* the interrupt pin of the can-controller */ + fragment@1 { + target = <&gpio>; + __overlay__ { + can1_pins: can1_pins { + brcm,pins = <25>; + brcm,function = <0>; /* input */ + }; + }; + }; + + /* the clock/oscillator of the can-controller */ + fragment@2 { + target-path = "/clocks"; + __overlay__ { + /* external oscillator of mcp2515 on spi0.1 */ + can1_osc: can1_osc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <16000000>; + }; + }; + }; + + /* the spi config of the can-controller itself binding everything together */ + fragment@3 { + target = <&spi0>; + __overlay__ { + /* needed to avoid dtc warning */ + #address-cells = <1>; + #size-cells = <0>; + can1: mcp2515@1 { + reg = <1>; + compatible = "microchip,mcp2515"; + pinctrl-names = "default"; + pinctrl-0 = <&can1_pins>; + spi-max-frequency = <10000000>; + interrupt-parent = <&gpio>; + interrupts = <25 0x2>; + clocks = <&can1_osc>; + }; + }; + }; + __overrides__ { + oscillator = <&can1_osc>,"clock-frequency:0"; + spimaxfrequency = <&can1>,"spi-max-frequency:0"; + interrupt = <&can1_pins>,"brcm,pins:0",<&can1>,"interrupts:0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/mmc-overlay.dts raspilinux/arch/arm/boot/dts/overlays/mmc-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/mmc-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/mmc-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,39 @@ +/dts-v1/; +/plugin/; + +/{ + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&mmc>; + frag0: __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&mmc_pins>; + bus-width = <4>; + brcm,overclock-50 = <0>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + mmc_pins: mmc_pins { + brcm,pins = <48 49 50 51 52 53>; + brcm,function = <7>; /* alt3 */ + }; + }; + }; + + fragment@2 { + target = <&sdhost>; + __overlay__ { + status = "disabled"; + }; + }; + + __overrides__ { + overclock_50 = <&frag0>,"brcm,overclock-50:0"; + force_pio = <&frag0>,"brcm,force-pio?"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/mz61581-overlay.dts raspilinux/arch/arm/boot/dts/overlays/mz61581-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/mz61581-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/mz61581-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,111 @@ +/* + * Device Tree overlay for MZ61581-PI-EXT 2014.12.28 by Tontec + * + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + + spidev@0{ + status = "disabled"; + }; + + spidev@1{ + status = "disabled"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + mz61581_pins: mz61581_pins { + brcm,pins = <4 15 18 25>; + brcm,function = <0 1 1 1>; /* in out out out */ + }; + }; + }; + + fragment@2 { + target = <&spi0>; + __overlay__ { + /* needed to avoid dtc warning */ + #address-cells = <1>; + #size-cells = <0>; + + mz61581: mz61581@0{ + compatible = "samsung,s6d02a1"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&mz61581_pins>; + + spi-max-frequency = <128000000>; + spi-cpol; + spi-cpha; + + width = <320>; + height = <480>; + rotate = <270>; + bgr; + fps = <30>; + buswidth = <8>; + txbuflen = <32768>; + + reset-gpios = <&gpio 15 0>; + dc-gpios = <&gpio 25 0>; + led-gpios = <&gpio 18 0>; + + init = <0x10000b0 00 + 0x1000011 + 0x20000ff + 0x10000b3 0x02 0x00 0x00 0x00 + 0x10000c0 0x13 0x3b 0x00 0x02 0x00 0x01 0x00 0x43 + 0x10000c1 0x08 0x16 0x08 0x08 + 0x10000c4 0x11 0x07 0x03 0x03 + 0x10000c6 0x00 + 0x10000c8 0x03 0x03 0x13 0x5c 0x03 0x07 0x14 0x08 0x00 0x21 0x08 0x14 0x07 0x53 0x0c 0x13 0x03 0x03 0x21 0x00 + 0x1000035 0x00 + 0x1000036 0xa0 + 0x100003a 0x55 + 0x1000044 0x00 0x01 + 0x10000d0 0x07 0x07 0x1d 0x03 + 0x10000d1 0x03 0x30 0x10 + 0x10000d2 0x03 0x14 0x04 + 0x1000029 + 0x100002c>; + + /* This is a workaround to make sure the init sequence slows down and doesn't fail */ + debug = <3>; + }; + + mz61581_ts: mz61581_ts@1 { + compatible = "ti,ads7846"; + reg = <1>; + + spi-max-frequency = <2000000>; + interrupts = <4 2>; /* high-to-low edge triggered */ + interrupt-parent = <&gpio>; + pendown-gpio = <&gpio 4 0>; + + ti,x-plate-ohms = /bits/ 16 <60>; + ti,pressure-max = /bits/ 16 <255>; + }; + }; + }; + __overrides__ { + speed = <&mz61581>, "spi-max-frequency:0"; + rotate = <&mz61581>, "rotate:0"; + fps = <&mz61581>, "fps:0"; + txbuflen = <&mz61581>, "txbuflen:0"; + debug = <&mz61581>, "debug:0"; + xohms = <&mz61581_ts>,"ti,x-plate-ohms;0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/piscreen2r-overlay.dts raspilinux/arch/arm/boot/dts/overlays/piscreen2r-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/piscreen2r-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/piscreen2r-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,100 @@ + /* + * Device Tree overlay for PiScreen2 3.5" TFT with resistive touch by Ozzmaker.com + * + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + + spidev@0{ + status = "disabled"; + }; + + spidev@1{ + status = "disabled"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + piscreen2_pins: piscreen2_pins { + brcm,pins = <17 25 24 22>; + brcm,function = <0 1 1 1>; /* in out out out */ + }; + }; + }; + + fragment@2 { + target = <&spi0>; + __overlay__ { + /* needed to avoid dtc warning */ + #address-cells = <1>; + #size-cells = <0>; + + piscreen2: piscreen2@0{ + compatible = "ilitek,ili9486"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&piscreen2_pins>; + bgr; + spi-max-frequency = <64000000>; + rotate = <90>; + fps = <30>; + buswidth = <8>; + regwidth = <16>; + txbuflen = <32768>; + reset-gpios = <&gpio 25 0>; + dc-gpios = <&gpio 24 0>; + led-gpios = <&gpio 22 1>; + debug = <0>; + + init = <0x10000b0 0x00 + 0x1000011 + 0x20000ff + 0x100003a 0x55 + 0x1000036 0x28 + 0x10000c0 0x11 0x09 + 0x10000c1 0x41 + 0x10000c5 0x00 0x00 0x00 0x00 + 0x10000b6 0x00 0x02 + 0x10000f7 0xa9 0x51 0x2c 0x2 + 0x10000be 0x00 0x04 + 0x10000e9 0x00 + 0x1000011 + 0x1000029>; + + }; + + piscreen2_ts: piscreen2-ts@1 { + compatible = "ti,ads7846"; + reg = <1>; + + spi-max-frequency = <2000000>; + interrupts = <17 2>; /* high-to-low edge triggered */ + interrupt-parent = <&gpio>; + pendown-gpio = <&gpio 17 0>; + ti,swap-xy; + ti,x-plate-ohms = /bits/ 16 <100>; + ti,pressure-max = /bits/ 16 <255>; + }; + }; + }; + __overrides__ { + speed = <&piscreen2>,"spi-max-frequency:0"; + rotate = <&piscreen2>,"rotate:0"; + fps = <&piscreen2>,"fps:0"; + debug = <&piscreen2>,"debug:0"; + xohms = <&piscreen2_ts>,"ti,x-plate-ohms;0"; + }; +}; + diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/piscreen-overlay.dts raspilinux/arch/arm/boot/dts/overlays/piscreen-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/piscreen-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/piscreen-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,96 @@ +/* + * Device Tree overlay for PiScreen 3.5" display shield by Ozzmaker + * + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + + spidev@0{ + status = "disabled"; + }; + + spidev@1{ + status = "disabled"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + piscreen_pins: piscreen_pins { + brcm,pins = <17 25 24 22>; + brcm,function = <0 1 1 1>; /* in out out out */ + }; + }; + }; + + fragment@2 { + target = <&spi0>; + __overlay__ { + /* needed to avoid dtc warning */ + #address-cells = <1>; + #size-cells = <0>; + + piscreen: piscreen@0{ + compatible = "ilitek,ili9486"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&piscreen_pins>; + + spi-max-frequency = <24000000>; + rotate = <270>; + bgr; + fps = <30>; + buswidth = <8>; + regwidth = <16>; + reset-gpios = <&gpio 25 0>; + dc-gpios = <&gpio 24 0>; + led-gpios = <&gpio 22 1>; + debug = <0>; + + init = <0x10000b0 0x00 + 0x1000011 + 0x20000ff + 0x100003a 0x55 + 0x1000036 0x28 + 0x10000c2 0x44 + 0x10000c5 0x00 0x00 0x00 0x00 + 0x10000e0 0x0f 0x1f 0x1c 0x0c 0x0f 0x08 0x48 0x98 0x37 0x0a 0x13 0x04 0x11 0x0d 0x00 + 0x10000e1 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 + 0x10000e2 0x0f 0x32 0x2e 0x0b 0x0d 0x05 0x47 0x75 0x37 0x06 0x10 0x03 0x24 0x20 0x00 + 0x1000011 + 0x1000029>; + }; + + piscreen_ts: piscreen-ts@1 { + compatible = "ti,ads7846"; + reg = <1>; + + spi-max-frequency = <2000000>; + interrupts = <17 2>; /* high-to-low edge triggered */ + interrupt-parent = <&gpio>; + pendown-gpio = <&gpio 17 0>; + ti,swap-xy; + ti,x-plate-ohms = /bits/ 16 <100>; + ti,pressure-max = /bits/ 16 <255>; + }; + }; + }; + __overrides__ { + speed = <&piscreen>,"spi-max-frequency:0"; + rotate = <&piscreen>,"rotate:0"; + fps = <&piscreen>,"fps:0"; + debug = <&piscreen>,"debug:0"; + xohms = <&piscreen_ts>,"ti,x-plate-ohms;0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts raspilinux/arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/pitft28-capacitive-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,88 @@ +/* + * Device Tree overlay for Adafruit PiTFT 2.8" capacitive touch screen + * + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + + spidev@0{ + status = "disabled"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + pitft_pins: pitft_pins { + brcm,pins = <24 25>; + brcm,function = <0 1>; /* in out */ + brcm,pull = <2 0>; /* pullup none */ + }; + }; + }; + + fragment@2 { + target = <&spi0>; + __overlay__ { + /* needed to avoid dtc warning */ + #address-cells = <1>; + #size-cells = <0>; + + pitft: pitft@0{ + compatible = "ilitek,ili9340"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pitft_pins>; + + spi-max-frequency = <32000000>; + rotate = <90>; + fps = <25>; + bgr; + buswidth = <8>; + dc-gpios = <&gpio 25 0>; + debug = <0>; + }; + }; + }; + + fragment@3 { + target = <&i2c1>; + __overlay__ { + /* needed to avoid dtc warning */ + #address-cells = <1>; + #size-cells = <0>; + + ft6236: ft6236@38 { + compatible = "focaltech,ft6236"; + reg = <0x38>; + + interrupt-parent = <&gpio>; + interrupts = <24 2>; + touchscreen-size-x = <240>; + touchscreen-size-y = <320>; + }; + }; + }; + + __overrides__ { + speed = <&pitft>,"spi-max-frequency:0"; + rotate = <&pitft>,"rotate:0"; + fps = <&pitft>,"fps:0"; + debug = <&pitft>,"debug:0"; + touch-sizex = <&ft6236>,"touchscreen-size-x?"; + touch-sizey = <&ft6236>,"touchscreen-size-y?"; + touch-invx = <&ft6236>,"touchscreen-inverted-x?"; + touch-invy = <&ft6236>,"touchscreen-inverted-y?"; + touch-swapxy = <&ft6236>,"touchscreen-swapped-x-y?"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts raspilinux/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,115 @@ +/* + * Device Tree overlay for Adafruit PiTFT 2.8" resistive touch screen + * + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + + spidev@0{ + status = "disabled"; + }; + + spidev@1{ + status = "disabled"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + pitft_pins: pitft_pins { + brcm,pins = <24 25>; + brcm,function = <0 1>; /* in out */ + brcm,pull = <2 0>; /* pullup none */ + }; + }; + }; + + fragment@2 { + target = <&spi0>; + __overlay__ { + /* needed to avoid dtc warning */ + #address-cells = <1>; + #size-cells = <0>; + + pitft: pitft@0{ + compatible = "ilitek,ili9340"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pitft_pins>; + + spi-max-frequency = <32000000>; + rotate = <90>; + fps = <25>; + bgr; + buswidth = <8>; + dc-gpios = <&gpio 25 0>; + debug = <0>; + }; + + pitft_ts@1 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stmpe610"; + reg = <1>; + + spi-max-frequency = <500000>; + irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */ + interrupts = <24 2>; /* high-to-low edge triggered */ + interrupt-parent = <&gpio>; + interrupt-controller; + + stmpe_touchscreen { + compatible = "st,stmpe-ts"; + st,sample-time = <4>; + st,mod-12b = <1>; + st,ref-sel = <0>; + st,adc-freq = <2>; + st,ave-ctrl = <3>; + st,touch-det-delay = <4>; + st,settling = <2>; + st,fraction-z = <7>; + st,i-drive = <0>; + }; + + stmpe_gpio: stmpe_gpio { + #gpio-cells = <2>; + compatible = "st,stmpe-gpio"; + /* + * only GPIO2 is wired/available + * and it is wired to the backlight + */ + st,norequest-mask = <0x7b>; + }; + }; + }; + }; + + fragment@3 { + target-path = "/soc"; + __overlay__ { + backlight { + compatible = "gpio-backlight"; + gpios = <&stmpe_gpio 2 0>; + default-on; + }; + }; + }; + + __overrides__ { + speed = <&pitft>,"spi-max-frequency:0"; + rotate = <&pitft>,"rotate:0"; + fps = <&pitft>,"fps:0"; + debug = <&pitft>,"debug:0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts raspilinux/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/pps-gpio-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,34 @@ +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + fragment@0 { + target-path = "/"; + __overlay__ { + pps: pps { + compatible = "pps-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pps_pins>; + gpios = <&gpio 18 0>; + status = "okay"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + pps_pins: pps_pins { + brcm,pins = <18>; + brcm,function = <0>; // in + brcm,pull = <0>; // off + }; + }; + }; + + __overrides__ { + gpiopin = <&pps>,"gpios:4", + <&pps_pins>,"brcm,pins:0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/pwm-2chan-overlay.dts raspilinux/arch/arm/boot/dts/overlays/pwm-2chan-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/pwm-2chan-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/pwm-2chan-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,46 @@ +/dts-v1/; +/plugin/; + +/* +This is the 2-channel overlay - only use it if you need both channels. + +Legal pin,function combinations for each channel: + PWM0: 12,4(Alt0) 18,2(Alt5) 40,4(Alt0) 52,5(Alt1) + PWM1: 13,4(Alt0) 19,2(Alt5) 41,4(Alt0) 45,4(Alt0) 53,5(Alt1) + +N.B.: + 1) Pin 18 is the only one available on all platforms, and + it is the one used by the I2S audio interface. + Pins 12 and 13 might be better choices on an A+, B+ or Pi2. + 2) The onboard analogue audio output uses both PWM channels. + 3) So be careful mixing audio and PWM. +*/ + +/ { + fragment@0 { + target = <&gpio>; + __overlay__ { + pwm_pins: pwm_pins { + brcm,pins = <18 19>; + brcm,function = <2 2>; /* Alt5 */ + }; + }; + }; + + fragment@1 { + target = <&pwm>; + __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&pwm_pins>; + status = "okay"; + }; + }; + + __overrides__ { + pin = <&pwm_pins>,"brcm,pins:0"; + pin2 = <&pwm_pins>,"brcm,pins:4"; + func = <&pwm_pins>,"brcm,function:0"; + func2 = <&pwm_pins>,"brcm,function:4"; + clock = <&clk_pwm>,"clock-frequency:0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/pwm-overlay.dts raspilinux/arch/arm/boot/dts/overlays/pwm-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/pwm-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/pwm-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,42 @@ +/dts-v1/; +/plugin/; + +/* +Legal pin,function combinations for each channel: + PWM0: 12,4(Alt0) 18,2(Alt5) 40,4(Alt0) 52,5(Alt1) + PWM1: 13,4(Alt0) 19,2(Alt5) 41,4(Alt0) 45,4(Alt0) 53,5(Alt1) + +N.B.: + 1) Pin 18 is the only one available on all platforms, and + it is the one used by the I2S audio interface. + Pins 12 and 13 might be better choices on an A+, B+ or Pi2. + 2) The onboard analogue audio output uses both PWM channels. + 3) So be careful mixing audio and PWM. +*/ + +/ { + fragment@0 { + target = <&gpio>; + __overlay__ { + pwm_pins: pwm_pins { + brcm,pins = <18>; + brcm,function = <2>; /* Alt5 */ + }; + }; + }; + + fragment@1 { + target = <&pwm>; + __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&pwm_pins>; + status = "okay"; + }; + }; + + __overrides__ { + pin = <&pwm_pins>,"brcm,pins:0"; + func = <&pwm_pins>,"brcm,function:0"; + clock = <&clk_pwm>,"clock-frequency:0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/raspidac3-overlay.dts raspilinux/arch/arm/boot/dts/overlays/raspidac3-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/raspidac3-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/raspidac3-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,45 @@ +// Definitions for RaspiDACv3 +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&sound>; + __overlay__ { + compatible = "jg,raspidacv3"; + i2s-controller = <&i2s>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@2 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + pcm5122@4c { + #sound-dai-cells = <0>; + compatible = "ti,pcm5122"; + reg = <0x4c>; + status = "okay"; + }; + + tpa6130a2: tpa6130a2@60 { + compatible = "ti,tpa6130a2"; + reg = <0x60>; + status = "okay"; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/README raspilinux/arch/arm/boot/dts/overlays/README --- linux-stable/arch/arm/boot/dts/overlays/README 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/README 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,742 @@ +Introduction +============ + +This directory contains Device Tree overlays. Device Tree makes it possible +to support many hardware configurations with a single kernel and without the +need to explicitly load or blacklist kernel modules. Note that this isn't a +"pure" Device Tree configuration (c.f. MACH_BCM2835) - some on-board devices +are still configured by the board support code, but the intention is to +eventually reach that goal. + +On Raspberry Pi, Device Tree usage is controlled from /boot/config.txt. By +default, the Raspberry Pi kernel boots with device tree enabled. You can +completely disable DT usage (for now) by adding: + + device_tree= + +to your config.txt, which should cause your Pi to revert to the old way of +doing things after a reboot. + +In /boot you will find a .dtb for each base platform. This describes the +hardware that is part of the Raspberry Pi board. The loader (start.elf and its +siblings) selects the .dtb file appropriate for the platform by name, and reads +it into memory. At this point, all of the optional interfaces (i2c, i2s, spi) +are disabled, but they can be enabled using Device Tree parameters: + + dtparam=i2c=on,i2s=on,spi=on + +However, this shouldn't be necessary in many use cases because loading an +overlay that requires one of those interfaces will cause it to be enabled +automatically, and it is advisable to only enable interfaces if they are +needed. + +Configuring additional, optional hardware is done using Device Tree overlays +(see below). + +raspi-config +============ + +The Advanced Options section of the raspi-config utility can enable and disable +Device Tree use, as well as toggling the I2C and SPI interfaces. Note that it +is possible to both enable an interface and blacklist the driver, if for some +reason you should want to defer the loading. + +Modules +======= + +As well as describing the hardware, Device Tree also gives enough information +to allow suitable driver modules to be located and loaded, with the corollary +that unneeded modules are not loaded. As a result it should be possible to +remove lines from /etc/modules, and /etc/modprobe.d/raspi-blacklist.conf can +have its contents deleted (or commented out). + +Using Overlays +============== + +Overlays are loaded using the "dtoverlay" directive. As an example, consider the +popular lirc-rpi module, the Linux Infrared Remote Control driver. In the +pre-DT world this would be loaded from /etc/modules, with an explicit +"modprobe lirc-rpi" command, or programmatically by lircd. With DT enabled, +this becomes a line in config.txt: + + dtoverlay=lirc-rpi + +This causes the file /boot/overlays/lirc-rpi-overlay.dtb to be loaded. By +default it will use GPIOs 17 (out) and 18 (in), but this can be modified using +DT parameters: + + dtoverlay=lirc-rpi,gpio_out_pin=17,gpio_in_pin=13 + +Parameters always have default values, although in some cases (e.g. "w1-gpio") +it is necessary to provided multiple overlays in order to get the desired +behaviour. See the list of overlays below for a description of the parameters +and their defaults. + +The Overlay and Parameter Reference +=================================== + +N.B. When editing this file, please preserve the indentation levels to make it +simple to parse programmatically. NO HARD TABS. + + +Name: +Info: Configures the base Raspberry Pi hardware +Load: +Params: + audio Set to "on" to enable the onboard ALSA audio + interface (default "off") + + i2c_arm Set to "on" to enable the ARM's i2c interface + (default "off") + + i2c_vc Set to "on" to enable the i2c interface + usually reserved for the VideoCore processor + (default "off") + + i2c An alias for i2c_arm + + i2c_arm_baudrate Set the baudrate of the ARM's i2c interface + (default "100000") + + i2c_vc_baudrate Set the baudrate of the VideoCore i2c interface + (default "100000") + + i2c_baudrate An alias for i2c_arm_baudrate + + i2s Set to "on" to enable the i2s interface + (default "off") + + spi Set to "on" to enable the spi interfaces + (default "off") + + random Set to "on" to enable the hardware random + number generator (default "off") + + uart0 Set to "off" to disable uart0 (default "on") + + watchdog Set to "on" to enable the hardware watchdog + (default "off") + + act_led_trigger Choose which activity the LED tracks. + Use "heartbeat" for a nice load indicator. + (default "mmc") + + act_led_activelow Set to "on" to invert the sense of the LED + (default "off") + + act_led_gpio Set which GPIO to use for the activity LED + (in case you want to connect it to an external + device) + (default "16" on a non-Plus board, "47" on a + Plus or Pi 2) + + pwr_led_trigger + pwr_led_activelow + pwr_led_gpio + As for act_led_*, but using the PWR LED. + Not available on Model A/B boards. + + N.B. It is recommended to only enable those interfaces that are needed. + Leaving all interfaces enabled can lead to unwanted behaviour (i2c_vc + interfering with Pi Camera, I2S and SPI hogging GPIO pins, etc.) + Note also that i2c, i2c_arm and i2c_vc are aliases for the physical + interfaces i2c0 and i2c1. Use of the numeric variants is still possible + but deprecated because the ARM/VC assignments differ between board + revisions. The same board-specific mapping applies to i2c_baudrate, + and the other i2c baudrate parameters. + + +Name: ads7846 +Info: ADS7846 Touch controller +Load: dtoverlay=ads7846,= +Params: cs SPI bus Chip Select (default 1) + speed SPI bus speed (default 2MHz, max 3.25MHz) + penirq GPIO used for PENIRQ. REQUIRED + penirq_pull Set GPIO pull (default 0=none, 2=pullup) + swapxy Swap x and y axis + xmin Minimum value on the X axis (default 0) + ymin Minimum value on the Y axis (default 0) + xmax Maximum value on the X axis (default 4095) + ymax Maximum value on the Y axis (default 4095) + pmin Minimum reported pressure value (default 0) + pmax Maximum reported pressure value (default 65535) + xohms Touchpanel sensitivity (X-plate resistance) + (default 400) + + penirq is required and usually xohms (60-100) has to be set as well. + Apart from that, pmax (255) and swapxy are also common. + The rest of the calibration can be done with xinput-calibrator. + See: github.com/notro/fbtft/wiki/FBTFT-on-Raspian + Device Tree binding document: + www.kernel.org/doc/Documentation/devicetree/bindings/input/ads7846.txt + + +Name: at86rf233 +Info: Configures the Atmel AT86RF233 802.15.4 low-power WPAN transceiver, + connected to spi0.0 +Load: dtoverlay=at86rf233,= +Params: interrupt GPIO used for INT (default 23) + reset GPIO used for Reset (default 24) + sleep GPIO used for Sleep (default 25) + speed SPI bus speed in Hz (default 6000000) + trim Fine tuning of the internal capacitance + arrays (0=+0pF, 15=+4.5pF, default 15) + + +Name: bmp085_i2c-sensor +Info: Configures the BMP085/BMP180 digital barometric pressure and temperature + sensors from Bosch Sensortec +Load: dtoverlay=bmp085_i2c-sensor +Params: + + +Name: dht11 +Info: Overlay for the DHT11/DHT21/DHT22 humidity/temperature sensors + Also sometimes found with the part number(s) AM230x. +Load: dtoverlay=dht11,= +Params: gpiopin GPIO connected to the sensor's DATA output. + (default 4) + + +[ The ds1307-rtc overlay has been deleted. See i2c-rtc. ] + + +Name: enc28j60 +Info: Overlay for the Microchip ENC28J60 Ethernet Controller (SPI) +Load: dtoverlay=enc28j60,= +Params: int_pin GPIO used for INT (default 25) + + speed SPI bus speed (default 12000000) + + +Name: gpio-ir +Info: Use GPIO pin as rc-core style infrared receiver input. The rc-core- + based gpio_ir_recv driver maps received keys directly to a + /dev/input/event* device, all decoding is done by the kernel - LIRC is + not required! The key mapping and other decoding parameters can be + configured by "ir-keytable" tool. +Load: dtoverlay=gpio-ir,= +Params: gpio_pin Input pin number. Default is 18. + + gpio_pull Desired pull-up/down state (off, down, up) + Default is "down". + + rc-map-name Default rc keymap (can also be changed by + ir-keytable), defaults to "rc-rc6-mce" + + +Name: gpio-poweroff +Info: Drives a GPIO high or low on reboot +Load: dtoverlay=gpio-poweroff,= +Params: gpiopin GPIO for signalling (default 26) + + active_low Set if the power control device requires a + high->low transition to trigger a power-down. + Note that this will require the support of a + custom dt-blob.bin to prevent a power-down + during the boot process, and that a reboot + will also cause the pin to go low. + + +Name: hifiberry-amp +Info: Configures the HifiBerry Amp and Amp+ audio cards +Load: dtoverlay=hifiberry-amp +Params: + + +Name: hifiberry-dac +Info: Configures the HifiBerry DAC audio card +Load: dtoverlay=hifiberry-dac +Params: + + +Name: hifiberry-dacplus +Info: Configures the HifiBerry DAC+ audio card +Load: dtoverlay=hifiberry-dacplus +Params: + + +Name: hifiberry-digi +Info: Configures the HifiBerry Digi audio card +Load: dtoverlay=hifiberry-digi +Params: + + +Name: hy28a +Info: HY28A - 2.8" TFT LCD Display Module by HAOYU Electronics + Default values match Texy's display shield +Load: dtoverlay=hy28a,= +Params: speed Display SPI bus speed + + rotate Display rotation {0,90,180,270} + + fps Delay between frame updates + + debug Debug output level {0-7} + + xohms Touchpanel sensitivity (X-plate resistance) + + resetgpio GPIO used to reset controller + + ledgpio GPIO used to control backlight + + +Name: hy28b +Info: HY28B - 2.8" TFT LCD Display Module by HAOYU Electronics + Default values match Texy's display shield +Load: dtoverlay=hy28b,= +Params: speed Display SPI bus speed + + rotate Display rotation {0,90,180,270} + + fps Delay between frame updates + + debug Debug output level {0-7} + + xohms Touchpanel sensitivity (X-plate resistance) + + resetgpio GPIO used to reset controller + + ledgpio GPIO used to control backlight + + +Name: i2c-gpio +Info: Adds support for software i2c controller on gpio pins +Load: dtoverlay=i2c-gpio,= +Params: i2c_gpio_sda GPIO used for I2C data (default "23") + + i2c_gpio_scl GPIO used for I2C clock (default "24") + + i2c_gpio_delay_us Clock delay in microseconds + (default "2" = ~100kHz) + + +Name: i2c-rtc +Info: Adds support for a number of I2C Real Time Clock devices +Load: dtoverlay=i2c-rtc,= +Params: ds1307 Select the DS1307 device + + ds3231 Select the DS3231 device + + mcp7941x Select the MCP7941x device + + pcf2127 Select the PCF2127 device + + pcf8523 Select the PCF8523 device + + pcf8563 Select the PCF8563 device + + +Name: i2s-mmap +Info: Enables mmap support in the bcm2708-i2s driver +Load: dtoverlay=i2s-mmap +Params: + + +Name: iqaudio-dac +Info: Configures the IQaudio DAC audio card +Load: dtoverlay=iqaudio-dac +Params: + + +Name: iqaudio-dacplus +Info: Configures the IQaudio DAC+ audio card +Load: dtoverlay=iqaudio-dacplus +Params: + + +Name: lirc-rpi +Info: Configures lirc-rpi (Linux Infrared Remote Control for Raspberry Pi) + Consult the module documentation for more details. +Load: dtoverlay=lirc-rpi,= +Params: gpio_out_pin GPIO for output (default "17") + + gpio_in_pin GPIO for input (default "18") + + gpio_in_pull Pull up/down/off on the input pin + (default "down") + + sense Override the IR receive auto-detection logic: + "0" = force active-high + "1" = force active-low + "-1" = use auto-detection + (default "-1") + + softcarrier Turn the software carrier "on" or "off" + (default "on") + + invert "on" = invert the output pin (default "off") + + debug "on" = enable additional debug messages + (default "off") + + +Name: mcp2515-can0 +Info: Configures the MCP2515 CAN controller on spi0.0 +Load: dtoverlay=mcp2515-can0,= +Params: oscillator Clock frequency for the CAN controller (Hz) + + spimaxfrequency Maximum SPI frequence (Hz) + + interrupt GPIO for interrupt signal + + +Name: mcp2515-can1 +Info: Configures the MCP2515 CAN controller on spi0.1 +Load: dtoverlay=mcp2515-can1,= +Params: oscillator Clock frequency for the CAN controller (Hz) + + spimaxfrequency Maximum SPI frequence (Hz) + + interrupt GPIO for interrupt signal + + +Name: mmc +Info: Selects the bcm2835-mmc SD/MMC driver, optionally with overclock +Load: dtoverlay=mmc,= +Params: overclock_50 Clock (in MHz) to use when the MMC framework + requests 50MHz + force_pio Disable DMA support + + +Name: mz61581 +Info: MZ61581 display by Tontec +Load: dtoverlay=mz61581,= +Params: speed Display SPI bus speed + + rotate Display rotation {0,90,180,270} + + fps Delay between frame updates + + txbuflen Transmit buffer length (default 32768) + + debug Debug output level {0-7} + + xohms Touchpanel sensitivity (X-plate resistance) + + +[ The pcf2127-rtc overlay has been deleted. See i2c-rtc. ] + + +[ The pcf8523-rtc overlay has been deleted. See i2c-rtc. ] + + +[ The pcf8563-rtc overlay has been deleted. See i2c-rtc. ] + + +Name: piscreen +Info: PiScreen display by OzzMaker.com +Load: dtoverlay=piscreen,= +Params: speed Display SPI bus speed + + rotate Display rotation {0,90,180,270} + + fps Delay between frame updates + + debug Debug output level {0-7} + + xohms Touchpanel sensitivity (X-plate resistance) + + +Name: piscreen2r +Info: PiScreen 2 with resistive TP display by OzzMaker.com +Load: dtoverlay=piscreen2r,= +Params: speed Display SPI bus speed + + rotate Display rotation {0,90,180,270} + + fps Delay between frame updates + + debug Debug output level {0-7} + + xohms Touchpanel sensitivity (X-plate resistance) + + +Name: pitft28-capacitive +Info: Adafruit PiTFT 2.8" capacitive touch screen +Load: dtoverlay=pitft28-capacitive,= +Params: speed Display SPI bus speed + + rotate Display rotation {0,90,180,270} + + fps Delay between frame updates + + debug Debug output level {0-7} + + touch-sizex Touchscreen size x (default 240) + + touch-sizey Touchscreen size y (default 320) + + touch-invx Touchscreen inverted x axis + + touch-invy Touchscreen inverted y axis + + touch-swapxy Touchscreen swapped x y axis + + +Name: pitft28-resistive +Info: Adafruit PiTFT 2.8" resistive touch screen +Load: dtoverlay=pitft28-resistive,= +Params: speed Display SPI bus speed + + rotate Display rotation {0,90,180,270} + + fps Delay between frame updates + + debug Debug output level {0-7} + + +Name: pps-gpio +Info: Configures the pps-gpio (pulse-per-second time signal via GPIO). +Load: dtoverlay=pps-gpio,= +Params: gpiopin Input GPIO (default "18") + + +Name: pwm +Info: Configures a single PWM channel + Legal pin,function combinations for each channel: + PWM0: 12,4(Alt0) 18,2(Alt5) 40,4(Alt0) 52,5(Alt1) + PWM1: 13,4(Alt0) 19,2(Alt5) 41,4(Alt0) 45,4(Alt0) 53,5(Alt1) + N.B.: + 1) Pin 18 is the only one available on all platforms, and + it is the one used by the I2S audio interface. + Pins 12 and 13 might be better choices on an A+, B+ or Pi2. + 2) The onboard analogue audio output uses both PWM channels. + 3) So be careful mixing audio and PWM. + 4) Currently the clock must have been enabled and configured + by other means. +Load: dtoverlay=pwm,= +Params: pin Output pin (default 18) - see table + func Pin function (default 2 = Alt5) - see above + clock PWM clock frequency (informational) + + +Name: pwm-2chan +Info: Configures both PWM channels + Legal pin,function combinations for each channel: + PWM0: 12,4(Alt0) 18,2(Alt5) 40,4(Alt0) 52,5(Alt1) + PWM1: 13,4(Alt0) 19,2(Alt5) 41,4(Alt0) 45,4(Alt0) 53,5(Alt1) + N.B.: + 1) Pin 18 is the only one available on all platforms, and + it is the one used by the I2S audio interface. + Pins 12 and 13 might be better choices on an A+, B+ or Pi2. + 2) The onboard analogue audio output uses both PWM channels. + 3) So be careful mixing audio and PWM. + 4) Currently the clock must have been enabled and configured + by other means. +Load: dtoverlay=pwm-2chan,= +Params: pin Output pin (default 18) - see table + pin2 Output pin for other channel (default 19) + func Pin function (default 2 = Alt5) - see above + func2 Function for pin2 (default 2 = Alt5) + clock PWM clock frequency (informational) + + +Name: raspidac3 +Info: Configures the RaspiDAV Rev.3x audio card +Load: dtoverlay=raspidac3 +Params: + + +Name: rpi-backlight +Info: Raspberry Pi official display backlight driver +Load: dtoverlay=rpi-backlight +Params: + + +Name: rpi-dac +Info: Configures the RPi DAC audio card +Load: dtoverlay=rpi-dac +Params: + + +Name: rpi-display +Info: RPi-Display - 2.8" Touch Display by Watterott +Load: dtoverlay=rpi-display,= +Params: speed Display SPI bus speed + + rotate Display rotation {0,90,180,270} + + fps Delay between frame updates + + debug Debug output level {0-7} + + xohms Touchpanel sensitivity (X-plate resistance) + + +Name: rpi-ft5406 +Info: Official Raspberry Pi display touchscreen +Load: dtoverlay=rpi-ft5406 +Params: + + +Name: rpi-proto +Info: Configures the RPi Proto audio card +Load: dtoverlay=rpi-proto +Params: + + +Name: rpi-sense +Info: Raspberry Pi Sense HAT +Load: dtoverlay=rpi-sense +Params: + + +Name: sdhost +Info: Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock +Load: dtoverlay=sdhost,= +Params: overclock_50 Clock (in MHz) to use when the MMC framework + requests 50MHz + + force_pio Disable DMA support (default off) + + pio_limit Number of blocks above which to use DMA + (default 1) + + debug Enable debug output (default off) + + +Name: sdio +Info: Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock, + and enables SDIO via GPIOs 22-27. +Load: dtoverlay=sdio,= +Params: overclock_50 Clock (in MHz) to use when the MMC framework + requests 50MHz + + force_pio Disable DMA support (default off) + + pio_limit Number of blocks above which to use DMA + (default 1) + + debug Enable debug output (default off) + + poll_once Disable SDIO-device polling every second + (default on: polling once at boot-time) + + +Name: smi +Info: Enables the Secondary Memory Interface peripheral. Uses GPIOs 2-25! +Load: dtoverlay=smi +Params: + + +Name: smi-dev +Info: Enables the userspace interface for the SMI driver +Load: dtoverlay=smi-dev +Params: + + +Name: smi-nand +Info: Enables access to NAND flash via the SMI interface +Load: dtoverlay=smi-nand +Params: + + +Name: spi-bcm2708 +Info: Selects the bcm2708-spi SPI driver +Load: dtoverlay=spi-bcm2708 +Params: + + +Name: spi-bcm2835 +Info: Selects the bcm2835-spi SPI driver +Load: dtoverlay=spi-bcm2835 +Params: + + +Name: spi-dma +Info: enables dma modes for spi-bcm2835 +Load: dtoverlay=spi-dma +Params: + + +Name: tinylcd35 +Info: 3.5" Color TFT Display by www.tinylcd.com + Options: Touch, RTC, keypad +Load: dtoverlay=tinylcd35,= +Params: speed Display SPI bus speed + + rotate Display rotation {0,90,180,270} + + fps Delay between frame updates + + debug Debug output level {0-7} + + touch Enable touch panel + + touchgpio Touch controller IRQ GPIO + + xohms Touchpanel: Resistance of X-plate in ohms + + rtc-pcf PCF8563 Real Time Clock + + rtc-ds DS1307 Real Time Clock + + keypad Enable keypad + + Examples: + Display with touchpanel, PCF8563 RTC and keypad: + dtoverlay=tinylcd35,touch,rtc-pcf,keypad + Old touch display: + dtoverlay=tinylcd35,touch,touchgpio=3 + + +Name: uart1 +Info: Enable uart1 in place of uart0 +Load: dtoverlay=uart1,= +Params: txd1_pin GPIO pin for TXD1 (14, 32 or 40 - default 14) + + rxd1_pin GPIO pin for RXD1 (15, 33 or 41 - default 15) + + +Name: vga666 +Info: Overlay for the Fen Logic VGA666 board + This uses GPIOs 2-21 (so no I2C), and activates the output 2-3 seconds + after the kernel has started. +Load: dtoverlay=vga666 +Params: + + +Name: w1-gpio +Info: Configures the w1-gpio Onewire interface module. + Use this overlay if you *don't* need a GPIO to drive an external pullup. +Load: dtoverlay=w1-gpio,= +Params: gpiopin GPIO for I/O (default "4") + + pullup Non-zero, "on", or "y" to enable the parasitic + power (2-wire, power-on-data) feature + + +Name: w1-gpio-pullup +Info: Configures the w1-gpio Onewire interface module. + Use this overlay if you *do* need a GPIO to drive an external pullup. +Load: dtoverlay=w1-gpio-pullup,= +Params: gpiopin GPIO for I/O (default "4") + + pullup Non-zero, "on", or "y" to enable the parasitic + power (2-wire, power-on-data) feature + + extpullup GPIO for external pullup (default "5") + + +Troubleshooting +=============== + +If you are experiencing problems that you think are DT-related, enable DT +diagnostic output by adding this to /boot/config.txt: + + dtdebug=on + +and rebooting. Then run: + + sudo vcdbg log msg + +and look for relevant messages. + +Further reading +=============== + +This is only meant to be a quick introduction to the subject of Device Tree on +Raspberry Pi. There is a more complete explanation here: + +http://www.raspberrypi.org/documentation/configuration/device-tree.md diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts raspilinux/arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,21 @@ +/* + * Devicetree overlay for mailbox-driven Raspberry Pi DSI Display + * backlight controller + */ +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target-path = "/"; + __overlay__ { + rpi_backlight: rpi_backlight { + compatible = "raspberrypi,rpi-backlight"; + firmware = <&firmware>; + status = "okay"; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts raspilinux/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,34 @@ +// Definitions for RPi DAC +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&sound>; + __overlay__ { + compatible = "rpi,rpi-dac"; + i2s-controller = <&i2s>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@2 { + target-path = "/"; + __overlay__ { + pcm1794a-codec { + #sound-dai-cells = <0>; + compatible = "ti,pcm1794a"; + status = "okay"; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/rpi-display-overlay.dts raspilinux/arch/arm/boot/dts/overlays/rpi-display-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/rpi-display-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/rpi-display-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,82 @@ +/* + * Device Tree overlay for rpi-display by Watterott + * + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + + spidev@0{ + status = "disabled"; + }; + + spidev@1{ + status = "disabled"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + rpi_display_pins: rpi_display_pins { + brcm,pins = <18 23 24 25>; + brcm,function = <1 1 1 0>; /* out out out in */ + brcm,pull = <0 0 0 2>; /* - - - up */ + }; + }; + }; + + fragment@2 { + target = <&spi0>; + __overlay__ { + /* needed to avoid dtc warning */ + #address-cells = <1>; + #size-cells = <0>; + + rpidisplay: rpi-display@0{ + compatible = "ilitek,ili9341"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&rpi_display_pins>; + + spi-max-frequency = <32000000>; + rotate = <270>; + bgr; + fps = <30>; + buswidth = <8>; + reset-gpios = <&gpio 23 0>; + dc-gpios = <&gpio 24 0>; + led-gpios = <&gpio 18 1>; + debug = <0>; + }; + + rpidisplay_ts: rpi-display-ts@1 { + compatible = "ti,ads7846"; + reg = <1>; + + spi-max-frequency = <2000000>; + interrupts = <25 2>; /* high-to-low edge triggered */ + interrupt-parent = <&gpio>; + pendown-gpio = <&gpio 25 0>; + ti,x-plate-ohms = /bits/ 16 <60>; + ti,pressure-max = /bits/ 16 <255>; + }; + }; + }; + __overrides__ { + speed = <&rpidisplay>,"spi-max-frequency:0"; + rotate = <&rpidisplay>,"rotate:0"; + fps = <&rpidisplay>,"fps:0"; + debug = <&rpidisplay>,"debug:0"; + xohms = <&rpidisplay_ts>,"ti,x-plate-ohms;0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts raspilinux/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,17 @@ +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target-path = "/"; + __overlay__ { + rpi_ft5406: rpi_ft5406 { + compatible = "rpi,rpi-ft5406"; + firmware = <&firmware>; + status = "okay"; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts raspilinux/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/rpi-proto-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,39 @@ +// Definitions for Rpi-Proto +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&sound>; + __overlay__ { + compatible = "rpi,rpi-proto"; + i2s-controller = <&i2s>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@2 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + wm8731@1a { + #sound-dai-cells = <0>; + compatible = "wlf,wm8731"; + reg = <0x1a>; + status = "okay"; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts raspilinux/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/rpi-sense-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,47 @@ +// rpi-sense HAT +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708", "brcm,bcm2709"; + + fragment@0 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + rpi-sense@46 { + compatible = "rpi,rpi-sense"; + reg = <0x46>; + keys-int-gpios = <&gpio 23 1>; + status = "okay"; + }; + + lsm9ds1-magn@1c { + compatible = "st,lsm9ds1-magn"; + reg = <0x1c>; + status = "okay"; + }; + + lsm9ds1-accel6a { + compatible = "st,lsm9ds1-accel"; + reg = <0x6a>; + status = "okay"; + }; + + lps25h-press@5c { + compatible = "st,lps25h-press"; + reg = <0x5c>; + status = "okay"; + }; + + hts221-humid@5f { + compatible = "st,hts221-humid"; + reg = <0x5f>; + status = "okay"; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/sdhost-overlay.dts raspilinux/arch/arm/boot/dts/overlays/sdhost-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/sdhost-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/sdhost-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,29 @@ +/dts-v1/; +/plugin/; + +/{ + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&mmc>; + __overlay__ { + status = "disabled"; + }; + }; + + fragment@1 { + target = <&sdhost>; + frag1: __overlay__ { + brcm,overclock-50 = <0>; + brcm,pio-limit = <1>; + status = "okay"; + }; + }; + + __overrides__ { + overclock_50 = <&frag1>,"brcm,overclock-50:0"; + force_pio = <&frag1>,"brcm,force-pio?"; + pio_limit = <&frag1>,"brcm,pio-limit:0"; + debug = <&frag1>,"brcm,debug?"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/sdio-overlay.dts raspilinux/arch/arm/boot/dts/overlays/sdio-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/sdio-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/sdio-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,32 @@ +/* Enable SDIO from MMC interface via GPIOs 22-27. Includes sdhost overlay. */ + +/include/ "sdhost-overlay.dts" + +/{ + compatible = "brcm,bcm2708"; + + fragment@3 { + target = <&mmc>; + sdio_mmc: __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&sdio_pins>; + non-removable; + status = "okay"; + }; + }; + + fragment@4 { + target = <&gpio>; + __overlay__ { + sdio_pins: sdio_pins { + brcm,pins = <22 23 24 25 26 27>; + brcm,function = <7 7 7 7 7 7>; /* ALT3 = SD1 */ + brcm,pull = <0 2 2 2 2 2>; + }; + }; + }; + + __overrides__ { + poll_once = <&sdio_mmc>,"non-removable?"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/smi-dev-overlay.dts raspilinux/arch/arm/boot/dts/overlays/smi-dev-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/smi-dev-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/smi-dev-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,18 @@ +// Description: Overlay to enable character device interface for SMI. +// Author: Luke Wren + +/dts-v1/; +/plugin/; + +/{ + fragment@0 { + target = <&soc>; + __overlay__ { + smi_dev { + compatible = "brcm,bcm2835-smi-dev"; + smi_handle = <&smi>; + status = "okay"; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/smi-nand-overlay.dts raspilinux/arch/arm/boot/dts/overlays/smi-nand-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/smi-nand-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/smi-nand-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,69 @@ +// Description: Overlay to enable NAND flash through +// the secondary memory interface +// Author: Luke Wren + +/dts-v1/; +/plugin/; + +/{ + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&smi>; + __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&smi_pins>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&soc>; + __overlay__ { + #address-cells = <1>; + #size-cells = <1>; + + nand: flash@0 { + compatible = "brcm,bcm2835-smi-nand"; + smi_handle = <&smi>; + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + + partition@0 { + label = "stage2"; + // 128k + reg = <0 0x20000>; + read-only; + }; + partition@1 { + label = "firmware"; + // 16M + reg = <0x20000 0x1000000>; + read-only; + }; + partition@2 { + label = "root"; + // 2G (will need to use 64 bit for >=4G) + reg = <0x1020000 0x80000000>; + }; + }; + }; + }; + + fragment@2 { + target = <&gpio>; + __overlay__ { + smi_pins: smi_pins { + brcm,pins = <0 1 2 3 4 5 6 7 8 9 10 11 + 12 13 14 15>; + /* Alt 1: SMI */ + brcm,function = <5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5>; + /* /CS, /WE and /OE are pulled high, as they are + generally active low signals */ + brcm,pull = <2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0>; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/smi-overlay.dts raspilinux/arch/arm/boot/dts/overlays/smi-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/smi-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/smi-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,37 @@ +// Description: Overlay to enable the secondary memory interface peripheral +// Author: Luke Wren + +/dts-v1/; +/plugin/; + +/{ + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&smi>; + __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&smi_pins>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + smi_pins: smi_pins { + /* Don't configure the top two address bits, as + these are already used as ID_SD and ID_SC */ + brcm,pins = <2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 24 25>; + /* Alt 0: SMI */ + brcm,function = <5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 + 5 5 5 5 5 5 5 5 5>; + /* /CS, /WE and /OE are pulled high, as they are + generally active low signals */ + brcm,pull = <2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0>; + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts raspilinux/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/spi-bcm2708-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,18 @@ +/* + * Device tree overlay for spi-bcm2835 + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; + /* setting up compatiblity to allow loading the spi-bcm2835 driver */ + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + compatible = "brcm,bcm2708-spi"; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts raspilinux/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/spi-bcm2835-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,18 @@ +/* + * Device tree overlay for spi-bcm2835 + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; + /* setting up compatiblity to allow loading the spi-bcm2835 driver */ + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + compatible = "brcm,bcm2835-spi"; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/spi-dma-overlay.dts raspilinux/arch/arm/boot/dts/overlays/spi-dma-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/spi-dma-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/spi-dma-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,20 @@ +/* + * Device tree overlay for spi-bcm2835 to allow dma + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + dmas = <&dma 6>, <&dma 7>; + dma-names = "tx", "rx"; + }; + }; + }; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts raspilinux/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/tinylcd35-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,216 @@ +/* + * tinylcd35-overlay.dts + * + * ------------------------------------------------- + * www.tinlylcd.com + * ------------------------------------------------- + * Device---Driver-----BUS GPIO's + * display tinylcd35 spi0.0 25 24 18 + * touch ads7846 spi0.1 5 + * rtc ds1307 i2c1-0068 + * rtc pcf8563 i2c1-0051 + * keypad gpio-keys --------- 17 22 27 23 28 + * + * + * TinyLCD.com 3.5 inch TFT + * + * Version 001 + * 5/3/2015 -- Noralf Trønnes Initial Device tree framework + * 10/3/2015 -- tinylcd@gmail.com added ds1307 support. + * + */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; + + fragment@0 { + target = <&spi0>; + __overlay__ { + status = "okay"; + + spidev@0{ + status = "disabled"; + }; + + spidev@1{ + status = "disabled"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + tinylcd35_pins: tinylcd35_pins { + brcm,pins = <25 24 18>; + brcm,function = <1>; /* out */ + }; + tinylcd35_ts_pins: tinylcd35_ts_pins { + brcm,pins = <5>; + brcm,function = <0>; /* in */ + }; + keypad_pins: keypad_pins { + brcm,pins = <4 17 22 23 27>; + brcm,function = <0>; /* in */ + brcm,pull = <1>; /* down */ + }; + }; + }; + + fragment@2 { + target = <&spi0>; + __overlay__ { + /* needed to avoid dtc warning */ + #address-cells = <1>; + #size-cells = <0>; + + tinylcd35: tinylcd35@0{ + compatible = "neosec,tinylcd"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&tinylcd35_pins>, + <&tinylcd35_ts_pins>; + + spi-max-frequency = <48000000>; + rotate = <270>; + fps = <20>; + bgr; + buswidth = <8>; + reset-gpios = <&gpio 25 0>; + dc-gpios = <&gpio 24 0>; + led-gpios = <&gpio 18 1>; + debug = <0>; + + init = <0x10000B0 0x80 + 0x10000C0 0x0A 0x0A + 0x10000C1 0x01 0x01 + 0x10000C2 0x33 + 0x10000C5 0x00 0x42 0x80 + 0x10000B1 0xD0 0x11 + 0x10000B4 0x02 + 0x10000B6 0x00 0x22 0x3B + 0x10000B7 0x07 + 0x1000036 0x58 + 0x10000F0 0x36 0xA5 0xD3 + 0x10000E5 0x80 + 0x10000E5 0x01 + 0x10000B3 0x00 + 0x10000E5 0x00 + 0x10000F0 0x36 0xA5 0x53 + 0x10000E0 0x00 0x35 0x33 0x00 0x00 0x00 0x00 0x35 0x33 0x00 0x00 0x00 + 0x100003A 0x55 + 0x1000011 + 0x2000001 + 0x1000029>; + }; + + tinylcd35_ts: tinylcd35_ts@1 { + compatible = "ti,ads7846"; + reg = <1>; + status = "disabled"; + + spi-max-frequency = <2000000>; + interrupts = <5 2>; /* high-to-low edge triggered */ + interrupt-parent = <&gpio>; + pendown-gpio = <&gpio 5 0>; + ti,x-plate-ohms = /bits/ 16 <100>; + ti,pressure-max = /bits/ 16 <255>; + }; + }; + }; + + /* RTC */ + + fragment@3 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + + pcf8563: pcf8563@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + status = "disabled"; + }; + }; + }; + + fragment@4 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + + ds1307: ds1307@68 { + compatible = "maxim,ds1307"; + reg = <0x68>; + status = "disabled"; + }; + }; + }; + + /* + * Values for input event code is found under the + * 'Keys and buttons' heading in include/uapi/linux/input.h + */ + fragment@5 { + target-path = "/soc"; + __overlay__ { + keypad: keypad { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&keypad_pins>; + status = "disabled"; + autorepeat; + + button@17 { + label = "GPIO KEY_UP"; + linux,code = <103>; + gpios = <&gpio 17 0>; + }; + button@22 { + label = "GPIO KEY_DOWN"; + linux,code = <108>; + gpios = <&gpio 22 0>; + }; + button@27 { + label = "GPIO KEY_LEFT"; + linux,code = <105>; + gpios = <&gpio 27 0>; + }; + button@23 { + label = "GPIO KEY_RIGHT"; + linux,code = <106>; + gpios = <&gpio 23 0>; + }; + button@4 { + label = "GPIO KEY_ENTER"; + linux,code = <28>; + gpios = <&gpio 4 0>; + }; + }; + }; + }; + + __overrides__ { + speed = <&tinylcd35>,"spi-max-frequency:0"; + rotate = <&tinylcd35>,"rotate:0"; + fps = <&tinylcd35>,"fps:0"; + debug = <&tinylcd35>,"debug:0"; + touch = <&tinylcd35_ts>,"status"; + touchgpio = <&tinylcd35_ts_pins>,"brcm,pins:0", + <&tinylcd35_ts>,"interrupts:0", + <&tinylcd35_ts>,"pendown-gpio:4"; + xohms = <&tinylcd35_ts>,"ti,x-plate-ohms;0"; + rtc-pcf = <&i2c1>,"status", + <&pcf8563>,"status"; + rtc-ds = <&i2c1>,"status", + <&ds1307>,"status"; + keypad = <&keypad>,"status"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/uart1-overlay.dts raspilinux/arch/arm/boot/dts/overlays/uart1-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/uart1-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/uart1-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,38 @@ +/dts-v1/; +/plugin/; + +/{ + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&uart1>; + __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + uart1_pins: uart1_pins { + brcm,pins = <14 15>; + brcm,function = <2>; /* alt5 */ + brcm,pull = <0 2>; + }; + }; + }; + + fragment@2 { + target-path = "/chosen"; + __overlay__ { + bootargs = "8250.nr_uarts=1"; + }; + }; + + __overrides__ { + txd1_pin = <&uart1_pins>,"brcm,pins:0"; + rxd1_pin = <&uart1_pins>,"brcm,pins:4"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/vga666-overlay.dts raspilinux/arch/arm/boot/dts/overlays/vga666-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/vga666-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/vga666-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,30 @@ +/dts-v1/; +/plugin/; + +/{ + compatible = "brcm,bcm2708"; + + // There is no VGA driver module, but we need a platform device + // node (that doesn't already use pinctrl) to hang the pinctrl + // reference on - leds will do + + fragment@0 { + target = <&leds>; + __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&vga666_pins>; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + vga666_pins: vga666_pins { + brcm,pins = <2 3 4 5 6 7 8 9 10 11 12 + 13 14 15 16 17 18 19 20 21>; + brcm,function = <6>; /* alt2 */ + brcm,pull = <0>; /* no pull */ + }; + }; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts raspilinux/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/w1-gpio-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,39 @@ +// Definitions for w1-gpio module (without external pullup) +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target-path = "/"; + __overlay__ { + + w1: onewire@0 { + compatible = "w1-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&w1_pins>; + gpios = <&gpio 4 0>; + rpi,parasitic-power = <0>; + status = "okay"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + w1_pins: w1_pins { + brcm,pins = <4>; + brcm,function = <0>; // in (initially) + brcm,pull = <0>; // off + }; + }; + }; + + __overrides__ { + gpiopin = <&w1>,"gpios:4", + <&w1_pins>,"brcm,pins:0"; + pullup = <&w1>,"rpi,parasitic-power:0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts raspilinux/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts --- linux-stable/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/boot/dts/overlays/w1-gpio-pullup-overlay.dts 2015-12-26 19:08:30.264748820 +0100 @@ -0,0 +1,41 @@ +// Definitions for w1-gpio module (with external pullup) +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target-path = "/"; + __overlay__ { + + w1: onewire@0 { + compatible = "w1-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&w1_pins>; + gpios = <&gpio 4 0>, <&gpio 5 1>; + rpi,parasitic-power = <0>; + status = "okay"; + }; + }; + }; + + fragment@1 { + target = <&gpio>; + __overlay__ { + w1_pins: w1_pins { + brcm,pins = <4 5>; + brcm,function = <0 1>; // in out + brcm,pull = <0 0>; // off off + }; + }; + }; + + __overrides__ { + gpiopin = <&w1>,"gpios:4", + <&w1_pins>,"brcm,pins:0"; + extpullup = <&w1>,"gpios:16", + <&w1_pins>,"brcm,pins:4"; + pullup = <&w1>,"rpi,parasitic-power:0"; + }; +}; diff -Nur '--exclude=.git' linux-stable/arch/arm/configs/bcm2709_defconfig raspilinux/arch/arm/configs/bcm2709_defconfig --- linux-stable/arch/arm/configs/bcm2709_defconfig 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/configs/bcm2709_defconfig 2015-12-26 19:08:30.284746955 +0100 @@ -0,0 +1,1259 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0 +CONFIG_LOCALVERSION="-v7" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_FHANDLE=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=m +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_MEMCG=y +CONFIG_BLK_CGROUP=y +CONFIG_NAMESPACES=y +CONFIG_SCHED_AUTOGROUP=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EMBEDDED=y +# CONFIG_COMPAT_BRK is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y +CONFIG_JUMP_LABEL=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y +CONFIG_CFQ_GROUP_IOSCHED=y +CONFIG_ARCH_BCM2709=y +CONFIG_BCM2709_DT=y +# CONFIG_CACHE_L2X0 is not set +CONFIG_SMP=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_VMSPLIT_2G=y +CONFIG_PREEMPT_VOLUNTARY=y +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_CLEANCACHE=y +CONFIG_FRONTSWAP=y +CONFIG_CMA=y +CONFIG_ZSMALLOC=m +CONFIG_PGTABLE_MAPPING=y +CONFIG_UACCESS_WITH_MEMCPY=y +CONFIG_SECCOMP=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_BINFMT_MISC=m +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IPGRE=m +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_LRO=m +CONFIG_INET_DIAG=m +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 +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NETFILTER_XT_SET=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_PE_SIP=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_IP6_NF_TARGET_NPT=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_SCTP_COOKIE_HMAC_SHA1=y +CONFIG_ATM=m +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 +CONFIG_ATALK=m +CONFIG_6LOWPAN=m +CONFIG_IEEE802154=m +CONFIG_IEEE802154_6LOWPAN=m +CONFIG_MAC802154=m +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_CHOKE=m +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_SCH_PLUG=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_CGROUP=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_IPSET=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_ACT_CSUM=m +CONFIG_BATMAN_ADV=m +CONFIG_OPENVSWITCH=m +CONFIG_NET_PKTGEN=m +CONFIG_HAMRADIO=y +CONFIG_AX25=m +CONFIG_NETROM=m +CONFIG_ROSE=m +CONFIG_MKISS=m +CONFIG_6PACK=m +CONFIG_BPQETHER=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +CONFIG_YAM=m +CONFIG_CAN=m +CONFIG_CAN_VCAN=m +CONFIG_CAN_MCP251X=m +CONFIG_IRDA=m +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +CONFIG_IRTTY_SIR=m +CONFIG_KINGSUN_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KS959_DONGLE=m +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_6LOWPAN=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_ATH3K=m +CONFIG_BT_WILINK=m +CONFIG_MAC80211=m +CONFIG_MAC80211_MESH=y +CONFIG_WIMAX=m +CONFIG_RFKILL=m +CONFIG_RFKILL_INPUT=y +CONFIG_NET_9P=m +CONFIG_NFC=m +CONFIG_NFC_PN533=m +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=5 +CONFIG_MTD=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_NAND=m +CONFIG_MTD_UBI=m +CONFIG_ZRAM=m +CONFIG_ZRAM_LZ4_COMPRESS=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_DRBD=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_ATA_OVER_ETH=m +CONFIG_EEPROM_AT24=m +CONFIG_TI_ST=m +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_CHR_DEV_SG=m +CONFIG_SCSI_ISCSI_ATTRS=y +CONFIG_ISCSI_TCP=m +CONFIG_ISCSI_BOOT_SYSFS=m +CONFIG_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_THIN_PROVISIONING=m +CONFIG_DM_MIRROR=m +CONFIG_DM_LOG_USERSPACE=m +CONFIG_DM_RAID=m +CONFIG_DM_ZERO=m +CONFIG_DM_DELAY=m +CONFIG_NETDEVICES=y +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_IFB=m +CONFIG_MACVLAN=m +CONFIG_NETCONSOLE=m +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_ENC28J60=m +CONFIG_MDIO_BITBANG=m +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOATM=m +CONFIG_PPPOE=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +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 +CONFIG_USB_NET_HUAWEI_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SR9700=m +CONFIG_USB_NET_SR9800=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=y +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_HSO=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_LIBERTAS_THINFIRM=m +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m +CONFIG_USB_ZD1201=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8187=m +CONFIG_MAC80211_HWSIM=m +CONFIG_ATH_CARDS=m +CONFIG_ATH9K=m +CONFIG_ATH9K_HTC=m +CONFIG_CARL9170=m +CONFIG_ATH6KL=m +CONFIG_ATH6KL_USB=m +CONFIG_AR5523=m +CONFIG_B43=m +# CONFIG_B43_PHY_N is not set +CONFIG_B43LEGACY=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_USB=y +CONFIG_HOSTAP=m +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +CONFIG_RT2X00=m +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_WL_MEDIATEK=y +CONFIG_MT7601U=m +CONFIG_RTL8192CU=m +CONFIG_ZD1211RW=m +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_WIMAX_I2400M_USB=m +CONFIG_IEEE802154_AT86RF230=m +CONFIG_IEEE802154_MRF24J40=m +CONFIG_IEEE802154_CC2520=m +CONFIG_INPUT_POLLDEV=m +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=m +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_RPISENSE=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_EGALAX=m +CONFIG_TOUCHSCREEN_FT6236=m +CONFIG_TOUCHSCREEN_RPI_FT5406=m +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_TOUCHSCREEN_STMPE=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AD714X=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_YEALINK=m +CONFIG_INPUT_CM109=m +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +CONFIG_INPUT_ADXL34X=m +CONFIG_INPUT_CMA3000=m +CONFIG_SERIO=m +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_DMA is not set +CONFIG_SERIAL_8250_NR_UARTS=1 +CONFIG_SERIAL_8250_RUNTIME_UARTS=0 +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_TTY_PRINTK=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_BCM2835=m +CONFIG_HW_RANDOM_BCM2708=m +CONFIG_RAW_DRIVER=y +CONFIG_BRCM_CHAR_DRIVERS=y +CONFIG_BCM_VC_CMA=y +CONFIG_BCM_VCIO=y +CONFIG_BCM_VC_SM=y +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_BCM2708=m +CONFIG_I2C_GPIO=m +CONFIG_SPI=y +CONFIG_SPI_BCM2835=m +CONFIG_SPI_BCM2708=m +CONFIG_SPI_SPIDEV=y +CONFIG_PPS=m +CONFIG_PPS_CLIENT_LDISC=m +CONFIG_PPS_CLIENT_GPIO=m +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_ARIZONA=m +CONFIG_GPIO_STMPE=y +CONFIG_W1=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_MASTER_DS1WM=m +CONFIG_W1_MASTER_GPIO=m +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2408=m +CONFIG_W1_SLAVE_DS2413=m +CONFIG_W1_SLAVE_DS2406=m +CONFIG_W1_SLAVE_DS2423=m +CONFIG_W1_SLAVE_DS2431=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2760=m +CONFIG_W1_SLAVE_DS2780=m +CONFIG_W1_SLAVE_DS2781=m +CONFIG_W1_SLAVE_DS28E04=m +CONFIG_W1_SLAVE_BQ27000=m +CONFIG_BATTERY_DS2760=m +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_HWMON=m +CONFIG_SENSORS_SHT21=m +CONFIG_SENSORS_SHTC1=m +CONFIG_THERMAL=y +CONFIG_THERMAL_BCM2835=y +CONFIG_WATCHDOG=y +CONFIG_BCM2708_WDT=m +CONFIG_BCM2835_WDT=m +CONFIG_UCB1400_CORE=m +CONFIG_MFD_STMPE=y +CONFIG_STMPE_SPI=y +CONFIG_MFD_ARIZONA_I2C=m +CONFIG_MFD_ARIZONA_SPI=m +CONFIG_MFD_WM5102=y +CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_RC_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_LIRC=m +CONFIG_RC_DEVICES=y +CONFIG_RC_ATI_REMOTE=m +CONFIG_IR_IMON=m +CONFIG_IR_MCEUSB=m +CONFIG_IR_REDRAT3=m +CONFIG_IR_STREAMZAP=m +CONFIG_IR_IGUANA=m +CONFIG_IR_TTUSBIR=m +CONFIG_RC_LOOPBACK=m +CONFIG_IR_GPIO_CIR=m +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_M5602=m +CONFIG_USB_STV06XX=m +CONFIG_USB_GL860=m +CONFIG_USB_GSPCA_BENQ=m +CONFIG_USB_GSPCA_CONEX=m +CONFIG_USB_GSPCA_CPIA1=m +CONFIG_USB_GSPCA_DTCS033=m +CONFIG_USB_GSPCA_ETOMS=m +CONFIG_USB_GSPCA_FINEPIX=m +CONFIG_USB_GSPCA_JEILINJ=m +CONFIG_USB_GSPCA_JL2005BCD=m +CONFIG_USB_GSPCA_KINECT=m +CONFIG_USB_GSPCA_KONICA=m +CONFIG_USB_GSPCA_MARS=m +CONFIG_USB_GSPCA_MR97310A=m +CONFIG_USB_GSPCA_NW80X=m +CONFIG_USB_GSPCA_OV519=m +CONFIG_USB_GSPCA_OV534=m +CONFIG_USB_GSPCA_OV534_9=m +CONFIG_USB_GSPCA_PAC207=m +CONFIG_USB_GSPCA_PAC7302=m +CONFIG_USB_GSPCA_PAC7311=m +CONFIG_USB_GSPCA_SE401=m +CONFIG_USB_GSPCA_SN9C2028=m +CONFIG_USB_GSPCA_SN9C20X=m +CONFIG_USB_GSPCA_SONIXB=m +CONFIG_USB_GSPCA_SONIXJ=m +CONFIG_USB_GSPCA_SPCA500=m +CONFIG_USB_GSPCA_SPCA501=m +CONFIG_USB_GSPCA_SPCA505=m +CONFIG_USB_GSPCA_SPCA506=m +CONFIG_USB_GSPCA_SPCA508=m +CONFIG_USB_GSPCA_SPCA561=m +CONFIG_USB_GSPCA_SPCA1528=m +CONFIG_USB_GSPCA_SQ905=m +CONFIG_USB_GSPCA_SQ905C=m +CONFIG_USB_GSPCA_SQ930X=m +CONFIG_USB_GSPCA_STK014=m +CONFIG_USB_GSPCA_STK1135=m +CONFIG_USB_GSPCA_STV0680=m +CONFIG_USB_GSPCA_SUNPLUS=m +CONFIG_USB_GSPCA_T613=m +CONFIG_USB_GSPCA_TOPRO=m +CONFIG_USB_GSPCA_TV8532=m +CONFIG_USB_GSPCA_VC032X=m +CONFIG_USB_GSPCA_VICAM=m +CONFIG_USB_GSPCA_XIRLINK_CIT=m +CONFIG_USB_GSPCA_ZC3XX=m +CONFIG_USB_PWC=m +CONFIG_VIDEO_CPIA2=m +CONFIG_USB_ZR364XX=m +CONFIG_USB_STKWEBCAM=m +CONFIG_USB_S2255=m +CONFIG_VIDEO_USBTV=m +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_STK1160_COMMON=m +CONFIG_VIDEO_STK1160_AC97=y +CONFIG_VIDEO_GO7007=m +CONFIG_VIDEO_GO7007_USB=m +CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_AU0828_RC=y +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_ALSA=m +CONFIG_VIDEO_CX231XX_DVB=m +CONFIG_VIDEO_TM6000=m +CONFIG_VIDEO_TM6000_ALSA=m +CONFIG_VIDEO_TM6000_DVB=m +CONFIG_DVB_USB=m +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_PCTV452E=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_CINERGY_T2=m +CONFIG_DVB_USB_DTV5100=m +CONFIG_DVB_USB_FRIIO=m +CONFIG_DVB_USB_AZ6027=m +CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_V2=m +CONFIG_DVB_USB_AF9015=m +CONFIG_DVB_USB_AF9035=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_AZ6007=m +CONFIG_DVB_USB_CE6230=m +CONFIG_DVB_USB_EC168=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_LME2510=m +CONFIG_DVB_USB_MXL111SF=m +CONFIG_DVB_USB_RTL28XXU=m +CONFIG_DVB_USB_DVBSKY=m +CONFIG_SMS_USB_DRV=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +CONFIG_DVB_AS102=m +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_EM28XX_V4L2=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_VIDEO_BCM2835=y +CONFIG_VIDEO_BCM2835_MMAL=m +CONFIG_RADIO_SI470X=y +CONFIG_USB_SI470X=m +CONFIG_I2C_SI470X=m +CONFIG_RADIO_SI4713=m +CONFIG_I2C_SI4713=m +CONFIG_USB_MR800=m +CONFIG_USB_DSBR=m +CONFIG_RADIO_SHARK=m +CONFIG_RADIO_SHARK2=m +CONFIG_USB_KEENE=m +CONFIG_USB_MA901=m +CONFIG_RADIO_TEA5764=m +CONFIG_RADIO_SAA7706H=m +CONFIG_RADIO_TEF6862=m +CONFIG_RADIO_WL1273=m +CONFIG_RADIO_WL128X=m +# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set +CONFIG_VIDEO_UDA1342=m +CONFIG_VIDEO_SONY_BTF_MPX=m +CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_TW2804=m +CONFIG_VIDEO_TW9903=m +CONFIG_VIDEO_TW9906=m +CONFIG_VIDEO_OV7640=m +CONFIG_VIDEO_MT9V011=m +CONFIG_FB=y +CONFIG_FB_BCM2708=y +CONFIG_FB_UDL=m +CONFIG_FB_SSD1307=m +CONFIG_FB_RPISENSE=m +# CONFIG_BACKLIGHT_GENERIC is not set +CONFIG_BACKLIGHT_RPI=m +CONFIG_BACKLIGHT_GPIO=m +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_SOUND=y +CONFIG_SND=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=m +CONFIG_SND_DUMMY=m +CONFIG_SND_ALOOP=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m +CONFIG_SND_BCM2835=m +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_6FIRE=m +CONFIG_SND_SOC=m +CONFIG_SND_BCM2708_SOC_I2S=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m +CONFIG_SND_BCM2708_SOC_RPI_DAC=m +CONFIG_SND_BCM2708_SOC_RPI_PROTO=m +CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m +CONFIG_SND_BCM2708_SOC_RASPIDAC3=m +CONFIG_SND_SOC_ADAU1701=m +CONFIG_SND_SOC_WM8804_I2C=m +CONFIG_SND_SIMPLE_CARD=m +CONFIG_SOUND_PRIME=m +CONFIG_HIDRAW=y +CONFIG_UHID=m +CONFIG_HID_A4TECH=m +CONFIG_HID_ACRUX=m +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_HID_EMS_FF=m +CONFIG_HID_ELECOM=m +CONFIG_HID_ELO=m +CONFIG_HID_EZKEY=m +CONFIG_HID_HOLTEK=m +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=m +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +CONFIG_HID_GYRATION=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LCPOWER=m +CONFIG_HID_LOGITECH=m +CONFIG_HID_MAGICMOUSE=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NTRIG=m +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_GREENASIA=m +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_THINGM=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_HID_WACOM=m +CONFIG_HID_WIIMOTE=m +CONFIG_HID_XINMO=m +CONFIG_HID_ZEROPLUS=m +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 +CONFIG_USB_PRINTER=m +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_REALTEK=m +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +CONFIG_USB_STORAGE_ENE_UB6250=m +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +CONFIG_USBIP_CORE=m +CONFIG_USBIP_VHCI_HCD=m +CONFIG_USBIP_HOST=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=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_SAFE=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_DEBUG=m +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_SEVSEG=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +CONFIG_USB_TEST=m +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_YUREX=m +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BCM2835=y +CONFIG_MMC_BCM2835_DMA=y +CONFIG_MMC_BCM2835_SDHOST=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SPI=m +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_CAMERA=m +CONFIG_LEDS_TRIGGER_INPUT=y +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 +CONFIG_RTC_DRV_DS3232=m +CONFIG_RTC_DRV_MAX6900=m +CONFIG_RTC_DRV_RS5C372=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_ISL12022=m +CONFIG_RTC_DRV_ISL12057=m +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_PCF2127=m +CONFIG_RTC_DRV_PCF8523=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_M41T80=m +CONFIG_RTC_DRV_BQ32K=m +CONFIG_RTC_DRV_S35390A=m +CONFIG_RTC_DRV_FM3130=m +CONFIG_RTC_DRV_RX8581=m +CONFIG_RTC_DRV_RX8025=m +CONFIG_RTC_DRV_EM3027=m +CONFIG_RTC_DRV_RV3029C2=m +CONFIG_RTC_DRV_M41T93=m +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_R9701=m +CONFIG_RTC_DRV_RS5C348=m +CONFIG_RTC_DRV_DS3234=m +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_RX4581=m +CONFIG_DMADEVICES=y +CONFIG_DMA_BCM2708=y +CONFIG_UIO=m +CONFIG_UIO_PDRV_GENIRQ=m +CONFIG_STAGING=y +CONFIG_PRISM2_USB=m +CONFIG_R8712U=m +CONFIG_R8188EU=m +CONFIG_R8723AU=m +CONFIG_VT6656=m +CONFIG_SPEAKUP=m +CONFIG_SPEAKUP_SYNTH_SOFT=m +CONFIG_STAGING_MEDIA=y +CONFIG_LIRC_STAGING=y +CONFIG_LIRC_IMON=m +CONFIG_LIRC_RPI=m +CONFIG_LIRC_SASEM=m +CONFIG_LIRC_SERIAL=m +CONFIG_FB_TFT=m +CONFIG_FB_TFT_AGM1264K_FL=m +CONFIG_FB_TFT_BD663474=m +CONFIG_FB_TFT_HX8340BN=m +CONFIG_FB_TFT_HX8347D=m +CONFIG_FB_TFT_HX8353D=m +CONFIG_FB_TFT_ILI9163=m +CONFIG_FB_TFT_ILI9320=m +CONFIG_FB_TFT_ILI9325=m +CONFIG_FB_TFT_ILI9340=m +CONFIG_FB_TFT_ILI9341=m +CONFIG_FB_TFT_ILI9481=m +CONFIG_FB_TFT_ILI9486=m +CONFIG_FB_TFT_PCD8544=m +CONFIG_FB_TFT_RA8875=m +CONFIG_FB_TFT_S6D02A1=m +CONFIG_FB_TFT_S6D1121=m +CONFIG_FB_TFT_SSD1289=m +CONFIG_FB_TFT_SSD1306=m +CONFIG_FB_TFT_SSD1331=m +CONFIG_FB_TFT_SSD1351=m +CONFIG_FB_TFT_ST7735R=m +CONFIG_FB_TFT_TINYLCD=m +CONFIG_FB_TFT_TLS8204=m +CONFIG_FB_TFT_UC1701=m +CONFIG_FB_TFT_UPD161704=m +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m +CONFIG_MAILBOX=y +CONFIG_BCM2835_MBOX=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXTCON=m +CONFIG_EXTCON_ARIZONA=m +CONFIG_IIO=m +CONFIG_IIO_BUFFER=y +CONFIG_IIO_BUFFER_CB=y +CONFIG_IIO_KFIFO_BUF=m +CONFIG_MCP320X=m +CONFIG_DHT11=m +CONFIG_PWM_BCM2835=m +CONFIG_RASPBERRYPI_FIRMWARE=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +CONFIG_JFS_STATISTICS=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +CONFIG_GFS2_FS=m +CONFIG_OCFS2_FS=m +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_NILFS2_FS=m +CONFIG_F2FS_FS=y +CONFIG_FANOTIFY=y +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=m +CONFIG_CUSE=m +CONFIG_OVERLAY_FS=m +CONFIG_FSCACHE=y +CONFIG_FSCACHE_STATS=y +CONFIG_FSCACHE_HISTOGRAM=y +CONFIG_CACHEFILES=y +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +CONFIG_NTFS_FS=m +CONFIG_NTFS_RW=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y +CONFIG_ECRYPT_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_SUMMARY=y +CONFIG_UBIFS_FS=m +CONFIG_SQUASHFS=m +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_SWAP=y +CONFIG_ROOT_NFS=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFSD=m +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_CIFS_ACL=y +CONFIG_CIFS_DFS_UPCALL=y +CONFIG_CIFS_SMB2=y +CONFIG_CIFS_FSCACHE=y +CONFIG_9P_FS=m +CONFIG_9P_FS_POSIX_ACL=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_DLM=m +CONFIG_PRINTK_TIME=y +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_TIMER_STATS=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_SCHED_TRACER=y +CONFIG_STACK_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y +# CONFIG_KPROBE_EVENT is not set +CONFIG_FUNCTION_PROFILER=y +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y +CONFIG_KDB_KEYBOARD=y +CONFIG_CRYPTO_USER=m +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTS=m +CONFIG_CRYPTO_XTS=m +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_USER_API_SKCIPHER=m +# CONFIG_CRYPTO_HW is not set +CONFIG_ARM_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM_NEON=m +CONFIG_CRYPTO_SHA512_ARM_NEON=m +CONFIG_CRYPTO_AES_ARM_BS=m +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y diff -Nur '--exclude=.git' linux-stable/arch/arm/configs/bcm2835_defconfig raspilinux/arch/arm/configs/bcm2835_defconfig --- linux-stable/arch/arm/configs/bcm2835_defconfig 2015-12-26 20:38:42.794785307 +0100 +++ raspilinux/arch/arm/configs/bcm2835_defconfig 2015-12-26 19:08:30.284746955 +0100 @@ -1,105 +1,1075 @@ # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y CONFIG_FHANDLE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=m +CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=18 CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y -CONFIG_RESOURCE_COUNTERS=y +CONFIG_MEMCG=y CONFIG_CGROUP_PERF=y CONFIG_CFS_BANDWIDTH=y CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_CGROUP=y CONFIG_NAMESPACES=y CONFIG_SCHED_AUTOGROUP=y -CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y -CONFIG_RD_BZIP2=y -CONFIG_RD_LZMA=y -CONFIG_RD_XZ=y -CONFIG_RD_LZO=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y -CONFIG_OPROFILE=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y CONFIG_JUMP_LABEL=y +CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y +CONFIG_CFQ_GROUP_IOSCHED=y CONFIG_ARCH_MULTI_V6=y # CONFIG_ARCH_MULTI_V7 is not set CONFIG_ARCH_BCM=y CONFIG_ARCH_BCM2835=y -CONFIG_PREEMPT_VOLUNTARY=y +CONFIG_PREEMPT=y CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y CONFIG_KSM=y CONFIG_CLEANCACHE=y +CONFIG_FRONTSWAP=y +CONFIG_CMA=y +CONFIG_UACCESS_WITH_MEMCPY=y CONFIG_SECCOMP=y -CONFIG_CC_STACKPROTECTOR=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_KEXEC=y CONFIG_CRASH_DUMP=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_VFP=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_MISC=m # CONFIG_SUSPEND is not set CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IPGRE=m +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_LRO=m +CONFIG_INET_DIAG=m +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 +CONFIG_IPV6_PIMSM_V2=y CONFIG_NETWORK_SECMARK=y CONFIG_NETFILTER=y -CONFIG_CFG80211=y -CONFIG_MAC80211=y +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NETFILTER_XT_SET=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_PE_SIP=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_IP6_NF_TARGET_NPT=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_SCTP_COOKIE_HMAC_SHA1=y +CONFIG_ATM=m +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 +CONFIG_ATALK=m +CONFIG_6LOWPAN=m +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_CHOKE=m +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_SCH_PLUG=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_CGROUP=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_IPSET=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_ACT_CSUM=m +CONFIG_BATMAN_ADV=m +CONFIG_OPENVSWITCH=m +CONFIG_NET_PKTGEN=m +CONFIG_HAMRADIO=y +CONFIG_AX25=m +CONFIG_NETROM=m +CONFIG_ROSE=m +CONFIG_MKISS=m +CONFIG_6PACK=m +CONFIG_BPQETHER=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +CONFIG_YAM=m +CONFIG_CAN=m +CONFIG_CAN_VCAN=m +CONFIG_CAN_MCP251X=m +CONFIG_IRDA=m +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +CONFIG_IRTTY_SIR=m +CONFIG_KINGSUN_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KS959_DONGLE=m +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_6LOWPAN=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_ATH3K=m +CONFIG_BT_WILINK=m +CONFIG_MAC80211=m +CONFIG_MAC80211_MESH=y +CONFIG_WIMAX=m +CONFIG_RFKILL=m +CONFIG_RFKILL_INPUT=y +CONFIG_NET_9P=m +CONFIG_NFC=m +CONFIG_NFC_PN533=m CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y # CONFIG_STANDALONE is not set +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=5 +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_DRBD=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_ATA_OVER_ETH=m +CONFIG_EEPROM_AT24=m +CONFIG_TI_ST=m CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=y -CONFIG_SCSI_MULTI_LUN=y +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_CHR_DEV_SG=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_ISCSI_ATTRS=y +CONFIG_ISCSI_TCP=m +CONFIG_ISCSI_BOOT_SYSFS=m +CONFIG_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_LOG_USERSPACE=m +CONFIG_DM_RAID=m +CONFIG_DM_ZERO=m +CONFIG_DM_DELAY=m CONFIG_NETDEVICES=y +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_IFB=m +CONFIG_MACVLAN=m +CONFIG_NETCONSOLE=m +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_ENC28J60=m +CONFIG_MDIO_BITBANG=m +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOATM=m +CONFIG_PPPOE=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +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 +CONFIG_USB_NET_HUAWEI_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SR9700=m +CONFIG_USB_NET_SR9800=m +CONFIG_USB_NET_SMSC75XX=m CONFIG_USB_NET_SMSC95XX=y -CONFIG_ZD1211RW=y -CONFIG_INPUT_EVDEV=y +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_HSO=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_LIBERTAS_THINFIRM=m +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m +CONFIG_USB_ZD1201=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8187=m +CONFIG_MAC80211_HWSIM=m +CONFIG_ATH_CARDS=m +CONFIG_ATH9K=m +CONFIG_ATH9K_HTC=m +CONFIG_CARL9170=m +CONFIG_ATH6KL=m +CONFIG_ATH6KL_USB=m +CONFIG_AR5523=m +CONFIG_B43=m +# CONFIG_B43_PHY_N is not set +CONFIG_B43LEGACY=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_USB=y +CONFIG_HOSTAP=m +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +CONFIG_RT2X00=m +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 +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_WIMAX_I2400M_USB=m +CONFIG_INPUT_POLLDEV=m +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=m +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_EGALAX=m +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_TOUCHSCREEN_STMPE=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AD714X=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_YEALINK=m +CONFIG_INPUT_CM109=m +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +CONFIG_INPUT_ADXL34X=m +CONFIG_INPUT_CMA3000=m +CONFIG_SERIO=m +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y # CONFIG_LEGACY_PTYS is not set # CONFIG_DEVKMEM is not set CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_TTY_PRINTK=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_BCM2835=m +CONFIG_RAW_DRIVER=y +CONFIG_BRCM_CHAR_DRIVERS=y +CONFIG_BCM_VC_CMA=y +CONFIG_BCM_VCIO=y +CONFIG_BCM_VC_SM=y CONFIG_I2C=y -CONFIG_I2C_CHARDEV=y +CONFIG_I2C_CHARDEV=m CONFIG_I2C_BCM2835=y CONFIG_SPI=y -CONFIG_SPI_BCM2835=y +CONFIG_SPI_BCM2835=m +CONFIG_SPI_SPIDEV=y +CONFIG_PPS=m +CONFIG_PPS_CLIENT_LDISC=m +CONFIG_PPS_CLIENT_GPIO=m CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_ARIZONA=m +CONFIG_GPIO_STMPE=y +CONFIG_W1=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_MASTER_DS1WM=m +CONFIG_W1_MASTER_GPIO=m +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2408=m +CONFIG_W1_SLAVE_DS2413=m +CONFIG_W1_SLAVE_DS2406=m +CONFIG_W1_SLAVE_DS2423=m +CONFIG_W1_SLAVE_DS2431=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2760=m +CONFIG_W1_SLAVE_DS2780=m +CONFIG_W1_SLAVE_DS2781=m +CONFIG_W1_SLAVE_DS28E04=m +CONFIG_W1_SLAVE_BQ27000=m +CONFIG_BATTERY_DS2760=m # CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_BCM2835=y +CONFIG_WATCHDOG=y +CONFIG_BCM2835_WDT=y +CONFIG_UCB1400_CORE=m +CONFIG_MFD_STMPE=y +CONFIG_STMPE_SPI=y +CONFIG_MFD_ARIZONA_I2C=m +CONFIG_MFD_ARIZONA_SPI=m +CONFIG_MFD_WM5102=y +CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_RC_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_LIRC=m +CONFIG_RC_DEVICES=y +CONFIG_RC_ATI_REMOTE=m +CONFIG_IR_IMON=m +CONFIG_IR_MCEUSB=m +CONFIG_IR_REDRAT3=m +CONFIG_IR_STREAMZAP=m +CONFIG_IR_IGUANA=m +CONFIG_IR_TTUSBIR=m +CONFIG_RC_LOOPBACK=m +CONFIG_IR_GPIO_CIR=m +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_M5602=m +CONFIG_USB_STV06XX=m +CONFIG_USB_GL860=m +CONFIG_USB_GSPCA_BENQ=m +CONFIG_USB_GSPCA_CONEX=m +CONFIG_USB_GSPCA_CPIA1=m +CONFIG_USB_GSPCA_DTCS033=m +CONFIG_USB_GSPCA_ETOMS=m +CONFIG_USB_GSPCA_FINEPIX=m +CONFIG_USB_GSPCA_JEILINJ=m +CONFIG_USB_GSPCA_JL2005BCD=m +CONFIG_USB_GSPCA_KINECT=m +CONFIG_USB_GSPCA_KONICA=m +CONFIG_USB_GSPCA_MARS=m +CONFIG_USB_GSPCA_MR97310A=m +CONFIG_USB_GSPCA_NW80X=m +CONFIG_USB_GSPCA_OV519=m +CONFIG_USB_GSPCA_OV534=m +CONFIG_USB_GSPCA_OV534_9=m +CONFIG_USB_GSPCA_PAC207=m +CONFIG_USB_GSPCA_PAC7302=m +CONFIG_USB_GSPCA_PAC7311=m +CONFIG_USB_GSPCA_SE401=m +CONFIG_USB_GSPCA_SN9C2028=m +CONFIG_USB_GSPCA_SN9C20X=m +CONFIG_USB_GSPCA_SONIXB=m +CONFIG_USB_GSPCA_SONIXJ=m +CONFIG_USB_GSPCA_SPCA500=m +CONFIG_USB_GSPCA_SPCA501=m +CONFIG_USB_GSPCA_SPCA505=m +CONFIG_USB_GSPCA_SPCA506=m +CONFIG_USB_GSPCA_SPCA508=m +CONFIG_USB_GSPCA_SPCA561=m +CONFIG_USB_GSPCA_SPCA1528=m +CONFIG_USB_GSPCA_SQ905=m +CONFIG_USB_GSPCA_SQ905C=m +CONFIG_USB_GSPCA_SQ930X=m +CONFIG_USB_GSPCA_STK014=m +CONFIG_USB_GSPCA_STK1135=m +CONFIG_USB_GSPCA_STV0680=m +CONFIG_USB_GSPCA_SUNPLUS=m +CONFIG_USB_GSPCA_T613=m +CONFIG_USB_GSPCA_TOPRO=m +CONFIG_USB_GSPCA_TV8532=m +CONFIG_USB_GSPCA_VC032X=m +CONFIG_USB_GSPCA_VICAM=m +CONFIG_USB_GSPCA_XIRLINK_CIT=m +CONFIG_USB_GSPCA_ZC3XX=m +CONFIG_USB_PWC=m +CONFIG_VIDEO_CPIA2=m +CONFIG_USB_ZR364XX=m +CONFIG_USB_STKWEBCAM=m +CONFIG_USB_S2255=m +CONFIG_VIDEO_USBTV=m +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_STK1160_COMMON=m +CONFIG_VIDEO_STK1160_AC97=y +CONFIG_VIDEO_GO7007=m +CONFIG_VIDEO_GO7007_USB=m +CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_AU0828_RC=y +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_ALSA=m +CONFIG_VIDEO_CX231XX_DVB=m +CONFIG_VIDEO_TM6000=m +CONFIG_VIDEO_TM6000_ALSA=m +CONFIG_VIDEO_TM6000_DVB=m +CONFIG_DVB_USB=m +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_PCTV452E=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_CINERGY_T2=m +CONFIG_DVB_USB_DTV5100=m +CONFIG_DVB_USB_FRIIO=m +CONFIG_DVB_USB_AZ6027=m +CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_V2=m +CONFIG_DVB_USB_AF9015=m +CONFIG_DVB_USB_AF9035=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_AZ6007=m +CONFIG_DVB_USB_CE6230=m +CONFIG_DVB_USB_EC168=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_LME2510=m +CONFIG_DVB_USB_MXL111SF=m +CONFIG_DVB_USB_RTL28XXU=m +CONFIG_DVB_USB_DVBSKY=m +CONFIG_SMS_USB_DRV=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +CONFIG_DVB_AS102=m +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_EM28XX_V4L2=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_VIDEO_BCM2835=y +CONFIG_VIDEO_BCM2835_MMAL=m +CONFIG_RADIO_SI470X=y +CONFIG_USB_SI470X=m +CONFIG_I2C_SI470X=m +CONFIG_RADIO_SI4713=m +CONFIG_I2C_SI4713=m +CONFIG_USB_MR800=m +CONFIG_USB_DSBR=m +CONFIG_RADIO_SHARK=m +CONFIG_RADIO_SHARK2=m +CONFIG_USB_KEENE=m +CONFIG_USB_MA901=m +CONFIG_RADIO_TEA5764=m +CONFIG_RADIO_SAA7706H=m +CONFIG_RADIO_TEF6862=m +CONFIG_RADIO_WL1273=m +CONFIG_RADIO_WL128X=m +# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set +CONFIG_VIDEO_UDA1342=m +CONFIG_VIDEO_SONY_BTF_MPX=m +CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_TW2804=m +CONFIG_VIDEO_TW9903=m +CONFIG_VIDEO_TW9906=m +CONFIG_VIDEO_OV7640=m +CONFIG_VIDEO_MT9V011=m CONFIG_FB=y -CONFIG_FB_SIMPLE=y +CONFIG_FB_BCM2708=y +CONFIG_FB_SSD1307=m +# CONFIG_BACKLIGHT_GENERIC is not set +CONFIG_BACKLIGHT_GPIO=m CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_SOUND=y +CONFIG_SND=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=m +CONFIG_SND_DUMMY=m +CONFIG_SND_ALOOP=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m +CONFIG_SND_BCM2835=m +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_6FIRE=m +CONFIG_SND_SOC=m +CONFIG_SND_BCM2835_SOC_I2S=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m +CONFIG_SND_BCM2708_SOC_RPI_DAC=m +CONFIG_SND_BCM2708_SOC_RPI_PROTO=m +CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m +CONFIG_SND_SIMPLE_CARD=m +CONFIG_SOUND_PRIME=m +CONFIG_HIDRAW=y +CONFIG_HID_A4TECH=m +CONFIG_HID_ACRUX=m +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_HID_EMS_FF=m +CONFIG_HID_ELECOM=m +CONFIG_HID_ELO=m +CONFIG_HID_EZKEY=m +CONFIG_HID_HOLTEK=m +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=m +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +CONFIG_HID_GYRATION=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LCPOWER=m +CONFIG_HID_LOGITECH=m +CONFIG_HID_MAGICMOUSE=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NTRIG=m +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_GREENASIA=m +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_THINGM=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_HID_WACOM=m +CONFIG_HID_WIIMOTE=m +CONFIG_HID_XINMO=m +CONFIG_HID_ZEROPLUS=m +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 +CONFIG_USB_PRINTER=m CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_REALTEK=m +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +CONFIG_USB_STORAGE_ENE_UB6250=m +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +CONFIG_USBIP_CORE=m +CONFIG_USBIP_VHCI_HCD=m +CONFIG_USBIP_HOST=m +CONFIG_USB_DWC2=y +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=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_SAFE=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_DEBUG=m +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_SEVSEG=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +CONFIG_USB_TEST=m +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_YUREX=m +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BCM2835=y +CONFIG_MMC_BCM2835_DMA=y +CONFIG_MMC_BCM2835_SDHOST=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_BCM2835=y +CONFIG_MMC_SPI=m +CONFIG_LEDS_CLASS=y CONFIG_LEDS_GPIO=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_ONESHOT=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y CONFIG_LEDS_TRIGGER_CPU=y CONFIG_LEDS_TRIGGER_GPIO=y CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -CONFIG_LEDS_TRIGGER_TRANSIENT=y -CONFIG_LEDS_TRIGGER_CAMERA=y +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_CAMERA=m +CONFIG_LEDS_TRIGGER_INPUT=y +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 +CONFIG_RTC_DRV_DS3232=m +CONFIG_RTC_DRV_MAX6900=m +CONFIG_RTC_DRV_RS5C372=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_ISL12022=m +CONFIG_RTC_DRV_ISL12057=m +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_PCF2127=m +CONFIG_RTC_DRV_PCF8523=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_M41T80=m +CONFIG_RTC_DRV_BQ32K=m +CONFIG_RTC_DRV_S35390A=m +CONFIG_RTC_DRV_FM3130=m +CONFIG_RTC_DRV_RX8581=m +CONFIG_RTC_DRV_RX8025=m +CONFIG_RTC_DRV_EM3027=m +CONFIG_RTC_DRV_RV3029C2=m +CONFIG_RTC_DRV_M41T93=m +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_R9701=m +CONFIG_RTC_DRV_RS5C348=m +CONFIG_RTC_DRV_DS3234=m +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_RX4581=m +CONFIG_DMADEVICES=y +CONFIG_DMA_BCM2708=y +CONFIG_UIO=m +CONFIG_UIO_PDRV_GENIRQ=m CONFIG_STAGING=y -CONFIG_USB_DWC2=y -CONFIG_USB_DWC2_HOST=y +CONFIG_PRISM2_USB=m +CONFIG_R8712U=m +CONFIG_R8188EU=m +CONFIG_R8723AU=m +CONFIG_VT6656=m +CONFIG_SPEAKUP=m +CONFIG_SPEAKUP_SYNTH_SOFT=m +CONFIG_STAGING_MEDIA=y +CONFIG_LIRC_STAGING=y +CONFIG_LIRC_IMON=m +CONFIG_LIRC_SASEM=m +CONFIG_LIRC_SERIAL=m +CONFIG_FB_TFT=m +CONFIG_FB_TFT_AGM1264K_FL=m +CONFIG_FB_TFT_BD663474=m +CONFIG_FB_TFT_HX8340BN=m +CONFIG_FB_TFT_HX8347D=m +CONFIG_FB_TFT_HX8353D=m +CONFIG_FB_TFT_ILI9320=m +CONFIG_FB_TFT_ILI9325=m +CONFIG_FB_TFT_ILI9340=m +CONFIG_FB_TFT_ILI9341=m +CONFIG_FB_TFT_ILI9481=m +CONFIG_FB_TFT_ILI9486=m +CONFIG_FB_TFT_PCD8544=m +CONFIG_FB_TFT_RA8875=m +CONFIG_FB_TFT_S6D02A1=m +CONFIG_FB_TFT_S6D1121=m +CONFIG_FB_TFT_SSD1289=m +CONFIG_FB_TFT_SSD1306=m +CONFIG_FB_TFT_SSD1331=m +CONFIG_FB_TFT_SSD1351=m +CONFIG_FB_TFT_ST7735R=m +CONFIG_FB_TFT_TINYLCD=m +CONFIG_FB_TFT_TLS8204=m +CONFIG_FB_TFT_UC1701=m +CONFIG_FB_TFT_UPD161704=m +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m +CONFIG_MAILBOX=y +CONFIG_BCM2835_MBOX=y # CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXTCON=m +CONFIG_EXTCON_ARIZONA=m +CONFIG_RASPBERRYPI_FIRMWARE=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y @@ -107,18 +1077,110 @@ CONFIG_EXT3_FS_POSIX_ACL=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +CONFIG_JFS_STATISTICS=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +CONFIG_GFS2_FS=m +CONFIG_OCFS2_FS=m +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_NILFS2_FS=m +CONFIG_F2FS_FS=y CONFIG_FANOTIFY=y +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=m +CONFIG_CUSE=m +CONFIG_FSCACHE=y +CONFIG_FSCACHE_STATS=y +CONFIG_FSCACHE_HISTOGRAM=y +CONFIG_CACHEFILES=y +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +CONFIG_NTFS_FS=m +CONFIG_NTFS_RW=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y -# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_CONFIGFS_FS=y +CONFIG_ECRYPT_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_SQUASHFS=m +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y CONFIG_NFS_FS=y -CONFIG_NFSD=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_SWAP=y +CONFIG_ROOT_NFS=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFSD=m +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_9P_FS=m +CONFIG_9P_FS_POSIX_ACL=y +CONFIG_NLS_DEFAULT="utf8" CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m CONFIG_NLS_ASCII=y -CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m CONFIG_NLS_UTF8=y +CONFIG_DLM=m CONFIG_PRINTK_TIME=y CONFIG_BOOT_PRINTK_DELAY=y CONFIG_DYNAMIC_DEBUG=y @@ -128,14 +1190,39 @@ CONFIG_UNUSED_SYMBOLS=y CONFIG_DEBUG_MEMORY_INIT=y CONFIG_LOCKUP_DETECTOR=y +CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_LATENCYTOP=y +CONFIG_IRQSOFF_TRACER=y CONFIG_SCHED_TRACER=y CONFIG_STACK_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y +# CONFIG_KPROBE_EVENT is not set CONFIG_FUNCTION_PROFILER=y CONFIG_TEST_KSTRTOX=y CONFIG_KGDB=y CONFIG_KGDB_KDB=y +CONFIG_KDB_KEYBOARD=y CONFIG_STRICT_DEVMEM=y CONFIG_DEBUG_LL=y CONFIG_EARLY_PRINTK=y +CONFIG_CRYPTO_USER=m +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTS=m +CONFIG_CRYPTO_XTS=m +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_ARM_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM=m +CONFIG_CRYPTO_AES_ARM=m +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y # CONFIG_XZ_DEC_ARM is not set # CONFIG_XZ_DEC_ARMTHUMB is not set diff -Nur '--exclude=.git' linux-stable/arch/arm/configs/bcmrpi_defconfig raspilinux/arch/arm/configs/bcmrpi_defconfig --- linux-stable/arch/arm/configs/bcmrpi_defconfig 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/configs/bcmrpi_defconfig 2015-12-26 19:08:30.284746955 +0100 @@ -0,0 +1,1254 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0 +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_FHANDLE=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=m +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_MEMCG=y +CONFIG_BLK_CGROUP=y +CONFIG_NAMESPACES=y +CONFIG_SCHED_AUTOGROUP=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EMBEDDED=y +# CONFIG_COMPAT_BRK is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y +CONFIG_JUMP_LABEL=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y +CONFIG_CFQ_GROUP_IOSCHED=y +CONFIG_ARCH_BCM2708=y +CONFIG_BCM2708_DT=y +CONFIG_PREEMPT_VOLUNTARY=y +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_CLEANCACHE=y +CONFIG_FRONTSWAP=y +CONFIG_CMA=y +CONFIG_ZSMALLOC=m +CONFIG_PGTABLE_MAPPING=y +CONFIG_UACCESS_WITH_MEMCPY=y +CONFIG_SECCOMP=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_VFP=y +CONFIG_BINFMT_MISC=m +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IPGRE=m +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_LRO=m +CONFIG_INET_DIAG=m +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 +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NETFILTER_XT_SET=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_PE_SIP=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_IP6_NF_TARGET_NPT=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_SCTP_COOKIE_HMAC_SHA1=y +CONFIG_ATM=m +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 +CONFIG_ATALK=m +CONFIG_6LOWPAN=m +CONFIG_IEEE802154=m +CONFIG_IEEE802154_6LOWPAN=m +CONFIG_MAC802154=m +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_CHOKE=m +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_SCH_PLUG=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_CGROUP=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_IPSET=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_ACT_CSUM=m +CONFIG_BATMAN_ADV=m +CONFIG_OPENVSWITCH=m +CONFIG_NET_PKTGEN=m +CONFIG_HAMRADIO=y +CONFIG_AX25=m +CONFIG_NETROM=m +CONFIG_ROSE=m +CONFIG_MKISS=m +CONFIG_6PACK=m +CONFIG_BPQETHER=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +CONFIG_YAM=m +CONFIG_CAN=m +CONFIG_CAN_VCAN=m +CONFIG_CAN_MCP251X=m +CONFIG_IRDA=m +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +CONFIG_IRTTY_SIR=m +CONFIG_KINGSUN_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KS959_DONGLE=m +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_6LOWPAN=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_ATH3K=m +CONFIG_BT_WILINK=m +CONFIG_MAC80211=m +CONFIG_MAC80211_MESH=y +CONFIG_WIMAX=m +CONFIG_RFKILL=m +CONFIG_RFKILL_INPUT=y +CONFIG_NET_9P=m +CONFIG_NFC=m +CONFIG_NFC_PN533=m +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=5 +CONFIG_MTD=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_NAND=m +CONFIG_MTD_UBI=m +CONFIG_ZRAM=m +CONFIG_ZRAM_LZ4_COMPRESS=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_DRBD=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_ATA_OVER_ETH=m +CONFIG_EEPROM_AT24=m +CONFIG_TI_ST=m +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_CHR_DEV_SG=m +CONFIG_SCSI_ISCSI_ATTRS=y +CONFIG_ISCSI_TCP=m +CONFIG_ISCSI_BOOT_SYSFS=m +CONFIG_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_THIN_PROVISIONING=m +CONFIG_DM_MIRROR=m +CONFIG_DM_LOG_USERSPACE=m +CONFIG_DM_RAID=m +CONFIG_DM_ZERO=m +CONFIG_DM_DELAY=m +CONFIG_NETDEVICES=y +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_IFB=m +CONFIG_MACVLAN=m +CONFIG_NETCONSOLE=m +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_ENC28J60=m +CONFIG_MDIO_BITBANG=m +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOATM=m +CONFIG_PPPOE=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +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 +CONFIG_USB_NET_HUAWEI_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SR9700=m +CONFIG_USB_NET_SR9800=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=y +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_HSO=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_LIBERTAS_THINFIRM=m +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m +CONFIG_USB_ZD1201=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8187=m +CONFIG_MAC80211_HWSIM=m +CONFIG_ATH_CARDS=m +CONFIG_ATH9K=m +CONFIG_ATH9K_HTC=m +CONFIG_CARL9170=m +CONFIG_ATH6KL=m +CONFIG_ATH6KL_USB=m +CONFIG_AR5523=m +CONFIG_B43=m +# CONFIG_B43_PHY_N is not set +CONFIG_B43LEGACY=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_USB=y +CONFIG_HOSTAP=m +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +CONFIG_RT2X00=m +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_WL_MEDIATEK=y +CONFIG_MT7601U=m +CONFIG_RTL8192CU=m +CONFIG_ZD1211RW=m +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_WIMAX_I2400M_USB=m +CONFIG_IEEE802154_AT86RF230=m +CONFIG_IEEE802154_MRF24J40=m +CONFIG_IEEE802154_CC2520=m +CONFIG_INPUT_POLLDEV=m +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=m +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_RPISENSE=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_EGALAX=m +CONFIG_TOUCHSCREEN_FT6236=m +CONFIG_TOUCHSCREEN_RPI_FT5406=m +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_TOUCHSCREEN_STMPE=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AD714X=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_YEALINK=m +CONFIG_INPUT_CM109=m +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +CONFIG_INPUT_ADXL34X=m +CONFIG_INPUT_CMA3000=m +CONFIG_SERIO=m +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_DMA is not set +CONFIG_SERIAL_8250_NR_UARTS=1 +CONFIG_SERIAL_8250_RUNTIME_UARTS=0 +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_TTY_PRINTK=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_BCM2835=m +CONFIG_HW_RANDOM_BCM2708=m +CONFIG_RAW_DRIVER=y +CONFIG_BRCM_CHAR_DRIVERS=y +CONFIG_BCM_VC_CMA=y +CONFIG_BCM_VCIO=y +CONFIG_BCM_VC_SM=y +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_BCM2708=m +CONFIG_I2C_GPIO=m +CONFIG_SPI=y +CONFIG_SPI_BCM2835=m +CONFIG_SPI_BCM2708=m +CONFIG_SPI_SPIDEV=y +CONFIG_PPS=m +CONFIG_PPS_CLIENT_LDISC=m +CONFIG_PPS_CLIENT_GPIO=m +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_ARIZONA=m +CONFIG_GPIO_STMPE=y +CONFIG_W1=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_MASTER_DS1WM=m +CONFIG_W1_MASTER_GPIO=m +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2408=m +CONFIG_W1_SLAVE_DS2413=m +CONFIG_W1_SLAVE_DS2406=m +CONFIG_W1_SLAVE_DS2423=m +CONFIG_W1_SLAVE_DS2431=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2760=m +CONFIG_W1_SLAVE_DS2780=m +CONFIG_W1_SLAVE_DS2781=m +CONFIG_W1_SLAVE_DS28E04=m +CONFIG_W1_SLAVE_BQ27000=m +CONFIG_BATTERY_DS2760=m +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_HWMON=m +CONFIG_SENSORS_SHT21=m +CONFIG_SENSORS_SHTC1=m +CONFIG_THERMAL=y +CONFIG_THERMAL_BCM2835=y +CONFIG_WATCHDOG=y +CONFIG_BCM2708_WDT=m +CONFIG_BCM2835_WDT=m +CONFIG_UCB1400_CORE=m +CONFIG_MFD_STMPE=y +CONFIG_STMPE_SPI=y +CONFIG_MFD_ARIZONA_I2C=m +CONFIG_MFD_ARIZONA_SPI=m +CONFIG_MFD_WM5102=y +CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_RC_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_LIRC=m +CONFIG_RC_DEVICES=y +CONFIG_RC_ATI_REMOTE=m +CONFIG_IR_IMON=m +CONFIG_IR_MCEUSB=m +CONFIG_IR_REDRAT3=m +CONFIG_IR_STREAMZAP=m +CONFIG_IR_IGUANA=m +CONFIG_IR_TTUSBIR=m +CONFIG_RC_LOOPBACK=m +CONFIG_IR_GPIO_CIR=m +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_M5602=m +CONFIG_USB_STV06XX=m +CONFIG_USB_GL860=m +CONFIG_USB_GSPCA_BENQ=m +CONFIG_USB_GSPCA_CONEX=m +CONFIG_USB_GSPCA_CPIA1=m +CONFIG_USB_GSPCA_DTCS033=m +CONFIG_USB_GSPCA_ETOMS=m +CONFIG_USB_GSPCA_FINEPIX=m +CONFIG_USB_GSPCA_JEILINJ=m +CONFIG_USB_GSPCA_JL2005BCD=m +CONFIG_USB_GSPCA_KINECT=m +CONFIG_USB_GSPCA_KONICA=m +CONFIG_USB_GSPCA_MARS=m +CONFIG_USB_GSPCA_MR97310A=m +CONFIG_USB_GSPCA_NW80X=m +CONFIG_USB_GSPCA_OV519=m +CONFIG_USB_GSPCA_OV534=m +CONFIG_USB_GSPCA_OV534_9=m +CONFIG_USB_GSPCA_PAC207=m +CONFIG_USB_GSPCA_PAC7302=m +CONFIG_USB_GSPCA_PAC7311=m +CONFIG_USB_GSPCA_SE401=m +CONFIG_USB_GSPCA_SN9C2028=m +CONFIG_USB_GSPCA_SN9C20X=m +CONFIG_USB_GSPCA_SONIXB=m +CONFIG_USB_GSPCA_SONIXJ=m +CONFIG_USB_GSPCA_SPCA500=m +CONFIG_USB_GSPCA_SPCA501=m +CONFIG_USB_GSPCA_SPCA505=m +CONFIG_USB_GSPCA_SPCA506=m +CONFIG_USB_GSPCA_SPCA508=m +CONFIG_USB_GSPCA_SPCA561=m +CONFIG_USB_GSPCA_SPCA1528=m +CONFIG_USB_GSPCA_SQ905=m +CONFIG_USB_GSPCA_SQ905C=m +CONFIG_USB_GSPCA_SQ930X=m +CONFIG_USB_GSPCA_STK014=m +CONFIG_USB_GSPCA_STK1135=m +CONFIG_USB_GSPCA_STV0680=m +CONFIG_USB_GSPCA_SUNPLUS=m +CONFIG_USB_GSPCA_T613=m +CONFIG_USB_GSPCA_TOPRO=m +CONFIG_USB_GSPCA_TV8532=m +CONFIG_USB_GSPCA_VC032X=m +CONFIG_USB_GSPCA_VICAM=m +CONFIG_USB_GSPCA_XIRLINK_CIT=m +CONFIG_USB_GSPCA_ZC3XX=m +CONFIG_USB_PWC=m +CONFIG_VIDEO_CPIA2=m +CONFIG_USB_ZR364XX=m +CONFIG_USB_STKWEBCAM=m +CONFIG_USB_S2255=m +CONFIG_VIDEO_USBTV=m +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_STK1160_COMMON=m +CONFIG_VIDEO_STK1160_AC97=y +CONFIG_VIDEO_GO7007=m +CONFIG_VIDEO_GO7007_USB=m +CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_AU0828_RC=y +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_ALSA=m +CONFIG_VIDEO_CX231XX_DVB=m +CONFIG_VIDEO_TM6000=m +CONFIG_VIDEO_TM6000_ALSA=m +CONFIG_VIDEO_TM6000_DVB=m +CONFIG_DVB_USB=m +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_PCTV452E=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_CINERGY_T2=m +CONFIG_DVB_USB_DTV5100=m +CONFIG_DVB_USB_FRIIO=m +CONFIG_DVB_USB_AZ6027=m +CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_V2=m +CONFIG_DVB_USB_AF9015=m +CONFIG_DVB_USB_AF9035=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_AZ6007=m +CONFIG_DVB_USB_CE6230=m +CONFIG_DVB_USB_EC168=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_LME2510=m +CONFIG_DVB_USB_MXL111SF=m +CONFIG_DVB_USB_RTL28XXU=m +CONFIG_DVB_USB_DVBSKY=m +CONFIG_SMS_USB_DRV=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +CONFIG_DVB_AS102=m +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_EM28XX_V4L2=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_VIDEO_BCM2835=y +CONFIG_VIDEO_BCM2835_MMAL=m +CONFIG_RADIO_SI470X=y +CONFIG_USB_SI470X=m +CONFIG_I2C_SI470X=m +CONFIG_RADIO_SI4713=m +CONFIG_I2C_SI4713=m +CONFIG_USB_MR800=m +CONFIG_USB_DSBR=m +CONFIG_RADIO_SHARK=m +CONFIG_RADIO_SHARK2=m +CONFIG_USB_KEENE=m +CONFIG_USB_MA901=m +CONFIG_RADIO_TEA5764=m +CONFIG_RADIO_SAA7706H=m +CONFIG_RADIO_TEF6862=m +CONFIG_RADIO_WL1273=m +CONFIG_RADIO_WL128X=m +# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set +CONFIG_VIDEO_UDA1342=m +CONFIG_VIDEO_SONY_BTF_MPX=m +CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_TW2804=m +CONFIG_VIDEO_TW9903=m +CONFIG_VIDEO_TW9906=m +CONFIG_VIDEO_OV7640=m +CONFIG_VIDEO_MT9V011=m +CONFIG_FB=y +CONFIG_FB_BCM2708=y +CONFIG_FB_UDL=m +CONFIG_FB_SSD1307=m +CONFIG_FB_RPISENSE=m +# CONFIG_BACKLIGHT_GENERIC is not set +CONFIG_BACKLIGHT_RPI=m +CONFIG_BACKLIGHT_GPIO=m +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_SOUND=y +CONFIG_SND=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=m +CONFIG_SND_DUMMY=m +CONFIG_SND_ALOOP=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m +CONFIG_SND_BCM2835=m +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_6FIRE=m +CONFIG_SND_SOC=m +CONFIG_SND_BCM2708_SOC_I2S=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m +CONFIG_SND_BCM2708_SOC_RPI_DAC=m +CONFIG_SND_BCM2708_SOC_RPI_PROTO=m +CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m +CONFIG_SND_BCM2708_SOC_RASPIDAC3=m +CONFIG_SND_SOC_ADAU1701=m +CONFIG_SND_SOC_WM8804_I2C=m +CONFIG_SND_SIMPLE_CARD=m +CONFIG_SOUND_PRIME=m +CONFIG_HIDRAW=y +CONFIG_UHID=m +CONFIG_HID_A4TECH=m +CONFIG_HID_ACRUX=m +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_HID_EMS_FF=m +CONFIG_HID_ELECOM=m +CONFIG_HID_ELO=m +CONFIG_HID_EZKEY=m +CONFIG_HID_HOLTEK=m +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=m +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +CONFIG_HID_GYRATION=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LCPOWER=m +CONFIG_HID_LOGITECH=m +CONFIG_HID_MAGICMOUSE=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NTRIG=m +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_GREENASIA=m +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_THINGM=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_HID_WACOM=m +CONFIG_HID_WIIMOTE=m +CONFIG_HID_XINMO=m +CONFIG_HID_ZEROPLUS=m +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 +CONFIG_USB_PRINTER=m +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_REALTEK=m +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +CONFIG_USB_STORAGE_ENE_UB6250=m +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +CONFIG_USBIP_CORE=m +CONFIG_USBIP_VHCI_HCD=m +CONFIG_USBIP_HOST=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=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_SAFE=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_DEBUG=m +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_SEVSEG=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +CONFIG_USB_TEST=m +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_YUREX=m +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BCM2835=y +CONFIG_MMC_BCM2835_DMA=y +CONFIG_MMC_BCM2835_SDHOST=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SPI=m +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_CAMERA=m +CONFIG_LEDS_TRIGGER_INPUT=y +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 +CONFIG_RTC_DRV_DS3232=m +CONFIG_RTC_DRV_MAX6900=m +CONFIG_RTC_DRV_RS5C372=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_ISL12022=m +CONFIG_RTC_DRV_ISL12057=m +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_PCF2127=m +CONFIG_RTC_DRV_PCF8523=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_M41T80=m +CONFIG_RTC_DRV_BQ32K=m +CONFIG_RTC_DRV_S35390A=m +CONFIG_RTC_DRV_FM3130=m +CONFIG_RTC_DRV_RX8581=m +CONFIG_RTC_DRV_RX8025=m +CONFIG_RTC_DRV_EM3027=m +CONFIG_RTC_DRV_RV3029C2=m +CONFIG_RTC_DRV_M41T93=m +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_R9701=m +CONFIG_RTC_DRV_RS5C348=m +CONFIG_RTC_DRV_DS3234=m +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_RX4581=m +CONFIG_DMADEVICES=y +CONFIG_DMA_BCM2708=y +CONFIG_UIO=m +CONFIG_UIO_PDRV_GENIRQ=m +CONFIG_STAGING=y +CONFIG_PRISM2_USB=m +CONFIG_R8712U=m +CONFIG_R8188EU=m +CONFIG_R8723AU=m +CONFIG_VT6656=m +CONFIG_SPEAKUP=m +CONFIG_SPEAKUP_SYNTH_SOFT=m +CONFIG_STAGING_MEDIA=y +CONFIG_LIRC_STAGING=y +CONFIG_LIRC_IMON=m +CONFIG_LIRC_RPI=m +CONFIG_LIRC_SASEM=m +CONFIG_LIRC_SERIAL=m +CONFIG_FB_TFT=m +CONFIG_FB_TFT_AGM1264K_FL=m +CONFIG_FB_TFT_BD663474=m +CONFIG_FB_TFT_HX8340BN=m +CONFIG_FB_TFT_HX8347D=m +CONFIG_FB_TFT_HX8353D=m +CONFIG_FB_TFT_ILI9163=m +CONFIG_FB_TFT_ILI9320=m +CONFIG_FB_TFT_ILI9325=m +CONFIG_FB_TFT_ILI9340=m +CONFIG_FB_TFT_ILI9341=m +CONFIG_FB_TFT_ILI9481=m +CONFIG_FB_TFT_ILI9486=m +CONFIG_FB_TFT_PCD8544=m +CONFIG_FB_TFT_RA8875=m +CONFIG_FB_TFT_S6D02A1=m +CONFIG_FB_TFT_S6D1121=m +CONFIG_FB_TFT_SSD1289=m +CONFIG_FB_TFT_SSD1306=m +CONFIG_FB_TFT_SSD1331=m +CONFIG_FB_TFT_SSD1351=m +CONFIG_FB_TFT_ST7735R=m +CONFIG_FB_TFT_TINYLCD=m +CONFIG_FB_TFT_TLS8204=m +CONFIG_FB_TFT_UC1701=m +CONFIG_FB_TFT_UPD161704=m +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m +CONFIG_MAILBOX=y +CONFIG_BCM2835_MBOX=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXTCON=m +CONFIG_EXTCON_ARIZONA=m +CONFIG_IIO=m +CONFIG_IIO_BUFFER=y +CONFIG_IIO_BUFFER_CB=y +CONFIG_IIO_KFIFO_BUF=m +CONFIG_MCP320X=m +CONFIG_DHT11=m +CONFIG_PWM_BCM2835=m +CONFIG_RASPBERRYPI_FIRMWARE=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +CONFIG_JFS_STATISTICS=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +CONFIG_GFS2_FS=m +CONFIG_OCFS2_FS=m +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_NILFS2_FS=m +CONFIG_F2FS_FS=y +CONFIG_FANOTIFY=y +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=m +CONFIG_CUSE=m +CONFIG_OVERLAY_FS=m +CONFIG_FSCACHE=y +CONFIG_FSCACHE_STATS=y +CONFIG_FSCACHE_HISTOGRAM=y +CONFIG_CACHEFILES=y +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +CONFIG_NTFS_FS=m +CONFIG_NTFS_RW=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y +CONFIG_ECRYPT_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_SUMMARY=y +CONFIG_UBIFS_FS=m +CONFIG_SQUASHFS=m +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_SWAP=y +CONFIG_ROOT_NFS=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFSD=m +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_CIFS_ACL=y +CONFIG_CIFS_DFS_UPCALL=y +CONFIG_CIFS_SMB2=y +CONFIG_CIFS_FSCACHE=y +CONFIG_9P_FS=m +CONFIG_9P_FS_POSIX_ACL=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_DLM=m +CONFIG_PRINTK_TIME=y +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_TIMER_STATS=y +CONFIG_LATENCYTOP=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_SCHED_TRACER=y +CONFIG_STACK_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y +# CONFIG_KPROBE_EVENT is not set +CONFIG_FUNCTION_PROFILER=y +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y +CONFIG_KDB_KEYBOARD=y +CONFIG_CRYPTO_USER=m +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTS=m +CONFIG_CRYPTO_XTS=m +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_USER_API_SKCIPHER=m +# CONFIG_CRYPTO_HW is not set +CONFIG_ARM_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM=m +CONFIG_CRYPTO_AES_ARM=m +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y diff -Nur '--exclude=.git' linux-stable/arch/arm/include/asm/entry-macro-multi.S raspilinux/arch/arm/include/asm/entry-macro-multi.S --- linux-stable/arch/arm/include/asm/entry-macro-multi.S 2015-12-26 20:44:59.692048897 +0100 +++ raspilinux/arch/arm/include/asm/entry-macro-multi.S 2015-12-26 19:08:30.292746209 +0100 @@ -1,5 +1,6 @@ #include +#ifndef CONFIG_ARCH_BCM2709 /* * Interrupt handling. Preserves r7, r8, r9 */ @@ -28,6 +29,7 @@ #endif 9997: .endm +#endif .macro arch_irq_handler, symbol_name .align 5 diff -Nur '--exclude=.git' linux-stable/arch/arm/include/asm/irqflags.h raspilinux/arch/arm/include/asm/irqflags.h --- linux-stable/arch/arm/include/asm/irqflags.h 2015-12-26 20:44:59.692048897 +0100 +++ raspilinux/arch/arm/include/asm/irqflags.h 2015-12-26 19:08:30.292746209 +0100 @@ -145,12 +145,22 @@ } /* - * restore saved IRQ & FIQ state + * restore saved IRQ state */ static inline void arch_local_irq_restore(unsigned long flags) { - 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 '--exclude=.git' linux-stable/arch/arm/include/asm/string.h raspilinux/arch/arm/include/asm/string.h --- linux-stable/arch/arm/include/asm/string.h 2015-12-26 20:38:42.826782358 +0100 +++ raspilinux/arch/arm/include/asm/string.h 2015-12-26 19:08:30.296745836 +0100 @@ -24,6 +24,11 @@ #define __HAVE_ARCH_MEMSET extern void * memset(void *, int, __kernel_size_t); +#ifdef CONFIG_MACH_BCM2708 +#define __HAVE_ARCH_MEMCMP +extern int memcmp(const void *, const void *, size_t); +#endif + extern void __memzero(void *ptr, __kernel_size_t n); #define memset(p,v,n) \ diff -Nur '--exclude=.git' linux-stable/arch/arm/include/asm/uaccess.h raspilinux/arch/arm/include/asm/uaccess.h --- linux-stable/arch/arm/include/asm/uaccess.h 2015-12-26 20:44:59.696048528 +0100 +++ raspilinux/arch/arm/include/asm/uaccess.h 2015-12-26 19:08:30.296745836 +0100 @@ -475,6 +475,7 @@ #ifdef CONFIG_MMU extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n); +extern unsigned long __must_check __copy_from_user_std(void *to, const void __user *from, unsigned long n); extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n); extern unsigned long __must_check __copy_to_user_std(void __user *to, const void *from, unsigned long n); extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n); diff -Nur '--exclude=.git' linux-stable/arch/arm/Kconfig raspilinux/arch/arm/Kconfig --- linux-stable/arch/arm/Kconfig 2015-12-26 20:44:59.608056639 +0100 +++ raspilinux/arch/arm/Kconfig 2015-12-26 19:08:30.224752550 +0100 @@ -314,6 +314,42 @@ default ARCH_VERSATILE if !MMU default ARCH_MULTIPLATFORM if MMU +config ARCH_BCM2708 + bool "Broadcom BCM2708 family" + select CPU_V6 + select ARM_AMBA + select HAVE_SCHED_CLOCK + select NEED_MACH_GPIO_H + select NEED_MACH_MEMORY_H + select COMMON_CLK + select ARCH_HAS_CPUFREQ + select GENERIC_CLOCKEVENTS + select ARM_ERRATA_411920 + select MACH_BCM2708 + select VC4 + select FIQ + help + This enables support for Broadcom BCM2708 boards. + +config ARCH_BCM2709 + bool "Broadcom BCM2709 family" + select ARCH_HAS_BARRIERS if SMP + select CPU_V7 + select HAVE_SMP + select ARM_AMBA + select MIGHT_HAVE_CACHE_L2X0 + select HAVE_SCHED_CLOCK + select NEED_MACH_MEMORY_H + select NEED_MACH_IO_H + select COMMON_CLK + select ARCH_HAS_CPUFREQ + select GENERIC_CLOCKEVENTS + select MACH_BCM2709 + select VC4 + select FIQ + help + This enables support for Broadcom BCM2709 boards. + config ARCH_MULTIPLATFORM bool "Allow multiple platforms to be selected" depends on MMU @@ -824,6 +860,9 @@ # Kconfigs may be included either alphabetically (according to the # plat- suffix) or along side the corresponding mach-* source. # +source "arch/arm/mach-bcm2708/Kconfig" +source "arch/arm/mach-bcm2709/Kconfig" + source "arch/arm/mach-mvebu/Kconfig" source "arch/arm/mach-alpine/Kconfig" diff -Nur '--exclude=.git' linux-stable/arch/arm/Kconfig.debug raspilinux/arch/arm/Kconfig.debug --- linux-stable/arch/arm/Kconfig.debug 2015-12-26 20:44:59.612056270 +0100 +++ raspilinux/arch/arm/Kconfig.debug 2015-12-26 19:08:30.224752550 +0100 @@ -1197,6 +1197,14 @@ options; the platform specific options are deprecated and will be soon removed. + config DEBUG_BCM2708_UART0 + bool "Broadcom BCM2708 UART0 (PL011)" + depends on MACH_BCM2708 + help + Say Y here if you want the debug print routines to direct + their output to UART 0. The port must have been initialised + by the boot-loader before use. + endchoice config DEBUG_AT91_UART diff -Nur '--exclude=.git' linux-stable/arch/arm/kernel/fiqasm.S raspilinux/arch/arm/kernel/fiqasm.S --- linux-stable/arch/arm/kernel/fiqasm.S 2015-12-26 20:38:42.834781621 +0100 +++ raspilinux/arch/arm/kernel/fiqasm.S 2015-12-26 19:08:30.300745463 +0100 @@ -47,3 +47,7 @@ mov r0, r0 @ avoid hazard prior to ARMv4 ret lr ENDPROC(__get_fiq_regs) + +ENTRY(__FIQ_Branch) + mov pc, r8 +ENDPROC(__FIQ_Branch) diff -Nur '--exclude=.git' linux-stable/arch/arm/kernel/head.S raspilinux/arch/arm/kernel/head.S --- linux-stable/arch/arm/kernel/head.S 2015-12-26 20:44:59.700048160 +0100 +++ raspilinux/arch/arm/kernel/head.S 2015-12-26 19:08:30.304745090 +0100 @@ -680,6 +680,14 @@ ldrcc r7, [r4], #4 @ use branch for delay slot bcc 1b ret lr + nop + nop + nop + nop + nop + nop + nop + nop #endif ENDPROC(__fixup_a_pv_table) diff -Nur '--exclude=.git' linux-stable/arch/arm/kernel/process.c raspilinux/arch/arm/kernel/process.c --- linux-stable/arch/arm/kernel/process.c 2015-12-26 20:44:59.704047791 +0100 +++ raspilinux/arch/arm/kernel/process.c 2015-12-26 19:08:30.304745090 +0100 @@ -98,6 +98,16 @@ } #endif +char bcm2708_reboot_mode = 'h'; + +int __init reboot_setup(char *str) +{ + bcm2708_reboot_mode = str[0]; + return 1; +} + +__setup("reboot=", reboot_setup); + void __show_regs(struct pt_regs *regs) { unsigned long flags; diff -Nur '--exclude=.git' linux-stable/arch/arm/lib/arm-mem.h raspilinux/arch/arm/lib/arm-mem.h --- linux-stable/arch/arm/lib/arm-mem.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/lib/arm-mem.h 2015-12-26 19:08:30.308744717 +0100 @@ -0,0 +1,159 @@ +/* +Copyright (c) 2013, Raspberry Pi Foundation +Copyright (c) 2013, RISC OS Open Ltd +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 the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +.macro myfunc fname + .func fname + .global fname +fname: +.endm + +.macro preload_leading_step1 backwards, ptr, base +/* If the destination is already 16-byte aligned, then we need to preload + * between 0 and prefetch_distance (inclusive) cache lines ahead so there + * are no gaps when the inner loop starts. + */ + .if backwards + sub ptr, base, #1 + bic ptr, ptr, #31 + .else + bic ptr, base, #31 + .endif + .set OFFSET, 0 + .rept prefetch_distance+1 + pld [ptr, #OFFSET] + .if backwards + .set OFFSET, OFFSET-32 + .else + .set OFFSET, OFFSET+32 + .endif + .endr +.endm + +.macro preload_leading_step2 backwards, ptr, base, leading_bytes, tmp +/* However, if the destination is not 16-byte aligned, we may need to + * preload one more cache line than that. The question we need to ask is: + * are the leading bytes more than the amount by which the source + * pointer will be rounded down for preloading, and if so, by how many + * cache lines? + */ + .if backwards +/* Here we compare against how many bytes we are into the + * cache line, counting down from the highest such address. + * Effectively, we want to calculate + * leading_bytes = dst&15 + * cacheline_offset = 31-((src-leading_bytes-1)&31) + * extra_needed = leading_bytes - cacheline_offset + * and test if extra_needed is <= 0, or rearranging: + * leading_bytes + (src-leading_bytes-1)&31 <= 31 + */ + mov tmp, base, lsl #32-5 + sbc tmp, tmp, leading_bytes, lsl #32-5 + adds tmp, tmp, leading_bytes, lsl #32-5 + bcc 61f + pld [ptr, #-32*(prefetch_distance+1)] + .else +/* Effectively, we want to calculate + * leading_bytes = (-dst)&15 + * cacheline_offset = (src+leading_bytes)&31 + * extra_needed = leading_bytes - cacheline_offset + * and test if extra_needed is <= 0. + */ + mov tmp, base, lsl #32-5 + add tmp, tmp, leading_bytes, lsl #32-5 + rsbs tmp, tmp, leading_bytes, lsl #32-5 + bls 61f + pld [ptr, #32*(prefetch_distance+1)] + .endif +61: +.endm + +.macro preload_trailing backwards, base, remain, tmp + /* We need either 0, 1 or 2 extra preloads */ + .if backwards + rsb tmp, base, #0 + mov tmp, tmp, lsl #32-5 + .else + mov tmp, base, lsl #32-5 + .endif + adds tmp, tmp, remain, lsl #32-5 + adceqs tmp, tmp, #0 + /* The instruction above has two effects: ensures Z is only + * set if C was clear (so Z indicates that both shifted quantities + * were 0), and clears C if Z was set (so C indicates that the sum + * of the shifted quantities was greater and not equal to 32) */ + beq 82f + .if backwards + sub tmp, base, #1 + bic tmp, tmp, #31 + .else + bic tmp, base, #31 + .endif + bcc 81f + .if backwards + pld [tmp, #-32*(prefetch_distance+1)] +81: + pld [tmp, #-32*prefetch_distance] + .else + pld [tmp, #32*(prefetch_distance+2)] +81: + pld [tmp, #32*(prefetch_distance+1)] + .endif +82: +.endm + +.macro preload_all backwards, narrow_case, shift, base, remain, tmp0, tmp1 + .if backwards + sub tmp0, base, #1 + bic tmp0, tmp0, #31 + pld [tmp0] + sub tmp1, base, remain, lsl #shift + .else + bic tmp0, base, #31 + pld [tmp0] + add tmp1, base, remain, lsl #shift + sub tmp1, tmp1, #1 + .endif + bic tmp1, tmp1, #31 + cmp tmp1, tmp0 + beq 92f + .if narrow_case + /* In this case, all the data fits in either 1 or 2 cache lines */ + pld [tmp1] + .else +91: + .if backwards + sub tmp0, tmp0, #32 + .else + add tmp0, tmp0, #32 + .endif + cmp tmp0, tmp1 + pld [tmp0] + bne 91b + .endif +92: +.endm diff -Nur '--exclude=.git' linux-stable/arch/arm/lib/copy_from_user.S raspilinux/arch/arm/lib/copy_from_user.S --- linux-stable/arch/arm/lib/copy_from_user.S 2015-12-26 20:44:59.708047422 +0100 +++ raspilinux/arch/arm/lib/copy_from_user.S 2015-12-26 19:08:30.308744717 +0100 @@ -89,11 +89,13 @@ .text -ENTRY(__copy_from_user) +ENTRY(__copy_from_user_std) +WEAK(__copy_from_user) #include "copy_template.S" ENDPROC(__copy_from_user) +ENDPROC(__copy_from_user_std) .pushsection .fixup,"ax" .align 0 diff -Nur '--exclude=.git' linux-stable/arch/arm/lib/exports_rpi.c raspilinux/arch/arm/lib/exports_rpi.c --- linux-stable/arch/arm/lib/exports_rpi.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/lib/exports_rpi.c 2015-12-26 19:08:30.308744717 +0100 @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2014, Raspberry Pi (Trading) Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +EXPORT_SYMBOL(memcmp); diff -Nur '--exclude=.git' linux-stable/arch/arm/lib/Makefile raspilinux/arch/arm/lib/Makefile --- linux-stable/arch/arm/lib/Makefile 2015-12-26 20:38:42.842780884 +0100 +++ raspilinux/arch/arm/lib/Makefile 2015-12-26 19:08:30.308744717 +0100 @@ -6,9 +6,8 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \ csumpartialcopy.o csumpartialcopyuser.o clearbit.o \ - delay.o delay-loop.o findbit.o memchr.o memcpy.o \ - memmove.o memset.o memzero.o setbit.o \ - strchr.o strrchr.o \ + delay.o delay-loop.o findbit.o memchr.o memzero.o \ + setbit.o strchr.o strrchr.o \ testchangebit.o testclearbit.o testsetbit.o \ ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ ucmpdi2.o lib1funcs.o div64.o \ @@ -18,6 +17,16 @@ mmu-y := clear_user.o copy_page.o getuser.o putuser.o \ copy_from_user.o copy_to_user.o +# Choose optimised implementations for Raspberry Pi +ifeq ($(CONFIG_MACH_BCM2708),y) + CFLAGS_uaccess_with_memcpy.o += -DCOPY_FROM_USER_THRESHOLD=1600 + CFLAGS_uaccess_with_memcpy.o += -DCOPY_TO_USER_THRESHOLD=672 + obj-$(CONFIG_MODULES) += exports_rpi.o + lib-y += memcpy_rpi.o memmove_rpi.o memset_rpi.o memcmp_rpi.o +else + lib-y += memcpy.o memmove.o memset.o +endif + # using lib_ here won't override already available weak symbols obj-$(CONFIG_UACCESS_WITH_MEMCPY) += uaccess_with_memcpy.o diff -Nur '--exclude=.git' linux-stable/arch/arm/lib/memcmp_rpi.S raspilinux/arch/arm/lib/memcmp_rpi.S --- linux-stable/arch/arm/lib/memcmp_rpi.S 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/lib/memcmp_rpi.S 2015-12-26 19:08:30.308744717 +0100 @@ -0,0 +1,285 @@ +/* +Copyright (c) 2013, Raspberry Pi Foundation +Copyright (c) 2013, RISC OS Open Ltd +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 the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include "arm-mem.h" + +/* Prevent the stack from becoming executable */ +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif + + .text + .arch armv6 + .object_arch armv4 + .arm + .altmacro + .p2align 2 + +.macro memcmp_process_head unaligned + .if unaligned + ldr DAT0, [S_1], #4 + ldr DAT1, [S_1], #4 + ldr DAT2, [S_1], #4 + ldr DAT3, [S_1], #4 + .else + ldmia S_1!, {DAT0, DAT1, DAT2, DAT3} + .endif + ldmia S_2!, {DAT4, DAT5, DAT6, DAT7} +.endm + +.macro memcmp_process_tail + cmp DAT0, DAT4 + cmpeq DAT1, DAT5 + cmpeq DAT2, DAT6 + cmpeq DAT3, DAT7 + bne 200f +.endm + +.macro memcmp_leading_31bytes + movs DAT0, OFF, lsl #31 + ldrmib DAT0, [S_1], #1 + ldrcsh DAT1, [S_1], #2 + ldrmib DAT4, [S_2], #1 + ldrcsh DAT5, [S_2], #2 + movpl DAT0, #0 + movcc DAT1, #0 + movpl DAT4, #0 + movcc DAT5, #0 + submi N, N, #1 + subcs N, N, #2 + cmp DAT0, DAT4 + cmpeq DAT1, DAT5 + bne 200f + movs DAT0, OFF, lsl #29 + ldrmi DAT0, [S_1], #4 + ldrcs DAT1, [S_1], #4 + ldrcs DAT2, [S_1], #4 + ldrmi DAT4, [S_2], #4 + ldmcsia S_2!, {DAT5, DAT6} + movpl DAT0, #0 + movcc DAT1, #0 + movcc DAT2, #0 + movpl DAT4, #0 + movcc DAT5, #0 + movcc DAT6, #0 + submi N, N, #4 + subcs N, N, #8 + cmp DAT0, DAT4 + cmpeq DAT1, DAT5 + cmpeq DAT2, DAT6 + bne 200f + tst OFF, #16 + beq 105f + memcmp_process_head 1 + sub N, N, #16 + memcmp_process_tail +105: +.endm + +.macro memcmp_trailing_15bytes unaligned + movs N, N, lsl #29 + .if unaligned + ldrcs DAT0, [S_1], #4 + ldrcs DAT1, [S_1], #4 + .else + ldmcsia S_1!, {DAT0, DAT1} + .endif + ldrmi DAT2, [S_1], #4 + ldmcsia S_2!, {DAT4, DAT5} + ldrmi DAT6, [S_2], #4 + movcc DAT0, #0 + movcc DAT1, #0 + movpl DAT2, #0 + movcc DAT4, #0 + movcc DAT5, #0 + movpl DAT6, #0 + cmp DAT0, DAT4 + cmpeq DAT1, DAT5 + cmpeq DAT2, DAT6 + bne 200f + movs N, N, lsl #2 + ldrcsh DAT0, [S_1], #2 + ldrmib DAT1, [S_1] + ldrcsh DAT4, [S_2], #2 + ldrmib DAT5, [S_2] + movcc DAT0, #0 + movpl DAT1, #0 + movcc DAT4, #0 + movpl DAT5, #0 + cmp DAT0, DAT4 + cmpeq DAT1, DAT5 + bne 200f +.endm + +.macro memcmp_long_inner_loop unaligned +110: + memcmp_process_head unaligned + pld [S_2, #prefetch_distance*32 + 16] + memcmp_process_tail + memcmp_process_head unaligned + pld [S_1, OFF] + memcmp_process_tail + subs N, N, #32 + bhs 110b + /* Just before the final (prefetch_distance+1) 32-byte blocks, + * deal with final preloads */ + preload_trailing 0, S_1, N, DAT0 + preload_trailing 0, S_2, N, DAT0 + add N, N, #(prefetch_distance+2)*32 - 16 +120: + memcmp_process_head unaligned + memcmp_process_tail + subs N, N, #16 + bhs 120b + /* Trailing words and bytes */ + tst N, #15 + beq 199f + memcmp_trailing_15bytes unaligned +199: /* Reached end without detecting a difference */ + mov a1, #0 + setend le + pop {DAT1-DAT6, pc} +.endm + +.macro memcmp_short_inner_loop unaligned + subs N, N, #16 /* simplifies inner loop termination */ + blo 122f +120: + memcmp_process_head unaligned + memcmp_process_tail + subs N, N, #16 + bhs 120b +122: /* Trailing words and bytes */ + tst N, #15 + beq 199f + memcmp_trailing_15bytes unaligned +199: /* Reached end without detecting a difference */ + mov a1, #0 + setend le + pop {DAT1-DAT6, pc} +.endm + +/* + * int memcmp(const void *s1, const void *s2, size_t n); + * On entry: + * a1 = pointer to buffer 1 + * a2 = pointer to buffer 2 + * a3 = number of bytes to compare (as unsigned chars) + * On exit: + * a1 = >0/=0/<0 if s1 >/=/< s2 + */ + +.set prefetch_distance, 2 + +ENTRY(memcmp) + S_1 .req a1 + S_2 .req a2 + N .req a3 + DAT0 .req a4 + DAT1 .req v1 + DAT2 .req v2 + DAT3 .req v3 + DAT4 .req v4 + DAT5 .req v5 + DAT6 .req v6 + DAT7 .req ip + OFF .req lr + + push {DAT1-DAT6, lr} + setend be /* lowest-addressed bytes are most significant */ + + /* To preload ahead as we go, we need at least (prefetch_distance+2) 32-byte blocks */ + cmp N, #(prefetch_distance+3)*32 - 1 + blo 170f + + /* Long case */ + /* Adjust N so that the decrement instruction can also test for + * inner loop termination. We want it to stop when there are + * (prefetch_distance+1) complete blocks to go. */ + sub N, N, #(prefetch_distance+2)*32 + preload_leading_step1 0, DAT0, S_1 + preload_leading_step1 0, DAT1, S_2 + tst S_2, #31 + beq 154f + rsb OFF, S_2, #0 /* no need to AND with 15 here */ + preload_leading_step2 0, DAT0, S_1, OFF, DAT2 + preload_leading_step2 0, DAT1, S_2, OFF, DAT2 + memcmp_leading_31bytes +154: /* Second source now cacheline (32-byte) aligned; we have at + * least one prefetch to go. */ + /* Prefetch offset is best selected such that it lies in the + * first 8 of each 32 bytes - but it's just as easy to aim for + * the first one */ + and OFF, S_1, #31 + rsb OFF, OFF, #32*prefetch_distance + tst S_1, #3 + bne 140f + memcmp_long_inner_loop 0 +140: memcmp_long_inner_loop 1 + +170: /* Short case */ + teq N, #0 + beq 199f + preload_all 0, 0, 0, S_1, N, DAT0, DAT1 + preload_all 0, 0, 0, S_2, N, DAT0, DAT1 + tst S_2, #3 + beq 174f +172: subs N, N, #1 + blo 199f + ldrb DAT0, [S_1], #1 + ldrb DAT4, [S_2], #1 + cmp DAT0, DAT4 + bne 200f + tst S_2, #3 + bne 172b +174: /* Second source now 4-byte aligned; we have 0 or more bytes to go */ + tst S_1, #3 + bne 140f + memcmp_short_inner_loop 0 +140: memcmp_short_inner_loop 1 + +200: /* Difference found: determine sign. */ + movhi a1, #1 + movlo a1, #-1 + setend le + pop {DAT1-DAT6, pc} + + .unreq S_1 + .unreq S_2 + .unreq N + .unreq DAT0 + .unreq DAT1 + .unreq DAT2 + .unreq DAT3 + .unreq DAT4 + .unreq DAT5 + .unreq DAT6 + .unreq DAT7 + .unreq OFF +ENDPROC(memcmp) diff -Nur '--exclude=.git' linux-stable/arch/arm/lib/memcpymove.h raspilinux/arch/arm/lib/memcpymove.h --- linux-stable/arch/arm/lib/memcpymove.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/lib/memcpymove.h 2015-12-26 19:08:30.308744717 +0100 @@ -0,0 +1,506 @@ +/* +Copyright (c) 2013, Raspberry Pi Foundation +Copyright (c) 2013, RISC OS Open Ltd +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 the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +.macro unaligned_words backwards, align, use_pld, words, r0, r1, r2, r3, r4, r5, r6, r7, r8 + .if words == 1 + .if backwards + mov r1, r0, lsl #32-align*8 + ldr r0, [S, #-4]! + orr r1, r1, r0, lsr #align*8 + str r1, [D, #-4]! + .else + mov r0, r1, lsr #align*8 + ldr r1, [S, #4]! + orr r0, r0, r1, lsl #32-align*8 + str r0, [D], #4 + .endif + .elseif words == 2 + .if backwards + ldr r1, [S, #-4]! + mov r2, r0, lsl #32-align*8 + ldr r0, [S, #-4]! + orr r2, r2, r1, lsr #align*8 + mov r1, r1, lsl #32-align*8 + orr r1, r1, r0, lsr #align*8 + stmdb D!, {r1, r2} + .else + ldr r1, [S, #4]! + mov r0, r2, lsr #align*8 + ldr r2, [S, #4]! + orr r0, r0, r1, lsl #32-align*8 + mov r1, r1, lsr #align*8 + orr r1, r1, r2, lsl #32-align*8 + stmia D!, {r0, r1} + .endif + .elseif words == 4 + .if backwards + ldmdb S!, {r2, r3} + mov r4, r0, lsl #32-align*8 + ldmdb S!, {r0, r1} + orr r4, r4, r3, lsr #align*8 + mov r3, r3, lsl #32-align*8 + orr r3, r3, r2, lsr #align*8 + mov r2, r2, lsl #32-align*8 + orr r2, r2, r1, lsr #align*8 + mov r1, r1, lsl #32-align*8 + orr r1, r1, r0, lsr #align*8 + stmdb D!, {r1, r2, r3, r4} + .else + ldmib S!, {r1, r2} + mov r0, r4, lsr #align*8 + ldmib S!, {r3, r4} + orr r0, r0, r1, lsl #32-align*8 + mov r1, r1, lsr #align*8 + orr r1, r1, r2, lsl #32-align*8 + mov r2, r2, lsr #align*8 + orr r2, r2, r3, lsl #32-align*8 + mov r3, r3, lsr #align*8 + orr r3, r3, r4, lsl #32-align*8 + stmia D!, {r0, r1, r2, r3} + .endif + .elseif words == 8 + .if backwards + ldmdb S!, {r4, r5, r6, r7} + mov r8, r0, lsl #32-align*8 + ldmdb S!, {r0, r1, r2, r3} + .if use_pld + pld [S, OFF] + .endif + orr r8, r8, r7, lsr #align*8 + mov r7, r7, lsl #32-align*8 + orr r7, r7, r6, lsr #align*8 + mov r6, r6, lsl #32-align*8 + orr r6, r6, r5, lsr #align*8 + mov r5, r5, lsl #32-align*8 + orr r5, r5, r4, lsr #align*8 + mov r4, r4, lsl #32-align*8 + orr r4, r4, r3, lsr #align*8 + mov r3, r3, lsl #32-align*8 + orr r3, r3, r2, lsr #align*8 + mov r2, r2, lsl #32-align*8 + orr r2, r2, r1, lsr #align*8 + mov r1, r1, lsl #32-align*8 + orr r1, r1, r0, lsr #align*8 + stmdb D!, {r5, r6, r7, r8} + stmdb D!, {r1, r2, r3, r4} + .else + ldmib S!, {r1, r2, r3, r4} + mov r0, r8, lsr #align*8 + ldmib S!, {r5, r6, r7, r8} + .if use_pld + pld [S, OFF] + .endif + orr r0, r0, r1, lsl #32-align*8 + mov r1, r1, lsr #align*8 + orr r1, r1, r2, lsl #32-align*8 + mov r2, r2, lsr #align*8 + orr r2, r2, r3, lsl #32-align*8 + mov r3, r3, lsr #align*8 + orr r3, r3, r4, lsl #32-align*8 + mov r4, r4, lsr #align*8 + orr r4, r4, r5, lsl #32-align*8 + mov r5, r5, lsr #align*8 + orr r5, r5, r6, lsl #32-align*8 + mov r6, r6, lsr #align*8 + orr r6, r6, r7, lsl #32-align*8 + mov r7, r7, lsr #align*8 + orr r7, r7, r8, lsl #32-align*8 + stmia D!, {r0, r1, r2, r3} + stmia D!, {r4, r5, r6, r7} + .endif + .endif +.endm + +.macro memcpy_leading_15bytes backwards, align + movs DAT1, DAT2, lsl #31 + sub N, N, DAT2 + .if backwards + ldrmib DAT0, [S, #-1]! + ldrcsh DAT1, [S, #-2]! + strmib DAT0, [D, #-1]! + strcsh DAT1, [D, #-2]! + .else + ldrmib DAT0, [S], #1 + ldrcsh DAT1, [S], #2 + strmib DAT0, [D], #1 + strcsh DAT1, [D], #2 + .endif + movs DAT1, DAT2, lsl #29 + .if backwards + ldrmi DAT0, [S, #-4]! + .if align == 0 + ldmcsdb S!, {DAT1, DAT2} + .else + ldrcs DAT2, [S, #-4]! + ldrcs DAT1, [S, #-4]! + .endif + strmi DAT0, [D, #-4]! + stmcsdb D!, {DAT1, DAT2} + .else + ldrmi DAT0, [S], #4 + .if align == 0 + ldmcsia S!, {DAT1, DAT2} + .else + ldrcs DAT1, [S], #4 + ldrcs DAT2, [S], #4 + .endif + strmi DAT0, [D], #4 + stmcsia D!, {DAT1, DAT2} + .endif +.endm + +.macro memcpy_trailing_15bytes backwards, align + movs N, N, lsl #29 + .if backwards + .if align == 0 + ldmcsdb S!, {DAT0, DAT1} + .else + ldrcs DAT1, [S, #-4]! + ldrcs DAT0, [S, #-4]! + .endif + ldrmi DAT2, [S, #-4]! + stmcsdb D!, {DAT0, DAT1} + strmi DAT2, [D, #-4]! + .else + .if align == 0 + ldmcsia S!, {DAT0, DAT1} + .else + ldrcs DAT0, [S], #4 + ldrcs DAT1, [S], #4 + .endif + ldrmi DAT2, [S], #4 + stmcsia D!, {DAT0, DAT1} + strmi DAT2, [D], #4 + .endif + movs N, N, lsl #2 + .if backwards + ldrcsh DAT0, [S, #-2]! + ldrmib DAT1, [S, #-1] + strcsh DAT0, [D, #-2]! + strmib DAT1, [D, #-1] + .else + ldrcsh DAT0, [S], #2 + ldrmib DAT1, [S] + strcsh DAT0, [D], #2 + strmib DAT1, [D] + .endif +.endm + +.macro memcpy_long_inner_loop backwards, align + .if align != 0 + .if backwards + ldr DAT0, [S, #-align]! + .else + ldr LAST, [S, #-align]! + .endif + .endif +110: + .if align == 0 + .if backwards + ldmdb S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST} + pld [S, OFF] + stmdb D!, {DAT4, DAT5, DAT6, LAST} + stmdb D!, {DAT0, DAT1, DAT2, DAT3} + .else + ldmia S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST} + pld [S, OFF] + stmia D!, {DAT0, DAT1, DAT2, DAT3} + stmia D!, {DAT4, DAT5, DAT6, LAST} + .endif + .else + unaligned_words backwards, align, 1, 8, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7, LAST + .endif + subs N, N, #32 + bhs 110b + /* Just before the final (prefetch_distance+1) 32-byte blocks, deal with final preloads */ + preload_trailing backwards, S, N, OFF + add N, N, #(prefetch_distance+2)*32 - 32 +120: + .if align == 0 + .if backwards + ldmdb S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST} + stmdb D!, {DAT4, DAT5, DAT6, LAST} + stmdb D!, {DAT0, DAT1, DAT2, DAT3} + .else + ldmia S!, {DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, LAST} + stmia D!, {DAT0, DAT1, DAT2, DAT3} + stmia D!, {DAT4, DAT5, DAT6, LAST} + .endif + .else + unaligned_words backwards, align, 0, 8, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7, LAST + .endif + subs N, N, #32 + bhs 120b + tst N, #16 + .if align == 0 + .if backwards + ldmnedb S!, {DAT0, DAT1, DAT2, LAST} + stmnedb D!, {DAT0, DAT1, DAT2, LAST} + .else + ldmneia S!, {DAT0, DAT1, DAT2, LAST} + stmneia D!, {DAT0, DAT1, DAT2, LAST} + .endif + .else + beq 130f + unaligned_words backwards, align, 0, 4, DAT0, DAT1, DAT2, DAT3, LAST +130: + .endif + /* Trailing words and bytes */ + tst N, #15 + beq 199f + .if align != 0 + add S, S, #align + .endif + memcpy_trailing_15bytes backwards, align +199: + pop {DAT3, DAT4, DAT5, DAT6, DAT7} + pop {D, DAT1, DAT2, pc} +.endm + +.macro memcpy_medium_inner_loop backwards, align +120: + .if backwards + .if align == 0 + ldmdb S!, {DAT0, DAT1, DAT2, LAST} + .else + ldr LAST, [S, #-4]! + ldr DAT2, [S, #-4]! + ldr DAT1, [S, #-4]! + ldr DAT0, [S, #-4]! + .endif + stmdb D!, {DAT0, DAT1, DAT2, LAST} + .else + .if align == 0 + ldmia S!, {DAT0, DAT1, DAT2, LAST} + .else + ldr DAT0, [S], #4 + ldr DAT1, [S], #4 + ldr DAT2, [S], #4 + ldr LAST, [S], #4 + .endif + stmia D!, {DAT0, DAT1, DAT2, LAST} + .endif + subs N, N, #16 + bhs 120b + /* Trailing words and bytes */ + tst N, #15 + beq 199f + memcpy_trailing_15bytes backwards, align +199: + pop {D, DAT1, DAT2, pc} +.endm + +.macro memcpy_short_inner_loop backwards, align + tst N, #16 + .if backwards + .if align == 0 + ldmnedb S!, {DAT0, DAT1, DAT2, LAST} + .else + ldrne LAST, [S, #-4]! + ldrne DAT2, [S, #-4]! + ldrne DAT1, [S, #-4]! + ldrne DAT0, [S, #-4]! + .endif + stmnedb D!, {DAT0, DAT1, DAT2, LAST} + .else + .if align == 0 + ldmneia S!, {DAT0, DAT1, DAT2, LAST} + .else + ldrne DAT0, [S], #4 + ldrne DAT1, [S], #4 + ldrne DAT2, [S], #4 + ldrne LAST, [S], #4 + .endif + stmneia D!, {DAT0, DAT1, DAT2, LAST} + .endif + memcpy_trailing_15bytes backwards, align +199: + pop {D, DAT1, DAT2, pc} +.endm + +.macro memcpy backwards + D .req a1 + S .req a2 + N .req a3 + DAT0 .req a4 + DAT1 .req v1 + DAT2 .req v2 + DAT3 .req v3 + DAT4 .req v4 + DAT5 .req v5 + DAT6 .req v6 + DAT7 .req sl + LAST .req ip + OFF .req lr + + .cfi_startproc + + push {D, DAT1, DAT2, lr} + + .cfi_def_cfa_offset 16 + .cfi_rel_offset D, 0 + .cfi_undefined S + .cfi_undefined N + .cfi_undefined DAT0 + .cfi_rel_offset DAT1, 4 + .cfi_rel_offset DAT2, 8 + .cfi_undefined LAST + .cfi_rel_offset lr, 12 + + .if backwards + add D, D, N + add S, S, N + .endif + + /* See if we're guaranteed to have at least one 16-byte aligned 16-byte write */ + cmp N, #31 + blo 170f + /* To preload ahead as we go, we need at least (prefetch_distance+2) 32-byte blocks */ + cmp N, #(prefetch_distance+3)*32 - 1 + blo 160f + + /* Long case */ + push {DAT3, DAT4, DAT5, DAT6, DAT7} + + .cfi_def_cfa_offset 36 + .cfi_rel_offset D, 20 + .cfi_rel_offset DAT1, 24 + .cfi_rel_offset DAT2, 28 + .cfi_rel_offset DAT3, 0 + .cfi_rel_offset DAT4, 4 + .cfi_rel_offset DAT5, 8 + .cfi_rel_offset DAT6, 12 + .cfi_rel_offset DAT7, 16 + .cfi_rel_offset lr, 32 + + /* Adjust N so that the decrement instruction can also test for + * inner loop termination. We want it to stop when there are + * (prefetch_distance+1) complete blocks to go. */ + sub N, N, #(prefetch_distance+2)*32 + preload_leading_step1 backwards, DAT0, S + .if backwards + /* Bug in GAS: it accepts, but mis-assembles the instruction + * ands DAT2, D, #60, 2 + * which sets DAT2 to the number of leading bytes until destination is aligned and also clears C (sets borrow) + */ + .word 0xE210513C + beq 154f + .else + ands DAT2, D, #15 + beq 154f + rsb DAT2, DAT2, #16 /* number of leading bytes until destination aligned */ + .endif + preload_leading_step2 backwards, DAT0, S, DAT2, OFF + memcpy_leading_15bytes backwards, 1 +154: /* Destination now 16-byte aligned; we have at least one prefetch as well as at least one 16-byte output block */ + /* Prefetch offset is best selected such that it lies in the first 8 of each 32 bytes - but it's just as easy to aim for the first one */ + .if backwards + rsb OFF, S, #3 + and OFF, OFF, #28 + sub OFF, OFF, #32*(prefetch_distance+1) + .else + and OFF, S, #28 + rsb OFF, OFF, #32*prefetch_distance + .endif + movs DAT0, S, lsl #31 + bhi 157f + bcs 156f + bmi 155f + memcpy_long_inner_loop backwards, 0 +155: memcpy_long_inner_loop backwards, 1 +156: memcpy_long_inner_loop backwards, 2 +157: memcpy_long_inner_loop backwards, 3 + + .cfi_def_cfa_offset 16 + .cfi_rel_offset D, 0 + .cfi_rel_offset DAT1, 4 + .cfi_rel_offset DAT2, 8 + .cfi_same_value DAT3 + .cfi_same_value DAT4 + .cfi_same_value DAT5 + .cfi_same_value DAT6 + .cfi_same_value DAT7 + .cfi_rel_offset lr, 12 + +160: /* Medium case */ + preload_all backwards, 0, 0, S, N, DAT2, OFF + sub N, N, #16 /* simplifies inner loop termination */ + .if backwards + ands DAT2, D, #15 + beq 164f + .else + ands DAT2, D, #15 + beq 164f + rsb DAT2, DAT2, #16 + .endif + memcpy_leading_15bytes backwards, align +164: /* Destination now 16-byte aligned; we have at least one 16-byte output block */ + tst S, #3 + bne 140f + memcpy_medium_inner_loop backwards, 0 +140: memcpy_medium_inner_loop backwards, 1 + +170: /* Short case, less than 31 bytes, so no guarantee of at least one 16-byte block */ + teq N, #0 + beq 199f + preload_all backwards, 1, 0, S, N, DAT2, LAST + tst D, #3 + beq 174f +172: subs N, N, #1 + blo 199f + .if backwards + ldrb DAT0, [S, #-1]! + strb DAT0, [D, #-1]! + .else + ldrb DAT0, [S], #1 + strb DAT0, [D], #1 + .endif + tst D, #3 + bne 172b +174: /* Destination now 4-byte aligned; we have 0 or more output bytes to go */ + tst S, #3 + bne 140f + memcpy_short_inner_loop backwards, 0 +140: memcpy_short_inner_loop backwards, 1 + + .cfi_endproc + + .unreq D + .unreq S + .unreq N + .unreq DAT0 + .unreq DAT1 + .unreq DAT2 + .unreq DAT3 + .unreq DAT4 + .unreq DAT5 + .unreq DAT6 + .unreq DAT7 + .unreq LAST + .unreq OFF +.endm diff -Nur '--exclude=.git' linux-stable/arch/arm/lib/memcpy_rpi.S raspilinux/arch/arm/lib/memcpy_rpi.S --- linux-stable/arch/arm/lib/memcpy_rpi.S 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/lib/memcpy_rpi.S 2015-12-26 19:08:30.308744717 +0100 @@ -0,0 +1,59 @@ +/* +Copyright (c) 2013, Raspberry Pi Foundation +Copyright (c) 2013, RISC OS Open Ltd +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 the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include "arm-mem.h" +#include "memcpymove.h" + +/* Prevent the stack from becoming executable */ +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif + + .text + .arch armv6 + .object_arch armv4 + .arm + .altmacro + .p2align 2 + +/* + * void *memcpy(void * restrict s1, const void * restrict s2, size_t n); + * On entry: + * a1 = pointer to destination + * a2 = pointer to source + * a3 = number of bytes to copy + * On exit: + * a1 preserved + */ + +.set prefetch_distance, 3 + +ENTRY(memcpy) + memcpy 0 +ENDPROC(memcpy) diff -Nur '--exclude=.git' linux-stable/arch/arm/lib/memmove_rpi.S raspilinux/arch/arm/lib/memmove_rpi.S --- linux-stable/arch/arm/lib/memmove_rpi.S 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/lib/memmove_rpi.S 2015-12-26 19:08:30.308744717 +0100 @@ -0,0 +1,61 @@ +/* +Copyright (c) 2013, Raspberry Pi Foundation +Copyright (c) 2013, RISC OS Open Ltd +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 the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include "arm-mem.h" +#include "memcpymove.h" + +/* Prevent the stack from becoming executable */ +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif + + .text + .arch armv6 + .object_arch armv4 + .arm + .altmacro + .p2align 2 + +/* + * void *memmove(void *s1, const void *s2, size_t n); + * On entry: + * a1 = pointer to destination + * a2 = pointer to source + * a3 = number of bytes to copy + * On exit: + * a1 preserved + */ + +.set prefetch_distance, 3 + +ENTRY(memmove) + cmp a2, a1 + bpl memcpy /* pl works even over -1 - 0 and 0x7fffffff - 0x80000000 boundaries */ + memcpy 1 +ENDPROC(memmove) diff -Nur '--exclude=.git' linux-stable/arch/arm/lib/memset_rpi.S raspilinux/arch/arm/lib/memset_rpi.S --- linux-stable/arch/arm/lib/memset_rpi.S 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/lib/memset_rpi.S 2015-12-26 19:08:30.308744717 +0100 @@ -0,0 +1,121 @@ +/* +Copyright (c) 2013, Raspberry Pi Foundation +Copyright (c) 2013, RISC OS Open Ltd +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 the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include "arm-mem.h" + +/* Prevent the stack from becoming executable */ +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif + + .text + .arch armv6 + .object_arch armv4 + .arm + .altmacro + .p2align 2 + +/* + * void *memset(void *s, int c, size_t n); + * On entry: + * a1 = pointer to buffer to fill + * a2 = byte pattern to fill with (caller-narrowed) + * a3 = number of bytes to fill + * On exit: + * a1 preserved + */ +ENTRY(memset) + S .req a1 + DAT0 .req a2 + N .req a3 + DAT1 .req a4 + DAT2 .req ip + DAT3 .req lr + + orr DAT0, DAT0, lsl #8 + push {S, lr} + orr DAT0, DAT0, lsl #16 + mov DAT1, DAT0 + + /* See if we're guaranteed to have at least one 16-byte aligned 16-byte write */ + cmp N, #31 + blo 170f + +161: sub N, N, #16 /* simplifies inner loop termination */ + /* Leading words and bytes */ + tst S, #15 + beq 164f + rsb DAT3, S, #0 /* bits 0-3 = number of leading bytes until aligned */ + movs DAT2, DAT3, lsl #31 + submi N, N, #1 + strmib DAT0, [S], #1 + subcs N, N, #2 + strcsh DAT0, [S], #2 + movs DAT2, DAT3, lsl #29 + submi N, N, #4 + strmi DAT0, [S], #4 + subcs N, N, #8 + stmcsia S!, {DAT0, DAT1} +164: /* Delayed set up of DAT2 and DAT3 so we could use them as scratch registers above */ + mov DAT2, DAT0 + mov DAT3, DAT0 + /* Now the inner loop of 16-byte stores */ +165: stmia S!, {DAT0, DAT1, DAT2, DAT3} + subs N, N, #16 + bhs 165b +166: /* Trailing words and bytes */ + movs N, N, lsl #29 + stmcsia S!, {DAT0, DAT1} + strmi DAT0, [S], #4 + movs N, N, lsl #2 + strcsh DAT0, [S], #2 + strmib DAT0, [S] +199: pop {S, pc} + +170: /* Short case */ + mov DAT2, DAT0 + mov DAT3, DAT0 + tst S, #3 + beq 174f +172: subs N, N, #1 + blo 199b + strb DAT0, [S], #1 + tst S, #3 + bne 172b +174: tst N, #16 + stmneia S!, {DAT0, DAT1, DAT2, DAT3} + b 166b + + .unreq S + .unreq DAT0 + .unreq N + .unreq DAT1 + .unreq DAT2 + .unreq DAT3 +ENDPROC(memset) diff -Nur '--exclude=.git' linux-stable/arch/arm/lib/uaccess_with_memcpy.c raspilinux/arch/arm/lib/uaccess_with_memcpy.c --- linux-stable/arch/arm/lib/uaccess_with_memcpy.c 2015-12-26 20:44:59.708047422 +0100 +++ raspilinux/arch/arm/lib/uaccess_with_memcpy.c 2015-12-26 19:08:30.308744717 +0100 @@ -22,6 +22,14 @@ #include #include +#ifndef COPY_FROM_USER_THRESHOLD +#define COPY_FROM_USER_THRESHOLD 64 +#endif + +#ifndef COPY_TO_USER_THRESHOLD +#define COPY_TO_USER_THRESHOLD 64 +#endif + static int pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp) { @@ -85,7 +93,44 @@ return 1; } -static unsigned long noinline +static int +pin_page_for_read(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp) +{ + unsigned long addr = (unsigned long)_addr; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + pud_t *pud; + spinlock_t *ptl; + + pgd = pgd_offset(current->mm, addr); + if (unlikely(pgd_none(*pgd) || pgd_bad(*pgd))) + { + return 0; + } + pud = pud_offset(pgd, addr); + if (unlikely(pud_none(*pud) || pud_bad(*pud))) + { + return 0; + } + + pmd = pmd_offset(pud, addr); + if (unlikely(pmd_none(*pmd) || pmd_bad(*pmd))) + return 0; + + pte = pte_offset_map_lock(current->mm, pmd, addr, &ptl); + if (unlikely(!pte_present(*pte) || !pte_young(*pte))) { + pte_unmap_unlock(pte, ptl); + return 0; + } + + *ptep = pte; + *ptlp = ptl; + + return 1; +} + +unsigned long noinline __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) { int atomic; @@ -135,6 +180,54 @@ return n; } +unsigned long noinline +__copy_from_user_memcpy(void *to, const void __user *from, unsigned long n) +{ + int atomic; + + if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { + memcpy(to, (const void *)from, n); + return 0; + } + + /* the mmap semaphore is taken only if not in an atomic context */ + atomic = in_atomic(); + + if (!atomic) + down_read(¤t->mm->mmap_sem); + while (n) { + pte_t *pte; + spinlock_t *ptl; + int tocopy; + + while (!pin_page_for_read(from, &pte, &ptl)) { + char temp; + if (!atomic) + up_read(¤t->mm->mmap_sem); + if (__get_user(temp, (char __user *)from)) + goto out; + if (!atomic) + down_read(¤t->mm->mmap_sem); + } + + tocopy = (~(unsigned long)from & ~PAGE_MASK) + 1; + if (tocopy > n) + tocopy = n; + + memcpy(to, (const void *)from, tocopy); + to += tocopy; + from += tocopy; + n -= tocopy; + + pte_unmap_unlock(pte, ptl); + } + if (!atomic) + up_read(¤t->mm->mmap_sem); + +out: + return n; +} + unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n) { @@ -145,10 +238,25 @@ * With frame pointer disabled, tail call optimization kicks in * as well making this test almost invisible. */ - if (n < 64) + if (n < COPY_TO_USER_THRESHOLD) return __copy_to_user_std(to, from, n); return __copy_to_user_memcpy(to, from, n); } + +unsigned long +__copy_from_user(void *to, const void __user *from, unsigned long n) +{ + /* + * This test is stubbed out of the main function above to keep + * the overhead for small copies low by avoiding a large + * register dump on the stack just to reload them right away. + * With frame pointer disabled, tail call optimization kicks in + * as well making this test almost invisible. + */ + if (n < COPY_FROM_USER_THRESHOLD) + return __copy_from_user_std(to, from, n); + return __copy_from_user_memcpy(to, from, n); +} static unsigned long noinline __clear_user_memset(void __user *addr, unsigned long n) diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm/board_bcm2835.c raspilinux/arch/arm/mach-bcm/board_bcm2835.c --- linux-stable/arch/arm/mach-bcm/board_bcm2835.c 2015-12-26 20:44:59.712047054 +0100 +++ raspilinux/arch/arm/mach-bcm/board_bcm2835.c 2015-12-26 19:08:30.312744344 +0100 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -107,6 +108,9 @@ static void __init bcm2835_init(void) { + struct device_node *np = of_find_node_by_path("/system"); + u32 val; + u64 val64; int ret; bcm2835_setup_restart(); @@ -121,6 +125,11 @@ pr_err("of_platform_populate failed: %d\n", ret); BUG(); } + + if (!of_property_read_u32(np, "linux,revision", &val)) + system_rev = val; + if (!of_property_read_u64(np, "linux,serial", &val64)) + system_serial_low = val64; } static const char * const bcm2835_compat[] = { diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm/Kconfig raspilinux/arch/arm/mach-bcm/Kconfig --- linux-stable/arch/arm/mach-bcm/Kconfig 2015-12-26 20:44:59.708047422 +0100 +++ raspilinux/arch/arm/mach-bcm/Kconfig 2015-12-26 19:08:30.312744344 +0100 @@ -114,6 +114,7 @@ select ARM_ERRATA_411920 select ARM_TIMER_SP804 select CLKSRC_OF + select FIQ select PINCTRL select PINCTRL_BCM2835 help diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/armctrl.c raspilinux/arch/arm/mach-bcm2708/armctrl.c --- linux-stable/arch/arm/mach-bcm2708/armctrl.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/armctrl.c 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,315 @@ +/* + * linux/arch/arm/mach-bcm2708/armctrl.c + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "armctrl.h" + +/* For support of kernels >= 3.0 assume only one VIC for now*/ +static unsigned int remap_irqs[(INTERRUPT_ARASANSDIO + 1) - INTERRUPT_JPEG] = { + INTERRUPT_VC_JPEG, + INTERRUPT_VC_USB, + INTERRUPT_VC_3D, + INTERRUPT_VC_DMA2, + INTERRUPT_VC_DMA3, + INTERRUPT_VC_I2C, + INTERRUPT_VC_SPI, + INTERRUPT_VC_I2SPCM, + INTERRUPT_VC_SDIO, + INTERRUPT_VC_UART, + INTERRUPT_VC_ARASANSDIO +}; + +static void armctrl_mask_irq(struct irq_data *d) +{ + static const unsigned int disables[4] = { + ARM_IRQ_DIBL1, + ARM_IRQ_DIBL2, + ARM_IRQ_DIBL3, + 0 + }; + + if (d->irq >= FIQ_START) { + writel(0, __io_address(ARM_IRQ_FAST)); + } else { + unsigned int data = (unsigned int)irq_get_chip_data(d->irq); + writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3])); + } +} + +static void armctrl_unmask_irq(struct irq_data *d) +{ + static const unsigned int enables[4] = { + ARM_IRQ_ENBL1, + ARM_IRQ_ENBL2, + ARM_IRQ_ENBL3, + 0 + }; + + if (d->irq >= FIQ_START) { + unsigned int data = + (unsigned int)irq_get_chip_data(d->irq) - FIQ_START; + writel(0x80 | data, __io_address(ARM_IRQ_FAST)); + } else { + unsigned int data = (unsigned int)irq_get_chip_data(d->irq); + writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3])); + } +} + +#ifdef CONFIG_OF + +#define NR_IRQS_BANK0 21 +#define NR_BANKS 3 +#define IRQS_PER_BANK 32 + +/* from drivers/irqchip/irq-bcm2835.c */ +static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr, + const u32 *intspec, unsigned int intsize, + unsigned long *out_hwirq, unsigned int *out_type) +{ + if (WARN_ON(intsize != 2)) + return -EINVAL; + + if (WARN_ON(intspec[0] >= NR_BANKS)) + return -EINVAL; + + if (WARN_ON(intspec[1] >= IRQS_PER_BANK)) + return -EINVAL; + + if (WARN_ON(intspec[0] == 0 && intspec[1] >= NR_IRQS_BANK0)) + return -EINVAL; + + if (intspec[0] == 0) + *out_hwirq = ARM_IRQ0_BASE + intspec[1]; + else if (intspec[0] == 1) + *out_hwirq = ARM_IRQ1_BASE + intspec[1]; + else + *out_hwirq = ARM_IRQ2_BASE + intspec[1]; + + /* reverse remap_irqs[] */ + switch (*out_hwirq) { + case INTERRUPT_VC_JPEG: + *out_hwirq = INTERRUPT_JPEG; + break; + case INTERRUPT_VC_USB: + *out_hwirq = INTERRUPT_USB; + break; + case INTERRUPT_VC_3D: + *out_hwirq = INTERRUPT_3D; + break; + case INTERRUPT_VC_DMA2: + *out_hwirq = INTERRUPT_DMA2; + break; + case INTERRUPT_VC_DMA3: + *out_hwirq = INTERRUPT_DMA3; + break; + case INTERRUPT_VC_I2C: + *out_hwirq = INTERRUPT_I2C; + break; + case INTERRUPT_VC_SPI: + *out_hwirq = INTERRUPT_SPI; + break; + case INTERRUPT_VC_I2SPCM: + *out_hwirq = INTERRUPT_I2SPCM; + break; + case INTERRUPT_VC_SDIO: + *out_hwirq = INTERRUPT_SDIO; + break; + case INTERRUPT_VC_UART: + *out_hwirq = INTERRUPT_UART; + break; + case INTERRUPT_VC_ARASANSDIO: + *out_hwirq = INTERRUPT_ARASANSDIO; + break; + } + + *out_type = IRQ_TYPE_NONE; + return 0; +} + +static struct irq_domain_ops armctrl_ops = { + .xlate = armctrl_xlate +}; + +void __init armctrl_dt_init(void) +{ + struct device_node *np; + struct irq_domain *domain; + + np = of_find_compatible_node(NULL, NULL, "brcm,bcm2708-armctrl-ic"); + if (!np) + return; + + domain = irq_domain_add_legacy(np, BCM2708_ALLOC_IRQS, + IRQ_ARMCTRL_START, 0, + &armctrl_ops, NULL); + WARN_ON(!domain); +} +#else +void __init armctrl_dt_init(void) { } +#endif /* CONFIG_OF */ + +#if defined(CONFIG_PM) + +/* for kernels 3.xx use the new syscore_ops apis but for older kernels use the sys dev class */ + +/* Static defines + * struct armctrl_device - VIC PM device (< 3.xx) + * @sysdev: The system device which is registered. (< 3.xx) + * @irq: The IRQ number for the base of the VIC. + * @base: The register base for the VIC. + * @resume_sources: A bitmask of interrupts for resume. + * @resume_irqs: The IRQs enabled for resume. + * @int_select: Save for VIC_INT_SELECT. + * @int_enable: Save for VIC_INT_ENABLE. + * @soft_int: Save for VIC_INT_SOFT. + * @protect: Save for VIC_PROTECT. + */ +struct armctrl_info { + void __iomem *base; + int irq; + u32 resume_sources; + u32 resume_irqs; + u32 int_select; + u32 int_enable; + u32 soft_int; + u32 protect; +} armctrl; + +static int armctrl_suspend(void) +{ + return 0; +} + +static void armctrl_resume(void) +{ + return; +} + +/** + * armctrl_pm_register - Register a VIC for later power management control + * @base: The base address of the VIC. + * @irq: The base IRQ for the VIC. + * @resume_sources: bitmask of interrupts allowed for resume sources. + * + * For older kernels (< 3.xx) do - + * Register the VIC with the system device tree so that it can be notified + * of suspend and resume requests and ensure that the correct actions are + * taken to re-instate the settings on resume. + */ +static void __init armctrl_pm_register(void __iomem * base, unsigned int irq, + u32 resume_sources) +{ + armctrl.base = base; + armctrl.resume_sources = resume_sources; + armctrl.irq = irq; +} + +static int armctrl_set_wake(struct irq_data *d, unsigned int on) +{ + unsigned int off = d->irq & 31; + u32 bit = 1 << off; + + if (!(bit & armctrl.resume_sources)) + return -EINVAL; + + if (on) + armctrl.resume_irqs |= bit; + else + armctrl.resume_irqs &= ~bit; + + return 0; +} + +#else +static inline void armctrl_pm_register(void __iomem * base, unsigned int irq, + u32 arg1) +{ +} + +#define armctrl_suspend NULL +#define armctrl_resume NULL +#define armctrl_set_wake NULL +#endif /* CONFIG_PM */ + +static struct syscore_ops armctrl_syscore_ops = { + .suspend = armctrl_suspend, + .resume = armctrl_resume, +}; + +/** + * armctrl_syscore_init - initicall to register VIC pm functions + * + * This is called via late_initcall() to register + * the resources for the VICs due to the early + * nature of the VIC's registration. +*/ +static int __init armctrl_syscore_init(void) +{ + register_syscore_ops(&armctrl_syscore_ops); + return 0; +} + +late_initcall(armctrl_syscore_init); + +static struct irq_chip armctrl_chip = { + .name = "ARMCTRL", + .irq_ack = NULL, + .irq_mask = armctrl_mask_irq, + .irq_unmask = armctrl_unmask_irq, + .irq_set_wake = armctrl_set_wake, +}; + +/** + * armctrl_init - initialise a vectored interrupt controller + * @base: iomem base address + * @irq_start: starting interrupt number, must be muliple of 32 + * @armctrl_sources: bitmask of interrupt sources to allow + * @resume_sources: bitmask of interrupt sources to allow for resume + */ +int __init armctrl_init(void __iomem * base, unsigned int irq_start, + u32 armctrl_sources, u32 resume_sources) +{ + unsigned int irq; + + for (irq = 0; irq < BCM2708_ALLOC_IRQS; irq++) { + unsigned int data = irq; + if (irq >= INTERRUPT_JPEG && irq <= INTERRUPT_ARASANSDIO) + data = remap_irqs[irq - INTERRUPT_JPEG]; + + irq_set_chip(irq, &armctrl_chip); + irq_set_chip_data(irq, (void *)data); + irq_set_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + + armctrl_pm_register(base, irq_start, resume_sources); + init_FIQ(FIQ_START); + armctrl_dt_init(); + return 0; +} diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/armctrl.h raspilinux/arch/arm/mach-bcm2708/armctrl.h --- linux-stable/arch/arm/mach-bcm2708/armctrl.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/armctrl.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,27 @@ +/* + * linux/arch/arm/mach-bcm2708/armctrl.h + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BCM2708_ARMCTRL_H +#define __BCM2708_ARMCTRL_H + +extern int __init armctrl_init(void __iomem * base, unsigned int irq_start, + u32 armctrl_sources, u32 resume_sources); + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/bcm2708.c raspilinux/arch/arm/mach-bcm2708/bcm2708.c --- linux-stable/arch/arm/mach-bcm2708/bcm2708.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/bcm2708.c 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,1162 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708.c + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "bcm2708.h" +#include "armctrl.h" + +#ifdef CONFIG_BCM_VC_CMA +#include +#endif + + +/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to + * give us IO access only to 64Mbytes of physical memory (26 bits). We could + * represent this window by setting our dmamasks to 26 bits but, in fact + * we're not going to use addresses outside this range (they're not in real + * memory) so we don't bother. + * + * In the future we might include code to use this IOMMU to remap other + * physical addresses onto VideoCore memory then the use of 32-bits would be + * more legitimate. + */ +#define DMA_MASK_BITS_COMMON 32 + +// use GPIO 4 for the one-wire GPIO pin, if enabled +#define W1_GPIO 4 +// ensure one-wire GPIO pullup is disabled by default +#define W1_PULLUP -1 + +/* command line parameters */ +static unsigned boardrev, serial; +static unsigned uart_clock = UART0_CLOCK; +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 unsigned w1_gpio_pullup = W1_PULLUP; +static bool vc_i2c_override = false; +static int pps_gpio_pin = -1; + +static unsigned use_dt = 0; + +static void __init bcm2708_init_led(void); + +void __init bcm2708_init_irq(void) +{ + armctrl_init(__io_address(ARMCTRL_IC_BASE), 0, 0, 0); +} + +static struct map_desc bcm2708_io_desc[] __initdata = { + { + .virtual = IO_ADDRESS(ARMCTRL_BASE), + .pfn = __phys_to_pfn(ARMCTRL_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(UART0_BASE), + .pfn = __phys_to_pfn(UART0_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(UART1_BASE), + .pfn = __phys_to_pfn(UART1_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(DMA_BASE), + .pfn = __phys_to_pfn(DMA_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(MCORE_BASE), + .pfn = __phys_to_pfn(MCORE_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(ST_BASE), + .pfn = __phys_to_pfn(ST_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(USB_BASE), + .pfn = __phys_to_pfn(USB_BASE), + .length = SZ_128K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(PM_BASE), + .pfn = __phys_to_pfn(PM_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(GPIO_BASE), + .pfn = __phys_to_pfn(GPIO_BASE), + .length = SZ_4K, + .type = MT_DEVICE} +}; + +void __init bcm2708_map_io(void) +{ + iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc)); +} + +/* The STC is a free running counter that increments at the rate of 1MHz */ +#define STC_FREQ_HZ 1000000 + +static inline uint32_t timer_read(void) +{ + /* STC: a free running counter that increments at the rate of 1MHz */ + return readl(__io_address(ST_BASE + 0x04)); +} + +static unsigned long bcm2708_read_current_timer(void) +{ + return timer_read(); +} + +static u64 notrace bcm2708_read_sched_clock(void) +{ + return timer_read(); +} + +static cycle_t clksrc_read(struct clocksource *cs) +{ + return timer_read(); +} + +static struct clocksource clocksource_stc = { + .name = "stc", + .rating = 300, + .read = clksrc_read, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +unsigned long frc_clock_ticks32(void) +{ + return timer_read(); +} + +static void __init bcm2708_clocksource_init(void) +{ + if (clocksource_register_hz(&clocksource_stc, STC_FREQ_HZ)) { + printk(KERN_ERR "timer: failed to initialize clock " + "source %s\n", clocksource_stc.name); + } +} + +struct clk __init *bcm2708_clk_register(const char *name, unsigned long fixed_rate) +{ + struct clk *clk; + + clk = clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, + fixed_rate); + if (IS_ERR(clk)) + pr_err("%s not registered\n", name); + + return clk; +} + +void __init bcm2708_register_clkdev(struct clk *clk, const char *name) +{ + int ret; + + ret = clk_register_clkdev(clk, NULL, name); + if (ret) + pr_err("%s alias not registered\n", name); +} + +void __init bcm2708_init_clocks(void) +{ + struct clk *clk; + + clk = bcm2708_clk_register("uart0_clk", uart_clock); + bcm2708_register_clkdev(clk, "dev:f1"); + + clk = bcm2708_clk_register("sdhost_clk", 250000000); + bcm2708_register_clkdev(clk, "mmc-bcm2835.0"); + bcm2708_register_clkdev(clk, "bcm2708_spi.0"); + bcm2708_register_clkdev(clk, "bcm2708_i2c.0"); + bcm2708_register_clkdev(clk, "bcm2708_i2c.1"); +} + +#define UART0_IRQ { IRQ_UART, 0 /*NO_IRQ*/ } +#define UART0_DMA { 15, 14 } + +AMBA_DEVICE(uart0, "dev:f1", UART0, NULL); + +static struct amba_device *amba_devs[] __initdata = { + &uart0_device, +}; + +static struct resource bcm2708_dmaengine_resources[] = { + { + .start = DMA_BASE, + .end = DMA_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_DMA0, + .end = IRQ_DMA0, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA1, + .end = IRQ_DMA1, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA2, + .end = IRQ_DMA2, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA3, + .end = IRQ_DMA3, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA4, + .end = IRQ_DMA4, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA5, + .end = IRQ_DMA5, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA6, + .end = IRQ_DMA6, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA7, + .end = IRQ_DMA7, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA8, + .end = IRQ_DMA8, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA9, + .end = IRQ_DMA9, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA10, + .end = IRQ_DMA10, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA11, + .end = IRQ_DMA11, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA12, + .end = IRQ_DMA12, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device bcm2708_dmaengine_device = { + .name = "bcm2708-dmaengine", + .id = -1, + .resource = bcm2708_dmaengine_resources, + .num_resources = ARRAY_SIZE(bcm2708_dmaengine_resources), +}; + +#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) +static struct w1_gpio_platform_data w1_gpio_pdata = { + .pin = W1_GPIO, + .ext_pullup_enable_pin = W1_PULLUP, + .is_open_drain = 0, +}; + +static struct platform_device w1_device = { + .name = "w1-gpio", + .id = -1, + .dev.platform_data = &w1_gpio_pdata, +}; +#endif + +static struct pps_gpio_platform_data pps_gpio_info = { + .assert_falling_edge = false, + .capture_clear = false, + .gpio_pin = -1, + .gpio_label = "PPS", +}; + +static struct platform_device pps_gpio_device = { + .name = "pps-gpio", + .id = PLATFORM_DEVID_NONE, + .dev.platform_data = &pps_gpio_info, +}; + +static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_fb_device = { + .name = "bcm2708_fb", + .id = -1, /* only one bcm2708_fb */ + .resource = NULL, + .num_resources = 0, + .dev = { + .dma_mask = &fb_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + +static struct resource bcm2708_usb_resources[] = { + [0] = { + .start = USB_BASE, + .end = USB_BASE + SZ_128K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MPHI_BASE, + .end = MPHI_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = IRQ_HOSTPORT, + .end = IRQ_HOSTPORT, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = IRQ_USB, + .end = IRQ_USB, + .flags = IORESOURCE_IRQ, + }, +}; + + +static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_usb_device = { + .name = "bcm2708_usb", + .id = -1, /* only one bcm2708_usb */ + .resource = bcm2708_usb_resources, + .num_resources = ARRAY_SIZE(bcm2708_usb_resources), + .dev = { + .dma_mask = &usb_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + +static struct resource bcm2708_vcio_resources[] = { + { + .start = ARMCTRL_0_MAIL0_BASE, + .end = ARMCTRL_0_MAIL0_BASE + SZ_64 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_ARM_MAILBOX, + .end = IRQ_ARM_MAILBOX, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_vcio_device = { + .name = "bcm2835-mbox", + .id = -1, /* only one VideoCore I/O area */ + .resource = bcm2708_vcio_resources, + .num_resources = ARRAY_SIZE(bcm2708_vcio_resources), + .dev = { + .dma_mask = &vcio_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + +static u64 rpifw_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_rpifw_device = { + .name = "raspberrypi-firmware", + .dev = { + .dma_mask = &rpifw_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + +static struct resource bcm2708_vchiq_resources[] = { + { + .start = ARMCTRL_0_BELL_BASE, + .end = ARMCTRL_0_BELL_BASE + 16, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_ARM_DOORBELL_0, + .end = IRQ_ARM_DOORBELL_0, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 vchiq_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_vchiq_device = { + .name = "bcm2835_vchiq", + .id = -1, + .resource = bcm2708_vchiq_resources, + .num_resources = ARRAY_SIZE(bcm2708_vchiq_resources), + .dev = { + .dma_mask = &vchiq_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + +#ifdef CONFIG_BCM2708_GPIO +#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" + +static struct resource bcm2708_gpio_resources[] = { + [0] = { /* general purpose I/O */ + .start = GPIO_BASE, + .end = GPIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_gpio_device = { + .name = BCM_GPIO_DRIVER_NAME, + .id = -1, /* only one VideoCore I/O area */ + .resource = bcm2708_gpio_resources, + .num_resources = ARRAY_SIZE(bcm2708_gpio_resources), + .dev = { + .dma_mask = &gpio_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; +#endif + +#ifdef CONFIG_MMC_BCM2835 /* Arasan emmc SD (new) */ +static struct resource bcm2835_emmc_resources[] = { + [0] = { + .start = EMMC_BASE, + .end = EMMC_BASE + SZ_256 - 1, /* we only need this area */ + /* the memory map actually makes SZ_4K available */ + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_ARASANSDIO, + .end = IRQ_ARASANSDIO, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 bcm2835_emmc_dmamask = 0xffffffffUL; + +struct platform_device bcm2835_emmc_device = { + .name = "mmc-bcm2835", + .id = 0, + .num_resources = ARRAY_SIZE(bcm2835_emmc_resources), + .resource = bcm2835_emmc_resources, + .dev = { + .dma_mask = &bcm2835_emmc_dmamask, + .coherent_dma_mask = 0xffffffffUL}, +}; +#endif /* CONFIG_MMC_BCM2835 */ + +static struct platform_device bcm2708_alsa_devices[] = { + [0] = { + .name = "bcm2835_AUD0", + .id = 0, /* first audio device */ + .resource = 0, + .num_resources = 0, + }, + [1] = { + .name = "bcm2835_AUD1", + .id = 1, /* second audio device */ + .resource = 0, + .num_resources = 0, + }, + [2] = { + .name = "bcm2835_AUD2", + .id = 2, /* third audio device */ + .resource = 0, + .num_resources = 0, + }, + [3] = { + .name = "bcm2835_AUD3", + .id = 3, /* forth audio device */ + .resource = 0, + .num_resources = 0, + }, + [4] = { + .name = "bcm2835_AUD4", + .id = 4, /* fifth audio device */ + .resource = 0, + .num_resources = 0, + }, + [5] = { + .name = "bcm2835_AUD5", + .id = 5, /* sixth audio device */ + .resource = 0, + .num_resources = 0, + }, + [6] = { + .name = "bcm2835_AUD6", + .id = 6, /* seventh audio device */ + .resource = 0, + .num_resources = 0, + }, + [7] = { + .name = "bcm2835_AUD7", + .id = 7, /* eighth audio device */ + .resource = 0, + .num_resources = 0, + }, +}; + +static struct resource bcm2708_spi_resources[] = { + { + .start = SPI0_BASE, + .end = SPI0_BASE + SZ_256 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_SPI, + .end = IRQ_SPI, + .flags = IORESOURCE_IRQ, + } +}; + + +static u64 bcm2708_spi_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); +static struct platform_device bcm2708_spi_device = { + .name = "bcm2708_spi", + .id = 0, + .num_resources = ARRAY_SIZE(bcm2708_spi_resources), + .resource = bcm2708_spi_resources, + .dev = { + .dma_mask = &bcm2708_spi_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON)}, +}; + +#ifdef CONFIG_BCM2708_SPIDEV +static struct spi_board_info bcm2708_spi_devices[] = { +#ifdef CONFIG_SPI_SPIDEV + { + .modalias = "spidev", + .max_speed_hz = 500000, + .bus_num = 0, + .chip_select = 0, + .mode = SPI_MODE_0, + }, { + .modalias = "spidev", + .max_speed_hz = 500000, + .bus_num = 0, + .chip_select = 1, + .mode = SPI_MODE_0, + } +#endif +}; +#endif + +static struct resource bcm2708_bsc0_resources[] = { + { + .start = BSC0_BASE, + .end = BSC0_BASE + SZ_256 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = INTERRUPT_I2C, + .end = INTERRUPT_I2C, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device bcm2708_bsc0_device = { + .name = "bcm2708_i2c", + .id = 0, + .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources), + .resource = bcm2708_bsc0_resources, +}; + + +static struct resource bcm2708_bsc1_resources[] = { + { + .start = BSC1_BASE, + .end = BSC1_BASE + SZ_256 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = INTERRUPT_I2C, + .end = INTERRUPT_I2C, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device bcm2708_bsc1_device = { + .name = "bcm2708_i2c", + .id = 1, + .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources), + .resource = bcm2708_bsc1_resources, +}; + +static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", +}; + +#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) +static struct resource bcm2708_i2s_resources[] = { + { + .start = I2S_BASE, + .end = I2S_BASE + 0x20, + .flags = IORESOURCE_MEM, + }, + { + .start = PCM_CLOCK_BASE, + .end = PCM_CLOCK_BASE + 0x02, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device bcm2708_i2s_device = { + .name = "bcm2708-i2s", + .id = 0, + .num_resources = ARRAY_SIZE(bcm2708_i2s_resources), + .resource = bcm2708_i2s_resources, +}; +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) +static struct platform_device snd_hifiberry_dac_device = { + .name = "snd-hifiberry-dac", + .id = 0, + .num_resources = 0, +}; + +static struct platform_device snd_pcm5102a_codec_device = { + .name = "pcm5102a-codec", + .id = -1, + .num_resources = 0, +}; +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) +static struct platform_device snd_rpi_hifiberry_dacplus_device = { + .name = "snd-rpi-hifiberry-dacplus", + .id = 0, + .num_resources = 0, +}; + +static struct i2c_board_info __initdata snd_pcm512x_hbdacplus_i2c_devices[] = { + { + I2C_BOARD_INFO("pcm5122", 0x4d) + }, +}; +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) +static struct platform_device snd_hifiberry_digi_device = { + .name = "snd-hifiberry-digi", + .id = 0, + .num_resources = 0, +}; + +static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { + { + I2C_BOARD_INFO("wm8804", 0x3b) + }, +}; + +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) +static struct platform_device snd_hifiberry_amp_device = { + .name = "snd-hifiberry-amp", + .id = 0, + .num_resources = 0, +}; + +static struct i2c_board_info __initdata snd_tas5713_i2c_devices[] = { + { + I2C_BOARD_INFO("tas5713", 0x1b) + }, +}; +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) +static struct platform_device snd_rpi_dac_device = { + .name = "snd-rpi-dac", + .id = 0, + .num_resources = 0, +}; + +static struct platform_device snd_pcm1794a_codec_device = { + .name = "pcm1794a-codec", + .id = -1, + .num_resources = 0, +}; +#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; + + ret = platform_device_register(pdev); + if (ret) + pr_debug("Unable to register platform device '%s': %d\n", + pdev->name, ret); + + return ret; +} + +/* + * Use these macros for platform and i2c devices that are present in the + * Device Tree. This way the devices are only added on non-DT systems. + */ +#define bcm_register_device_dt(pdev) \ + if (!use_dt) bcm_register_device(pdev) + +#define i2c_register_board_info_dt(busnum, info, n) \ + if (!use_dt) i2c_register_board_info(busnum, info, n) + +int calc_rsts(int partition) +{ + return PM_PASSWORD | + ((partition & (1 << 0)) << 0) | + ((partition & (1 << 1)) << 1) | + ((partition & (1 << 2)) << 2) | + ((partition & (1 << 3)) << 3) | + ((partition & (1 << 4)) << 4) | + ((partition & (1 << 5)) << 5); +} + +static void bcm2708_restart(enum reboot_mode mode, const char *cmd) +{ + extern char bcm2708_reboot_mode; + uint32_t pm_rstc, pm_wdog; + uint32_t timeout = 10; + uint32_t pm_rsts = 0; + + if(bcm2708_reboot_mode == 'q') + { + // NOOBS < 1.3 booting with reboot=q + pm_rsts = readl(__io_address(PM_RSTS)); + pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRQ_SET; + } + else if(bcm2708_reboot_mode == 'p') + { + // NOOBS < 1.3 halting + pm_rsts = readl(__io_address(PM_RSTS)); + pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRH_SET; + } + else + { + pm_rsts = calc_rsts(reboot_part); + } + + writel(pm_rsts, __io_address(PM_RSTS)); + + /* Setup watchdog for reset */ + pm_rstc = readl(__io_address(PM_RSTC)); + + pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) + pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; + + writel(pm_wdog, __io_address(PM_WDOG)); + writel(pm_rstc, __io_address(PM_RSTC)); +} + +/* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */ +static void bcm2708_power_off(void) +{ + extern char bcm2708_reboot_mode; + if(bcm2708_reboot_mode == 'q') + { + // NOOBS < v1.3 + bcm2708_restart('p', ""); + } + else + { + /* partition 63 is special code for HALT the bootloader knows not to boot*/ + reboot_part = 63; + /* continue with normal reset mechanism */ + bcm2708_restart(0, ""); + } +} + +static void __init bcm2708_init_uart1(void) +{ + struct device_node *np; + + np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); + if (of_device_is_available(np)) { + pr_info("bcm2708: Mini UART enabled\n"); + writel(1, __io_address(UART1_BASE + 0x4)); + } +} + +#ifdef CONFIG_OF +static void __init bcm2708_dt_init(void) +{ + int ret; + + of_clk_init(NULL); + ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + if (ret) { + pr_err("of_platform_populate failed: %d\n", ret); + /* Proceed as if CONFIG_OF was not defined */ + } else { + use_dt = 1; + } +} +#else +static void __init bcm2708_dt_init(void) { } +#endif /* CONFIG_OF */ + +void __init bcm2708_init(void) +{ + int i; + +#if defined(CONFIG_BCM_VC_CMA) + vc_cma_early_init(); +#endif + printk("bcm2708.uart_clock = %d\n", uart_clock); + pm_power_off = bcm2708_power_off; + + bcm2708_init_clocks(); + bcm2708_dt_init(); + + bcm_register_device_dt(&bcm2708_dmaengine_device); + bcm_register_device_dt(&bcm2708_vcio_device); + bcm_register_device_dt(&bcm2708_rpifw_device); + bcm_register_device_dt(&bcm2708_vchiq_device); +#ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); +#endif + +#if defined(CONFIG_PPS_CLIENT_GPIO) || defined(CONFIG_PPS_CLIENT_GPIO_MODULE) + if (!use_dt && (pps_gpio_pin >= 0)) { + pr_info("bcm2708: GPIO %d setup as pps-gpio device\n", pps_gpio_pin); + pps_gpio_info.gpio_pin = pps_gpio_pin; + pps_gpio_device.id = pps_gpio_pin; + bcm_register_device(&pps_gpio_device); + } +#endif + +#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) + w1_gpio_pdata.pin = w1_gpio_pin; + w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; + bcm_register_device_dt(&w1_device); +#endif + bcm_register_device_dt(&bcm2708_fb_device); + bcm_register_device_dt(&bcm2708_usb_device); + +#ifdef CONFIG_MMC_BCM2835 + bcm_register_device_dt(&bcm2835_emmc_device); +#endif + bcm2708_init_led(); + bcm2708_init_uart1(); + + /* Only create the platform devices for the ALSA driver in the + absence of an enabled "audio" DT node */ + if (!use_dt || + !of_device_is_available(of_find_node_by_path("/audio"))) { + for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) + bcm_register_device(&bcm2708_alsa_devices[i]); + } + + bcm_register_device_dt(&bcm2708_spi_device); + + if (vc_i2c_override) { + bcm_register_device_dt(&bcm2708_bsc0_device); + bcm_register_device_dt(&bcm2708_bsc1_device); + } else if ((boardrev & 0xffffff) == 0x2 || (boardrev & 0xffffff) == 0x3) { + bcm_register_device_dt(&bcm2708_bsc0_device); + } else { + bcm_register_device_dt(&bcm2708_bsc1_device); + } + + bcm_register_device_dt(&bcm2835_thermal_device); + +#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) + bcm_register_device_dt(&bcm2708_i2s_device); +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) + bcm_register_device_dt(&snd_hifiberry_dac_device); + bcm_register_device_dt(&snd_pcm5102a_codec_device); +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) + bcm_register_device_dt(&snd_rpi_hifiberry_dacplus_device); + i2c_register_board_info_dt(1, snd_pcm512x_hbdacplus_i2c_devices, ARRAY_SIZE(snd_pcm512x_hbdacplus_i2c_devices)); +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) + bcm_register_device_dt(&snd_hifiberry_digi_device); + i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) + bcm_register_device_dt(&snd_hifiberry_amp_device); + i2c_register_board_info_dt(1, snd_tas5713_i2c_devices, ARRAY_SIZE(snd_tas5713_i2c_devices)); +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) + bcm_register_device_dt(&snd_rpi_dac_device); + bcm_register_device_dt(&snd_pcm1794a_codec_device); +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) + bcm_register_device_dt(&snd_rpi_iqaudio_dac_device); + i2c_register_board_info_dt(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); +#endif + + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; + amba_device_register(d, &iomem_resource); + } + } + system_rev = boardrev; + system_serial_low = serial; + +#ifdef CONFIG_BCM2708_SPIDEV + if (!use_dt) + spi_register_board_info(bcm2708_spi_devices, + ARRAY_SIZE(bcm2708_spi_devices)); +#endif +} + +static void timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: /* Leave the timer disabled, .set_next_event will enable it */ + case CLOCK_EVT_MODE_SHUTDOWN: + break; + case CLOCK_EVT_MODE_PERIODIC: + + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_RESUME: + + default: + printk(KERN_ERR "timer_set_mode: unhandled mode:%d\n", + (int)mode); + break; + } + +} + +static int timer_set_next_event(unsigned long cycles, + struct clock_event_device *unused) +{ + unsigned long stc; + do { + stc = readl(__io_address(ST_BASE + 0x04)); + /* We could take a FIQ here, which may push ST above STC3 */ + writel(stc + cycles, __io_address(ST_BASE + 0x18)); + } while ((signed long) cycles >= 0 && + (signed long) (readl(__io_address(ST_BASE + 0x04)) - stc) + >= (signed long) cycles); + return 0; +} + +static struct clock_event_device timer0_clockevent = { + .name = "timer0", + .shift = 32, + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_mode = timer_set_mode, + .set_next_event = timer_set_next_event, +}; + +/* + * IRQ handler for the timer + */ +static irqreturn_t bcm2708_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = &timer0_clockevent; + + writel(1 << 3, __io_address(ST_BASE + 0x00)); /* stcs clear timer int */ + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction bcm2708_timer_irq = { + .name = "BCM2708 Timer Tick", + .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2708_timer_interrupt, +}; + +/* + * Set up timer interrupt, and return the current time in seconds. + */ + +static struct delay_timer bcm2708_delay_timer = { + .read_current_timer = bcm2708_read_current_timer, + .freq = STC_FREQ_HZ, +}; + +static void __init bcm2708_timer_init(void) +{ + /* init high res timer */ + bcm2708_clocksource_init(); + + /* + * Make irqs happen for the system timer + */ + setup_irq(IRQ_TIMER3, &bcm2708_timer_irq); + + sched_clock_register(bcm2708_read_sched_clock, 32, STC_FREQ_HZ); + + timer0_clockevent.mult = + div_sc(STC_FREQ_HZ, NSEC_PER_SEC, timer0_clockevent.shift); + timer0_clockevent.max_delta_ns = + clockevent_delta2ns(0xffffffff, &timer0_clockevent); + timer0_clockevent.min_delta_ns = + clockevent_delta2ns(0xf, &timer0_clockevent); + + timer0_clockevent.cpumask = cpumask_of(0); + clockevents_register_device(&timer0_clockevent); + + register_current_timer_delay(&bcm2708_delay_timer); +} + +#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) +#include + +static struct gpio_led bcm2708_leds[] = { + [0] = { + .gpio = 16, + .name = "led0", + .default_trigger = "mmc0", + .active_low = 1, + }, +}; + +static struct gpio_led_platform_data bcm2708_led_pdata = { + .num_leds = ARRAY_SIZE(bcm2708_leds), + .leds = bcm2708_leds, +}; + +static struct platform_device bcm2708_led_device = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &bcm2708_led_pdata, + }, +}; + +static void __init bcm2708_init_led(void) +{ + bcm2708_leds[0].gpio = disk_led_gpio; + bcm2708_leds[0].active_low = disk_led_active_low; + bcm_register_device_dt(&bcm2708_led_device); +} +#else +static inline void bcm2708_init_led(void) +{ +} +#endif + +void __init bcm2708_init_early(void) +{ + /* + * Some devices allocate their coherent buffers from atomic + * context. Increase size of atomic coherent pool to make sure such + * the allocations won't fail. + */ + init_dma_coherent_pool_size(SZ_4M); +} + +static void __init board_reserve(void) +{ +#if defined(CONFIG_BCM_VC_CMA) + vc_cma_reserve(); +#endif +} + +static const char * const bcm2708_compat[] = { + "brcm,bcm2708", + NULL +}; + +MACHINE_START(BCM2708, "BCM2708") + /* Maintainer: Broadcom Europe Ltd. */ + .map_io = bcm2708_map_io, + .init_irq = bcm2708_init_irq, + .init_time = bcm2708_timer_init, + .init_machine = bcm2708_init, + .init_early = bcm2708_init_early, + .reserve = board_reserve, + .restart = bcm2708_restart, + .dt_compat = bcm2708_compat, +MACHINE_END + +module_param(boardrev, uint, 0644); +module_param(serial, uint, 0644); +module_param(uart_clock, uint, 0644); +module_param(disk_led_gpio, uint, 0644); +module_param(disk_led_active_low, uint, 0644); +module_param(reboot_part, uint, 0644); +module_param(w1_gpio_pin, uint, 0644); +module_param(w1_gpio_pullup, uint, 0644); +module_param(vc_i2c_override, bool, 0644); +MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); +module_param(pps_gpio_pin, int, 0644); +MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/bcm2708_gpio.c raspilinux/arch/arm/mach-bcm2708/bcm2708_gpio.c --- linux-stable/arch/arm/mach-bcm2708/bcm2708_gpio.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/bcm2708_gpio.c 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,426 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708_gpio.c + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" +#define DRIVER_NAME BCM_GPIO_DRIVER_NAME +#define BCM_GPIO_USE_IRQ 1 + +#define GPIOFSEL(x) (0x00+(x)*4) +#define GPIOSET(x) (0x1c+(x)*4) +#define GPIOCLR(x) (0x28+(x)*4) +#define GPIOLEV(x) (0x34+(x)*4) +#define GPIOEDS(x) (0x40+(x)*4) +#define GPIOREN(x) (0x4c+(x)*4) +#define GPIOFEN(x) (0x58+(x)*4) +#define GPIOHEN(x) (0x64+(x)*4) +#define GPIOLEN(x) (0x70+(x)*4) +#define GPIOAREN(x) (0x7c+(x)*4) +#define GPIOAFEN(x) (0x88+(x)*4) +#define GPIOUD(x) (0x94+(x)*4) +#define GPIOUDCLK(x) (0x98+(x)*4) + +#define GPIO_BANKS 2 + +enum { GPIO_FSEL_INPUT, GPIO_FSEL_OUTPUT, + GPIO_FSEL_ALT5, GPIO_FSEL_ALT_4, + GPIO_FSEL_ALT0, GPIO_FSEL_ALT1, + GPIO_FSEL_ALT2, GPIO_FSEL_ALT3, +}; + + /* Each of the two spinlocks protects a different set of hardware + * regiters and data structurs. This decouples the code of the IRQ from + * the GPIO code. This also makes the case of a GPIO routine call from + * the IRQ code simpler. + */ +static DEFINE_SPINLOCK(lock); /* GPIO registers */ + +struct bcm2708_gpio { + struct list_head list; + void __iomem *base; + struct gpio_chip gc; + unsigned long rising[(BCM2708_NR_GPIOS + 31) / 32]; + unsigned long falling[(BCM2708_NR_GPIOS + 31) / 32]; + unsigned long high[(BCM2708_NR_GPIOS + 31) / 32]; + unsigned long low[(BCM2708_NR_GPIOS + 31) / 32]; +}; + +static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset, + int function) +{ + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); + unsigned long flags; + unsigned gpiodir; + unsigned gpio_bank = offset / 10; + 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 >= BCM2708_NR_GPIOS) + return -EINVAL; + + spin_lock_irqsave(&lock, flags); + + gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank)); + gpiodir &= ~(7 << gpio_field_offset); + gpiodir |= function << gpio_field_offset; + writel(gpiodir, gpio->base + GPIOFSEL(gpio_bank)); + spin_unlock_irqrestore(&lock, flags); + gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank)); + + return 0; +} + +static int bcm2708_gpio_dir_in(struct gpio_chip *gc, unsigned offset) +{ + return bcm2708_set_function(gc, offset, GPIO_FSEL_INPUT); +} + +static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value); +static int bcm2708_gpio_dir_out(struct gpio_chip *gc, unsigned offset, + int value) +{ + int ret; + ret = bcm2708_set_function(gc, offset, GPIO_FSEL_OUTPUT); + if (ret >= 0) + bcm2708_gpio_set(gc, offset, value); + return ret; +} + +static int bcm2708_gpio_get(struct gpio_chip *gc, unsigned offset) +{ + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); + unsigned gpio_bank = offset / 32; + unsigned gpio_field_offset = (offset - 32 * gpio_bank); + unsigned lev; + + 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)); + return 0x1 & (lev >> gpio_field_offset); +} + +static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value) +{ + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); + 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 >= BCM2708_NR_GPIOS) + return; + if (value) + writel(1 << gpio_field_offset, gpio->base + GPIOSET(gpio_bank)); + else + writel(1 << gpio_field_offset, gpio->base + GPIOCLR(gpio_bank)); +} + +/********************** + * extension to configure pullups + */ +int bcm2708_gpio_setpull(struct gpio_chip *gc, unsigned offset, + bcm2708_gpio_pull_t value) +{ + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); + unsigned gpio_bank = offset / 32; + unsigned gpio_field_offset = (offset - 32 * gpio_bank); + + if (offset >= BCM2708_NR_GPIOS) + return -EINVAL; + + switch (value) { + case BCM2708_PULL_UP: + writel(2, gpio->base + GPIOUD(0)); + break; + case BCM2708_PULL_DOWN: + writel(1, gpio->base + GPIOUD(0)); + break; + case BCM2708_PULL_OFF: + writel(0, gpio->base + GPIOUD(0)); + break; + } + + udelay(5); + writel(1 << gpio_field_offset, gpio->base + GPIOUDCLK(gpio_bank)); + udelay(5); + writel(0, gpio->base + GPIOUD(0)); + writel(0 << gpio_field_offset, gpio->base + GPIOUDCLK(gpio_bank)); + + return 0; +} +EXPORT_SYMBOL(bcm2708_gpio_setpull); + +/************************************************************************************************************************* + * bcm2708 GPIO IRQ + */ + +#if BCM_GPIO_USE_IRQ + +static int bcm2708_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) +{ + return gpio_to_irq(gpio); +} + +static int bcm2708_gpio_irq_set_type(struct irq_data *d, unsigned type) +{ + unsigned irq = d->irq; + struct bcm2708_gpio *gpio = irq_get_chip_data(irq); + unsigned gn = irq_to_gpio(irq); + unsigned gb = gn / 32; + unsigned go = gn % 32; + + gpio->rising[gb] &= ~(1 << go); + gpio->falling[gb] &= ~(1 << go); + gpio->high[gb] &= ~(1 << go); + gpio->low[gb] &= ~(1 << go); + + 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) + gpio->rising[gb] |= (1 << go); + if (type & IRQ_TYPE_EDGE_FALLING) + gpio->falling[gb] |= (1 << go); + if (type & IRQ_TYPE_LEVEL_HIGH) + gpio->high[gb] |= (1 << go); + if (type & IRQ_TYPE_LEVEL_LOW) + gpio->low[gb] |= (1 << go); + return 0; +} + +static void bcm2708_gpio_irq_mask(struct irq_data *d) +{ + unsigned irq = d->irq; + 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 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(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) +{ + unsigned irq = d->irq; + struct bcm2708_gpio *gpio = irq_get_chip_data(irq); + unsigned gn = irq_to_gpio(irq); + unsigned gb = gn / 32; + unsigned go = gn % 32; + 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)); + + if (gpio->rising[gb] & (1 << go)) { + writel(rising | (1 << go), gpio->base + GPIOREN(gb)); + } else { + writel(rising & ~(1 << go), gpio->base + GPIOREN(gb)); + } + + if (gpio->falling[gb] & (1 << go)) { + writel(falling | (1 << go), gpio->base + GPIOFEN(gb)); + } else { + writel(falling & ~(1 << go), gpio->base + GPIOFEN(gb)); + } + + if (gpio->high[gb] & (1 << go)) { + writel(high | (1 << go), gpio->base + GPIOHEN(gb)); + } else { + writel(high & ~(1 << go), gpio->base + GPIOHEN(gb)); + } + + if (gpio->low[gb] & (1 << go)) { + writel(low | (1 << go), gpio->base + GPIOLEN(gb)); + } else { + writel(low & ~(1 << go), gpio->base + GPIOLEN(gb)); + } +} + +static struct irq_chip bcm2708_irqchip = { + .name = "GPIO", + .irq_enable = bcm2708_gpio_irq_unmask, + .irq_disable = bcm2708_gpio_irq_mask, + .irq_unmask = bcm2708_gpio_irq_unmask, + .irq_mask = bcm2708_gpio_irq_mask, + .irq_set_type = bcm2708_gpio_irq_set_type, +}; + +static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id) +{ + unsigned long edsr; + unsigned bank; + int i; + unsigned gpio; + unsigned level_bits; + struct bcm2708_gpio *gpio_data = dev_id; + + for (bank = 0; bank < GPIO_BANKS; bank++) { + edsr = readl(__io_address(GPIO_BASE) + GPIOEDS(bank)); + level_bits = gpio_data->high[bank] | gpio_data->low[bank]; + + for_each_set_bit(i, &edsr, 32) { + gpio = i + bank * 32; + /* ack edge triggered IRQs immediately */ + if (!(level_bits & (1<gc.to_irq = bcm2708_gpio_to_irq; + + for (irq = GPIO_IRQ_START; irq < (GPIO_IRQ_START + GPIO_IRQS); irq++) { + irq_set_chip_data(irq, ucb); + irq_set_chip_and_handler(irq, &bcm2708_irqchip, + handle_simple_irq); + set_irq_flags(irq, IRQF_VALID); + } + + bcm2708_gpio_irq.dev_id = ucb; + setup_irq(IRQ_GPIO3, &bcm2708_gpio_irq); +} + +#else + +static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb) +{ +} + +#endif /* #if BCM_GPIO_USE_IRQ ***************************************************************************************************************** */ + +static int bcm2708_gpio_probe(struct platform_device *dev) +{ + struct bcm2708_gpio *ucb; + struct resource *res; + int bank; + int err = 0; + + printk(KERN_INFO DRIVER_NAME ": bcm2708_gpio_probe %p\n", dev); + + ucb = kzalloc(sizeof(*ucb), GFP_KERNEL); + if (NULL == ucb) { + printk(KERN_ERR DRIVER_NAME ": failed to allocate " + "mailbox memory\n"); + err = -ENOMEM; + goto err; + } + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + + platform_set_drvdata(dev, ucb); + ucb->base = __io_address(GPIO_BASE); + + ucb->gc.label = "bcm2708_gpio"; + ucb->gc.base = 0; + ucb->gc.ngpio = BCM2708_NR_GPIOS; + ucb->gc.owner = THIS_MODULE; + + ucb->gc.direction_input = bcm2708_gpio_dir_in; + ucb->gc.direction_output = bcm2708_gpio_dir_out; + ucb->gc.get = bcm2708_gpio_get; + ucb->gc.set = bcm2708_gpio_set; + ucb->gc.can_sleep = 0; + + for (bank = 0; bank < GPIO_BANKS; bank++) { + writel(0, ucb->base + GPIOREN(bank)); + writel(0, ucb->base + GPIOFEN(bank)); + writel(0, ucb->base + GPIOHEN(bank)); + writel(0, ucb->base + GPIOLEN(bank)); + writel(0, ucb->base + GPIOAREN(bank)); + writel(0, ucb->base + GPIOAFEN(bank)); + writel(~0, ucb->base + GPIOEDS(bank)); + } + + bcm2708_gpio_irq_init(ucb); + + err = gpiochip_add(&ucb->gc); + +err: + return err; + +} + +static int bcm2708_gpio_remove(struct platform_device *dev) +{ + int err = 0; + struct bcm2708_gpio *ucb = platform_get_drvdata(dev); + + printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_remove %p\n", dev); + + gpiochip_remove(&ucb->gc); + + platform_set_drvdata(dev, NULL); + kfree(ucb); + + return err; +} + +static struct platform_driver bcm2708_gpio_driver = { + .probe = bcm2708_gpio_probe, + .remove = bcm2708_gpio_remove, + .driver = { + .name = "bcm2708_gpio"}, +}; + +static int __init bcm2708_gpio_init(void) +{ + return platform_driver_register(&bcm2708_gpio_driver); +} + +static void __exit bcm2708_gpio_exit(void) +{ + platform_driver_unregister(&bcm2708_gpio_driver); +} + +module_init(bcm2708_gpio_init); +module_exit(bcm2708_gpio_exit); + +MODULE_DESCRIPTION("Broadcom BCM2708 GPIO driver"); +MODULE_LICENSE("GPL"); diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/bcm2708.h raspilinux/arch/arm/mach-bcm2708/bcm2708.h --- linux-stable/arch/arm/mach-bcm2708/bcm2708.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/bcm2708.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,49 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708.h + * + * BCM2708 machine support header + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BCM2708_BCM2708_H +#define __BCM2708_BCM2708_H + +#include + +extern void __init bcm2708_init(void); +extern void __init bcm2708_init_irq(void); +extern void __init bcm2708_map_io(void); +extern struct sys_timer bcm2708_timer; +extern unsigned int mmc_status(struct device *dev); + +#define AMBA_DEVICE(name, busid, base, plat) \ +static struct amba_device name##_device = { \ + .dev = { \ + .coherent_dma_mask = ~0, \ + .init_name = busid, \ + .platform_data = plat, \ + }, \ + .res = { \ + .start = base##_BASE, \ + .end = (base##_BASE) + SZ_4K - 1,\ + .flags = IORESOURCE_MEM, \ + }, \ + .irq = base##_IRQ, \ +} + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/arm_control.h raspilinux/arch/arm/mach-bcm2708/include/mach/arm_control.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/arm_control.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/arm_control.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,419 @@ +/* + * linux/arch/arm/mach-bcm2708/arm_control.h + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BCM2708_ARM_CONTROL_H +#define __BCM2708_ARM_CONTROL_H + +/* + * Definitions and addresses for the ARM CONTROL logic + * This file is manually generated. + */ + +#define ARM_BASE 0x7E00B000 + +/* Basic configuration */ +#define ARM_CONTROL0 HW_REGISTER_RW(ARM_BASE+0x000) +#define ARM_C0_SIZ128M 0x00000000 +#define ARM_C0_SIZ256M 0x00000001 +#define ARM_C0_SIZ512M 0x00000002 +#define ARM_C0_SIZ1G 0x00000003 +#define ARM_C0_BRESP0 0x00000000 +#define ARM_C0_BRESP1 0x00000004 +#define ARM_C0_BRESP2 0x00000008 +#define ARM_C0_BOOTHI 0x00000010 +#define ARM_C0_UNUSED05 0x00000020 /* free */ +#define ARM_C0_FULLPERI 0x00000040 +#define ARM_C0_UNUSED78 0x00000180 /* free */ +#define ARM_C0_JTAGMASK 0x00000E00 +#define ARM_C0_JTAGOFF 0x00000000 +#define ARM_C0_JTAGBASH 0x00000800 /* Debug on GPIO off */ +#define ARM_C0_JTAGGPIO 0x00000C00 /* Debug on GPIO on */ +#define ARM_C0_APROTMSK 0x0000F000 +#define ARM_C0_DBG0SYNC 0x00010000 /* VPU0 halt sync */ +#define ARM_C0_DBG1SYNC 0x00020000 /* VPU1 halt sync */ +#define ARM_C0_SWDBGREQ 0x00040000 /* HW debug request */ +#define ARM_C0_PASSHALT 0x00080000 /* ARM halt passed to debugger */ +#define ARM_C0_PRIO_PER 0x00F00000 /* per priority mask */ +#define ARM_C0_PRIO_L2 0x0F000000 +#define ARM_C0_PRIO_UC 0xF0000000 + +#define ARM_C0_APROTPASS 0x0000A000 /* Translate 1:1 */ +#define ARM_C0_APROTUSER 0x00000000 /* Only user mode */ +#define ARM_C0_APROTSYST 0x0000F000 /* Only system mode */ + + +#define ARM_CONTROL1 HW_REGISTER_RW(ARM_BASE+0x440) +#define ARM_C1_TIMER 0x00000001 /* re-route timer IRQ to VC */ +#define ARM_C1_MAIL 0x00000002 /* re-route Mail IRQ to VC */ +#define ARM_C1_BELL0 0x00000004 /* re-route Doorbell 0 to VC */ +#define ARM_C1_BELL1 0x00000008 /* re-route Doorbell 1 to VC */ +#define ARM_C1_PERSON 0x00000100 /* peripherals on */ +#define ARM_C1_REQSTOP 0x00000200 /* ASYNC bridge request stop */ + +#define ARM_STATUS HW_REGISTER_RW(ARM_BASE+0x444) +#define ARM_S_ACKSTOP 0x80000000 /* Bridge stopped */ +#define ARM_S_READPEND 0x000003FF /* pending reads counter */ +#define ARM_S_WRITPEND 0x000FFC00 /* pending writes counter */ + +#define ARM_ERRHALT HW_REGISTER_RW(ARM_BASE+0x448) +#define ARM_EH_PERIBURST 0x00000001 /* Burst write seen on peri bus */ +#define ARM_EH_ILLADDRS1 0x00000002 /* Address bits 25-27 error */ +#define ARM_EH_ILLADDRS2 0x00000004 /* Address bits 31-28 error */ +#define ARM_EH_VPU0HALT 0x00000008 /* VPU0 halted & in debug mode */ +#define ARM_EH_VPU1HALT 0x00000010 /* VPU1 halted & in debug mode */ +#define ARM_EH_ARMHALT 0x00000020 /* ARM in halted debug mode */ + +#define ARM_ID_SECURE HW_REGISTER_RW(ARM_BASE+0x00C) +#define ARM_ID HW_REGISTER_RW(ARM_BASE+0x44C) +#define ARM_IDVAL 0x364D5241 + +/* Translation memory */ +#define ARM_TRANSLATE HW_REGISTER_RW(ARM_BASE+0x100) +/* 32 locations: 0x100.. 0x17F */ +/* 32 spare means we CAN go to 64 pages.... */ + + +/* Interrupts */ +#define ARM_IRQ_PEND0 HW_REGISTER_RW(ARM_BASE+0x200) /* Top IRQ bits */ +#define ARM_I0_TIMER 0x00000001 /* timer IRQ */ +#define ARM_I0_MAIL 0x00000002 /* Mail IRQ */ +#define ARM_I0_BELL0 0x00000004 /* Doorbell 0 */ +#define ARM_I0_BELL1 0x00000008 /* Doorbell 1 */ +#define ARM_I0_BANK1 0x00000100 /* Bank1 IRQ */ +#define ARM_I0_BANK2 0x00000200 /* Bank2 IRQ */ + +#define ARM_IRQ_PEND1 HW_REGISTER_RW(ARM_BASE+0x204) /* All bank1 IRQ bits */ +/* todo: all I1_interrupt sources */ +#define ARM_IRQ_PEND2 HW_REGISTER_RW(ARM_BASE+0x208) /* All bank2 IRQ bits */ +/* todo: all I2_interrupt sources */ + +#define ARM_IRQ_FAST HW_REGISTER_RW(ARM_BASE+0x20C) /* FIQ control */ +#define ARM_IF_INDEX 0x0000007F /* FIQ select */ +#define ARM_IF_ENABLE 0x00000080 /* FIQ enable */ +#define ARM_IF_VCMASK 0x0000003F /* FIQ = (index from VC source) */ +#define ARM_IF_TIMER 0x00000040 /* FIQ = ARM timer */ +#define ARM_IF_MAIL 0x00000041 /* FIQ = ARM Mail */ +#define ARM_IF_BELL0 0x00000042 /* FIQ = ARM Doorbell 0 */ +#define ARM_IF_BELL1 0x00000043 /* FIQ = ARM Doorbell 1 */ +#define ARM_IF_VP0HALT 0x00000044 /* FIQ = VPU0 Halt seen */ +#define ARM_IF_VP1HALT 0x00000045 /* FIQ = VPU1 Halt seen */ +#define ARM_IF_ILLEGAL 0x00000046 /* FIQ = Illegal access seen */ + +#define ARM_IRQ_ENBL1 HW_REGISTER_RW(ARM_BASE+0x210) /* Bank1 enable bits */ +#define ARM_IRQ_ENBL2 HW_REGISTER_RW(ARM_BASE+0x214) /* Bank2 enable bits */ +#define ARM_IRQ_ENBL3 HW_REGISTER_RW(ARM_BASE+0x218) /* ARM irqs enable bits */ +#define ARM_IRQ_DIBL1 HW_REGISTER_RW(ARM_BASE+0x21C) /* Bank1 disable bits */ +#define ARM_IRQ_DIBL2 HW_REGISTER_RW(ARM_BASE+0x220) /* Bank2 disable bits */ +#define ARM_IRQ_DIBL3 HW_REGISTER_RW(ARM_BASE+0x224) /* ARM irqs disable bits */ +#define ARM_IE_TIMER 0x00000001 /* Timer IRQ */ +#define ARM_IE_MAIL 0x00000002 /* Mail IRQ */ +#define ARM_IE_BELL0 0x00000004 /* Doorbell 0 */ +#define ARM_IE_BELL1 0x00000008 /* Doorbell 1 */ +#define ARM_IE_VP0HALT 0x00000010 /* VPU0 Halt */ +#define ARM_IE_VP1HALT 0x00000020 /* VPU1 Halt */ +#define ARM_IE_ILLEGAL 0x00000040 /* Illegal access seen */ + +/* Timer */ +/* For reg. fields see sp804 spec. */ +#define ARM_T_LOAD HW_REGISTER_RW(ARM_BASE+0x400) +#define ARM_T_VALUE HW_REGISTER_RW(ARM_BASE+0x404) +#define ARM_T_CONTROL HW_REGISTER_RW(ARM_BASE+0x408) +#define ARM_T_IRQCNTL HW_REGISTER_RW(ARM_BASE+0x40C) +#define ARM_T_RAWIRQ HW_REGISTER_RW(ARM_BASE+0x410) +#define ARM_T_MSKIRQ HW_REGISTER_RW(ARM_BASE+0x414) +#define ARM_T_RELOAD HW_REGISTER_RW(ARM_BASE+0x418) +#define ARM_T_PREDIV HW_REGISTER_RW(ARM_BASE+0x41c) +#define ARM_T_FREECNT HW_REGISTER_RW(ARM_BASE+0x420) + +#define TIMER_CTRL_ONESHOT (1 << 0) +#define TIMER_CTRL_32BIT (1 << 1) +#define TIMER_CTRL_DIV1 (0 << 2) +#define TIMER_CTRL_DIV16 (1 << 2) +#define TIMER_CTRL_DIV256 (2 << 2) +#define TIMER_CTRL_IE (1 << 5) +#define TIMER_CTRL_PERIODIC (1 << 6) +#define TIMER_CTRL_ENABLE (1 << 7) +#define TIMER_CTRL_DBGHALT (1 << 8) +#define TIMER_CTRL_ENAFREE (1 << 9) +#define TIMER_CTRL_FREEDIV_SHIFT 16) +#define TIMER_CTRL_FREEDIV_MASK 0xff + +/* Semaphores, Doorbells, Mailboxes */ +#define ARM_SBM_OWN0 (ARM_BASE+0x800) +#define ARM_SBM_OWN1 (ARM_BASE+0x900) +#define ARM_SBM_OWN2 (ARM_BASE+0xA00) +#define ARM_SBM_OWN3 (ARM_BASE+0xB00) + +/* MAILBOXES + * Register flags are common across all + * owner registers. See end of this section + * + * Semaphores, Doorbells, Mailboxes Owner 0 + * + */ + +#define ARM_0_SEMS HW_REGISTER_RW(ARM_SBM_OWN0+0x00) +#define ARM_0_SEM0 HW_REGISTER_RW(ARM_SBM_OWN0+0x00) +#define ARM_0_SEM1 HW_REGISTER_RW(ARM_SBM_OWN0+0x04) +#define ARM_0_SEM2 HW_REGISTER_RW(ARM_SBM_OWN0+0x08) +#define ARM_0_SEM3 HW_REGISTER_RW(ARM_SBM_OWN0+0x0C) +#define ARM_0_SEM4 HW_REGISTER_RW(ARM_SBM_OWN0+0x10) +#define ARM_0_SEM5 HW_REGISTER_RW(ARM_SBM_OWN0+0x14) +#define ARM_0_SEM6 HW_REGISTER_RW(ARM_SBM_OWN0+0x18) +#define ARM_0_SEM7 HW_REGISTER_RW(ARM_SBM_OWN0+0x1C) +#define ARM_0_BELL0 HW_REGISTER_RW(ARM_SBM_OWN0+0x40) +#define ARM_0_BELL1 HW_REGISTER_RW(ARM_SBM_OWN0+0x44) +#define ARM_0_BELL2 HW_REGISTER_RW(ARM_SBM_OWN0+0x48) +#define ARM_0_BELL3 HW_REGISTER_RW(ARM_SBM_OWN0+0x4C) +/* MAILBOX 0 access in Owner 0 area */ +/* Some addresses should ONLY be used by owner 0 */ +#define ARM_0_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN0+0x80) /* .. 0x8C (4 locations) */ +#define ARM_0_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN0+0x80) /* .. 0x8C (4 locations) Normal read */ +#define ARM_0_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN0+0x90) /* none-pop read */ +#define ARM_0_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN0+0x94) /* Sender read (only LS 2 bits) */ +#define ARM_0_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN0+0x98) /* Status read */ +#define ARM_0_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN0+0x9C) /* Config read/write */ +/* MAILBOX 1 access in Owner 0 area */ +/* Owner 0 should only WRITE to this mailbox */ +#define ARM_0_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN0+0xA0) /* .. 0xAC (4 locations) */ +/*#define ARM_0_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN0+0xA0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_0_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN0+0xB0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_0_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN0+0xB4) */ /* DO NOT USE THIS !!!!! */ +#define ARM_0_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN0+0xB8) /* Status read */ +/*#define ARM_0_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN0+0xBC) */ /* DO NOT USE THIS !!!!! */ +/* General SEM, BELL, MAIL config/status */ +#define ARM_0_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN0+0xE0) /* semaphore clear/debug register */ +#define ARM_0_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN0+0xE4) /* Doorbells clear/debug register */ +#define ARM_0_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN0+0xF8) /* ALL interrupts */ +#define ARM_0_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN0+0xFC) /* IRQS pending for owner 0 */ + +/* Semaphores, Doorbells, Mailboxes Owner 1 */ +#define ARM_1_SEMS HW_REGISTER_RW(ARM_SBM_OWN1+0x00) +#define ARM_1_SEM0 HW_REGISTER_RW(ARM_SBM_OWN1+0x00) +#define ARM_1_SEM1 HW_REGISTER_RW(ARM_SBM_OWN1+0x04) +#define ARM_1_SEM2 HW_REGISTER_RW(ARM_SBM_OWN1+0x08) +#define ARM_1_SEM3 HW_REGISTER_RW(ARM_SBM_OWN1+0x0C) +#define ARM_1_SEM4 HW_REGISTER_RW(ARM_SBM_OWN1+0x10) +#define ARM_1_SEM5 HW_REGISTER_RW(ARM_SBM_OWN1+0x14) +#define ARM_1_SEM6 HW_REGISTER_RW(ARM_SBM_OWN1+0x18) +#define ARM_1_SEM7 HW_REGISTER_RW(ARM_SBM_OWN1+0x1C) +#define ARM_1_BELL0 HW_REGISTER_RW(ARM_SBM_OWN1+0x40) +#define ARM_1_BELL1 HW_REGISTER_RW(ARM_SBM_OWN1+0x44) +#define ARM_1_BELL2 HW_REGISTER_RW(ARM_SBM_OWN1+0x48) +#define ARM_1_BELL3 HW_REGISTER_RW(ARM_SBM_OWN1+0x4C) +/* MAILBOX 0 access in Owner 0 area */ +/* Owner 1 should only WRITE to this mailbox */ +#define ARM_1_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN1+0x80) /* .. 0x8C (4 locations) */ +/*#define ARM_1_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN1+0x80) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_1_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN1+0x90) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_1_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN1+0x94) */ /* DO NOT USE THIS !!!!! */ +#define ARM_1_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN1+0x98) /* Status read */ +/*#define ARM_1_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN1+0x9C) */ /* DO NOT USE THIS !!!!! */ +/* MAILBOX 1 access in Owner 0 area */ +#define ARM_1_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN1+0xA0) /* .. 0xAC (4 locations) */ +#define ARM_1_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN1+0xA0) /* .. 0xAC (4 locations) Normal read */ +#define ARM_1_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN1+0xB0) /* none-pop read */ +#define ARM_1_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN1+0xB4) /* Sender read (only LS 2 bits) */ +#define ARM_1_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN1+0xB8) /* Status read */ +#define ARM_1_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN1+0xBC) +/* General SEM, BELL, MAIL config/status */ +#define ARM_1_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN1+0xE0) /* semaphore clear/debug register */ +#define ARM_1_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN1+0xE4) /* Doorbells clear/debug register */ +#define ARM_1_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN1+0xFC) /* IRQS pending for owner 1 */ +#define ARM_1_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN1+0xF8) /* ALL interrupts */ + +/* Semaphores, Doorbells, Mailboxes Owner 2 */ +#define ARM_2_SEMS HW_REGISTER_RW(ARM_SBM_OWN2+0x00) +#define ARM_2_SEM0 HW_REGISTER_RW(ARM_SBM_OWN2+0x00) +#define ARM_2_SEM1 HW_REGISTER_RW(ARM_SBM_OWN2+0x04) +#define ARM_2_SEM2 HW_REGISTER_RW(ARM_SBM_OWN2+0x08) +#define ARM_2_SEM3 HW_REGISTER_RW(ARM_SBM_OWN2+0x0C) +#define ARM_2_SEM4 HW_REGISTER_RW(ARM_SBM_OWN2+0x10) +#define ARM_2_SEM5 HW_REGISTER_RW(ARM_SBM_OWN2+0x14) +#define ARM_2_SEM6 HW_REGISTER_RW(ARM_SBM_OWN2+0x18) +#define ARM_2_SEM7 HW_REGISTER_RW(ARM_SBM_OWN2+0x1C) +#define ARM_2_BELL0 HW_REGISTER_RW(ARM_SBM_OWN2+0x40) +#define ARM_2_BELL1 HW_REGISTER_RW(ARM_SBM_OWN2+0x44) +#define ARM_2_BELL2 HW_REGISTER_RW(ARM_SBM_OWN2+0x48) +#define ARM_2_BELL3 HW_REGISTER_RW(ARM_SBM_OWN2+0x4C) +/* MAILBOX 0 access in Owner 2 area */ +/* Owner 2 should only WRITE to this mailbox */ +#define ARM_2_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN2+0x80) /* .. 0x8C (4 locations) */ +/*#define ARM_2_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN2+0x80) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_2_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN2+0x90) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_2_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN2+0x94) */ /* DO NOT USE THIS !!!!! */ +#define ARM_2_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN2+0x98) /* Status read */ +/*#define ARM_2_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN2+0x9C) */ /* DO NOT USE THIS !!!!! */ +/* MAILBOX 1 access in Owner 2 area */ +/* Owner 2 should only WRITE to this mailbox */ +#define ARM_2_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN2+0xA0) /* .. 0xAC (4 locations) */ +/*#define ARM_2_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN2+0xA0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_2_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN2+0xB0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_2_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN2+0xB4) */ /* DO NOT USE THIS !!!!! */ +#define ARM_2_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN2+0xB8) /* Status read */ +/*#define ARM_2_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN2+0xBC) */ /* DO NOT USE THIS !!!!! */ +/* General SEM, BELL, MAIL config/status */ +#define ARM_2_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN2+0xE0) /* semaphore clear/debug register */ +#define ARM_2_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN2+0xE4) /* Doorbells clear/debug register */ +#define ARM_2_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN2+0xFC) /* IRQS pending for owner 2 */ +#define ARM_2_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN2+0xF8) /* ALL interrupts */ + +/* Semaphores, Doorbells, Mailboxes Owner 3 */ +#define ARM_3_SEMS HW_REGISTER_RW(ARM_SBM_OWN3+0x00) +#define ARM_3_SEM0 HW_REGISTER_RW(ARM_SBM_OWN3+0x00) +#define ARM_3_SEM1 HW_REGISTER_RW(ARM_SBM_OWN3+0x04) +#define ARM_3_SEM2 HW_REGISTER_RW(ARM_SBM_OWN3+0x08) +#define ARM_3_SEM3 HW_REGISTER_RW(ARM_SBM_OWN3+0x0C) +#define ARM_3_SEM4 HW_REGISTER_RW(ARM_SBM_OWN3+0x10) +#define ARM_3_SEM5 HW_REGISTER_RW(ARM_SBM_OWN3+0x14) +#define ARM_3_SEM6 HW_REGISTER_RW(ARM_SBM_OWN3+0x18) +#define ARM_3_SEM7 HW_REGISTER_RW(ARM_SBM_OWN3+0x1C) +#define ARM_3_BELL0 HW_REGISTER_RW(ARM_SBM_OWN3+0x40) +#define ARM_3_BELL1 HW_REGISTER_RW(ARM_SBM_OWN3+0x44) +#define ARM_3_BELL2 HW_REGISTER_RW(ARM_SBM_OWN3+0x48) +#define ARM_3_BELL3 HW_REGISTER_RW(ARM_SBM_OWN3+0x4C) +/* MAILBOX 0 access in Owner 3 area */ +/* Owner 3 should only WRITE to this mailbox */ +#define ARM_3_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN3+0x80) /* .. 0x8C (4 locations) */ +/*#define ARM_3_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN3+0x80) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_3_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN3+0x90) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_3_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN3+0x94) */ /* DO NOT USE THIS !!!!! */ +#define ARM_3_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN3+0x98) /* Status read */ +/*#define ARM_3_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN3+0x9C) */ /* DO NOT USE THIS !!!!! */ +/* MAILBOX 1 access in Owner 3 area */ +/* Owner 3 should only WRITE to this mailbox */ +#define ARM_3_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN3+0xA0) /* .. 0xAC (4 locations) */ +/*#define ARM_3_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN3+0xA0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_3_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN3+0xB0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_3_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN3+0xB4) */ /* DO NOT USE THIS !!!!! */ +#define ARM_3_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN3+0xB8) /* Status read */ +/*#define ARM_3_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN3+0xBC) */ /* DO NOT USE THIS !!!!! */ +/* General SEM, BELL, MAIL config/status */ +#define ARM_3_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN3+0xE0) /* semaphore clear/debug register */ +#define ARM_3_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN3+0xE4) /* Doorbells clear/debug register */ +#define ARM_3_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN3+0xFC) /* IRQS pending for owner 3 */ +#define ARM_3_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN3+0xF8) /* ALL interrupts */ + + + +/* Mailbox flags. Valid for all owners */ + +/* Mailbox status register (...0x98) */ +#define ARM_MS_FULL 0x80000000 +#define ARM_MS_EMPTY 0x40000000 +#define ARM_MS_LEVEL 0x400000FF /* Max. value depdnds on mailbox depth parameter */ + +/* MAILBOX config/status register (...0x9C) */ +/* ANY write to this register clears the error bits! */ +#define ARM_MC_IHAVEDATAIRQEN 0x00000001 /* mailbox irq enable: has data */ +#define ARM_MC_IHAVESPACEIRQEN 0x00000002 /* mailbox irq enable: has space */ +#define ARM_MC_OPPISEMPTYIRQEN 0x00000004 /* mailbox irq enable: Opp. is empty */ +#define ARM_MC_MAIL_CLEAR 0x00000008 /* mailbox clear write 1, then 0 */ +#define ARM_MC_IHAVEDATAIRQPEND 0x00000010 /* mailbox irq pending: has space */ +#define ARM_MC_IHAVESPACEIRQPEND 0x00000020 /* mailbox irq pending: Opp. is empty */ +#define ARM_MC_OPPISEMPTYIRQPEND 0x00000040 /* mailbox irq pending */ +/* Bit 7 is unused */ +#define ARM_MC_ERRNOOWN 0x00000100 /* error : none owner read from mailbox */ +#define ARM_MC_ERROVERFLW 0x00000200 /* error : write to fill mailbox */ +#define ARM_MC_ERRUNDRFLW 0x00000400 /* error : read from empty mailbox */ + +/* Semaphore clear/debug register (...0xE0) */ +#define ARM_SD_OWN0 0x00000003 /* Owner of sem 0 */ +#define ARM_SD_OWN1 0x0000000C /* Owner of sem 1 */ +#define ARM_SD_OWN2 0x00000030 /* Owner of sem 2 */ +#define ARM_SD_OWN3 0x000000C0 /* Owner of sem 3 */ +#define ARM_SD_OWN4 0x00000300 /* Owner of sem 4 */ +#define ARM_SD_OWN5 0x00000C00 /* Owner of sem 5 */ +#define ARM_SD_OWN6 0x00003000 /* Owner of sem 6 */ +#define ARM_SD_OWN7 0x0000C000 /* Owner of sem 7 */ +#define ARM_SD_SEM0 0x00010000 /* Status of sem 0 */ +#define ARM_SD_SEM1 0x00020000 /* Status of sem 1 */ +#define ARM_SD_SEM2 0x00040000 /* Status of sem 2 */ +#define ARM_SD_SEM3 0x00080000 /* Status of sem 3 */ +#define ARM_SD_SEM4 0x00100000 /* Status of sem 4 */ +#define ARM_SD_SEM5 0x00200000 /* Status of sem 5 */ +#define ARM_SD_SEM6 0x00400000 /* Status of sem 6 */ +#define ARM_SD_SEM7 0x00800000 /* Status of sem 7 */ + +/* Doorbells clear/debug register (...0xE4) */ +#define ARM_BD_OWN0 0x00000003 /* Owner of doorbell 0 */ +#define ARM_BD_OWN1 0x0000000C /* Owner of doorbell 1 */ +#define ARM_BD_OWN2 0x00000030 /* Owner of doorbell 2 */ +#define ARM_BD_OWN3 0x000000C0 /* Owner of doorbell 3 */ +#define ARM_BD_BELL0 0x00000100 /* Status of doorbell 0 */ +#define ARM_BD_BELL1 0x00000200 /* Status of doorbell 1 */ +#define ARM_BD_BELL2 0x00000400 /* Status of doorbell 2 */ +#define ARM_BD_BELL3 0x00000800 /* Status of doorbell 3 */ + +/* MY IRQS register (...0xF8) */ +#define ARM_MYIRQ_BELL 0x00000001 /* This owner has a doorbell IRQ */ +#define ARM_MYIRQ_MAIL 0x00000002 /* This owner has a mailbox IRQ */ + +/* ALL IRQS register (...0xF8) */ +#define ARM_AIS_BELL0 0x00000001 /* Doorbell 0 IRQ pending */ +#define ARM_AIS_BELL1 0x00000002 /* Doorbell 1 IRQ pending */ +#define ARM_AIS_BELL2 0x00000004 /* Doorbell 2 IRQ pending */ +#define ARM_AIS_BELL3 0x00000008 /* Doorbell 3 IRQ pending */ +#define ARM_AIS0_HAVEDATA 0x00000010 /* MAIL 0 has data IRQ pending */ +#define ARM_AIS0_HAVESPAC 0x00000020 /* MAIL 0 has space IRQ pending */ +#define ARM_AIS0_OPPEMPTY 0x00000040 /* MAIL 0 opposite is empty IRQ */ +#define ARM_AIS1_HAVEDATA 0x00000080 /* MAIL 1 has data IRQ pending */ +#define ARM_AIS1_HAVESPAC 0x00000100 /* MAIL 1 has space IRQ pending */ +#define ARM_AIS1_OPPEMPTY 0x00000200 /* MAIL 1 opposite is empty IRQ */ +/* Note that bell-0, bell-1 and MAIL0 IRQ go only to the ARM */ +/* Whilst that bell-2, bell-3 and MAIL1 IRQ go only to the VC */ +/* */ +/* ARM JTAG BASH */ +/* */ +#define AJB_BASE 0x7e2000c0 + +#define AJBCONF HW_REGISTER_RW(AJB_BASE+0x00) +#define AJB_BITS0 0x000000 +#define AJB_BITS4 0x000004 +#define AJB_BITS8 0x000008 +#define AJB_BITS12 0x00000C +#define AJB_BITS16 0x000010 +#define AJB_BITS20 0x000014 +#define AJB_BITS24 0x000018 +#define AJB_BITS28 0x00001C +#define AJB_BITS32 0x000020 +#define AJB_BITS34 0x000022 +#define AJB_OUT_MS 0x000040 +#define AJB_OUT_LS 0x000000 +#define AJB_INV_CLK 0x000080 +#define AJB_D0_RISE 0x000100 +#define AJB_D0_FALL 0x000000 +#define AJB_D1_RISE 0x000200 +#define AJB_D1_FALL 0x000000 +#define AJB_IN_RISE 0x000400 +#define AJB_IN_FALL 0x000000 +#define AJB_ENABLE 0x000800 +#define AJB_HOLD0 0x000000 +#define AJB_HOLD1 0x001000 +#define AJB_HOLD2 0x002000 +#define AJB_HOLD3 0x003000 +#define AJB_RESETN 0x004000 +#define AJB_CLKSHFT 16 +#define AJB_BUSY 0x80000000 +#define AJBTMS HW_REGISTER_RW(AJB_BASE+0x04) +#define AJBTDI HW_REGISTER_RW(AJB_BASE+0x08) +#define AJBTDO HW_REGISTER_RW(AJB_BASE+0x0c) + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/clkdev.h raspilinux/arch/arm/mach-bcm2708/include/mach/clkdev.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/clkdev.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/clkdev.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/debug-macro.S raspilinux/arch/arm/mach-bcm2708/include/mach/debug-macro.S --- linux-stable/arch/arm/mach-bcm2708/include/mach/debug-macro.S 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/debug-macro.S 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,22 @@ +/* arch/arm/mach-bcm2708/include/mach/debug-macro.S + * + * Debugging macro include header + * + * Copyright (C) 2010 Broadcom + * Copyright (C) 1994-1999 Russell King + * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include + + .macro addruart, rp, rv, tmp + ldr \rp, =UART0_BASE + ldr \rv, =IO_ADDRESS(UART0_BASE) + .endm + +#include diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/entry-macro.S raspilinux/arch/arm/mach-bcm2708/include/mach/entry-macro.S --- linux-stable/arch/arm/mach-bcm2708/include/mach/entry-macro.S 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/entry-macro.S 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,69 @@ +/* + * arch/arm/mach-bcm2708/include/mach/entry-macro.S + * + * Low-level IRQ helper macros for BCM2708 platforms + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =IO_ADDRESS(ARMCTRL_IC_BASE) + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + /* get masked status */ + ldr \irqstat, [\base, #(ARM_IRQ_PEND0 - ARMCTRL_IC_BASE)] + mov \irqnr, #(ARM_IRQ0_BASE + 31) + and \tmp, \irqstat, #0x300 @ save bits 8 and 9 + /* clear bits 8 and 9, and test */ + bics \irqstat, \irqstat, #0x300 + bne 1010f + + tst \tmp, #0x100 + ldrne \irqstat, [\base, #(ARM_IRQ_PEND1 - ARMCTRL_IC_BASE)] + movne \irqnr, #(ARM_IRQ1_BASE + 31) + @ Mask out the interrupts also present in PEND0 - see SW-5809 + bicne \irqstat, #((1<<7) | (1<<9) | (1<<10)) + bicne \irqstat, #((1<<18) | (1<<19)) + bne 1010f + + tst \tmp, #0x200 + ldrne \irqstat, [\base, #(ARM_IRQ_PEND2 - ARMCTRL_IC_BASE)] + movne \irqnr, #(ARM_IRQ2_BASE + 31) + @ Mask out the interrupts also present in PEND0 - see SW-5809 + bicne \irqstat, #((1<<21) | (1<<22) | (1<<23) | (1<<24) | (1<<25)) + bicne \irqstat, #((1<<30)) + beq 1020f + +1010: + @ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1)) + @ N.B. CLZ is an ARM5 instruction. + sub \tmp, \irqstat, #1 + eor \irqstat, \irqstat, \tmp + clz \tmp, \irqstat + sub \irqnr, \tmp + +1020: @ EQ will be set if no irqs pending + + .endm diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/frc.h raspilinux/arch/arm/mach-bcm2708/include/mach/frc.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/frc.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/frc.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,38 @@ +/* + * arch/arm/mach-bcm2708/include/mach/timex.h + * + * BCM2708 free running counter (timer) + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MACH_FRC_H +#define _MACH_FRC_H + +#define FRC_TICK_RATE (1000000) + +/*! Free running counter incrementing at the CLOCK_TICK_RATE + (slightly faster than frc_clock_ticks63() + */ +extern unsigned long frc_clock_ticks32(void); + +/*! Free running counter incrementing at the CLOCK_TICK_RATE + * Note - top bit should be ignored (see cnt32_to_63) + */ +extern unsigned long long frc_clock_ticks63(void); + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/gpio.h raspilinux/arch/arm/mach-bcm2708/include/mach/gpio.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/gpio.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/gpio.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,17 @@ +/* + * arch/arm/mach-bcm2708/include/mach/gpio.h + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H + +#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 '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/hardware.h raspilinux/arch/arm/mach-bcm2708/include/mach/hardware.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/hardware.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/hardware.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-bcm2708/include/mach/hardware.h + * + * This file contains the hardware definitions of the BCM2708 devices. + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +#include +#include + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/io.h raspilinux/arch/arm/mach-bcm2708/include/mach/io.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/io.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/io.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,27 @@ +/* + * arch/arm/mach-bcm2708/include/mach/io.h + * + * Copyright (C) 2003 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +#define __io(a) __typesafe_io(a) + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/irqs.h raspilinux/arch/arm/mach-bcm2708/include/mach/irqs.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/irqs.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/irqs.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,199 @@ +/* + * arch/arm/mach-bcm2708/include/mach/irqs.h + * + * Copyright (C) 2010 Broadcom + * Copyright (C) 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _BCM2708_IRQS_H_ +#define _BCM2708_IRQS_H_ + +#include + +/* + * IRQ interrupts definitions are the same as the INT definitions + * held within platform.h + */ +#define IRQ_ARMCTRL_START 0 +#define IRQ_TIMER0 (IRQ_ARMCTRL_START + INTERRUPT_TIMER0) +#define IRQ_TIMER1 (IRQ_ARMCTRL_START + INTERRUPT_TIMER1) +#define IRQ_TIMER2 (IRQ_ARMCTRL_START + INTERRUPT_TIMER2) +#define IRQ_TIMER3 (IRQ_ARMCTRL_START + INTERRUPT_TIMER3) +#define IRQ_CODEC0 (IRQ_ARMCTRL_START + INTERRUPT_CODEC0) +#define IRQ_CODEC1 (IRQ_ARMCTRL_START + INTERRUPT_CODEC1) +#define IRQ_CODEC2 (IRQ_ARMCTRL_START + INTERRUPT_CODEC2) +#define IRQ_JPEG (IRQ_ARMCTRL_START + INTERRUPT_JPEG) +#define IRQ_ISP (IRQ_ARMCTRL_START + INTERRUPT_ISP) +#define IRQ_USB (IRQ_ARMCTRL_START + INTERRUPT_USB) +#define IRQ_3D (IRQ_ARMCTRL_START + INTERRUPT_3D) +#define IRQ_TRANSPOSER (IRQ_ARMCTRL_START + INTERRUPT_TRANSPOSER) +#define IRQ_MULTICORESYNC0 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC0) +#define IRQ_MULTICORESYNC1 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC1) +#define IRQ_MULTICORESYNC2 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC2) +#define IRQ_MULTICORESYNC3 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC3) +#define IRQ_DMA0 (IRQ_ARMCTRL_START + INTERRUPT_DMA0) +#define IRQ_DMA1 (IRQ_ARMCTRL_START + INTERRUPT_DMA1) +#define IRQ_DMA2 (IRQ_ARMCTRL_START + INTERRUPT_DMA2) +#define IRQ_DMA3 (IRQ_ARMCTRL_START + INTERRUPT_DMA3) +#define IRQ_DMA4 (IRQ_ARMCTRL_START + INTERRUPT_DMA4) +#define IRQ_DMA5 (IRQ_ARMCTRL_START + INTERRUPT_DMA5) +#define IRQ_DMA6 (IRQ_ARMCTRL_START + INTERRUPT_DMA6) +#define IRQ_DMA7 (IRQ_ARMCTRL_START + INTERRUPT_DMA7) +#define IRQ_DMA8 (IRQ_ARMCTRL_START + INTERRUPT_DMA8) +#define IRQ_DMA9 (IRQ_ARMCTRL_START + INTERRUPT_DMA9) +#define IRQ_DMA10 (IRQ_ARMCTRL_START + INTERRUPT_DMA10) +#define IRQ_DMA11 (IRQ_ARMCTRL_START + INTERRUPT_DMA11) +#define IRQ_DMA12 (IRQ_ARMCTRL_START + INTERRUPT_DMA12) +#define IRQ_AUX (IRQ_ARMCTRL_START + INTERRUPT_AUX) +#define IRQ_ARM (IRQ_ARMCTRL_START + INTERRUPT_ARM) +#define IRQ_VPUDMA (IRQ_ARMCTRL_START + INTERRUPT_VPUDMA) +#define IRQ_HOSTPORT (IRQ_ARMCTRL_START + INTERRUPT_HOSTPORT) +#define IRQ_VIDEOSCALER (IRQ_ARMCTRL_START + INTERRUPT_VIDEOSCALER) +#define IRQ_CCP2TX (IRQ_ARMCTRL_START + INTERRUPT_CCP2TX) +#define IRQ_SDC (IRQ_ARMCTRL_START + INTERRUPT_SDC) +#define IRQ_DSI0 (IRQ_ARMCTRL_START + INTERRUPT_DSI0) +#define IRQ_AVE (IRQ_ARMCTRL_START + INTERRUPT_AVE) +#define IRQ_CAM0 (IRQ_ARMCTRL_START + INTERRUPT_CAM0) +#define IRQ_CAM1 (IRQ_ARMCTRL_START + INTERRUPT_CAM1) +#define IRQ_HDMI0 (IRQ_ARMCTRL_START + INTERRUPT_HDMI0) +#define IRQ_HDMI1 (IRQ_ARMCTRL_START + INTERRUPT_HDMI1) +#define IRQ_PIXELVALVE1 (IRQ_ARMCTRL_START + INTERRUPT_PIXELVALVE1) +#define IRQ_I2CSPISLV (IRQ_ARMCTRL_START + INTERRUPT_I2CSPISLV) +#define IRQ_DSI1 (IRQ_ARMCTRL_START + INTERRUPT_DSI1) +#define IRQ_PWA0 (IRQ_ARMCTRL_START + INTERRUPT_PWA0) +#define IRQ_PWA1 (IRQ_ARMCTRL_START + INTERRUPT_PWA1) +#define IRQ_CPR (IRQ_ARMCTRL_START + INTERRUPT_CPR) +#define IRQ_SMI (IRQ_ARMCTRL_START + INTERRUPT_SMI) +#define IRQ_GPIO0 (IRQ_ARMCTRL_START + INTERRUPT_GPIO0) +#define IRQ_GPIO1 (IRQ_ARMCTRL_START + INTERRUPT_GPIO1) +#define IRQ_GPIO2 (IRQ_ARMCTRL_START + INTERRUPT_GPIO2) +#define IRQ_GPIO3 (IRQ_ARMCTRL_START + INTERRUPT_GPIO3) +#define IRQ_I2C (IRQ_ARMCTRL_START + INTERRUPT_I2C) +#define IRQ_SPI (IRQ_ARMCTRL_START + INTERRUPT_SPI) +#define IRQ_I2SPCM (IRQ_ARMCTRL_START + INTERRUPT_I2SPCM) +#define IRQ_SDIO (IRQ_ARMCTRL_START + INTERRUPT_SDIO) +#define IRQ_UART (IRQ_ARMCTRL_START + INTERRUPT_UART) +#define IRQ_SLIMBUS (IRQ_ARMCTRL_START + INTERRUPT_SLIMBUS) +#define IRQ_VEC (IRQ_ARMCTRL_START + INTERRUPT_VEC) +#define IRQ_CPG (IRQ_ARMCTRL_START + INTERRUPT_CPG) +#define IRQ_RNG (IRQ_ARMCTRL_START + INTERRUPT_RNG) +#define IRQ_ARASANSDIO (IRQ_ARMCTRL_START + INTERRUPT_ARASANSDIO) +#define IRQ_AVSPMON (IRQ_ARMCTRL_START + INTERRUPT_AVSPMON) + +#define IRQ_ARM_TIMER (IRQ_ARMCTRL_START + INTERRUPT_ARM_TIMER) +#define IRQ_ARM_MAILBOX (IRQ_ARMCTRL_START + INTERRUPT_ARM_MAILBOX) +#define IRQ_ARM_DOORBELL_0 (IRQ_ARMCTRL_START + INTERRUPT_ARM_DOORBELL_0) +#define IRQ_ARM_DOORBELL_1 (IRQ_ARMCTRL_START + INTERRUPT_ARM_DOORBELL_1) +#define IRQ_VPU0_HALTED (IRQ_ARMCTRL_START + INTERRUPT_VPU0_HALTED) +#define IRQ_VPU1_HALTED (IRQ_ARMCTRL_START + INTERRUPT_VPU1_HALTED) +#define IRQ_ILLEGAL_TYPE0 (IRQ_ARMCTRL_START + INTERRUPT_ILLEGAL_TYPE0) +#define IRQ_ILLEGAL_TYPE1 (IRQ_ARMCTRL_START + INTERRUPT_ILLEGAL_TYPE1) +#define IRQ_PENDING1 (IRQ_ARMCTRL_START + INTERRUPT_PENDING1) +#define IRQ_PENDING2 (IRQ_ARMCTRL_START + INTERRUPT_PENDING2) + +#define FIQ_START HARD_IRQS + +/* + * FIQ interrupts definitions are the same as the INT definitions. + */ +#define FIQ_TIMER0 (FIQ_START+INTERRUPT_TIMER0) +#define FIQ_TIMER1 (FIQ_START+INTERRUPT_TIMER1) +#define FIQ_TIMER2 (FIQ_START+INTERRUPT_TIMER2) +#define FIQ_TIMER3 (FIQ_START+INTERRUPT_TIMER3) +#define FIQ_CODEC0 (FIQ_START+INTERRUPT_CODEC0) +#define FIQ_CODEC1 (FIQ_START+INTERRUPT_CODEC1) +#define FIQ_CODEC2 (FIQ_START+INTERRUPT_CODEC2) +#define FIQ_JPEG (FIQ_START+INTERRUPT_JPEG) +#define FIQ_ISP (FIQ_START+INTERRUPT_ISP) +#define FIQ_USB (FIQ_START+INTERRUPT_USB) +#define FIQ_3D (FIQ_START+INTERRUPT_3D) +#define FIQ_TRANSPOSER (FIQ_START+INTERRUPT_TRANSPOSER) +#define FIQ_MULTICORESYNC0 (FIQ_START+INTERRUPT_MULTICORESYNC0) +#define FIQ_MULTICORESYNC1 (FIQ_START+INTERRUPT_MULTICORESYNC1) +#define FIQ_MULTICORESYNC2 (FIQ_START+INTERRUPT_MULTICORESYNC2) +#define FIQ_MULTICORESYNC3 (FIQ_START+INTERRUPT_MULTICORESYNC3) +#define FIQ_DMA0 (FIQ_START+INTERRUPT_DMA0) +#define FIQ_DMA1 (FIQ_START+INTERRUPT_DMA1) +#define FIQ_DMA2 (FIQ_START+INTERRUPT_DMA2) +#define FIQ_DMA3 (FIQ_START+INTERRUPT_DMA3) +#define FIQ_DMA4 (FIQ_START+INTERRUPT_DMA4) +#define FIQ_DMA5 (FIQ_START+INTERRUPT_DMA5) +#define FIQ_DMA6 (FIQ_START+INTERRUPT_DMA6) +#define FIQ_DMA7 (FIQ_START+INTERRUPT_DMA7) +#define FIQ_DMA8 (FIQ_START+INTERRUPT_DMA8) +#define FIQ_DMA9 (FIQ_START+INTERRUPT_DMA9) +#define FIQ_DMA10 (FIQ_START+INTERRUPT_DMA10) +#define FIQ_DMA11 (FIQ_START+INTERRUPT_DMA11) +#define FIQ_DMA12 (FIQ_START+INTERRUPT_DMA12) +#define FIQ_AUX (FIQ_START+INTERRUPT_AUX) +#define FIQ_ARM (FIQ_START+INTERRUPT_ARM) +#define FIQ_VPUDMA (FIQ_START+INTERRUPT_VPUDMA) +#define FIQ_HOSTPORT (FIQ_START+INTERRUPT_HOSTPORT) +#define FIQ_VIDEOSCALER (FIQ_START+INTERRUPT_VIDEOSCALER) +#define FIQ_CCP2TX (FIQ_START+INTERRUPT_CCP2TX) +#define FIQ_SDC (FIQ_START+INTERRUPT_SDC) +#define FIQ_DSI0 (FIQ_START+INTERRUPT_DSI0) +#define FIQ_AVE (FIQ_START+INTERRUPT_AVE) +#define FIQ_CAM0 (FIQ_START+INTERRUPT_CAM0) +#define FIQ_CAM1 (FIQ_START+INTERRUPT_CAM1) +#define FIQ_HDMI0 (FIQ_START+INTERRUPT_HDMI0) +#define FIQ_HDMI1 (FIQ_START+INTERRUPT_HDMI1) +#define FIQ_PIXELVALVE1 (FIQ_START+INTERRUPT_PIXELVALVE1) +#define FIQ_I2CSPISLV (FIQ_START+INTERRUPT_I2CSPISLV) +#define FIQ_DSI1 (FIQ_START+INTERRUPT_DSI1) +#define FIQ_PWA0 (FIQ_START+INTERRUPT_PWA0) +#define FIQ_PWA1 (FIQ_START+INTERRUPT_PWA1) +#define FIQ_CPR (FIQ_START+INTERRUPT_CPR) +#define FIQ_SMI (FIQ_START+INTERRUPT_SMI) +#define FIQ_GPIO0 (FIQ_START+INTERRUPT_GPIO0) +#define FIQ_GPIO1 (FIQ_START+INTERRUPT_GPIO1) +#define FIQ_GPIO2 (FIQ_START+INTERRUPT_GPIO2) +#define FIQ_GPIO3 (FIQ_START+INTERRUPT_GPIO3) +#define FIQ_I2C (FIQ_START+INTERRUPT_I2C) +#define FIQ_SPI (FIQ_START+INTERRUPT_SPI) +#define FIQ_I2SPCM (FIQ_START+INTERRUPT_I2SPCM) +#define FIQ_SDIO (FIQ_START+INTERRUPT_SDIO) +#define FIQ_UART (FIQ_START+INTERRUPT_UART) +#define FIQ_SLIMBUS (FIQ_START+INTERRUPT_SLIMBUS) +#define FIQ_VEC (FIQ_START+INTERRUPT_VEC) +#define FIQ_CPG (FIQ_START+INTERRUPT_CPG) +#define FIQ_RNG (FIQ_START+INTERRUPT_RNG) +#define FIQ_ARASANSDIO (FIQ_START+INTERRUPT_ARASANSDIO) +#define FIQ_AVSPMON (FIQ_START+INTERRUPT_AVSPMON) + +#define FIQ_ARM_TIMER (FIQ_START+INTERRUPT_ARM_TIMER) +#define FIQ_ARM_MAILBOX (FIQ_START+INTERRUPT_ARM_MAILBOX) +#define FIQ_ARM_DOORBELL_0 (FIQ_START+INTERRUPT_ARM_DOORBELL_0) +#define FIQ_ARM_DOORBELL_1 (FIQ_START+INTERRUPT_ARM_DOORBELL_1) +#define FIQ_VPU0_HALTED (FIQ_START+INTERRUPT_VPU0_HALTED) +#define FIQ_VPU1_HALTED (FIQ_START+INTERRUPT_VPU1_HALTED) +#define FIQ_ILLEGAL_TYPE0 (FIQ_START+INTERRUPT_ILLEGAL_TYPE0) +#define FIQ_ILLEGAL_TYPE1 (FIQ_START+INTERRUPT_ILLEGAL_TYPE1) +#define FIQ_PENDING1 (FIQ_START+INTERRUPT_PENDING1) +#define FIQ_PENDING2 (FIQ_START+INTERRUPT_PENDING2) + +#define HARD_IRQS (64 + 21) +#define FIQ_IRQS (64 + 21) +#define GPIO_IRQ_START (HARD_IRQS + FIQ_IRQS) +#define GPIO_IRQS (32*5) +#define SPARE_ALLOC_IRQS 64 +#define BCM2708_ALLOC_IRQS (HARD_IRQS+FIQ_IRQS+GPIO_IRQS+SPARE_ALLOC_IRQS) +#define FREE_IRQS 128 +#define NR_IRQS (BCM2708_ALLOC_IRQS+FREE_IRQS) + +#endif /* _BCM2708_IRQS_H_ */ diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/memory.h raspilinux/arch/arm/mach-bcm2708/include/mach/memory.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/memory.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/memory.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,57 @@ +/* + * arch/arm/mach-bcm2708/include/mach/memory.h + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +/* Memory overview: + + [ARMcore] <--virtual addr--> + [ARMmmu] <--physical addr--> + [GERTmap] <--bus add--> + [VCperiph] + +*/ + +/* + * Physical DRAM offset. + */ +#define BCM_PLAT_PHYS_OFFSET UL(0x00000000) +#define VC_ARMMEM_OFFSET UL(0x00000000) /* offset in VC of ARM memory */ + +#ifdef CONFIG_BCM2708_NOL2CACHE + #define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */ +#else + #define _REAL_BUS_OFFSET UL(0x40000000) /* use L2 cache */ +#endif + +/* We're using the memory at 64M in the VideoCore for Linux - this adjustment + * will provide the offset into this area as well as setting the bits that + * stop the L1 and L2 cache from being used + * + * WARNING: this only works because the ARM is given memory at a fixed location + * (ARMMEM_OFFSET) + */ +#define BUS_OFFSET (VC_ARMMEM_OFFSET + _REAL_BUS_OFFSET) +#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) +#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) +#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) +#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/platform.h raspilinux/arch/arm/mach-bcm2708/include/mach/platform.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/platform.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/platform.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,230 @@ +/* + * arch/arm/mach-bcm2708/include/mach/platform.h + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _BCM2708_PLATFORM_H +#define _BCM2708_PLATFORM_H + + +/* macros to get at IO space when running virtually */ +#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) + +#define __io_address(n) IOMEM(IO_ADDRESS(n)) + + +/* + * SDRAM + */ +#define BCM2708_SDRAM_BASE 0x00000000 + +/* + * Logic expansion modules + * + */ + + +/* ------------------------------------------------------------------------ + * BCM2708 ARMCTRL Registers + * ------------------------------------------------------------------------ + */ + +#define HW_REGISTER_RW(addr) (addr) +#define HW_REGISTER_RO(addr) (addr) + +#include "arm_control.h" +#undef ARM_BASE + +/* + * Definitions and addresses for the ARM CONTROL logic + * This file is manually generated. + */ + +#define BCM2708_PERI_BASE 0x20000000 +#define IC0_BASE (BCM2708_PERI_BASE + 0x2000) +#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */ +#define MPHI_BASE (BCM2708_PERI_BASE + 0x6000) /* Message -based Parallel Host Interface */ +#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ +#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ +#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ +#define PCM_CLOCK_BASE (BCM2708_PERI_BASE + 0x101098) /* PCM Clock */ +#define RNG_BASE (BCM2708_PERI_BASE + 0x104000) /* Hardware RNG */ +#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */ +#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ +#define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ +#define I2S_BASE (BCM2708_PERI_BASE + 0x203000) /* I2S */ +#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 */ +#define BSC0_BASE (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */ +#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */ +#define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */ +#define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */ +#define BSC1_BASE (BCM2708_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */ +#define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */ +#define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/ + +#define ARMCTRL_BASE (ARM_BASE + 0x000) +#define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ +#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ +#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ +#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ +#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ + + +/* + * Interrupt assignments + */ + +#define ARM_IRQ1_BASE 0 +#define INTERRUPT_TIMER0 (ARM_IRQ1_BASE + 0) +#define INTERRUPT_TIMER1 (ARM_IRQ1_BASE + 1) +#define INTERRUPT_TIMER2 (ARM_IRQ1_BASE + 2) +#define INTERRUPT_TIMER3 (ARM_IRQ1_BASE + 3) +#define INTERRUPT_CODEC0 (ARM_IRQ1_BASE + 4) +#define INTERRUPT_CODEC1 (ARM_IRQ1_BASE + 5) +#define INTERRUPT_CODEC2 (ARM_IRQ1_BASE + 6) +#define INTERRUPT_VC_JPEG (ARM_IRQ1_BASE + 7) +#define INTERRUPT_ISP (ARM_IRQ1_BASE + 8) +#define INTERRUPT_VC_USB (ARM_IRQ1_BASE + 9) +#define INTERRUPT_VC_3D (ARM_IRQ1_BASE + 10) +#define INTERRUPT_TRANSPOSER (ARM_IRQ1_BASE + 11) +#define INTERRUPT_MULTICORESYNC0 (ARM_IRQ1_BASE + 12) +#define INTERRUPT_MULTICORESYNC1 (ARM_IRQ1_BASE + 13) +#define INTERRUPT_MULTICORESYNC2 (ARM_IRQ1_BASE + 14) +#define INTERRUPT_MULTICORESYNC3 (ARM_IRQ1_BASE + 15) +#define INTERRUPT_DMA0 (ARM_IRQ1_BASE + 16) +#define INTERRUPT_DMA1 (ARM_IRQ1_BASE + 17) +#define INTERRUPT_VC_DMA2 (ARM_IRQ1_BASE + 18) +#define INTERRUPT_VC_DMA3 (ARM_IRQ1_BASE + 19) +#define INTERRUPT_DMA4 (ARM_IRQ1_BASE + 20) +#define INTERRUPT_DMA5 (ARM_IRQ1_BASE + 21) +#define INTERRUPT_DMA6 (ARM_IRQ1_BASE + 22) +#define INTERRUPT_DMA7 (ARM_IRQ1_BASE + 23) +#define INTERRUPT_DMA8 (ARM_IRQ1_BASE + 24) +#define INTERRUPT_DMA9 (ARM_IRQ1_BASE + 25) +#define INTERRUPT_DMA10 (ARM_IRQ1_BASE + 26) +#define INTERRUPT_DMA11 (ARM_IRQ1_BASE + 27) +#define INTERRUPT_DMA12 (ARM_IRQ1_BASE + 28) +#define INTERRUPT_AUX (ARM_IRQ1_BASE + 29) +#define INTERRUPT_ARM (ARM_IRQ1_BASE + 30) +#define INTERRUPT_VPUDMA (ARM_IRQ1_BASE + 31) + +#define ARM_IRQ2_BASE 32 +#define INTERRUPT_HOSTPORT (ARM_IRQ2_BASE + 0) +#define INTERRUPT_VIDEOSCALER (ARM_IRQ2_BASE + 1) +#define INTERRUPT_CCP2TX (ARM_IRQ2_BASE + 2) +#define INTERRUPT_SDC (ARM_IRQ2_BASE + 3) +#define INTERRUPT_DSI0 (ARM_IRQ2_BASE + 4) +#define INTERRUPT_AVE (ARM_IRQ2_BASE + 5) +#define INTERRUPT_CAM0 (ARM_IRQ2_BASE + 6) +#define INTERRUPT_CAM1 (ARM_IRQ2_BASE + 7) +#define INTERRUPT_HDMI0 (ARM_IRQ2_BASE + 8) +#define INTERRUPT_HDMI1 (ARM_IRQ2_BASE + 9) +#define INTERRUPT_PIXELVALVE1 (ARM_IRQ2_BASE + 10) +#define INTERRUPT_I2CSPISLV (ARM_IRQ2_BASE + 11) +#define INTERRUPT_DSI1 (ARM_IRQ2_BASE + 12) +#define INTERRUPT_PWA0 (ARM_IRQ2_BASE + 13) +#define INTERRUPT_PWA1 (ARM_IRQ2_BASE + 14) +#define INTERRUPT_CPR (ARM_IRQ2_BASE + 15) +#define INTERRUPT_SMI (ARM_IRQ2_BASE + 16) +#define INTERRUPT_GPIO0 (ARM_IRQ2_BASE + 17) +#define INTERRUPT_GPIO1 (ARM_IRQ2_BASE + 18) +#define INTERRUPT_GPIO2 (ARM_IRQ2_BASE + 19) +#define INTERRUPT_GPIO3 (ARM_IRQ2_BASE + 20) +#define INTERRUPT_VC_I2C (ARM_IRQ2_BASE + 21) +#define INTERRUPT_VC_SPI (ARM_IRQ2_BASE + 22) +#define INTERRUPT_VC_I2SPCM (ARM_IRQ2_BASE + 23) +#define INTERRUPT_VC_SDIO (ARM_IRQ2_BASE + 24) +#define INTERRUPT_VC_UART (ARM_IRQ2_BASE + 25) +#define INTERRUPT_SLIMBUS (ARM_IRQ2_BASE + 26) +#define INTERRUPT_VEC (ARM_IRQ2_BASE + 27) +#define INTERRUPT_CPG (ARM_IRQ2_BASE + 28) +#define INTERRUPT_RNG (ARM_IRQ2_BASE + 29) +#define INTERRUPT_VC_ARASANSDIO (ARM_IRQ2_BASE + 30) +#define INTERRUPT_AVSPMON (ARM_IRQ2_BASE + 31) + +#define ARM_IRQ0_BASE 64 +#define INTERRUPT_ARM_TIMER (ARM_IRQ0_BASE + 0) +#define INTERRUPT_ARM_MAILBOX (ARM_IRQ0_BASE + 1) +#define INTERRUPT_ARM_DOORBELL_0 (ARM_IRQ0_BASE + 2) +#define INTERRUPT_ARM_DOORBELL_1 (ARM_IRQ0_BASE + 3) +#define INTERRUPT_VPU0_HALTED (ARM_IRQ0_BASE + 4) +#define INTERRUPT_VPU1_HALTED (ARM_IRQ0_BASE + 5) +#define INTERRUPT_ILLEGAL_TYPE0 (ARM_IRQ0_BASE + 6) +#define INTERRUPT_ILLEGAL_TYPE1 (ARM_IRQ0_BASE + 7) +#define INTERRUPT_PENDING1 (ARM_IRQ0_BASE + 8) +#define INTERRUPT_PENDING2 (ARM_IRQ0_BASE + 9) +#define INTERRUPT_JPEG (ARM_IRQ0_BASE + 10) +#define INTERRUPT_USB (ARM_IRQ0_BASE + 11) +#define INTERRUPT_3D (ARM_IRQ0_BASE + 12) +#define INTERRUPT_DMA2 (ARM_IRQ0_BASE + 13) +#define INTERRUPT_DMA3 (ARM_IRQ0_BASE + 14) +#define INTERRUPT_I2C (ARM_IRQ0_BASE + 15) +#define INTERRUPT_SPI (ARM_IRQ0_BASE + 16) +#define INTERRUPT_I2SPCM (ARM_IRQ0_BASE + 17) +#define INTERRUPT_SDIO (ARM_IRQ0_BASE + 18) +#define INTERRUPT_UART (ARM_IRQ0_BASE + 19) +#define INTERRUPT_ARASANSDIO (ARM_IRQ0_BASE + 20) + +#define MAXIRQNUM (32 + 32 + 20) +#define MAXFIQNUM (32 + 32 + 20) + +#define MAX_TIMER 2 +#define MAX_PERIOD 699050 +#define TICKS_PER_uSEC 1 + +/* + * These are useconds NOT ticks. + * + */ +#define mSEC_1 1000 +#define mSEC_5 (mSEC_1 * 5) +#define mSEC_10 (mSEC_1 * 10) +#define mSEC_25 (mSEC_1 * 25) +#define SEC_1 (mSEC_1 * 1000) + +/* + * Watchdog + */ +#define PM_RSTC (PM_BASE+0x1c) +#define PM_RSTS (PM_BASE+0x20) +#define PM_WDOG (PM_BASE+0x24) + +#define PM_WDOG_RESET 0000000000 +#define PM_PASSWORD 0x5a000000 +#define PM_WDOG_TIME_SET 0x000fffff +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 + +#define PM_RSTS_HADPOR_SET 0x00001000 +#define PM_RSTS_HADSRH_SET 0x00000400 +#define PM_RSTS_HADSRF_SET 0x00000200 +#define PM_RSTS_HADSRQ_SET 0x00000100 +#define PM_RSTS_HADWRH_SET 0x00000040 +#define PM_RSTS_HADWRF_SET 0x00000020 +#define PM_RSTS_HADWRQ_SET 0x00000010 +#define PM_RSTS_HADDRH_SET 0x00000004 +#define PM_RSTS_HADDRF_SET 0x00000002 +#define PM_RSTS_HADDRQ_SET 0x00000001 + +#define UART0_CLOCK 3000000 + +#endif + +/* END */ diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/system.h raspilinux/arch/arm/mach-bcm2708/include/mach/system.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/system.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/system.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,38 @@ +/* + * arch/arm/mach-bcm2708/include/mach/system.h + * + * Copyright (C) 2010 Broadcom + * Copyright (C) 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +#include +#include +#include + +static inline void arch_idle(void) +{ + /* + * This should do all the clock switching + * and wait for interrupt tricks + */ + cpu_do_idle(); +} + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/timex.h raspilinux/arch/arm/mach-bcm2708/include/mach/timex.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/timex.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/timex.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,23 @@ +/* + * arch/arm/mach-bcm2708/include/mach/timex.h + * + * BCM2708 sysem clock frequency + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define CLOCK_TICK_RATE (1000000) diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/uncompress.h raspilinux/arch/arm/mach-bcm2708/include/mach/uncompress.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/uncompress.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/uncompress.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,84 @@ +/* + * arch/arm/mach-bcn2708/include/mach/uncompress.h + * + * Copyright (C) 2010 Broadcom + * Copyright (C) 2003 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#define UART_BAUD 115200 + +#define BCM2708_UART_DR __io(UART0_BASE + UART01x_DR) +#define BCM2708_UART_FR __io(UART0_BASE + UART01x_FR) +#define BCM2708_UART_IBRD __io(UART0_BASE + UART011_IBRD) +#define BCM2708_UART_FBRD __io(UART0_BASE + UART011_FBRD) +#define BCM2708_UART_LCRH __io(UART0_BASE + UART011_LCRH) +#define BCM2708_UART_CR __io(UART0_BASE + UART011_CR) + +/* + * This does not append a newline + */ +static inline void putc(int c) +{ + while (__raw_readl(BCM2708_UART_FR) & UART01x_FR_TXFF) + barrier(); + + __raw_writel(c, BCM2708_UART_DR); +} + +static inline void flush(void) +{ + int fr; + + do { + fr = __raw_readl(BCM2708_UART_FR); + barrier(); + } while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE); +} + +static inline void arch_decomp_setup(void) +{ + int temp, div, rem, frac; + + temp = 16 * UART_BAUD; + div = UART0_CLOCK / temp; + rem = UART0_CLOCK % temp; + temp = (8 * rem) / UART_BAUD; + frac = (temp >> 1) + (temp & 1); + + /* Make sure the UART is disabled before we start */ + __raw_writel(0, BCM2708_UART_CR); + + /* Set the baud rate */ + __raw_writel(div, BCM2708_UART_IBRD); + __raw_writel(frac, BCM2708_UART_FBRD); + + /* Set the UART to 8n1, FIFO enabled */ + __raw_writel(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, BCM2708_UART_LCRH); + + /* Enable the UART */ + __raw_writel(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE, + BCM2708_UART_CR); +} + +/* + * nothing to do + */ +#define arch_decomp_wdog() diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/vc_sm_defs.h raspilinux/arch/arm/mach-bcm2708/include/mach/vc_sm_defs.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/vc_sm_defs.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/vc_sm_defs.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,181 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#ifndef __VC_SM_DEFS_H__INCLUDED__ +#define __VC_SM_DEFS_H__INCLUDED__ + +/* FourCC code used for VCHI connection */ +#define VC_SM_SERVER_NAME MAKE_FOURCC("SMEM") + +/* Maximum message length */ +#define VC_SM_MAX_MSG_LEN (sizeof(VC_SM_MSG_UNION_T) + \ + sizeof(VC_SM_MSG_HDR_T)) +#define VC_SM_MAX_RSP_LEN (sizeof(VC_SM_MSG_UNION_T)) + +/* Resource name maximum size */ +#define VC_SM_RESOURCE_NAME 32 + +/* All message types supported for HOST->VC direction */ +typedef enum { + /* Allocate shared memory block */ + VC_SM_MSG_TYPE_ALLOC, + /* Lock allocated shared memory block */ + VC_SM_MSG_TYPE_LOCK, + /* Unlock allocated shared memory block */ + VC_SM_MSG_TYPE_UNLOCK, + /* Unlock allocated shared memory block, do not answer command */ + VC_SM_MSG_TYPE_UNLOCK_NOANS, + /* Free shared memory block */ + VC_SM_MSG_TYPE_FREE, + /* Resize a shared memory block */ + VC_SM_MSG_TYPE_RESIZE, + /* Walk the allocated shared memory block(s) */ + VC_SM_MSG_TYPE_WALK_ALLOC, + + /* A previously applied action will need to be reverted */ + VC_SM_MSG_TYPE_ACTION_CLEAN, + VC_SM_MSG_TYPE_MAX +} VC_SM_MSG_TYPE; + +/* Type of memory to be allocated */ +typedef enum { + VC_SM_ALLOC_CACHED, + VC_SM_ALLOC_NON_CACHED, + +} VC_SM_ALLOC_TYPE_T; + +/* Message header for all messages in HOST->VC direction */ +typedef struct { + int32_t type; + uint32_t trans_id; + uint8_t body[0]; + +} VC_SM_MSG_HDR_T; + +/* Request to allocate memory (HOST->VC) */ +typedef struct { + /* type of memory to allocate */ + VC_SM_ALLOC_TYPE_T type; + /* byte amount of data to allocate per unit */ + uint32_t base_unit; + /* number of unit to allocate */ + uint32_t num_unit; + /* alignement to be applied on allocation */ + uint32_t alignement; + /* identity of who allocated this block */ + uint32_t allocator; + /* resource name (for easier tracking on vc side) */ + char name[VC_SM_RESOURCE_NAME]; + +} VC_SM_ALLOC_T; + +/* Result of a requested memory allocation (VC->HOST) */ +typedef struct { + /* Transaction identifier */ + uint32_t trans_id; + + /* Resource handle */ + uint32_t res_handle; + /* Pointer to resource buffer */ + void *res_mem; + /* Resource base size (bytes) */ + uint32_t res_base_size; + /* Resource number */ + uint32_t res_num; + +} VC_SM_ALLOC_RESULT_T; + +/* Request to free a previously allocated memory (HOST->VC) */ +typedef struct { + /* Resource handle (returned from alloc) */ + uint32_t res_handle; + /* Resource buffer (returned from alloc) */ + void *res_mem; + +} VC_SM_FREE_T; + +/* Request to lock a previously allocated memory (HOST->VC) */ +typedef struct { + /* Resource handle (returned from alloc) */ + uint32_t res_handle; + /* Resource buffer (returned from alloc) */ + void *res_mem; + +} VC_SM_LOCK_UNLOCK_T; + +/* Request to resize a previously allocated memory (HOST->VC) */ +typedef struct { + /* Resource handle (returned from alloc) */ + uint32_t res_handle; + /* Resource buffer (returned from alloc) */ + void *res_mem; + /* Resource *new* size requested (bytes) */ + uint32_t res_new_size; + +} VC_SM_RESIZE_T; + +/* Result of a requested memory lock (VC->HOST) */ +typedef struct { + /* Transaction identifier */ + uint32_t trans_id; + + /* Resource handle */ + uint32_t res_handle; + /* Pointer to resource buffer */ + void *res_mem; + /* Pointer to former resource buffer if the memory + * was reallocated */ + void *res_old_mem; + +} VC_SM_LOCK_RESULT_T; + +/* Generic result for a request (VC->HOST) */ +typedef struct { + /* Transaction identifier */ + uint32_t trans_id; + + int32_t success; + +} VC_SM_RESULT_T; + +/* Request to revert a previously applied action (HOST->VC) */ +typedef struct { + /* Action of interest */ + VC_SM_MSG_TYPE res_action; + /* Transaction identifier for the action of interest */ + uint32_t action_trans_id; + +} VC_SM_ACTION_CLEAN_T; + +/* Request to remove all data associated with a given allocator (HOST->VC) */ +typedef struct { + /* Allocator identifier */ + uint32_t allocator; + +} VC_SM_FREE_ALL_T; + +/* Union of ALL messages */ +typedef union { + VC_SM_ALLOC_T alloc; + VC_SM_ALLOC_RESULT_T alloc_result; + VC_SM_FREE_T free; + VC_SM_ACTION_CLEAN_T action_clean; + VC_SM_RESIZE_T resize; + VC_SM_LOCK_RESULT_T lock_result; + VC_SM_RESULT_T result; + VC_SM_FREE_ALL_T free_all; + +} VC_SM_MSG_UNION_T; + +#endif /* __VC_SM_DEFS_H__INCLUDED__ */ diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/vc_sm_knl.h raspilinux/arch/arm/mach-bcm2708/include/mach/vc_sm_knl.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/vc_sm_knl.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/vc_sm_knl.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,55 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#ifndef __VC_SM_KNL_H__INCLUDED__ +#define __VC_SM_KNL_H__INCLUDED__ + +#if !defined(__KERNEL__) +#error "This interface is for kernel use only..." +#endif + +/* Type of memory to be locked (ie mapped) */ +typedef enum { + VC_SM_LOCK_CACHED, + VC_SM_LOCK_NON_CACHED, + +} VC_SM_LOCK_CACHE_MODE_T; + +/* Allocate a shared memory handle and block. +*/ +int vc_sm_alloc(VC_SM_ALLOC_T *alloc, int *handle); + +/* Free a previously allocated shared memory handle and block. +*/ +int vc_sm_free(int handle); + +/* Lock a memory handle for use by kernel. +*/ +int vc_sm_lock(int handle, VC_SM_LOCK_CACHE_MODE_T mode, + long unsigned int *data); + +/* Unlock a memory handle in use by kernel. +*/ +int vc_sm_unlock(int handle, int flush, int no_vc_unlock); + +/* Get an internal resource handle mapped from the external one. +*/ +int vc_sm_int_handle(int handle); + +/* Map a shared memory region for use by kernel. +*/ +int vc_sm_map(int handle, unsigned int sm_addr, VC_SM_LOCK_CACHE_MODE_T mode, + long unsigned int *data); + +#endif /* __VC_SM_KNL_H__INCLUDED__ */ diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/vc_vchi_sm.h raspilinux/arch/arm/mach-bcm2708/include/mach/vc_vchi_sm.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/vc_vchi_sm.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/vc_vchi_sm.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,82 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#ifndef __VC_VCHI_SM_H__INCLUDED__ +#define __VC_VCHI_SM_H__INCLUDED__ + +#include "interface/vchi/vchi.h" + +#include "vc_sm_defs.h" + +/* Forward declare. +*/ +typedef struct sm_instance *VC_VCHI_SM_HANDLE_T; + +/* Initialize the shared memory service, opens up vchi connection to talk to it. +*/ +VC_VCHI_SM_HANDLE_T vc_vchi_sm_init(VCHI_INSTANCE_T vchi_instance, + VCHI_CONNECTION_T **vchi_connections, + uint32_t num_connections); + +/* Terminates the shared memory service. +*/ +int vc_vchi_sm_stop(VC_VCHI_SM_HANDLE_T *handle); + +/* Ask the shared memory service to allocate some memory on videocre and +** return the result of this allocation (which upon success will be a pointer +** to some memory in videocore space). +*/ +int vc_vchi_sm_alloc(VC_VCHI_SM_HANDLE_T handle, + VC_SM_ALLOC_T *alloc, + VC_SM_ALLOC_RESULT_T *alloc_result, uint32_t *trans_id); + +/* Ask the shared memory service to free up some memory that was previously +** allocated by the vc_vchi_sm_alloc function call. +*/ +int vc_vchi_sm_free(VC_VCHI_SM_HANDLE_T handle, + VC_SM_FREE_T *free, uint32_t *trans_id); + +/* Ask the shared memory service to lock up some memory that was previously +** allocated by the vc_vchi_sm_alloc function call. +*/ +int vc_vchi_sm_lock(VC_VCHI_SM_HANDLE_T handle, + VC_SM_LOCK_UNLOCK_T *lock_unlock, + VC_SM_LOCK_RESULT_T *lock_result, uint32_t *trans_id); + +/* Ask the shared memory service to unlock some memory that was previously +** allocated by the vc_vchi_sm_alloc function call. +*/ +int vc_vchi_sm_unlock(VC_VCHI_SM_HANDLE_T handle, + VC_SM_LOCK_UNLOCK_T *lock_unlock, + uint32_t *trans_id, uint8_t wait_reply); + +/* Ask the shared memory service to resize some memory that was previously +** allocated by the vc_vchi_sm_alloc function call. +*/ +int vc_vchi_sm_resize(VC_VCHI_SM_HANDLE_T handle, + VC_SM_RESIZE_T *resize, uint32_t *trans_id); + +/* Walk the allocated resources on the videocore side, the allocation will +** show up in the log. This is purely for debug/information and takes no +** specific actions. +*/ +int vc_vchi_sm_walk_alloc(VC_VCHI_SM_HANDLE_T handle); + +/* Clean up following a previously interrupted action which left the system +** in a bad state of some sort. +*/ +int vc_vchi_sm_clean_up(VC_VCHI_SM_HANDLE_T handle, + VC_SM_ACTION_CLEAN_T *action_clean); + +#endif /* __VC_VCHI_SM_H__INCLUDED__ */ diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/vmalloc.h raspilinux/arch/arm/mach-bcm2708/include/mach/vmalloc.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/vmalloc.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/vmalloc.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,20 @@ +/* + * arch/arm/mach-bcm2708/include/mach/vmalloc.h + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#define VMALLOC_END (0xe8000000) diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h raspilinux/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h --- linux-stable/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,248 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +* +*****************************************************************************/ + +#if !defined(__VMCS_SM_IOCTL_H__INCLUDED__) +#define __VMCS_SM_IOCTL_H__INCLUDED__ + +/* ---- Include Files ---------------------------------------------------- */ + +#if defined(__KERNEL__) +#include /* Needed for standard types */ +#else +#include +#endif + +#include + +/* ---- Constants and Types ---------------------------------------------- */ + +#define VMCS_SM_RESOURCE_NAME 32 +#define VMCS_SM_RESOURCE_NAME_DEFAULT "sm-host-resource" + +/* Type define used to create unique IOCTL number */ +#define VMCS_SM_MAGIC_TYPE 'I' + +/* IOCTL commands */ +enum vmcs_sm_cmd_e { + VMCS_SM_CMD_ALLOC = 0x5A, /* Start at 0x5A arbitrarily */ + VMCS_SM_CMD_ALLOC_SHARE, + VMCS_SM_CMD_LOCK, + VMCS_SM_CMD_LOCK_CACHE, + VMCS_SM_CMD_UNLOCK, + VMCS_SM_CMD_RESIZE, + VMCS_SM_CMD_UNMAP, + VMCS_SM_CMD_FREE, + VMCS_SM_CMD_FLUSH, + VMCS_SM_CMD_INVALID, + + VMCS_SM_CMD_SIZE_USR_HANDLE, + VMCS_SM_CMD_CHK_USR_HANDLE, + + VMCS_SM_CMD_MAPPED_USR_HANDLE, + VMCS_SM_CMD_MAPPED_USR_ADDRESS, + VMCS_SM_CMD_MAPPED_VC_HDL_FROM_ADDR, + VMCS_SM_CMD_MAPPED_VC_HDL_FROM_HDL, + VMCS_SM_CMD_MAPPED_VC_ADDR_FROM_HDL, + + VMCS_SM_CMD_VC_WALK_ALLOC, + VMCS_SM_CMD_HOST_WALK_MAP, + VMCS_SM_CMD_HOST_WALK_PID_ALLOC, + VMCS_SM_CMD_HOST_WALK_PID_MAP, + + VMCS_SM_CMD_CLEAN_INVALID, + + VMCS_SM_CMD_LAST /* Do no delete */ +}; + +/* Cache type supported, conveniently matches the user space definition in +** user-vcsm.h. +*/ +enum vmcs_sm_cache_e { + VMCS_SM_CACHE_NONE, + VMCS_SM_CACHE_HOST, + VMCS_SM_CACHE_VC, + VMCS_SM_CACHE_BOTH, +}; + +/* IOCTL Data structures */ +struct vmcs_sm_ioctl_alloc { + /* user -> kernel */ + unsigned int size; + unsigned int num; + enum vmcs_sm_cache_e cached; + char name[VMCS_SM_RESOURCE_NAME]; + + /* kernel -> user */ + unsigned int handle; + /* unsigned int base_addr; */ +}; + +struct vmcs_sm_ioctl_alloc_share { + /* user -> kernel */ + unsigned int handle; + unsigned int size; +}; + +struct vmcs_sm_ioctl_free { + /* user -> kernel */ + unsigned int handle; + /* unsigned int base_addr; */ +}; + +struct vmcs_sm_ioctl_lock_unlock { + /* user -> kernel */ + unsigned int handle; + + /* kernel -> user */ + unsigned int addr; +}; + +struct vmcs_sm_ioctl_lock_cache { + /* user -> kernel */ + unsigned int handle; + enum vmcs_sm_cache_e cached; +}; + +struct vmcs_sm_ioctl_resize { + /* user -> kernel */ + unsigned int handle; + unsigned int new_size; + + /* kernel -> user */ + unsigned int old_size; +}; + +struct vmcs_sm_ioctl_map { + /* user -> kernel */ + /* and kernel -> user */ + unsigned int pid; + unsigned int handle; + unsigned int addr; + + /* kernel -> user */ + unsigned int size; +}; + +struct vmcs_sm_ioctl_walk { + /* user -> kernel */ + unsigned int pid; +}; + +struct vmcs_sm_ioctl_chk { + /* user -> kernel */ + unsigned int handle; + + /* kernel -> user */ + unsigned int addr; + unsigned int size; + enum vmcs_sm_cache_e cache; +}; + +struct vmcs_sm_ioctl_size { + /* user -> kernel */ + unsigned int handle; + + /* kernel -> user */ + unsigned int size; +}; + +struct vmcs_sm_ioctl_cache { + /* user -> kernel */ + unsigned int handle; + unsigned int addr; + unsigned int size; +}; + +struct vmcs_sm_ioctl_clean_invalid { + /* user -> kernel */ + struct { + unsigned int cmd; + unsigned int handle; + unsigned int addr; + unsigned int size; + } s[8]; +}; + +/* IOCTL numbers */ +#define VMCS_SM_IOCTL_MEM_ALLOC\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_ALLOC,\ + struct vmcs_sm_ioctl_alloc) +#define VMCS_SM_IOCTL_MEM_ALLOC_SHARE\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_ALLOC_SHARE,\ + struct vmcs_sm_ioctl_alloc_share) +#define VMCS_SM_IOCTL_MEM_LOCK\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_LOCK,\ + struct vmcs_sm_ioctl_lock_unlock) +#define VMCS_SM_IOCTL_MEM_LOCK_CACHE\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_LOCK_CACHE,\ + struct vmcs_sm_ioctl_lock_cache) +#define VMCS_SM_IOCTL_MEM_UNLOCK\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_UNLOCK,\ + struct vmcs_sm_ioctl_lock_unlock) +#define VMCS_SM_IOCTL_MEM_RESIZE\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_RESIZE,\ + struct vmcs_sm_ioctl_resize) +#define VMCS_SM_IOCTL_MEM_FREE\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_FREE,\ + struct vmcs_sm_ioctl_free) +#define VMCS_SM_IOCTL_MEM_FLUSH\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_FLUSH,\ + struct vmcs_sm_ioctl_cache) +#define VMCS_SM_IOCTL_MEM_INVALID\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_INVALID,\ + struct vmcs_sm_ioctl_cache) +#define VMCS_SM_IOCTL_MEM_CLEAN_INVALID\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_CLEAN_INVALID,\ + struct vmcs_sm_ioctl_clean_invalid) + +#define VMCS_SM_IOCTL_SIZE_USR_HDL\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_SIZE_USR_HANDLE,\ + struct vmcs_sm_ioctl_size) +#define VMCS_SM_IOCTL_CHK_USR_HDL\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_CHK_USR_HANDLE,\ + struct vmcs_sm_ioctl_chk) + +#define VMCS_SM_IOCTL_MAP_USR_HDL\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_USR_HANDLE,\ + struct vmcs_sm_ioctl_map) +#define VMCS_SM_IOCTL_MAP_USR_ADDRESS\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_USR_ADDRESS,\ + struct vmcs_sm_ioctl_map) +#define VMCS_SM_IOCTL_MAP_VC_HDL_FR_ADDR\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_VC_HDL_FROM_ADDR,\ + struct vmcs_sm_ioctl_map) +#define VMCS_SM_IOCTL_MAP_VC_HDL_FR_HDL\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_VC_HDL_FROM_HDL,\ + struct vmcs_sm_ioctl_map) +#define VMCS_SM_IOCTL_MAP_VC_ADDR_FR_HDL\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_MAPPED_VC_ADDR_FROM_HDL,\ + struct vmcs_sm_ioctl_map) + +#define VMCS_SM_IOCTL_VC_WALK_ALLOC\ + _IO(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_VC_WALK_ALLOC) +#define VMCS_SM_IOCTL_HOST_WALK_MAP\ + _IO(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_HOST_WALK_MAP) +#define VMCS_SM_IOCTL_HOST_WALK_PID_ALLOC\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_HOST_WALK_PID_ALLOC,\ + struct vmcs_sm_ioctl_walk) +#define VMCS_SM_IOCTL_HOST_WALK_PID_MAP\ + _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_HOST_WALK_PID_MAP,\ + struct vmcs_sm_ioctl_walk) + +/* ---- Variable Externs ------------------------------------------------- */ + +/* ---- Function Prototypes ---------------------------------------------- */ + +#endif /* __VMCS_SM_IOCTL_H__INCLUDED__ */ diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/Kconfig raspilinux/arch/arm/mach-bcm2708/Kconfig --- linux-stable/arch/arm/mach-bcm2708/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/Kconfig 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,45 @@ +menu "Broadcom BCM2708 Implementations" + depends on ARCH_BCM2708 + +config MACH_BCM2708 + bool "Broadcom BCM2708 Development Platform" + select NEED_MACH_MEMORY_H + select NEED_MACH_IO_H + select CPU_V6 + help + Include support for the Broadcom(R) BCM2708 platform. + +config BCM2708_DT + bool "BCM2708 Device Tree support" + depends on MACH_BCM2708 + default n + select USE_OF + select ARCH_REQUIRE_GPIOLIB + select PINCTRL + select PINCTRL_BCM2835 + help + Enable Device Tree support for BCM2708 + +config BCM2708_GPIO + bool "BCM2708 gpio support" + depends on MACH_BCM2708 + select ARCH_REQUIRE_GPIOLIB + default y + help + Include support for the Broadcom(R) BCM2708 gpio. + +config BCM2708_NOL2CACHE + bool "Videocore L2 cache disable" + depends on MACH_BCM2708 + default n + help + Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. + +config BCM2708_SPIDEV + bool "Bind spidev to SPI0 master" + depends on MACH_BCM2708 + depends on SPI + default y + help + Binds spidev driver to the SPI0 master +endmenu diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/Makefile raspilinux/arch/arm/mach-bcm2708/Makefile --- linux-stable/arch/arm/mach-bcm2708/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/Makefile 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,6 @@ +# +# Makefile for the linux kernel. +# + +obj-$(CONFIG_MACH_BCM2708) += bcm2708.o armctrl.o +obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2708/Makefile.boot raspilinux/arch/arm/mach-bcm2708/Makefile.boot --- linux-stable/arch/arm/mach-bcm2708/Makefile.boot 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2708/Makefile.boot 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,3 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00800000 diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/armctrl.c raspilinux/arch/arm/mach-bcm2709/armctrl.c --- linux-stable/arch/arm/mach-bcm2709/armctrl.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/armctrl.c 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,384 @@ +/* + * linux/arch/arm/mach-bcm2708/armctrl.c + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "armctrl.h" + +/* For support of kernels >= 3.0 assume only one VIC for now*/ +static unsigned int remap_irqs[(INTERRUPT_ARASANSDIO + 1) - INTERRUPT_JPEG] = { + INTERRUPT_VC_JPEG, + INTERRUPT_VC_USB, + INTERRUPT_VC_3D, + INTERRUPT_VC_DMA2, + INTERRUPT_VC_DMA3, + INTERRUPT_VC_I2C, + INTERRUPT_VC_SPI, + INTERRUPT_VC_I2SPCM, + INTERRUPT_VC_SDIO, + INTERRUPT_VC_UART, + INTERRUPT_VC_ARASANSDIO +}; + +extern unsigned force_core; + +static void armctrl_mask_irq(struct irq_data *d) +{ + static const unsigned int disables[4] = { + ARM_IRQ_DIBL1, + ARM_IRQ_DIBL2, + ARM_IRQ_DIBL3, + 0 + }; + int i; + if (d->irq >= FIQ_START) { + writel(0, __io_address(ARM_IRQ_FAST)); + } else if (d->irq >= IRQ_ARM_LOCAL_CNTPSIRQ && d->irq < IRQ_ARM_LOCAL_CNTPSIRQ + 4) { +#if 1 + unsigned int data = (unsigned int)irq_get_chip_data(d->irq) - IRQ_ARM_LOCAL_CNTPSIRQ; + for (i=0; i<4; i++) // i = raw_smp_processor_id(); // + { + unsigned int val = readl(__io_address(ARM_LOCAL_TIMER_INT_CONTROL0 + 4*i)); + writel(val &~ (1 << data), __io_address(ARM_LOCAL_TIMER_INT_CONTROL0 + 4*i)); + } +#endif + } else if (d->irq >= IRQ_ARM_LOCAL_MAILBOX0 && d->irq < IRQ_ARM_LOCAL_MAILBOX0 + 4) { +#if 0 + unsigned int data = (unsigned int)irq_get_chip_data(d->irq) - IRQ_ARM_LOCAL_MAILBOX0; + for (i=0; i<4; i++) { + unsigned int val = readl(__io_address(ARM_LOCAL_MAILBOX_INT_CONTROL0 + 4*i)); + writel(val &~ (1 << data), __io_address(ARM_LOCAL_MAILBOX_INT_CONTROL0 + 4*i)); + } +#endif + } else if (d->irq >= ARM_IRQ1_BASE && d->irq < ARM_IRQ_LOCAL_BASE) { + unsigned int data = (unsigned int)irq_get_chip_data(d->irq); + writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3])); + } else if (d->irq == INTERRUPT_ARM_LOCAL_PMU_FAST) { + writel(0xf, __io_address(ARM_LOCAL_PM_ROUTING_CLR)); + } else { printk("%s: %d\n", __func__, d->irq); BUG(); } +} + +static void armctrl_unmask_irq(struct irq_data *d) +{ + static const unsigned int enables[4] = { + ARM_IRQ_ENBL1, + ARM_IRQ_ENBL2, + ARM_IRQ_ENBL3, + 0 + }; + int i; + if (d->irq >= FIQ_START) { + unsigned int data; + if (force_core) { + data = readl(__io_address(ARM_LOCAL_GPU_INT_ROUTING)); + data &= ~0xc; + data |= ((force_core-1) << 2); + writel(data, __io_address(ARM_LOCAL_GPU_INT_ROUTING)); + } + else if (num_online_cpus() > 1) { + data = readl(__io_address(ARM_LOCAL_GPU_INT_ROUTING)); + data &= ~0xc; + data |= (1 << 2); + writel(data, __io_address(ARM_LOCAL_GPU_INT_ROUTING)); + } + /* Unmask in ARMCTRL block after routing it properly */ + data = (unsigned int)irq_get_chip_data(d->irq) - FIQ_START; + writel(0x80 | data, __io_address(ARM_IRQ_FAST)); + } else if (d->irq >= IRQ_ARM_LOCAL_CNTPSIRQ && d->irq < IRQ_ARM_LOCAL_CNTPSIRQ + 4) { +#if 1 + unsigned int data = (unsigned int)irq_get_chip_data(d->irq) - IRQ_ARM_LOCAL_CNTPSIRQ; + for (i=0; i<4; i++) // i = raw_smp_processor_id(); + { + unsigned int val = readl(__io_address(ARM_LOCAL_TIMER_INT_CONTROL0 + 4*i)); + writel(val | (1 << data), __io_address(ARM_LOCAL_TIMER_INT_CONTROL0 + 4*i)); + } +#endif + } else if (d->irq >= IRQ_ARM_LOCAL_MAILBOX0 && d->irq < IRQ_ARM_LOCAL_MAILBOX0 + 4) { +#if 0 + unsigned int data = (unsigned int)irq_get_chip_data(d->irq) - IRQ_ARM_LOCAL_MAILBOX0; + for (i=0; i<4; i++) { + unsigned int val = readl(__io_address(ARM_LOCAL_MAILBOX_INT_CONTROL0 + 4*i)); + writel(val | (1 << data), __io_address(ARM_LOCAL_MAILBOX_INT_CONTROL0 + 4*i)); + } +#endif + } else if (d->irq >= ARM_IRQ1_BASE && d->irq < ARM_IRQ_LOCAL_BASE) { + if (force_core) { + unsigned int data; + data = readl(__io_address(ARM_LOCAL_GPU_INT_ROUTING)); + data &= ~0x3; + data |= ((force_core-1) << 0); + writel(data, __io_address(ARM_LOCAL_GPU_INT_ROUTING)); + } + unsigned int data = (unsigned int)irq_get_chip_data(d->irq); + writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3])); + } else if (d->irq == INTERRUPT_ARM_LOCAL_PMU_FAST) { + writel(0xf, __io_address(ARM_LOCAL_PM_ROUTING_SET)); + } else { printk("%s: %d\n", __func__, d->irq); BUG(); } +} + +#ifdef CONFIG_OF + +#define NR_IRQS_BANK0 21 +#define NR_BANKS 4 +#define IRQS_PER_BANK 32 + +/* from drivers/irqchip/irq-bcm2835.c */ +static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr, + const u32 *intspec, unsigned int intsize, + unsigned long *out_hwirq, unsigned int *out_type) +{ + if (WARN_ON(intsize != 2)) + return -EINVAL; + + if (WARN_ON(intspec[0] >= NR_BANKS)) + return -EINVAL; + + if (WARN_ON(intspec[1] >= IRQS_PER_BANK)) + return -EINVAL; + + if (WARN_ON(intspec[0] == 0 && intspec[1] >= NR_IRQS_BANK0)) + return -EINVAL; + + if (WARN_ON(intspec[0] == 3 && intspec[1] > 3 && intspec[1] != 5 && intspec[1] != 9)) + return -EINVAL; + + if (intspec[0] == 0) + *out_hwirq = ARM_IRQ0_BASE + intspec[1]; + else if (intspec[0] == 1) + *out_hwirq = ARM_IRQ1_BASE + intspec[1]; + else if (intspec[0] == 2) + *out_hwirq = ARM_IRQ2_BASE + intspec[1]; + else + *out_hwirq = ARM_IRQ_LOCAL_BASE + intspec[1]; + + /* reverse remap_irqs[] */ + switch (*out_hwirq) { + case INTERRUPT_VC_JPEG: + *out_hwirq = INTERRUPT_JPEG; + break; + case INTERRUPT_VC_USB: + *out_hwirq = INTERRUPT_USB; + break; + case INTERRUPT_VC_3D: + *out_hwirq = INTERRUPT_3D; + break; + case INTERRUPT_VC_DMA2: + *out_hwirq = INTERRUPT_DMA2; + break; + case INTERRUPT_VC_DMA3: + *out_hwirq = INTERRUPT_DMA3; + break; + case INTERRUPT_VC_I2C: + *out_hwirq = INTERRUPT_I2C; + break; + case INTERRUPT_VC_SPI: + *out_hwirq = INTERRUPT_SPI; + break; + case INTERRUPT_VC_I2SPCM: + *out_hwirq = INTERRUPT_I2SPCM; + break; + case INTERRUPT_VC_SDIO: + *out_hwirq = INTERRUPT_SDIO; + break; + case INTERRUPT_VC_UART: + *out_hwirq = INTERRUPT_UART; + break; + case INTERRUPT_VC_ARASANSDIO: + *out_hwirq = INTERRUPT_ARASANSDIO; + break; + } + + *out_type = IRQ_TYPE_NONE; + return 0; +} + +static struct irq_domain_ops armctrl_ops = { + .xlate = armctrl_xlate +}; + +void __init armctrl_dt_init(void) +{ + struct device_node *np; + struct irq_domain *domain; + + np = of_find_compatible_node(NULL, NULL, "brcm,bcm2708-armctrl-ic"); + if (!np) + return; + + domain = irq_domain_add_legacy(np, BCM2708_ALLOC_IRQS, + IRQ_ARMCTRL_START, 0, + &armctrl_ops, NULL); + WARN_ON(!domain); +} +#else +void __init armctrl_dt_init(void) { } +#endif /* CONFIG_OF */ + +#if defined(CONFIG_PM) + +/* for kernels 3.xx use the new syscore_ops apis but for older kernels use the sys dev class */ + +/* Static defines + * struct armctrl_device - VIC PM device (< 3.xx) + * @sysdev: The system device which is registered. (< 3.xx) + * @irq: The IRQ number for the base of the VIC. + * @base: The register base for the VIC. + * @resume_sources: A bitmask of interrupts for resume. + * @resume_irqs: The IRQs enabled for resume. + * @int_select: Save for VIC_INT_SELECT. + * @int_enable: Save for VIC_INT_ENABLE. + * @soft_int: Save for VIC_INT_SOFT. + * @protect: Save for VIC_PROTECT. + */ +struct armctrl_info { + void __iomem *base; + int irq; + u32 resume_sources; + u32 resume_irqs; + u32 int_select; + u32 int_enable; + u32 soft_int; + u32 protect; +} armctrl; + +static int armctrl_suspend(void) +{ + return 0; +} + +static void armctrl_resume(void) +{ + return; +} + +/** + * armctrl_pm_register - Register a VIC for later power management control + * @base: The base address of the VIC. + * @irq: The base IRQ for the VIC. + * @resume_sources: bitmask of interrupts allowed for resume sources. + * + * For older kernels (< 3.xx) do - + * Register the VIC with the system device tree so that it can be notified + * of suspend and resume requests and ensure that the correct actions are + * taken to re-instate the settings on resume. + */ +static void __init armctrl_pm_register(void __iomem * base, unsigned int irq, + u32 resume_sources) +{ + armctrl.base = base; + armctrl.resume_sources = resume_sources; + armctrl.irq = irq; +} + +static int armctrl_set_wake(struct irq_data *d, unsigned int on) +{ + unsigned int off = d->irq & 31; + u32 bit = 1 << off; + + if (!(bit & armctrl.resume_sources)) + return -EINVAL; + + if (on) + armctrl.resume_irqs |= bit; + else + armctrl.resume_irqs &= ~bit; + + return 0; +} + +#else +static inline void armctrl_pm_register(void __iomem * base, unsigned int irq, + u32 arg1) +{ +} + +#define armctrl_suspend NULL +#define armctrl_resume NULL +#define armctrl_set_wake NULL +#endif /* CONFIG_PM */ + +static struct syscore_ops armctrl_syscore_ops = { + .suspend = armctrl_suspend, + .resume = armctrl_resume, +}; + +/** + * armctrl_syscore_init - initicall to register VIC pm functions + * + * This is called via late_initcall() to register + * the resources for the VICs due to the early + * nature of the VIC's registration. +*/ +static int __init armctrl_syscore_init(void) +{ + register_syscore_ops(&armctrl_syscore_ops); + return 0; +} + +late_initcall(armctrl_syscore_init); + +static struct irq_chip armctrl_chip = { + .name = "ARMCTRL", + .irq_ack = NULL, + .irq_mask = armctrl_mask_irq, + .irq_unmask = armctrl_unmask_irq, + .irq_set_wake = armctrl_set_wake, +}; + +/** + * armctrl_init - initialise a vectored interrupt controller + * @base: iomem base address + * @irq_start: starting interrupt number, must be muliple of 32 + * @armctrl_sources: bitmask of interrupt sources to allow + * @resume_sources: bitmask of interrupt sources to allow for resume + */ +int __init armctrl_init(void __iomem * base, unsigned int irq_start, + u32 armctrl_sources, u32 resume_sources) +{ + unsigned int irq; + + for (irq = 0; irq < BCM2708_ALLOC_IRQS; irq++) { + unsigned int data = irq; + if (irq >= INTERRUPT_JPEG && irq <= INTERRUPT_ARASANSDIO) + data = remap_irqs[irq - INTERRUPT_JPEG]; + if (irq >= IRQ_ARM_LOCAL_CNTPSIRQ && irq <= IRQ_ARM_LOCAL_TIMER) { + irq_set_percpu_devid(irq); + irq_set_chip_and_handler(irq, &armctrl_chip, handle_percpu_devid_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); + } else { + irq_set_chip_and_handler(irq, &armctrl_chip, handle_level_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + irq_set_chip_data(irq, (void *)data); + } + + armctrl_pm_register(base, irq_start, resume_sources); + init_FIQ(FIQ_START); + armctrl_dt_init(); + return 0; +} diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/armctrl.h raspilinux/arch/arm/mach-bcm2709/armctrl.h --- linux-stable/arch/arm/mach-bcm2709/armctrl.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/armctrl.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,27 @@ +/* + * linux/arch/arm/mach-bcm2708/armctrl.h + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BCM2708_ARMCTRL_H +#define __BCM2708_ARMCTRL_H + +extern int __init armctrl_init(void __iomem * base, unsigned int irq_start, + u32 armctrl_sources, u32 resume_sources); + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/bcm2708_gpio.c raspilinux/arch/arm/mach-bcm2709/bcm2708_gpio.c --- linux-stable/arch/arm/mach-bcm2709/bcm2708_gpio.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/bcm2708_gpio.c 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,426 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708_gpio.c + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" +#define DRIVER_NAME BCM_GPIO_DRIVER_NAME +#define BCM_GPIO_USE_IRQ 1 + +#define GPIOFSEL(x) (0x00+(x)*4) +#define GPIOSET(x) (0x1c+(x)*4) +#define GPIOCLR(x) (0x28+(x)*4) +#define GPIOLEV(x) (0x34+(x)*4) +#define GPIOEDS(x) (0x40+(x)*4) +#define GPIOREN(x) (0x4c+(x)*4) +#define GPIOFEN(x) (0x58+(x)*4) +#define GPIOHEN(x) (0x64+(x)*4) +#define GPIOLEN(x) (0x70+(x)*4) +#define GPIOAREN(x) (0x7c+(x)*4) +#define GPIOAFEN(x) (0x88+(x)*4) +#define GPIOUD(x) (0x94+(x)*4) +#define GPIOUDCLK(x) (0x98+(x)*4) + +#define GPIO_BANKS 2 + +enum { GPIO_FSEL_INPUT, GPIO_FSEL_OUTPUT, + GPIO_FSEL_ALT5, GPIO_FSEL_ALT_4, + GPIO_FSEL_ALT0, GPIO_FSEL_ALT1, + GPIO_FSEL_ALT2, GPIO_FSEL_ALT3, +}; + + /* Each of the two spinlocks protects a different set of hardware + * regiters and data structurs. This decouples the code of the IRQ from + * the GPIO code. This also makes the case of a GPIO routine call from + * the IRQ code simpler. + */ +static DEFINE_SPINLOCK(lock); /* GPIO registers */ + +struct bcm2708_gpio { + struct list_head list; + void __iomem *base; + struct gpio_chip gc; + unsigned long rising[(BCM2708_NR_GPIOS + 31) / 32]; + unsigned long falling[(BCM2708_NR_GPIOS + 31) / 32]; + unsigned long high[(BCM2708_NR_GPIOS + 31) / 32]; + unsigned long low[(BCM2708_NR_GPIOS + 31) / 32]; +}; + +static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset, + int function) +{ + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); + unsigned long flags; + unsigned gpiodir; + unsigned gpio_bank = offset / 10; + 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 >= BCM2708_NR_GPIOS) + return -EINVAL; + + spin_lock_irqsave(&lock, flags); + + gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank)); + gpiodir &= ~(7 << gpio_field_offset); + gpiodir |= function << gpio_field_offset; + writel(gpiodir, gpio->base + GPIOFSEL(gpio_bank)); + spin_unlock_irqrestore(&lock, flags); + gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank)); + + return 0; +} + +static int bcm2708_gpio_dir_in(struct gpio_chip *gc, unsigned offset) +{ + return bcm2708_set_function(gc, offset, GPIO_FSEL_INPUT); +} + +static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value); +static int bcm2708_gpio_dir_out(struct gpio_chip *gc, unsigned offset, + int value) +{ + int ret; + ret = bcm2708_set_function(gc, offset, GPIO_FSEL_OUTPUT); + if (ret >= 0) + bcm2708_gpio_set(gc, offset, value); + return ret; +} + +static int bcm2708_gpio_get(struct gpio_chip *gc, unsigned offset) +{ + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); + unsigned gpio_bank = offset / 32; + unsigned gpio_field_offset = (offset - 32 * gpio_bank); + unsigned lev; + + 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)); + return 0x1 & (lev >> gpio_field_offset); +} + +static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value) +{ + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); + 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 >= BCM2708_NR_GPIOS) + return; + if (value) + writel(1 << gpio_field_offset, gpio->base + GPIOSET(gpio_bank)); + else + writel(1 << gpio_field_offset, gpio->base + GPIOCLR(gpio_bank)); +} + +/********************** + * extension to configure pullups + */ +int bcm2708_gpio_setpull(struct gpio_chip *gc, unsigned offset, + bcm2708_gpio_pull_t value) +{ + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); + unsigned gpio_bank = offset / 32; + unsigned gpio_field_offset = (offset - 32 * gpio_bank); + + if (offset >= BCM2708_NR_GPIOS) + return -EINVAL; + + switch (value) { + case BCM2708_PULL_UP: + writel(2, gpio->base + GPIOUD(0)); + break; + case BCM2708_PULL_DOWN: + writel(1, gpio->base + GPIOUD(0)); + break; + case BCM2708_PULL_OFF: + writel(0, gpio->base + GPIOUD(0)); + break; + } + + udelay(5); + writel(1 << gpio_field_offset, gpio->base + GPIOUDCLK(gpio_bank)); + udelay(5); + writel(0, gpio->base + GPIOUD(0)); + writel(0 << gpio_field_offset, gpio->base + GPIOUDCLK(gpio_bank)); + + return 0; +} +EXPORT_SYMBOL(bcm2708_gpio_setpull); + +/************************************************************************************************************************* + * bcm2708 GPIO IRQ + */ + +#if BCM_GPIO_USE_IRQ + +static int bcm2708_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) +{ + return gpio_to_irq(gpio); +} + +static int bcm2708_gpio_irq_set_type(struct irq_data *d, unsigned type) +{ + unsigned irq = d->irq; + struct bcm2708_gpio *gpio = irq_get_chip_data(irq); + unsigned gn = irq_to_gpio(irq); + unsigned gb = gn / 32; + unsigned go = gn % 32; + + gpio->rising[gb] &= ~(1 << go); + gpio->falling[gb] &= ~(1 << go); + gpio->high[gb] &= ~(1 << go); + gpio->low[gb] &= ~(1 << go); + + 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) + gpio->rising[gb] |= (1 << go); + if (type & IRQ_TYPE_EDGE_FALLING) + gpio->falling[gb] |= (1 << go); + if (type & IRQ_TYPE_LEVEL_HIGH) + gpio->high[gb] |= (1 << go); + if (type & IRQ_TYPE_LEVEL_LOW) + gpio->low[gb] |= (1 << go); + return 0; +} + +static void bcm2708_gpio_irq_mask(struct irq_data *d) +{ + unsigned irq = d->irq; + 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 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(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) +{ + unsigned irq = d->irq; + struct bcm2708_gpio *gpio = irq_get_chip_data(irq); + unsigned gn = irq_to_gpio(irq); + unsigned gb = gn / 32; + unsigned go = gn % 32; + 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)); + + if (gpio->rising[gb] & (1 << go)) { + writel(rising | (1 << go), gpio->base + GPIOREN(gb)); + } else { + writel(rising & ~(1 << go), gpio->base + GPIOREN(gb)); + } + + if (gpio->falling[gb] & (1 << go)) { + writel(falling | (1 << go), gpio->base + GPIOFEN(gb)); + } else { + writel(falling & ~(1 << go), gpio->base + GPIOFEN(gb)); + } + + if (gpio->high[gb] & (1 << go)) { + writel(high | (1 << go), gpio->base + GPIOHEN(gb)); + } else { + writel(high & ~(1 << go), gpio->base + GPIOHEN(gb)); + } + + if (gpio->low[gb] & (1 << go)) { + writel(low | (1 << go), gpio->base + GPIOLEN(gb)); + } else { + writel(low & ~(1 << go), gpio->base + GPIOLEN(gb)); + } +} + +static struct irq_chip bcm2708_irqchip = { + .name = "GPIO", + .irq_enable = bcm2708_gpio_irq_unmask, + .irq_disable = bcm2708_gpio_irq_mask, + .irq_unmask = bcm2708_gpio_irq_unmask, + .irq_mask = bcm2708_gpio_irq_mask, + .irq_set_type = bcm2708_gpio_irq_set_type, +}; + +static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id) +{ + unsigned long edsr; + unsigned bank; + int i; + unsigned gpio; + unsigned level_bits; + struct bcm2708_gpio *gpio_data = dev_id; + + for (bank = 0; bank < GPIO_BANKS; bank++) { + edsr = readl(__io_address(GPIO_BASE) + GPIOEDS(bank)); + level_bits = gpio_data->high[bank] | gpio_data->low[bank]; + + for_each_set_bit(i, &edsr, 32) { + gpio = i + bank * 32; + /* ack edge triggered IRQs immediately */ + if (!(level_bits & (1<gc.to_irq = bcm2708_gpio_to_irq; + + for (irq = GPIO_IRQ_START; irq < (GPIO_IRQ_START + GPIO_IRQS); irq++) { + irq_set_chip_data(irq, ucb); + irq_set_chip_and_handler(irq, &bcm2708_irqchip, + handle_simple_irq); + set_irq_flags(irq, IRQF_VALID); + } + + bcm2708_gpio_irq.dev_id = ucb; + setup_irq(IRQ_GPIO3, &bcm2708_gpio_irq); +} + +#else + +static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb) +{ +} + +#endif /* #if BCM_GPIO_USE_IRQ ***************************************************************************************************************** */ + +static int bcm2708_gpio_probe(struct platform_device *dev) +{ + struct bcm2708_gpio *ucb; + struct resource *res; + int bank; + int err = 0; + + printk(KERN_INFO DRIVER_NAME ": bcm2708_gpio_probe %p\n", dev); + + ucb = kzalloc(sizeof(*ucb), GFP_KERNEL); + if (NULL == ucb) { + printk(KERN_ERR DRIVER_NAME ": failed to allocate " + "mailbox memory\n"); + err = -ENOMEM; + goto err; + } + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + + platform_set_drvdata(dev, ucb); + ucb->base = __io_address(GPIO_BASE); + + ucb->gc.label = "bcm2708_gpio"; + ucb->gc.base = 0; + ucb->gc.ngpio = BCM2708_NR_GPIOS; + ucb->gc.owner = THIS_MODULE; + + ucb->gc.direction_input = bcm2708_gpio_dir_in; + ucb->gc.direction_output = bcm2708_gpio_dir_out; + ucb->gc.get = bcm2708_gpio_get; + ucb->gc.set = bcm2708_gpio_set; + ucb->gc.can_sleep = 0; + + for (bank = 0; bank < GPIO_BANKS; bank++) { + writel(0, ucb->base + GPIOREN(bank)); + writel(0, ucb->base + GPIOFEN(bank)); + writel(0, ucb->base + GPIOHEN(bank)); + writel(0, ucb->base + GPIOLEN(bank)); + writel(0, ucb->base + GPIOAREN(bank)); + writel(0, ucb->base + GPIOAFEN(bank)); + writel(~0, ucb->base + GPIOEDS(bank)); + } + + bcm2708_gpio_irq_init(ucb); + + err = gpiochip_add(&ucb->gc); + +err: + return err; + +} + +static int bcm2708_gpio_remove(struct platform_device *dev) +{ + int err = 0; + struct bcm2708_gpio *ucb = platform_get_drvdata(dev); + + printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_remove %p\n", dev); + + gpiochip_remove(&ucb->gc); + + platform_set_drvdata(dev, NULL); + kfree(ucb); + + return err; +} + +static struct platform_driver bcm2708_gpio_driver = { + .probe = bcm2708_gpio_probe, + .remove = bcm2708_gpio_remove, + .driver = { + .name = "bcm2708_gpio"}, +}; + +static int __init bcm2708_gpio_init(void) +{ + return platform_driver_register(&bcm2708_gpio_driver); +} + +static void __exit bcm2708_gpio_exit(void) +{ + platform_driver_unregister(&bcm2708_gpio_driver); +} + +module_init(bcm2708_gpio_init); +module_exit(bcm2708_gpio_exit); + +MODULE_DESCRIPTION("Broadcom BCM2708 GPIO driver"); +MODULE_LICENSE("GPL"); diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/bcm2709.c raspilinux/arch/arm/mach-bcm2709/bcm2709.c --- linux-stable/arch/arm/mach-bcm2709/bcm2709.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/bcm2709.c 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,1332 @@ +/* + * linux/arch/arm/mach-bcm2709/bcm2709.c + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "bcm2709.h" +#include "armctrl.h" + +#ifdef CONFIG_BCM_VC_CMA +#include +#endif + +//#define SYSTEM_TIMER + +/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to + * give us IO access only to 64Mbytes of physical memory (26 bits). We could + * represent this window by setting our dmamasks to 26 bits but, in fact + * we're not going to use addresses outside this range (they're not in real + * memory) so we don't bother. + * + * In the future we might include code to use this IOMMU to remap other + * physical addresses onto VideoCore memory then the use of 32-bits would be + * more legitimate. + */ +#define DMA_MASK_BITS_COMMON 32 + +// use GPIO 4 for the one-wire GPIO pin, if enabled +#define W1_GPIO 4 +// ensure one-wire GPIO pullup is disabled by default +#define W1_PULLUP -1 + +/* command line parameters */ +static unsigned boardrev, serial; +static unsigned uart_clock = UART0_CLOCK; +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 unsigned w1_gpio_pullup = W1_PULLUP; +static bool vc_i2c_override = false; +static int pps_gpio_pin = -1; +unsigned force_core; + +static unsigned use_dt = 0; + +static void __init bcm2709_init_led(void); + +void __init bcm2709_init_irq(void) +{ + armctrl_init(__io_address(ARMCTRL_IC_BASE), 0, 0, 0); +} + +static struct map_desc bcm2709_io_desc[] __initdata = { + { + .virtual = IO_ADDRESS(ARMCTRL_BASE), + .pfn = __phys_to_pfn(ARMCTRL_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(UART0_BASE), + .pfn = __phys_to_pfn(UART0_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(UART1_BASE), + .pfn = __phys_to_pfn(UART1_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(DMA_BASE), + .pfn = __phys_to_pfn(DMA_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(MCORE_BASE), + .pfn = __phys_to_pfn(MCORE_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(ST_BASE), + .pfn = __phys_to_pfn(ST_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(USB_BASE), + .pfn = __phys_to_pfn(USB_BASE), + .length = SZ_128K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(PM_BASE), + .pfn = __phys_to_pfn(PM_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(GPIO_BASE), + .pfn = __phys_to_pfn(GPIO_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(ARM_LOCAL_BASE), + .pfn = __phys_to_pfn(ARM_LOCAL_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, +}; + +void __init bcm2709_map_io(void) +{ + iotable_init(bcm2709_io_desc, ARRAY_SIZE(bcm2709_io_desc)); +} + +#ifdef SYSTEM_TIMER + +/* The STC is a free running counter that increments at the rate of 1MHz */ +#define STC_FREQ_HZ 1000000 + +static inline uint32_t timer_read(void) +{ + /* STC: a free running counter that increments at the rate of 1MHz */ + return readl(__io_address(ST_BASE + 0x04)); +} + +static unsigned long bcm2709_read_current_timer(void) +{ + return timer_read(); +} + +static u64 notrace bcm2709_read_sched_clock(void) +{ + return timer_read(); +} + +static cycle_t clksrc_read(struct clocksource *cs) +{ + return timer_read(); +} + +static struct clocksource clocksource_stc = { + .name = "stc", + .rating = 300, + .read = clksrc_read, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +unsigned long frc_clock_ticks32(void) +{ + return timer_read(); +} + +static void __init bcm2709_clocksource_init(void) +{ + if (clocksource_register_hz(&clocksource_stc, STC_FREQ_HZ)) { + printk(KERN_ERR "timer: failed to initialize clock " + "source %s\n", clocksource_stc.name); + } +} +#endif + +struct clk __init *bcm2709_clk_register(const char *name, unsigned long fixed_rate) +{ + struct clk *clk; + + clk = clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, + fixed_rate); + if (IS_ERR(clk)) + pr_err("%s not registered\n", name); + + return clk; +} + +void __init bcm2709_register_clkdev(struct clk *clk, const char *name) +{ + int ret; + + ret = clk_register_clkdev(clk, NULL, name); + if (ret) + pr_err("%s alias not registered\n", name); +} + +void __init bcm2709_init_clocks(void) +{ + struct clk *clk; + + clk = bcm2709_clk_register("uart0_clk", uart_clock); + bcm2709_register_clkdev(clk, "dev:f1"); + + clk = bcm2709_clk_register("sdhost_clk", 250000000); + bcm2709_register_clkdev(clk, "mmc-bcm2835.0"); + bcm2709_register_clkdev(clk, "bcm2708_spi.0"); + bcm2709_register_clkdev(clk, "bcm2708_i2c.0"); + bcm2709_register_clkdev(clk, "bcm2708_i2c.1"); +} + +#define UART0_IRQ { IRQ_UART, 0 /*NO_IRQ*/ } +#define UART0_DMA { 15, 14 } + +AMBA_DEVICE(uart0, "dev:f1", UART0, NULL); + +static struct amba_device *amba_devs[] __initdata = { + &uart0_device, +}; + +static struct resource bcm2708_dmaengine_resources[] = { + { + .start = DMA_BASE, + .end = DMA_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_DMA0, + .end = IRQ_DMA0, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA1, + .end = IRQ_DMA1, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA2, + .end = IRQ_DMA2, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA3, + .end = IRQ_DMA3, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA4, + .end = IRQ_DMA4, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA5, + .end = IRQ_DMA5, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA6, + .end = IRQ_DMA6, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA7, + .end = IRQ_DMA7, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA8, + .end = IRQ_DMA8, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA9, + .end = IRQ_DMA9, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA10, + .end = IRQ_DMA10, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA11, + .end = IRQ_DMA11, + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_DMA12, + .end = IRQ_DMA12, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device bcm2708_dmaengine_device = { + .name = "bcm2708-dmaengine", + .id = -1, + .resource = bcm2708_dmaengine_resources, + .num_resources = ARRAY_SIZE(bcm2708_dmaengine_resources), +}; + +#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) +static struct w1_gpio_platform_data w1_gpio_pdata = { + .pin = W1_GPIO, + .ext_pullup_enable_pin = W1_PULLUP, + .is_open_drain = 0, +}; + +static struct platform_device w1_device = { + .name = "w1-gpio", + .id = -1, + .dev.platform_data = &w1_gpio_pdata, +}; +#endif + +static struct pps_gpio_platform_data pps_gpio_info = { + .assert_falling_edge = false, + .capture_clear = false, + .gpio_pin = -1, + .gpio_label = "PPS", +}; + +static struct platform_device pps_gpio_device = { + .name = "pps-gpio", + .id = PLATFORM_DEVID_NONE, + .dev.platform_data = &pps_gpio_info, +}; + +static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_fb_device = { + .name = "bcm2708_fb", + .id = -1, /* only one bcm2708_fb */ + .resource = NULL, + .num_resources = 0, + .dev = { + .dma_mask = &fb_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + +static struct resource bcm2708_usb_resources[] = { + [0] = { + .start = USB_BASE, + .end = USB_BASE + SZ_128K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MPHI_BASE, + .end = MPHI_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = IRQ_HOSTPORT, + .end = IRQ_HOSTPORT, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = IRQ_USB, + .end = IRQ_USB, + .flags = IORESOURCE_IRQ, + }, + [4] = { + .start = ARM_LOCAL_BASE, + .end = ARM_LOCAL_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [5] = { + .start = IRQ_ARM_LOCAL_MAILBOX1, + .end = IRQ_ARM_LOCAL_MAILBOX1, + .flags = IORESOURCE_IRQ + }, +}; + + +static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_usb_device = { + .name = "bcm2708_usb", + .id = -1, /* only one bcm2708_usb */ + .resource = bcm2708_usb_resources, + .num_resources = ARRAY_SIZE(bcm2708_usb_resources), + .dev = { + .dma_mask = &usb_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + +static struct resource bcm2708_vcio_resources[] = { + { + .start = ARMCTRL_0_MAIL0_BASE, + .end = ARMCTRL_0_MAIL0_BASE + SZ_64 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_ARM_MAILBOX, + .end = IRQ_ARM_MAILBOX, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_vcio_device = { + .name = "bcm2835-mbox", + .id = -1, /* only one VideoCore I/O area */ + .resource = bcm2708_vcio_resources, + .num_resources = ARRAY_SIZE(bcm2708_vcio_resources), + .dev = { + .dma_mask = &vcio_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + +static u64 rpifw_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_rpifw_device = { + .name = "raspberrypi-firmware", + .dev = { + .dma_mask = &rpifw_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + +static struct resource bcm2708_vchiq_resources[] = { + { + .start = ARMCTRL_0_BELL_BASE, + .end = ARMCTRL_0_BELL_BASE + 16, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_ARM_DOORBELL_0, + .end = IRQ_ARM_DOORBELL_0, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 vchiq_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_vchiq_device = { + .name = "bcm2835_vchiq", + .id = -1, + .resource = bcm2708_vchiq_resources, + .num_resources = ARRAY_SIZE(bcm2708_vchiq_resources), + .dev = { + .dma_mask = &vchiq_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + +#ifdef CONFIG_BCM2708_GPIO +#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" + +static struct resource bcm2708_gpio_resources[] = { + [0] = { /* general purpose I/O */ + .start = GPIO_BASE, + .end = GPIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_gpio_device = { + .name = BCM_GPIO_DRIVER_NAME, + .id = -1, /* only one VideoCore I/O area */ + .resource = bcm2708_gpio_resources, + .num_resources = ARRAY_SIZE(bcm2708_gpio_resources), + .dev = { + .dma_mask = &gpio_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; +#endif + +#ifdef CONFIG_MMC_BCM2835 /* Arasan emmc SD (new) */ +static struct resource bcm2835_emmc_resources[] = { + [0] = { + .start = EMMC_BASE, + .end = EMMC_BASE + SZ_256 - 1, /* we only need this area */ + /* the memory map actually makes SZ_4K available */ + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_ARASANSDIO, + .end = IRQ_ARASANSDIO, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 bcm2835_emmc_dmamask = 0xffffffffUL; + +struct platform_device bcm2835_emmc_device = { + .name = "mmc-bcm2835", + .id = 0, + .num_resources = ARRAY_SIZE(bcm2835_emmc_resources), + .resource = bcm2835_emmc_resources, + .dev = { + .dma_mask = &bcm2835_emmc_dmamask, + .coherent_dma_mask = 0xffffffffUL}, +}; +#endif /* CONFIG_MMC_BCM2835 */ + +static struct platform_device bcm2708_alsa_devices[] = { + [0] = { + .name = "bcm2835_AUD0", + .id = 0, /* first audio device */ + .resource = 0, + .num_resources = 0, + }, + [1] = { + .name = "bcm2835_AUD1", + .id = 1, /* second audio device */ + .resource = 0, + .num_resources = 0, + }, + [2] = { + .name = "bcm2835_AUD2", + .id = 2, /* third audio device */ + .resource = 0, + .num_resources = 0, + }, + [3] = { + .name = "bcm2835_AUD3", + .id = 3, /* forth audio device */ + .resource = 0, + .num_resources = 0, + }, + [4] = { + .name = "bcm2835_AUD4", + .id = 4, /* fifth audio device */ + .resource = 0, + .num_resources = 0, + }, + [5] = { + .name = "bcm2835_AUD5", + .id = 5, /* sixth audio device */ + .resource = 0, + .num_resources = 0, + }, + [6] = { + .name = "bcm2835_AUD6", + .id = 6, /* seventh audio device */ + .resource = 0, + .num_resources = 0, + }, + [7] = { + .name = "bcm2835_AUD7", + .id = 7, /* eighth audio device */ + .resource = 0, + .num_resources = 0, + }, +}; + +static struct resource bcm2708_spi_resources[] = { + { + .start = SPI0_BASE, + .end = SPI0_BASE + SZ_256 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_SPI, + .end = IRQ_SPI, + .flags = IORESOURCE_IRQ, + } +}; + + +static u64 bcm2708_spi_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); +static struct platform_device bcm2708_spi_device = { + .name = "bcm2708_spi", + .id = 0, + .num_resources = ARRAY_SIZE(bcm2708_spi_resources), + .resource = bcm2708_spi_resources, + .dev = { + .dma_mask = &bcm2708_spi_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON)}, +}; + +#ifdef CONFIG_BCM2708_SPIDEV +static struct spi_board_info bcm2708_spi_devices[] = { +#ifdef CONFIG_SPI_SPIDEV + { + .modalias = "spidev", + .max_speed_hz = 500000, + .bus_num = 0, + .chip_select = 0, + .mode = SPI_MODE_0, + }, { + .modalias = "spidev", + .max_speed_hz = 500000, + .bus_num = 0, + .chip_select = 1, + .mode = SPI_MODE_0, + } +#endif +}; +#endif + +static struct resource bcm2708_bsc0_resources[] = { + { + .start = BSC0_BASE, + .end = BSC0_BASE + SZ_256 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = INTERRUPT_I2C, + .end = INTERRUPT_I2C, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device bcm2708_bsc0_device = { + .name = "bcm2708_i2c", + .id = 0, + .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources), + .resource = bcm2708_bsc0_resources, +}; + + +static struct resource bcm2708_bsc1_resources[] = { + { + .start = BSC1_BASE, + .end = BSC1_BASE + SZ_256 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = INTERRUPT_I2C, + .end = INTERRUPT_I2C, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device bcm2708_bsc1_device = { + .name = "bcm2708_i2c", + .id = 1, + .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources), + .resource = bcm2708_bsc1_resources, +}; + +static struct platform_device bcm2835_thermal_device = { + .name = "bcm2835_thermal", +}; + +#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) +static struct resource bcm2708_i2s_resources[] = { + { + .start = I2S_BASE, + .end = I2S_BASE + 0x20, + .flags = IORESOURCE_MEM, + }, + { + .start = PCM_CLOCK_BASE, + .end = PCM_CLOCK_BASE + 0x02, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device bcm2708_i2s_device = { + .name = "bcm2708-i2s", + .id = 0, + .num_resources = ARRAY_SIZE(bcm2708_i2s_resources), + .resource = bcm2708_i2s_resources, +}; +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) +static struct platform_device snd_hifiberry_dac_device = { + .name = "snd-hifiberry-dac", + .id = 0, + .num_resources = 0, +}; + +static struct platform_device snd_pcm5102a_codec_device = { + .name = "pcm5102a-codec", + .id = -1, + .num_resources = 0, +}; +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) +static struct platform_device snd_rpi_hifiberry_dacplus_device = { + .name = "snd-rpi-hifiberry-dacplus", + .id = 0, + .num_resources = 0, +}; + +static struct i2c_board_info __initdata snd_pcm512x_hbdacplus_i2c_devices[] = { + { + I2C_BOARD_INFO("pcm5122", 0x4d) + }, +}; +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) +static struct platform_device snd_hifiberry_digi_device = { + .name = "snd-hifiberry-digi", + .id = 0, + .num_resources = 0, +}; + +static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { + { + I2C_BOARD_INFO("wm8804", 0x3b) + }, +}; + +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) +static struct platform_device snd_hifiberry_amp_device = { + .name = "snd-hifiberry-amp", + .id = 0, + .num_resources = 0, +}; + +static struct i2c_board_info __initdata snd_tas5713_i2c_devices[] = { + { + I2C_BOARD_INFO("tas5713", 0x1b) + }, +}; +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) +static struct platform_device snd_rpi_dac_device = { + .name = "snd-rpi-dac", + .id = 0, + .num_resources = 0, +}; + +static struct platform_device snd_pcm1794a_codec_device = { + .name = "pcm1794a-codec", + .id = -1, + .num_resources = 0, +}; +#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; + + ret = platform_device_register(pdev); + if (ret) + pr_debug("Unable to register platform device '%s': %d\n", + pdev->name, ret); + + return ret; +} + +/* + * Use these macros for platform and i2c devices that are present in the + * Device Tree. This way the devices are only added on non-DT systems. + */ +#define bcm_register_device_dt(pdev) \ + if (!use_dt) bcm_register_device(pdev) + +#define i2c_register_board_info_dt(busnum, info, n) \ + if (!use_dt) i2c_register_board_info(busnum, info, n) + +int calc_rsts(int partition) +{ + return PM_PASSWORD | + ((partition & (1 << 0)) << 0) | + ((partition & (1 << 1)) << 1) | + ((partition & (1 << 2)) << 2) | + ((partition & (1 << 3)) << 3) | + ((partition & (1 << 4)) << 4) | + ((partition & (1 << 5)) << 5); +} + +static void bcm2709_restart(enum reboot_mode mode, const char *cmd) +{ + extern char bcm2708_reboot_mode; + uint32_t pm_rstc, pm_wdog; + uint32_t timeout = 10; + uint32_t pm_rsts = 0; + + if(bcm2708_reboot_mode == 'q') + { + // NOOBS < 1.3 booting with reboot=q + pm_rsts = readl(__io_address(PM_RSTS)); + pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRQ_SET; + } + else if(bcm2708_reboot_mode == 'p') + { + // NOOBS < 1.3 halting + pm_rsts = readl(__io_address(PM_RSTS)); + pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRH_SET; + } + else + { + pm_rsts = calc_rsts(reboot_part); + } + + writel(pm_rsts, __io_address(PM_RSTS)); + + /* Setup watchdog for reset */ + pm_rstc = readl(__io_address(PM_RSTC)); + + pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) + pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; + + writel(pm_wdog, __io_address(PM_WDOG)); + writel(pm_rstc, __io_address(PM_RSTC)); +} + +/* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */ +static void bcm2709_power_off(void) +{ + extern char bcm2708_reboot_mode; + if(bcm2708_reboot_mode == 'q') + { + // NOOBS < v1.3 + bcm2709_restart('p', ""); + } + else + { + /* partition 63 is special code for HALT the bootloader knows not to boot*/ + reboot_part = 63; + /* continue with normal reset mechanism */ + bcm2709_restart(0, ""); + } +} + +static void __init bcm2709_init_uart1(void) +{ + struct device_node *np; + + np = of_find_compatible_node(NULL, NULL, "brcm,bcm2835-aux-uart"); + if (of_device_is_available(np)) { + pr_info("bcm2709: Mini UART enabled\n"); + writel(1, __io_address(UART1_BASE + 0x4)); + } +} + +#ifdef CONFIG_OF +static void __init bcm2709_dt_init(void) +{ + int ret; + + of_clk_init(NULL); + ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + if (ret) { + pr_err("of_platform_populate failed: %d\n", ret); + /* Proceed as if CONFIG_OF was not defined */ + } else { + use_dt = 1; + } +} +#else +static void __init bcm2709_dt_init(void) { } +#endif /* CONFIG_OF */ + +void __init bcm2709_init(void) +{ + int i; + +#if defined(CONFIG_BCM_VC_CMA) + vc_cma_early_init(); +#endif + printk("bcm2709.uart_clock = %d\n", uart_clock); + pm_power_off = bcm2709_power_off; + + bcm2709_init_clocks(); + bcm2709_dt_init(); + + bcm_register_device_dt(&bcm2708_dmaengine_device); + bcm_register_device_dt(&bcm2708_vcio_device); + bcm_register_device_dt(&bcm2708_rpifw_device); + bcm_register_device_dt(&bcm2708_vchiq_device); +#ifdef CONFIG_BCM2708_GPIO + bcm_register_device_dt(&bcm2708_gpio_device); +#endif + +#if defined(CONFIG_PPS_CLIENT_GPIO) || defined(CONFIG_PPS_CLIENT_GPIO_MODULE) + if (!use_dt && (pps_gpio_pin >= 0)) { + pr_info("bcm2709: GPIO %d setup as pps-gpio device\n", pps_gpio_pin); + pps_gpio_info.gpio_pin = pps_gpio_pin; + pps_gpio_device.id = pps_gpio_pin; + bcm_register_device(&pps_gpio_device); + } +#endif + +#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) + w1_gpio_pdata.pin = w1_gpio_pin; + w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup; + bcm_register_device_dt(&w1_device); +#endif + bcm_register_device_dt(&bcm2708_fb_device); + bcm_register_device_dt(&bcm2708_usb_device); + +#ifdef CONFIG_MMC_BCM2835 + bcm_register_device_dt(&bcm2835_emmc_device); +#endif + bcm2709_init_led(); + bcm2709_init_uart1(); + + /* Only create the platform devices for the ALSA driver in the + absence of an enabled "audio" DT node */ + if (!use_dt || + !of_device_is_available(of_find_node_by_path("/audio"))) { + for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++) + bcm_register_device(&bcm2708_alsa_devices[i]); + } + + bcm_register_device_dt(&bcm2708_spi_device); + + if (vc_i2c_override) { + bcm_register_device_dt(&bcm2708_bsc0_device); + bcm_register_device_dt(&bcm2708_bsc1_device); + } else if ((boardrev & 0xffffff) == 0x2 || (boardrev & 0xffffff) == 0x3) { + bcm_register_device_dt(&bcm2708_bsc0_device); + } else { + bcm_register_device_dt(&bcm2708_bsc1_device); + } + + bcm_register_device_dt(&bcm2835_thermal_device); + +#if defined(CONFIG_SND_BCM2708_SOC_I2S) || defined(CONFIG_SND_BCM2708_SOC_I2S_MODULE) + bcm_register_device_dt(&bcm2708_i2s_device); +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) + bcm_register_device_dt(&snd_hifiberry_dac_device); + bcm_register_device_dt(&snd_pcm5102a_codec_device); +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS_MODULE) + bcm_register_device_dt(&snd_rpi_hifiberry_dacplus_device); + i2c_register_board_info_dt(1, snd_pcm512x_hbdacplus_i2c_devices, ARRAY_SIZE(snd_pcm512x_hbdacplus_i2c_devices)); +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) + bcm_register_device_dt(&snd_hifiberry_digi_device); + i2c_register_board_info_dt(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP_MODULE) + bcm_register_device_dt(&snd_hifiberry_amp_device); + i2c_register_board_info_dt(1, snd_tas5713_i2c_devices, ARRAY_SIZE(snd_tas5713_i2c_devices)); +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) + bcm_register_device_dt(&snd_rpi_dac_device); + bcm_register_device_dt(&snd_pcm1794a_codec_device); +#endif + +#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE) + bcm_register_device_dt(&snd_rpi_iqaudio_dac_device); + i2c_register_board_info_dt(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices)); +#endif + + if (!use_dt) { + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; + amba_device_register(d, &iomem_resource); + } + } + system_rev = boardrev; + system_serial_low = serial; + +#ifdef CONFIG_BCM2708_SPIDEV + if (!use_dt) + spi_register_board_info(bcm2708_spi_devices, + ARRAY_SIZE(bcm2708_spi_devices)); +#endif +} + +#ifdef SYSTEM_TIMER +static void timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: /* Leave the timer disabled, .set_next_event will enable it */ + case CLOCK_EVT_MODE_SHUTDOWN: + break; + case CLOCK_EVT_MODE_PERIODIC: + + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_RESUME: + + default: + printk(KERN_ERR "timer_set_mode: unhandled mode:%d\n", + (int)mode); + break; + } + +} + +static int timer_set_next_event(unsigned long cycles, + struct clock_event_device *unused) +{ + unsigned long stc; + do { + stc = readl(__io_address(ST_BASE + 0x04)); + /* We could take a FIQ here, which may push ST above STC3 */ + writel(stc + cycles, __io_address(ST_BASE + 0x18)); + } while ((signed long) cycles >= 0 && + (signed long) (readl(__io_address(ST_BASE + 0x04)) - stc) + >= (signed long) cycles); + return 0; +} + +static struct clock_event_device timer0_clockevent = { + .name = "timer0", + .shift = 32, + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_mode = timer_set_mode, + .set_next_event = timer_set_next_event, +}; + +/* + * IRQ handler for the timer + */ +static irqreturn_t bcm2709_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = &timer0_clockevent; + + writel(1 << 3, __io_address(ST_BASE + 0x00)); /* stcs clear timer int */ + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction bcm2709_timer_irq = { + .name = "BCM2709 Timer Tick", + .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2709_timer_interrupt, +}; + +/* + * Set up timer interrupt, and return the current time in seconds. + */ + +static struct delay_timer bcm2709_delay_timer = { + .read_current_timer = bcm2709_read_current_timer, + .freq = STC_FREQ_HZ, +}; + +static void __init bcm2709_timer_init(void) +{ + /* init high res timer */ + bcm2709_clocksource_init(); + + /* + * Make irqs happen for the system timer + */ + setup_irq(IRQ_TIMER3, &bcm2709_timer_irq); + + sched_clock_register(bcm2709_read_sched_clock, 32, STC_FREQ_HZ); + + timer0_clockevent.mult = + div_sc(STC_FREQ_HZ, NSEC_PER_SEC, timer0_clockevent.shift); + timer0_clockevent.max_delta_ns = + clockevent_delta2ns(0xffffffff, &timer0_clockevent); + timer0_clockevent.min_delta_ns = + clockevent_delta2ns(0xf, &timer0_clockevent); + + timer0_clockevent.cpumask = cpumask_of(0); + clockevents_register_device(&timer0_clockevent); + + register_current_timer_delay(&bcm2709_delay_timer); +} + +#else + +static void __init bcm2709_timer_init(void) +{ + extern void dc4_arch_timer_init(void); + // timer control + writel(0, __io_address(ARM_LOCAL_CONTROL)); + // timer pre_scaler + writel(0x80000000, __io_address(ARM_LOCAL_PRESCALER)); // 19.2MHz + //writel(0x06AAAAAB, __io_address(ARM_LOCAL_PRESCALER)); // 1MHz + + if (use_dt) + { + of_clk_init(NULL); + clocksource_of_init(); + } + else + dc4_arch_timer_init(); +} + +#endif + +#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) +#include + +static struct gpio_led bcm2709_leds[] = { + [0] = { + .gpio = 16, + .name = "led0", + .default_trigger = "mmc0", + .active_low = 1, + }, +}; + +static struct gpio_led_platform_data bcm2709_led_pdata = { + .num_leds = ARRAY_SIZE(bcm2709_leds), + .leds = bcm2709_leds, +}; + +static struct platform_device bcm2709_led_device = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &bcm2709_led_pdata, + }, +}; + +static void __init bcm2709_init_led(void) +{ + bcm2709_leds[0].gpio = disk_led_gpio; + bcm2709_leds[0].active_low = disk_led_active_low; + bcm_register_device_dt(&bcm2709_led_device); +} +#else +static inline void bcm2709_init_led(void) +{ +} +#endif + +void __init bcm2709_init_early(void) +{ + /* + * Some devices allocate their coherent buffers from atomic + * context. Increase size of atomic coherent pool to make sure such + * the allocations won't fail. + */ + init_dma_coherent_pool_size(SZ_4M); +} + +static void __init board_reserve(void) +{ +#if defined(CONFIG_BCM_VC_CMA) + vc_cma_reserve(); +#endif +} + + +#ifdef CONFIG_SMP +#include + +#include +#include +#include +int dc4=0; +//void dc4_log(unsigned x) { if (dc4) writel((x), __io_address(ST_BASE+10 + raw_smp_processor_id()*4)); } +void dc4_log_dead(unsigned x) { if (dc4) writel((readl(__io_address(ST_BASE+0x10 + raw_smp_processor_id()*4)) & 0xffff) | ((x)<<16), __io_address(ST_BASE+0x10 + raw_smp_processor_id()*4)); } + +static void bcm2835_send_doorbell(const struct cpumask *mask, unsigned int irq) +{ + int cpu; + /* + * Ensure that stores to Normal memory are visible to the + * other CPUs before issuing the IPI. + */ + dsb(); + + /* Convert our logical CPU mask into a physical one. */ + for_each_cpu(cpu, mask) + { + /* submit softirq */ + writel(1<%x)\n", __FUNCTION__, (unsigned)virt_to_phys((void *)secondary_startup), (unsigned)__io_address(ST_BASE + 0x10)); + printk("[%s] ncores=%d\n", __FUNCTION__, ncores); + + for (i = 0; i < ncores; i++) { + set_cpu_possible(i, true); + /* enable IRQ (not FIQ) */ + writel(0x1, __io_address(ARM_LOCAL_MAILBOX_INT_CONTROL0 + 0x4 * i)); + //writel(0xf, __io_address(ARM_LOCAL_TIMER_INT_CONTROL0 + 0x4 * i)); + } + set_smp_cross_call(bcm2835_send_doorbell); +} + +/* + * for arch/arm/kernel/smp.c:smp_prepare_cpus(unsigned int max_cpus) + */ +void __init bcm2709_smp_prepare_cpus(unsigned int max_cpus) +{ + //void __iomem *scu_base; + + printk("[%s] enter\n", __FUNCTION__); + //scu_base = scu_base_addr(); + //scu_enable(scu_base); +} + +/* + * for linux/arch/arm/kernel/smp.c:secondary_start_kernel(void) + */ +void __cpuinit bcm2709_secondary_init(unsigned int cpu) +{ + printk("[%s] enter cpu:%d\n", __FUNCTION__, cpu); + //gic_secondary_init(0); +} + +/* + * for linux/arch/arm/kernel/smp.c:__cpu_up(..) + */ +int __cpuinit bcm2709_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + void secondary_startup(void); + void *mbox_set = __io_address(ARM_LOCAL_MAILBOX3_SET0 + 0x10 * MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0)); + void *mbox_clr = __io_address(ARM_LOCAL_MAILBOX3_CLR0 + 0x10 * MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0)); + unsigned secondary_boot = (unsigned)virt_to_phys((void *)secondary_startup); + int timeout=20; + unsigned t = -1; + //printk("[%s] enter cpu:%d (%x->%p) %x\n", __FUNCTION__, cpu, secondary_boot, wake, readl(wake)); + + dsb(); + BUG_ON(readl(mbox_clr) != 0); + writel(secondary_boot, mbox_set); + + while (--timeout > 0) { + t = readl(mbox_clr); + if (t == 0) break; + cpu_relax(); + } + if (timeout==0) + printk("[%s] cpu:%d failed to start (%x)\n", __FUNCTION__, cpu, t); + else + printk("[%s] cpu:%d started (%x) %d\n", __FUNCTION__, cpu, t, timeout); + + return 0; +} + + +struct smp_operations bcm2709_smp_ops __initdata = { + .smp_init_cpus = bcm2709_smp_init_cpus, + .smp_prepare_cpus = bcm2709_smp_prepare_cpus, + .smp_secondary_init = bcm2709_secondary_init, + .smp_boot_secondary = bcm2709_boot_secondary, +}; +#endif + +static const char * const bcm2709_compat[] = { + "brcm,bcm2709", + "brcm,bcm2708", /* Could use bcm2708 in a pinch */ + NULL +}; + +MACHINE_START(BCM2709, "BCM2709") + /* Maintainer: Broadcom Europe Ltd. */ +#ifdef CONFIG_SMP + .smp = smp_ops(bcm2709_smp_ops), +#endif + .map_io = bcm2709_map_io, + .init_irq = bcm2709_init_irq, + .init_time = bcm2709_timer_init, + .init_machine = bcm2709_init, + .init_early = bcm2709_init_early, + .reserve = board_reserve, + .restart = bcm2709_restart, + .dt_compat = bcm2709_compat, +MACHINE_END + +MACHINE_START(BCM2708, "BCM2709") + /* Maintainer: Broadcom Europe Ltd. */ +#ifdef CONFIG_SMP + .smp = smp_ops(bcm2709_smp_ops), +#endif + .map_io = bcm2709_map_io, + .init_irq = bcm2709_init_irq, + .init_time = bcm2709_timer_init, + .init_machine = bcm2709_init, + .init_early = bcm2709_init_early, + .reserve = board_reserve, + .restart = bcm2709_restart, + .dt_compat = bcm2709_compat, +MACHINE_END + +module_param(force_core, uint, 0644); +module_param(boardrev, uint, 0644); +module_param(serial, uint, 0644); +module_param(uart_clock, uint, 0644); +module_param(disk_led_gpio, uint, 0644); +module_param(disk_led_active_low, uint, 0644); +module_param(reboot_part, uint, 0644); +module_param(w1_gpio_pin, uint, 0644); +module_param(w1_gpio_pullup, uint, 0644); +module_param(vc_i2c_override, bool, 0644); +MODULE_PARM_DESC(vc_i2c_override, "Allow the use of VC's I2C peripheral."); +module_param(pps_gpio_pin, int, 0644); +MODULE_PARM_DESC(pps_gpio_pin, "Set GPIO pin to reserve for PPS"); diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/bcm2709.h raspilinux/arch/arm/mach-bcm2709/bcm2709.h --- linux-stable/arch/arm/mach-bcm2709/bcm2709.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/bcm2709.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,49 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708.h + * + * BCM2708 machine support header + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BCM2708_BCM2708_H +#define __BCM2708_BCM2708_H + +#include + +extern void __init bcm2708_init(void); +extern void __init bcm2708_init_irq(void); +extern void __init bcm2708_map_io(void); +extern struct sys_timer bcm2708_timer; +extern unsigned int mmc_status(struct device *dev); + +#define AMBA_DEVICE(name, busid, base, plat) \ +static struct amba_device name##_device = { \ + .dev = { \ + .coherent_dma_mask = ~0, \ + .init_name = busid, \ + .platform_data = plat, \ + }, \ + .res = { \ + .start = base##_BASE, \ + .end = (base##_BASE) + SZ_4K - 1,\ + .flags = IORESOURCE_MEM, \ + }, \ + .irq = base##_IRQ, \ +} + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/delay.S raspilinux/arch/arm/mach-bcm2709/delay.S --- linux-stable/arch/arm/mach-bcm2709/delay.S 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/delay.S 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,21 @@ +/* + * linux/arch/arm/lib/delay.S + * + * Copyright (C) 1995, 1996 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + + .text +.align 3 @ 8 byte alignment seems to be needed to avoid fetching stalls +@ Delay routine +ENTRY(bcm2708_delay) + subs r0, r0, #1 + bhi bcm2708_delay + mov pc, lr +ENDPROC(bcm2708_delay) diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/arm_control.h raspilinux/arch/arm/mach-bcm2709/include/mach/arm_control.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/arm_control.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/arm_control.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,493 @@ +/* + * linux/arch/arm/mach-bcm2708/arm_control.h + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BCM2708_ARM_CONTROL_H +#define __BCM2708_ARM_CONTROL_H + +/* + * Definitions and addresses for the ARM CONTROL logic + * This file is manually generated. + */ + +#define ARM_BASE 0x7E00B000 + +/* Basic configuration */ +#define ARM_CONTROL0 HW_REGISTER_RW(ARM_BASE+0x000) +#define ARM_C0_SIZ128M 0x00000000 +#define ARM_C0_SIZ256M 0x00000001 +#define ARM_C0_SIZ512M 0x00000002 +#define ARM_C0_SIZ1G 0x00000003 +#define ARM_C0_BRESP0 0x00000000 +#define ARM_C0_BRESP1 0x00000004 +#define ARM_C0_BRESP2 0x00000008 +#define ARM_C0_BOOTHI 0x00000010 +#define ARM_C0_UNUSED05 0x00000020 /* free */ +#define ARM_C0_FULLPERI 0x00000040 +#define ARM_C0_UNUSED78 0x00000180 /* free */ +#define ARM_C0_JTAGMASK 0x00000E00 +#define ARM_C0_JTAGOFF 0x00000000 +#define ARM_C0_JTAGBASH 0x00000800 /* Debug on GPIO off */ +#define ARM_C0_JTAGGPIO 0x00000C00 /* Debug on GPIO on */ +#define ARM_C0_APROTMSK 0x0000F000 +#define ARM_C0_DBG0SYNC 0x00010000 /* VPU0 halt sync */ +#define ARM_C0_DBG1SYNC 0x00020000 /* VPU1 halt sync */ +#define ARM_C0_SWDBGREQ 0x00040000 /* HW debug request */ +#define ARM_C0_PASSHALT 0x00080000 /* ARM halt passed to debugger */ +#define ARM_C0_PRIO_PER 0x00F00000 /* per priority mask */ +#define ARM_C0_PRIO_L2 0x0F000000 +#define ARM_C0_PRIO_UC 0xF0000000 + +#define ARM_C0_APROTPASS 0x0000A000 /* Translate 1:1 */ +#define ARM_C0_APROTUSER 0x00000000 /* Only user mode */ +#define ARM_C0_APROTSYST 0x0000F000 /* Only system mode */ + + +#define ARM_CONTROL1 HW_REGISTER_RW(ARM_BASE+0x440) +#define ARM_C1_TIMER 0x00000001 /* re-route timer IRQ to VC */ +#define ARM_C1_MAIL 0x00000002 /* re-route Mail IRQ to VC */ +#define ARM_C1_BELL0 0x00000004 /* re-route Doorbell 0 to VC */ +#define ARM_C1_BELL1 0x00000008 /* re-route Doorbell 1 to VC */ +#define ARM_C1_PERSON 0x00000100 /* peripherals on */ +#define ARM_C1_REQSTOP 0x00000200 /* ASYNC bridge request stop */ + +#define ARM_STATUS HW_REGISTER_RW(ARM_BASE+0x444) +#define ARM_S_ACKSTOP 0x80000000 /* Bridge stopped */ +#define ARM_S_READPEND 0x000003FF /* pending reads counter */ +#define ARM_S_WRITPEND 0x000FFC00 /* pending writes counter */ + +#define ARM_ERRHALT HW_REGISTER_RW(ARM_BASE+0x448) +#define ARM_EH_PERIBURST 0x00000001 /* Burst write seen on peri bus */ +#define ARM_EH_ILLADDRS1 0x00000002 /* Address bits 25-27 error */ +#define ARM_EH_ILLADDRS2 0x00000004 /* Address bits 31-28 error */ +#define ARM_EH_VPU0HALT 0x00000008 /* VPU0 halted & in debug mode */ +#define ARM_EH_VPU1HALT 0x00000010 /* VPU1 halted & in debug mode */ +#define ARM_EH_ARMHALT 0x00000020 /* ARM in halted debug mode */ + +#define ARM_ID_SECURE HW_REGISTER_RW(ARM_BASE+0x00C) +#define ARM_ID HW_REGISTER_RW(ARM_BASE+0x44C) +#define ARM_IDVAL 0x364D5241 + +/* Translation memory */ +#define ARM_TRANSLATE HW_REGISTER_RW(ARM_BASE+0x100) +/* 32 locations: 0x100.. 0x17F */ +/* 32 spare means we CAN go to 64 pages.... */ + + +/* Interrupts */ +#define ARM_IRQ_PEND0 HW_REGISTER_RW(ARM_BASE+0x200) /* Top IRQ bits */ +#define ARM_I0_TIMER 0x00000001 /* timer IRQ */ +#define ARM_I0_MAIL 0x00000002 /* Mail IRQ */ +#define ARM_I0_BELL0 0x00000004 /* Doorbell 0 */ +#define ARM_I0_BELL1 0x00000008 /* Doorbell 1 */ +#define ARM_I0_BANK1 0x00000100 /* Bank1 IRQ */ +#define ARM_I0_BANK2 0x00000200 /* Bank2 IRQ */ + +#define ARM_IRQ_PEND1 HW_REGISTER_RW(ARM_BASE+0x204) /* All bank1 IRQ bits */ +/* todo: all I1_interrupt sources */ +#define ARM_IRQ_PEND2 HW_REGISTER_RW(ARM_BASE+0x208) /* All bank2 IRQ bits */ +/* todo: all I2_interrupt sources */ + +#define ARM_IRQ_FAST HW_REGISTER_RW(ARM_BASE+0x20C) /* FIQ control */ +#define ARM_IF_INDEX 0x0000007F /* FIQ select */ +#define ARM_IF_ENABLE 0x00000080 /* FIQ enable */ +#define ARM_IF_VCMASK 0x0000003F /* FIQ = (index from VC source) */ +#define ARM_IF_TIMER 0x00000040 /* FIQ = ARM timer */ +#define ARM_IF_MAIL 0x00000041 /* FIQ = ARM Mail */ +#define ARM_IF_BELL0 0x00000042 /* FIQ = ARM Doorbell 0 */ +#define ARM_IF_BELL1 0x00000043 /* FIQ = ARM Doorbell 1 */ +#define ARM_IF_VP0HALT 0x00000044 /* FIQ = VPU0 Halt seen */ +#define ARM_IF_VP1HALT 0x00000045 /* FIQ = VPU1 Halt seen */ +#define ARM_IF_ILLEGAL 0x00000046 /* FIQ = Illegal access seen */ + +#define ARM_IRQ_ENBL1 HW_REGISTER_RW(ARM_BASE+0x210) /* Bank1 enable bits */ +#define ARM_IRQ_ENBL2 HW_REGISTER_RW(ARM_BASE+0x214) /* Bank2 enable bits */ +#define ARM_IRQ_ENBL3 HW_REGISTER_RW(ARM_BASE+0x218) /* ARM irqs enable bits */ +#define ARM_IRQ_DIBL1 HW_REGISTER_RW(ARM_BASE+0x21C) /* Bank1 disable bits */ +#define ARM_IRQ_DIBL2 HW_REGISTER_RW(ARM_BASE+0x220) /* Bank2 disable bits */ +#define ARM_IRQ_DIBL3 HW_REGISTER_RW(ARM_BASE+0x224) /* ARM irqs disable bits */ +#define ARM_IE_TIMER 0x00000001 /* Timer IRQ */ +#define ARM_IE_MAIL 0x00000002 /* Mail IRQ */ +#define ARM_IE_BELL0 0x00000004 /* Doorbell 0 */ +#define ARM_IE_BELL1 0x00000008 /* Doorbell 1 */ +#define ARM_IE_VP0HALT 0x00000010 /* VPU0 Halt */ +#define ARM_IE_VP1HALT 0x00000020 /* VPU1 Halt */ +#define ARM_IE_ILLEGAL 0x00000040 /* Illegal access seen */ + +/* Timer */ +/* For reg. fields see sp804 spec. */ +#define ARM_T_LOAD HW_REGISTER_RW(ARM_BASE+0x400) +#define ARM_T_VALUE HW_REGISTER_RW(ARM_BASE+0x404) +#define ARM_T_CONTROL HW_REGISTER_RW(ARM_BASE+0x408) +#define ARM_T_IRQCNTL HW_REGISTER_RW(ARM_BASE+0x40C) +#define ARM_T_RAWIRQ HW_REGISTER_RW(ARM_BASE+0x410) +#define ARM_T_MSKIRQ HW_REGISTER_RW(ARM_BASE+0x414) +#define ARM_T_RELOAD HW_REGISTER_RW(ARM_BASE+0x418) +#define ARM_T_PREDIV HW_REGISTER_RW(ARM_BASE+0x41c) +#define ARM_T_FREECNT HW_REGISTER_RW(ARM_BASE+0x420) + +#define TIMER_CTRL_ONESHOT (1 << 0) +#define TIMER_CTRL_32BIT (1 << 1) +#define TIMER_CTRL_DIV1 (0 << 2) +#define TIMER_CTRL_DIV16 (1 << 2) +#define TIMER_CTRL_DIV256 (2 << 2) +#define TIMER_CTRL_IE (1 << 5) +#define TIMER_CTRL_PERIODIC (1 << 6) +#define TIMER_CTRL_ENABLE (1 << 7) +#define TIMER_CTRL_DBGHALT (1 << 8) +#define TIMER_CTRL_ENAFREE (1 << 9) +#define TIMER_CTRL_FREEDIV_SHIFT 16) +#define TIMER_CTRL_FREEDIV_MASK 0xff + +/* Semaphores, Doorbells, Mailboxes */ +#define ARM_SBM_OWN0 (ARM_BASE+0x800) +#define ARM_SBM_OWN1 (ARM_BASE+0x900) +#define ARM_SBM_OWN2 (ARM_BASE+0xA00) +#define ARM_SBM_OWN3 (ARM_BASE+0xB00) + +/* MAILBOXES + * Register flags are common across all + * owner registers. See end of this section + * + * Semaphores, Doorbells, Mailboxes Owner 0 + * + */ + +#define ARM_0_SEMS HW_REGISTER_RW(ARM_SBM_OWN0+0x00) +#define ARM_0_SEM0 HW_REGISTER_RW(ARM_SBM_OWN0+0x00) +#define ARM_0_SEM1 HW_REGISTER_RW(ARM_SBM_OWN0+0x04) +#define ARM_0_SEM2 HW_REGISTER_RW(ARM_SBM_OWN0+0x08) +#define ARM_0_SEM3 HW_REGISTER_RW(ARM_SBM_OWN0+0x0C) +#define ARM_0_SEM4 HW_REGISTER_RW(ARM_SBM_OWN0+0x10) +#define ARM_0_SEM5 HW_REGISTER_RW(ARM_SBM_OWN0+0x14) +#define ARM_0_SEM6 HW_REGISTER_RW(ARM_SBM_OWN0+0x18) +#define ARM_0_SEM7 HW_REGISTER_RW(ARM_SBM_OWN0+0x1C) +#define ARM_0_BELL0 HW_REGISTER_RW(ARM_SBM_OWN0+0x40) +#define ARM_0_BELL1 HW_REGISTER_RW(ARM_SBM_OWN0+0x44) +#define ARM_0_BELL2 HW_REGISTER_RW(ARM_SBM_OWN0+0x48) +#define ARM_0_BELL3 HW_REGISTER_RW(ARM_SBM_OWN0+0x4C) +/* MAILBOX 0 access in Owner 0 area */ +/* Some addresses should ONLY be used by owner 0 */ +#define ARM_0_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN0+0x80) /* .. 0x8C (4 locations) */ +#define ARM_0_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN0+0x80) /* .. 0x8C (4 locations) Normal read */ +#define ARM_0_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN0+0x90) /* none-pop read */ +#define ARM_0_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN0+0x94) /* Sender read (only LS 2 bits) */ +#define ARM_0_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN0+0x98) /* Status read */ +#define ARM_0_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN0+0x9C) /* Config read/write */ +/* MAILBOX 1 access in Owner 0 area */ +/* Owner 0 should only WRITE to this mailbox */ +#define ARM_0_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN0+0xA0) /* .. 0xAC (4 locations) */ +/*#define ARM_0_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN0+0xA0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_0_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN0+0xB0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_0_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN0+0xB4) */ /* DO NOT USE THIS !!!!! */ +#define ARM_0_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN0+0xB8) /* Status read */ +/*#define ARM_0_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN0+0xBC) */ /* DO NOT USE THIS !!!!! */ +/* General SEM, BELL, MAIL config/status */ +#define ARM_0_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN0+0xE0) /* semaphore clear/debug register */ +#define ARM_0_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN0+0xE4) /* Doorbells clear/debug register */ +#define ARM_0_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN0+0xF8) /* ALL interrupts */ +#define ARM_0_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN0+0xFC) /* IRQS pending for owner 0 */ + +/* Semaphores, Doorbells, Mailboxes Owner 1 */ +#define ARM_1_SEMS HW_REGISTER_RW(ARM_SBM_OWN1+0x00) +#define ARM_1_SEM0 HW_REGISTER_RW(ARM_SBM_OWN1+0x00) +#define ARM_1_SEM1 HW_REGISTER_RW(ARM_SBM_OWN1+0x04) +#define ARM_1_SEM2 HW_REGISTER_RW(ARM_SBM_OWN1+0x08) +#define ARM_1_SEM3 HW_REGISTER_RW(ARM_SBM_OWN1+0x0C) +#define ARM_1_SEM4 HW_REGISTER_RW(ARM_SBM_OWN1+0x10) +#define ARM_1_SEM5 HW_REGISTER_RW(ARM_SBM_OWN1+0x14) +#define ARM_1_SEM6 HW_REGISTER_RW(ARM_SBM_OWN1+0x18) +#define ARM_1_SEM7 HW_REGISTER_RW(ARM_SBM_OWN1+0x1C) +#define ARM_1_BELL0 HW_REGISTER_RW(ARM_SBM_OWN1+0x40) +#define ARM_1_BELL1 HW_REGISTER_RW(ARM_SBM_OWN1+0x44) +#define ARM_1_BELL2 HW_REGISTER_RW(ARM_SBM_OWN1+0x48) +#define ARM_1_BELL3 HW_REGISTER_RW(ARM_SBM_OWN1+0x4C) +/* MAILBOX 0 access in Owner 0 area */ +/* Owner 1 should only WRITE to this mailbox */ +#define ARM_1_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN1+0x80) /* .. 0x8C (4 locations) */ +/*#define ARM_1_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN1+0x80) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_1_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN1+0x90) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_1_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN1+0x94) */ /* DO NOT USE THIS !!!!! */ +#define ARM_1_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN1+0x98) /* Status read */ +/*#define ARM_1_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN1+0x9C) */ /* DO NOT USE THIS !!!!! */ +/* MAILBOX 1 access in Owner 0 area */ +#define ARM_1_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN1+0xA0) /* .. 0xAC (4 locations) */ +#define ARM_1_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN1+0xA0) /* .. 0xAC (4 locations) Normal read */ +#define ARM_1_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN1+0xB0) /* none-pop read */ +#define ARM_1_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN1+0xB4) /* Sender read (only LS 2 bits) */ +#define ARM_1_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN1+0xB8) /* Status read */ +#define ARM_1_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN1+0xBC) +/* General SEM, BELL, MAIL config/status */ +#define ARM_1_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN1+0xE0) /* semaphore clear/debug register */ +#define ARM_1_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN1+0xE4) /* Doorbells clear/debug register */ +#define ARM_1_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN1+0xFC) /* IRQS pending for owner 1 */ +#define ARM_1_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN1+0xF8) /* ALL interrupts */ + +/* Semaphores, Doorbells, Mailboxes Owner 2 */ +#define ARM_2_SEMS HW_REGISTER_RW(ARM_SBM_OWN2+0x00) +#define ARM_2_SEM0 HW_REGISTER_RW(ARM_SBM_OWN2+0x00) +#define ARM_2_SEM1 HW_REGISTER_RW(ARM_SBM_OWN2+0x04) +#define ARM_2_SEM2 HW_REGISTER_RW(ARM_SBM_OWN2+0x08) +#define ARM_2_SEM3 HW_REGISTER_RW(ARM_SBM_OWN2+0x0C) +#define ARM_2_SEM4 HW_REGISTER_RW(ARM_SBM_OWN2+0x10) +#define ARM_2_SEM5 HW_REGISTER_RW(ARM_SBM_OWN2+0x14) +#define ARM_2_SEM6 HW_REGISTER_RW(ARM_SBM_OWN2+0x18) +#define ARM_2_SEM7 HW_REGISTER_RW(ARM_SBM_OWN2+0x1C) +#define ARM_2_BELL0 HW_REGISTER_RW(ARM_SBM_OWN2+0x40) +#define ARM_2_BELL1 HW_REGISTER_RW(ARM_SBM_OWN2+0x44) +#define ARM_2_BELL2 HW_REGISTER_RW(ARM_SBM_OWN2+0x48) +#define ARM_2_BELL3 HW_REGISTER_RW(ARM_SBM_OWN2+0x4C) +/* MAILBOX 0 access in Owner 2 area */ +/* Owner 2 should only WRITE to this mailbox */ +#define ARM_2_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN2+0x80) /* .. 0x8C (4 locations) */ +/*#define ARM_2_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN2+0x80) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_2_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN2+0x90) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_2_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN2+0x94) */ /* DO NOT USE THIS !!!!! */ +#define ARM_2_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN2+0x98) /* Status read */ +/*#define ARM_2_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN2+0x9C) */ /* DO NOT USE THIS !!!!! */ +/* MAILBOX 1 access in Owner 2 area */ +/* Owner 2 should only WRITE to this mailbox */ +#define ARM_2_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN2+0xA0) /* .. 0xAC (4 locations) */ +/*#define ARM_2_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN2+0xA0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_2_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN2+0xB0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_2_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN2+0xB4) */ /* DO NOT USE THIS !!!!! */ +#define ARM_2_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN2+0xB8) /* Status read */ +/*#define ARM_2_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN2+0xBC) */ /* DO NOT USE THIS !!!!! */ +/* General SEM, BELL, MAIL config/status */ +#define ARM_2_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN2+0xE0) /* semaphore clear/debug register */ +#define ARM_2_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN2+0xE4) /* Doorbells clear/debug register */ +#define ARM_2_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN2+0xFC) /* IRQS pending for owner 2 */ +#define ARM_2_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN2+0xF8) /* ALL interrupts */ + +/* Semaphores, Doorbells, Mailboxes Owner 3 */ +#define ARM_3_SEMS HW_REGISTER_RW(ARM_SBM_OWN3+0x00) +#define ARM_3_SEM0 HW_REGISTER_RW(ARM_SBM_OWN3+0x00) +#define ARM_3_SEM1 HW_REGISTER_RW(ARM_SBM_OWN3+0x04) +#define ARM_3_SEM2 HW_REGISTER_RW(ARM_SBM_OWN3+0x08) +#define ARM_3_SEM3 HW_REGISTER_RW(ARM_SBM_OWN3+0x0C) +#define ARM_3_SEM4 HW_REGISTER_RW(ARM_SBM_OWN3+0x10) +#define ARM_3_SEM5 HW_REGISTER_RW(ARM_SBM_OWN3+0x14) +#define ARM_3_SEM6 HW_REGISTER_RW(ARM_SBM_OWN3+0x18) +#define ARM_3_SEM7 HW_REGISTER_RW(ARM_SBM_OWN3+0x1C) +#define ARM_3_BELL0 HW_REGISTER_RW(ARM_SBM_OWN3+0x40) +#define ARM_3_BELL1 HW_REGISTER_RW(ARM_SBM_OWN3+0x44) +#define ARM_3_BELL2 HW_REGISTER_RW(ARM_SBM_OWN3+0x48) +#define ARM_3_BELL3 HW_REGISTER_RW(ARM_SBM_OWN3+0x4C) +/* MAILBOX 0 access in Owner 3 area */ +/* Owner 3 should only WRITE to this mailbox */ +#define ARM_3_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN3+0x80) /* .. 0x8C (4 locations) */ +/*#define ARM_3_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN3+0x80) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_3_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN3+0x90) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_3_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN3+0x94) */ /* DO NOT USE THIS !!!!! */ +#define ARM_3_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN3+0x98) /* Status read */ +/*#define ARM_3_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN3+0x9C) */ /* DO NOT USE THIS !!!!! */ +/* MAILBOX 1 access in Owner 3 area */ +/* Owner 3 should only WRITE to this mailbox */ +#define ARM_3_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN3+0xA0) /* .. 0xAC (4 locations) */ +/*#define ARM_3_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN3+0xA0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_3_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN3+0xB0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_3_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN3+0xB4) */ /* DO NOT USE THIS !!!!! */ +#define ARM_3_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN3+0xB8) /* Status read */ +/*#define ARM_3_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN3+0xBC) */ /* DO NOT USE THIS !!!!! */ +/* General SEM, BELL, MAIL config/status */ +#define ARM_3_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN3+0xE0) /* semaphore clear/debug register */ +#define ARM_3_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN3+0xE4) /* Doorbells clear/debug register */ +#define ARM_3_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN3+0xFC) /* IRQS pending for owner 3 */ +#define ARM_3_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN3+0xF8) /* ALL interrupts */ + + + +/* Mailbox flags. Valid for all owners */ + +/* Mailbox status register (...0x98) */ +#define ARM_MS_FULL 0x80000000 +#define ARM_MS_EMPTY 0x40000000 +#define ARM_MS_LEVEL 0x400000FF /* Max. value depdnds on mailbox depth parameter */ + +/* MAILBOX config/status register (...0x9C) */ +/* ANY write to this register clears the error bits! */ +#define ARM_MC_IHAVEDATAIRQEN 0x00000001 /* mailbox irq enable: has data */ +#define ARM_MC_IHAVESPACEIRQEN 0x00000002 /* mailbox irq enable: has space */ +#define ARM_MC_OPPISEMPTYIRQEN 0x00000004 /* mailbox irq enable: Opp. is empty */ +#define ARM_MC_MAIL_CLEAR 0x00000008 /* mailbox clear write 1, then 0 */ +#define ARM_MC_IHAVEDATAIRQPEND 0x00000010 /* mailbox irq pending: has space */ +#define ARM_MC_IHAVESPACEIRQPEND 0x00000020 /* mailbox irq pending: Opp. is empty */ +#define ARM_MC_OPPISEMPTYIRQPEND 0x00000040 /* mailbox irq pending */ +/* Bit 7 is unused */ +#define ARM_MC_ERRNOOWN 0x00000100 /* error : none owner read from mailbox */ +#define ARM_MC_ERROVERFLW 0x00000200 /* error : write to fill mailbox */ +#define ARM_MC_ERRUNDRFLW 0x00000400 /* error : read from empty mailbox */ + +/* Semaphore clear/debug register (...0xE0) */ +#define ARM_SD_OWN0 0x00000003 /* Owner of sem 0 */ +#define ARM_SD_OWN1 0x0000000C /* Owner of sem 1 */ +#define ARM_SD_OWN2 0x00000030 /* Owner of sem 2 */ +#define ARM_SD_OWN3 0x000000C0 /* Owner of sem 3 */ +#define ARM_SD_OWN4 0x00000300 /* Owner of sem 4 */ +#define ARM_SD_OWN5 0x00000C00 /* Owner of sem 5 */ +#define ARM_SD_OWN6 0x00003000 /* Owner of sem 6 */ +#define ARM_SD_OWN7 0x0000C000 /* Owner of sem 7 */ +#define ARM_SD_SEM0 0x00010000 /* Status of sem 0 */ +#define ARM_SD_SEM1 0x00020000 /* Status of sem 1 */ +#define ARM_SD_SEM2 0x00040000 /* Status of sem 2 */ +#define ARM_SD_SEM3 0x00080000 /* Status of sem 3 */ +#define ARM_SD_SEM4 0x00100000 /* Status of sem 4 */ +#define ARM_SD_SEM5 0x00200000 /* Status of sem 5 */ +#define ARM_SD_SEM6 0x00400000 /* Status of sem 6 */ +#define ARM_SD_SEM7 0x00800000 /* Status of sem 7 */ + +/* Doorbells clear/debug register (...0xE4) */ +#define ARM_BD_OWN0 0x00000003 /* Owner of doorbell 0 */ +#define ARM_BD_OWN1 0x0000000C /* Owner of doorbell 1 */ +#define ARM_BD_OWN2 0x00000030 /* Owner of doorbell 2 */ +#define ARM_BD_OWN3 0x000000C0 /* Owner of doorbell 3 */ +#define ARM_BD_BELL0 0x00000100 /* Status of doorbell 0 */ +#define ARM_BD_BELL1 0x00000200 /* Status of doorbell 1 */ +#define ARM_BD_BELL2 0x00000400 /* Status of doorbell 2 */ +#define ARM_BD_BELL3 0x00000800 /* Status of doorbell 3 */ + +/* MY IRQS register (...0xF8) */ +#define ARM_MYIRQ_BELL 0x00000001 /* This owner has a doorbell IRQ */ +#define ARM_MYIRQ_MAIL 0x00000002 /* This owner has a mailbox IRQ */ + +/* ALL IRQS register (...0xF8) */ +#define ARM_AIS_BELL0 0x00000001 /* Doorbell 0 IRQ pending */ +#define ARM_AIS_BELL1 0x00000002 /* Doorbell 1 IRQ pending */ +#define ARM_AIS_BELL2 0x00000004 /* Doorbell 2 IRQ pending */ +#define ARM_AIS_BELL3 0x00000008 /* Doorbell 3 IRQ pending */ +#define ARM_AIS0_HAVEDATA 0x00000010 /* MAIL 0 has data IRQ pending */ +#define ARM_AIS0_HAVESPAC 0x00000020 /* MAIL 0 has space IRQ pending */ +#define ARM_AIS0_OPPEMPTY 0x00000040 /* MAIL 0 opposite is empty IRQ */ +#define ARM_AIS1_HAVEDATA 0x00000080 /* MAIL 1 has data IRQ pending */ +#define ARM_AIS1_HAVESPAC 0x00000100 /* MAIL 1 has space IRQ pending */ +#define ARM_AIS1_OPPEMPTY 0x00000200 /* MAIL 1 opposite is empty IRQ */ +/* Note that bell-0, bell-1 and MAIL0 IRQ go only to the ARM */ +/* Whilst that bell-2, bell-3 and MAIL1 IRQ go only to the VC */ +/* */ +/* ARM JTAG BASH */ +/* */ +#define AJB_BASE 0x7e2000c0 + +#define AJBCONF HW_REGISTER_RW(AJB_BASE+0x00) +#define AJB_BITS0 0x000000 +#define AJB_BITS4 0x000004 +#define AJB_BITS8 0x000008 +#define AJB_BITS12 0x00000C +#define AJB_BITS16 0x000010 +#define AJB_BITS20 0x000014 +#define AJB_BITS24 0x000018 +#define AJB_BITS28 0x00001C +#define AJB_BITS32 0x000020 +#define AJB_BITS34 0x000022 +#define AJB_OUT_MS 0x000040 +#define AJB_OUT_LS 0x000000 +#define AJB_INV_CLK 0x000080 +#define AJB_D0_RISE 0x000100 +#define AJB_D0_FALL 0x000000 +#define AJB_D1_RISE 0x000200 +#define AJB_D1_FALL 0x000000 +#define AJB_IN_RISE 0x000400 +#define AJB_IN_FALL 0x000000 +#define AJB_ENABLE 0x000800 +#define AJB_HOLD0 0x000000 +#define AJB_HOLD1 0x001000 +#define AJB_HOLD2 0x002000 +#define AJB_HOLD3 0x003000 +#define AJB_RESETN 0x004000 +#define AJB_CLKSHFT 16 +#define AJB_BUSY 0x80000000 +#define AJBTMS HW_REGISTER_RW(AJB_BASE+0x04) +#define AJBTDI HW_REGISTER_RW(AJB_BASE+0x08) +#define AJBTDO HW_REGISTER_RW(AJB_BASE+0x0c) + +#define ARM_LOCAL_BASE 0x40000000 +#define ARM_LOCAL_CONTROL HW_REGISTER_RW(ARM_LOCAL_BASE+0x000) +#define ARM_LOCAL_PRESCALER HW_REGISTER_RW(ARM_LOCAL_BASE+0x008) +#define ARM_LOCAL_GPU_INT_ROUTING HW_REGISTER_RW(ARM_LOCAL_BASE+0x00C) +#define ARM_LOCAL_PM_ROUTING_SET HW_REGISTER_RW(ARM_LOCAL_BASE+0x010) +#define ARM_LOCAL_PM_ROUTING_CLR HW_REGISTER_RW(ARM_LOCAL_BASE+0x014) +#define ARM_LOCAL_TIMER_LS HW_REGISTER_RW(ARM_LOCAL_BASE+0x01C) +#define ARM_LOCAL_TIMER_MS HW_REGISTER_RW(ARM_LOCAL_BASE+0x020) +#define ARM_LOCAL_INT_ROUTING HW_REGISTER_RW(ARM_LOCAL_BASE+0x024) +#define ARM_LOCAL_AXI_COUNT HW_REGISTER_RW(ARM_LOCAL_BASE+0x02C) +#define ARM_LOCAL_AXI_IRQ HW_REGISTER_RW(ARM_LOCAL_BASE+0x030) +#define ARM_LOCAL_TIMER_CONTROL HW_REGISTER_RW(ARM_LOCAL_BASE+0x034) +#define ARM_LOCAL_TIMER_WRITE HW_REGISTER_RW(ARM_LOCAL_BASE+0x038) + +#define ARM_LOCAL_TIMER_INT_CONTROL0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x040) +#define ARM_LOCAL_TIMER_INT_CONTROL1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x044) +#define ARM_LOCAL_TIMER_INT_CONTROL2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x048) +#define ARM_LOCAL_TIMER_INT_CONTROL3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x04C) + +#define ARM_LOCAL_MAILBOX_INT_CONTROL0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x050) +#define ARM_LOCAL_MAILBOX_INT_CONTROL1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x054) +#define ARM_LOCAL_MAILBOX_INT_CONTROL2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x058) +#define ARM_LOCAL_MAILBOX_INT_CONTROL3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x05C) + +#define ARM_LOCAL_IRQ_PENDING0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x060) +#define ARM_LOCAL_IRQ_PENDING1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x064) +#define ARM_LOCAL_IRQ_PENDING2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x068) +#define ARM_LOCAL_IRQ_PENDING3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x06C) + +#define ARM_LOCAL_FIQ_PENDING0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x070) +#define ARM_LOCAL_FIQ_PENDING1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x074) +#define ARM_LOCAL_FIQ_PENDING2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x078) +#define ARM_LOCAL_FIQ_PENDING3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x07C) + +#define ARM_LOCAL_MAILBOX0_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x080) +#define ARM_LOCAL_MAILBOX1_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x084) +#define ARM_LOCAL_MAILBOX2_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x088) +#define ARM_LOCAL_MAILBOX3_SET0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x08C) + +#define ARM_LOCAL_MAILBOX0_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x090) +#define ARM_LOCAL_MAILBOX1_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x094) +#define ARM_LOCAL_MAILBOX2_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x098) +#define ARM_LOCAL_MAILBOX3_SET1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x09C) + +#define ARM_LOCAL_MAILBOX0_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A0) +#define ARM_LOCAL_MAILBOX1_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A4) +#define ARM_LOCAL_MAILBOX2_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0A8) +#define ARM_LOCAL_MAILBOX3_SET2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0AC) + +#define ARM_LOCAL_MAILBOX0_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B0) +#define ARM_LOCAL_MAILBOX1_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B4) +#define ARM_LOCAL_MAILBOX2_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0B8) +#define ARM_LOCAL_MAILBOX3_SET3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0BC) + +#define ARM_LOCAL_MAILBOX0_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C0) +#define ARM_LOCAL_MAILBOX1_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C4) +#define ARM_LOCAL_MAILBOX2_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0C8) +#define ARM_LOCAL_MAILBOX3_CLR0 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0CC) + +#define ARM_LOCAL_MAILBOX0_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D0) +#define ARM_LOCAL_MAILBOX1_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D4) +#define ARM_LOCAL_MAILBOX2_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0D8) +#define ARM_LOCAL_MAILBOX3_CLR1 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0DC) + +#define ARM_LOCAL_MAILBOX0_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E0) +#define ARM_LOCAL_MAILBOX1_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E4) +#define ARM_LOCAL_MAILBOX2_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0E8) +#define ARM_LOCAL_MAILBOX3_CLR2 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0EC) + +#define ARM_LOCAL_MAILBOX0_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F0) +#define ARM_LOCAL_MAILBOX1_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F4) +#define ARM_LOCAL_MAILBOX2_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0F8) +#define ARM_LOCAL_MAILBOX3_CLR3 HW_REGISTER_RW(ARM_LOCAL_BASE+0x0FC) + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/barriers.h raspilinux/arch/arm/mach-bcm2709/include/mach/barriers.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/barriers.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/barriers.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,3 @@ +#define mb() dsb() +#define rmb() dsb() +#define wmb() mb() diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/clkdev.h raspilinux/arch/arm/mach-bcm2709/include/mach/clkdev.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/clkdev.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/clkdev.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/debug-macro.S raspilinux/arch/arm/mach-bcm2709/include/mach/debug-macro.S --- linux-stable/arch/arm/mach-bcm2709/include/mach/debug-macro.S 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/debug-macro.S 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,22 @@ +/* arch/arm/mach-bcm2708/include/mach/debug-macro.S + * + * Debugging macro include header + * + * Copyright (C) 2010 Broadcom + * Copyright (C) 1994-1999 Russell King + * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include + + .macro addruart, rp, rv, tmp + ldr \rp, =UART0_BASE + ldr \rv, =IO_ADDRESS(UART0_BASE) + .endm + +#include diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/entry-macro.S raspilinux/arch/arm/mach-bcm2709/include/mach/entry-macro.S --- linux-stable/arch/arm/mach-bcm2709/include/mach/entry-macro.S 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/entry-macro.S 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,120 @@ +/* + * arch/arm/mach-bcm2708/include/mach/entry-macro.S + * + * Low-level IRQ helper macros for BCM2708 platforms + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + /* get core number */ + mrc p15, 0, \base, c0, c0, 5 + ubfx \base, \base, #0, #2 + + /* get core's local interrupt controller */ + ldr \irqstat, = __io_address(ARM_LOCAL_IRQ_PENDING0) @ local interrupt source + add \irqstat, \irqstat, \base, lsl #2 + ldr \tmp, [\irqstat] +#ifdef CONFIG_SMP + /* test for mailbox0 (IPI) interrupt */ + tst \tmp, #0x10 + beq 1030f + + /* get core's mailbox interrupt control */ + ldr \irqstat, = __io_address(ARM_LOCAL_MAILBOX0_CLR0) @ mbox_clr + add \irqstat, \irqstat, \base, lsl #4 + ldr \tmp, [\irqstat] + clz \tmp, \tmp + rsb \irqnr, \tmp, #31 + mov \tmp, #1 + lsl \tmp, \irqnr + str \tmp, [\irqstat] @ clear interrupt source + dsb + mov r1, sp + adr lr, BSYM(1b) + b do_IPI +#endif +1030: + /* check gpu interrupt */ + tst \tmp, #0x100 + beq 1040f + + ldr \base, =IO_ADDRESS(ARMCTRL_IC_BASE) + /* get masked status */ + ldr \irqstat, [\base, #(ARM_IRQ_PEND0 - ARMCTRL_IC_BASE)] + mov \irqnr, #(ARM_IRQ0_BASE + 31) + and \tmp, \irqstat, #0x300 @ save bits 8 and 9 + /* clear bits 8 and 9, and test */ + bics \irqstat, \irqstat, #0x300 + bne 1010f + + tst \tmp, #0x100 + ldrne \irqstat, [\base, #(ARM_IRQ_PEND1 - ARMCTRL_IC_BASE)] + movne \irqnr, #(ARM_IRQ1_BASE + 31) + @ Mask out the interrupts also present in PEND0 - see SW-5809 + bicne \irqstat, #((1<<7) | (1<<9) | (1<<10)) + bicne \irqstat, #((1<<18) | (1<<19)) + bne 1010f + + tst \tmp, #0x200 + ldrne \irqstat, [\base, #(ARM_IRQ_PEND2 - ARMCTRL_IC_BASE)] + movne \irqnr, #(ARM_IRQ2_BASE + 31) + @ Mask out the interrupts also present in PEND0 - see SW-5809 + bicne \irqstat, #((1<<21) | (1<<22) | (1<<23) | (1<<24) | (1<<25)) + bicne \irqstat, #((1<<30)) + beq 1020f +1010: + @ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1)) + sub \tmp, \irqstat, #1 + eor \irqstat, \irqstat, \tmp + clz \tmp, \irqstat + sub \irqnr, \tmp + b 1050f +1040: + cmp \tmp, #0 + beq 1020f + + /* handle local (e.g. timer) interrupts */ + @ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1)) + mov \irqnr, #(ARM_IRQ_LOCAL_BASE + 31) + sub \irqstat, \tmp, #1 + eor \irqstat, \irqstat, \tmp + clz \tmp, \irqstat + sub \irqnr, \tmp +1050: + mov r1, sp + @ + @ routine called with r0 = irq number, r1 = struct pt_regs * + @ + adr lr, BSYM(1b) + b asm_do_IRQ + +1020: @ EQ will be set if no irqs pending + .endm + +/* + * Interrupt handling. Preserves r7, r8, r9 + */ + .macro arch_irq_handler_default +1: get_irqnr_and_base r0, r2, r6, lr + .endm diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/frc.h raspilinux/arch/arm/mach-bcm2709/include/mach/frc.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/frc.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/frc.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,38 @@ +/* + * arch/arm/mach-bcm2708/include/mach/timex.h + * + * BCM2708 free running counter (timer) + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MACH_FRC_H +#define _MACH_FRC_H + +#define FRC_TICK_RATE (1000000) + +/*! Free running counter incrementing at the CLOCK_TICK_RATE + (slightly faster than frc_clock_ticks63() + */ +extern unsigned long frc_clock_ticks32(void); + +/*! Free running counter incrementing at the CLOCK_TICK_RATE + * Note - top bit should be ignored (see cnt32_to_63) + */ +extern unsigned long long frc_clock_ticks63(void); + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/gpio.h raspilinux/arch/arm/mach-bcm2709/include/mach/gpio.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/gpio.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/gpio.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,17 @@ +/* + * arch/arm/mach-bcm2708/include/mach/gpio.h + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H + +#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 '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/hardware.h raspilinux/arch/arm/mach-bcm2709/include/mach/hardware.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/hardware.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/hardware.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-bcm2708/include/mach/hardware.h + * + * This file contains the hardware definitions of the BCM2708 devices. + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +#include +#include + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/io.h raspilinux/arch/arm/mach-bcm2709/include/mach/io.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/io.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/io.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,27 @@ +/* + * arch/arm/mach-bcm2708/include/mach/io.h + * + * Copyright (C) 2003 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +#define __io(a) __typesafe_io(a) + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/irqs.h raspilinux/arch/arm/mach-bcm2709/include/mach/irqs.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/irqs.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/irqs.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,225 @@ +/* + * arch/arm/mach-bcm2708/include/mach/irqs.h + * + * Copyright (C) 2010 Broadcom + * Copyright (C) 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _BCM2708_IRQS_H_ +#define _BCM2708_IRQS_H_ + +#include + +/* + * IRQ interrupts definitions are the same as the INT definitions + * held within platform.h + */ +#define IRQ_ARMCTRL_START 0 +#define IRQ_TIMER0 (IRQ_ARMCTRL_START + INTERRUPT_TIMER0) +#define IRQ_TIMER1 (IRQ_ARMCTRL_START + INTERRUPT_TIMER1) +#define IRQ_TIMER2 (IRQ_ARMCTRL_START + INTERRUPT_TIMER2) +#define IRQ_TIMER3 (IRQ_ARMCTRL_START + INTERRUPT_TIMER3) +#define IRQ_CODEC0 (IRQ_ARMCTRL_START + INTERRUPT_CODEC0) +#define IRQ_CODEC1 (IRQ_ARMCTRL_START + INTERRUPT_CODEC1) +#define IRQ_CODEC2 (IRQ_ARMCTRL_START + INTERRUPT_CODEC2) +#define IRQ_JPEG (IRQ_ARMCTRL_START + INTERRUPT_JPEG) +#define IRQ_ISP (IRQ_ARMCTRL_START + INTERRUPT_ISP) +#define IRQ_USB (IRQ_ARMCTRL_START + INTERRUPT_USB) +#define IRQ_3D (IRQ_ARMCTRL_START + INTERRUPT_3D) +#define IRQ_TRANSPOSER (IRQ_ARMCTRL_START + INTERRUPT_TRANSPOSER) +#define IRQ_MULTICORESYNC0 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC0) +#define IRQ_MULTICORESYNC1 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC1) +#define IRQ_MULTICORESYNC2 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC2) +#define IRQ_MULTICORESYNC3 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC3) +#define IRQ_DMA0 (IRQ_ARMCTRL_START + INTERRUPT_DMA0) +#define IRQ_DMA1 (IRQ_ARMCTRL_START + INTERRUPT_DMA1) +#define IRQ_DMA2 (IRQ_ARMCTRL_START + INTERRUPT_DMA2) +#define IRQ_DMA3 (IRQ_ARMCTRL_START + INTERRUPT_DMA3) +#define IRQ_DMA4 (IRQ_ARMCTRL_START + INTERRUPT_DMA4) +#define IRQ_DMA5 (IRQ_ARMCTRL_START + INTERRUPT_DMA5) +#define IRQ_DMA6 (IRQ_ARMCTRL_START + INTERRUPT_DMA6) +#define IRQ_DMA7 (IRQ_ARMCTRL_START + INTERRUPT_DMA7) +#define IRQ_DMA8 (IRQ_ARMCTRL_START + INTERRUPT_DMA8) +#define IRQ_DMA9 (IRQ_ARMCTRL_START + INTERRUPT_DMA9) +#define IRQ_DMA10 (IRQ_ARMCTRL_START + INTERRUPT_DMA10) +#define IRQ_DMA11 (IRQ_ARMCTRL_START + INTERRUPT_DMA11) +#define IRQ_DMA12 (IRQ_ARMCTRL_START + INTERRUPT_DMA12) +#define IRQ_AUX (IRQ_ARMCTRL_START + INTERRUPT_AUX) +#define IRQ_ARM (IRQ_ARMCTRL_START + INTERRUPT_ARM) +#define IRQ_VPUDMA (IRQ_ARMCTRL_START + INTERRUPT_VPUDMA) +#define IRQ_HOSTPORT (IRQ_ARMCTRL_START + INTERRUPT_HOSTPORT) +#define IRQ_VIDEOSCALER (IRQ_ARMCTRL_START + INTERRUPT_VIDEOSCALER) +#define IRQ_CCP2TX (IRQ_ARMCTRL_START + INTERRUPT_CCP2TX) +#define IRQ_SDC (IRQ_ARMCTRL_START + INTERRUPT_SDC) +#define IRQ_DSI0 (IRQ_ARMCTRL_START + INTERRUPT_DSI0) +#define IRQ_AVE (IRQ_ARMCTRL_START + INTERRUPT_AVE) +#define IRQ_CAM0 (IRQ_ARMCTRL_START + INTERRUPT_CAM0) +#define IRQ_CAM1 (IRQ_ARMCTRL_START + INTERRUPT_CAM1) +#define IRQ_HDMI0 (IRQ_ARMCTRL_START + INTERRUPT_HDMI0) +#define IRQ_HDMI1 (IRQ_ARMCTRL_START + INTERRUPT_HDMI1) +#define IRQ_PIXELVALVE1 (IRQ_ARMCTRL_START + INTERRUPT_PIXELVALVE1) +#define IRQ_I2CSPISLV (IRQ_ARMCTRL_START + INTERRUPT_I2CSPISLV) +#define IRQ_DSI1 (IRQ_ARMCTRL_START + INTERRUPT_DSI1) +#define IRQ_PWA0 (IRQ_ARMCTRL_START + INTERRUPT_PWA0) +#define IRQ_PWA1 (IRQ_ARMCTRL_START + INTERRUPT_PWA1) +#define IRQ_CPR (IRQ_ARMCTRL_START + INTERRUPT_CPR) +#define IRQ_SMI (IRQ_ARMCTRL_START + INTERRUPT_SMI) +#define IRQ_GPIO0 (IRQ_ARMCTRL_START + INTERRUPT_GPIO0) +#define IRQ_GPIO1 (IRQ_ARMCTRL_START + INTERRUPT_GPIO1) +#define IRQ_GPIO2 (IRQ_ARMCTRL_START + INTERRUPT_GPIO2) +#define IRQ_GPIO3 (IRQ_ARMCTRL_START + INTERRUPT_GPIO3) +#define IRQ_I2C (IRQ_ARMCTRL_START + INTERRUPT_I2C) +#define IRQ_SPI (IRQ_ARMCTRL_START + INTERRUPT_SPI) +#define IRQ_I2SPCM (IRQ_ARMCTRL_START + INTERRUPT_I2SPCM) +#define IRQ_SDIO (IRQ_ARMCTRL_START + INTERRUPT_SDIO) +#define IRQ_UART (IRQ_ARMCTRL_START + INTERRUPT_UART) +#define IRQ_SLIMBUS (IRQ_ARMCTRL_START + INTERRUPT_SLIMBUS) +#define IRQ_VEC (IRQ_ARMCTRL_START + INTERRUPT_VEC) +#define IRQ_CPG (IRQ_ARMCTRL_START + INTERRUPT_CPG) +#define IRQ_RNG (IRQ_ARMCTRL_START + INTERRUPT_RNG) +#define IRQ_ARASANSDIO (IRQ_ARMCTRL_START + INTERRUPT_ARASANSDIO) +#define IRQ_AVSPMON (IRQ_ARMCTRL_START + INTERRUPT_AVSPMON) + +#define IRQ_ARM_TIMER (IRQ_ARMCTRL_START + INTERRUPT_ARM_TIMER) +#define IRQ_ARM_MAILBOX (IRQ_ARMCTRL_START + INTERRUPT_ARM_MAILBOX) +#define IRQ_ARM_DOORBELL_0 (IRQ_ARMCTRL_START + INTERRUPT_ARM_DOORBELL_0) +#define IRQ_ARM_DOORBELL_1 (IRQ_ARMCTRL_START + INTERRUPT_ARM_DOORBELL_1) +#define IRQ_VPU0_HALTED (IRQ_ARMCTRL_START + INTERRUPT_VPU0_HALTED) +#define IRQ_VPU1_HALTED (IRQ_ARMCTRL_START + INTERRUPT_VPU1_HALTED) +#define IRQ_ILLEGAL_TYPE0 (IRQ_ARMCTRL_START + INTERRUPT_ILLEGAL_TYPE0) +#define IRQ_ILLEGAL_TYPE1 (IRQ_ARMCTRL_START + INTERRUPT_ILLEGAL_TYPE1) +#define IRQ_PENDING1 (IRQ_ARMCTRL_START + INTERRUPT_PENDING1) +#define IRQ_PENDING2 (IRQ_ARMCTRL_START + INTERRUPT_PENDING2) + +#define IRQ_ARM_LOCAL_CNTPSIRQ (IRQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_CNTPSIRQ) +#define IRQ_ARM_LOCAL_CNTPNSIRQ (IRQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_CNTPNSIRQ) +#define IRQ_ARM_LOCAL_CNTHPIRQ (IRQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_CNTHPIRQ) +#define IRQ_ARM_LOCAL_CNTVIRQ (IRQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_CNTVIRQ) +#define IRQ_ARM_LOCAL_MAILBOX0 (IRQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_MAILBOX0) +#define IRQ_ARM_LOCAL_MAILBOX1 (IRQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_MAILBOX1) +#define IRQ_ARM_LOCAL_MAILBOX2 (IRQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_MAILBOX2) +#define IRQ_ARM_LOCAL_MAILBOX3 (IRQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_MAILBOX3) +#define IRQ_ARM_LOCAL_GPU_FAST (IRQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_GPU_FAST) +#define IRQ_ARM_LOCAL_PMU_FAST (IRQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_PMU_FAST) +#define IRQ_ARM_LOCAL_ZERO (IRQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_ZERO) +#define IRQ_ARM_LOCAL_TIMER (IRQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_TIMER) + +#define FIQ_START HARD_IRQS + +/* + * FIQ interrupts definitions are the same as the INT definitions. + */ +#define FIQ_TIMER0 (FIQ_START+INTERRUPT_TIMER0) +#define FIQ_TIMER1 (FIQ_START+INTERRUPT_TIMER1) +#define FIQ_TIMER2 (FIQ_START+INTERRUPT_TIMER2) +#define FIQ_TIMER3 (FIQ_START+INTERRUPT_TIMER3) +#define FIQ_CODEC0 (FIQ_START+INTERRUPT_CODEC0) +#define FIQ_CODEC1 (FIQ_START+INTERRUPT_CODEC1) +#define FIQ_CODEC2 (FIQ_START+INTERRUPT_CODEC2) +#define FIQ_JPEG (FIQ_START+INTERRUPT_JPEG) +#define FIQ_ISP (FIQ_START+INTERRUPT_ISP) +#define FIQ_USB (FIQ_START+INTERRUPT_USB) +#define FIQ_3D (FIQ_START+INTERRUPT_3D) +#define FIQ_TRANSPOSER (FIQ_START+INTERRUPT_TRANSPOSER) +#define FIQ_MULTICORESYNC0 (FIQ_START+INTERRUPT_MULTICORESYNC0) +#define FIQ_MULTICORESYNC1 (FIQ_START+INTERRUPT_MULTICORESYNC1) +#define FIQ_MULTICORESYNC2 (FIQ_START+INTERRUPT_MULTICORESYNC2) +#define FIQ_MULTICORESYNC3 (FIQ_START+INTERRUPT_MULTICORESYNC3) +#define FIQ_DMA0 (FIQ_START+INTERRUPT_DMA0) +#define FIQ_DMA1 (FIQ_START+INTERRUPT_DMA1) +#define FIQ_DMA2 (FIQ_START+INTERRUPT_DMA2) +#define FIQ_DMA3 (FIQ_START+INTERRUPT_DMA3) +#define FIQ_DMA4 (FIQ_START+INTERRUPT_DMA4) +#define FIQ_DMA5 (FIQ_START+INTERRUPT_DMA5) +#define FIQ_DMA6 (FIQ_START+INTERRUPT_DMA6) +#define FIQ_DMA7 (FIQ_START+INTERRUPT_DMA7) +#define FIQ_DMA8 (FIQ_START+INTERRUPT_DMA8) +#define FIQ_DMA9 (FIQ_START+INTERRUPT_DMA9) +#define FIQ_DMA10 (FIQ_START+INTERRUPT_DMA10) +#define FIQ_DMA11 (FIQ_START+INTERRUPT_DMA11) +#define FIQ_DMA12 (FIQ_START+INTERRUPT_DMA12) +#define FIQ_AUX (FIQ_START+INTERRUPT_AUX) +#define FIQ_ARM (FIQ_START+INTERRUPT_ARM) +#define FIQ_VPUDMA (FIQ_START+INTERRUPT_VPUDMA) +#define FIQ_HOSTPORT (FIQ_START+INTERRUPT_HOSTPORT) +#define FIQ_VIDEOSCALER (FIQ_START+INTERRUPT_VIDEOSCALER) +#define FIQ_CCP2TX (FIQ_START+INTERRUPT_CCP2TX) +#define FIQ_SDC (FIQ_START+INTERRUPT_SDC) +#define FIQ_DSI0 (FIQ_START+INTERRUPT_DSI0) +#define FIQ_AVE (FIQ_START+INTERRUPT_AVE) +#define FIQ_CAM0 (FIQ_START+INTERRUPT_CAM0) +#define FIQ_CAM1 (FIQ_START+INTERRUPT_CAM1) +#define FIQ_HDMI0 (FIQ_START+INTERRUPT_HDMI0) +#define FIQ_HDMI1 (FIQ_START+INTERRUPT_HDMI1) +#define FIQ_PIXELVALVE1 (FIQ_START+INTERRUPT_PIXELVALVE1) +#define FIQ_I2CSPISLV (FIQ_START+INTERRUPT_I2CSPISLV) +#define FIQ_DSI1 (FIQ_START+INTERRUPT_DSI1) +#define FIQ_PWA0 (FIQ_START+INTERRUPT_PWA0) +#define FIQ_PWA1 (FIQ_START+INTERRUPT_PWA1) +#define FIQ_CPR (FIQ_START+INTERRUPT_CPR) +#define FIQ_SMI (FIQ_START+INTERRUPT_SMI) +#define FIQ_GPIO0 (FIQ_START+INTERRUPT_GPIO0) +#define FIQ_GPIO1 (FIQ_START+INTERRUPT_GPIO1) +#define FIQ_GPIO2 (FIQ_START+INTERRUPT_GPIO2) +#define FIQ_GPIO3 (FIQ_START+INTERRUPT_GPIO3) +#define FIQ_I2C (FIQ_START+INTERRUPT_I2C) +#define FIQ_SPI (FIQ_START+INTERRUPT_SPI) +#define FIQ_I2SPCM (FIQ_START+INTERRUPT_I2SPCM) +#define FIQ_SDIO (FIQ_START+INTERRUPT_SDIO) +#define FIQ_UART (FIQ_START+INTERRUPT_UART) +#define FIQ_SLIMBUS (FIQ_START+INTERRUPT_SLIMBUS) +#define FIQ_VEC (FIQ_START+INTERRUPT_VEC) +#define FIQ_CPG (FIQ_START+INTERRUPT_CPG) +#define FIQ_RNG (FIQ_START+INTERRUPT_RNG) +#define FIQ_ARASANSDIO (FIQ_START+INTERRUPT_ARASANSDIO) +#define FIQ_AVSPMON (FIQ_START+INTERRUPT_AVSPMON) + +#define FIQ_ARM_TIMER (FIQ_START+INTERRUPT_ARM_TIMER) +#define FIQ_ARM_MAILBOX (FIQ_START+INTERRUPT_ARM_MAILBOX) +#define FIQ_ARM_DOORBELL_0 (FIQ_START+INTERRUPT_ARM_DOORBELL_0) +#define FIQ_ARM_DOORBELL_1 (FIQ_START+INTERRUPT_ARM_DOORBELL_1) +#define FIQ_VPU0_HALTED (FIQ_START+INTERRUPT_VPU0_HALTED) +#define FIQ_VPU1_HALTED (FIQ_START+INTERRUPT_VPU1_HALTED) +#define FIQ_ILLEGAL_TYPE0 (FIQ_START+INTERRUPT_ILLEGAL_TYPE0) +#define FIQ_ILLEGAL_TYPE1 (FIQ_START+INTERRUPT_ILLEGAL_TYPE1) +#define FIQ_PENDING1 (FIQ_START+INTERRUPT_PENDING1) +#define FIQ_PENDING2 (FIQ_START+INTERRUPT_PENDING2) + +#define FIQ_ARM_LOCAL_CNTPSIRQ (FIQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_CNTPSIRQ) +#define FIQ_ARM_LOCAL_CNTPNSIRQ (FIQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_CNTPNSIRQ) +#define FIQ_ARM_LOCAL_CNTHPIRQ (FIQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_CNTHPIRQ) +#define FIQ_ARM_LOCAL_CNTVIRQ (FIQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_CNTVIRQ) +#define FIQ_ARM_LOCAL_MAILBOX0 (FIQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_MAILBOX0) +#define FIQ_ARM_LOCAL_MAILBOX1 (FIQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_MAILBOX1) +#define FIQ_ARM_LOCAL_MAILBOX2 (FIQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_MAILBOX2) +#define FIQ_ARM_LOCAL_MAILBOX3 (FIQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_MAILBOX3) +#define FIQ_ARM_LOCAL_GPU_FAST (FIQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_GPU_FAST) +#define FIQ_ARM_LOCAL_PMU_FAST (FIQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_PMU_FAST) +#define FIQ_ARM_LOCAL_ZERO (FIQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_ZERO) +#define FIQ_ARM_LOCAL_TIMER (FIQ_ARMCTRL_START + INTERRUPT_ARM_LOCAL_TIMER) + +#define HARD_IRQS (128) +#define FIQ_IRQS (128) +#define GPIO_IRQ_START (HARD_IRQS + FIQ_IRQS) +#define GPIO_IRQS (32*5) +#define SPARE_ALLOC_IRQS 64 +#define BCM2708_ALLOC_IRQS (HARD_IRQS+FIQ_IRQS+GPIO_IRQS+SPARE_ALLOC_IRQS) +#define FREE_IRQS 128 +#define NR_IRQS (BCM2708_ALLOC_IRQS+FREE_IRQS) + +#endif /* _BCM2708_IRQS_H_ */ diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/memory.h raspilinux/arch/arm/mach-bcm2709/include/mach/memory.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/memory.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/memory.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,57 @@ +/* + * arch/arm/mach-bcm2708/include/mach/memory.h + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +/* Memory overview: + + [ARMcore] <--virtual addr--> + [ARMmmu] <--physical addr--> + [GERTmap] <--bus add--> + [VCperiph] + +*/ + +/* + * Physical DRAM offset. + */ +#define BCM_PLAT_PHYS_OFFSET UL(0x00000000) +#define VC_ARMMEM_OFFSET UL(0x00000000) /* offset in VC of ARM memory */ + +#ifdef CONFIG_BCM2708_NOL2CACHE + #define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */ +#else + #define _REAL_BUS_OFFSET UL(0x40000000) /* use L2 cache */ +#endif + +/* We're using the memory at 64M in the VideoCore for Linux - this adjustment + * will provide the offset into this area as well as setting the bits that + * stop the L1 and L2 cache from being used + * + * WARNING: this only works because the ARM is given memory at a fixed location + * (ARMMEM_OFFSET) + */ +#define BUS_OFFSET (VC_ARMMEM_OFFSET + _REAL_BUS_OFFSET) +#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) +#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) +#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) +#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - BCM_PLAT_PHYS_OFFSET)) + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/platform.h raspilinux/arch/arm/mach-bcm2709/include/mach/platform.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/platform.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/platform.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,227 @@ +/* + * arch/arm/mach-bcm2708/include/mach/platform.h + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _BCM2708_PLATFORM_H +#define _BCM2708_PLATFORM_H + + +/* macros to get at IO space when running virtually */ +#define IO_ADDRESS(x) (((x) & 0x00ffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) + +#define __io_address(n) IOMEM(IO_ADDRESS(n)) + + +/* + * SDRAM + */ +#define BCM2708_SDRAM_BASE 0x00000000 + +/* + * Logic expansion modules + * + */ + + +/* ------------------------------------------------------------------------ + * BCM2708 ARMCTRL Registers + * ------------------------------------------------------------------------ + */ + +#define HW_REGISTER_RW(addr) (addr) +#define HW_REGISTER_RO(addr) (addr) + +#include "arm_control.h" +#undef ARM_BASE + +/* + * Definitions and addresses for the ARM CONTROL logic + * This file is manually generated. + */ + +#define BCM2708_PERI_BASE 0x3F000000 +#define IC0_BASE (BCM2708_PERI_BASE + 0x2000) +#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */ +#define MPHI_BASE (BCM2708_PERI_BASE + 0x6000) /* Message -based Parallel Host Interface */ +#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ +#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ +#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ +#define PCM_CLOCK_BASE (BCM2708_PERI_BASE + 0x101098) /* PCM Clock */ +#define RNG_BASE (BCM2708_PERI_BASE + 0x104000) /* Hardware RNG */ +#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */ +#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ +#define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ +#define I2S_BASE (BCM2708_PERI_BASE + 0x203000) /* I2S */ +#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 */ +#define BSC0_BASE (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */ +#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */ +#define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */ +#define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */ +#define BSC1_BASE (BCM2708_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */ +#define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */ +#define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/ + +#define ARMCTRL_BASE (ARM_BASE + 0x000) +#define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ +#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ +#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ +#define ARMCTRL_0_BELL_BASE (ARMCTRL_0_SBM_BASE + 0x40) /* User 0 (ARM)'s Doorbell */ +#define ARMCTRL_0_MAIL0_BASE (ARMCTRL_0_SBM_BASE + 0x80) /* User 0 (ARM)'s Mailbox 0 */ + + +/* + * Interrupt assignments + */ + +#define ARM_IRQ1_BASE 0 +#define INTERRUPT_TIMER0 (ARM_IRQ1_BASE + 0) +#define INTERRUPT_TIMER1 (ARM_IRQ1_BASE + 1) +#define INTERRUPT_TIMER2 (ARM_IRQ1_BASE + 2) +#define INTERRUPT_TIMER3 (ARM_IRQ1_BASE + 3) +#define INTERRUPT_CODEC0 (ARM_IRQ1_BASE + 4) +#define INTERRUPT_CODEC1 (ARM_IRQ1_BASE + 5) +#define INTERRUPT_CODEC2 (ARM_IRQ1_BASE + 6) +#define INTERRUPT_VC_JPEG (ARM_IRQ1_BASE + 7) +#define INTERRUPT_ISP (ARM_IRQ1_BASE + 8) +#define INTERRUPT_VC_USB (ARM_IRQ1_BASE + 9) +#define INTERRUPT_VC_3D (ARM_IRQ1_BASE + 10) +#define INTERRUPT_TRANSPOSER (ARM_IRQ1_BASE + 11) +#define INTERRUPT_MULTICORESYNC0 (ARM_IRQ1_BASE + 12) +#define INTERRUPT_MULTICORESYNC1 (ARM_IRQ1_BASE + 13) +#define INTERRUPT_MULTICORESYNC2 (ARM_IRQ1_BASE + 14) +#define INTERRUPT_MULTICORESYNC3 (ARM_IRQ1_BASE + 15) +#define INTERRUPT_DMA0 (ARM_IRQ1_BASE + 16) +#define INTERRUPT_DMA1 (ARM_IRQ1_BASE + 17) +#define INTERRUPT_VC_DMA2 (ARM_IRQ1_BASE + 18) +#define INTERRUPT_VC_DMA3 (ARM_IRQ1_BASE + 19) +#define INTERRUPT_DMA4 (ARM_IRQ1_BASE + 20) +#define INTERRUPT_DMA5 (ARM_IRQ1_BASE + 21) +#define INTERRUPT_DMA6 (ARM_IRQ1_BASE + 22) +#define INTERRUPT_DMA7 (ARM_IRQ1_BASE + 23) +#define INTERRUPT_DMA8 (ARM_IRQ1_BASE + 24) +#define INTERRUPT_DMA9 (ARM_IRQ1_BASE + 25) +#define INTERRUPT_DMA10 (ARM_IRQ1_BASE + 26) +#define INTERRUPT_DMA11 (ARM_IRQ1_BASE + 27) +#define INTERRUPT_DMA12 (ARM_IRQ1_BASE + 28) +#define INTERRUPT_AUX (ARM_IRQ1_BASE + 29) +#define INTERRUPT_ARM (ARM_IRQ1_BASE + 30) +#define INTERRUPT_VPUDMA (ARM_IRQ1_BASE + 31) + +#define ARM_IRQ2_BASE 32 +#define INTERRUPT_HOSTPORT (ARM_IRQ2_BASE + 0) +#define INTERRUPT_VIDEOSCALER (ARM_IRQ2_BASE + 1) +#define INTERRUPT_CCP2TX (ARM_IRQ2_BASE + 2) +#define INTERRUPT_SDC (ARM_IRQ2_BASE + 3) +#define INTERRUPT_DSI0 (ARM_IRQ2_BASE + 4) +#define INTERRUPT_AVE (ARM_IRQ2_BASE + 5) +#define INTERRUPT_CAM0 (ARM_IRQ2_BASE + 6) +#define INTERRUPT_CAM1 (ARM_IRQ2_BASE + 7) +#define INTERRUPT_HDMI0 (ARM_IRQ2_BASE + 8) +#define INTERRUPT_HDMI1 (ARM_IRQ2_BASE + 9) +#define INTERRUPT_PIXELVALVE1 (ARM_IRQ2_BASE + 10) +#define INTERRUPT_I2CSPISLV (ARM_IRQ2_BASE + 11) +#define INTERRUPT_DSI1 (ARM_IRQ2_BASE + 12) +#define INTERRUPT_PWA0 (ARM_IRQ2_BASE + 13) +#define INTERRUPT_PWA1 (ARM_IRQ2_BASE + 14) +#define INTERRUPT_CPR (ARM_IRQ2_BASE + 15) +#define INTERRUPT_SMI (ARM_IRQ2_BASE + 16) +#define INTERRUPT_GPIO0 (ARM_IRQ2_BASE + 17) +#define INTERRUPT_GPIO1 (ARM_IRQ2_BASE + 18) +#define INTERRUPT_GPIO2 (ARM_IRQ2_BASE + 19) +#define INTERRUPT_GPIO3 (ARM_IRQ2_BASE + 20) +#define INTERRUPT_VC_I2C (ARM_IRQ2_BASE + 21) +#define INTERRUPT_VC_SPI (ARM_IRQ2_BASE + 22) +#define INTERRUPT_VC_I2SPCM (ARM_IRQ2_BASE + 23) +#define INTERRUPT_VC_SDIO (ARM_IRQ2_BASE + 24) +#define INTERRUPT_VC_UART (ARM_IRQ2_BASE + 25) +#define INTERRUPT_SLIMBUS (ARM_IRQ2_BASE + 26) +#define INTERRUPT_VEC (ARM_IRQ2_BASE + 27) +#define INTERRUPT_CPG (ARM_IRQ2_BASE + 28) +#define INTERRUPT_RNG (ARM_IRQ2_BASE + 29) +#define INTERRUPT_VC_ARASANSDIO (ARM_IRQ2_BASE + 30) +#define INTERRUPT_AVSPMON (ARM_IRQ2_BASE + 31) + +#define ARM_IRQ0_BASE 64 +#define INTERRUPT_ARM_TIMER (ARM_IRQ0_BASE + 0) +#define INTERRUPT_ARM_MAILBOX (ARM_IRQ0_BASE + 1) +#define INTERRUPT_ARM_DOORBELL_0 (ARM_IRQ0_BASE + 2) +#define INTERRUPT_ARM_DOORBELL_1 (ARM_IRQ0_BASE + 3) +#define INTERRUPT_VPU0_HALTED (ARM_IRQ0_BASE + 4) +#define INTERRUPT_VPU1_HALTED (ARM_IRQ0_BASE + 5) +#define INTERRUPT_ILLEGAL_TYPE0 (ARM_IRQ0_BASE + 6) +#define INTERRUPT_ILLEGAL_TYPE1 (ARM_IRQ0_BASE + 7) +#define INTERRUPT_PENDING1 (ARM_IRQ0_BASE + 8) +#define INTERRUPT_PENDING2 (ARM_IRQ0_BASE + 9) +#define INTERRUPT_JPEG (ARM_IRQ0_BASE + 10) +#define INTERRUPT_USB (ARM_IRQ0_BASE + 11) +#define INTERRUPT_3D (ARM_IRQ0_BASE + 12) +#define INTERRUPT_DMA2 (ARM_IRQ0_BASE + 13) +#define INTERRUPT_DMA3 (ARM_IRQ0_BASE + 14) +#define INTERRUPT_I2C (ARM_IRQ0_BASE + 15) +#define INTERRUPT_SPI (ARM_IRQ0_BASE + 16) +#define INTERRUPT_I2SPCM (ARM_IRQ0_BASE + 17) +#define INTERRUPT_SDIO (ARM_IRQ0_BASE + 18) +#define INTERRUPT_UART (ARM_IRQ0_BASE + 19) +#define INTERRUPT_ARASANSDIO (ARM_IRQ0_BASE + 20) + +#define ARM_IRQ_LOCAL_BASE 96 +#define INTERRUPT_ARM_LOCAL_CNTPSIRQ (ARM_IRQ_LOCAL_BASE + 0) +#define INTERRUPT_ARM_LOCAL_CNTPNSIRQ (ARM_IRQ_LOCAL_BASE + 1) +#define INTERRUPT_ARM_LOCAL_CNTHPIRQ (ARM_IRQ_LOCAL_BASE + 2) +#define INTERRUPT_ARM_LOCAL_CNTVIRQ (ARM_IRQ_LOCAL_BASE + 3) +#define INTERRUPT_ARM_LOCAL_MAILBOX0 (ARM_IRQ_LOCAL_BASE + 4) +#define INTERRUPT_ARM_LOCAL_MAILBOX1 (ARM_IRQ_LOCAL_BASE + 5) +#define INTERRUPT_ARM_LOCAL_MAILBOX2 (ARM_IRQ_LOCAL_BASE + 6) +#define INTERRUPT_ARM_LOCAL_MAILBOX3 (ARM_IRQ_LOCAL_BASE + 7) +#define INTERRUPT_ARM_LOCAL_GPU_FAST (ARM_IRQ_LOCAL_BASE + 8) +#define INTERRUPT_ARM_LOCAL_PMU_FAST (ARM_IRQ_LOCAL_BASE + 9) +#define INTERRUPT_ARM_LOCAL_ZERO (ARM_IRQ_LOCAL_BASE + 10) +#define INTERRUPT_ARM_LOCAL_TIMER (ARM_IRQ_LOCAL_BASE + 11) + +/* + * Watchdog + */ +#define PM_RSTC (PM_BASE+0x1c) +#define PM_RSTS (PM_BASE+0x20) +#define PM_WDOG (PM_BASE+0x24) + +#define PM_WDOG_RESET 0000000000 +#define PM_PASSWORD 0x5a000000 +#define PM_WDOG_TIME_SET 0x000fffff +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 + +#define PM_RSTS_HADPOR_SET 0x00001000 +#define PM_RSTS_HADSRH_SET 0x00000400 +#define PM_RSTS_HADSRF_SET 0x00000200 +#define PM_RSTS_HADSRQ_SET 0x00000100 +#define PM_RSTS_HADWRH_SET 0x00000040 +#define PM_RSTS_HADWRF_SET 0x00000020 +#define PM_RSTS_HADWRQ_SET 0x00000010 +#define PM_RSTS_HADDRH_SET 0x00000004 +#define PM_RSTS_HADDRF_SET 0x00000002 +#define PM_RSTS_HADDRQ_SET 0x00000001 + +#define UART0_CLOCK 3000000 + +#endif + +/* END */ diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/system.h raspilinux/arch/arm/mach-bcm2709/include/mach/system.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/system.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/system.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,38 @@ +/* + * arch/arm/mach-bcm2708/include/mach/system.h + * + * Copyright (C) 2010 Broadcom + * Copyright (C) 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +#include +#include +#include + +static inline void arch_idle(void) +{ + /* + * This should do all the clock switching + * and wait for interrupt tricks + */ + cpu_do_idle(); +} + +#endif diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/timex.h raspilinux/arch/arm/mach-bcm2709/include/mach/timex.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/timex.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/timex.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,23 @@ +/* + * arch/arm/mach-bcm2708/include/mach/timex.h + * + * BCM2708 sysem clock frequency + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define CLOCK_TICK_RATE (1000000) diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/uncompress.h raspilinux/arch/arm/mach-bcm2709/include/mach/uncompress.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/uncompress.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/uncompress.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,84 @@ +/* + * arch/arm/mach-bcn2708/include/mach/uncompress.h + * + * Copyright (C) 2010 Broadcom + * Copyright (C) 2003 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#define UART_BAUD 115200 + +#define BCM2708_UART_DR __io(UART0_BASE + UART01x_DR) +#define BCM2708_UART_FR __io(UART0_BASE + UART01x_FR) +#define BCM2708_UART_IBRD __io(UART0_BASE + UART011_IBRD) +#define BCM2708_UART_FBRD __io(UART0_BASE + UART011_FBRD) +#define BCM2708_UART_LCRH __io(UART0_BASE + UART011_LCRH) +#define BCM2708_UART_CR __io(UART0_BASE + UART011_CR) + +/* + * This does not append a newline + */ +static inline void putc(int c) +{ + while (__raw_readl(BCM2708_UART_FR) & UART01x_FR_TXFF) + barrier(); + + __raw_writel(c, BCM2708_UART_DR); +} + +static inline void flush(void) +{ + int fr; + + do { + fr = __raw_readl(BCM2708_UART_FR); + barrier(); + } while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE); +} + +static inline void arch_decomp_setup(void) +{ + int temp, div, rem, frac; + + temp = 16 * UART_BAUD; + div = UART0_CLOCK / temp; + rem = UART0_CLOCK % temp; + temp = (8 * rem) / UART_BAUD; + frac = (temp >> 1) + (temp & 1); + + /* Make sure the UART is disabled before we start */ + __raw_writel(0, BCM2708_UART_CR); + + /* Set the baud rate */ + __raw_writel(div, BCM2708_UART_IBRD); + __raw_writel(frac, BCM2708_UART_FBRD); + + /* Set the UART to 8n1, FIFO enabled */ + __raw_writel(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, BCM2708_UART_LCRH); + + /* Enable the UART */ + __raw_writel(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE, + BCM2708_UART_CR); +} + +/* + * nothing to do + */ +#define arch_decomp_wdog() diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/vc_support.h raspilinux/arch/arm/mach-bcm2709/include/mach/vc_support.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/vc_support.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/vc_support.h 2015-12-26 19:08:30.312744344 +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 '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/include/mach/vmalloc.h raspilinux/arch/arm/mach-bcm2709/include/mach/vmalloc.h --- linux-stable/arch/arm/mach-bcm2709/include/mach/vmalloc.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/include/mach/vmalloc.h 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,20 @@ +/* + * arch/arm/mach-bcm2708/include/mach/vmalloc.h + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#define VMALLOC_END (0xff000000) diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/Kconfig raspilinux/arch/arm/mach-bcm2709/Kconfig --- linux-stable/arch/arm/mach-bcm2709/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/Kconfig 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,42 @@ +menu "Broadcom BCM2709 Implementations" + depends on ARCH_BCM2709 + +config MACH_BCM2709 + bool "Broadcom BCM2709 Development Platform" + help + Include support for the Broadcom(R) BCM2709 platform. + +config BCM2709_DT + bool "BCM2709 Device Tree support" + depends on MACH_BCM2709 + default n + select USE_OF + select ARCH_REQUIRE_GPIOLIB + select PINCTRL + select PINCTRL_BCM2835 + help + Enable Device Tree support for BCM2709 + +config BCM2708_GPIO + bool "BCM2709 gpio support" + depends on MACH_BCM2709 + select ARCH_REQUIRE_GPIOLIB + default y + help + Include support for the Broadcom(R) BCM2709 gpio. + +config BCM2708_NOL2CACHE + bool "Videocore L2 cache disable" + depends on MACH_BCM2709 + default y + help + Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. + +config BCM2708_SPIDEV + bool "Bind spidev to SPI0 master" + depends on MACH_BCM2709 + depends on SPI + default y + help + Binds spidev driver to the SPI0 master +endmenu diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/Makefile raspilinux/arch/arm/mach-bcm2709/Makefile --- linux-stable/arch/arm/mach-bcm2709/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/Makefile 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,6 @@ +# +# Makefile for the linux kernel. +# + +obj-$(CONFIG_MACH_BCM2709) += bcm2709.o armctrl.o +obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/Makefile.boot raspilinux/arch/arm/mach-bcm2709/Makefile.boot --- linux-stable/arch/arm/mach-bcm2709/Makefile.boot 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/Makefile.boot 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,3 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00800000 diff -Nur '--exclude=.git' linux-stable/arch/arm/mach-bcm2709/vc_support.c raspilinux/arch/arm/mach-bcm2709/vc_support.c --- linux-stable/arch/arm/mach-bcm2709/vc_support.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/arch/arm/mach-bcm2709/vc_support.c 2015-12-26 19:08:30.312744344 +0100 @@ -0,0 +1,318 @@ +/* + * vc_support.c + * + * Created on: 25 Nov 2012 + * Author: Simon + */ + +#include +#include + +#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 '--exclude=.git' linux-stable/arch/arm/Makefile raspilinux/arch/arm/Makefile --- linux-stable/arch/arm/Makefile 2015-12-26 20:44:59.612056270 +0100 +++ raspilinux/arch/arm/Makefile 2015-12-26 19:08:30.224752550 +0100 @@ -150,6 +150,8 @@ # Machine directory name. This list is sorted alphanumerically # by CONFIG_* macro name. +machine-$(CONFIG_ARCH_BCM2708) += bcm2708 +machine-$(CONFIG_ARCH_BCM2709) += bcm2709 machine-$(CONFIG_ARCH_ALPINE) += alpine machine-$(CONFIG_ARCH_AT91) += at91 machine-$(CONFIG_ARCH_AXXIA) += axxia diff -Nur '--exclude=.git' linux-stable/arch/arm/mm/Kconfig raspilinux/arch/arm/mm/Kconfig --- linux-stable/arch/arm/mm/Kconfig 2015-12-26 20:44:59.788040049 +0100 +++ raspilinux/arch/arm/mm/Kconfig 2015-12-26 19:08:30.408735392 +0100 @@ -358,7 +358,7 @@ # ARMv6 config CPU_V6 - bool "Support ARM V6 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX) + bool "Support ARM V6 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || MACH_BCM2708) select CPU_32v6 select CPU_ABRT_EV6 select CPU_CACHE_V6 diff -Nur '--exclude=.git' linux-stable/arch/arm/mm/proc-v6.S raspilinux/arch/arm/mm/proc-v6.S --- linux-stable/arch/arm/mm/proc-v6.S 2015-12-26 20:38:43.026763928 +0100 +++ raspilinux/arch/arm/mm/proc-v6.S 2015-12-26 19:08:30.412735019 +0100 @@ -73,10 +73,19 @@ * * IRQs are already disabled. */ + +/* See jira SW-5991 for details of this workaround */ ENTRY(cpu_v6_do_idle) - mov r1, #0 - mcr p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode - mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt + .align 5 + mov r1, #2 +1: subs r1, #1 + nop + mcreq p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode + mcreq p15, 0, r1, c7, c0, 4 @ wait for interrupt + nop + nop + nop + bne 1b ret lr ENTRY(cpu_v6_dcache_clean_area) diff -Nur '--exclude=.git' linux-stable/arch/arm/mm/proc-v7.S raspilinux/arch/arm/mm/proc-v7.S --- linux-stable/arch/arm/mm/proc-v7.S 2015-12-26 20:44:59.792039681 +0100 +++ raspilinux/arch/arm/mm/proc-v7.S 2015-12-26 19:08:30.412735019 +0100 @@ -460,6 +460,7 @@ orr r0, r0, r6 @ set them THUMB( orr r0, r0, #1 << 30 ) @ Thumb exceptions ret lr @ return to head.S:__ret + .space 256 ENDPROC(__v7_setup) .align 2 diff -Nur '--exclude=.git' linux-stable/arch/arm/tools/mach-types raspilinux/arch/arm/tools/mach-types --- linux-stable/arch/arm/tools/mach-types 2015-12-26 20:38:43.042762454 +0100 +++ raspilinux/arch/arm/tools/mach-types 2015-12-26 19:08:30.420734273 +0100 @@ -522,6 +522,8 @@ prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 paz00 MACH_PAZ00 PAZ00 3128 acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129 +bcm2708 MACH_BCM2708 BCM2708 3138 +bcm2709 MACH_BCM2709 BCM2709 3139 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 '--exclude=.git' linux-stable/Documentation/ABI/stable/sysfs-driver-w1_ds28ea00 raspilinux/Documentation/ABI/stable/sysfs-driver-w1_ds28ea00 --- linux-stable/Documentation/ABI/stable/sysfs-driver-w1_ds28ea00 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/Documentation/ABI/stable/sysfs-driver-w1_ds28ea00 2015-12-26 19:08:29.968776422 +0100 @@ -0,0 +1,6 @@ +What: /sys/bus/w1/devices/.../w1_seq +Date: Apr 2015 +Contact: Matt Campbell +Description: Support for the DS28EA00 chain sequence function + see Documentation/w1/slaves/w1_therm for detailed information +Users: any user space application which wants to communicate with DS28EA00 diff -Nur '--exclude=.git' linux-stable/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt raspilinux/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt --- linux-stable/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt 2015-12-26 20:38:42.362825115 +0100 +++ raspilinux/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt 2015-12-26 19:08:30.028770827 +0100 @@ -48,8 +48,8 @@ bcm2835_i2s: i2s@7e203000 { compatible = "brcm,bcm2835-i2s"; - reg = < 0x7e203000 0x20>, - < 0x7e101098 0x02>; + reg = < 0x7e203000 0x24>, + < 0x7e101098 0x08>; dmas = <&dma 2>, <&dma 3>; diff -Nur '--exclude=.git' linux-stable/Documentation/devicetree/bindings/input/touchscreen/focaltech-ft6236.txt raspilinux/Documentation/devicetree/bindings/input/touchscreen/focaltech-ft6236.txt --- linux-stable/Documentation/devicetree/bindings/input/touchscreen/focaltech-ft6236.txt 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/Documentation/devicetree/bindings/input/touchscreen/focaltech-ft6236.txt 2015-12-26 19:08:30.036770081 +0100 @@ -0,0 +1,35 @@ +* FocalTech FT6236 I2C touchscreen controller + +Required properties: + - compatible : "focaltech,ft6236" + - reg : I2C slave address of the chip (0x38) + - interrupt-parent : a phandle pointing to the interrupt controller + serving the interrupt for this chip + - interrupts : interrupt specification for the touch controller + interrupt + - reset-gpios : GPIO specification for the RSTN input + - touchscreen-size-x : horizontal resolution of touchscreen (in pixels) + - touchscreen-size-y : vertical resolution of touchscreen (in pixels) + +Optional properties: + - touchscreen-fuzz-x : horizontal noise value of the absolute input + device (in pixels) + - touchscreen-fuzz-y : vertical noise value of the absolute input + device (in pixels) + - touchscreen-inverted-x : X axis is inverted (boolean) + - touchscreen-inverted-y : Y axis is inverted (boolean) + - touchscreen-swapped-x-y: X and Y axis are swapped (boolean) + Swapping is done after inverting the axis + +Example: + + ft6x06@38 { + compatible = "focaltech,ft6236"; + reg = <0x38>; + interrupt-parent = <&gpio>; + interrupts = <23 2>; + touchscreen-size-x = <320>; + touchscreen-size-y = <480>; + touchscreen-inverted-x; + touchscreen-swapped-x-y; + }; diff -Nur '--exclude=.git' linux-stable/Documentation/devicetree/bindings/misc/brcm,bcm2835-smi-dev.txt raspilinux/Documentation/devicetree/bindings/misc/brcm,bcm2835-smi-dev.txt --- linux-stable/Documentation/devicetree/bindings/misc/brcm,bcm2835-smi-dev.txt 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/Documentation/devicetree/bindings/misc/brcm,bcm2835-smi-dev.txt 2015-12-26 19:08:30.044769335 +0100 @@ -0,0 +1,17 @@ +* Broadcom BCM2835 SMI character device driver. + +SMI or secondary memory interface is a peripheral specific to certain Broadcom +SOCs, and is helpful for talking to things like parallel-interface displays +and NAND flashes (in fact, most things with a parallel register interface). + +This driver adds a character device which provides a user-space interface to +an instance of the SMI driver. + +Required properties: +- compatible: "brcm,bcm2835-smi-dev" +- smi_handle: a phandle to the smi node. + +Optional properties: +- None. + + diff -Nur '--exclude=.git' linux-stable/Documentation/devicetree/bindings/misc/brcm,bcm2835-smi.txt raspilinux/Documentation/devicetree/bindings/misc/brcm,bcm2835-smi.txt --- linux-stable/Documentation/devicetree/bindings/misc/brcm,bcm2835-smi.txt 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/Documentation/devicetree/bindings/misc/brcm,bcm2835-smi.txt 2015-12-26 19:08:30.044769335 +0100 @@ -0,0 +1,48 @@ +* Broadcom BCM2835 SMI driver. + +SMI or secondary memory interface is a peripheral specific to certain Broadcom +SOCs, and is helpful for talking to things like parallel-interface displays +and NAND flashes (in fact, most things with a parallel register interface). + +Required properties: +- compatible: "brcm,bcm2835-smi" +- reg: Should contain location and length of SMI registers and SMI clkman regs +- interrupts: *the* SMI interrupt. +- pinctrl-names: should be "default". +- pinctrl-0: the phandle of the gpio pin node. +- brcm,smi-clock-source: the clock source for clkman +- brcm,smi-clock-divisor: the integer clock divisor for clkman +- dmas: the dma controller phandle and the DREQ number (4 on a 2835) +- dma-names: the name used by the driver to request its channel. + Should be "rx-tx". + +Optional properties: +- None. + +Examples: + +8 data pin configuration: + +smi: smi@7e600000 { + compatible = "brcm,bcm2835-smi"; + reg = <0x7e600000 0x44>, <0x7e1010b0 0x8>; + interrupts = <2 16>; + pinctrl-names = "default"; + pinctrl-0 = <&smi_pins>; + brcm,smi-clock-source = <6>; + brcm,smi-clock-divisor = <4>; + dmas = <&dma 4>; + dma-names = "rx-tx"; + + status = "okay"; +}; + +smi_pins: smi_pins { + brcm,pins = <2 3 4 5 6 7 8 9 10 11 12 13 14 15>; + /* Alt 1: SMI */ + brcm,function = <5 5 5 5 5 5 5 5 5 5 5 5 5 5>; + /* /CS, /WE and /OE are pulled high, as they are + generally active low signals */ + brcm,pull = <2 2 2 2 2 2 0 0 0 0 0 0 0 0>; +}; + diff -Nur '--exclude=.git' linux-stable/Documentation/devicetree/bindings/mtd/brcm,bcm2835-smi-nand.txt raspilinux/Documentation/devicetree/bindings/mtd/brcm,bcm2835-smi-nand.txt --- linux-stable/Documentation/devicetree/bindings/mtd/brcm,bcm2835-smi-nand.txt 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/Documentation/devicetree/bindings/mtd/brcm,bcm2835-smi-nand.txt 2015-12-26 19:08:30.044769335 +0100 @@ -0,0 +1,42 @@ +* BCM2835 SMI NAND flash + +This driver is a shim between the BCM2835 SMI driver (SMI is a peripheral for +talking to parallel register interfaces) and Linux's MTD layer. + +Required properties: +- compatible: "brcm,bcm2835-smi-nand" +- status: "okay" + +Optional properties: +- partition@n, where n is an integer from a consecutive sequence starting at 0 + - Difficult to store partition table on NAND device - normally put it + in the source code, kernel bootparams, or device tree (the best way!) + - Sub-properties: + - label: the partition name, as shown by mtdinfo /dev/mtd* + - reg: the size and offset of this partition. + - (optional) read-only: an empty property flagging as read only + +Example: + +nand: flash@0 { + compatible = "brcm,bcm2835-smi-nand"; + status = "okay"; + + partition@0 { + label = "stage2"; + // 128k + reg = <0 0x20000>; + read-only; + }; + partition@1 { + label = "firmware"; + // 16M + reg = <0x20000 0x1000000>; + read-only; + }; + partition@2 { + label = "root"; + // 2G + reg = <0x1020000 0x80000000>; + }; +}; \ No newline at end of file diff -Nur '--exclude=.git' linux-stable/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt raspilinux/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt --- linux-stable/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt 2015-12-26 20:38:42.434818480 +0100 +++ raspilinux/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt 2015-12-26 19:08:30.064767470 +0100 @@ -16,8 +16,8 @@ bcm2835_i2s: i2s@7e203000 { compatible = "brcm,bcm2835-i2s"; - reg = <0x7e203000 0x20>, - <0x7e101098 0x02>; + reg = <0x7e203000 0x24>, + <0x7e101098 0x08>; dmas = <&dma 2>, <&dma 3>; diff -Nur '--exclude=.git' linux-stable/Documentation/devicetree/bindings/vendor-prefixes.txt raspilinux/Documentation/devicetree/bindings/vendor-prefixes.txt --- linux-stable/Documentation/devicetree/bindings/vendor-prefixes.txt 2015-12-26 20:44:59.532063643 +0100 +++ raspilinux/Documentation/devicetree/bindings/vendor-prefixes.txt 2015-12-26 19:08:30.072766724 +0100 @@ -76,6 +76,7 @@ excito Excito fcs Fairchild Semiconductor firefly Firefly +focaltech FocalTech Systems Co.,Ltd fsl Freescale Semiconductor GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc. gef GE Fanuc Intelligent Platforms Embedded Systems, Inc. diff -Nur '--exclude=.git' linux-stable/Documentation/video4linux/bcm2835-v4l2.txt raspilinux/Documentation/video4linux/bcm2835-v4l2.txt --- linux-stable/Documentation/video4linux/bcm2835-v4l2.txt 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/Documentation/video4linux/bcm2835-v4l2.txt 2015-12-26 19:08:30.184756280 +0100 @@ -0,0 +1,60 @@ + +BCM2835 (aka Raspberry Pi) V4L2 driver +====================================== + +1. Copyright +============ + +Copyright © 2013 Raspberry Pi (Trading) Ltd. + +2. License +========== + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +3. Quick Start +============== + +You need a version 1.0 or later of v4l2-ctl, available from: + git://git.linuxtv.org/v4l-utils.git + +$ sudo modprobe bcm2835-v4l2 + +Turn on the overlay: + +$ v4l2-ctl --overlay=1 + +Turn off the overlay: + +$ v4l2-ctl --overlay=0 + +Set the capture format for video: + +$ v4l2-ctl --set-fmt-video=width=1920,height=1088,pixelformat=4 + +(Note: 1088 not 1080). + +Capture: + +$ v4l2-ctl --stream-mmap=3 --stream-count=100 --stream-to=somefile.h264 + +Stills capture: + +$ v4l2-ctl --set-fmt-video=width=2592,height=1944,pixelformat=3 +$ v4l2-ctl --stream-mmap=3 --stream-count=1 --stream-to=somefile.jpg + +List of available formats: + +$ v4l2-ctl --list-formats diff -Nur '--exclude=.git' linux-stable/Documentation/w1/slaves/w1_therm raspilinux/Documentation/w1/slaves/w1_therm --- linux-stable/Documentation/w1/slaves/w1_therm 2015-12-26 20:44:59.580059219 +0100 +++ raspilinux/Documentation/w1/slaves/w1_therm 2015-12-26 19:08:30.192755534 +0100 @@ -11,12 +11,14 @@ Description ----------- -w1_therm provides basic temperature conversion for ds18*20 devices. +w1_therm provides basic temperature conversion for ds18*20 devices, and the +ds28ea00 device. supported family codes: W1_THERM_DS18S20 0x10 W1_THERM_DS1822 0x22 W1_THERM_DS18B20 0x28 W1_THERM_DS1825 0x3B +W1_THERM_DS28EA00 0x42 Support is provided through the sysfs w1_slave file. Each open and read sequence will initiate a temperature conversion then provide two @@ -48,3 +50,10 @@ maximum current draw of 1.5mA and that a 5k pullup resistor is not sufficient. The strong pullup is designed to provide the additional current required. + +The DS28EA00 provides an additional two pins for implementing a sequence +detection algorithm. This feature allows you to determine the physical +location of the chip in the 1-wire bus without needing pre-existing +knowledge of the bus ordering. Support is provided through the sysfs +w1_seq file. The file will contain a single line with an integer value +representing the device index in the bus starting at 0. diff -Nur '--exclude=.git' linux-stable/drivers/char/broadcom/bcm2835-gpiomem.c raspilinux/drivers/char/broadcom/bcm2835-gpiomem.c --- linux-stable/drivers/char/broadcom/bcm2835-gpiomem.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/char/broadcom/bcm2835-gpiomem.c 2015-12-26 19:08:31.148666386 +0100 @@ -0,0 +1,260 @@ +/** + * GPIO memory device driver + * + * Creates a chardev /dev/gpiomem which will provide user access to + * the BCM2835's GPIO registers when it is mmap()'d. + * No longer need root for user GPIO access, but without relaxing permissions + * on /dev/mem. + * + * Written by Luke Wren + * Copyright (c) 2015, Raspberry Pi (Trading) Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVICE_NAME "bcm2835-gpiomem" +#define DRIVER_NAME "gpiomem-bcm2835" +#define DEVICE_MINOR 0 + +struct bcm2835_gpiomem_instance { + unsigned long gpio_regs_phys; + struct device *dev; +}; + +static struct cdev bcm2835_gpiomem_cdev; +static dev_t bcm2835_gpiomem_devid; +static struct class *bcm2835_gpiomem_class; +static struct device *bcm2835_gpiomem_dev; +static struct bcm2835_gpiomem_instance *inst; + + +/**************************************************************************** +* +* GPIO mem chardev file ops +* +***************************************************************************/ + +static int bcm2835_gpiomem_open(struct inode *inode, struct file *file) +{ + int dev = iminor(inode); + int ret = 0; + + dev_info(inst->dev, "gpiomem device opened."); + + if (dev != DEVICE_MINOR) { + dev_err(inst->dev, "Unknown minor device: %d", dev); + ret = -ENXIO; + } + return ret; +} + +static int bcm2835_gpiomem_release(struct inode *inode, struct file *file) +{ + int dev = iminor(inode); + int ret = 0; + + if (dev != DEVICE_MINOR) { + dev_err(inst->dev, "Unknown minor device %d", dev); + ret = -ENXIO; + } + return ret; +} + +static const struct vm_operations_struct bcm2835_gpiomem_vm_ops = { +#ifdef CONFIG_HAVE_IOREMAP_PROT + .access = generic_access_phys +#endif +}; + +static int bcm2835_gpiomem_mmap(struct file *file, struct vm_area_struct *vma) +{ + /* Ignore what the user says - they're getting the GPIO regs + whether they like it or not! */ + unsigned long gpio_page = inst->gpio_regs_phys >> PAGE_SHIFT; + + vma->vm_page_prot = phys_mem_access_prot(file, gpio_page, + PAGE_SIZE, + vma->vm_page_prot); + vma->vm_ops = &bcm2835_gpiomem_vm_ops; + if (remap_pfn_range(vma, vma->vm_start, + gpio_page, + PAGE_SIZE, + vma->vm_page_prot)) { + return -EAGAIN; + } + return 0; +} + +static const struct file_operations +bcm2835_gpiomem_fops = { + .owner = THIS_MODULE, + .open = bcm2835_gpiomem_open, + .release = bcm2835_gpiomem_release, + .mmap = bcm2835_gpiomem_mmap, +}; + + + /**************************************************************************** +* +* Probe and remove functions +* +***************************************************************************/ + + +static int bcm2835_gpiomem_probe(struct platform_device *pdev) +{ + int err; + void *ptr_err; + struct device *dev = &pdev->dev; + struct resource *ioresource; + + /* Allocate buffers and instance data */ + + inst = kzalloc(sizeof(struct bcm2835_gpiomem_instance), GFP_KERNEL); + + if (!inst) { + err = -ENOMEM; + goto failed_inst_alloc; + } + + inst->dev = dev; + + ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (ioresource) { + inst->gpio_regs_phys = ioresource->start; + } else { + dev_err(inst->dev, "failed to get IO resource"); + err = -ENOENT; + goto failed_get_resource; + } + + /* Create character device entries */ + + err = alloc_chrdev_region(&bcm2835_gpiomem_devid, + DEVICE_MINOR, 1, DEVICE_NAME); + if (err != 0) { + dev_err(inst->dev, "unable to allocate device number"); + goto failed_alloc_chrdev; + } + cdev_init(&bcm2835_gpiomem_cdev, &bcm2835_gpiomem_fops); + bcm2835_gpiomem_cdev.owner = THIS_MODULE; + err = cdev_add(&bcm2835_gpiomem_cdev, bcm2835_gpiomem_devid, 1); + if (err != 0) { + dev_err(inst->dev, "unable to register device"); + goto failed_cdev_add; + } + + /* Create sysfs entries */ + + bcm2835_gpiomem_class = class_create(THIS_MODULE, DEVICE_NAME); + ptr_err = bcm2835_gpiomem_class; + if (IS_ERR(ptr_err)) + goto failed_class_create; + + bcm2835_gpiomem_dev = device_create(bcm2835_gpiomem_class, NULL, + bcm2835_gpiomem_devid, NULL, + "gpiomem"); + ptr_err = bcm2835_gpiomem_dev; + if (IS_ERR(ptr_err)) + goto failed_device_create; + + dev_info(inst->dev, "Initialised: Registers at 0x%08lx", + inst->gpio_regs_phys); + + return 0; + +failed_device_create: + class_destroy(bcm2835_gpiomem_class); +failed_class_create: + cdev_del(&bcm2835_gpiomem_cdev); + err = PTR_ERR(ptr_err); +failed_cdev_add: + unregister_chrdev_region(bcm2835_gpiomem_devid, 1); +failed_alloc_chrdev: +failed_get_resource: + kfree(inst); +failed_inst_alloc: + dev_err(inst->dev, "could not load bcm2835_gpiomem"); + return err; +} + +static int bcm2835_gpiomem_remove(struct platform_device *pdev) +{ + struct device *dev = inst->dev; + + kfree(inst); + device_destroy(bcm2835_gpiomem_class, bcm2835_gpiomem_devid); + class_destroy(bcm2835_gpiomem_class); + cdev_del(&bcm2835_gpiomem_cdev); + unregister_chrdev_region(bcm2835_gpiomem_devid, 1); + + dev_info(dev, "GPIO mem driver removed - OK"); + return 0; +} + + /**************************************************************************** +* +* Register the driver with device tree +* +***************************************************************************/ + +static const struct of_device_id bcm2835_gpiomem_of_match[] = { + {.compatible = "brcm,bcm2835-gpiomem",}, + { /* sentinel */ }, +}; + +MODULE_DEVICE_TABLE(of, bcm2835_gpiomem_of_match); + +static struct platform_driver bcm2835_gpiomem_driver = { + .probe = bcm2835_gpiomem_probe, + .remove = bcm2835_gpiomem_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = bcm2835_gpiomem_of_match, + }, +}; + +module_platform_driver(bcm2835_gpiomem_driver); + +MODULE_ALIAS("platform:gpiomem-bcm2835"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("gpiomem driver for accessing GPIO from userspace"); +MODULE_AUTHOR("Luke Wren "); diff -Nur '--exclude=.git' linux-stable/drivers/char/broadcom/bcm2835_smi_dev.c raspilinux/drivers/char/broadcom/bcm2835_smi_dev.c --- linux-stable/drivers/char/broadcom/bcm2835_smi_dev.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/char/broadcom/bcm2835_smi_dev.c 2015-12-26 19:08:31.148666386 +0100 @@ -0,0 +1,402 @@ +/** + * Character device driver for Broadcom Secondary Memory Interface + * + * Written by Luke Wren + * Copyright (c) 2015, Raspberry Pi (Trading) Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DEVICE_NAME "bcm2835-smi-dev" +#define DRIVER_NAME "smi-dev-bcm2835" +#define DEVICE_MINOR 0 + +static struct cdev bcm2835_smi_cdev; +static dev_t bcm2835_smi_devid; +static struct class *bcm2835_smi_class; +static struct device *bcm2835_smi_dev; + +struct bcm2835_smi_dev_instance { + struct device *dev; +}; + +static struct bcm2835_smi_instance *smi_inst; +static struct bcm2835_smi_dev_instance *inst; + +static const char *const ioctl_names[] = { + "READ_SETTINGS", + "WRITE_SETTINGS", + "ADDRESS" +}; + +/**************************************************************************** +* +* SMI chardev file ops +* +***************************************************************************/ +static long +bcm2835_smi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret = 0; + + dev_info(inst->dev, "serving ioctl..."); + + switch (cmd) { + case BCM2835_SMI_IOC_GET_SETTINGS:{ + struct smi_settings *settings; + + dev_info(inst->dev, "Reading SMI settings to user."); + settings = bcm2835_smi_get_settings_from_regs(smi_inst); + if (copy_to_user((void *)arg, settings, + sizeof(struct smi_settings))) + dev_err(inst->dev, "settings copy failed."); + break; + } + case BCM2835_SMI_IOC_WRITE_SETTINGS:{ + struct smi_settings *settings; + + dev_info(inst->dev, "Setting user's SMI settings."); + settings = bcm2835_smi_get_settings_from_regs(smi_inst); + if (copy_from_user(settings, (void *)arg, + sizeof(struct smi_settings))) + dev_err(inst->dev, "settings copy failed."); + else + bcm2835_smi_set_regs_from_settings(smi_inst); + break; + } + case BCM2835_SMI_IOC_ADDRESS: + dev_info(inst->dev, "SMI address set: 0x%02x", (int)arg); + bcm2835_smi_set_address(smi_inst, arg); + break; + default: + dev_err(inst->dev, "invalid ioctl cmd: %d", cmd); + ret = -ENOTTY; + break; + } + + return ret; +} + +static int bcm2835_smi_open(struct inode *inode, struct file *file) +{ + int dev = iminor(inode); + + dev_dbg(inst->dev, "SMI device opened."); + + if (dev != DEVICE_MINOR) { + dev_err(inst->dev, + "bcm2835_smi_release: Unknown minor device: %d", + dev); + return -ENXIO; + } + + return 0; +} + +static int bcm2835_smi_release(struct inode *inode, struct file *file) +{ + int dev = iminor(inode); + + if (dev != DEVICE_MINOR) { + dev_err(inst->dev, + "bcm2835_smi_release: Unknown minor device %d", dev); + return -ENXIO; + } + + return 0; +} + +static ssize_t dma_bounce_user( + enum dma_transfer_direction dma_dir, + char __user *user_ptr, + size_t count, + struct bcm2835_smi_bounce_info *bounce) +{ + int chunk_size; + int chunk_no = 0; + int count_left = count; + + while (count_left) { + int rv; + void *buf; + + /* Wait for current chunk to complete: */ + if (down_timeout(&bounce->callback_sem, + msecs_to_jiffies(1000))) { + dev_err(inst->dev, "DMA bounce timed out"); + count -= (count_left); + break; + } + + if (bounce->callback_sem.count >= DMA_BOUNCE_BUFFER_COUNT - 1) + dev_err(inst->dev, "WARNING: Ring buffer overflow"); + chunk_size = count_left > DMA_BOUNCE_BUFFER_SIZE ? + DMA_BOUNCE_BUFFER_SIZE : count_left; + buf = bounce->buffer[chunk_no % DMA_BOUNCE_BUFFER_COUNT]; + if (dma_dir == DMA_DEV_TO_MEM) + rv = copy_to_user(user_ptr, buf, chunk_size); + else + rv = copy_from_user(buf, user_ptr, chunk_size); + if (rv) + dev_err(inst->dev, "copy_*_user() failed!: %d", rv); + user_ptr += chunk_size; + count_left -= chunk_size; + chunk_no++; + } + return count; +} + +static ssize_t +bcm2835_read_file(struct file *f, char __user *user_ptr, + size_t count, loff_t *offs) +{ + int odd_bytes; + + dev_dbg(inst->dev, "User reading %d bytes from SMI.", count); + /* We don't want to DMA a number of bytes % 4 != 0 (32 bit FIFO) */ + if (count > DMA_THRESHOLD_BYTES) + odd_bytes = count & 0x3; + else + odd_bytes = count; + count -= odd_bytes; + if (count) { + struct bcm2835_smi_bounce_info *bounce; + + count = bcm2835_smi_user_dma(smi_inst, + DMA_DEV_TO_MEM, user_ptr, count, + &bounce); + if (count) + count = dma_bounce_user(DMA_DEV_TO_MEM, user_ptr, + count, bounce); + } + if (odd_bytes) { + /* Read from FIFO directly if not using DMA */ + uint8_t buf[DMA_THRESHOLD_BYTES]; + + bcm2835_smi_read_buf(smi_inst, buf, odd_bytes); + if (copy_to_user(user_ptr, buf, odd_bytes)) + dev_err(inst->dev, "copy_to_user() failed."); + count += odd_bytes; + + } + return count; +} + +static ssize_t +bcm2835_write_file(struct file *f, const char __user *user_ptr, + size_t count, loff_t *offs) +{ + int odd_bytes; + + dev_dbg(inst->dev, "User writing %d bytes to SMI.", count); + if (count > DMA_THRESHOLD_BYTES) + odd_bytes = count & 0x3; + else + odd_bytes = count; + count -= odd_bytes; + if (count) { + struct bcm2835_smi_bounce_info *bounce; + + count = bcm2835_smi_user_dma(smi_inst, + DMA_MEM_TO_DEV, (char __user *)user_ptr, count, + &bounce); + if (count) + count = dma_bounce_user(DMA_MEM_TO_DEV, + (char __user *)user_ptr, + count, bounce); + } + if (odd_bytes) { + uint8_t buf[DMA_THRESHOLD_BYTES]; + + if (copy_from_user(buf, user_ptr, odd_bytes)) + dev_err(inst->dev, "copy_from_user() failed."); + else + bcm2835_smi_write_buf(smi_inst, buf, odd_bytes); + count += odd_bytes; + } + return count; +} + +static const struct file_operations +bcm2835_smi_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = bcm2835_smi_ioctl, + .open = bcm2835_smi_open, + .release = bcm2835_smi_release, + .read = bcm2835_read_file, + .write = bcm2835_write_file, +}; + + +/**************************************************************************** +* +* bcm2835_smi_probe - called when the driver is loaded. +* +***************************************************************************/ + +static int bcm2835_smi_dev_probe(struct platform_device *pdev) +{ + int err; + void *ptr_err; + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node, *smi_node; + + if (!node) { + dev_err(dev, "No device tree node supplied!"); + return -EINVAL; + } + + smi_node = of_parse_phandle(node, "smi_handle", 0); + + if (!smi_node) { + dev_err(dev, "No such property: smi_handle"); + return -ENXIO; + } + + smi_inst = bcm2835_smi_get(smi_node); + + if (!smi_inst) + return -EPROBE_DEFER; + + /* Allocate buffers and instance data */ + + inst = devm_kzalloc(dev, sizeof(*inst), GFP_KERNEL); + + if (!inst) + return -ENOMEM; + + inst->dev = dev; + + /* Create character device entries */ + + err = alloc_chrdev_region(&bcm2835_smi_devid, + DEVICE_MINOR, 1, DEVICE_NAME); + if (err != 0) { + dev_err(inst->dev, "unable to allocate device number"); + return -ENOMEM; + } + cdev_init(&bcm2835_smi_cdev, &bcm2835_smi_fops); + bcm2835_smi_cdev.owner = THIS_MODULE; + err = cdev_add(&bcm2835_smi_cdev, bcm2835_smi_devid, 1); + if (err != 0) { + dev_err(inst->dev, "unable to register device"); + err = -ENOMEM; + goto failed_cdev_add; + } + + /* Create sysfs entries */ + + bcm2835_smi_class = class_create(THIS_MODULE, DEVICE_NAME); + ptr_err = bcm2835_smi_class; + if (IS_ERR(ptr_err)) + goto failed_class_create; + + bcm2835_smi_dev = device_create(bcm2835_smi_class, NULL, + bcm2835_smi_devid, NULL, + "smi"); + ptr_err = bcm2835_smi_dev; + if (IS_ERR(ptr_err)) + goto failed_device_create; + + dev_info(inst->dev, "initialised"); + + return 0; + +failed_device_create: + class_destroy(bcm2835_smi_class); +failed_class_create: + cdev_del(&bcm2835_smi_cdev); + err = PTR_ERR(ptr_err); +failed_cdev_add: + unregister_chrdev_region(bcm2835_smi_devid, 1); + dev_err(dev, "could not load bcm2835_smi_dev"); + return err; +} + +/**************************************************************************** +* +* bcm2835_smi_remove - called when the driver is unloaded. +* +***************************************************************************/ + +static int bcm2835_smi_dev_remove(struct platform_device *pdev) +{ + device_destroy(bcm2835_smi_class, bcm2835_smi_devid); + class_destroy(bcm2835_smi_class); + cdev_del(&bcm2835_smi_cdev); + unregister_chrdev_region(bcm2835_smi_devid, 1); + + dev_info(inst->dev, "SMI character dev removed - OK"); + return 0; +} + +/**************************************************************************** +* +* Register the driver with device tree +* +***************************************************************************/ + +static const struct of_device_id bcm2835_smi_dev_of_match[] = { + {.compatible = "brcm,bcm2835-smi-dev",}, + { /* sentinel */ }, +}; + +MODULE_DEVICE_TABLE(of, bcm2835_smi_dev_of_match); + +static struct platform_driver bcm2835_smi_dev_driver = { + .probe = bcm2835_smi_dev_probe, + .remove = bcm2835_smi_dev_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = bcm2835_smi_dev_of_match, + }, +}; + +module_platform_driver(bcm2835_smi_dev_driver); + +MODULE_ALIAS("platform:smi-dev-bcm2835"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION( + "Character device driver for BCM2835's secondary memory interface"); +MODULE_AUTHOR("Luke Wren "); diff -Nur '--exclude=.git' linux-stable/drivers/char/broadcom/Kconfig raspilinux/drivers/char/broadcom/Kconfig --- linux-stable/drivers/char/broadcom/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/char/broadcom/Kconfig 2015-12-26 19:08:31.148666386 +0100 @@ -0,0 +1,57 @@ +# +# Broadcom char driver config +# + +menuconfig BRCM_CHAR_DRIVERS + bool "Broadcom Char Drivers" + help + Broadcom's char drivers + +if BRCM_CHAR_DRIVERS + +config BCM_VC_CMA + bool "Videocore CMA" + depends on CMA && BCM2708_VCHIQ + default n + help + Helper for videocore CMA access. + +config BCM2708_VCMEM + bool "Videocore Memory" + default y + help + Helper for videocore memory access and total size allocation. + +config BCM_VCIO + tristate "Mailbox userspace access" + depends on BCM2835_MBOX + help + Gives access to the mailbox property channel from userspace. + +endif + +config BCM_VC_SM + bool "VMCS Shared Memory" + depends on BCM2708_VCHIQ + select BCM2708_VCMEM + default n + help + Support for the VC shared memory on the Broadcom reference + design. Uses the VCHIQ stack. + +config BCM2835_DEVGPIOMEM + tristate "/dev/gpiomem rootless GPIO access via mmap() on the BCM2835" + default m + help + Provides users with root-free access to the GPIO registers + on the 2835. Calling mmap(/dev/gpiomem) will map the GPIO + register page to the user's pointer. + +config BCM2835_SMI_DEV + tristate "Character device driver for BCM2835 Secondary Memory Interface" + depends on (MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835) && BCM2835_SMI + default m + help + This driver provides a character device interface (ioctl + read/write) to + Broadcom's Secondary Memory interface. The low-level functionality is provided + by the SMI driver itself. diff -Nur '--exclude=.git' linux-stable/drivers/char/broadcom/Makefile raspilinux/drivers/char/broadcom/Makefile --- linux-stable/drivers/char/broadcom/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/char/broadcom/Makefile 2015-12-26 19:08:31.148666386 +0100 @@ -0,0 +1,7 @@ +obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ +obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o +obj-$(CONFIG_BCM_VCIO) += vcio.o +obj-$(CONFIG_BCM_VC_SM) += vc_sm/ + +obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o +obj-$(CONFIG_BCM2835_SMI_DEV) += bcm2835_smi_dev.o diff -Nur '--exclude=.git' linux-stable/drivers/char/broadcom/vc_cma/Makefile raspilinux/drivers/char/broadcom/vc_cma/Makefile --- linux-stable/drivers/char/broadcom/vc_cma/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/char/broadcom/vc_cma/Makefile 2015-12-26 19:08:31.148666386 +0100 @@ -0,0 +1,14 @@ +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 + +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 '--exclude=.git' linux-stable/drivers/char/broadcom/vc_cma/vc_cma.c raspilinux/drivers/char/broadcom/vc_cma/vc_cma.c --- linux-stable/drivers/char/broadcom/vc_cma/vc_cma.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/char/broadcom/vc_cma/vc_cma.c 2015-12-26 19:08:31.148666386 +0100 @@ -0,0 +1,1193 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vc_cma.h" + +#include "vchiq_util.h" +#include "vchiq_connected.h" +//#include "debug_sym.h" +//#include "vc_mem.h" + +#define DRIVER_NAME "vc-cma" + +#define LOG_DBG(fmt, ...) \ + if (vc_cma_debug) \ + printk(KERN_INFO fmt "\n", ##__VA_ARGS__) +#define LOG_INFO(fmt, ...) \ + printk(KERN_INFO fmt "\n", ##__VA_ARGS__) +#define LOG_ERR(fmt, ...) \ + printk(KERN_ERR fmt "\n", ##__VA_ARGS__) + +#define VC_CMA_FOURCC VCHIQ_MAKE_FOURCC('C', 'M', 'A', ' ') +#define VC_CMA_VERSION 2 + +#define VC_CMA_CHUNK_ORDER 6 /* 256K */ +#define VC_CMA_CHUNK_SIZE (4096 << VC_CMA_CHUNK_ORDER) +#define VC_CMA_MAX_PARAMS_PER_MSG \ + ((VCHIQ_MAX_MSG_SIZE - sizeof(unsigned short))/sizeof(unsigned short)) +#define VC_CMA_RESERVE_COUNT_MAX 16 + +#define PAGES_PER_CHUNK (VC_CMA_CHUNK_SIZE / PAGE_SIZE) + +#define VCADDR_TO_PHYSADDR(vcaddr) (mm_vc_mem_phys_addr + vcaddr) + +#define loud_error(...) \ + LOG_ERR("===== " __VA_ARGS__) + +enum { + VC_CMA_MSG_QUIT, + VC_CMA_MSG_OPEN, + VC_CMA_MSG_TICK, + VC_CMA_MSG_ALLOC, /* chunk count */ + VC_CMA_MSG_FREE, /* chunk, chunk, ... */ + VC_CMA_MSG_ALLOCATED, /* chunk, chunk, ... */ + VC_CMA_MSG_REQUEST_ALLOC, /* chunk count */ + VC_CMA_MSG_REQUEST_FREE, /* chunk count */ + VC_CMA_MSG_RESERVE, /* bytes lo, bytes hi */ + VC_CMA_MSG_UPDATE_RESERVE, + VC_CMA_MSG_MAX +}; + +struct cma_msg { + unsigned short type; + unsigned short params[VC_CMA_MAX_PARAMS_PER_MSG]; +}; + +struct vc_cma_reserve_user { + unsigned int pid; + unsigned int reserve; +}; + +/* Device (/dev) related variables */ +static dev_t vc_cma_devnum; +static struct class *vc_cma_class; +static struct cdev vc_cma_cdev; +static int vc_cma_inited; +static int vc_cma_debug; + +/* Proc entry */ +static struct proc_dir_entry *vc_cma_proc_entry; + +phys_addr_t vc_cma_base; +struct page *vc_cma_base_page; +unsigned int vc_cma_size; +EXPORT_SYMBOL(vc_cma_size); +unsigned int vc_cma_initial; +unsigned int vc_cma_chunks; +unsigned int vc_cma_chunks_used; +unsigned int vc_cma_chunks_reserved; + + +void *vc_cma_dma_alloc; +unsigned int vc_cma_dma_size; + +static int in_loud_error; + +unsigned int vc_cma_reserve_total; +unsigned int vc_cma_reserve_count; +struct vc_cma_reserve_user vc_cma_reserve_users[VC_CMA_RESERVE_COUNT_MAX]; +static DEFINE_SEMAPHORE(vc_cma_reserve_mutex); +static DEFINE_SEMAPHORE(vc_cma_worker_queue_push_mutex); + +static u64 vc_cma_dma_mask = DMA_BIT_MASK(32); +static struct platform_device vc_cma_device = { + .name = "vc-cma", + .id = 0, + .dev = { + .dma_mask = &vc_cma_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +static VCHIQ_INSTANCE_T cma_instance; +static VCHIQ_SERVICE_HANDLE_T cma_service; +static VCHIU_QUEUE_T cma_msg_queue; +static struct task_struct *cma_worker; + +static int vc_cma_set_reserve(unsigned int reserve, unsigned int pid); +static int vc_cma_alloc_chunks(int num_chunks, struct cma_msg *reply); +static VCHIQ_STATUS_T cma_service_callback(VCHIQ_REASON_T reason, + VCHIQ_HEADER_T * header, + VCHIQ_SERVICE_HANDLE_T service, + void *bulk_userdata); +static void send_vc_msg(unsigned short type, + unsigned short param1, unsigned short param2); +static bool send_worker_msg(VCHIQ_HEADER_T * msg); + +static int early_vc_cma_mem(char *p) +{ + unsigned int new_size; + printk(KERN_NOTICE "early_vc_cma_mem(%s)", p); + vc_cma_size = memparse(p, &p); + vc_cma_initial = vc_cma_size; + if (*p == '/') + vc_cma_size = memparse(p + 1, &p); + if (*p == '@') + vc_cma_base = memparse(p + 1, &p); + + new_size = (vc_cma_size - ((-vc_cma_base) & (VC_CMA_CHUNK_SIZE - 1))) + & ~(VC_CMA_CHUNK_SIZE - 1); + if (new_size > vc_cma_size) + vc_cma_size = 0; + vc_cma_initial = (vc_cma_initial + VC_CMA_CHUNK_SIZE - 1) + & ~(VC_CMA_CHUNK_SIZE - 1); + if (vc_cma_initial > vc_cma_size) + vc_cma_initial = vc_cma_size; + vc_cma_base = (vc_cma_base + VC_CMA_CHUNK_SIZE - 1) + & ~(VC_CMA_CHUNK_SIZE - 1); + + printk(KERN_NOTICE " -> initial %x, size %x, base %x", vc_cma_initial, + vc_cma_size, (unsigned int)vc_cma_base); + + return 0; +} + +early_param("vc-cma-mem", early_vc_cma_mem); + +void vc_cma_early_init(void) +{ + LOG_DBG("vc_cma_early_init - vc_cma_chunks = %d", vc_cma_chunks); + if (vc_cma_size) { + int rc = platform_device_register(&vc_cma_device); + LOG_DBG("platform_device_register -> %d", rc); + } +} + +void vc_cma_reserve(void) +{ + /* if vc_cma_size is set, then declare vc CMA area of the same + * size from the end of memory + */ + if (vc_cma_size) { + if (dma_declare_contiguous(&vc_cma_device.dev, vc_cma_size, + vc_cma_base, 0) == 0) { + if (!dev_get_cma_area(NULL)) { + /* There is no default CMA area - make this + the default */ + struct cma *vc_cma_area = dev_get_cma_area( + &vc_cma_device.dev); + dma_contiguous_set_default(vc_cma_area); + LOG_INFO("vc_cma_reserve - using vc_cma as " + "the default contiguous DMA area"); + } + } else { + LOG_ERR("vc_cma: dma_declare_contiguous(%x,%x) failed", + vc_cma_size, (unsigned int)vc_cma_base); + vc_cma_size = 0; + } + } + vc_cma_chunks = vc_cma_size / VC_CMA_CHUNK_SIZE; +} + +/**************************************************************************** +* +* vc_cma_open +* +***************************************************************************/ + +static int vc_cma_open(struct inode *inode, struct file *file) +{ + (void)inode; + (void)file; + + return 0; +} + +/**************************************************************************** +* +* vc_cma_release +* +***************************************************************************/ + +static int vc_cma_release(struct inode *inode, struct file *file) +{ + (void)inode; + (void)file; + + vc_cma_set_reserve(0, current->tgid); + + return 0; +} + +/**************************************************************************** +* +* vc_cma_ioctl +* +***************************************************************************/ + +static long vc_cma_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int rc = 0; + + (void)cmd; + (void)arg; + + switch (cmd) { + case VC_CMA_IOC_RESERVE: + rc = vc_cma_set_reserve((unsigned int)arg, current->tgid); + if (rc >= 0) + rc = 0; + break; + default: + LOG_ERR("vc-cma: Unknown ioctl %x", cmd); + return -ENOTTY; + } + + return rc; +} + +/**************************************************************************** +* +* File Operations for the driver. +* +***************************************************************************/ + +static const struct file_operations vc_cma_fops = { + .owner = THIS_MODULE, + .open = vc_cma_open, + .release = vc_cma_release, + .unlocked_ioctl = vc_cma_ioctl, +}; + +/**************************************************************************** +* +* vc_cma_proc_open +* +***************************************************************************/ + +static int vc_cma_show_info(struct seq_file *m, void *v) +{ + int i; + + seq_printf(m, "Videocore CMA:\n"); + seq_printf(m, " Base : %08x\n", (unsigned int)vc_cma_base); + seq_printf(m, " Length : %08x\n", vc_cma_size); + seq_printf(m, " Initial : %08x\n", vc_cma_initial); + seq_printf(m, " Chunk size : %08x\n", VC_CMA_CHUNK_SIZE); + seq_printf(m, " Chunks : %4d (%d bytes)\n", + (int)vc_cma_chunks, + (int)(vc_cma_chunks * VC_CMA_CHUNK_SIZE)); + seq_printf(m, " Used : %4d (%d bytes)\n", + (int)vc_cma_chunks_used, + (int)(vc_cma_chunks_used * VC_CMA_CHUNK_SIZE)); + seq_printf(m, " Reserved : %4d (%d bytes)\n", + (unsigned int)vc_cma_chunks_reserved, + (int)(vc_cma_chunks_reserved * VC_CMA_CHUNK_SIZE)); + + for (i = 0; i < vc_cma_reserve_count; i++) { + struct vc_cma_reserve_user *user = &vc_cma_reserve_users[i]; + seq_printf(m, " PID %5d: %d bytes\n", user->pid, + user->reserve); + } + seq_printf(m, " dma_alloc : %p (%d pages)\n", + vc_cma_dma_alloc ? page_address(vc_cma_dma_alloc) : 0, + vc_cma_dma_size); + + seq_printf(m, "\n"); + + return 0; +} + +static int vc_cma_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, vc_cma_show_info, NULL); +} + +/**************************************************************************** +* +* vc_cma_proc_write +* +***************************************************************************/ + +static int vc_cma_proc_write(struct file *file, + const char __user *buffer, + size_t size, loff_t *ppos) +{ + int rc = -EFAULT; + char input_str[20]; + + memset(input_str, 0, sizeof(input_str)); + + if (size > sizeof(input_str)) { + LOG_ERR("%s: input string length too long", __func__); + goto out; + } + + if (copy_from_user(input_str, buffer, size - 1)) { + LOG_ERR("%s: failed to get input string", __func__); + goto out; + } +#define ALLOC_STR "alloc" +#define FREE_STR "free" +#define DEBUG_STR "debug" +#define RESERVE_STR "reserve" +#define DMA_ALLOC_STR "dma_alloc" +#define DMA_FREE_STR "dma_free" + if (strncmp(input_str, ALLOC_STR, strlen(ALLOC_STR)) == 0) { + int alloc_size; + char *p = input_str + strlen(ALLOC_STR); + + while (*p == ' ') + p++; + alloc_size = memparse(p, NULL); + LOG_INFO("/proc/vc-cma: alloc %d", alloc_size); + if (alloc_size) + send_vc_msg(VC_CMA_MSG_REQUEST_FREE, + alloc_size / VC_CMA_CHUNK_SIZE, 0); + else + LOG_ERR("invalid size '%s'", p); + rc = size; + } else if (strncmp(input_str, FREE_STR, strlen(FREE_STR)) == 0) { + int alloc_size; + char *p = input_str + strlen(FREE_STR); + + while (*p == ' ') + p++; + alloc_size = memparse(p, NULL); + LOG_INFO("/proc/vc-cma: free %d", alloc_size); + if (alloc_size) + send_vc_msg(VC_CMA_MSG_REQUEST_ALLOC, + alloc_size / VC_CMA_CHUNK_SIZE, 0); + else + LOG_ERR("invalid size '%s'", p); + rc = size; + } else if (strncmp(input_str, DEBUG_STR, strlen(DEBUG_STR)) == 0) { + char *p = input_str + strlen(DEBUG_STR); + while (*p == ' ') + p++; + if ((strcmp(p, "on") == 0) || (strcmp(p, "1") == 0)) + vc_cma_debug = 1; + else if ((strcmp(p, "off") == 0) || (strcmp(p, "0") == 0)) + vc_cma_debug = 0; + LOG_INFO("/proc/vc-cma: debug %s", vc_cma_debug ? "on" : "off"); + rc = size; + } else if (strncmp(input_str, RESERVE_STR, strlen(RESERVE_STR)) == 0) { + int alloc_size; + int reserved; + char *p = input_str + strlen(RESERVE_STR); + while (*p == ' ') + p++; + alloc_size = memparse(p, NULL); + + reserved = vc_cma_set_reserve(alloc_size, current->tgid); + rc = (reserved >= 0) ? size : reserved; + } else if (strncmp(input_str, DMA_ALLOC_STR, strlen(DMA_ALLOC_STR)) == 0) { + int alloc_size; + char *p = input_str + strlen(DMA_ALLOC_STR); + while (*p == ' ') + p++; + alloc_size = memparse(p, NULL); + + if (vc_cma_dma_alloc) { + dma_release_from_contiguous(NULL, vc_cma_dma_alloc, + vc_cma_dma_size); + vc_cma_dma_alloc = NULL; + vc_cma_dma_size = 0; + } + vc_cma_dma_alloc = dma_alloc_from_contiguous(NULL, alloc_size, 0); + vc_cma_dma_size = (vc_cma_dma_alloc ? alloc_size : 0); + if (vc_cma_dma_alloc) + LOG_INFO("dma_alloc(%d pages) -> %p", alloc_size, page_address(vc_cma_dma_alloc)); + else + LOG_ERR("dma_alloc(%d pages) failed", alloc_size); + rc = size; + } else if (strncmp(input_str, DMA_FREE_STR, strlen(DMA_FREE_STR)) == 0) { + if (vc_cma_dma_alloc) { + dma_release_from_contiguous(NULL, vc_cma_dma_alloc, + vc_cma_dma_size); + vc_cma_dma_alloc = NULL; + vc_cma_dma_size = 0; + } + rc = size; + } + +out: + return rc; +} + +/**************************************************************************** +* +* File Operations for /proc interface. +* +***************************************************************************/ + +static const struct file_operations vc_cma_proc_fops = { + .open = vc_cma_proc_open, + .read = seq_read, + .write = vc_cma_proc_write, + .llseek = seq_lseek, + .release = single_release +}; + +static int vc_cma_set_reserve(unsigned int reserve, unsigned int pid) +{ + struct vc_cma_reserve_user *user = NULL; + int delta = 0; + int i; + + if (down_interruptible(&vc_cma_reserve_mutex)) + return -ERESTARTSYS; + + for (i = 0; i < vc_cma_reserve_count; i++) { + if (pid == vc_cma_reserve_users[i].pid) { + user = &vc_cma_reserve_users[i]; + delta = reserve - user->reserve; + if (reserve) + user->reserve = reserve; + else { + /* Remove this entry by copying downwards */ + while ((i + 1) < vc_cma_reserve_count) { + user[0].pid = user[1].pid; + user[0].reserve = user[1].reserve; + user++; + i++; + } + vc_cma_reserve_count--; + user = NULL; + } + break; + } + } + + if (reserve && !user) { + if (vc_cma_reserve_count == VC_CMA_RESERVE_COUNT_MAX) { + LOG_ERR("vc-cma: Too many reservations - " + "increase CMA_RESERVE_COUNT_MAX"); + up(&vc_cma_reserve_mutex); + return -EBUSY; + } + user = &vc_cma_reserve_users[vc_cma_reserve_count]; + user->pid = pid; + user->reserve = reserve; + delta = reserve; + vc_cma_reserve_count++; + } + + vc_cma_reserve_total += delta; + + send_vc_msg(VC_CMA_MSG_RESERVE, + vc_cma_reserve_total & 0xffff, vc_cma_reserve_total >> 16); + + send_worker_msg((VCHIQ_HEADER_T *) VC_CMA_MSG_UPDATE_RESERVE); + + LOG_DBG("/proc/vc-cma: reserve %d (PID %d) - total %u", + reserve, pid, vc_cma_reserve_total); + + up(&vc_cma_reserve_mutex); + + return vc_cma_reserve_total; +} + +static VCHIQ_STATUS_T cma_service_callback(VCHIQ_REASON_T reason, + VCHIQ_HEADER_T * header, + VCHIQ_SERVICE_HANDLE_T service, + void *bulk_userdata) +{ + switch (reason) { + case VCHIQ_MESSAGE_AVAILABLE: + if (!send_worker_msg(header)) + return VCHIQ_RETRY; + break; + case VCHIQ_SERVICE_CLOSED: + LOG_DBG("CMA service closed"); + break; + default: + LOG_ERR("Unexpected CMA callback reason %d", reason); + break; + } + return VCHIQ_SUCCESS; +} + +static void send_vc_msg(unsigned short type, + unsigned short param1, unsigned short param2) +{ + unsigned short msg[] = { type, param1, param2 }; + VCHIQ_ELEMENT_T elem = { &msg, sizeof(msg) }; + VCHIQ_STATUS_T ret; + vchiq_use_service(cma_service); + ret = vchiq_queue_message(cma_service, &elem, 1); + vchiq_release_service(cma_service); + if (ret != VCHIQ_SUCCESS) + LOG_ERR("vchiq_queue_message returned %x", ret); +} + +static bool send_worker_msg(VCHIQ_HEADER_T * msg) +{ + if (down_interruptible(&vc_cma_worker_queue_push_mutex)) + return false; + vchiu_queue_push(&cma_msg_queue, msg); + up(&vc_cma_worker_queue_push_mutex); + return true; +} + +static int vc_cma_alloc_chunks(int num_chunks, struct cma_msg *reply) +{ + int i; + for (i = 0; i < num_chunks; i++) { + struct page *chunk; + unsigned int chunk_num; + uint8_t *chunk_addr; + size_t chunk_size = PAGES_PER_CHUNK << PAGE_SHIFT; + + chunk = dma_alloc_from_contiguous(&vc_cma_device.dev, + PAGES_PER_CHUNK, + VC_CMA_CHUNK_ORDER); + if (!chunk) + break; + + chunk_addr = page_address(chunk); + dmac_flush_range(chunk_addr, chunk_addr + chunk_size); + outer_inv_range(__pa(chunk_addr), __pa(chunk_addr) + + chunk_size); + + chunk_num = + (page_to_phys(chunk) - vc_cma_base) / VC_CMA_CHUNK_SIZE; + BUG_ON(((page_to_phys(chunk) - vc_cma_base) % + VC_CMA_CHUNK_SIZE) != 0); + if (chunk_num >= vc_cma_chunks) { + phys_addr_t _pa = vc_cma_base + vc_cma_size - 1; + LOG_ERR("%s: ===============================", + __func__); + LOG_ERR("%s: chunk phys %x, vc_cma %pa-%pa - " + "bad SPARSEMEM configuration?", + __func__, (unsigned int)page_to_phys(chunk), + &vc_cma_base, &_pa); + LOG_ERR("%s: dev->cma_area = %p", __func__, + (void*)0/*vc_cma_device.dev.cma_area*/); + LOG_ERR("%s: ===============================", + __func__); + break; + } + reply->params[i] = chunk_num; + vc_cma_chunks_used++; + } + + if (i < num_chunks) { + LOG_ERR("%s: dma_alloc_from_contiguous failed " + "for %x bytes (alloc %d of %d, %d free)", + __func__, VC_CMA_CHUNK_SIZE, i, + num_chunks, vc_cma_chunks - vc_cma_chunks_used); + num_chunks = i; + } + + LOG_DBG("CMA allocated %d chunks -> %d used", + num_chunks, vc_cma_chunks_used); + reply->type = VC_CMA_MSG_ALLOCATED; + + { + VCHIQ_ELEMENT_T elem = { + reply, + offsetof(struct cma_msg, params[0]) + + num_chunks * sizeof(reply->params[0]) + }; + VCHIQ_STATUS_T ret; + vchiq_use_service(cma_service); + ret = vchiq_queue_message(cma_service, &elem, 1); + vchiq_release_service(cma_service); + if (ret != VCHIQ_SUCCESS) + LOG_ERR("vchiq_queue_message return " "%x", ret); + } + + return num_chunks; +} + +static int cma_worker_proc(void *param) +{ + static struct cma_msg reply; + (void)param; + + while (1) { + VCHIQ_HEADER_T *msg; + static struct cma_msg msg_copy; + struct cma_msg *cma_msg = &msg_copy; + int type, msg_size; + + msg = vchiu_queue_pop(&cma_msg_queue); + if ((unsigned int)msg >= VC_CMA_MSG_MAX) { + msg_size = msg->size; + memcpy(&msg_copy, msg->data, msg_size); + type = cma_msg->type; + vchiq_release_message(cma_service, msg); + } else { + msg_size = 0; + type = (int)msg; + if (type == VC_CMA_MSG_QUIT) + break; + else if (type == VC_CMA_MSG_UPDATE_RESERVE) { + msg = NULL; + cma_msg = NULL; + } else { + BUG(); + continue; + } + } + + switch (type) { + case VC_CMA_MSG_ALLOC:{ + int num_chunks, free_chunks; + num_chunks = cma_msg->params[0]; + free_chunks = + vc_cma_chunks - vc_cma_chunks_used; + LOG_DBG("CMA_MSG_ALLOC(%d chunks)", num_chunks); + if (num_chunks > VC_CMA_MAX_PARAMS_PER_MSG) { + LOG_ERR + ("CMA_MSG_ALLOC - chunk count (%d) " + "exceeds VC_CMA_MAX_PARAMS_PER_MSG (%d)", + num_chunks, + VC_CMA_MAX_PARAMS_PER_MSG); + num_chunks = VC_CMA_MAX_PARAMS_PER_MSG; + } + + if (num_chunks > free_chunks) { + LOG_ERR + ("CMA_MSG_ALLOC - chunk count (%d) " + "exceeds free chunks (%d)", + num_chunks, free_chunks); + num_chunks = free_chunks; + } + + vc_cma_alloc_chunks(num_chunks, &reply); + } + break; + + case VC_CMA_MSG_FREE:{ + int chunk_count = + (msg_size - + offsetof(struct cma_msg, + params)) / + sizeof(cma_msg->params[0]); + int i; + BUG_ON(chunk_count <= 0); + + LOG_DBG("CMA_MSG_FREE(%d chunks - %x, ...)", + chunk_count, cma_msg->params[0]); + for (i = 0; i < chunk_count; i++) { + int chunk_num = cma_msg->params[i]; + struct page *page = vc_cma_base_page + + chunk_num * PAGES_PER_CHUNK; + if (chunk_num >= vc_cma_chunks) { + LOG_ERR + ("CMA_MSG_FREE - chunk %d of %d" + " (value %x) exceeds maximum " + "(%x)", i, chunk_count, + chunk_num, + vc_cma_chunks - 1); + break; + } + + if (!dma_release_from_contiguous + (&vc_cma_device.dev, page, + PAGES_PER_CHUNK)) { + phys_addr_t _pa = page_to_phys(page); + LOG_ERR + ("CMA_MSG_FREE - failed to " + "release chunk %d (phys %pa, " + "page %x)", chunk_num, + &_pa, + (unsigned int)page); + } + vc_cma_chunks_used--; + } + LOG_DBG("CMA released %d chunks -> %d used", + i, vc_cma_chunks_used); + } + break; + + case VC_CMA_MSG_UPDATE_RESERVE:{ + int chunks_needed = + ((vc_cma_reserve_total + VC_CMA_CHUNK_SIZE - + 1) + / VC_CMA_CHUNK_SIZE) - + vc_cma_chunks_reserved; + + LOG_DBG + ("CMA_MSG_UPDATE_RESERVE(%d chunks needed)", + chunks_needed); + + /* Cap the reservations to what is available */ + if (chunks_needed > 0) { + if (chunks_needed > + (vc_cma_chunks - + vc_cma_chunks_used)) + chunks_needed = + (vc_cma_chunks - + vc_cma_chunks_used); + + chunks_needed = + vc_cma_alloc_chunks(chunks_needed, + &reply); + } + + LOG_DBG + ("CMA_MSG_UPDATE_RESERVE(%d chunks allocated)", + chunks_needed); + vc_cma_chunks_reserved += chunks_needed; + } + break; + + default: + LOG_ERR("unexpected msg type %d", type); + break; + } + } + + LOG_DBG("quitting..."); + return 0; +} + +/**************************************************************************** +* +* vc_cma_connected_init +* +* This function is called once the videocore has been connected. +* +***************************************************************************/ + +static void vc_cma_connected_init(void) +{ + VCHIQ_SERVICE_PARAMS_T service_params; + + LOG_DBG("vc_cma_connected_init"); + + if (!vchiu_queue_init(&cma_msg_queue, 16)) { + LOG_ERR("could not create CMA msg queue"); + goto fail_queue; + } + + if (vchiq_initialise(&cma_instance) != VCHIQ_SUCCESS) + goto fail_vchiq_init; + + vchiq_connect(cma_instance); + + service_params.fourcc = VC_CMA_FOURCC; + service_params.callback = cma_service_callback; + service_params.userdata = NULL; + service_params.version = VC_CMA_VERSION; + service_params.version_min = VC_CMA_VERSION; + + if (vchiq_open_service(cma_instance, &service_params, + &cma_service) != VCHIQ_SUCCESS) { + LOG_ERR("failed to open service - already in use?"); + goto fail_vchiq_open; + } + + vchiq_release_service(cma_service); + + cma_worker = kthread_create(cma_worker_proc, NULL, "cma_worker"); + if (!cma_worker) { + LOG_ERR("could not create CMA worker thread"); + goto fail_worker; + } + set_user_nice(cma_worker, -20); + wake_up_process(cma_worker); + + return; + +fail_worker: + vchiq_close_service(cma_service); +fail_vchiq_open: + vchiq_shutdown(cma_instance); +fail_vchiq_init: + vchiu_queue_delete(&cma_msg_queue); +fail_queue: + return; +} + +void +loud_error_header(void) +{ + if (in_loud_error) + return; + + LOG_ERR("============================================================" + "================"); + LOG_ERR("============================================================" + "================"); + LOG_ERR("====="); + + in_loud_error = 1; +} + +void +loud_error_footer(void) +{ + if (!in_loud_error) + return; + + LOG_ERR("====="); + LOG_ERR("============================================================" + "================"); + LOG_ERR("============================================================" + "================"); + + in_loud_error = 0; +} + +#if 1 +static int check_cma_config(void) { return 1; } +#else +static int +read_vc_debug_var(VC_MEM_ACCESS_HANDLE_T handle, + const char *symbol, + void *buf, size_t bufsize) +{ + VC_MEM_ADDR_T vcMemAddr; + size_t vcMemSize; + uint8_t *mapAddr; + off_t vcMapAddr; + + if (!LookupVideoCoreSymbol(handle, symbol, + &vcMemAddr, + &vcMemSize)) { + loud_error_header(); + loud_error( + "failed to find VC symbol \"%s\".", + symbol); + loud_error_footer(); + return 0; + } + + if (vcMemSize != bufsize) { + loud_error_header(); + loud_error( + "VC symbol \"%s\" is the wrong size.", + symbol); + loud_error_footer(); + return 0; + } + + vcMapAddr = (off_t)vcMemAddr & VC_MEM_TO_ARM_ADDR_MASK; + vcMapAddr += mm_vc_mem_phys_addr; + mapAddr = ioremap_nocache(vcMapAddr, vcMemSize); + if (mapAddr == 0) { + loud_error_header(); + loud_error( + "failed to ioremap \"%s\" @ 0x%x " + "(phys: 0x%x, size: %u).", + symbol, + (unsigned int)vcMapAddr, + (unsigned int)vcMemAddr, + (unsigned int)vcMemSize); + loud_error_footer(); + return 0; + } + + memcpy(buf, mapAddr, bufsize); + iounmap(mapAddr); + + return 1; +} + + +static int +check_cma_config(void) +{ + VC_MEM_ACCESS_HANDLE_T mem_hndl; + VC_MEM_ADDR_T mempool_start; + VC_MEM_ADDR_T mempool_end; + VC_MEM_ADDR_T mempool_offline_start; + VC_MEM_ADDR_T mempool_offline_end; + VC_MEM_ADDR_T cam_alloc_base; + VC_MEM_ADDR_T cam_alloc_size; + VC_MEM_ADDR_T cam_alloc_end; + int success = 0; + + if (OpenVideoCoreMemory(&mem_hndl) != 0) + goto out; + + /* Read the relevant VideoCore variables */ + if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_START", + &mempool_start, + sizeof(mempool_start))) + goto close; + + if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_END", + &mempool_end, + sizeof(mempool_end))) + goto close; + + if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_OFFLINE_START", + &mempool_offline_start, + sizeof(mempool_offline_start))) + goto close; + + if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_OFFLINE_END", + &mempool_offline_end, + sizeof(mempool_offline_end))) + goto close; + + if (!read_vc_debug_var(mem_hndl, "cam_alloc_base", + &cam_alloc_base, + sizeof(cam_alloc_base))) + goto close; + + if (!read_vc_debug_var(mem_hndl, "cam_alloc_size", + &cam_alloc_size, + sizeof(cam_alloc_size))) + goto close; + + cam_alloc_end = cam_alloc_base + cam_alloc_size; + + success = 1; + + /* Now the sanity checks */ + if (!mempool_offline_start) + mempool_offline_start = mempool_start; + if (!mempool_offline_end) + mempool_offline_end = mempool_end; + + if (VCADDR_TO_PHYSADDR(mempool_offline_start) != vc_cma_base) { + loud_error_header(); + loud_error( + "__MEMPOOL_OFFLINE_START(%x -> %lx) doesn't match " + "vc_cma_base(%x)", + mempool_offline_start, + VCADDR_TO_PHYSADDR(mempool_offline_start), + vc_cma_base); + success = 0; + } + + if (VCADDR_TO_PHYSADDR(mempool_offline_end) != + (vc_cma_base + vc_cma_size)) { + loud_error_header(); + loud_error( + "__MEMPOOL_OFFLINE_END(%x -> %lx) doesn't match " + "vc_cma_base(%x) + vc_cma_size(%x) = %x", + mempool_offline_start, + VCADDR_TO_PHYSADDR(mempool_offline_end), + vc_cma_base, vc_cma_size, vc_cma_base + vc_cma_size); + success = 0; + } + + if (mempool_end < mempool_start) { + loud_error_header(); + loud_error( + "__MEMPOOL_END(%x) must not be before " + "__MEMPOOL_START(%x)", + mempool_end, + mempool_start); + success = 0; + } + + if (mempool_offline_end < mempool_offline_start) { + loud_error_header(); + loud_error( + "__MEMPOOL_OFFLINE_END(%x) must not be before " + "__MEMPOOL_OFFLINE_START(%x)", + mempool_offline_end, + mempool_offline_start); + success = 0; + } + + if (mempool_offline_start < mempool_start) { + loud_error_header(); + loud_error( + "__MEMPOOL_OFFLINE_START(%x) must not be before " + "__MEMPOOL_START(%x)", + mempool_offline_start, + mempool_start); + success = 0; + } + + if (mempool_offline_end > mempool_end) { + loud_error_header(); + loud_error( + "__MEMPOOL_OFFLINE_END(%x) must not be after " + "__MEMPOOL_END(%x)", + mempool_offline_end, + mempool_end); + success = 0; + } + + if ((cam_alloc_base < mempool_end) && + (cam_alloc_end > mempool_start)) { + loud_error_header(); + loud_error( + "cam_alloc pool(%x-%x) overlaps " + "mempool(%x-%x)", + cam_alloc_base, cam_alloc_end, + mempool_start, mempool_end); + success = 0; + } + + loud_error_footer(); + +close: + CloseVideoCoreMemory(mem_hndl); + +out: + return success; +} +#endif + +static int vc_cma_init(void) +{ + int rc = -EFAULT; + struct device *dev; + + if (!check_cma_config()) + goto out_release; + + LOG_INFO("vc-cma: Videocore CMA driver"); + LOG_INFO("vc-cma: vc_cma_base = %pa", &vc_cma_base); + LOG_INFO("vc-cma: vc_cma_size = 0x%08x (%u MiB)", + vc_cma_size, vc_cma_size / (1024 * 1024)); + LOG_INFO("vc-cma: vc_cma_initial = 0x%08x (%u MiB)", + vc_cma_initial, vc_cma_initial / (1024 * 1024)); + + vc_cma_base_page = phys_to_page(vc_cma_base); + + if (vc_cma_chunks) { + int chunks_needed = vc_cma_initial / VC_CMA_CHUNK_SIZE; + + for (vc_cma_chunks_used = 0; + vc_cma_chunks_used < chunks_needed; vc_cma_chunks_used++) { + struct page *chunk; + chunk = dma_alloc_from_contiguous(&vc_cma_device.dev, + PAGES_PER_CHUNK, + VC_CMA_CHUNK_ORDER); + if (!chunk) + break; + BUG_ON(((page_to_phys(chunk) - vc_cma_base) % + VC_CMA_CHUNK_SIZE) != 0); + } + if (vc_cma_chunks_used != chunks_needed) { + LOG_ERR("%s: dma_alloc_from_contiguous failed (%d " + "bytes, allocation %d of %d)", + __func__, VC_CMA_CHUNK_SIZE, + vc_cma_chunks_used, chunks_needed); + goto out_release; + } + + vchiq_add_connected_callback(vc_cma_connected_init); + } + + rc = alloc_chrdev_region(&vc_cma_devnum, 0, 1, DRIVER_NAME); + if (rc < 0) { + LOG_ERR("%s: alloc_chrdev_region failed (rc=%d)", __func__, rc); + goto out_release; + } + + cdev_init(&vc_cma_cdev, &vc_cma_fops); + rc = cdev_add(&vc_cma_cdev, vc_cma_devnum, 1); + if (rc != 0) { + LOG_ERR("%s: cdev_add failed (rc=%d)", __func__, rc); + goto out_unregister; + } + + vc_cma_class = class_create(THIS_MODULE, DRIVER_NAME); + if (IS_ERR(vc_cma_class)) { + rc = PTR_ERR(vc_cma_class); + LOG_ERR("%s: class_create failed (rc=%d)", __func__, rc); + goto out_cdev_del; + } + + dev = device_create(vc_cma_class, NULL, vc_cma_devnum, NULL, + DRIVER_NAME); + if (IS_ERR(dev)) { + rc = PTR_ERR(dev); + LOG_ERR("%s: device_create failed (rc=%d)", __func__, rc); + goto out_class_destroy; + } + + vc_cma_proc_entry = proc_create(DRIVER_NAME, 0444, NULL, &vc_cma_proc_fops); + if (vc_cma_proc_entry == NULL) { + rc = -EFAULT; + LOG_ERR("%s: proc_create failed", __func__); + goto out_device_destroy; + } + + vc_cma_inited = 1; + return 0; + +out_device_destroy: + device_destroy(vc_cma_class, vc_cma_devnum); + +out_class_destroy: + class_destroy(vc_cma_class); + vc_cma_class = NULL; + +out_cdev_del: + cdev_del(&vc_cma_cdev); + +out_unregister: + unregister_chrdev_region(vc_cma_devnum, 1); + +out_release: + /* It is tempting to try to clean up by calling + dma_release_from_contiguous for all allocated chunks, but it isn't + a very safe thing to do. If vc_cma_initial is non-zero it is because + VideoCore is already using that memory, so giving it back to Linux + is likely to be fatal. + */ + return -1; +} + +/**************************************************************************** +* +* vc_cma_exit +* +***************************************************************************/ + +static void __exit vc_cma_exit(void) +{ + LOG_DBG("%s: called", __func__); + + if (vc_cma_inited) { + remove_proc_entry(DRIVER_NAME, NULL); + device_destroy(vc_cma_class, vc_cma_devnum); + class_destroy(vc_cma_class); + cdev_del(&vc_cma_cdev); + unregister_chrdev_region(vc_cma_devnum, 1); + } +} + +module_init(vc_cma_init); +module_exit(vc_cma_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Broadcom Corporation"); diff -Nur '--exclude=.git' linux-stable/drivers/char/broadcom/vcio.c raspilinux/drivers/char/broadcom/vcio.c --- linux-stable/drivers/char/broadcom/vcio.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/char/broadcom/vcio.c 2015-12-26 19:08:31.148666386 +0100 @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2010 Broadcom + * Copyright (C) 2015 Noralf Trønnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MBOX_CHAN_PROPERTY 8 + +#define VCIO_IOC_MAGIC 100 +#define IOCTL_MBOX_PROPERTY _IOWR(VCIO_IOC_MAGIC, 0, char *) + +static struct { + dev_t devt; + struct cdev cdev; + struct class *class; + struct rpi_firmware *fw; +} vcio; + +static int vcio_user_property_list(void *user) +{ + u32 *buf, size; + int ret; + + /* The first 32-bit is the size of the buffer */ + if (copy_from_user(&size, user, sizeof(size))) + return -EFAULT; + + buf = kmalloc(size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (copy_from_user(buf, user, size)) { + kfree(buf); + return -EFAULT; + } + + /* Strip off protocol encapsulation */ + ret = rpi_firmware_property_list(vcio.fw, &buf[2], size - 12); + if (ret) { + kfree(buf); + return ret; + } + + buf[1] = RPI_FIRMWARE_STATUS_SUCCESS; + if (copy_to_user(user, buf, size)) + ret = -EFAULT; + + kfree(buf); + + return ret; +} + +static int vcio_device_open(struct inode *inode, struct file *file) +{ + try_module_get(THIS_MODULE); + + return 0; +} + +static int vcio_device_release(struct inode *inode, struct file *file) +{ + module_put(THIS_MODULE); + + return 0; +} + +static long vcio_device_ioctl(struct file *file, unsigned int ioctl_num, + unsigned long ioctl_param) +{ + switch (ioctl_num) { + case IOCTL_MBOX_PROPERTY: + return vcio_user_property_list((void *)ioctl_param); + default: + pr_err("unknown ioctl: %d\n", ioctl_num); + return -EINVAL; + } +} + +const struct file_operations vcio_fops = { + .unlocked_ioctl = vcio_device_ioctl, + .open = vcio_device_open, + .release = vcio_device_release, +}; + +static int __init vcio_init(void) +{ + struct device_node *np; + static struct device *dev; + int ret; + + np = of_find_compatible_node(NULL, NULL, + "raspberrypi,bcm2835-firmware"); +/* Uncomment this when we only boot with Device Tree + if (!of_device_is_available(np)) + return -ENODEV; +*/ + vcio.fw = rpi_firmware_get(np); + if (!vcio.fw) + return -ENODEV; + + ret = alloc_chrdev_region(&vcio.devt, 0, 1, "vcio"); + if (ret) { + pr_err("failed to allocate device number\n"); + return ret; + } + + cdev_init(&vcio.cdev, &vcio_fops); + vcio.cdev.owner = THIS_MODULE; + ret = cdev_add(&vcio.cdev, vcio.devt, 1); + if (ret) { + pr_err("failed to register device\n"); + goto err_unregister_chardev; + } + + /* + * Create sysfs entries + * 'bcm2708_vcio' is used for backwards compatibility so we don't break + * userspace. Raspian has a udev rule that changes the permissions. + */ + vcio.class = class_create(THIS_MODULE, "bcm2708_vcio"); + if (IS_ERR(vcio.class)) { + ret = PTR_ERR(vcio.class); + pr_err("failed to create class\n"); + goto err_cdev_del; + } + + dev = device_create(vcio.class, NULL, vcio.devt, NULL, "vcio"); + if (IS_ERR(dev)) { + ret = PTR_ERR(dev); + pr_err("failed to create device\n"); + goto err_class_destroy; + } + + return 0; + +err_class_destroy: + class_destroy(vcio.class); +err_cdev_del: + cdev_del(&vcio.cdev); +err_unregister_chardev: + unregister_chrdev_region(vcio.devt, 1); + + return ret; +} +module_init(vcio_init); + +static void __exit vcio_exit(void) +{ + device_destroy(vcio.class, vcio.devt); + class_destroy(vcio.class); + cdev_del(&vcio.cdev); + unregister_chrdev_region(vcio.devt, 1); +} +module_exit(vcio_exit); + +MODULE_AUTHOR("Gray Girling"); +MODULE_AUTHOR("Noralf Trønnes"); +MODULE_DESCRIPTION("Mailbox userspace access"); +MODULE_LICENSE("GPL"); diff -Nur '--exclude=.git' linux-stable/drivers/char/broadcom/vc_mem.c raspilinux/drivers/char/broadcom/vc_mem.c --- linux-stable/drivers/char/broadcom/vc_mem.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/char/broadcom/vc_mem.c 2015-12-26 19:08:31.148666386 +0100 @@ -0,0 +1,422 @@ +/***************************************************************************** +* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "vc-mem" + +// 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; + +#ifdef CONFIG_DEBUG_FS +static struct dentry *vc_mem_debugfs_entry; +#endif + +/* + * Videocore memory addresses and size + * + * Drivers that wish to know the videocore memory addresses and sizes should + * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in + * headers. This allows the other drivers to not be tied down to a a certain + * address/size at compile time. + * + * In the future, the goal is to have the videocore memory virtual address and + * size be calculated at boot time rather than at compile time. The decision of + * where the videocore memory resides and its size would be in the hands of the + * bootloader (and/or kernel). When that happens, the values of these variables + * would be calculated and assigned in the init function. + */ +// in the 2835 VC in mapped above ARM, but ARM has full access to VC space +unsigned long mm_vc_mem_phys_addr = 0x00000000; +unsigned int mm_vc_mem_size = 0; +unsigned int mm_vc_mem_base = 0; + +EXPORT_SYMBOL(mm_vc_mem_phys_addr); +EXPORT_SYMBOL(mm_vc_mem_size); +EXPORT_SYMBOL(mm_vc_mem_base); + +static uint phys_addr = 0; +static uint mem_size = 0; +static uint mem_base = 0; + + +/**************************************************************************** +* +* vc_mem_open +* +***************************************************************************/ + +static int +vc_mem_open(struct inode *inode, struct file *file) +{ + (void) inode; + (void) file; + + pr_debug("%s: called file = 0x%p\n", __func__, file); + + return 0; +} + +/**************************************************************************** +* +* vc_mem_release +* +***************************************************************************/ + +static int +vc_mem_release(struct inode *inode, struct file *file) +{ + (void) inode; + (void) file; + + pr_debug("%s: called file = 0x%p\n", __func__, file); + + return 0; +} + +/**************************************************************************** +* +* vc_mem_get_size +* +***************************************************************************/ + +static void +vc_mem_get_size(void) +{ +} + +/**************************************************************************** +* +* vc_mem_get_base +* +***************************************************************************/ + +static void +vc_mem_get_base(void) +{ +} + +/**************************************************************************** +* +* vc_mem_get_current_size +* +***************************************************************************/ + +int +vc_mem_get_current_size(void) +{ + return mm_vc_mem_size; +} + +EXPORT_SYMBOL_GPL(vc_mem_get_current_size); + +/**************************************************************************** +* +* vc_mem_ioctl +* +***************************************************************************/ + +static long +vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int rc = 0; + + (void) cmd; + (void) arg; + + pr_debug("%s: called file = 0x%p\n", __func__, file); + + switch (cmd) { + case VC_MEM_IOC_MEM_PHYS_ADDR: + { + 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, + sizeof (mm_vc_mem_phys_addr)) != 0) { + rc = -EFAULT; + } + break; + } + case VC_MEM_IOC_MEM_SIZE: + { + // Get the videocore memory size first + vc_mem_get_size(); + + 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, + sizeof (mm_vc_mem_size)) != 0) { + rc = -EFAULT; + } + break; + } + case VC_MEM_IOC_MEM_BASE: + { + // Get the videocore memory base + vc_mem_get_base(); + + 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, + sizeof (mm_vc_mem_base)) != 0) { + rc = -EFAULT; + } + break; + } + case VC_MEM_IOC_MEM_LOAD: + { + // Get the videocore memory base + vc_mem_get_base(); + + 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, + sizeof (mm_vc_mem_base)) != 0) { + rc = -EFAULT; + } + break; + } + default: + { + return -ENOTTY; + } + } + pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); + + return rc; +} + +/**************************************************************************** +* +* vc_mem_mmap +* +***************************************************************************/ + +static int +vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) +{ + int rc = 0; + unsigned long length = vma->vm_end - vma->vm_start; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + + 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) { + pr_err("%s: length %ld is too big\n", __func__, length); + return -EINVAL; + } + // Do not cache the memory map + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + rc = remap_pfn_range(vma, vma->vm_start, + (mm_vc_mem_phys_addr >> PAGE_SHIFT) + + vma->vm_pgoff, length, vma->vm_page_prot); + if (rc != 0) { + pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); + } + + return rc; +} + +/**************************************************************************** +* +* File Operations for the driver. +* +***************************************************************************/ + +static const struct file_operations vc_mem_fops = { + .owner = THIS_MODULE, + .open = vc_mem_open, + .release = vc_mem_release, + .unlocked_ioctl = vc_mem_ioctl, + .mmap = vc_mem_mmap, +}; + +#ifdef CONFIG_DEBUG_FS +static void vc_mem_debugfs_deinit(void) +{ + debugfs_remove_recursive(vc_mem_debugfs_entry); + vc_mem_debugfs_entry = NULL; +} + + +static int vc_mem_debugfs_init( + struct device *dev) +{ + 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 (!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 (!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 (!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; + } + + return 0; + +fail: + vc_mem_debugfs_deinit(); + return -EFAULT; +} + +#endif /* CONFIG_DEBUG_FS */ + + +/**************************************************************************** +* +* vc_mem_init +* +***************************************************************************/ + +static int __init +vc_mem_init(void) +{ + int rc = -EFAULT; + struct device *dev; + + pr_debug("%s: called\n", __func__); + + mm_vc_mem_phys_addr = phys_addr; + mm_vc_mem_size = mem_size; + mm_vc_mem_base = mem_base; + + vc_mem_get_size(); + + 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) { + 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) { + 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); + pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); + goto out_cdev_del; + } + + dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, + DRIVER_NAME); + if (IS_ERR(dev)) { + rc = PTR_ERR(dev); + pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); + goto out_class_destroy; + } + +#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; + + device_destroy(vc_mem_class, vc_mem_devnum); + + out_class_destroy: + class_destroy(vc_mem_class); + vc_mem_class = NULL; + + out_cdev_del: + cdev_del(&vc_mem_cdev); + + out_unregister: + unregister_chrdev_region(vc_mem_devnum, 1); + + out_err: + return -1; +} + +/**************************************************************************** +* +* vc_mem_exit +* +***************************************************************************/ + +static void __exit +vc_mem_exit(void) +{ + pr_debug("%s: called\n", __func__); + + if (vc_mem_inited) { +#if CONFIG_DEBUG_FS + vc_mem_debugfs_deinit(); +#endif + device_destroy(vc_mem_class, vc_mem_devnum); + class_destroy(vc_mem_class); + cdev_del(&vc_mem_cdev); + unregister_chrdev_region(vc_mem_devnum, 1); + } +} + +module_init(vc_mem_init); +module_exit(vc_mem_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Broadcom Corporation"); + +module_param(phys_addr, uint, 0644); +module_param(mem_size, uint, 0644); +module_param(mem_base, uint, 0644); diff -Nur '--exclude=.git' linux-stable/drivers/char/broadcom/vc_sm/Makefile raspilinux/drivers/char/broadcom/vc_sm/Makefile --- linux-stable/drivers/char/broadcom/vc_sm/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/char/broadcom/vc_sm/Makefile 2015-12-26 19:08:31.148666386 +0100 @@ -0,0 +1,21 @@ +EXTRA_CFLAGS += -Wall -Wstrict-prototypes -Wno-trigraphs -O2 + +EXTRA_CFLAGS += -I"./arch/arm/mach-bcm2708/include/mach" +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" +EXTRA_CFLAGS += -I"$(srctree)/fs/" + +EXTRA_CFLAGS += -DOS_ASSERT_FAILURE +EXTRA_CFLAGS += -D__STDC_VERSION=199901L +EXTRA_CFLAGS += -D__STDC_VERSION__=199901L +EXTRA_CFLAGS += -D__VCCOREVER__=0 +EXTRA_CFLAGS += -D__KERNEL__ +EXTRA_CFLAGS += -D__linux__ +EXTRA_CFLAGS += -Werror + +obj-$(CONFIG_BCM_VC_SM) := vc-sm.o + +vc-sm-objs := \ + vmcs_sm.o \ + vc_vchi_sm.o diff -Nur '--exclude=.git' linux-stable/drivers/char/broadcom/vc_sm/vc_vchi_sm.c raspilinux/drivers/char/broadcom/vc_sm/vc_vchi_sm.c --- linux-stable/drivers/char/broadcom/vc_sm/vc_vchi_sm.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/char/broadcom/vc_sm/vc_vchi_sm.c 2015-12-26 19:08:31.148666386 +0100 @@ -0,0 +1,492 @@ +/***************************************************************************** +* Copyright 2011-2012 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/* ---- Include Files ----------------------------------------------------- */ +#include +#include +#include +#include +#include +#include +#include + +#include "vc_vchi_sm.h" + +#define VC_SM_VER 1 +#define VC_SM_MIN_VER 0 + +/* ---- Private Constants and Types -------------------------------------- */ + +/* Command blocks come from a pool */ +#define SM_MAX_NUM_CMD_RSP_BLKS 32 + +struct sm_cmd_rsp_blk { + struct list_head head; /* To create lists */ + struct semaphore sema; /* To be signaled when the response is there */ + + uint16_t id; + uint16_t length; + + uint8_t msg[VC_SM_MAX_MSG_LEN]; + + uint32_t wait:1; + uint32_t sent:1; + uint32_t alloc:1; + +}; + +struct sm_instance { + uint32_t num_connections; + VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS]; + struct task_struct *io_thread; + struct semaphore io_sema; + + uint32_t trans_id; + + struct mutex lock; + struct list_head cmd_list; + struct list_head rsp_list; + struct list_head dead_list; + + struct sm_cmd_rsp_blk free_blk[SM_MAX_NUM_CMD_RSP_BLKS]; + struct list_head free_list; + struct mutex free_lock; + struct semaphore free_sema; + +}; + +/* ---- Private Variables ------------------------------------------------ */ + +/* ---- Private Function Prototypes -------------------------------------- */ + +/* ---- Private Functions ------------------------------------------------ */ +static struct +sm_cmd_rsp_blk *vc_vchi_cmd_create(struct sm_instance *instance, + VC_SM_MSG_TYPE id, void *msg, + uint32_t size, int wait) +{ + struct sm_cmd_rsp_blk *blk; + VC_SM_MSG_HDR_T *hdr; + + if (down_interruptible(&instance->free_sema)) { + blk = kmalloc(sizeof(*blk), GFP_KERNEL); + if (!blk) + return NULL; + + blk->alloc = 1; + sema_init(&blk->sema, 0); + } else { + mutex_lock(&instance->free_lock); + blk = + list_first_entry(&instance->free_list, + struct sm_cmd_rsp_blk, head); + list_del(&blk->head); + mutex_unlock(&instance->free_lock); + } + + blk->sent = 0; + blk->wait = wait; + blk->length = sizeof(*hdr) + size; + + hdr = (VC_SM_MSG_HDR_T *) blk->msg; + hdr->type = id; + mutex_lock(&instance->lock); + hdr->trans_id = blk->id = ++instance->trans_id; + mutex_unlock(&instance->lock); + + if (size) + memcpy(hdr->body, msg, size); + + return blk; +} + +static void +vc_vchi_cmd_delete(struct sm_instance *instance, struct sm_cmd_rsp_blk *blk) +{ + if (blk->alloc) { + kfree(blk); + return; + } + + mutex_lock(&instance->free_lock); + list_add(&blk->head, &instance->free_list); + mutex_unlock(&instance->free_lock); + up(&instance->free_sema); +} + +static int vc_vchi_sm_videocore_io(void *arg) +{ + struct sm_instance *instance = arg; + struct sm_cmd_rsp_blk *cmd = NULL, *cmd_tmp; + VC_SM_RESULT_T *reply; + uint32_t reply_len; + int32_t status; + int svc_use = 1; + + while (1) { + if (svc_use) + vchi_service_release(instance->vchi_handle[0]); + svc_use = 0; + if (!down_interruptible(&instance->io_sema)) { + vchi_service_use(instance->vchi_handle[0]); + svc_use = 1; + + do { + unsigned int flags; + /* + * Get new command and move it to response list + */ + mutex_lock(&instance->lock); + if (list_empty(&instance->cmd_list)) { + /* no more commands to process */ + mutex_unlock(&instance->lock); + break; + } + cmd = + list_first_entry(&instance->cmd_list, + struct sm_cmd_rsp_blk, + head); + list_move(&cmd->head, &instance->rsp_list); + cmd->sent = 1; + mutex_unlock(&instance->lock); + + /* Send the command */ + flags = VCHI_FLAGS_BLOCK_UNTIL_QUEUED; + status = vchi_msg_queue( + instance->vchi_handle[0], + cmd->msg, cmd->length, + flags, NULL); + if (status) { + pr_err("%s: failed to queue message (%d)", + __func__, status); + } + + /* If no reply is needed then we're done */ + if (!cmd->wait) { + mutex_lock(&instance->lock); + list_del(&cmd->head); + mutex_unlock(&instance->lock); + vc_vchi_cmd_delete(instance, cmd); + continue; + } + + if (status) { + up(&cmd->sema); + continue; + } + + } while (1); + + while (!vchi_msg_peek + (instance->vchi_handle[0], (void **)&reply, + &reply_len, VCHI_FLAGS_NONE)) { + mutex_lock(&instance->lock); + list_for_each_entry(cmd, &instance->rsp_list, + head) { + if (cmd->id == reply->trans_id) + break; + } + mutex_unlock(&instance->lock); + + if (&cmd->head == &instance->rsp_list) { + pr_debug("%s: received response %u, throw away...", + __func__, reply->trans_id); + } else if (reply_len > sizeof(cmd->msg)) { + pr_err("%s: reply too big (%u) %u, throw away...", + __func__, reply_len, + reply->trans_id); + } else { + memcpy(cmd->msg, reply, reply_len); + up(&cmd->sema); + } + + vchi_msg_remove(instance->vchi_handle[0]); + } + + /* Go through the dead list and free them */ + mutex_lock(&instance->lock); + list_for_each_entry_safe(cmd, cmd_tmp, + &instance->dead_list, head) { + list_del(&cmd->head); + vc_vchi_cmd_delete(instance, cmd); + } + mutex_unlock(&instance->lock); + } + } + + return 0; +} + +static void vc_sm_vchi_callback(void *param, + const VCHI_CALLBACK_REASON_T reason, + void *msg_handle) +{ + struct sm_instance *instance = param; + + (void)msg_handle; + + switch (reason) { + case VCHI_CALLBACK_MSG_AVAILABLE: + up(&instance->io_sema); + break; + + case VCHI_CALLBACK_SERVICE_CLOSED: + pr_info("%s: service CLOSED!!", __func__); + default: + break; + } +} + +VC_VCHI_SM_HANDLE_T vc_vchi_sm_init(VCHI_INSTANCE_T vchi_instance, + VCHI_CONNECTION_T **vchi_connections, + uint32_t num_connections) +{ + uint32_t i; + struct sm_instance *instance; + int status; + + pr_debug("%s: start", __func__); + + if (num_connections > VCHI_MAX_NUM_CONNECTIONS) { + pr_err("%s: unsupported number of connections %u (max=%u)", + __func__, num_connections, VCHI_MAX_NUM_CONNECTIONS); + + goto err_null; + } + /* Allocate memory for this instance */ + instance = kzalloc(sizeof(*instance), GFP_KERNEL); + + /* Misc initialisations */ + mutex_init(&instance->lock); + sema_init(&instance->io_sema, 0); + INIT_LIST_HEAD(&instance->cmd_list); + INIT_LIST_HEAD(&instance->rsp_list); + INIT_LIST_HEAD(&instance->dead_list); + INIT_LIST_HEAD(&instance->free_list); + sema_init(&instance->free_sema, SM_MAX_NUM_CMD_RSP_BLKS); + mutex_init(&instance->free_lock); + for (i = 0; i < SM_MAX_NUM_CMD_RSP_BLKS; i++) { + sema_init(&instance->free_blk[i].sema, 0); + list_add(&instance->free_blk[i].head, &instance->free_list); + } + + /* Open the VCHI service connections */ + instance->num_connections = num_connections; + for (i = 0; i < num_connections; i++) { + SERVICE_CREATION_T params = { + VCHI_VERSION_EX(VC_SM_VER, VC_SM_MIN_VER), + VC_SM_SERVER_NAME, + vchi_connections[i], + 0, + 0, + vc_sm_vchi_callback, + instance, + 0, + 0, + 0, + }; + + status = vchi_service_open(vchi_instance, + ¶ms, &instance->vchi_handle[i]); + if (status) { + pr_err("%s: failed to open VCHI service (%d)", + __func__, status); + + goto err_close_services; + } + } + + /* Create the thread which takes care of all io to/from videoocore. */ + instance->io_thread = kthread_create(&vc_vchi_sm_videocore_io, + (void *)instance, "SMIO"); + if (instance->io_thread == NULL) { + pr_err("%s: failed to create SMIO thread", __func__); + + goto err_close_services; + } + set_user_nice(instance->io_thread, -10); + wake_up_process(instance->io_thread); + + pr_debug("%s: success - instance 0x%x", __func__, (unsigned)instance); + return instance; + +err_close_services: + for (i = 0; i < instance->num_connections; i++) { + if (instance->vchi_handle[i] != NULL) + vchi_service_close(instance->vchi_handle[i]); + } + kfree(instance); +err_null: + pr_debug("%s: FAILED", __func__); + return NULL; +} + +int vc_vchi_sm_stop(VC_VCHI_SM_HANDLE_T *handle) +{ + struct sm_instance *instance; + uint32_t i; + + if (handle == NULL) { + pr_err("%s: invalid pointer to handle %p", __func__, handle); + goto lock; + } + + if (*handle == NULL) { + pr_err("%s: invalid handle %p", __func__, *handle); + goto lock; + } + + instance = *handle; + + /* Close all VCHI service connections */ + for (i = 0; i < instance->num_connections; i++) { + int32_t success; + vchi_service_use(instance->vchi_handle[i]); + + success = vchi_service_close(instance->vchi_handle[i]); + } + + kfree(instance); + + *handle = NULL; + return 0; + +lock: + return -EINVAL; +} + +int vc_vchi_sm_send_msg(VC_VCHI_SM_HANDLE_T handle, + VC_SM_MSG_TYPE msg_id, + void *msg, uint32_t msg_size, + void *result, uint32_t result_size, + uint32_t *cur_trans_id, uint8_t wait_reply) +{ + int status = 0; + struct sm_instance *instance = handle; + struct sm_cmd_rsp_blk *cmd_blk; + + if (handle == NULL) { + pr_err("%s: invalid handle", __func__); + return -EINVAL; + } + if (msg == NULL) { + pr_err("%s: invalid msg pointer", __func__); + return -EINVAL; + } + + cmd_blk = + vc_vchi_cmd_create(instance, msg_id, msg, msg_size, wait_reply); + if (cmd_blk == NULL) { + pr_err("[%s]: failed to allocate global tracking resource", + __func__); + return -ENOMEM; + } + + if (cur_trans_id != NULL) + *cur_trans_id = cmd_blk->id; + + mutex_lock(&instance->lock); + list_add_tail(&cmd_blk->head, &instance->cmd_list); + mutex_unlock(&instance->lock); + up(&instance->io_sema); + + if (!wait_reply) + /* We're done */ + return 0; + + /* Wait for the response */ + if (down_interruptible(&cmd_blk->sema)) { + mutex_lock(&instance->lock); + if (!cmd_blk->sent) { + list_del(&cmd_blk->head); + mutex_unlock(&instance->lock); + vc_vchi_cmd_delete(instance, cmd_blk); + return -ENXIO; + } + mutex_unlock(&instance->lock); + + mutex_lock(&instance->lock); + list_move(&cmd_blk->head, &instance->dead_list); + mutex_unlock(&instance->lock); + up(&instance->io_sema); + return -EINTR; /* We're done */ + } + + if (result && result_size) { + memcpy(result, cmd_blk->msg, result_size); + } else { + VC_SM_RESULT_T *res = (VC_SM_RESULT_T *) cmd_blk->msg; + status = (res->success == 0) ? 0 : -ENXIO; + } + + mutex_lock(&instance->lock); + list_del(&cmd_blk->head); + mutex_unlock(&instance->lock); + vc_vchi_cmd_delete(instance, cmd_blk); + return status; +} + +int vc_vchi_sm_alloc(VC_VCHI_SM_HANDLE_T handle, VC_SM_ALLOC_T *msg, + VC_SM_ALLOC_RESULT_T *result, uint32_t *cur_trans_id) +{ + return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_ALLOC, + msg, sizeof(*msg), result, sizeof(*result), + cur_trans_id, 1); +} + +int vc_vchi_sm_free(VC_VCHI_SM_HANDLE_T handle, + VC_SM_FREE_T *msg, uint32_t *cur_trans_id) +{ + return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_FREE, + msg, sizeof(*msg), 0, 0, cur_trans_id, 0); +} + +int vc_vchi_sm_lock(VC_VCHI_SM_HANDLE_T handle, + VC_SM_LOCK_UNLOCK_T *msg, + VC_SM_LOCK_RESULT_T *result, uint32_t *cur_trans_id) +{ + return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_LOCK, + msg, sizeof(*msg), result, sizeof(*result), + cur_trans_id, 1); +} + +int vc_vchi_sm_unlock(VC_VCHI_SM_HANDLE_T handle, + VC_SM_LOCK_UNLOCK_T *msg, + uint32_t *cur_trans_id, uint8_t wait_reply) +{ + return vc_vchi_sm_send_msg(handle, wait_reply ? + VC_SM_MSG_TYPE_UNLOCK : + VC_SM_MSG_TYPE_UNLOCK_NOANS, msg, + sizeof(*msg), 0, 0, cur_trans_id, + wait_reply); +} + +int vc_vchi_sm_resize(VC_VCHI_SM_HANDLE_T handle, VC_SM_RESIZE_T *msg, + uint32_t *cur_trans_id) +{ + return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_RESIZE, + msg, sizeof(*msg), 0, 0, cur_trans_id, 1); +} + +int vc_vchi_sm_walk_alloc(VC_VCHI_SM_HANDLE_T handle) +{ + return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_WALK_ALLOC, + 0, 0, 0, 0, 0, 0); +} + +int vc_vchi_sm_clean_up(VC_VCHI_SM_HANDLE_T handle, VC_SM_ACTION_CLEAN_T *msg) +{ + return vc_vchi_sm_send_msg(handle, VC_SM_MSG_TYPE_ACTION_CLEAN, + msg, sizeof(*msg), 0, 0, 0, 0); +} diff -Nur '--exclude=.git' linux-stable/drivers/char/broadcom/vc_sm/vmcs_sm.c raspilinux/drivers/char/broadcom/vc_sm/vmcs_sm.c --- linux-stable/drivers/char/broadcom/vc_sm/vmcs_sm.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/char/broadcom/vc_sm/vmcs_sm.c 2015-12-26 19:08:31.148666386 +0100 @@ -0,0 +1,3211 @@ +/***************************************************************************** +* Copyright 2011-2012 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/* ---- Include Files ----------------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vchiq_connected.h" +#include "vc_vchi_sm.h" + +#include +#include "vc_sm_knl.h" + +/* ---- Private Constants and Types --------------------------------------- */ + +#define DEVICE_NAME "vcsm" +#define DEVICE_MINOR 0 + +#define VC_SM_DIR_ROOT_NAME "vc-smem" +#define VC_SM_DIR_ALLOC_NAME "alloc" +#define VC_SM_STATE "state" +#define VC_SM_STATS "statistics" +#define VC_SM_RESOURCES "resources" +#define VC_SM_DEBUG "debug" +#define VC_SM_WRITE_BUF_SIZE 128 + +/* Statistics tracked per resource and globally. +*/ +enum SM_STATS_T { + /* Attempt. */ + ALLOC, + FREE, + LOCK, + UNLOCK, + MAP, + FLUSH, + INVALID, + + END_ATTEMPT, + + /* Failure. */ + ALLOC_FAIL, + FREE_FAIL, + LOCK_FAIL, + UNLOCK_FAIL, + MAP_FAIL, + FLUSH_FAIL, + INVALID_FAIL, + + END_ALL, + +}; + +static const char *const sm_stats_human_read[] = { + "Alloc", + "Free", + "Lock", + "Unlock", + "Map", + "Cache Flush", + "Cache Invalidate", +}; + +typedef int (*VC_SM_SHOW) (struct seq_file *s, void *v); +struct SM_PDE_T { + VC_SM_SHOW show; /* Debug fs function hookup. */ + struct dentry *dir_entry; /* Debug fs directory entry. */ + void *priv_data; /* Private data */ + +}; + +/* Single resource allocation tracked for all devices. +*/ +struct sm_mmap { + struct list_head map_list; /* Linked list of maps. */ + + struct SM_RESOURCE_T *resource; /* Pointer to the resource. */ + + pid_t res_pid; /* PID owning that resource. */ + unsigned int res_vc_hdl; /* Resource handle (videocore). */ + unsigned int res_usr_hdl; /* Resource handle (user). */ + + long unsigned int res_addr; /* Mapped virtual address. */ + struct vm_area_struct *vma; /* VM area for this mapping. */ + unsigned int ref_count; /* Reference count to this vma. */ + + /* Used to link maps associated with a resource. */ + struct list_head resource_map_list; +}; + +/* Single resource allocation tracked for each opened device. +*/ +struct SM_RESOURCE_T { + struct list_head resource_list; /* List of resources. */ + struct list_head global_resource_list; /* Global list of resources. */ + + pid_t pid; /* PID owning that resource. */ + uint32_t res_guid; /* Unique identifier. */ + uint32_t lock_count; /* Lock count for this resource. */ + uint32_t ref_count; /* Ref count for this resource. */ + + uint32_t res_handle; /* Resource allocation handle. */ + void *res_base_mem; /* Resource base memory address. */ + uint32_t res_size; /* Resource size allocated. */ + enum vmcs_sm_cache_e res_cached; /* Resource cache type. */ + struct SM_RESOURCE_T *res_shared; /* Shared resource */ + + enum SM_STATS_T res_stats[END_ALL]; /* Resource statistics. */ + + uint8_t map_count; /* Counter of mappings for this resource. */ + struct list_head map_list; /* Maps associated with a resource. */ + + struct SM_PRIV_DATA_T *private; +}; + +/* Private file data associated with each opened device. +*/ +struct SM_PRIV_DATA_T { + struct list_head resource_list; /* List of resources. */ + + pid_t pid; /* PID of creator. */ + + struct dentry *dir_pid; /* Debug fs entries root. */ + struct SM_PDE_T dir_stats; /* Debug fs entries statistics sub-tree. */ + struct SM_PDE_T dir_res; /* Debug fs resource sub-tree. */ + + int restart_sys; /* Tracks restart on interrupt. */ + VC_SM_MSG_TYPE int_action; /* Interrupted action. */ + uint32_t int_trans_id; /* Interrupted transaction. */ + +}; + +/* Global state information. +*/ +struct SM_STATE_T { + VC_VCHI_SM_HANDLE_T sm_handle; /* Handle for videocore service. */ + struct dentry *dir_root; /* Debug fs entries root. */ + struct dentry *dir_alloc; /* Debug fs entries allocations. */ + struct SM_PDE_T dir_stats; /* Debug fs entries statistics sub-tree. */ + struct SM_PDE_T dir_state; /* Debug fs entries state sub-tree. */ + struct dentry *debug; /* Debug fs entries debug. */ + + struct mutex map_lock; /* Global map lock. */ + struct list_head map_list; /* List of maps. */ + struct list_head resource_list; /* List of resources. */ + + enum SM_STATS_T deceased[END_ALL]; /* Natural termination stats. */ + enum SM_STATS_T terminated[END_ALL]; /* Forced termination stats. */ + uint32_t res_deceased_cnt; /* Natural termination counter. */ + uint32_t res_terminated_cnt; /* Forced termination counter. */ + + struct cdev sm_cdev; /* Device. */ + dev_t sm_devid; /* Device identifier. */ + struct class *sm_class; /* Class. */ + struct device *sm_dev; /* Device. */ + + struct SM_PRIV_DATA_T *data_knl; /* Kernel internal data tracking. */ + + struct mutex lock; /* Global lock. */ + uint32_t guid; /* GUID (next) tracker. */ + +}; + +/* ---- Private Variables ----------------------------------------------- */ + +static struct SM_STATE_T *sm_state; +static int sm_inited; + +static const char *const sm_cache_map_vector[] = { + "(null)", + "host", + "videocore", + "host+videocore", +}; + +/* ---- Private Function Prototypes -------------------------------------- */ + +/* ---- Private Functions ------------------------------------------------ */ + +static inline unsigned vcaddr_to_pfn(unsigned long vc_addr) +{ + unsigned long pfn = vc_addr & 0x3FFFFFFF; + pfn += mm_vc_mem_phys_addr; + pfn >>= PAGE_SHIFT; + return pfn; +} + +/* Carries over to the state statistics the statistics once owned by a deceased +** resource. +*/ +static void vc_sm_resource_deceased(struct SM_RESOURCE_T *p_res, int terminated) +{ + if (sm_state != NULL) { + if (p_res != NULL) { + int ix; + + if (terminated) + sm_state->res_terminated_cnt++; + else + sm_state->res_deceased_cnt++; + + for (ix = 0; ix < END_ALL; ix++) { + if (terminated) + sm_state->terminated[ix] += + p_res->res_stats[ix]; + else + sm_state->deceased[ix] += + p_res->res_stats[ix]; + } + } + } +} + +/* Fetch a videocore handle corresponding to a mapping of the pid+address +** returns 0 (ie NULL) if no such handle exists in the global map. +*/ +static unsigned int vmcs_sm_vc_handle_from_pid_and_address(unsigned int pid, + unsigned int addr) +{ + struct sm_mmap *map = NULL; + unsigned int handle = 0; + + if (!sm_state || addr == 0) + goto out; + + mutex_lock(&(sm_state->map_lock)); + + /* Lookup the resource. + */ + if (!list_empty(&sm_state->map_list)) { + list_for_each_entry(map, &sm_state->map_list, map_list) { + if (map->res_pid != pid || map->res_addr != addr) + continue; + + pr_debug("[%s]: global map %p (pid %u, addr %lx) -> vc-hdl %x (usr-hdl %x)\n", + __func__, map, map->res_pid, map->res_addr, + map->res_vc_hdl, map->res_usr_hdl); + + handle = map->res_vc_hdl; + break; + } + } + + mutex_unlock(&(sm_state->map_lock)); + +out: + /* Use a debug log here as it may be a valid situation that we query + ** for something that is not mapped, we do not want a kernel log each + ** time around. + ** + ** There are other error log that would pop up accordingly if someone + ** subsequently tries to use something invalid after being told not to + ** use it... + */ + if (handle == 0) { + pr_debug("[%s]: not a valid map (pid %u, addr %x)\n", + __func__, pid, addr); + } + + return handle; +} + +/* Fetch a user handle corresponding to a mapping of the pid+address +** returns 0 (ie NULL) if no such handle exists in the global map. +*/ +static unsigned int vmcs_sm_usr_handle_from_pid_and_address(unsigned int pid, + unsigned int addr) +{ + struct sm_mmap *map = NULL; + unsigned int handle = 0; + + if (!sm_state || addr == 0) + goto out; + + mutex_lock(&(sm_state->map_lock)); + + /* Lookup the resource. + */ + if (!list_empty(&sm_state->map_list)) { + list_for_each_entry(map, &sm_state->map_list, map_list) { + if (map->res_pid != pid || map->res_addr != addr) + continue; + + pr_debug("[%s]: global map %p (pid %u, addr %lx) -> usr-hdl %x (vc-hdl %x)\n", + __func__, map, map->res_pid, map->res_addr, + map->res_usr_hdl, map->res_vc_hdl); + + handle = map->res_usr_hdl; + break; + } + } + + mutex_unlock(&(sm_state->map_lock)); + +out: + /* Use a debug log here as it may be a valid situation that we query + * for something that is not mapped yet. + * + * There are other error log that would pop up accordingly if someone + * subsequently tries to use something invalid after being told not to + * use it... + */ + if (handle == 0) + pr_debug("[%s]: not a valid map (pid %u, addr %x)\n", + __func__, pid, addr); + + return handle; +} + +#if defined(DO_NOT_USE) +/* Fetch an address corresponding to a mapping of the pid+handle +** returns 0 (ie NULL) if no such address exists in the global map. +*/ +static unsigned int vmcs_sm_usr_address_from_pid_and_vc_handle(unsigned int pid, + unsigned int hdl) +{ + struct sm_mmap *map = NULL; + unsigned int addr = 0; + + if (sm_state == NULL || hdl == 0) + goto out; + + mutex_lock(&(sm_state->map_lock)); + + /* Lookup the resource. + */ + if (!list_empty(&sm_state->map_list)) { + list_for_each_entry(map, &sm_state->map_list, map_list) { + if (map->res_pid != pid || map->res_vc_hdl != hdl) + continue; + + pr_debug("[%s]: global map %p (pid %u, vc-hdl %x, usr-hdl %x) -> addr %lx\n", + __func__, map, map->res_pid, map->res_vc_hdl, + map->res_usr_hdl, map->res_addr); + + addr = map->res_addr; + break; + } + } + + mutex_unlock(&(sm_state->map_lock)); + +out: + /* Use a debug log here as it may be a valid situation that we query + ** for something that is not mapped, we do not want a kernel log each + ** time around. + ** + ** There are other error log that would pop up accordingly if someone + ** subsequently tries to use something invalid after being told not to + ** use it... + */ + if (addr == 0) + pr_debug("[%s]: not a valid map (pid %u, hdl %x)\n", + __func__, pid, hdl); + + return addr; +} +#endif + +/* Fetch an address corresponding to a mapping of the pid+handle +** returns 0 (ie NULL) if no such address exists in the global map. +*/ +static unsigned int vmcs_sm_usr_address_from_pid_and_usr_handle(unsigned int + pid, + unsigned int + hdl) +{ + struct sm_mmap *map = NULL; + unsigned int addr = 0; + + if (sm_state == NULL || hdl == 0) + goto out; + + mutex_lock(&(sm_state->map_lock)); + + /* Lookup the resource. + */ + if (!list_empty(&sm_state->map_list)) { + list_for_each_entry(map, &sm_state->map_list, map_list) { + if (map->res_pid != pid || map->res_usr_hdl != hdl) + continue; + + pr_debug("[%s]: global map %p (pid %u, vc-hdl %x, usr-hdl %x) -> addr %lx\n", + __func__, map, map->res_pid, map->res_vc_hdl, + map->res_usr_hdl, map->res_addr); + + addr = map->res_addr; + break; + } + } + + mutex_unlock(&(sm_state->map_lock)); + +out: + /* Use a debug log here as it may be a valid situation that we query + * for something that is not mapped, we do not want a kernel log each + * time around. + * + * There are other error log that would pop up accordingly if someone + * subsequently tries to use something invalid after being told not to + * use it... + */ + if (addr == 0) + pr_debug("[%s]: not a valid map (pid %u, hdl %x)\n", __func__, + pid, hdl); + + return addr; +} + +/* Adds a resource mapping to the global data list. +*/ +static void vmcs_sm_add_map(struct SM_STATE_T *state, + struct SM_RESOURCE_T *resource, struct sm_mmap *map) +{ + mutex_lock(&(state->map_lock)); + + /* Add to the global list of mappings + */ + list_add(&map->map_list, &state->map_list); + + /* Add to the list of mappings for this resource + */ + list_add(&map->resource_map_list, &resource->map_list); + resource->map_count++; + + mutex_unlock(&(state->map_lock)); + + pr_debug("[%s]: added map %p (pid %u, vc-hdl %x, usr-hdl %x, addr %lx)\n", + __func__, map, map->res_pid, map->res_vc_hdl, + map->res_usr_hdl, map->res_addr); +} + +/* Removes a resource mapping from the global data list. +*/ +static void vmcs_sm_remove_map(struct SM_STATE_T *state, + struct SM_RESOURCE_T *resource, + struct sm_mmap *map) +{ + mutex_lock(&(state->map_lock)); + + /* Remove from the global list of mappings + */ + list_del(&map->map_list); + + /* Remove from the list of mapping for this resource + */ + list_del(&map->resource_map_list); + if (resource->map_count > 0) + resource->map_count--; + + mutex_unlock(&(state->map_lock)); + + pr_debug("[%s]: removed map %p (pid %d, vc-hdl %x, usr-hdl %x, addr %lx)\n", + __func__, map, map->res_pid, map->res_vc_hdl, map->res_usr_hdl, + map->res_addr); + + kfree(map); +} + +/* Read callback for the global state proc entry. +*/ +static int vc_sm_global_state_show(struct seq_file *s, void *v) +{ + struct sm_mmap *map = NULL; + int map_count = 0; + + if (sm_state == NULL) + return 0; + + seq_printf(s, "\nVC-ServiceHandle 0x%x\n", + (unsigned int)sm_state->sm_handle); + + /* Log all applicable mapping(s). + */ + + mutex_lock(&(sm_state->map_lock)); + + if (!list_empty(&sm_state->map_list)) { + list_for_each_entry(map, &sm_state->map_list, map_list) { + map_count++; + + seq_printf(s, "\nMapping 0x%x\n", + (unsigned int)map); + seq_printf(s, " TGID %u\n", + map->res_pid); + seq_printf(s, " VC-HDL 0x%x\n", + map->res_vc_hdl); + seq_printf(s, " USR-HDL 0x%x\n", + map->res_usr_hdl); + seq_printf(s, " USR-ADDR 0x%lx\n", + map->res_addr); + } + } + + mutex_unlock(&(sm_state->map_lock)); + seq_printf(s, "\n\nTotal map count: %d\n\n", map_count); + + return 0; +} + +static int vc_sm_global_statistics_show(struct seq_file *s, void *v) +{ + int ix; + + /* Global state tracked statistics. + */ + if (sm_state != NULL) { + seq_puts(s, "\nDeceased Resources Statistics\n"); + + seq_printf(s, "\nNatural Cause (%u occurences)\n", + sm_state->res_deceased_cnt); + for (ix = 0; ix < END_ATTEMPT; ix++) { + if (sm_state->deceased[ix] > 0) { + seq_printf(s, " %u\t%s\n", + sm_state->deceased[ix], + sm_stats_human_read[ix]); + } + } + seq_puts(s, "\n"); + for (ix = 0; ix < END_ATTEMPT; ix++) { + if (sm_state->deceased[ix + END_ATTEMPT] > 0) { + seq_printf(s, " %u\tFAILED %s\n", + sm_state->deceased[ix + END_ATTEMPT], + sm_stats_human_read[ix]); + } + } + + seq_printf(s, "\nForcefull (%u occurences)\n", + sm_state->res_terminated_cnt); + for (ix = 0; ix < END_ATTEMPT; ix++) { + if (sm_state->terminated[ix] > 0) { + seq_printf(s, " %u\t%s\n", + sm_state->terminated[ix], + sm_stats_human_read[ix]); + } + } + seq_puts(s, "\n"); + for (ix = 0; ix < END_ATTEMPT; ix++) { + if (sm_state->terminated[ix + END_ATTEMPT] > 0) { + seq_printf(s, " %u\tFAILED %s\n", + sm_state->terminated[ix + + END_ATTEMPT], + sm_stats_human_read[ix]); + } + } + } + + return 0; +} + +#if 0 +/* Read callback for the statistics proc entry. +*/ +static int vc_sm_statistics_show(struct seq_file *s, void *v) +{ + int ix; + struct SM_PRIV_DATA_T *file_data; + struct SM_RESOURCE_T *resource; + int res_count = 0; + struct SM_PDE_T *p_pde; + + p_pde = (struct SM_PDE_T *)(s->private); + file_data = (struct SM_PRIV_DATA_T *)(p_pde->priv_data); + + if (file_data == NULL) + return 0; + + /* Per process statistics. + */ + + seq_printf(s, "\nStatistics for TGID %d\n", file_data->pid); + + mutex_lock(&(sm_state->map_lock)); + + if (!list_empty(&file_data->resource_list)) { + list_for_each_entry(resource, &file_data->resource_list, + resource_list) { + res_count++; + + seq_printf(s, "\nGUID: 0x%x\n\n", + resource->res_guid); + for (ix = 0; ix < END_ATTEMPT; ix++) { + if (resource->res_stats[ix] > 0) { + seq_printf(s, + " %u\t%s\n", + resource->res_stats[ix], + sm_stats_human_read[ix]); + } + } + seq_puts(s, "\n"); + for (ix = 0; ix < END_ATTEMPT; ix++) { + if (resource->res_stats[ix + END_ATTEMPT] > 0) { + seq_printf(s, + " %u\tFAILED %s\n", + resource->res_stats[ + ix + END_ATTEMPT], + sm_stats_human_read[ix]); + } + } + } + } + + mutex_unlock(&(sm_state->map_lock)); + + seq_printf(s, "\nResources Count %d\n", res_count); + + return 0; +} +#endif + +#if 0 +/* Read callback for the allocation proc entry. */ +static int vc_sm_alloc_show(struct seq_file *s, void *v) +{ + struct SM_PRIV_DATA_T *file_data; + struct SM_RESOURCE_T *resource; + int alloc_count = 0; + struct SM_PDE_T *p_pde; + + p_pde = (struct SM_PDE_T *)(s->private); + file_data = (struct SM_PRIV_DATA_T *)(p_pde->priv_data); + + if (!file_data) + return 0; + + /* Per process statistics. */ + seq_printf(s, "\nAllocation for TGID %d\n", file_data->pid); + + mutex_lock(&(sm_state->map_lock)); + + if (!list_empty(&file_data->resource_list)) { + list_for_each_entry(resource, &file_data->resource_list, + resource_list) { + alloc_count++; + + seq_printf(s, "\nGUID: 0x%x\n", + resource->res_guid); + seq_printf(s, "Lock Count: %u\n", + resource->lock_count); + seq_printf(s, "Mapped: %s\n", + (resource->map_count ? "yes" : "no")); + seq_printf(s, "VC-handle: 0x%x\n", + resource->res_handle); + seq_printf(s, "VC-address: 0x%p\n", + resource->res_base_mem); + seq_printf(s, "VC-size (bytes): %u\n", + resource->res_size); + seq_printf(s, "Cache: %s\n", + sm_cache_map_vector[resource->res_cached]); + } + } + + mutex_unlock(&(sm_state->map_lock)); + + seq_printf(s, "\n\nTotal allocation count: %d\n\n", alloc_count); + + return 0; +} +#endif + +static int vc_sm_seq_file_show(struct seq_file *s, void *v) +{ + struct SM_PDE_T *sm_pde; + + sm_pde = (struct SM_PDE_T *)(s->private); + + if (sm_pde && sm_pde->show) + sm_pde->show(s, v); + + return 0; +} + +static int vc_sm_single_open(struct inode *inode, struct file *file) +{ + return single_open(file, vc_sm_seq_file_show, inode->i_private); +} + +static const struct file_operations vc_sm_debug_fs_fops = { + .open = vc_sm_single_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* Adds a resource to the private data list which tracks all the allocated +** data. +*/ +static void vmcs_sm_add_resource(struct SM_PRIV_DATA_T *privdata, + struct SM_RESOURCE_T *resource) +{ + mutex_lock(&(sm_state->map_lock)); + list_add(&resource->resource_list, &privdata->resource_list); + list_add(&resource->global_resource_list, &sm_state->resource_list); + mutex_unlock(&(sm_state->map_lock)); + + pr_debug("[%s]: added resource %p (base addr %p, hdl %x, size %u, cache %u)\n", + __func__, resource, resource->res_base_mem, + resource->res_handle, resource->res_size, resource->res_cached); +} + +/* Locates a resource and acquire a reference on it. +** The resource won't be deleted while there is a reference on it. +*/ +static struct SM_RESOURCE_T *vmcs_sm_acquire_resource(struct SM_PRIV_DATA_T + *private, + unsigned int res_guid) +{ + struct SM_RESOURCE_T *resource, *ret = NULL; + + mutex_lock(&(sm_state->map_lock)); + + list_for_each_entry(resource, &private->resource_list, resource_list) { + if (resource->res_guid != res_guid) + continue; + + pr_debug("[%s]: located resource %p (guid: %x, base addr %p, hdl %x, size %u, cache %u)\n", + __func__, resource, resource->res_guid, + resource->res_base_mem, resource->res_handle, + resource->res_size, resource->res_cached); + resource->ref_count++; + ret = resource; + break; + } + + mutex_unlock(&(sm_state->map_lock)); + + return ret; +} + +/* Locates a resource and acquire a reference on it. +** The resource won't be deleted while there is a reference on it. +*/ +static struct SM_RESOURCE_T *vmcs_sm_acquire_first_resource( + struct SM_PRIV_DATA_T *private) +{ + struct SM_RESOURCE_T *resource, *ret = NULL; + + mutex_lock(&(sm_state->map_lock)); + + list_for_each_entry(resource, &private->resource_list, resource_list) { + pr_debug("[%s]: located resource %p (guid: %x, base addr %p, hdl %x, size %u, cache %u)\n", + __func__, resource, resource->res_guid, + resource->res_base_mem, resource->res_handle, + resource->res_size, resource->res_cached); + resource->ref_count++; + ret = resource; + break; + } + + mutex_unlock(&(sm_state->map_lock)); + + return ret; +} + +/* Locates a resource and acquire a reference on it. +** The resource won't be deleted while there is a reference on it. +*/ +static struct SM_RESOURCE_T *vmcs_sm_acquire_global_resource(unsigned int + res_guid) +{ + struct SM_RESOURCE_T *resource, *ret = NULL; + + mutex_lock(&(sm_state->map_lock)); + + list_for_each_entry(resource, &sm_state->resource_list, + global_resource_list) { + if (resource->res_guid != res_guid) + continue; + + pr_debug("[%s]: located resource %p (guid: %x, base addr %p, hdl %x, size %u, cache %u)\n", + __func__, resource, resource->res_guid, + resource->res_base_mem, resource->res_handle, + resource->res_size, resource->res_cached); + resource->ref_count++; + ret = resource; + break; + } + + mutex_unlock(&(sm_state->map_lock)); + + return ret; +} + +/* Release a previously acquired resource. +** The resource will be deleted when its refcount reaches 0. +*/ +static void vmcs_sm_release_resource(struct SM_RESOURCE_T *resource, int force) +{ + struct SM_PRIV_DATA_T *private = resource->private; + struct sm_mmap *map, *map_tmp; + struct SM_RESOURCE_T *res_tmp; + int ret; + + mutex_lock(&(sm_state->map_lock)); + + if (--resource->ref_count) { + if (force) + pr_err("[%s]: resource %p in use\n", __func__, resource); + + mutex_unlock(&(sm_state->map_lock)); + return; + } + + /* Time to free the resource. Start by removing it from the list */ + list_del(&resource->resource_list); + list_del(&resource->global_resource_list); + + /* Walk the global resource list, find out if the resource is used + * somewhere else. In which case we don't want to delete it. + */ + list_for_each_entry(res_tmp, &sm_state->resource_list, + global_resource_list) { + if (res_tmp->res_handle == resource->res_handle) { + resource->res_handle = 0; + break; + } + } + + mutex_unlock(&(sm_state->map_lock)); + + pr_debug("[%s]: freeing data - guid %x, hdl %x, base address %p\n", + __func__, resource->res_guid, resource->res_handle, + resource->res_base_mem); + resource->res_stats[FREE]++; + + /* Make sure the resource we're removing is unmapped first */ + if (resource->map_count && !list_empty(&resource->map_list)) { + down_write(¤t->mm->mmap_sem); + list_for_each_entry_safe(map, map_tmp, &resource->map_list, + resource_map_list) { + ret = + do_munmap(current->mm, map->res_addr, + resource->res_size); + if (ret) { + pr_err("[%s]: could not unmap resource %p\n", + __func__, resource); + } + } + up_write(¤t->mm->mmap_sem); + } + + /* Free up the videocore allocated resource. + */ + if (resource->res_handle) { + VC_SM_FREE_T free = { + resource->res_handle, resource->res_base_mem + }; + int status = vc_vchi_sm_free(sm_state->sm_handle, &free, + &private->int_trans_id); + if (status != 0 && status != -EINTR) { + pr_err("[%s]: failed to free memory on videocore (status: %u, trans_id: %u)\n", + __func__, status, private->int_trans_id); + resource->res_stats[FREE_FAIL]++; + ret = -EPERM; + } + } + + /* Free up the shared resource. + */ + if (resource->res_shared) + vmcs_sm_release_resource(resource->res_shared, 0); + + /* Free up the local resource tracking this allocation. + */ + vc_sm_resource_deceased(resource, force); + kfree(resource); +} + +/* Dump the map table for the driver. If process is -1, dumps the whole table, +** if process is a valid pid (non -1) dump only the entries associated with the +** pid of interest. +*/ +static void vmcs_sm_host_walk_map_per_pid(int pid) +{ + struct sm_mmap *map = NULL; + + /* Make sure the device was started properly. + */ + if (sm_state == NULL) { + pr_err("[%s]: invalid device\n", __func__); + return; + } + + mutex_lock(&(sm_state->map_lock)); + + /* Log all applicable mapping(s). + */ + if (!list_empty(&sm_state->map_list)) { + list_for_each_entry(map, &sm_state->map_list, map_list) { + if (pid == -1 || map->res_pid == pid) { + pr_info("[%s]: tgid: %u - vc-hdl: %x, usr-hdl: %x, usr-addr: %lx\n", + __func__, map->res_pid, map->res_vc_hdl, + map->res_usr_hdl, map->res_addr); + } + } + } + + mutex_unlock(&(sm_state->map_lock)); + + return; +} + +/* Dump the allocation table from host side point of view. This only dumps the +** data allocated for this process/device referenced by the file_data. +*/ +static void vmcs_sm_host_walk_alloc(struct SM_PRIV_DATA_T *file_data) +{ + struct SM_RESOURCE_T *resource = NULL; + + /* Make sure the device was started properly. + */ + if ((sm_state == NULL) || (file_data == NULL)) { + pr_err("[%s]: invalid device\n", __func__); + return; + } + + mutex_lock(&(sm_state->map_lock)); + + if (!list_empty(&file_data->resource_list)) { + list_for_each_entry(resource, &file_data->resource_list, + resource_list) { + pr_info("[%s]: guid: %x - hdl: %x, vc-mem: %p, size: %u, cache: %u\n", + __func__, resource->res_guid, resource->res_handle, + resource->res_base_mem, resource->res_size, + resource->res_cached); + } + } + + mutex_unlock(&(sm_state->map_lock)); + + return; +} + +/* Create support for private data tracking. +*/ +static struct SM_PRIV_DATA_T *vc_sm_create_priv_data(pid_t id) +{ + char alloc_name[32]; + struct SM_PRIV_DATA_T *file_data = NULL; + + /* Allocate private structure. */ + file_data = kzalloc(sizeof(*file_data), GFP_KERNEL); + + if (!file_data) { + pr_err("[%s]: cannot allocate file data\n", __func__); + goto out; + } + + snprintf(alloc_name, sizeof(alloc_name), "%d", id); + + INIT_LIST_HEAD(&file_data->resource_list); + file_data->pid = id; + file_data->dir_pid = debugfs_create_dir(alloc_name, + sm_state->dir_alloc); +#if 0 + /* TODO: fix this to support querying statistics per pid */ + + if (IS_ERR_OR_NULL(file_data->dir_pid)) { + file_data->dir_pid = NULL; + } else { + struct dentry *dir_entry; + + dir_entry = debugfs_create_file(VC_SM_RESOURCES, S_IRUGO, + file_data->dir_pid, file_data, + vc_sm_debug_fs_fops); + + file_data->dir_res.dir_entry = dir_entry; + file_data->dir_res.priv_data = file_data; + file_data->dir_res.show = &vc_sm_alloc_show; + + dir_entry = debugfs_create_file(VC_SM_STATS, S_IRUGO, + file_data->dir_pid, file_data, + vc_sm_debug_fs_fops); + + file_data->dir_res.dir_entry = dir_entry; + file_data->dir_res.priv_data = file_data; + file_data->dir_res.show = &vc_sm_statistics_show; + } + pr_debug("[%s]: private data allocated %p\n", __func__, file_data); + +#endif +out: + return file_data; +} + +/* Open the device. Creates a private state to help track all allocation +** associated with this device. +*/ +static int vc_sm_open(struct inode *inode, struct file *file) +{ + int ret = 0; + + /* Make sure the device was started properly. + */ + if (!sm_state) { + pr_err("[%s]: invalid device\n", __func__); + ret = -EPERM; + goto out; + } + + file->private_data = vc_sm_create_priv_data(current->tgid); + if (file->private_data == NULL) { + pr_err("[%s]: failed to create data tracker\n", __func__); + + ret = -ENOMEM; + goto out; + } + +out: + return ret; +} + +/* Close the device. Free up all resources still associated with this device +** at the time. +*/ +static int vc_sm_release(struct inode *inode, struct file *file) +{ + struct SM_PRIV_DATA_T *file_data = + (struct SM_PRIV_DATA_T *)file->private_data; + struct SM_RESOURCE_T *resource; + int ret = 0; + + /* Make sure the device was started properly. + */ + if (sm_state == NULL || file_data == NULL) { + pr_err("[%s]: invalid device\n", __func__); + ret = -EPERM; + goto out; + } + + pr_debug("[%s]: using private data %p\n", __func__, file_data); + + if (file_data->restart_sys == -EINTR) { + VC_SM_ACTION_CLEAN_T action_clean; + + pr_debug("[%s]: releasing following EINTR on %u (trans_id: %u) (likely due to signal)...\n", + __func__, file_data->int_action, + file_data->int_trans_id); + + action_clean.res_action = file_data->int_action; + action_clean.action_trans_id = file_data->int_trans_id; + + vc_vchi_sm_clean_up(sm_state->sm_handle, &action_clean); + } + + while ((resource = vmcs_sm_acquire_first_resource(file_data)) != NULL) { + vmcs_sm_release_resource(resource, 0); + vmcs_sm_release_resource(resource, 1); + } + + /* Remove the corresponding proc entry. */ + debugfs_remove_recursive(file_data->dir_pid); + + /* Terminate the private data. + */ + kfree(file_data); + +out: + return ret; +} + +static void vcsm_vma_open(struct vm_area_struct *vma) +{ + struct sm_mmap *map = (struct sm_mmap *)vma->vm_private_data; + + pr_debug("[%s]: virt %lx-%lx, pid %i, pfn %i\n", + __func__, vma->vm_start, vma->vm_end, (int)current->tgid, + (int)vma->vm_pgoff); + + map->ref_count++; +} + +static void vcsm_vma_close(struct vm_area_struct *vma) +{ + struct sm_mmap *map = (struct sm_mmap *)vma->vm_private_data; + + pr_debug("[%s]: virt %lx-%lx, pid %i, pfn %i\n", + __func__, vma->vm_start, vma->vm_end, (int)current->tgid, + (int)vma->vm_pgoff); + + map->ref_count--; + + /* Remove from the map table. + */ + if (map->ref_count == 0) + vmcs_sm_remove_map(sm_state, map->resource, map); +} + +static int vcsm_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct sm_mmap *map = (struct sm_mmap *)vma->vm_private_data; + struct SM_RESOURCE_T *resource = map->resource; + pgoff_t page_offset; + unsigned long pfn; + int ret = 0; + + /* Lock the resource if necessary. + */ + if (!resource->lock_count) { + VC_SM_LOCK_UNLOCK_T lock_unlock; + VC_SM_LOCK_RESULT_T lock_result; + int status; + + lock_unlock.res_handle = resource->res_handle; + lock_unlock.res_mem = resource->res_base_mem; + + pr_debug("[%s]: attempt to lock data - hdl %x, base address %p\n", + __func__, lock_unlock.res_handle, lock_unlock.res_mem); + + /* Lock the videocore allocated resource. + */ + status = vc_vchi_sm_lock(sm_state->sm_handle, + &lock_unlock, &lock_result, 0); + if ((status != 0) || + ((status == 0) && (lock_result.res_mem == NULL))) { + pr_err("[%s]: failed to lock memory on videocore (status: %u)\n", + __func__, status); + resource->res_stats[LOCK_FAIL]++; + return VM_FAULT_SIGBUS; + } + + pfn = vcaddr_to_pfn((unsigned long)resource->res_base_mem); + outer_inv_range(__pfn_to_phys(pfn), + __pfn_to_phys(pfn) + resource->res_size); + + resource->res_stats[LOCK]++; + resource->lock_count++; + + /* Keep track of the new base memory. + */ + if ((lock_result.res_mem != NULL) && + (lock_result.res_old_mem != NULL) && + (lock_result.res_mem != lock_result.res_old_mem)) { + resource->res_base_mem = lock_result.res_mem; + } + } + + /* We don't use vmf->pgoff since that has the fake offset */ + page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start); + pfn = (uint32_t)resource->res_base_mem & 0x3FFFFFFF; + pfn += mm_vc_mem_phys_addr; + pfn += page_offset; + pfn >>= PAGE_SHIFT; + + /* Finally, remap it */ + ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); + + switch (ret) { + case 0: + case -ERESTARTSYS: + return VM_FAULT_NOPAGE; + case -ENOMEM: + case -EAGAIN: + return VM_FAULT_OOM; + default: + return VM_FAULT_SIGBUS; + } +} + +static struct vm_operations_struct vcsm_vm_ops = { + .open = vcsm_vma_open, + .close = vcsm_vma_close, + .fault = vcsm_vma_fault, +}; + +/* Walks a VMA and clean each valid page from the cache */ +static void vcsm_vma_cache_clean_page_range(unsigned long addr, + unsigned long end) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + unsigned long pgd_next, pud_next, pmd_next; + + if (addr >= end) + return; + + /* Walk PGD */ + pgd = pgd_offset(current->mm, addr); + do { + pgd_next = pgd_addr_end(addr, end); + + if (pgd_none(*pgd) || pgd_bad(*pgd)) + continue; + + /* Walk PUD */ + pud = pud_offset(pgd, addr); + do { + pud_next = pud_addr_end(addr, pgd_next); + if (pud_none(*pud) || pud_bad(*pud)) + continue; + + /* Walk PMD */ + pmd = pmd_offset(pud, addr); + do { + pmd_next = pmd_addr_end(addr, pud_next); + if (pmd_none(*pmd) || pmd_bad(*pmd)) + continue; + + /* Walk PTE */ + pte = pte_offset_map(pmd, addr); + do { + if (pte_none(*pte) + || !pte_present(*pte)) + continue; + + /* Clean + invalidate */ + dmac_flush_range((const void *) addr, + (const void *) + (addr + PAGE_SIZE)); + + } while (pte++, addr += + PAGE_SIZE, addr != pmd_next); + pte_unmap(pte); + + } while (pmd++, addr = pmd_next, addr != pud_next); + + } while (pud++, addr = pud_next, addr != pgd_next); + } while (pgd++, addr = pgd_next, addr != end); +} + +/* Map an allocated data into something that the user space. +*/ +static int vc_sm_mmap(struct file *file, struct vm_area_struct *vma) +{ + int ret = 0; + struct SM_PRIV_DATA_T *file_data = + (struct SM_PRIV_DATA_T *)file->private_data; + struct SM_RESOURCE_T *resource = NULL; + struct sm_mmap *map = NULL; + + /* Make sure the device was started properly. + */ + if ((sm_state == NULL) || (file_data == NULL)) { + pr_err("[%s]: invalid device\n", __func__); + return -EPERM; + } + + pr_debug("[%s]: private data %p, guid %x\n", __func__, file_data, + ((unsigned int)vma->vm_pgoff << PAGE_SHIFT)); + + /* We lookup to make sure that the data we are being asked to mmap is + ** something that we allocated. + ** + ** We use the offset information as the key to tell us which resource + ** we are mapping. + */ + resource = vmcs_sm_acquire_resource(file_data, + ((unsigned int)vma->vm_pgoff << + PAGE_SHIFT)); + if (resource == NULL) { + pr_err("[%s]: failed to locate resource for guid %x\n", __func__, + ((unsigned int)vma->vm_pgoff << PAGE_SHIFT)); + return -ENOMEM; + } + + pr_debug("[%s]: guid %x, tgid %u, %u, %u\n", + __func__, resource->res_guid, current->tgid, resource->pid, + file_data->pid); + + /* Check permissions. + */ + if (resource->pid && (resource->pid != current->tgid)) { + pr_err("[%s]: current tgid %u != %u owner\n", + __func__, current->tgid, resource->pid); + ret = -EPERM; + goto error; + } + + /* Verify that what we are asked to mmap is proper. + */ + if (resource->res_size != (unsigned int)(vma->vm_end - vma->vm_start)) { + pr_err("[%s]: size inconsistency (resource: %u - mmap: %u)\n", + __func__, + resource->res_size, + (unsigned int)(vma->vm_end - vma->vm_start)); + + ret = -EINVAL; + goto error; + } + + /* Keep track of the tuple in the global resource list such that one + * can do a mapping lookup for address/memory handle. + */ + map = kzalloc(sizeof(*map), GFP_KERNEL); + if (map == NULL) { + pr_err("[%s]: failed to allocate global tracking resource\n", + __func__); + ret = -ENOMEM; + goto error; + } + + map->res_pid = current->tgid; + map->res_vc_hdl = resource->res_handle; + map->res_usr_hdl = resource->res_guid; + map->res_addr = (long unsigned int)vma->vm_start; + map->resource = resource; + map->vma = vma; + vmcs_sm_add_map(sm_state, resource, map); + + /* We are not actually mapping the pages, we just provide a fault + ** handler to allow pages to be mapped when accessed + */ + vma->vm_flags |= + VM_IO | VM_PFNMAP | VM_DONTCOPY | VM_DONTEXPAND; + vma->vm_ops = &vcsm_vm_ops; + vma->vm_private_data = map; + + /* vm_pgoff is the first PFN of the mapped memory */ + vma->vm_pgoff = (unsigned long)resource->res_base_mem & 0x3FFFFFFF; + vma->vm_pgoff += mm_vc_mem_phys_addr; + vma->vm_pgoff >>= PAGE_SHIFT; + + if ((resource->res_cached == VMCS_SM_CACHE_NONE) || + (resource->res_cached == VMCS_SM_CACHE_VC)) { + /* Allocated non host cached memory, honour it. + */ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + } + + pr_debug("[%s]: resource %p (guid %x) - cnt %u, base address %p, handle %x, size %u (%u), cache %u\n", + __func__, + resource, resource->res_guid, resource->lock_count, + resource->res_base_mem, resource->res_handle, + resource->res_size, (unsigned int)(vma->vm_end - vma->vm_start), + resource->res_cached); + + pr_debug("[%s]: resource %p (base address %p, handle %x) - map-count %d, usr-addr %x\n", + __func__, resource, resource->res_base_mem, + resource->res_handle, resource->map_count, + (unsigned int)vma->vm_start); + + vcsm_vma_open(vma); + resource->res_stats[MAP]++; + vmcs_sm_release_resource(resource, 0); + return 0; + +error: + resource->res_stats[MAP_FAIL]++; + vmcs_sm_release_resource(resource, 0); + return ret; +} + +/* Allocate a shared memory handle and block. +*/ +int vc_sm_ioctl_alloc(struct SM_PRIV_DATA_T *private, + struct vmcs_sm_ioctl_alloc *ioparam) +{ + int ret = 0; + int status; + struct SM_RESOURCE_T *resource; + VC_SM_ALLOC_T alloc = { 0 }; + VC_SM_ALLOC_RESULT_T result = { 0 }; + + /* Setup our allocation parameters */ + alloc.type = ((ioparam->cached == VMCS_SM_CACHE_VC) + || (ioparam->cached == + VMCS_SM_CACHE_BOTH)) ? VC_SM_ALLOC_CACHED : + VC_SM_ALLOC_NON_CACHED; + alloc.base_unit = ioparam->size; + alloc.num_unit = ioparam->num; + alloc.allocator = current->tgid; + /* Align to kernel page size */ + alloc.alignement = 4096; + /* Align the size to the kernel page size */ + alloc.base_unit = + (alloc.base_unit + alloc.alignement - 1) & ~(alloc.alignement - 1); + if (*ioparam->name) { + memcpy(alloc.name, ioparam->name, sizeof(alloc.name) - 1); + } else { + memcpy(alloc.name, VMCS_SM_RESOURCE_NAME_DEFAULT, + sizeof(VMCS_SM_RESOURCE_NAME_DEFAULT)); + } + + pr_debug("[%s]: attempt to allocate \"%s\" data - type %u, base %u (%u), num %u, alignement %u\n", + __func__, alloc.name, alloc.type, ioparam->size, + alloc.base_unit, alloc.num_unit, alloc.alignement); + + /* Allocate local resource to track this allocation. + */ + resource = kzalloc(sizeof(*resource), GFP_KERNEL); + if (!resource) { + ret = -ENOMEM; + goto error; + } + INIT_LIST_HEAD(&resource->map_list); + resource->ref_count++; + resource->pid = current->tgid; + + /* Allocate the videocore resource. + */ + status = vc_vchi_sm_alloc(sm_state->sm_handle, &alloc, &result, + &private->int_trans_id); + if (status == -EINTR) { + pr_debug("[%s]: requesting allocate memory action restart (trans_id: %u)\n", + __func__, private->int_trans_id); + ret = -ERESTARTSYS; + private->restart_sys = -EINTR; + private->int_action = VC_SM_MSG_TYPE_ALLOC; + goto error; + } else if (status != 0 || (status == 0 && result.res_mem == NULL)) { + pr_err("[%s]: failed to allocate memory on videocore (status: %u, trans_id: %u)\n", + __func__, status, private->int_trans_id); + ret = -ENOMEM; + resource->res_stats[ALLOC_FAIL]++; + goto error; + } + + /* Keep track of the resource we created. + */ + resource->private = private; + resource->res_handle = result.res_handle; + resource->res_base_mem = result.res_mem; + resource->res_size = alloc.base_unit * alloc.num_unit; + resource->res_cached = ioparam->cached; + + /* Kernel/user GUID. This global identifier is used for mmap'ing the + * allocated region from user space, it is passed as the mmap'ing + * offset, we use it to 'hide' the videocore handle/address. + */ + mutex_lock(&sm_state->lock); + resource->res_guid = ++sm_state->guid; + mutex_unlock(&sm_state->lock); + resource->res_guid <<= PAGE_SHIFT; + + vmcs_sm_add_resource(private, resource); + + pr_debug("[%s]: allocated data - guid %x, hdl %x, base address %p, size %d, cache %d\n", + __func__, resource->res_guid, resource->res_handle, + resource->res_base_mem, resource->res_size, + resource->res_cached); + + /* We're done */ + resource->res_stats[ALLOC]++; + ioparam->handle = resource->res_guid; + return 0; + +error: + pr_err("[%s]: failed to allocate \"%s\" data (%i) - type %u, base %u (%u), num %u, alignment %u\n", + __func__, alloc.name, ret, alloc.type, ioparam->size, + alloc.base_unit, alloc.num_unit, alloc.alignement); + if (resource != NULL) { + vc_sm_resource_deceased(resource, 1); + kfree(resource); + } + return ret; +} + +/* Share an allocate memory handle and block. +*/ +int vc_sm_ioctl_alloc_share(struct SM_PRIV_DATA_T *private, + struct vmcs_sm_ioctl_alloc_share *ioparam) +{ + struct SM_RESOURCE_T *resource, *shared_resource; + int ret = 0; + + pr_debug("[%s]: attempt to share resource %u\n", __func__, + ioparam->handle); + + shared_resource = vmcs_sm_acquire_global_resource(ioparam->handle); + if (shared_resource == NULL) { + ret = -ENOMEM; + goto error; + } + + /* Allocate local resource to track this allocation. + */ + resource = kzalloc(sizeof(*resource), GFP_KERNEL); + if (resource == NULL) { + pr_err("[%s]: failed to allocate local tracking resource\n", + __func__); + ret = -ENOMEM; + goto error; + } + INIT_LIST_HEAD(&resource->map_list); + resource->ref_count++; + resource->pid = current->tgid; + + /* Keep track of the resource we created. + */ + resource->private = private; + resource->res_handle = shared_resource->res_handle; + resource->res_base_mem = shared_resource->res_base_mem; + resource->res_size = shared_resource->res_size; + resource->res_cached = shared_resource->res_cached; + resource->res_shared = shared_resource; + + mutex_lock(&sm_state->lock); + resource->res_guid = ++sm_state->guid; + mutex_unlock(&sm_state->lock); + resource->res_guid <<= PAGE_SHIFT; + + vmcs_sm_add_resource(private, resource); + + pr_debug("[%s]: allocated data - guid %x, hdl %x, base address %p, size %d, cache %d\n", + __func__, resource->res_guid, resource->res_handle, + resource->res_base_mem, resource->res_size, + resource->res_cached); + + /* We're done */ + resource->res_stats[ALLOC]++; + ioparam->handle = resource->res_guid; + ioparam->size = resource->res_size; + return 0; + +error: + pr_err("[%s]: failed to share %u\n", __func__, ioparam->handle); + if (shared_resource != NULL) + vmcs_sm_release_resource(shared_resource, 0); + + return ret; +} + +/* Free a previously allocated shared memory handle and block. +*/ +static int vc_sm_ioctl_free(struct SM_PRIV_DATA_T *private, + struct vmcs_sm_ioctl_free *ioparam) +{ + struct SM_RESOURCE_T *resource = + vmcs_sm_acquire_resource(private, ioparam->handle); + + if (resource == NULL) { + pr_err("[%s]: resource for guid %u does not exist\n", __func__, + ioparam->handle); + return -EINVAL; + } + + /* Check permissions. + */ + if (resource->pid && (resource->pid != current->tgid)) { + pr_err("[%s]: current tgid %u != %u owner\n", + __func__, current->tgid, resource->pid); + vmcs_sm_release_resource(resource, 0); + return -EPERM; + } + + vmcs_sm_release_resource(resource, 0); + vmcs_sm_release_resource(resource, 0); + return 0; +} + +/* Resize a previously allocated shared memory handle and block. +*/ +static int vc_sm_ioctl_resize(struct SM_PRIV_DATA_T *private, + struct vmcs_sm_ioctl_resize *ioparam) +{ + int ret = 0; + int status; + VC_SM_RESIZE_T resize; + struct SM_RESOURCE_T *resource; + + /* Locate resource from GUID. + */ + resource = vmcs_sm_acquire_resource(private, ioparam->handle); + if (!resource) { + pr_err("[%s]: failed resource - guid %x\n", + __func__, ioparam->handle); + ret = -EFAULT; + goto error; + } + + /* If the resource is locked, its reference count will be not NULL, + ** in which case we will not be allowed to resize it anyways, so + ** reject the attempt here. + */ + if (resource->lock_count != 0) { + pr_err("[%s]: cannot resize - guid %x, ref-cnt %d\n", + __func__, ioparam->handle, resource->lock_count); + ret = -EFAULT; + goto error; + } + + /* Check permissions. + */ + if (resource->pid && (resource->pid != current->tgid)) { + pr_err("[%s]: current tgid %u != %u owner\n", __func__, + current->tgid, resource->pid); + ret = -EPERM; + goto error; + } + + if (resource->map_count != 0) { + pr_err("[%s]: cannot resize - guid %x, ref-cnt %d\n", + __func__, ioparam->handle, resource->map_count); + ret = -EFAULT; + goto error; + } + + resize.res_handle = resource->res_handle; + resize.res_mem = resource->res_base_mem; + resize.res_new_size = ioparam->new_size; + + pr_debug("[%s]: attempt to resize data - guid %x, hdl %x, base address %p\n", + __func__, ioparam->handle, resize.res_handle, resize.res_mem); + + /* Resize the videocore allocated resource. + */ + status = vc_vchi_sm_resize(sm_state->sm_handle, &resize, + &private->int_trans_id); + if (status == -EINTR) { + pr_debug("[%s]: requesting resize memory action restart (trans_id: %u)\n", + __func__, private->int_trans_id); + ret = -ERESTARTSYS; + private->restart_sys = -EINTR; + private->int_action = VC_SM_MSG_TYPE_RESIZE; + goto error; + } else if (status != 0) { + pr_err("[%s]: failed to resize memory on videocore (status: %u, trans_id: %u)\n", + __func__, status, private->int_trans_id); + ret = -EPERM; + goto error; + } + + pr_debug("[%s]: success to resize data - hdl %x, size %d -> %d\n", + __func__, resize.res_handle, resource->res_size, + resize.res_new_size); + + /* Successfully resized, save the information and inform the user. + */ + ioparam->old_size = resource->res_size; + resource->res_size = resize.res_new_size; + +error: + if (resource) + vmcs_sm_release_resource(resource, 0); + + return ret; +} + +/* Lock a previously allocated shared memory handle and block. +*/ +static int vc_sm_ioctl_lock(struct SM_PRIV_DATA_T *private, + struct vmcs_sm_ioctl_lock_unlock *ioparam, + int change_cache, enum vmcs_sm_cache_e cache_type, + unsigned int vc_addr) +{ + int status; + VC_SM_LOCK_UNLOCK_T lock; + VC_SM_LOCK_RESULT_T result; + struct SM_RESOURCE_T *resource; + int ret = 0; + struct sm_mmap *map, *map_tmp; + long unsigned int phys_addr; + + map = NULL; + + /* Locate resource from GUID. + */ + resource = vmcs_sm_acquire_resource(private, ioparam->handle); + if (resource == NULL) { + ret = -EINVAL; + goto error; + } + + /* Check permissions. + */ + if (resource->pid && (resource->pid != current->tgid)) { + pr_err("[%s]: current tgid %u != %u owner\n", __func__, + current->tgid, resource->pid); + ret = -EPERM; + goto error; + } + + lock.res_handle = resource->res_handle; + lock.res_mem = resource->res_base_mem; + + /* Take the lock and get the address to be mapped. + */ + if (vc_addr == 0) { + pr_debug("[%s]: attempt to lock data - guid %x, hdl %x, base address %p\n", + __func__, ioparam->handle, lock.res_handle, + lock.res_mem); + + /* Lock the videocore allocated resource. + */ + status = vc_vchi_sm_lock(sm_state->sm_handle, &lock, &result, + &private->int_trans_id); + if (status == -EINTR) { + pr_debug("[%s]: requesting lock memory action restart (trans_id: %u)\n", + __func__, private->int_trans_id); + ret = -ERESTARTSYS; + private->restart_sys = -EINTR; + private->int_action = VC_SM_MSG_TYPE_LOCK; + goto error; + } else if (status != 0 || + (status == 0 && result.res_mem == NULL)) { + pr_err("[%s]: failed to lock memory on videocore (status: %u, trans_id: %u)\n", + __func__, status, private->int_trans_id); + ret = -EPERM; + resource->res_stats[LOCK_FAIL]++; + goto error; + } + + pr_debug("[%s]: succeed to lock data - hdl %x, base address %p (%p), ref-cnt %d\n", + __func__, lock.res_handle, result.res_mem, + lock.res_mem, resource->lock_count); + } + /* Lock assumed taken already, address to be mapped is known. + */ + else + resource->res_base_mem = (void *)vc_addr; + + resource->res_stats[LOCK]++; + resource->lock_count++; + + /* Keep track of the new base memory allocation if it has changed. + */ + if ((vc_addr == 0) && + (result.res_mem != NULL) && + (result.res_old_mem != NULL) && + (result.res_mem != result.res_old_mem)) { + resource->res_base_mem = result.res_mem; + + /* Kernel allocated resources. + */ + if (resource->pid == 0) { + if (!list_empty(&resource->map_list)) { + list_for_each_entry_safe(map, map_tmp, + &resource->map_list, + resource_map_list) { + if (map->res_addr) { + iounmap((void *)map->res_addr); + map->res_addr = 0; + + vmcs_sm_remove_map(sm_state, + map->resource, + map); + break; + } + } + } + } + } + + if (change_cache) + resource->res_cached = cache_type; + + if (resource->map_count) { + ioparam->addr = + vmcs_sm_usr_address_from_pid_and_usr_handle( + current->tgid, ioparam->handle); + + pr_debug("[%s] map_count %d private->pid %d current->tgid %d hnd %x addr %u\n", + __func__, resource->map_count, private->pid, + current->tgid, ioparam->handle, ioparam->addr); + } else { + /* Kernel allocated resources. + */ + if (resource->pid == 0) { + pr_debug("[%s]: attempt mapping kernel resource - guid %x, hdl %x\n", + __func__, ioparam->handle, lock.res_handle); + + ioparam->addr = 0; + + map = kzalloc(sizeof(*map), GFP_KERNEL); + if (map == NULL) { + pr_err("[%s]: failed allocating tracker\n", + __func__); + ret = -ENOMEM; + goto error; + } else { + phys_addr = (uint32_t)resource->res_base_mem & + 0x3FFFFFFF; + phys_addr += mm_vc_mem_phys_addr; + if (resource->res_cached + == VMCS_SM_CACHE_HOST) { + ioparam->addr = (long unsigned int) + /* TODO - make cached work */ + ioremap_nocache(phys_addr, + resource->res_size); + + pr_debug("[%s]: mapping kernel - guid %x, hdl %x - cached mapping %u\n", + __func__, ioparam->handle, + lock.res_handle, ioparam->addr); + } else { + ioparam->addr = (long unsigned int) + ioremap_nocache(phys_addr, + resource->res_size); + + pr_debug("[%s]: mapping kernel- guid %x, hdl %x - non cached mapping %u\n", + __func__, ioparam->handle, + lock.res_handle, ioparam->addr); + } + + map->res_pid = 0; + map->res_vc_hdl = resource->res_handle; + map->res_usr_hdl = resource->res_guid; + map->res_addr = ioparam->addr; + map->resource = resource; + map->vma = NULL; + + vmcs_sm_add_map(sm_state, resource, map); + } + } else + ioparam->addr = 0; + } + +error: + if (resource) + vmcs_sm_release_resource(resource, 0); + + return ret; +} + +/* Unlock a previously allocated shared memory handle and block. +*/ +static int vc_sm_ioctl_unlock(struct SM_PRIV_DATA_T *private, + struct vmcs_sm_ioctl_lock_unlock *ioparam, + int flush, int wait_reply, int no_vc_unlock) +{ + int status; + VC_SM_LOCK_UNLOCK_T unlock; + struct sm_mmap *map, *map_tmp; + struct SM_RESOURCE_T *resource; + int ret = 0; + + map = NULL; + + /* Locate resource from GUID. + */ + resource = vmcs_sm_acquire_resource(private, ioparam->handle); + if (resource == NULL) { + ret = -EINVAL; + goto error; + } + + /* Check permissions. + */ + if (resource->pid && (resource->pid != current->tgid)) { + pr_err("[%s]: current tgid %u != %u owner\n", + __func__, current->tgid, resource->pid); + ret = -EPERM; + goto error; + } + + unlock.res_handle = resource->res_handle; + unlock.res_mem = resource->res_base_mem; + + pr_debug("[%s]: attempt to unlock data - guid %x, hdl %x, base address %p\n", + __func__, ioparam->handle, unlock.res_handle, unlock.res_mem); + + /* User space allocated resources. + */ + if (resource->pid) { + /* Flush if requested */ + if (resource->res_cached && flush) { + dma_addr_t phys_addr = 0; + resource->res_stats[FLUSH]++; + + phys_addr = + (dma_addr_t)((uint32_t)resource->res_base_mem & + 0x3FFFFFFF); + phys_addr += (dma_addr_t)mm_vc_mem_phys_addr; + + /* L1 cache flush */ + down_read(¤t->mm->mmap_sem); + list_for_each_entry(map, &resource->map_list, + resource_map_list) { + if (map->vma) { + unsigned long start; + unsigned long end; + start = map->vma->vm_start; + end = map->vma->vm_end; + + vcsm_vma_cache_clean_page_range( + start, end); + } + } + up_read(¤t->mm->mmap_sem); + + /* L2 cache flush */ + outer_clean_range(phys_addr, + phys_addr + + (size_t) resource->res_size); + } + + /* We need to zap all the vmas associated with this resource */ + if (resource->lock_count == 1) { + down_read(¤t->mm->mmap_sem); + list_for_each_entry(map, &resource->map_list, + resource_map_list) { + if (map->vma) { + zap_vma_ptes(map->vma, + map->vma->vm_start, + map->vma->vm_end - + map->vma->vm_start); + } + } + up_read(¤t->mm->mmap_sem); + } + } + /* Kernel allocated resources. */ + else { + /* Global + Taken in this context */ + if (resource->ref_count == 2) { + if (!list_empty(&resource->map_list)) { + list_for_each_entry_safe(map, map_tmp, + &resource->map_list, + resource_map_list) { + if (map->res_addr) { + if (flush && + (resource->res_cached == + VMCS_SM_CACHE_HOST)) { + long unsigned int + phys_addr; + phys_addr = (uint32_t) + resource->res_base_mem & 0x3FFFFFFF; + phys_addr += + mm_vc_mem_phys_addr; + + /* L1 cache flush */ + dmac_flush_range((const + void + *) + map->res_addr, (const void *) + (map->res_addr + resource->res_size)); + + /* L2 cache flush */ + outer_clean_range + (phys_addr, + phys_addr + + (size_t) + resource->res_size); + } + + iounmap((void *)map->res_addr); + map->res_addr = 0; + + vmcs_sm_remove_map(sm_state, + map->resource, + map); + break; + } + } + } + } + } + + if (resource->lock_count) { + /* Bypass the videocore unlock. + */ + if (no_vc_unlock) + status = 0; + /* Unlock the videocore allocated resource. + */ + else { + status = + vc_vchi_sm_unlock(sm_state->sm_handle, &unlock, + &private->int_trans_id, + wait_reply); + if (status == -EINTR) { + pr_debug("[%s]: requesting unlock memory action restart (trans_id: %u)\n", + __func__, private->int_trans_id); + + ret = -ERESTARTSYS; + resource->res_stats[UNLOCK]--; + private->restart_sys = -EINTR; + private->int_action = VC_SM_MSG_TYPE_UNLOCK; + goto error; + } else if (status != 0) { + pr_err("[%s]: failed to unlock vc mem (status: %u, trans_id: %u)\n", + __func__, status, private->int_trans_id); + + ret = -EPERM; + resource->res_stats[UNLOCK_FAIL]++; + goto error; + } + } + + resource->res_stats[UNLOCK]++; + resource->lock_count--; + } + + pr_debug("[%s]: success to unlock data - hdl %x, base address %p, ref-cnt %d\n", + __func__, unlock.res_handle, unlock.res_mem, + resource->lock_count); + +error: + if (resource) + vmcs_sm_release_resource(resource, 0); + + return ret; +} + +/* Handle control from host. */ +static long vc_sm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + unsigned int cmdnr = _IOC_NR(cmd); + struct SM_PRIV_DATA_T *file_data = + (struct SM_PRIV_DATA_T *)file->private_data; + struct SM_RESOURCE_T *resource = NULL; + + /* Validate we can work with this device. */ + if ((sm_state == NULL) || (file_data == NULL)) { + pr_err("[%s]: invalid device\n", __func__); + ret = -EPERM; + goto out; + } + + pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr, + current->tgid, file_data->pid); + + /* Action is a re-post of a previously interrupted action? */ + if (file_data->restart_sys == -EINTR) { + VC_SM_ACTION_CLEAN_T action_clean; + + pr_debug("[%s]: clean up of action %u (trans_id: %u) following EINTR\n", + __func__, file_data->int_action, + file_data->int_trans_id); + + action_clean.res_action = file_data->int_action; + action_clean.action_trans_id = file_data->int_trans_id; + + vc_vchi_sm_clean_up(sm_state->sm_handle, &action_clean); + + file_data->restart_sys = 0; + } + + /* Now process the command. + */ + switch (cmdnr) { + /* New memory allocation. + */ + case VMCS_SM_CMD_ALLOC: + { + struct vmcs_sm_ioctl_alloc ioparam; + + /* Get the parameter data. + */ + if (copy_from_user + (&ioparam, (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + ret = vc_sm_ioctl_alloc(file_data, &ioparam); + if (!ret && + (copy_to_user((void *)arg, + &ioparam, sizeof(ioparam)) != 0)) { + struct vmcs_sm_ioctl_free freeparam = { + ioparam.handle + }; + pr_err("[%s]: failed to copy-to-user for cmd %x\n", + __func__, cmdnr); + vc_sm_ioctl_free(file_data, &freeparam); + ret = -EFAULT; + } + + /* Done. + */ + goto out; + } + break; + + /* Share existing memory allocation. + */ + case VMCS_SM_CMD_ALLOC_SHARE: + { + struct vmcs_sm_ioctl_alloc_share ioparam; + + /* Get the parameter data. + */ + if (copy_from_user + (&ioparam, (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + ret = vc_sm_ioctl_alloc_share(file_data, &ioparam); + + /* Copy result back to user. + */ + if (!ret + && copy_to_user((void *)arg, &ioparam, + sizeof(ioparam)) != 0) { + struct vmcs_sm_ioctl_free freeparam = { + ioparam.handle + }; + pr_err("[%s]: failed to copy-to-user for cmd %x\n", + __func__, cmdnr); + vc_sm_ioctl_free(file_data, &freeparam); + ret = -EFAULT; + } + + /* Done. + */ + goto out; + } + break; + + /* Lock (attempt to) *and* register a cache behavior change. + */ + case VMCS_SM_CMD_LOCK_CACHE: + { + struct vmcs_sm_ioctl_lock_cache ioparam; + struct vmcs_sm_ioctl_lock_unlock lock; + + /* Get parameter data. + */ + if (copy_from_user + (&ioparam, (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + lock.handle = ioparam.handle; + ret = + vc_sm_ioctl_lock(file_data, &lock, 1, + ioparam.cached, 0); + + /* Done. + */ + goto out; + } + break; + + /* Lock (attempt to) existing memory allocation. + */ + case VMCS_SM_CMD_LOCK: + { + struct vmcs_sm_ioctl_lock_unlock ioparam; + + /* Get parameter data. + */ + if (copy_from_user + (&ioparam, (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + ret = vc_sm_ioctl_lock(file_data, &ioparam, 0, 0, 0); + + /* Copy result back to user. + */ + if (copy_to_user((void *)arg, &ioparam, sizeof(ioparam)) + != 0) { + pr_err("[%s]: failed to copy-to-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + } + + /* Done. + */ + goto out; + } + break; + + /* Unlock (attempt to) existing memory allocation. + */ + case VMCS_SM_CMD_UNLOCK: + { + struct vmcs_sm_ioctl_lock_unlock ioparam; + + /* Get parameter data. + */ + if (copy_from_user + (&ioparam, (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + ret = vc_sm_ioctl_unlock(file_data, &ioparam, 0, 1, 0); + + /* Done. + */ + goto out; + } + break; + + /* Resize (attempt to) existing memory allocation. + */ + case VMCS_SM_CMD_RESIZE: + { + struct vmcs_sm_ioctl_resize ioparam; + + /* Get parameter data. + */ + if (copy_from_user + (&ioparam, (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + ret = vc_sm_ioctl_resize(file_data, &ioparam); + + /* Copy result back to user. + */ + if (copy_to_user((void *)arg, &ioparam, sizeof(ioparam)) + != 0) { + pr_err("[%s]: failed to copy-to-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + } + + /* Done. + */ + goto out; + } + break; + + /* Terminate existing memory allocation. + */ + case VMCS_SM_CMD_FREE: + { + struct vmcs_sm_ioctl_free ioparam; + + /* Get parameter data. + */ + if (copy_from_user + (&ioparam, (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + ret = vc_sm_ioctl_free(file_data, &ioparam); + + /* Done. + */ + goto out; + } + break; + + /* Walk allocation on videocore, information shows up in the + ** videocore log. + */ + case VMCS_SM_CMD_VC_WALK_ALLOC: + { + pr_debug("[%s]: invoking walk alloc\n", __func__); + + if (vc_vchi_sm_walk_alloc(sm_state->sm_handle) != 0) + pr_err("[%s]: failed to walk-alloc on videocore\n", + __func__); + + /* Done. + */ + goto out; + } + break; +/* Walk mapping table on host, information shows up in the + ** kernel log. + */ + case VMCS_SM_CMD_HOST_WALK_MAP: + { + /* Use pid of -1 to tell to walk the whole map. */ + vmcs_sm_host_walk_map_per_pid(-1); + + /* Done. */ + goto out; + } + break; + + /* Walk mapping table per process on host. */ + case VMCS_SM_CMD_HOST_WALK_PID_ALLOC: + { + struct vmcs_sm_ioctl_walk ioparam; + + /* Get parameter data. */ + if (copy_from_user(&ioparam, + (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + vmcs_sm_host_walk_alloc(file_data); + + /* Done. */ + goto out; + } + break; + + /* Walk allocation per process on host. */ + case VMCS_SM_CMD_HOST_WALK_PID_MAP: + { + struct vmcs_sm_ioctl_walk ioparam; + + /* Get parameter data. */ + if (copy_from_user(&ioparam, + (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + vmcs_sm_host_walk_map_per_pid(ioparam.pid); + + /* Done. */ + goto out; + } + break; + + /* Gets the size of the memory associated with a user handle. */ + case VMCS_SM_CMD_SIZE_USR_HANDLE: + { + struct vmcs_sm_ioctl_size ioparam; + + /* Get parameter data. */ + if (copy_from_user(&ioparam, + (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + /* Locate resource from GUID. */ + resource = + vmcs_sm_acquire_resource(file_data, ioparam.handle); + if (resource != NULL) { + ioparam.size = resource->res_size; + vmcs_sm_release_resource(resource, 0); + } else { + ioparam.size = 0; + } + + if (copy_to_user((void *)arg, + &ioparam, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-to-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + } + + /* Done. */ + goto out; + } + break; + + /* Verify we are dealing with a valid resource. */ + case VMCS_SM_CMD_CHK_USR_HANDLE: + { + struct vmcs_sm_ioctl_chk ioparam; + + /* Get parameter data. + */ + if (copy_from_user(&ioparam, + (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + + ret = -EFAULT; + goto out; + } + + /* Locate resource from GUID. */ + resource = + vmcs_sm_acquire_resource(file_data, ioparam.handle); + if (resource == NULL) + ret = -EINVAL; + /* If the resource is cacheable, return additional + * information that may be needed to flush the cache. + */ + else if ((resource->res_cached == VMCS_SM_CACHE_HOST) || + (resource->res_cached == VMCS_SM_CACHE_BOTH)) { + ioparam.addr = + vmcs_sm_usr_address_from_pid_and_usr_handle + (current->tgid, ioparam.handle); + ioparam.size = resource->res_size; + ioparam.cache = resource->res_cached; + } else { + ioparam.addr = 0; + ioparam.size = 0; + ioparam.cache = resource->res_cached; + } + + if (resource) + vmcs_sm_release_resource(resource, 0); + + if (copy_to_user((void *)arg, + &ioparam, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-to-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + } + + /* Done. + */ + goto out; + } + break; + + /* + * Maps a user handle given the process and the virtual address. + */ + case VMCS_SM_CMD_MAPPED_USR_HANDLE: + { + struct vmcs_sm_ioctl_map ioparam; + + /* Get parameter data. */ + if (copy_from_user(&ioparam, + (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + + ret = -EFAULT; + goto out; + } + + ioparam.handle = + vmcs_sm_usr_handle_from_pid_and_address( + ioparam.pid, ioparam.addr); + + resource = + vmcs_sm_acquire_resource(file_data, ioparam.handle); + if ((resource != NULL) + && ((resource->res_cached == VMCS_SM_CACHE_HOST) + || (resource->res_cached == + VMCS_SM_CACHE_BOTH))) { + ioparam.size = resource->res_size; + } else { + ioparam.size = 0; + } + + if (resource) + vmcs_sm_release_resource(resource, 0); + + if (copy_to_user((void *)arg, + &ioparam, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-to-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + } + + /* Done. */ + goto out; + } + break; + + /* + * Maps a videocore handle given process and virtual address. + */ + case VMCS_SM_CMD_MAPPED_VC_HDL_FROM_ADDR: + { + struct vmcs_sm_ioctl_map ioparam; + + /* Get parameter data. */ + if (copy_from_user(&ioparam, + (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + ioparam.handle = vmcs_sm_vc_handle_from_pid_and_address( + ioparam.pid, ioparam.addr); + + if (copy_to_user((void *)arg, + &ioparam, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-to-user for cmd %x\n", + __func__, cmdnr); + + ret = -EFAULT; + } + + /* Done. + */ + goto out; + } + break; + + /* Maps a videocore handle given process and user handle. */ + case VMCS_SM_CMD_MAPPED_VC_HDL_FROM_HDL: + { + struct vmcs_sm_ioctl_map ioparam; + + /* Get parameter data. */ + if (copy_from_user(&ioparam, + (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + /* Locate resource from GUID. */ + resource = + vmcs_sm_acquire_resource(file_data, ioparam.handle); + if (resource != NULL) { + ioparam.handle = resource->res_handle; + vmcs_sm_release_resource(resource, 0); + } else { + ioparam.handle = 0; + } + + if (copy_to_user((void *)arg, + &ioparam, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-to-user for cmd %x\n", + __func__, cmdnr); + + ret = -EFAULT; + } + + /* Done. */ + goto out; + } + break; + + /* + * Maps a videocore address given process and videocore handle. + */ + case VMCS_SM_CMD_MAPPED_VC_ADDR_FROM_HDL: + { + struct vmcs_sm_ioctl_map ioparam; + + /* Get parameter data. */ + if (copy_from_user(&ioparam, + (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + + ret = -EFAULT; + goto out; + } + + /* Locate resource from GUID. */ + resource = + vmcs_sm_acquire_resource(file_data, ioparam.handle); + if (resource != NULL) { + ioparam.addr = + (unsigned int)resource->res_base_mem; + vmcs_sm_release_resource(resource, 0); + } else { + ioparam.addr = 0; + } + + if (copy_to_user((void *)arg, + &ioparam, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-to-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + } + + /* Done. */ + goto out; + } + break; + + /* Maps a user address given process and vc handle. + */ + case VMCS_SM_CMD_MAPPED_USR_ADDRESS: + { + struct vmcs_sm_ioctl_map ioparam; + + /* Get parameter data. */ + if (copy_from_user(&ioparam, + (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + /* + * Return the address information from the mapping, + * 0 (ie NULL) if it cannot locate the actual mapping. + */ + ioparam.addr = + vmcs_sm_usr_address_from_pid_and_usr_handle + (ioparam.pid, ioparam.handle); + + if (copy_to_user((void *)arg, + &ioparam, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-to-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + } + + /* Done. */ + goto out; + } + break; + + /* Flush the cache for a given mapping. */ + case VMCS_SM_CMD_FLUSH: + { + struct vmcs_sm_ioctl_cache ioparam; + + /* Get parameter data. */ + if (copy_from_user(&ioparam, + (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + /* Locate resource from GUID. */ + resource = + vmcs_sm_acquire_resource(file_data, ioparam.handle); + + if ((resource != NULL) && resource->res_cached) { + dma_addr_t phys_addr = 0; + + resource->res_stats[FLUSH]++; + + phys_addr = + (dma_addr_t)((uint32_t) + resource->res_base_mem & + 0x3FFFFFFF); + phys_addr += (dma_addr_t)mm_vc_mem_phys_addr; + + /* L1 cache flush */ + down_read(¤t->mm->mmap_sem); + vcsm_vma_cache_clean_page_range((unsigned long) + ioparam.addr, + (unsigned long) + ioparam.addr + + ioparam.size); + up_read(¤t->mm->mmap_sem); + + /* L2 cache flush */ + outer_clean_range(phys_addr, + phys_addr + + (size_t) ioparam.size); + } else if (resource == NULL) { + ret = -EINVAL; + goto out; + } + + if (resource) + vmcs_sm_release_resource(resource, 0); + + /* Done. */ + goto out; + } + break; + + /* Invalidate the cache for a given mapping. */ + case VMCS_SM_CMD_INVALID: + { + struct vmcs_sm_ioctl_cache ioparam; + + /* Get parameter data. */ + if (copy_from_user(&ioparam, + (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + + /* Locate resource from GUID. + */ + resource = + vmcs_sm_acquire_resource(file_data, ioparam.handle); + + if ((resource != NULL) && resource->res_cached) { + dma_addr_t phys_addr = 0; + + resource->res_stats[INVALID]++; + + phys_addr = + (dma_addr_t)((uint32_t) + resource->res_base_mem & + 0x3FFFFFFF); + phys_addr += (dma_addr_t)mm_vc_mem_phys_addr; + + /* L2 cache invalidate */ + outer_inv_range(phys_addr, + phys_addr + + (size_t) ioparam.size); + + /* L1 cache invalidate */ + down_read(¤t->mm->mmap_sem); + vcsm_vma_cache_clean_page_range((unsigned long) + ioparam.addr, + (unsigned long) + ioparam.addr + + ioparam.size); + up_read(¤t->mm->mmap_sem); + } else if (resource == NULL) { + ret = -EINVAL; + goto out; + } + + if (resource) + vmcs_sm_release_resource(resource, 0); + + /* Done. + */ + goto out; + } + break; + + /* Flush/Invalidate the cache for a given mapping. */ + case VMCS_SM_CMD_CLEAN_INVALID: + { + int i; + struct vmcs_sm_ioctl_clean_invalid ioparam; + + /* Get parameter data. */ + if (copy_from_user(&ioparam, + (void *)arg, sizeof(ioparam)) != 0) { + pr_err("[%s]: failed to copy-from-user for cmd %x\n", + __func__, cmdnr); + ret = -EFAULT; + goto out; + } + for (i=0; ires_cached) { + unsigned long base = ioparam.s[i].addr & ~(PAGE_SIZE-1); + unsigned long end = (ioparam.s[i].addr + ioparam.s[i].size + PAGE_SIZE-1) & ~(PAGE_SIZE-1); + resource->res_stats[ioparam.s[i].cmd == 1 ? INVALID:FLUSH]++; + + /* L1/L2 cache flush */ + down_read(¤t->mm->mmap_sem); + vcsm_vma_cache_clean_page_range(base, end); + up_read(¤t->mm->mmap_sem); + } else if (resource == NULL) { + ret = -EINVAL; + goto out; + } + + if (resource) + vmcs_sm_release_resource(resource, 0); + } + break; + } + } + } + break; + + default: + { + ret = -EINVAL; + goto out; + } + break; + } + +out: + return ret; +} + +/* Device operations that we managed in this driver. +*/ +static const struct file_operations vmcs_sm_ops = { + .owner = THIS_MODULE, + .unlocked_ioctl = vc_sm_ioctl, + .open = vc_sm_open, + .release = vc_sm_release, + .mmap = vc_sm_mmap, +}; + +/* Creation of device. +*/ +static int vc_sm_create_sharedmemory(void) +{ + int ret; + + if (sm_state == NULL) { + ret = -ENOMEM; + goto out; + } + + /* Create a device class for creating dev nodes. + */ + sm_state->sm_class = class_create(THIS_MODULE, "vc-sm"); + if (IS_ERR(sm_state->sm_class)) { + pr_err("[%s]: unable to create device class\n", __func__); + ret = PTR_ERR(sm_state->sm_class); + goto out; + } + + /* Create a character driver. + */ + ret = alloc_chrdev_region(&sm_state->sm_devid, + DEVICE_MINOR, 1, DEVICE_NAME); + if (ret != 0) { + pr_err("[%s]: unable to allocate device number\n", __func__); + goto out_dev_class_destroy; + } + + cdev_init(&sm_state->sm_cdev, &vmcs_sm_ops); + ret = cdev_add(&sm_state->sm_cdev, sm_state->sm_devid, 1); + if (ret != 0) { + pr_err("[%s]: unable to register device\n", __func__); + goto out_chrdev_unreg; + } + + /* Create a device node. + */ + sm_state->sm_dev = device_create(sm_state->sm_class, + NULL, + MKDEV(MAJOR(sm_state->sm_devid), + DEVICE_MINOR), NULL, + DEVICE_NAME); + if (IS_ERR(sm_state->sm_dev)) { + pr_err("[%s]: unable to create device node\n", __func__); + ret = PTR_ERR(sm_state->sm_dev); + goto out_chrdev_del; + } + + goto out; + +out_chrdev_del: + cdev_del(&sm_state->sm_cdev); +out_chrdev_unreg: + unregister_chrdev_region(sm_state->sm_devid, 1); +out_dev_class_destroy: + class_destroy(sm_state->sm_class); + sm_state->sm_class = NULL; +out: + return ret; +} + +/* Termination of the device. +*/ +static int vc_sm_remove_sharedmemory(void) +{ + int ret; + + if (sm_state == NULL) { + /* Nothing to do. + */ + ret = 0; + goto out; + } + + /* Remove the sharedmemory character driver. + */ + cdev_del(&sm_state->sm_cdev); + + /* Unregister region. + */ + unregister_chrdev_region(sm_state->sm_devid, 1); + + ret = 0; + goto out; + +out: + return ret; +} + +/* Videocore connected. */ +static void vc_sm_connected_init(void) +{ + int ret; + VCHI_INSTANCE_T vchi_instance; + VCHI_CONNECTION_T *vchi_connection = NULL; + + pr_info("[%s]: start\n", __func__); + + /* Allocate memory for the state structure. + */ + sm_state = kzalloc(sizeof(struct SM_STATE_T), GFP_KERNEL); + if (sm_state == NULL) { + pr_err("[%s]: failed to allocate memory\n", __func__); + ret = -ENOMEM; + goto out; + } + + mutex_init(&sm_state->lock); + mutex_init(&sm_state->map_lock); + + /* Initialize and create a VCHI connection for the shared memory service + ** running on videocore. + */ + ret = vchi_initialise(&vchi_instance); + if (ret != 0) { + pr_err("[%s]: failed to initialise VCHI instance (ret=%d)\n", + __func__, ret); + + ret = -EIO; + goto err_free_mem; + } + + ret = vchi_connect(NULL, 0, vchi_instance); + if (ret != 0) { + pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n", + __func__, ret); + + ret = -EIO; + goto err_free_mem; + } + + /* Initialize an instance of the shared memory service. */ + sm_state->sm_handle = + vc_vchi_sm_init(vchi_instance, &vchi_connection, 1); + if (sm_state->sm_handle == NULL) { + pr_err("[%s]: failed to initialize shared memory service\n", + __func__); + + ret = -EPERM; + goto err_free_mem; + } + + /* Create a debug fs directory entry (root). */ + sm_state->dir_root = debugfs_create_dir(VC_SM_DIR_ROOT_NAME, NULL); + if (!sm_state->dir_root) { + pr_err("[%s]: failed to create \'%s\' directory entry\n", + __func__, VC_SM_DIR_ROOT_NAME); + + ret = -EPERM; + goto err_stop_sm_service; + } + + sm_state->dir_state.show = &vc_sm_global_state_show; + sm_state->dir_state.dir_entry = debugfs_create_file(VC_SM_STATE, + S_IRUGO, sm_state->dir_root, &sm_state->dir_state, + &vc_sm_debug_fs_fops); + + sm_state->dir_stats.show = &vc_sm_global_statistics_show; + sm_state->dir_stats.dir_entry = debugfs_create_file(VC_SM_STATS, + S_IRUGO, sm_state->dir_root, &sm_state->dir_stats, + &vc_sm_debug_fs_fops); + + /* Create the proc entry children. */ + sm_state->dir_alloc = debugfs_create_dir(VC_SM_DIR_ALLOC_NAME, + sm_state->dir_root); + + /* Create a shared memory device. */ + ret = vc_sm_create_sharedmemory(); + if (ret != 0) { + pr_err("[%s]: failed to create shared memory device\n", + __func__); + goto err_remove_debugfs; + } + + INIT_LIST_HEAD(&sm_state->map_list); + INIT_LIST_HEAD(&sm_state->resource_list); + + sm_state->data_knl = vc_sm_create_priv_data(0); + if (sm_state->data_knl == NULL) { + pr_err("[%s]: failed to create kernel private data tracker\n", + __func__); + goto err_remove_shared_memory; + } + + /* Done! + */ + sm_inited = 1; + goto out; + +err_remove_shared_memory: + vc_sm_remove_sharedmemory(); +err_remove_debugfs: + debugfs_remove_recursive(sm_state->dir_root); +err_stop_sm_service: + vc_vchi_sm_stop(&sm_state->sm_handle); +err_free_mem: + kfree(sm_state); +out: + pr_info("[%s]: end - returning %d\n", __func__, ret); +} + +/* Driver loading. */ +static int __init vc_sm_init(void) +{ + pr_info("vc-sm: Videocore shared memory driver\n"); + vchiq_add_connected_callback(vc_sm_connected_init); + return 0; +} + +/* Driver unloading. */ +static void __exit vc_sm_exit(void) +{ + pr_debug("[%s]: start\n", __func__); + if (sm_inited) { + /* Remove shared memory device. + */ + vc_sm_remove_sharedmemory(); + + /* Remove all proc entries. + */ + debugfs_remove_recursive(sm_state->dir_root); + + /* Stop the videocore shared memory service. + */ + vc_vchi_sm_stop(&sm_state->sm_handle); + + /* Free the memory for the state structure. + */ + mutex_destroy(&(sm_state->map_lock)); + kfree(sm_state); + } + + pr_debug("[%s]: end\n", __func__); +} + +#if defined(__KERNEL__) +/* Allocate a shared memory handle and block. */ +int vc_sm_alloc(VC_SM_ALLOC_T *alloc, int *handle) +{ + struct vmcs_sm_ioctl_alloc ioparam = { 0 }; + int ret; + struct SM_RESOURCE_T *resource; + + /* Validate we can work with this device. + */ + if (sm_state == NULL || alloc == NULL || handle == NULL) { + pr_err("[%s]: invalid input\n", __func__); + return -EPERM; + } + + ioparam.size = alloc->base_unit; + ioparam.num = alloc->num_unit; + ioparam.cached = + alloc->type == VC_SM_ALLOC_CACHED ? VMCS_SM_CACHE_VC : 0; + + ret = vc_sm_ioctl_alloc(sm_state->data_knl, &ioparam); + + if (ret == 0) { + resource = + vmcs_sm_acquire_resource(sm_state->data_knl, + ioparam.handle); + if (resource) { + resource->pid = 0; + vmcs_sm_release_resource(resource, 0); + + /* Assign valid handle at this time. + */ + *handle = ioparam.handle; + } else { + ret = -ENOMEM; + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(vc_sm_alloc); + +/* Get an internal resource handle mapped from the external one. +*/ +int vc_sm_int_handle(int handle) +{ + struct SM_RESOURCE_T *resource; + int ret = 0; + + /* Validate we can work with this device. + */ + if (sm_state == NULL || handle == 0) { + pr_err("[%s]: invalid input\n", __func__); + return 0; + } + + /* Locate resource from GUID. + */ + resource = vmcs_sm_acquire_resource(sm_state->data_knl, handle); + if (resource) { + ret = resource->res_handle; + vmcs_sm_release_resource(resource, 0); + } + + return ret; +} +EXPORT_SYMBOL_GPL(vc_sm_int_handle); + +/* Free a previously allocated shared memory handle and block. +*/ +int vc_sm_free(int handle) +{ + struct vmcs_sm_ioctl_free ioparam = { handle }; + + /* Validate we can work with this device. + */ + if (sm_state == NULL || handle == 0) { + pr_err("[%s]: invalid input\n", __func__); + return -EPERM; + } + + return vc_sm_ioctl_free(sm_state->data_knl, &ioparam); +} +EXPORT_SYMBOL_GPL(vc_sm_free); + +/* Lock a memory handle for use by kernel. +*/ +int vc_sm_lock(int handle, VC_SM_LOCK_CACHE_MODE_T mode, + long unsigned int *data) +{ + struct vmcs_sm_ioctl_lock_unlock ioparam; + int ret; + + /* Validate we can work with this device. + */ + if (sm_state == NULL || handle == 0 || data == NULL) { + pr_err("[%s]: invalid input\n", __func__); + return -EPERM; + } + + *data = 0; + + ioparam.handle = handle; + ret = vc_sm_ioctl_lock(sm_state->data_knl, + &ioparam, + 1, + ((mode == + VC_SM_LOCK_CACHED) ? VMCS_SM_CACHE_HOST : + VMCS_SM_CACHE_NONE), 0); + + *data = ioparam.addr; + return ret; +} +EXPORT_SYMBOL_GPL(vc_sm_lock); + +/* Unlock a memory handle in use by kernel. +*/ +int vc_sm_unlock(int handle, int flush, int no_vc_unlock) +{ + struct vmcs_sm_ioctl_lock_unlock ioparam; + + /* Validate we can work with this device. + */ + if (sm_state == NULL || handle == 0) { + pr_err("[%s]: invalid input\n", __func__); + return -EPERM; + } + + ioparam.handle = handle; + return vc_sm_ioctl_unlock(sm_state->data_knl, + &ioparam, flush, 0, no_vc_unlock); +} +EXPORT_SYMBOL_GPL(vc_sm_unlock); + +/* Map a shared memory region for use by kernel. +*/ +int vc_sm_map(int handle, unsigned int sm_addr, VC_SM_LOCK_CACHE_MODE_T mode, + long unsigned int *data) +{ + struct vmcs_sm_ioctl_lock_unlock ioparam; + int ret; + + /* Validate we can work with this device. + */ + if (sm_state == NULL || handle == 0 || data == NULL || sm_addr == 0) { + pr_err("[%s]: invalid input\n", __func__); + return -EPERM; + } + + *data = 0; + + ioparam.handle = handle; + ret = vc_sm_ioctl_lock(sm_state->data_knl, + &ioparam, + 1, + ((mode == + VC_SM_LOCK_CACHED) ? VMCS_SM_CACHE_HOST : + VMCS_SM_CACHE_NONE), sm_addr); + + *data = ioparam.addr; + return ret; +} +EXPORT_SYMBOL_GPL(vc_sm_map); +#endif + +late_initcall(vc_sm_init); +module_exit(vc_sm_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("VideoCore SharedMemory Driver"); +MODULE_LICENSE("GPL v2"); diff -Nur '--exclude=.git' linux-stable/drivers/char/hw_random/bcm2708-rng.c raspilinux/drivers/char/hw_random/bcm2708-rng.c --- linux-stable/drivers/char/hw_random/bcm2708-rng.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/char/hw_random/bcm2708-rng.c 2015-12-26 19:08:31.152666013 +0100 @@ -0,0 +1,118 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define RNG_CTRL (0x0) +#define RNG_STATUS (0x4) +#define RNG_DATA (0x8) +#define RNG_FF_THRESHOLD (0xc) + +/* enable rng */ +#define RNG_RBGEN 0x1 +/* double speed, less random mode */ +#define RNG_RBG2X 0x2 + +/* the initial numbers generated are "less random" so will be discarded */ +#define RNG_WARMUP_COUNT 0x40000 + +static int bcm2708_rng_data_read(struct hwrng *rng, u32 *buffer) +{ + void __iomem *rng_base = (void __iomem *)rng->priv; + unsigned words; + /* wait for a random number to be in fifo */ + do { + words = __raw_readl(rng_base + RNG_STATUS)>>24; + } + while (words == 0); + /* read the random number */ + *buffer = __raw_readl(rng_base + RNG_DATA); + return 4; +} + +static struct hwrng bcm2708_rng_ops = { + .name = "bcm2708", + .data_read = bcm2708_rng_data_read, +}; + +static int __init bcm2708_rng_init(void) +{ + void __iomem *rng_base; + int err; + + /* map peripheral */ + rng_base = ioremap(RNG_BASE, 0x10); + pr_info("bcm2708_rng_init=%p\n", rng_base); + if (!rng_base) { + pr_err("bcm2708_rng_init failed to ioremap\n"); + return -ENOMEM; + } + bcm2708_rng_ops.priv = (unsigned long)rng_base; + + /* set warm-up count & enable */ + __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS); + __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL); + + /* register driver */ + err = hwrng_register(&bcm2708_rng_ops); + if (err) { + pr_err("bcm2708_rng_init hwrng_register()=%d\n", err); + iounmap(rng_base); + } + return err; +} + +static void __exit bcm2708_rng_exit(void) +{ + void __iomem *rng_base = (void __iomem *)bcm2708_rng_ops.priv; + pr_info("bcm2708_rng_exit\n"); + /* disable rng hardware */ + __raw_writel(0, rng_base + RNG_CTRL); + /* unregister driver */ + hwrng_unregister(&bcm2708_rng_ops); + iounmap(rng_base); +} + +module_init(bcm2708_rng_init); +module_exit(bcm2708_rng_exit); + +MODULE_DESCRIPTION("BCM2708 H/W Random Number Generator (RNG) driver"); +MODULE_LICENSE("GPL and additional rights"); diff -Nur '--exclude=.git' linux-stable/drivers/char/hw_random/Kconfig raspilinux/drivers/char/hw_random/Kconfig --- linux-stable/drivers/char/hw_random/Kconfig 2015-12-26 20:45:00.295993230 +0100 +++ raspilinux/drivers/char/hw_random/Kconfig 2015-12-26 19:08:31.152666013 +0100 @@ -90,7 +90,7 @@ config HW_RANDOM_BCM2835 tristate "Broadcom BCM2835 Random Number Generator support" - depends on ARCH_BCM2835 + depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 default HW_RANDOM ---help--- This driver provides kernel-side support for the Random Number @@ -333,6 +333,17 @@ If unsure, say Y. +config HW_RANDOM_BCM2708 + tristate "BCM2708 generic true random number generator support" + depends on HW_RANDOM && (ARCH_BCM2708 || ARCH_BCM2709) + ---help--- + This driver provides the kernel-side support for the BCM2708 hardware. + + To compile this driver as a module, choose M here: the + module will be called bcm2708-rng. + + If unsure, say N. + config HW_RANDOM_MSM tristate "Qualcomm SoCs Random Number Generator support" depends on HW_RANDOM && ARCH_QCOM diff -Nur '--exclude=.git' linux-stable/drivers/char/hw_random/Makefile raspilinux/drivers/char/hw_random/Makefile --- linux-stable/drivers/char/hw_random/Makefile 2015-12-26 20:45:00.295993230 +0100 +++ raspilinux/drivers/char/hw_random/Makefile 2015-12-26 19:08:31.152666013 +0100 @@ -4,6 +4,7 @@ obj-$(CONFIG_HW_RANDOM) += rng-core.o rng-core-y := core.o +obj-$(CONFIG_HW_RANDOM_BCM2708) += bcm2708-rng.o obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o diff -Nur '--exclude=.git' linux-stable/drivers/char/Kconfig raspilinux/drivers/char/Kconfig --- linux-stable/drivers/char/Kconfig 2015-12-26 20:45:00.291993599 +0100 +++ raspilinux/drivers/char/Kconfig 2015-12-26 19:08:31.144666759 +0100 @@ -590,6 +590,8 @@ source "drivers/s390/char/Kconfig" +source "drivers/char/broadcom/Kconfig" + config MSM_SMD_PKT bool "Enable device interface for some SMD packet ports" default n diff -Nur '--exclude=.git' linux-stable/drivers/char/Makefile raspilinux/drivers/char/Makefile --- linux-stable/drivers/char/Makefile 2015-12-26 20:45:00.291993599 +0100 +++ raspilinux/drivers/char/Makefile 2015-12-26 19:08:31.144666759 +0100 @@ -62,3 +62,4 @@ obj-$(CONFIG_TILE_SROM) += tile-srom.o obj-$(CONFIG_XILLYBUS) += xillybus/ +obj-$(CONFIG_BRCM_CHAR_DRIVERS) += broadcom/ diff -Nur '--exclude=.git' linux-stable/drivers/clk/clk-hifiberry-dacpro.c raspilinux/drivers/clk/clk-hifiberry-dacpro.c --- linux-stable/drivers/clk/clk-hifiberry-dacpro.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/clk/clk-hifiberry-dacpro.c 2015-12-26 19:08:31.164664894 +0100 @@ -0,0 +1,160 @@ +/* + * Clock Driver for HiFiBerry DAC Pro + * + * Author: Stuart MacLean + * Copyright 2015 + * + * This program is free software; you can 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 +#include +#include +#include +#include +#include +#include + +/* Clock rate of CLK44EN attached to GPIO6 pin */ +#define CLK_44EN_RATE 22579200UL +/* Clock rate of CLK48EN attached to GPIO3 pin */ +#define CLK_48EN_RATE 24576000UL + +/** + * struct hifiberry_dacpro_clk - Common struct to the HiFiBerry DAC Pro + * @hw: clk_hw for the common clk framework + * @mode: 0 => CLK44EN, 1 => CLK48EN + */ +struct clk_hifiberry_hw { + struct clk_hw hw; + uint8_t mode; +}; + +#define to_hifiberry_clk(_hw) container_of(_hw, struct clk_hifiberry_hw, hw) + +static const struct of_device_id clk_hifiberry_dacpro_dt_ids[] = { + { .compatible = "hifiberry,dacpro-clk",}, + { } +}; +MODULE_DEVICE_TABLE(of, clk_hifiberry_dacpro_dt_ids); + +static unsigned long clk_hifiberry_dacpro_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return (to_hifiberry_clk(hw)->mode == 0) ? CLK_44EN_RATE : + CLK_48EN_RATE; +} + +static long clk_hifiberry_dacpro_round_rate(struct clk_hw *hw, + unsigned long rate, unsigned long *parent_rate) +{ + long actual_rate; + + if (rate <= CLK_44EN_RATE) { + actual_rate = (long)CLK_44EN_RATE; + } else if (rate >= CLK_48EN_RATE) { + actual_rate = (long)CLK_48EN_RATE; + } else { + long diff44Rate = (long)(rate - CLK_44EN_RATE); + long diff48Rate = (long)(CLK_48EN_RATE - rate); + + if (diff44Rate < diff48Rate) + actual_rate = (long)CLK_44EN_RATE; + else + actual_rate = (long)CLK_48EN_RATE; + } + return actual_rate; +} + + +static int clk_hifiberry_dacpro_set_rate(struct clk_hw *hw, + unsigned long rate, unsigned long parent_rate) +{ + unsigned long actual_rate; + struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw); + + actual_rate = (unsigned long)clk_hifiberry_dacpro_round_rate(hw, rate, + &parent_rate); + clk->mode = (actual_rate == CLK_44EN_RATE) ? 0 : 1; + return 0; +} + + +const struct clk_ops clk_hifiberry_dacpro_rate_ops = { + .recalc_rate = clk_hifiberry_dacpro_recalc_rate, + .round_rate = clk_hifiberry_dacpro_round_rate, + .set_rate = clk_hifiberry_dacpro_set_rate, +}; + +static int clk_hifiberry_dacpro_probe(struct platform_device *pdev) +{ + int ret; + struct clk_hifiberry_hw *proclk; + struct clk *clk; + struct device *dev; + struct clk_init_data init; + + dev = &pdev->dev; + + proclk = kzalloc(sizeof(struct clk_hifiberry_hw), GFP_KERNEL); + if (!proclk) + return -ENOMEM; + + init.name = "clk-hifiberry-dacpro"; + init.ops = &clk_hifiberry_dacpro_rate_ops; + init.flags = CLK_IS_ROOT | CLK_IS_BASIC; + init.parent_names = NULL; + init.num_parents = 0; + + proclk->mode = 0; + proclk->hw.init = &init; + + clk = devm_clk_register(dev, &proclk->hw); + if (!IS_ERR(clk)) { + ret = of_clk_add_provider(dev->of_node, of_clk_src_simple_get, + clk); + } else { + dev_err(dev, "Fail to register clock driver\n"); + kfree(proclk); + ret = PTR_ERR(clk); + } + return ret; +} + +static int clk_hifiberry_dacpro_remove(struct platform_device *pdev) +{ + of_clk_del_provider(pdev->dev.of_node); + return 0; +} + +static struct platform_driver clk_hifiberry_dacpro_driver = { + .probe = clk_hifiberry_dacpro_probe, + .remove = clk_hifiberry_dacpro_remove, + .driver = { + .name = "clk-hifiberry-dacpro", + .of_match_table = clk_hifiberry_dacpro_dt_ids, + }, +}; + +static int __init clk_hifiberry_dacpro_init(void) +{ + return platform_driver_register(&clk_hifiberry_dacpro_driver); +} +core_initcall(clk_hifiberry_dacpro_init); + +static void __exit clk_hifiberry_dacpro_exit(void) +{ + platform_driver_unregister(&clk_hifiberry_dacpro_driver); +} +module_exit(clk_hifiberry_dacpro_exit); + +MODULE_DESCRIPTION("HiFiBerry DAC Pro clock driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:clk-hifiberry-dacpro"); diff -Nur '--exclude=.git' linux-stable/drivers/clk/Makefile raspilinux/drivers/clk/Makefile --- linux-stable/drivers/clk/Makefile 2015-12-26 20:45:00.307992124 +0100 +++ raspilinux/drivers/clk/Makefile 2015-12-26 19:08:31.160665267 +0100 @@ -24,6 +24,7 @@ obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += clk-hifiberry-dacpro.o obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o diff -Nur '--exclude=.git' linux-stable/drivers/clocksource/arm_arch_timer.c raspilinux/drivers/clocksource/arm_arch_timer.c --- linux-stable/drivers/clocksource/arm_arch_timer.c 2015-12-26 20:45:00.351988069 +0100 +++ raspilinux/drivers/clocksource/arm_arch_timer.c 2015-12-26 19:08:31.184663029 +0100 @@ -882,3 +882,39 @@ acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init); } #endif + +int __init dc4_arch_timer_init(void) +{ + if (arch_timers_present & ARCH_CP15_TIMER) { + pr_warn("arch_timer: multiple nodes in dt, skipping\n"); + return -1; + } + + arch_timers_present |= ARCH_CP15_TIMER; + + /* Try to determine the frequency from the device tree or CNTFRQ */ + arch_timer_rate = 19200000; + + arch_timer_ppi[PHYS_SECURE_PPI] = IRQ_ARM_LOCAL_CNTPSIRQ; + arch_timer_ppi[PHYS_NONSECURE_PPI] = IRQ_ARM_LOCAL_CNTPNSIRQ; + arch_timer_ppi[VIRT_PPI] = IRQ_ARM_LOCAL_CNTVIRQ; + arch_timer_ppi[HYP_PPI] = IRQ_ARM_LOCAL_CNTHPIRQ; + + /* + * If HYP mode is available, we know that the physical timer + * has been configured to be accessible from PL1. Use it, so + * that a guest can use the virtual timer instead. + * + * If no interrupt provided for virtual timer, we'll have to + * stick to the physical timer. It'd better be accessible... + */ + if (is_hyp_mode_available() || !arch_timer_ppi[VIRT_PPI]) { + arch_timer_use_virtual = false; + } + + arch_timer_c3stop = 0; + + arch_timer_register(); + arch_timer_common_init(); + return 0; +} diff -Nur '--exclude=.git' linux-stable/drivers/cpufreq/bcm2835-cpufreq.c raspilinux/drivers/cpufreq/bcm2835-cpufreq.c --- linux-stable/drivers/cpufreq/bcm2835-cpufreq.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/cpufreq/bcm2835-cpufreq.c 2015-12-26 19:08:31.188662656 +0100 @@ -0,0 +1,213 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/***************************************************************************** +* FILENAME: bcm2835-cpufreq.h +* DESCRIPTION: This driver dynamically manages the CPU Frequency of the ARM +* processor. Messages are sent to Videocore either setting or requesting the +* frequency of the ARM in order to match an appropiate frequency to the current +* usage of the processor. The policy which selects the frequency to use is +* defined in the kernel .config file, but can be changed during runtime. +*****************************************************************************/ + +/* ---------- INCLUDES ---------- */ +#include +#include +#include +#include +#include + +/* ---------- DEFINES ---------- */ +/*#define CPUFREQ_DEBUG_ENABLE*/ /* enable debugging */ +#define MODULE_NAME "bcm2835-cpufreq" + +#define VCMSG_ID_ARM_CLOCK 0x000000003 /* Clock/Voltage ID's */ + +/* debug printk macros */ +#ifdef CPUFREQ_DEBUG_ENABLE +#define print_debug(fmt,...) pr_debug("%s:%s:%d: "fmt, MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__) +#else +#define print_debug(fmt,...) +#endif +#define print_err(fmt,...) pr_err("%s:%s:%d: "fmt, MODULE_NAME, __func__,__LINE__, ##__VA_ARGS__) +#define print_info(fmt,...) pr_info("%s: "fmt, MODULE_NAME, ##__VA_ARGS__) + +/* ---------- GLOBALS ---------- */ +static struct cpufreq_driver bcm2835_cpufreq_driver; /* the cpufreq driver global */ + +static struct cpufreq_frequency_table bcm2835_freq_table[] = { + {0, 0, 0}, + {0, 0, 0}, + {0, 0, CPUFREQ_TABLE_END}, +}; + +/* + =============================================== + clk_rate either gets or sets the clock rates. + =============================================== +*/ + +static int bcm2835_cpufreq_clock_property(u32 tag, u32 id, u32 *val) +{ + struct rpi_firmware *fw = rpi_firmware_get(NULL); + struct { + u32 id; + u32 val; + } packet; + int ret; + + packet.id = id; + packet.val = *val; + ret = rpi_firmware_property(fw, tag, &packet, sizeof(packet)); + if (ret) + return ret; + + *val = packet.val; + + return 0; +} + +static uint32_t bcm2835_cpufreq_set_clock(int cur_rate, int arm_rate) +{ + u32 rate = arm_rate * 1000; + int ret; + + ret = bcm2835_cpufreq_clock_property(RPI_FIRMWARE_SET_CLOCK_RATE, VCMSG_ID_ARM_CLOCK, &rate); + if (ret) { + print_err("Failed to set clock: %d (%d)\n", arm_rate, ret); + return 0; + } + + rate /= 1000; + print_debug("Setting new frequency = %d -> %d (actual %d)\n", cur_rate, arm_rate, rate); + + return rate; +} + +static uint32_t bcm2835_cpufreq_get_clock(int tag) +{ + u32 rate; + int ret; + + ret = bcm2835_cpufreq_clock_property(tag, VCMSG_ID_ARM_CLOCK, &rate); + if (ret) { + print_err("Failed to get clock (%d)\n", ret); + return 0; + } + + rate /= 1000; + print_debug("%s frequency = %u\n", + tag == RPI_FIRMWARE_GET_CLOCK_RATE ? "Current": + tag == RPI_FIRMWARE_GET_MIN_CLOCK_RATE ? "Min": + tag == RPI_FIRMWARE_GET_MAX_CLOCK_RATE ? "Max": + "Unexpected", rate); + + return rate; +} + +/* + ==================================================== + Module Initialisation registers the cpufreq driver + ==================================================== +*/ +static int __init bcm2835_cpufreq_module_init(void) +{ + print_debug("IN\n"); + return cpufreq_register_driver(&bcm2835_cpufreq_driver); +} + +/* + ============= + Module exit + ============= +*/ +static void __exit bcm2835_cpufreq_module_exit(void) +{ + print_debug("IN\n"); + cpufreq_unregister_driver(&bcm2835_cpufreq_driver); + return; +} + +/* + ============================================================== + Initialisation function sets up the CPU policy for first use + ============================================================== +*/ +static int bcm2835_cpufreq_driver_init(struct cpufreq_policy *policy) +{ + /* measured value of how long it takes to change frequency */ + const unsigned int transition_latency = 355000; /* ns */ + + if (!rpi_firmware_get(NULL)) { + print_err("Firmware is not available\n"); + return -ENODEV; + } + + /* now find out what the maximum and minimum frequencies are */ + bcm2835_freq_table[0].frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MIN_CLOCK_RATE); + bcm2835_freq_table[1].frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MAX_CLOCK_RATE); + + print_info("min=%d max=%d\n", bcm2835_freq_table[0].frequency, bcm2835_freq_table[1].frequency); + return cpufreq_generic_init(policy, bcm2835_freq_table, transition_latency); +} + +/* + ===================================================================== + Target index function chooses the requested frequency from the table + ===================================================================== +*/ + +static int bcm2835_cpufreq_driver_target_index(struct cpufreq_policy *policy, unsigned int state) +{ + unsigned int target_freq = bcm2835_freq_table[state].frequency; + unsigned int cur = bcm2835_cpufreq_set_clock(policy->cur, target_freq); + + if (!cur) + { + print_err("Error occurred setting a new frequency (%d)\n", target_freq); + return -EINVAL; + } + print_debug("%s: %i: freq %d->%d\n", policy->governor->name, state, policy->cur, cur); + return 0; +} + +/* + ====================================================== + Get function returns the current frequency from table + ====================================================== +*/ + +static unsigned int bcm2835_cpufreq_driver_get(unsigned int cpu) +{ + unsigned int actual_rate = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_CLOCK_RATE); + print_debug("cpu%d: freq=%d\n", cpu, actual_rate); + return actual_rate <= bcm2835_freq_table[0].frequency ? bcm2835_freq_table[0].frequency : bcm2835_freq_table[1].frequency; +} + +/* the CPUFreq driver */ +static struct cpufreq_driver bcm2835_cpufreq_driver = { + .name = "BCM2835 CPUFreq", + .init = bcm2835_cpufreq_driver_init, + .verify = cpufreq_generic_frequency_table_verify, + .target_index = bcm2835_cpufreq_driver_target_index, + .get = bcm2835_cpufreq_driver_get, + .attr = cpufreq_generic_attr, +}; + +MODULE_AUTHOR("Dorian Peake and Dom Cobley"); +MODULE_DESCRIPTION("CPU frequency driver for BCM2835 chip"); +MODULE_LICENSE("GPL"); + +module_init(bcm2835_cpufreq_module_init); +module_exit(bcm2835_cpufreq_module_exit); diff -Nur '--exclude=.git' linux-stable/drivers/cpufreq/Kconfig.arm raspilinux/drivers/cpufreq/Kconfig.arm --- linux-stable/drivers/cpufreq/Kconfig.arm 2015-12-26 20:45:00.359987332 +0100 +++ raspilinux/drivers/cpufreq/Kconfig.arm 2015-12-26 19:08:31.188662656 +0100 @@ -258,6 +258,15 @@ help This adds the CPUFreq driver support for SPEAr SOCs. +config ARM_BCM2835_CPUFREQ + depends on RASPBERRYPI_FIRMWARE + bool "BCM2835 Driver" + default y + help + This adds the CPUFreq driver for BCM2835 + + If in doubt, say N. + config ARM_TEGRA_CPUFREQ bool "TEGRA CPUFreq support" depends on ARCH_TEGRA diff -Nur '--exclude=.git' linux-stable/drivers/cpufreq/Makefile raspilinux/drivers/cpufreq/Makefile --- linux-stable/drivers/cpufreq/Makefile 2015-12-26 20:45:00.359987332 +0100 +++ raspilinux/drivers/cpufreq/Makefile 2015-12-26 19:08:31.188662656 +0100 @@ -77,6 +77,7 @@ obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o +obj-$(CONFIG_ARM_BCM2835_CPUFREQ) += bcm2835-cpufreq.o obj-$(CONFIG_ARM_TEGRA_CPUFREQ) += tegra-cpufreq.o obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o diff -Nur '--exclude=.git' linux-stable/drivers/dma/bcm2708-dmaengine.c raspilinux/drivers/dma/bcm2708-dmaengine.c --- linux-stable/drivers/dma/bcm2708-dmaengine.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/dma/bcm2708-dmaengine.c 2015-12-26 19:08:31.212660418 +0100 @@ -0,0 +1,1314 @@ +/* + * BCM2835 DMA engine support + * + * This driver supports cyclic and scatter/gather DMA transfers. + * + * Author: Florian Meier + * Gellert Weisz + * Copyright 2013-2014 + * + * Based on + * OMAP DMAengine support by Russell King + * + * BCM2708 DMA Driver + * Copyright (C) 2010 Broadcom + * + * Raspberry Pi PCM I2S ALSA Driver + * Copyright (c) by Phil Poole 2013 + * + * MARVELL MMP Peripheral DMA Driver + * Copyright 2012 Marvell International Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "virt-dma.h" + +static unsigned dma_debug; + +/* + * Legacy DMA API + */ + +#ifdef CONFIG_DMA_BCM2708_LEGACY + +#define CACHE_LINE_MASK 31 +#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ + +/* valid only for channels 0 - 14, 15 has its own base address */ +#define BCM2708_DMA_CHAN(n) ((n) << 8) /* base address */ +#define BCM2708_DMA_CHANIO(dma_base, n) \ + ((void __iomem *)((char *)(dma_base) + BCM2708_DMA_CHAN(n))) + +struct vc_dmaman { + void __iomem *dma_base; + u32 chan_available; /* bitmap of available channels */ + u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ + struct mutex lock; +}; + +static struct device *dmaman_dev; /* we assume there's only one! */ +static struct vc_dmaman *g_dmaman; /* DMA manager */ +static int dmachans = -1; /* module parameter */ + +/* DMA Auxiliary Functions */ + +/* A DMA buffer on an arbitrary boundary may separate a cache line into a + section inside the DMA buffer and another section outside it. + Even if we flush DMA buffers from the cache there is always the chance that + during a DMA someone will access the part of a cache line that is outside + the DMA buffer - which will then bring in unwelcome data. + Without being able to dictate our own buffer pools we must insist that + DMA buffers consist of a whole number of cache lines. +*/ +extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) +{ + int i; + + for (i = 0; i < sg_len; i++) { + if (sg_ptr[i].offset & CACHE_LINE_MASK || + sg_ptr[i].length & CACHE_LINE_MASK) + return 0; + } + + return 1; +} +EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); + +extern void bcm_dma_start(void __iomem *dma_chan_base, + dma_addr_t control_block) +{ + dsb(); /* ARM data synchronization (push) operation */ + + writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); + writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); +} +EXPORT_SYMBOL_GPL(bcm_dma_start); + +extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) +{ + dsb(); + + /* ugly busy wait only option for now */ + while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE) + cpu_relax(); +} +EXPORT_SYMBOL_GPL(bcm_dma_wait_idle); + +extern bool bcm_dma_is_busy(void __iomem *dma_chan_base) +{ + dsb(); + + return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE; +} +EXPORT_SYMBOL_GPL(bcm_dma_is_busy); + +/* Complete an ongoing DMA (assuming its results are to be ignored) + Does nothing if there is no DMA in progress. + This routine waits for the current AXI transfer to complete before + terminating the current DMA. If the current transfer is hung on a DREQ used + by an uncooperative peripheral the AXI transfer may never complete. In this + case the routine times out and return a non-zero error code. + Use of this routine doesn't guarantee that the ongoing or aborted DMA + does not produce an interrupt. +*/ +extern int bcm_dma_abort(void __iomem *dma_chan_base) +{ + unsigned long int cs; + int rc = 0; + + cs = readl(dma_chan_base + BCM2708_DMA_CS); + + if (BCM2708_DMA_ACTIVE & cs) { + long int timeout = 10000; + + /* write 0 to the active bit - pause the DMA */ + writel(0, dma_chan_base + BCM2708_DMA_CS); + + /* wait for any current AXI transfer to complete */ + while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) + cs = readl(dma_chan_base + BCM2708_DMA_CS); + + if (0 != (cs & BCM2708_DMA_ISPAUSED)) { + /* we'll un-pause when we set of our next DMA */ + rc = -ETIMEDOUT; + + } else if (BCM2708_DMA_ACTIVE & cs) { + /* terminate the control block chain */ + writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); + + /* abort the whole DMA */ + writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, + dma_chan_base + BCM2708_DMA_CS); + } + } + + return rc; +} +EXPORT_SYMBOL_GPL(bcm_dma_abort); + + /* DMA Manager Device Methods */ + +static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, + u32 chans_available) +{ + dmaman->dma_base = dma_base; + dmaman->chan_available = chans_available; + dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* 2 & 3 */ + dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* 0 */ + dmaman->has_feature[BCM_DMA_FEATURE_NORMAL_ORD] = 0xfe; /* 1 to 7 */ + dmaman->has_feature[BCM_DMA_FEATURE_LITE_ORD] = 0x7f00; /* 8 to 14 */ +} + +static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, + unsigned required_feature_set) +{ + u32 chans; + int chan = 0; + int feature; + + chans = dmaman->chan_available; + for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) + /* select the subset of available channels with the desired + features */ + if (required_feature_set & (1 << feature)) + chans &= dmaman->has_feature[feature]; + + if (!chans) + return -ENOENT; + + /* return the ordinal of the first channel in the bitmap */ + while (chans != 0 && (chans & 1) == 0) { + chans >>= 1; + chan++; + } + /* claim the channel */ + dmaman->chan_available &= ~(1 << chan); + + return chan; +} + +static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) +{ + if (chan < 0) + return -EINVAL; + + if ((1 << chan) & dmaman->chan_available) + return -EIDRM; + + dmaman->chan_available |= (1 << chan); + + return 0; +} + +/* DMA Manager Monitor */ + +extern int bcm_dma_chan_alloc(unsigned required_feature_set, + void __iomem **out_dma_base, int *out_dma_irq) +{ + struct vc_dmaman *dmaman = g_dmaman; + struct platform_device *pdev = to_platform_device(dmaman_dev); + struct resource *r; + int chan; + + if (!dmaman_dev) + return -ENODEV; + + mutex_lock(&dmaman->lock); + chan = vc_dmaman_chan_alloc(dmaman, required_feature_set); + if (chan < 0) + goto out; + + r = platform_get_resource(pdev, IORESOURCE_IRQ, (unsigned int)chan); + if (!r) { + dev_err(dmaman_dev, "failed to get irq for DMA channel %d\n", + chan); + vc_dmaman_chan_free(dmaman, chan); + chan = -ENOENT; + goto out; + } + + *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, chan); + *out_dma_irq = r->start; + dev_dbg(dmaman_dev, + "Legacy API allocated channel=%d, base=%p, irq=%i\n", + chan, *out_dma_base, *out_dma_irq); + +out: + mutex_unlock(&dmaman->lock); + + return chan; +} +EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); + +extern int bcm_dma_chan_free(int channel) +{ + struct vc_dmaman *dmaman = g_dmaman; + int rc; + + if (!dmaman_dev) + return -ENODEV; + + mutex_lock(&dmaman->lock); + rc = vc_dmaman_chan_free(dmaman, channel); + mutex_unlock(&dmaman->lock); + + return rc; +} +EXPORT_SYMBOL_GPL(bcm_dma_chan_free); + +static int bcm_dmaman_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct vc_dmaman *dmaman; + struct resource *r; + void __iomem *dma_base; + uint32_t val; + + if (!of_property_read_u32(dev->of_node, + "brcm,dma-channel-mask", &val)) + dmachans = val; + else if (dmachans == -1) + dmachans = DEFAULT_DMACHAN_BITMAP; + + dmaman = devm_kzalloc(dev, sizeof(*dmaman), GFP_KERNEL); + if (!dmaman) + return -ENOMEM; + + mutex_init(&dmaman->lock); + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dma_base = devm_ioremap_resource(dev, r); + if (IS_ERR(dma_base)) + return PTR_ERR(dma_base); + + vc_dmaman_init(dmaman, dma_base, dmachans); + g_dmaman = dmaman; + dmaman_dev = dev; + + dev_info(dev, "DMA legacy API manager at %p, dmachans=0x%x\n", + dma_base, dmachans); + + return 0; +} + +static int bcm_dmaman_remove(struct platform_device *pdev) +{ + dmaman_dev = NULL; + + return 0; +} + +#else /* CONFIG_DMA_BCM2708_LEGACY */ + +static int bcm_dmaman_remove(struct platform_device *pdev) +{ + return 0; +} + +#endif /* CONFIG_DMA_BCM2708_LEGACY */ + +/* + * DMA engine + */ + +struct bcm2835_dmadev { + struct dma_device ddev; + spinlock_t lock; + void __iomem *base; + struct device_dma_parameters dma_parms; +}; + +struct bcm2835_dma_cb { + uint32_t info; + uint32_t src; + uint32_t dst; + uint32_t length; + uint32_t stride; + uint32_t next; + uint32_t pad[2]; +}; + +struct bcm2835_chan { + struct virt_dma_chan vc; + struct list_head node; + + struct dma_slave_config cfg; + bool cyclic; + + int ch; + struct bcm2835_desc *desc; + + void __iomem *chan_base; + int irq_number; + + unsigned int dreq; +}; + +struct bcm2835_desc { + struct virt_dma_desc vd; + enum dma_transfer_direction dir; + + unsigned int control_block_size; + struct bcm2835_dma_cb *control_block_base; + dma_addr_t control_block_base_phys; + + unsigned int frames; + size_t size; +}; + +#define BCM2835_DMA_CS 0x00 +#define BCM2835_DMA_ADDR 0x04 +#define BCM2835_DMA_SOURCE_AD 0x0c +#define BCM2835_DMA_DEST_AD 0x10 +#define BCM2835_DMA_NEXTCB 0x1C + +/* DMA CS Control and Status bits */ +#define BCM2835_DMA_ACTIVE BIT(0) +#define BCM2835_DMA_INT BIT(2) +#define BCM2835_DMA_ISPAUSED BIT(4) /* Pause requested or not active */ +#define BCM2835_DMA_ISHELD BIT(5) /* Is held by DREQ flow control */ +#define BCM2835_DMA_ERR BIT(8) +#define BCM2835_DMA_ABORT BIT(30) /* Stop current CB, go to next, WO */ +#define BCM2835_DMA_RESET BIT(31) /* WO, self clearing */ + +#define BCM2835_DMA_INT_EN BIT(0) +#define BCM2835_DMA_WAIT_RESP BIT(3) +#define BCM2835_DMA_D_INC BIT(4) +#define BCM2835_DMA_D_WIDTH BIT(5) +#define BCM2835_DMA_D_DREQ BIT(6) +#define BCM2835_DMA_S_INC BIT(8) +#define BCM2835_DMA_S_WIDTH BIT(9) +#define BCM2835_DMA_S_DREQ BIT(10) + +#define BCM2835_DMA_PER_MAP(x) ((x) << 16) +#define BCM2835_DMA_WAITS(x) (((x)&0x1f) << 21) + +#define SDHCI_BCM_DMA_WAITS 0 /* delays slowing DMA transfers: 0-31 */ + +#define BCM2835_DMA_DATA_TYPE_S8 1 +#define BCM2835_DMA_DATA_TYPE_S16 2 +#define BCM2835_DMA_DATA_TYPE_S32 4 +#define BCM2835_DMA_DATA_TYPE_S128 16 + +#define BCM2835_DMA_BULK_MASK BIT(0) +#define BCM2835_DMA_FIQ_MASK (BIT(2) | BIT(3)) + + +/* Valid only for channels 0 - 14, 15 has its own base address */ +#define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ +#define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) + +#define MAX_LITE_TRANSFER 32768 +#define MAX_NORMAL_TRANSFER 1073741824 + +static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d) +{ + return container_of(d, struct bcm2835_dmadev, ddev); +} + +static inline struct bcm2835_chan *to_bcm2835_dma_chan(struct dma_chan *c) +{ + return container_of(c, struct bcm2835_chan, vc.chan); +} + +static inline struct bcm2835_desc *to_bcm2835_dma_desc( + struct dma_async_tx_descriptor *t) +{ + return container_of(t, struct bcm2835_desc, vd.tx); +} + +#if 0 +static void dma_dumpregs(struct bcm2835_chan *c) +{ + pr_debug("-------------DMA DUMPREGS-------------\n"); + pr_debug("CS= %u\n", + readl(c->chan_base + BCM2835_DMA_CS)); + pr_debug("ADDR= %u\n", + readl(c->chan_base + BCM2835_DMA_ADDR)); + pr_debug("SOURCE_ADDR= %u\n", + readl(c->chan_base + BCM2835_DMA_SOURCE_AD)); + pr_debug("DEST_AD= %u\n", + readl(c->chan_base + BCM2835_DMA_DEST_AD)); + pr_debug("NEXTCB= %u\n", + readl(c->chan_base + BCM2835_DMA_NEXTCB)); + pr_debug("--------------------------------------\n"); +} +#endif + +static void bcm2835_dma_desc_free(struct virt_dma_desc *vd) +{ + struct bcm2835_desc *desc = container_of(vd, struct bcm2835_desc, vd); + dma_free_coherent(desc->vd.tx.chan->device->dev, + desc->control_block_size, + desc->control_block_base, + desc->control_block_base_phys); + kfree(desc); +} + +static int bcm2835_dma_abort(void __iomem *chan_base) +{ + unsigned long cs; + long int timeout = 10000; + + cs = readl(chan_base + BCM2835_DMA_CS); + if (!(cs & BCM2835_DMA_ACTIVE)) + return 0; + + /* Write 0 to the active bit - Pause the DMA */ + writel(0, chan_base + BCM2835_DMA_CS); + + /* Wait for any current AXI transfer to complete */ + while ((cs & BCM2835_DMA_ISPAUSED) && --timeout) { + cpu_relax(); + cs = readl(chan_base + BCM2835_DMA_CS); + } + + /* We'll un-pause when we set of our next DMA */ + if (!timeout) + return -ETIMEDOUT; + + if (!(cs & BCM2835_DMA_ACTIVE)) + return 0; + + /* Terminate the control block chain */ + writel(0, chan_base + BCM2835_DMA_NEXTCB); + + /* Abort the whole DMA */ + writel(BCM2835_DMA_ABORT | BCM2835_DMA_ACTIVE, + chan_base + BCM2835_DMA_CS); + + return 0; +} + + +static void bcm2835_dma_start_desc(struct bcm2835_chan *c) +{ + struct virt_dma_desc *vd = vchan_next_desc(&c->vc); + struct bcm2835_desc *d; + + if (!vd) { + c->desc = NULL; + return; + } + + list_del(&vd->node); + + c->desc = d = to_bcm2835_dma_desc(&vd->tx); + + writel(d->control_block_base_phys, c->chan_base + BCM2835_DMA_ADDR); + writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS); + +} + +static irqreturn_t bcm2835_dma_callback(int irq, void *data) +{ + struct bcm2835_chan *c = data; + struct bcm2835_desc *d; + unsigned long flags; + + spin_lock_irqsave(&c->vc.lock, flags); + + /* Acknowledge interrupt */ + writel(BCM2835_DMA_INT, c->chan_base + BCM2835_DMA_CS); + + d = c->desc; + + if (d) { + if (c->cyclic) { + vchan_cyclic_callback(&d->vd); + + /* Keep the DMA engine running */ + writel(BCM2835_DMA_ACTIVE, + c->chan_base + BCM2835_DMA_CS); + + } else { + vchan_cookie_complete(&c->desc->vd); + bcm2835_dma_start_desc(c); + } + } + + spin_unlock_irqrestore(&c->vc.lock, flags); + + return IRQ_HANDLED; +} + +static int bcm2835_dma_alloc_chan_resources(struct dma_chan *chan) +{ + struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); + int ret; + + dev_dbg(c->vc.chan.device->dev, + "Allocating DMA channel %d\n", c->ch); + + ret = request_irq(c->irq_number, + bcm2835_dma_callback, 0, "DMA IRQ", c); + + return ret; +} + +static void bcm2835_dma_free_chan_resources(struct dma_chan *chan) +{ + struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); + + vchan_free_chan_resources(&c->vc); + free_irq(c->irq_number, c); + + dev_dbg(c->vc.chan.device->dev, "Freeing DMA channel %u\n", c->ch); +} + +static size_t bcm2835_dma_desc_size(struct bcm2835_desc *d) +{ + return d->size; +} + +static size_t bcm2835_dma_desc_size_pos(struct bcm2835_desc *d, dma_addr_t addr) +{ + unsigned int i; + size_t size; + + for (size = i = 0; i < d->frames; i++) { + struct bcm2835_dma_cb *control_block = + &d->control_block_base[i]; + size_t this_size = control_block->length; + dma_addr_t dma; + + if (d->dir == DMA_DEV_TO_MEM) + dma = control_block->dst; + else + dma = control_block->src; + + if (size) + size += this_size; + else if (addr >= dma && addr < dma + this_size) + size += dma + this_size - addr; + } + + return size; +} + +static enum dma_status bcm2835_dma_tx_status(struct dma_chan *chan, + dma_cookie_t cookie, struct dma_tx_state *txstate) +{ + struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); + struct bcm2835_desc *d; + struct virt_dma_desc *vd; + enum dma_status ret; + unsigned long flags; + dma_addr_t pos; + + ret = dma_cookie_status(chan, cookie, txstate); + if (ret == DMA_COMPLETE || !txstate) + return ret; + + spin_lock_irqsave(&c->vc.lock, flags); + vd = vchan_find_desc(&c->vc, cookie); + if (vd) { + txstate->residue = + bcm2835_dma_desc_size(to_bcm2835_dma_desc(&vd->tx)); + } else if (c->desc && c->desc->vd.tx.cookie == cookie) { + d = c->desc; + + if (d->dir == DMA_MEM_TO_DEV) + pos = readl(c->chan_base + BCM2835_DMA_SOURCE_AD); + else if (d->dir == DMA_DEV_TO_MEM) + pos = readl(c->chan_base + BCM2835_DMA_DEST_AD); + else + pos = 0; + + txstate->residue = bcm2835_dma_desc_size_pos(d, pos); + } else { + txstate->residue = 0; + } + + spin_unlock_irqrestore(&c->vc.lock, flags); + + return ret; +} + +static void bcm2835_dma_issue_pending(struct dma_chan *chan) +{ + struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); + unsigned long flags; + + spin_lock_irqsave(&c->vc.lock, flags); + if (vchan_issue_pending(&c->vc) && !c->desc) + bcm2835_dma_start_desc(c); + + spin_unlock_irqrestore(&c->vc.lock, flags); +} + +static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( + struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_transfer_direction direction, + unsigned long flags) +{ + struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); + enum dma_slave_buswidth dev_width; + struct bcm2835_desc *d; + dma_addr_t dev_addr; + unsigned int es, sync_type; + unsigned int frame, max_size; + + /* Grab configuration */ + if (!is_slave_direction(direction)) { + dev_err(chan->device->dev, "%s: bad direction?\n", __func__); + return NULL; + } + + if (direction == DMA_DEV_TO_MEM) { + dev_addr = c->cfg.src_addr; + dev_width = c->cfg.src_addr_width; + sync_type = BCM2835_DMA_S_DREQ; + } else { + dev_addr = c->cfg.dst_addr; + dev_width = c->cfg.dst_addr_width; + sync_type = BCM2835_DMA_D_DREQ; + } + + /* Bus width translates to the element size (ES) */ + switch (dev_width) { + case DMA_SLAVE_BUSWIDTH_4_BYTES: + es = BCM2835_DMA_DATA_TYPE_S32; + break; + default: + return NULL; + } + + /* Now allocate and setup the descriptor. */ + d = kzalloc(sizeof(*d), GFP_NOWAIT); + if (!d) + return NULL; + + d->dir = direction; + + if (c->ch >= 8) /* we have a LITE channel */ + max_size = MAX_LITE_TRANSFER; + else + max_size = MAX_NORMAL_TRANSFER; + period_len = min(period_len, max_size); + + d->frames = (buf_len-1) / period_len + 1; + + /* Allocate memory for control blocks */ + d->control_block_size = d->frames * sizeof(struct bcm2835_dma_cb); + d->control_block_base = dma_zalloc_coherent(chan->device->dev, + d->control_block_size, &d->control_block_base_phys, + GFP_NOWAIT); + + if (!d->control_block_base) { + kfree(d); + return NULL; + } + + /* + * Iterate over all frames, create a control block + * for each frame and link them together. + */ + for (frame = 0; frame < d->frames; frame++) { + struct bcm2835_dma_cb *control_block = + &d->control_block_base[frame]; + + /* Setup adresses */ + if (d->dir == DMA_DEV_TO_MEM) { + control_block->info = BCM2835_DMA_D_INC; + control_block->src = dev_addr; + control_block->dst = buf_addr + frame * period_len; + } else { + control_block->info = BCM2835_DMA_S_INC; + control_block->src = buf_addr + frame * period_len; + control_block->dst = dev_addr; + } + + /* Enable interrupt */ + control_block->info |= BCM2835_DMA_INT_EN; + + /* Setup synchronization */ + if (sync_type != 0) + control_block->info |= sync_type; + + /* Setup DREQ channel */ + if (c->cfg.slave_id != 0) + control_block->info |= + BCM2835_DMA_PER_MAP(c->cfg.slave_id); + + /* Length of a frame */ + if (frame != d->frames-1) + control_block->length = period_len; + else + control_block->length = buf_len - (d->frames - 1) * period_len; + + d->size += control_block->length; + + /* + * Next block is the next frame. + * This function is called on cyclic DMA transfers. + * Therefore, wrap around at number of frames. + */ + control_block->next = d->control_block_base_phys + + sizeof(struct bcm2835_dma_cb) + * ((frame + 1) % d->frames); + } + + c->cyclic = true; + + return vchan_tx_prep(&c->vc, &d->vd, flags); +} + + +static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( + struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_transfer_direction direction, + unsigned long flags, void *context) +{ + struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); + enum dma_slave_buswidth dev_width; + struct bcm2835_desc *d; + dma_addr_t dev_addr; + struct scatterlist *sgent; + unsigned int es, sync_type; + unsigned int i, j, splitct, max_size; + + if (!is_slave_direction(direction)) { + dev_err(chan->device->dev, "%s: bad direction?\n", __func__); + return NULL; + } + + if (direction == DMA_DEV_TO_MEM) { + dev_addr = c->cfg.src_addr; + dev_width = c->cfg.src_addr_width; + sync_type = BCM2835_DMA_S_DREQ; + } else { + dev_addr = c->cfg.dst_addr; + dev_width = c->cfg.dst_addr_width; + sync_type = BCM2835_DMA_D_DREQ; + } + + /* Bus width translates to the element size (ES) */ + switch (dev_width) { + case DMA_SLAVE_BUSWIDTH_4_BYTES: + es = BCM2835_DMA_DATA_TYPE_S32; + break; + default: + return NULL; + } + + /* Now allocate and setup the descriptor. */ + d = kzalloc(sizeof(*d), GFP_NOWAIT); + if (!d) + return NULL; + + d->dir = direction; + + if (c->ch >= 8) /* we have a LITE channel */ + max_size = MAX_LITE_TRANSFER; + else + max_size = MAX_NORMAL_TRANSFER; + + /* We store the length of the SG list in d->frames + taking care to account for splitting up transfers + too large for a LITE channel */ + + d->frames = 0; + for_each_sg(sgl, sgent, sg_len, i) { + uint32_t len = sg_dma_len(sgent); + d->frames += 1 + len / max_size; + } + + /* Allocate memory for control blocks */ + d->control_block_size = d->frames * sizeof(struct bcm2835_dma_cb); + d->control_block_base = dma_zalloc_coherent(chan->device->dev, + d->control_block_size, &d->control_block_base_phys, + GFP_NOWAIT); + + if (!d->control_block_base) { + kfree(d); + return NULL; + } + + /* + * Iterate over all SG entries, create a control block + * for each frame and link them together. + */ + + /* we count the number of times an SG entry had to be splitct + as a result of using a LITE channel */ + splitct = 0; + + for_each_sg(sgl, sgent, sg_len, i) { + dma_addr_t addr = sg_dma_address(sgent); + uint32_t len = sg_dma_len(sgent); + + for (j = 0; j < len; j += max_size) { + u32 waits; + struct bcm2835_dma_cb *control_block = + &d->control_block_base[i+splitct]; + + /* Setup adresses */ + if (d->dir == DMA_DEV_TO_MEM) { + control_block->info = BCM2835_DMA_D_INC | + BCM2835_DMA_D_WIDTH | BCM2835_DMA_S_DREQ; + control_block->src = dev_addr; + control_block->dst = addr + (dma_addr_t)j; + } else { + control_block->info = BCM2835_DMA_S_INC | + BCM2835_DMA_S_WIDTH | BCM2835_DMA_D_DREQ; + control_block->src = addr + (dma_addr_t)j; + control_block->dst = dev_addr; + } + + /* Common part */ + waits = SDHCI_BCM_DMA_WAITS; + if ((dma_debug >> 0) & 0x1f) + waits = (dma_debug >> 0) & 0x1f; + control_block->info |= BCM2835_DMA_WAITS(waits); + control_block->info |= BCM2835_DMA_WAIT_RESP; + + /* Enable */ + if (i == sg_len-1 && len-j <= max_size) + control_block->info |= BCM2835_DMA_INT_EN; + + /* Setup synchronization */ + if (sync_type != 0) + control_block->info |= sync_type; + + /* Setup DREQ channel */ + if (c->dreq != 0) + control_block->info |= + BCM2835_DMA_PER_MAP(c->dreq); + + /* Length of a frame */ + control_block->length = min(len-j, max_size); + d->size += control_block->length; + + /* + * Next block is the next frame. + */ + if (i < sg_len-1 || len-j > max_size) { + /* next block is the next frame. */ + control_block->next = d->control_block_base_phys + + sizeof(struct bcm2835_dma_cb) * (i + splitct + 1); + } else { + /* next block is empty. */ + control_block->next = 0; + } + + if (len-j > max_size) + splitct++; + } + } + + c->cyclic = false; + + return vchan_tx_prep(&c->vc, &d->vd, flags); +} + +static int bcm2835_dma_slave_config(struct dma_chan *chan, + struct dma_slave_config *cfg) +{ + struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); + if ((cfg->direction == DMA_DEV_TO_MEM && + cfg->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) || + (cfg->direction == DMA_MEM_TO_DEV && + cfg->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) || + !is_slave_direction(cfg->direction)) { + return -EINVAL; + } + + c->cfg = *cfg; + if (!c->dreq) + c->dreq = cfg->slave_id; + + return 0; +} + +static int bcm2835_dma_terminate_all(struct dma_chan *chan) +{ + struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); + struct bcm2835_dmadev *d = to_bcm2835_dma_dev(c->vc.chan.device); + unsigned long flags; + int timeout = 10000; + LIST_HEAD(head); + + spin_lock_irqsave(&c->vc.lock, flags); + + /* Prevent this channel being scheduled */ + spin_lock(&d->lock); + list_del_init(&c->node); + spin_unlock(&d->lock); + + /* + * Stop DMA activity: we assume the callback will not be called + * after bcm_dma_abort() returns (even if it does, it will see + * c->desc is NULL and exit.) + */ + if (c->desc) { + bcm2835_dma_desc_free(&c->desc->vd); + c->desc = NULL; + bcm2835_dma_abort(c->chan_base); + + /* Wait for stopping */ + while (--timeout) { + if (!(readl(c->chan_base + BCM2835_DMA_CS) & + BCM2835_DMA_ACTIVE)) + break; + + cpu_relax(); + } + + if (!timeout) + dev_err(d->ddev.dev, "DMA transfer could not be terminated\n"); + } + + vchan_get_all_descriptors(&c->vc, &head); + spin_unlock_irqrestore(&c->vc.lock, flags); + vchan_dma_desc_free_list(&c->vc, &head); + + return 0; +} + +#ifndef CONFIG_DMA_BCM2708_LEGACY +static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) +{ + struct bcm2835_chan *c; + + c = devm_kzalloc(d->ddev.dev, sizeof(*c), GFP_KERNEL); + if (!c) + return -ENOMEM; + + c->vc.desc_free = bcm2835_dma_desc_free; + vchan_init(&c->vc, &d->ddev); + INIT_LIST_HEAD(&c->node); + + c->chan_base = BCM2835_DMA_CHANIO(d->base, chan_id); + c->ch = chan_id; + c->irq_number = irq; + + return 0; +} +#endif + +static int bcm2708_dma_chan_init(struct bcm2835_dmadev *d, + void __iomem *chan_base, int chan_id, int irq) +{ + struct bcm2835_chan *c; + + c = devm_kzalloc(d->ddev.dev, sizeof(*c), GFP_KERNEL); + if (!c) + return -ENOMEM; + + c->vc.desc_free = bcm2835_dma_desc_free; + vchan_init(&c->vc, &d->ddev); + INIT_LIST_HEAD(&c->node); + + c->chan_base = chan_base; + c->ch = chan_id; + c->irq_number = irq; + + return 0; +} + + +static void bcm2835_dma_free(struct bcm2835_dmadev *od) +{ + struct bcm2835_chan *c, *next; + + list_for_each_entry_safe(c, next, &od->ddev.channels, + vc.chan.device_node) { + list_del(&c->vc.chan.device_node); + tasklet_kill(&c->vc.task); + } +} + +static const struct of_device_id bcm2835_dma_of_match[] = { + { .compatible = "brcm,bcm2835-dma", }, + {}, +}; +MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match); + +static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec, + struct of_dma *ofdma) +{ + struct bcm2835_dmadev *d = ofdma->of_dma_data; + struct dma_chan *chan; + + chan = dma_get_any_slave_channel(&d->ddev); + if (!chan) + return NULL; + + /* Set DREQ from param */ + to_bcm2835_dma_chan(chan)->dreq = spec->args[0]; + + return chan; +} + +static int bcm2835_dma_probe(struct platform_device *pdev) +{ + struct bcm2835_dmadev *od; +#ifndef CONFIG_DMA_BCM2708_LEGACY + struct resource *res; + void __iomem *base; + uint32_t chans_available; +#endif + int rc; + int i; + int irq; +#ifdef CONFIG_DMA_BCM2708_LEGACY + static const u32 wanted_features[] = { + BCM_DMA_FEATURE_FAST, + BCM_DMA_FEATURE_NORMAL, + BCM_DMA_FEATURE_LITE + }; + int j; +#endif + + + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; + +#ifdef CONFIG_DMA_BCM2708_LEGACY + + rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); + if (rc) + return rc; + dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); + + + od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL); + if (!od) + return -ENOMEM; + + rc = bcm_dmaman_probe(pdev); + if (rc) + return rc; + + pdev->dev.dma_parms = &od->dma_parms; + dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF); + + + dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); + dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask); + dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); + od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources; + od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources; + od->ddev.device_tx_status = bcm2835_dma_tx_status; + od->ddev.device_issue_pending = bcm2835_dma_issue_pending; + od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; + od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg; + od->ddev.device_terminate_all = bcm2835_dma_terminate_all; + od->ddev.device_config = bcm2835_dma_slave_config; + od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); + od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + od->ddev.dev = &pdev->dev; + INIT_LIST_HEAD(&od->ddev.channels); + spin_lock_init(&od->lock); + + platform_set_drvdata(pdev, od); + + for (i = 0, j = 0; j < ARRAY_SIZE(wanted_features);) { + + void __iomem *chan_base; + int chan_id; + + chan_id = bcm_dma_chan_alloc(wanted_features[j], + &chan_base, + &irq); + + if (chan_id < 0) { + j++; + continue; + } + + rc = bcm2708_dma_chan_init(od, chan_base, chan_id, irq); + if (rc) + goto err_no_dma; + i++; + } + + if (pdev->dev.of_node) { + rc = of_dma_controller_register(pdev->dev.of_node, + bcm2835_dma_xlate, od); + if (rc) { + dev_err(&pdev->dev, + "Failed to register DMA controller\n"); + goto err_no_dma; + } + } + + dev_info(&pdev->dev, "Initialized %i DMA channels (+ 1 legacy)\n", i); + +#else + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (rc) + return rc; + + + od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL); + if (!od) + return -ENOMEM; + + pdev->dev.dma_parms = &od->dma_parms; + dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF); + + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + od->base = base; + + + dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); + dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask); + dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); + od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources; + od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources; + od->ddev.device_tx_status = bcm2835_dma_tx_status; + od->ddev.device_issue_pending = bcm2835_dma_issue_pending; + od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; + od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg; + od->ddev.device_terminate_all = bcm2835_dma_terminate_all; + od->ddev.device_config = bcm2835_dma_slave_config; + od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); + od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + od->ddev.dev = &pdev->dev; + INIT_LIST_HEAD(&od->ddev.channels); + spin_lock_init(&od->lock); + + platform_set_drvdata(pdev, od); + + + /* Request DMA channel mask from device tree */ + if (of_property_read_u32(pdev->dev.of_node, + "brcm,dma-channel-mask", + &chans_available)) { + dev_err(&pdev->dev, "Failed to get channel mask\n"); + rc = -EINVAL; + goto err_no_dma; + } + + + /* + * Do not use the FIQ and BULK channels, + * because they are used by the GPU. + */ + chans_available &= ~(BCM2835_DMA_FIQ_MASK | BCM2835_DMA_BULK_MASK); + + + for (i = 0; i < pdev->num_resources; i++) { + irq = platform_get_irq(pdev, i); + if (irq < 0) + break; + + if (chans_available & (1 << i)) { + rc = bcm2835_dma_chan_init(od, i, irq); + if (rc) + goto err_no_dma; + } + } + + dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", i); + + /* Device-tree DMA controller registration */ + rc = of_dma_controller_register(pdev->dev.of_node, + bcm2835_dma_xlate, od); + if (rc) { + dev_err(&pdev->dev, "Failed to register DMA controller\n"); + goto err_no_dma; + } +#endif + + rc = dma_async_device_register(&od->ddev); + if (rc) { + dev_err(&pdev->dev, + "Failed to register slave DMA engine device: %d\n", rc); + goto err_no_dma; + } + + dev_info(&pdev->dev, "Load BCM2835 DMA engine driver\n"); + dev_info(&pdev->dev, "dma_debug:%x\n", dma_debug); + + return 0; + +err_no_dma: + bcm2835_dma_free(od); + return rc; +} + +static int bcm2835_dma_remove(struct platform_device *pdev) +{ + struct bcm2835_dmadev *od = platform_get_drvdata(pdev); + + dma_async_device_unregister(&od->ddev); + bcm2835_dma_free(od); + bcm_dmaman_remove(pdev); + + return 0; +} + +static struct platform_driver bcm2835_dma_driver = { + .probe = bcm2835_dma_probe, + .remove = bcm2835_dma_remove, + .driver = { + .name = "bcm2708-dmaengine", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(bcm2835_dma_of_match), + }, +}; + +static int bcm2835_init(void) +{ + return platform_driver_register(&bcm2835_dma_driver); +} + +static void bcm2835_exit(void) +{ + platform_driver_unregister(&bcm2835_dma_driver); +} + +/* + * Load after serial driver (arch_initcall) so we see the messages if it fails, + * but before drivers (module_init) that need a DMA channel. + */ +subsys_initcall(bcm2835_init); +module_exit(bcm2835_exit); + +module_param(dma_debug, uint, 0644); +#ifdef CONFIG_DMA_BCM2708_LEGACY +/* Keep backward compatibility: dma.dmachans= */ +#undef MODULE_PARAM_PREFIX +#define MODULE_PARAM_PREFIX "dma." +module_param(dmachans, int, 0644); +#endif +MODULE_ALIAS("platform:bcm2835-dma"); +MODULE_DESCRIPTION("BCM2835 DMA engine driver"); +MODULE_AUTHOR("Florian Meier "); +MODULE_AUTHOR("Gellert Weisz "); +MODULE_LICENSE("GPL v2"); diff -Nur '--exclude=.git' linux-stable/drivers/dma/Kconfig raspilinux/drivers/dma/Kconfig --- linux-stable/drivers/dma/Kconfig 2015-12-26 20:45:00.387984751 +0100 +++ raspilinux/drivers/dma/Kconfig 2015-12-26 19:08:31.212660418 +0100 @@ -337,6 +337,17 @@ select DMA_ENGINE select DMA_VIRTUAL_CHANNELS +config DMA_BCM2708 + tristate "BCM2708 DMA engine support" + depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + +config DMA_BCM2708_LEGACY + bool "BCM2708 DMA legacy API support" + depends on DMA_BCM2708 + default y + config TI_CPPI41 tristate "AM33xx CPPI41 DMA support" depends on ARCH_OMAP @@ -385,7 +396,7 @@ select DMA_VIRTUAL_CHANNELS help Enable support for the MOXA ART SoC DMA controller. - + config FSL_EDMA tristate "Freescale eDMA engine support" depends on OF diff -Nur '--exclude=.git' linux-stable/drivers/dma/Makefile raspilinux/drivers/dma/Makefile --- linux-stable/drivers/dma/Makefile 2015-12-26 20:45:00.387984751 +0100 +++ raspilinux/drivers/dma/Makefile 2015-12-26 19:08:31.212660418 +0100 @@ -39,6 +39,7 @@ obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o obj-$(CONFIG_DMA_OMAP) += omap-dma.o obj-$(CONFIG_DMA_BCM2835) += bcm2835-dma.o +obj-$(CONFIG_DMA_BCM2708) += bcm2708-dmaengine.o obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o obj-$(CONFIG_DMA_JZ4780) += dma-jz4780.o diff -Nur '--exclude=.git' linux-stable/drivers/firmware/Kconfig raspilinux/drivers/firmware/Kconfig --- linux-stable/drivers/firmware/Kconfig 2015-12-26 20:45:00.415982171 +0100 +++ raspilinux/drivers/firmware/Kconfig 2015-12-26 19:08:31.232658553 +0100 @@ -136,6 +136,13 @@ bool depends on ARM || ARM64 +config RASPBERRYPI_FIRMWARE + tristate "Raspberry Pi Firmware Driver" + depends on BCM2835_MBOX + help + This option enables support for communicating with the firmware on the + Raspberry Pi. + source "drivers/firmware/google/Kconfig" source "drivers/firmware/efi/Kconfig" diff -Nur '--exclude=.git' linux-stable/drivers/firmware/Makefile raspilinux/drivers/firmware/Makefile --- linux-stable/drivers/firmware/Makefile 2015-12-26 20:45:00.415982171 +0100 +++ raspilinux/drivers/firmware/Makefile 2015-12-26 19:08:31.232658553 +0100 @@ -13,6 +13,7 @@ obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o obj-$(CONFIG_QCOM_SCM) += qcom_scm.o CFLAGS_qcom_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) +obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ obj-$(CONFIG_EFI) += efi/ diff -Nur '--exclude=.git' linux-stable/drivers/firmware/raspberrypi.c raspilinux/drivers/firmware/raspberrypi.c --- linux-stable/drivers/firmware/raspberrypi.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/firmware/raspberrypi.c 2015-12-26 19:08:31.236658180 +0100 @@ -0,0 +1,297 @@ +/* + * Defines interfaces for interacting wtih the Raspberry Pi firmware's + * property channel. + * + * Copyright © 2015 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) +#define MBOX_CHAN(msg) ((msg) & 0xf) +#define MBOX_DATA28(msg) ((msg) & ~0xf) +#define MBOX_CHAN_PROPERTY 8 + +struct rpi_firmware { + struct mbox_client cl; + struct mbox_chan *chan; /* The property channel. */ + struct completion c; + u32 enabled; +}; + +static struct platform_device *g_pdev; + +static DEFINE_MUTEX(transaction_lock); + +static void response_callback(struct mbox_client *cl, void *msg) +{ + struct rpi_firmware *fw = container_of(cl, struct rpi_firmware, cl); + complete(&fw->c); +} + +/* + * Sends a request to the firmware through the BCM2835 mailbox driver, + * and synchronously waits for the reply. + */ +static int +rpi_firmware_transaction(struct rpi_firmware *fw, u32 chan, u32 data) +{ + u32 message = MBOX_MSG(chan, data); + int ret; + + WARN_ON(data & 0xf); + + mutex_lock(&transaction_lock); + reinit_completion(&fw->c); + ret = mbox_send_message(fw->chan, &message); + if (ret >= 0) { + wait_for_completion(&fw->c); + ret = 0; + } else { + dev_err(fw->cl.dev, "mbox_send_message returned %d\n", ret); + } + mutex_unlock(&transaction_lock); + + return ret; +} + +/** + * rpi_firmware_property_list - Submit firmware property list + * @fw: Pointer to firmware structure from rpi_firmware_get(). + * @data: Buffer holding tags. + * @tag_size: Size of tags buffer. + * + * Submits a set of concatenated tags to the VPU firmware through the + * mailbox property interface. + * + * The buffer header and the ending tag are added by this function and + * don't need to be supplied, just the actual tags for your operation. + * See struct rpi_firmware_property_tag_header for the per-tag + * structure. + */ +int rpi_firmware_property_list(struct rpi_firmware *fw, + void *data, size_t tag_size) +{ + size_t size = tag_size + 12; + u32 *buf; + dma_addr_t bus_addr; + int ret; + + /* Packets are processed a dword at a time. */ + if (size & 3) + return -EINVAL; + + buf = dma_alloc_coherent(fw->cl.dev, PAGE_ALIGN(size), &bus_addr, + GFP_ATOMIC); + if (!buf) + return -ENOMEM; + + /* The firmware will error out without parsing in this case. */ + WARN_ON(size >= 1024 * 1024); + + buf[0] = size; + buf[1] = RPI_FIRMWARE_STATUS_REQUEST; + memcpy(&buf[2], data, tag_size); + buf[size / 4 - 1] = RPI_FIRMWARE_PROPERTY_END; + wmb(); + + ret = rpi_firmware_transaction(fw, MBOX_CHAN_PROPERTY, bus_addr); + + rmb(); + memcpy(data, &buf[2], tag_size); + if (ret == 0 && buf[1] != RPI_FIRMWARE_STATUS_SUCCESS) { + /* + * The tag name here might not be the one causing the + * error, if there were multiple tags in the request. + * But single-tag is the most common, so go with it. + */ + dev_err(fw->cl.dev, "Request 0x%08x returned status 0x%08x\n", + buf[2], buf[1]); + ret = -EINVAL; + } + + dma_free_coherent(fw->cl.dev, PAGE_ALIGN(size), buf, bus_addr); + + return ret; +} +EXPORT_SYMBOL_GPL(rpi_firmware_property_list); + +/** + * rpi_firmware_property - Submit single firmware property + * @fw: Pointer to firmware structure from rpi_firmware_get(). + * @tag: One of enum_mbox_property_tag. + * @tag_data: Tag data buffer. + * @buf_size: Buffer size. + * + * Submits a single tag to the VPU firmware through the mailbox + * property interface. + * + * This is a convenience wrapper around + * rpi_firmware_property_list() to avoid some of the + * boilerplate in property calls. + */ +int rpi_firmware_property(struct rpi_firmware *fw, + u32 tag, void *tag_data, size_t buf_size) +{ + /* Single tags are very small (generally 8 bytes), so the + * stack should be safe. + */ + u8 data[buf_size + sizeof(struct rpi_firmware_property_tag_header)]; + struct rpi_firmware_property_tag_header *header = + (struct rpi_firmware_property_tag_header *)data; + int ret; + + header->tag = tag; + header->buf_size = buf_size; + header->req_resp_size = 0; + memcpy(data + sizeof(struct rpi_firmware_property_tag_header), + tag_data, buf_size); + + ret = rpi_firmware_property_list(fw, &data, sizeof(data)); + memcpy(tag_data, + data + sizeof(struct rpi_firmware_property_tag_header), + buf_size); + + return ret; +} +EXPORT_SYMBOL_GPL(rpi_firmware_property); + +static void +rpi_firmware_print_firmware_revision(struct rpi_firmware *fw) +{ + u32 packet; + int ret = rpi_firmware_property(fw, + RPI_FIRMWARE_GET_FIRMWARE_REVISION, + &packet, sizeof(packet)); + + if (ret == 0) { + struct tm tm; + + time_to_tm(packet, 0, &tm); + + dev_info(fw->cl.dev, + "Attached to firmware from %04ld-%02d-%02d %02d:%02d\n", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min); + } +} + +static int raspberrypi_firmware_set_power(struct rpi_firmware *fw, + u32 domain, bool on) +{ + struct { + u32 domain; + u32 on; + } packet; + int ret; + + packet.domain = domain; + packet.on = on; + ret = rpi_firmware_property(fw, RPI_FIRMWARE_SET_POWER_STATE, + &packet, sizeof(packet)); + if (!ret && packet.on != on) + ret = -EINVAL; + + return ret; +} + +static int rpi_firmware_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct rpi_firmware *fw; + + fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL); + if (!fw) + return -ENOMEM; + + fw->cl.dev = dev; + fw->cl.rx_callback = response_callback; + fw->cl.tx_block = true; + + fw->chan = mbox_request_channel(&fw->cl, 0); + if (IS_ERR(fw->chan)) { + int ret = PTR_ERR(fw->chan); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get mbox channel: %d\n", ret); + return ret; + } + + init_completion(&fw->c); + + platform_set_drvdata(pdev, fw); + g_pdev = pdev; + + rpi_firmware_print_firmware_revision(fw); + + if (raspberrypi_firmware_set_power(fw, 3, true)) + dev_err(dev, "failed to turn on USB power\n"); + + return 0; +} + +static int rpi_firmware_remove(struct platform_device *pdev) +{ + struct rpi_firmware *fw = platform_get_drvdata(pdev); + + mbox_free_channel(fw->chan); + g_pdev = NULL; + + return 0; +} + +/** + * rpi_firmware_get - Get pointer to rpi_firmware structure. + * @firmware_node: Pointer to the firmware Device Tree node. + * + * Returns NULL is the firmware device is not ready. + */ +struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node) +{ + struct platform_device *pdev = g_pdev; + + if (!pdev) + return NULL; + + return platform_get_drvdata(pdev); +} +EXPORT_SYMBOL_GPL(rpi_firmware_get); + +static const struct of_device_id rpi_firmware_of_match[] = { + { .compatible = "raspberrypi,bcm2835-firmware", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rpi_firmware_of_match); + +static struct platform_driver rpi_firmware_driver = { + .driver = { + .name = "raspberrypi-firmware", + .of_match_table = rpi_firmware_of_match, + }, + .probe = rpi_firmware_probe, + .remove = rpi_firmware_remove, +}; + +static int __init rpi_firmware_init(void) +{ + return platform_driver_register(&rpi_firmware_driver); +} +subsys_initcall(rpi_firmware_init); + +static void __init rpi_firmware_exit(void) +{ + platform_driver_unregister(&rpi_firmware_driver); +} +module_exit(rpi_firmware_exit); + +MODULE_AUTHOR("Eric Anholt "); +MODULE_DESCRIPTION("Raspberry Pi firmware driver"); +MODULE_LICENSE("GPL v2"); diff -Nur '--exclude=.git' linux-stable/drivers/hid/usbhid/hid-core.c raspilinux/drivers/hid/usbhid/hid-core.c --- linux-stable/drivers/hid/usbhid/hid-core.c 2015-12-26 20:45:00.651960420 +0100 +++ raspilinux/drivers/hid/usbhid/hid-core.c 2015-12-26 19:08:31.400642887 +0100 @@ -49,7 +49,7 @@ * Module parameters. */ -static unsigned int hid_mousepoll_interval; +static unsigned int hid_mousepoll_interval = ~0; module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); @@ -1090,8 +1090,12 @@ } /* Change the polling interval of mice. */ - if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) - interval = hid_mousepoll_interval; + if (hid->collection->usage == HID_GD_MOUSE) { + if (hid_mousepoll_interval == ~0 && interval < 16) + interval = 16; + else if (hid_mousepoll_interval != ~0 && hid_mousepoll_interval != 0) + interval = hid_mousepoll_interval; + } ret = -ENOMEM; if (usb_endpoint_dir_in(endpoint)) { diff -Nur '--exclude=.git' linux-stable/drivers/i2c/busses/i2c-bcm2708.c raspilinux/drivers/i2c/busses/i2c-bcm2708.c --- linux-stable/drivers/i2c/busses/i2c-bcm2708.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/i2c/busses/i2c-bcm2708.c 2015-12-26 19:08:31.424640649 +0100 @@ -0,0 +1,524 @@ +/* + * Driver for Broadcom BCM2708 BSC Controllers + * + * Copyright (C) 2012 Chris Boot & Frank Buss + * + * This driver is inspired by: + * i2c-ocores.c, by Peter Korsgaard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BSC register offsets */ +#define BSC_C 0x00 +#define BSC_S 0x04 +#define BSC_DLEN 0x08 +#define BSC_A 0x0c +#define BSC_FIFO 0x10 +#define BSC_DIV 0x14 +#define BSC_DEL 0x18 +#define BSC_CLKT 0x1c + +/* Bitfields in BSC_C */ +#define BSC_C_I2CEN 0x00008000 +#define BSC_C_INTR 0x00000400 +#define BSC_C_INTT 0x00000200 +#define BSC_C_INTD 0x00000100 +#define BSC_C_ST 0x00000080 +#define BSC_C_CLEAR_1 0x00000020 +#define BSC_C_CLEAR_2 0x00000010 +#define BSC_C_READ 0x00000001 + +/* Bitfields in BSC_S */ +#define BSC_S_CLKT 0x00000200 +#define BSC_S_ERR 0x00000100 +#define BSC_S_RXF 0x00000080 +#define BSC_S_TXE 0x00000040 +#define BSC_S_RXD 0x00000020 +#define BSC_S_TXD 0x00000010 +#define BSC_S_RXR 0x00000008 +#define BSC_S_TXW 0x00000004 +#define BSC_S_DONE 0x00000002 +#define BSC_S_TA 0x00000001 + +#define I2C_WAIT_LOOP_COUNT 200 + +#define DRV_NAME "bcm2708_i2c" + +static unsigned int baudrate = CONFIG_I2C_BCM2708_BAUDRATE; +module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); +MODULE_PARM_DESC(baudrate, "The I2C baudrate"); + +static bool combined = false; +module_param(combined, bool, 0644); +MODULE_PARM_DESC(combined, "Use combined transactions"); + +struct bcm2708_i2c { + struct i2c_adapter adapter; + + spinlock_t lock; + void __iomem *base; + int irq; + struct clk *clk; + u32 cdiv; + + struct completion done; + + struct i2c_msg *msg; + int pos; + int nmsgs; + bool error; +}; + +/* + * This function sets the ALT mode on the I2C pins so that we can use them with + * the BSC hardware. + * + * FIXME: This is a hack. Use pinmux / pinctrl. + */ +static void bcm2708_i2c_init_pinmode(int id) +{ +#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) +#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) + + int pin; + u32 *gpio = ioremap(GPIO_BASE, SZ_16K); + + BUG_ON(id != 0 && id != 1); + /* BSC0 is on GPIO 0 & 1, BSC1 is on GPIO 2 & 3 */ + for (pin = id*2+0; pin <= id*2+1; pin++) { + printk("bcm2708_i2c_init_pinmode(%d,%d)\n", id, pin); + INP_GPIO(pin); /* set mode to GPIO input first */ + SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */ + } + + iounmap(gpio); + +#undef INP_GPIO +#undef SET_GPIO_ALT +} + +static inline u32 bcm2708_rd(struct bcm2708_i2c *bi, unsigned reg) +{ + return readl(bi->base + reg); +} + +static inline void bcm2708_wr(struct bcm2708_i2c *bi, unsigned reg, u32 val) +{ + writel(val, bi->base + reg); +} + +static inline void bcm2708_bsc_reset(struct bcm2708_i2c *bi) +{ + bcm2708_wr(bi, BSC_C, 0); + bcm2708_wr(bi, BSC_S, BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE); +} + +static inline void bcm2708_bsc_fifo_drain(struct bcm2708_i2c *bi) +{ + while ((bcm2708_rd(bi, BSC_S) & BSC_S_RXD) && (bi->pos < bi->msg->len)) + bi->msg->buf[bi->pos++] = bcm2708_rd(bi, BSC_FIFO); +} + +static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi) +{ + while ((bcm2708_rd(bi, BSC_S) & BSC_S_TXD) && (bi->pos < bi->msg->len)) + bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]); +} + +static inline int bcm2708_bsc_setup(struct bcm2708_i2c *bi) +{ + u32 cdiv, s; + u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1; + int wait_loops = I2C_WAIT_LOOP_COUNT; + + /* Can't call clk_get_rate as it locks a mutex and here we are spinlocked. + * Use the value that we cached in the probe. + */ + cdiv = bi->cdiv; + + if (bi->msg->flags & I2C_M_RD) + c |= BSC_C_INTR | BSC_C_READ; + else + c |= BSC_C_INTT; + + bcm2708_wr(bi, BSC_DIV, cdiv); + bcm2708_wr(bi, BSC_A, bi->msg->addr); + bcm2708_wr(bi, BSC_DLEN, bi->msg->len); + if (combined) + { + /* Do the next two messages meet combined transaction criteria? + - Current message is a write, next message is a read + - Both messages to same slave address + - Write message can fit inside FIFO (16 bytes or less) */ + if ( (bi->nmsgs > 1) && + !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) && + (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) { + /* Fill FIFO with entire write message (16 byte FIFO) */ + while (bi->pos < bi->msg->len) { + bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]); + } + /* Start write transfer (no interrupts, don't clear FIFO) */ + bcm2708_wr(bi, BSC_C, BSC_C_I2CEN | BSC_C_ST); + + /* poll for transfer start bit (should only take 1-20 polls) */ + do { + s = bcm2708_rd(bi, BSC_S); + } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE)) && --wait_loops >= 0); + + /* did we time out or some error occured? */ + if (wait_loops < 0 || (s & (BSC_S_ERR | BSC_S_CLKT))) { + return -1; + } + + /* Send next read message before the write transfer finishes. */ + bi->nmsgs--; + bi->msg++; + bi->pos = 0; + bcm2708_wr(bi, BSC_DLEN, bi->msg->len); + c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_INTR | BSC_C_ST | BSC_C_READ; + } + } + bcm2708_wr(bi, BSC_C, c); + + return 0; +} + +static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id) +{ + struct bcm2708_i2c *bi = dev_id; + bool handled = true; + u32 s; + int ret; + + spin_lock(&bi->lock); + + /* we may see camera interrupts on the "other" I2C channel + Just return if we've not sent anything */ + if (!bi->nmsgs || !bi->msg) { + goto early_exit; + } + + s = bcm2708_rd(bi, BSC_S); + + if (s & (BSC_S_CLKT | BSC_S_ERR)) { + bcm2708_bsc_reset(bi); + bi->error = true; + + bi->msg = 0; /* to inform the that all work is done */ + bi->nmsgs = 0; + /* wake up our bh */ + complete(&bi->done); + } else if (s & BSC_S_DONE) { + bi->nmsgs--; + + if (bi->msg->flags & I2C_M_RD) { + bcm2708_bsc_fifo_drain(bi); + } + + bcm2708_bsc_reset(bi); + + if (bi->nmsgs) { + /* advance to next message */ + bi->msg++; + bi->pos = 0; + ret = bcm2708_bsc_setup(bi); + if (ret < 0) { + bcm2708_bsc_reset(bi); + bi->error = true; + bi->msg = 0; /* to inform the that all work is done */ + bi->nmsgs = 0; + /* wake up our bh */ + complete(&bi->done); + goto early_exit; + } + } else { + bi->msg = 0; /* to inform the that all work is done */ + bi->nmsgs = 0; + /* wake up our bh */ + complete(&bi->done); + } + } else if (s & BSC_S_TXW) { + bcm2708_bsc_fifo_fill(bi); + } else if (s & BSC_S_RXR) { + bcm2708_bsc_fifo_drain(bi); + } else { + handled = false; + } + +early_exit: + spin_unlock(&bi->lock); + + return handled ? IRQ_HANDLED : IRQ_NONE; +} + +static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct bcm2708_i2c *bi = adap->algo_data; + unsigned long flags; + int ret; + + spin_lock_irqsave(&bi->lock, flags); + + reinit_completion(&bi->done); + bi->msg = msgs; + bi->pos = 0; + bi->nmsgs = num; + bi->error = false; + + ret = bcm2708_bsc_setup(bi); + + spin_unlock_irqrestore(&bi->lock, flags); + + /* check the result of the setup */ + if (ret < 0) + { + dev_err(&adap->dev, "transfer setup timed out\n"); + goto error_timeout; + } + + ret = wait_for_completion_timeout(&bi->done, adap->timeout); + if (ret == 0) { + dev_err(&adap->dev, "transfer timed out\n"); + goto error_timeout; + } + + ret = bi->error ? -EIO : num; + return ret; + +error_timeout: + spin_lock_irqsave(&bi->lock, flags); + bcm2708_bsc_reset(bi); + bi->msg = 0; /* to inform the interrupt handler that there's nothing else to be done */ + bi->nmsgs = 0; + spin_unlock_irqrestore(&bi->lock, flags); + return -ETIMEDOUT; +} + +static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | /*I2C_FUNC_10BIT_ADDR |*/ I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm bcm2708_i2c_algorithm = { + .master_xfer = bcm2708_i2c_master_xfer, + .functionality = bcm2708_i2c_functionality, +}; + +static int bcm2708_i2c_probe(struct platform_device *pdev) +{ + struct resource *regs; + int irq, err = -ENOMEM; + struct clk *clk; + struct bcm2708_i2c *bi; + struct i2c_adapter *adap; + unsigned long bus_hz; + u32 cdiv; + + if (pdev->dev.of_node) { + u32 bus_clk_rate; + pdev->id = of_alias_get_id(pdev->dev.of_node, "i2c"); + if (pdev->id < 0) { + dev_err(&pdev->dev, "alias is missing\n"); + return -EINVAL; + } + if (!of_property_read_u32(pdev->dev.of_node, + "clock-frequency", &bus_clk_rate)) + baudrate = bus_clk_rate; + else + dev_warn(&pdev->dev, + "Could not read clock-frequency property\n"); + } + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "could not get IO memory\n"); + return -ENXIO; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "could not get IRQ\n"); + return irq; + } + + clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk)); + return PTR_ERR(clk); + } + + err = clk_prepare_enable(clk); + if (err) { + dev_err(&pdev->dev, "could not enable clk: %d\n", err); + goto out_clk_put; + } + + if (!pdev->dev.of_node) + bcm2708_i2c_init_pinmode(pdev->id); + + bi = kzalloc(sizeof(*bi), GFP_KERNEL); + if (!bi) + goto out_clk_disable; + + platform_set_drvdata(pdev, bi); + + adap = &bi->adapter; + adap->class = I2C_CLASS_HWMON | I2C_CLASS_DDC; + adap->algo = &bcm2708_i2c_algorithm; + adap->algo_data = bi; + adap->dev.parent = &pdev->dev; + adap->nr = pdev->id; + strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); + adap->dev.of_node = pdev->dev.of_node; + + switch (pdev->id) { + case 0: + adap->class = I2C_CLASS_HWMON; + break; + case 1: + adap->class = I2C_CLASS_DDC; + break; + case 2: + adap->class = I2C_CLASS_DDC; + break; + default: + dev_err(&pdev->dev, "can only bind to BSC 0, 1 or 2\n"); + err = -ENXIO; + goto out_free_bi; + } + + spin_lock_init(&bi->lock); + init_completion(&bi->done); + + bi->base = ioremap(regs->start, resource_size(regs)); + if (!bi->base) { + dev_err(&pdev->dev, "could not remap memory\n"); + goto out_free_bi; + } + + bi->irq = irq; + bi->clk = clk; + + err = request_irq(irq, bcm2708_i2c_interrupt, IRQF_SHARED, + dev_name(&pdev->dev), bi); + if (err) { + dev_err(&pdev->dev, "could not request IRQ: %d\n", err); + goto out_iounmap; + } + + bcm2708_bsc_reset(bi); + + err = i2c_add_numbered_adapter(adap); + if (err < 0) { + dev_err(&pdev->dev, "could not add I2C adapter: %d\n", err); + goto out_free_irq; + } + + bus_hz = clk_get_rate(bi->clk); + cdiv = bus_hz / baudrate; + if (cdiv > 0xffff) { + cdiv = 0xffff; + baudrate = bus_hz / cdiv; + } + bi->cdiv = cdiv; + + dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %d)\n", + pdev->id, (unsigned long)regs->start, irq, baudrate); + + return 0; + +out_free_irq: + free_irq(bi->irq, bi); +out_iounmap: + iounmap(bi->base); +out_free_bi: + kfree(bi); +out_clk_disable: + clk_disable_unprepare(clk); +out_clk_put: + clk_put(clk); + return err; +} + +static int bcm2708_i2c_remove(struct platform_device *pdev) +{ + struct bcm2708_i2c *bi = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + + i2c_del_adapter(&bi->adapter); + free_irq(bi->irq, bi); + iounmap(bi->base); + clk_disable_unprepare(bi->clk); + clk_put(bi->clk); + kfree(bi); + + return 0; +} + +static const struct of_device_id bcm2708_i2c_of_match[] = { + { .compatible = "brcm,bcm2708-i2c" }, + {}, +}; +MODULE_DEVICE_TABLE(of, bcm2708_i2c_of_match); + +static struct platform_driver bcm2708_i2c_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = bcm2708_i2c_of_match, + }, + .probe = bcm2708_i2c_probe, + .remove = bcm2708_i2c_remove, +}; + +// module_platform_driver(bcm2708_i2c_driver); + + +static int __init bcm2708_i2c_init(void) +{ + return platform_driver_register(&bcm2708_i2c_driver); +} + +static void __exit bcm2708_i2c_exit(void) +{ + platform_driver_unregister(&bcm2708_i2c_driver); +} + +module_init(bcm2708_i2c_init); +module_exit(bcm2708_i2c_exit); + + + +MODULE_DESCRIPTION("BSC controller driver for Broadcom BCM2708"); +MODULE_AUTHOR("Chris Boot "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); diff -Nur '--exclude=.git' linux-stable/drivers/i2c/busses/Kconfig raspilinux/drivers/i2c/busses/Kconfig --- linux-stable/drivers/i2c/busses/Kconfig 2015-12-26 20:45:00.671958577 +0100 +++ raspilinux/drivers/i2c/busses/Kconfig 2015-12-26 19:08:31.424640649 +0100 @@ -8,6 +8,25 @@ comment "PC SMBus host controller drivers" depends on PCI +config I2C_BCM2708 + tristate "BCM2708 BSC" + depends on MACH_BCM2708 || MACH_BCM2709 + help + Enabling this option will add BSC (Broadcom Serial Controller) + support for the BCM2708. BSC is a Broadcom proprietary bus compatible + with I2C/TWI/SMBus. + +config I2C_BCM2708_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. + config I2C_ALI1535 tristate "ALI 1535" depends on PCI @@ -362,7 +381,7 @@ config I2C_BCM2835 tristate "Broadcom BCM2835 I2C controller" - depends on ARCH_BCM2835 + depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 help If you say yes to this option, support will be included for the BCM2835 I2C controller. diff -Nur '--exclude=.git' linux-stable/drivers/i2c/busses/Makefile raspilinux/drivers/i2c/busses/Makefile --- linux-stable/drivers/i2c/busses/Makefile 2015-12-26 20:45:00.671958577 +0100 +++ raspilinux/drivers/i2c/busses/Makefile 2015-12-26 19:08:31.424640649 +0100 @@ -2,6 +2,8 @@ # Makefile for the i2c bus drivers. # +obj-$(CONFIG_I2C_BCM2708) += i2c-bcm2708.o + # ACPI drivers obj-$(CONFIG_I2C_SCMI) += i2c-scmi.o diff -Nur '--exclude=.git' linux-stable/drivers/input/joystick/Kconfig raspilinux/drivers/input/joystick/Kconfig --- linux-stable/drivers/input/joystick/Kconfig 2015-12-26 20:45:00.775948992 +0100 +++ raspilinux/drivers/input/joystick/Kconfig 2015-12-26 19:08:31.500633562 +0100 @@ -329,4 +329,12 @@ To compile this as a module choose M here: the module will be called maplecontrol. +config JOYSTICK_RPISENSE + tristate "Raspberry Pi Sense HAT joystick" + depends on GPIOLIB && INPUT + select MFD_RPISENSE_CORE + + help + This is the joystick driver for the Raspberry Pi Sense HAT + endif diff -Nur '--exclude=.git' linux-stable/drivers/input/joystick/Makefile raspilinux/drivers/input/joystick/Makefile --- linux-stable/drivers/input/joystick/Makefile 2015-12-26 20:38:45.222561571 +0100 +++ raspilinux/drivers/input/joystick/Makefile 2015-12-26 19:08:31.500633562 +0100 @@ -32,4 +32,5 @@ obj-$(CONFIG_JOYSTICK_XPAD) += xpad.o obj-$(CONFIG_JOYSTICK_ZHENHUA) += zhenhua.o obj-$(CONFIG_JOYSTICK_WALKERA0701) += walkera0701.o +obj-$(CONFIG_JOYSTICK_RPISENSE) += rpisense-js.o diff -Nur '--exclude=.git' linux-stable/drivers/input/joystick/rpisense-js.c raspilinux/drivers/input/joystick/rpisense-js.c --- linux-stable/drivers/input/joystick/rpisense-js.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/input/joystick/rpisense-js.c 2015-12-26 19:08:31.500633562 +0100 @@ -0,0 +1,153 @@ +/* + * Raspberry Pi Sense HAT joystick driver + * http://raspberrypi.org + * + * Copyright (C) 2015 Raspberry Pi + * + * Author: Serge Schneider + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include + +#include +#include + +struct rpisense *rpisense; +unsigned char keymap[5] = {KEY_DOWN, KEY_RIGHT, KEY_UP, KEY_ENTER, KEY_LEFT,}; + +static void keys_work_fn(struct work_struct *work) +{ + int i; + static s32 prev_keys; + struct rpisense_js *rpisense_js = &rpisense->joystick; + s32 keys = rpisense_reg_read(rpisense, RPISENSE_KEYS); + s32 changes = keys ^ prev_keys; + + prev_keys = keys; + for (i = 0; i < 5; i++) { + if (changes & 1) { + input_report_key(rpisense_js->keys_dev, + keymap[i], keys & 1); + } + changes >>= 1; + keys >>= 1; + } + input_sync(rpisense_js->keys_dev); +} + +static irqreturn_t keys_irq_handler(int irq, void *pdev) +{ + struct rpisense_js *rpisense_js = &rpisense->joystick; + + schedule_work(&rpisense_js->keys_work_s); + return IRQ_HANDLED; +} + +static int rpisense_js_probe(struct platform_device *pdev) +{ + int ret; + int i; + struct rpisense_js *rpisense_js; + + rpisense = rpisense_get_dev(); + rpisense_js = &rpisense->joystick; + + INIT_WORK(&rpisense_js->keys_work_s, keys_work_fn); + + rpisense_js->keys_dev = input_allocate_device(); + if (!rpisense_js->keys_dev) { + dev_err(&pdev->dev, "Could not allocate input device.\n"); + return -ENOMEM; + } + + rpisense_js->keys_dev->evbit[0] = BIT_MASK(EV_KEY); + for (i = 0; i < ARRAY_SIZE(keymap); i++) { + set_bit(keymap[i], + rpisense_js->keys_dev->keybit); + } + + rpisense_js->keys_dev->name = "Raspberry Pi Sense HAT Joystick"; + rpisense_js->keys_dev->phys = "rpi-sense-joy/input0"; + rpisense_js->keys_dev->id.bustype = BUS_I2C; + rpisense_js->keys_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); + rpisense_js->keys_dev->keycode = keymap; + rpisense_js->keys_dev->keycodesize = sizeof(unsigned char); + rpisense_js->keys_dev->keycodemax = ARRAY_SIZE(keymap); + + ret = input_register_device(rpisense_js->keys_dev); + if (ret) { + dev_err(&pdev->dev, "Could not register input device.\n"); + goto err_keys_alloc; + } + + ret = gpiod_direction_input(rpisense_js->keys_desc); + if (ret) { + dev_err(&pdev->dev, "Could not set keys-int direction.\n"); + goto err_keys_reg; + } + + rpisense_js->keys_irq = gpiod_to_irq(rpisense_js->keys_desc); + if (rpisense_js->keys_irq < 0) { + dev_err(&pdev->dev, "Could not determine keys-int IRQ.\n"); + ret = rpisense_js->keys_irq; + goto err_keys_reg; + } + + ret = devm_request_irq(&pdev->dev, rpisense_js->keys_irq, + keys_irq_handler, IRQF_TRIGGER_RISING, + "keys", &pdev->dev); + if (ret) { + dev_err(&pdev->dev, "IRQ request failed.\n"); + goto err_keys_reg; + } + return 0; +err_keys_reg: + input_unregister_device(rpisense_js->keys_dev); +err_keys_alloc: + input_free_device(rpisense_js->keys_dev); + return ret; +} + +static int rpisense_js_remove(struct platform_device *pdev) +{ + struct rpisense_js *rpisense_js = &rpisense->joystick; + + input_unregister_device(rpisense_js->keys_dev); + input_free_device(rpisense_js->keys_dev); + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id rpisense_js_id[] = { + { .compatible = "rpi,rpi-sense-js" }, + { }, +}; +MODULE_DEVICE_TABLE(of, rpisense_js_id); +#endif + +static struct platform_device_id rpisense_js_device_id[] = { + { .name = "rpi-sense-js" }, + { }, +}; +MODULE_DEVICE_TABLE(platform, rpisense_js_device_id); + +static struct platform_driver rpisense_js_driver = { + .probe = rpisense_js_probe, + .remove = rpisense_js_remove, + .driver = { + .name = "rpi-sense-js", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(rpisense_js_driver); + +MODULE_DESCRIPTION("Raspberry Pi Sense HAT joystick driver"); +MODULE_AUTHOR("Serge Schneider "); +MODULE_LICENSE("GPL"); diff -Nur '--exclude=.git' linux-stable/drivers/input/touchscreen/ft6236.c raspilinux/drivers/input/touchscreen/ft6236.c --- linux-stable/drivers/input/touchscreen/ft6236.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/input/touchscreen/ft6236.c 2015-12-26 19:08:31.524631324 +0100 @@ -0,0 +1,326 @@ +/* + * FocalTech FT6236 TouchScreen driver. + * + * Copyright (c) 2010 Focal tech Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define FT6236_MAX_TOUCH_POINTS 2 + +#define FT6236_REG_TH_GROUP 0x80 +#define FT6236_REG_PERIODACTIVE 0x88 +#define FT6236_REG_LIB_VER_H 0xa1 +#define FT6236_REG_LIB_VER_L 0xa2 +#define FT6236_REG_CIPHER 0xa3 +#define FT6236_REG_FIRMID 0xa6 +#define FT6236_REG_FOCALTECH_ID 0xa8 +#define FT6236_REG_RELEASE_CODE_ID 0xaf + +#define FT6236_EVENT_PRESS_DOWN 0 +#define FT6236_EVENT_LIFT_UP 1 +#define FT6236_EVENT_CONTACT 2 +#define FT6236_EVENT_NO_EVENT 3 + +struct ft6236_data { + struct i2c_client *client; + struct input_dev *input; + struct gpio_desc *reset_gpio; + u32 max_x; + u32 max_y; + bool invert_x; + bool invert_y; + bool swap_xy; +}; + +/* + * This struct is a touchpoint as stored in hardware. Note that the id, + * as well as the event, are stored in the upper nybble of the hi byte. + */ +struct ft6236_touchpoint { + union { + u8 xhi; + u8 event; + }; + u8 xlo; + union { + u8 yhi; + u8 id; + }; + u8 ylo; + u8 weight; + u8 misc; +} __packed; + +/* This packet represents the register map as read from offset 0 */ +struct ft6236_packet { + u8 dev_mode; + u8 gest_id; + u8 touches; + struct ft6236_touchpoint points[FT6236_MAX_TOUCH_POINTS]; +} __packed; + +static int ft6236_read(struct i2c_client *client, u8 reg, u8 len, void *data) +{ + int error; + + error = i2c_smbus_read_i2c_block_data(client, reg, len, data); + if (error < 0) + return error; + + if (error != len) + return -EIO; + + return 0; +} + +static irqreturn_t ft6236_interrupt(int irq, void *dev_id) +{ + struct ft6236_data *ft6236 = dev_id; + struct device *dev = &ft6236->client->dev; + struct input_dev *input = ft6236->input; + struct ft6236_packet buf; + u8 touches; + int i, error; + + error = ft6236_read(ft6236->client, 0, sizeof(buf), &buf); + if (error) { + dev_err(dev, "read touchdata failed %d\n", error); + return IRQ_HANDLED; + } + + touches = buf.touches & 0xf; + if (touches > FT6236_MAX_TOUCH_POINTS) { + dev_dbg(dev, + "%d touch points reported, only %d are supported\n", + touches, FT6236_MAX_TOUCH_POINTS); + touches = FT6236_MAX_TOUCH_POINTS; + } + + for (i = 0; i < touches; i++) { + struct ft6236_touchpoint *point = &buf.points[i]; + u16 x = ((point->xhi & 0xf) << 8) | buf.points[i].xlo; + u16 y = ((point->yhi & 0xf) << 8) | buf.points[i].ylo; + u8 event = point->event >> 6; + u8 id = point->id >> 4; + bool act = (event == FT6236_EVENT_PRESS_DOWN || + event == FT6236_EVENT_CONTACT); + + input_mt_slot(input, id); + input_mt_report_slot_state(input, MT_TOOL_FINGER, act); + if (!act) + continue; + + if (ft6236->invert_x) + x = ft6236->max_x - x; + + if (ft6236->invert_y) + y = ft6236->max_y - y; + + if (ft6236->swap_xy) { + input_report_abs(input, ABS_MT_POSITION_X, y); + input_report_abs(input, ABS_MT_POSITION_Y, x); + } else { + input_report_abs(input, ABS_MT_POSITION_X, x); + input_report_abs(input, ABS_MT_POSITION_Y, y); + } + } + + input_mt_sync_frame(input); + input_sync(input); + + return IRQ_HANDLED; +} + +static u8 ft6236_debug_read_byte(struct ft6236_data *ft6236, u8 reg) +{ + struct i2c_client *client = ft6236->client; + u8 val = 0; + int error; + + error = ft6236_read(client, reg, 1, &val); + if (error) + dev_dbg(&client->dev, + "error reading register 0x%02x: %d\n", reg, error); + + return val; +} + +static void ft6236_debug_info(struct ft6236_data *ft6236) +{ + struct device *dev = &ft6236->client->dev; + + dev_dbg(dev, "Touch threshold is %d\n", + ft6236_debug_read_byte(ft6236, FT6236_REG_TH_GROUP) * 4); + dev_dbg(dev, "Report rate is %dHz\n", + ft6236_debug_read_byte(ft6236, FT6236_REG_PERIODACTIVE) * 10); + dev_dbg(dev, "Firmware library version 0x%02x%02x\n", + ft6236_debug_read_byte(ft6236, FT6236_REG_LIB_VER_H), + ft6236_debug_read_byte(ft6236, FT6236_REG_LIB_VER_L)); + dev_dbg(dev, "Firmware version 0x%02x\n", + ft6236_debug_read_byte(ft6236, FT6236_REG_FIRMID)); + dev_dbg(dev, "Chip vendor ID 0x%02x\n", + ft6236_debug_read_byte(ft6236, FT6236_REG_CIPHER)); + dev_dbg(dev, "CTPM vendor ID 0x%02x\n", + ft6236_debug_read_byte(ft6236, FT6236_REG_FOCALTECH_ID)); + dev_dbg(dev, "Release code version 0x%02x\n", + ft6236_debug_read_byte(ft6236, FT6236_REG_RELEASE_CODE_ID)); +} + +static void ft6236_reset(struct ft6236_data *ft6236) +{ + if (!ft6236->reset_gpio) + return; + + gpiod_set_value_cansleep(ft6236->reset_gpio, 1); + usleep_range(5000, 20000); + gpiod_set_value_cansleep(ft6236->reset_gpio, 0); + msleep(300); +} + +static int ft6236_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct ft6236_data *ft6236; + struct input_dev *input; + u32 fuzz_x = 0, fuzz_y = 0; + u8 val; + int error; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENXIO; + + if (!client->irq) { + dev_err(dev, "irq is missing\n"); + return -EINVAL; + } + + ft6236 = devm_kzalloc(dev, sizeof(*ft6236), GFP_KERNEL); + if (!ft6236) + return -ENOMEM; + + ft6236->client = client; + ft6236->reset_gpio = devm_gpiod_get_optional(dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(ft6236->reset_gpio)) { + error = PTR_ERR(ft6236->reset_gpio); + if (error != -EPROBE_DEFER) + dev_err(dev, "error getting reset gpio: %d\n", error); + return error; + } + + ft6236_reset(ft6236); + + /* verify that the controller is present */ + error = ft6236_read(client, 0x00, 1, &val); + if (error) { + dev_err(dev, "failed to read from controller: %d\n", error); + return error; + } + + ft6236_debug_info(ft6236); + + input = devm_input_allocate_device(dev); + if (!input) + return -ENOMEM; + + ft6236->input = input; + input->name = client->name; + input->id.bustype = BUS_I2C; + + if (device_property_read_u32(dev, "touchscreen-size-x", + &ft6236->max_x) || + device_property_read_u32(dev, "touchscreen-size-y", + &ft6236->max_y)) { + dev_err(dev, "touchscreen-size-x and/or -y missing\n"); + return -EINVAL; + } + + device_property_read_u32(dev, "touchscreen-fuzz-x", &fuzz_x); + device_property_read_u32(dev, "touchscreen-fuzz-y", &fuzz_y); + ft6236->invert_x = device_property_read_bool(dev, + "touchscreen-inverted-x"); + ft6236->invert_y = device_property_read_bool(dev, + "touchscreen-inverted-y"); + ft6236->swap_xy = device_property_read_bool(dev, + "touchscreen-swapped-x-y"); + + if (ft6236->swap_xy) { + input_set_abs_params(input, ABS_MT_POSITION_X, 0, + ft6236->max_y, fuzz_y, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, 0, + ft6236->max_x, fuzz_x, 0); + } else { + input_set_abs_params(input, ABS_MT_POSITION_X, 0, + ft6236->max_x, fuzz_x, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, 0, + ft6236->max_y, fuzz_y, 0); + } + + error = input_mt_init_slots(input, FT6236_MAX_TOUCH_POINTS, + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); + if (error) + return error; + + error = devm_request_threaded_irq(dev, client->irq, NULL, + ft6236_interrupt, IRQF_ONESHOT, + client->name, ft6236); + if (error) { + dev_err(dev, "request irq %d failed: %d\n", client->irq, error); + return error; + } + + error = input_register_device(input); + if (error) { + dev_err(dev, "failed to register input device: %d\n", error); + return error; + } + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id ft6236_of_match[] = { + { .compatible = "focaltech,ft6236", }, + { } +}; +MODULE_DEVICE_TABLE(of, ft6236_of_match); +#endif + +static const struct i2c_device_id ft6236_id[] = { + { "ft6236", }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ft6236_id); + +static struct i2c_driver ft6236_driver = { + .driver = { + .name = "ft6236", + .of_match_table = of_match_ptr(ft6236_of_match), + }, + .probe = ft6236_probe, + .id_table = ft6236_id, +}; +module_i2c_driver(ft6236_driver); + +MODULE_AUTHOR("Sean Cross "); +MODULE_AUTHOR("Noralf Trønnes "); +MODULE_DESCRIPTION("FocalTech FT6236 TouchScreen driver"); +MODULE_LICENSE("GPL v2"); diff -Nur '--exclude=.git' linux-stable/drivers/input/touchscreen/Kconfig raspilinux/drivers/input/touchscreen/Kconfig --- linux-stable/drivers/input/touchscreen/Kconfig 2015-12-26 20:45:00.795947149 +0100 +++ raspilinux/drivers/input/touchscreen/Kconfig 2015-12-26 19:08:31.520631697 +0100 @@ -295,6 +295,19 @@ To compile this driver as a module, choose M here: the module will be called egalax_ts. +config TOUCHSCREEN_FT6236 + tristate "FT6236 I2C touchscreen" + depends on I2C + depends on GPIOLIB || COMPILE_TEST + help + Say Y here to enable support for the I2C connected FT6x06 and + FT6x36 family of capacitive touchscreen drivers. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called ft6236. + config TOUCHSCREEN_FUJITSU tristate "Fujitsu serial touchscreen" select SERIO @@ -583,6 +596,13 @@ To compile this driver as a module, choose M here: the module will be called edt-ft5x06. +config TOUCHSCREEN_RPI_FT5406 + tristate "Raspberry Pi FT5406 driver" + depends on RASPBERRYPI_FIRMWARE + help + Say Y here to enable the Raspberry Pi memory based FT5406 device + + config TOUCHSCREEN_MIGOR tristate "Renesas MIGO-R touchscreen" depends on SH_MIGOR && I2C diff -Nur '--exclude=.git' linux-stable/drivers/input/touchscreen/Makefile raspilinux/drivers/input/touchscreen/Makefile --- linux-stable/drivers/input/touchscreen/Makefile 2015-12-26 20:45:00.795947149 +0100 +++ raspilinux/drivers/input/touchscreen/Makefile 2015-12-26 19:08:31.520631697 +0100 @@ -29,12 +29,14 @@ obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o +obj-$(CONFIG_TOUCHSCREEN_RPI_FT5406) += rpi-ft5406.o obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o obj-$(CONFIG_TOUCHSCREEN_ELAN) += elants_i2c.o obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o +obj-$(CONFIG_TOUCHSCREEN_FT6236) += ft6236.o obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o diff -Nur '--exclude=.git' linux-stable/drivers/input/touchscreen/rpi-ft5406.c raspilinux/drivers/input/touchscreen/rpi-ft5406.c --- linux-stable/drivers/input/touchscreen/rpi-ft5406.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/input/touchscreen/rpi-ft5406.c 2015-12-26 19:08:31.524631324 +0100 @@ -0,0 +1,246 @@ +/* + * Driver for memory based ft5406 touchscreen + * + * Copyright (C) 2015 Raspberry Pi + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAXIMUM_SUPPORTED_POINTS 10 +struct ft5406_regs { + uint8_t device_mode; + uint8_t gesture_id; + uint8_t num_points; + struct ft5406_touch { + uint8_t xh; + uint8_t xl; + uint8_t yh; + uint8_t yl; + uint8_t res1; + uint8_t res2; + } point[MAXIMUM_SUPPORTED_POINTS]; +}; + +#define SCREEN_WIDTH 800 +#define SCREEN_HEIGHT 480 + +struct ft5406 { + struct platform_device * pdev; + struct input_dev * input_dev; + void __iomem * ts_base; + struct ft5406_regs * regs; + struct task_struct * thread; +}; + +/* Thread to poll for touchscreen events + * + * This thread polls the memory based register copy of the ft5406 registers + * using the number of points register to know whether the copy has been + * updated (we write 99 to the memory copy, the GPU will write between + * 0 - 10 points) + */ +static int ft5406_thread(void *arg) +{ + struct ft5406 *ts = (struct ft5406 *) arg; + struct ft5406_regs regs; + int known_ids = 0; + + while(!kthread_should_stop()) + { + // 60fps polling + msleep_interruptible(17); + memcpy_fromio(®s, ts->regs, sizeof(*ts->regs)); + writel(99, &ts->regs->num_points); + // Do not output if theres no new information (num_points is 99) + // or we have no touch points and don't need to release any + if(!(regs.num_points == 99 || (regs.num_points == 0 && known_ids == 0))) + { + int i; + int modified_ids = 0, released_ids; + for(i = 0; i < regs.num_points; i++) + { + int x = (((int) regs.point[i].xh & 0xf) << 8) + regs.point[i].xl; + int y = (((int) regs.point[i].yh & 0xf) << 8) + regs.point[i].yl; + int touchid = (regs.point[i].yh >> 4) & 0xf; + + modified_ids |= 1 << touchid; + + if(!((1 << touchid) & known_ids)) + dev_dbg(&ts->pdev->dev, "x = %d, y = %d, touchid = %d\n", x, y, touchid); + + input_mt_slot(ts->input_dev, touchid); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1); + + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y); + + } + + released_ids = known_ids & ~modified_ids; + for(i = 0; released_ids && i < MAXIMUM_SUPPORTED_POINTS; i++) + { + if(released_ids & (1<pdev->dev, "Released %d, known = %x modified = %x\n", i, known_ids, modified_ids); + input_mt_slot(ts->input_dev, i); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); + modified_ids &= ~(1 << i); + } + } + known_ids = modified_ids; + + input_mt_report_pointer_emulation(ts->input_dev, true); + input_sync(ts->input_dev); + } + + } + + return 0; +} + +static int ft5406_probe(struct platform_device *pdev) +{ + int ret; + struct input_dev * input_dev = input_allocate_device(); + struct ft5406 * ts; + struct device_node *fw_node; + struct rpi_firmware *fw; + u32 touchbuf; + + dev_info(&pdev->dev, "Probing device\n"); + + fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); + if (!fw_node) { + dev_err(&pdev->dev, "Missing firmware node\n"); + return -ENOENT; + } + + fw = rpi_firmware_get(fw_node); + if (!fw) + return -EPROBE_DEFER; + + ret = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF, + &touchbuf, sizeof(touchbuf)); + if (ret) { + dev_err(&pdev->dev, "Failed to get touch buffer\n"); + return ret; + } + + if (!touchbuf) { + dev_err(&pdev->dev, "Touchscreen not detected\n"); + return -ENODEV; + } + + dev_dbg(&pdev->dev, "Got TS buffer 0x%x\n", touchbuf); + + ts = kzalloc(sizeof(struct ft5406), GFP_KERNEL); + + if (!ts || !input_dev) { + ret = -ENOMEM; + dev_err(&pdev->dev, "Failed to allocate memory\n"); + return ret; + } + ts->input_dev = input_dev; + platform_set_drvdata(pdev, ts); + ts->pdev = pdev; + + input_dev->name = "FT5406 memory based driver"; + + __set_bit(EV_KEY, input_dev->evbit); + __set_bit(EV_SYN, input_dev->evbit); + __set_bit(EV_ABS, input_dev->evbit); + + input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, + SCREEN_WIDTH, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, + SCREEN_HEIGHT, 0, 0); + + input_mt_init_slots(input_dev, MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT); + + input_set_drvdata(input_dev, ts); + + ret = input_register_device(input_dev); + if (ret) { + dev_err(&pdev->dev, "could not register input device, %d\n", + ret); + return ret; + } + + // mmap the physical memory + touchbuf &= ~0xc0000000; + ts->ts_base = ioremap(touchbuf, sizeof(*ts->regs)); + if(ts->ts_base == NULL) + { + dev_err(&pdev->dev, "Failed to map physical address\n"); + input_unregister_device(input_dev); + kzfree(ts); + return -ENOMEM; + } + + ts->regs = (struct ft5406_regs *) ts->ts_base; + + // create thread to poll the touch events + ts->thread = kthread_run(ft5406_thread, ts, "ft5406"); + if(ts->thread == NULL) + { + dev_err(&pdev->dev, "Failed to create kernel thread"); + iounmap(ts->ts_base); + input_unregister_device(input_dev); + kzfree(ts); + } + + return 0; +} + +static int ft5406_remove(struct platform_device *pdev) +{ + struct ft5406 *ts = (struct ft5406 *) platform_get_drvdata(pdev); + + dev_info(&pdev->dev, "Removing rpi-ft5406\n"); + + kthread_stop(ts->thread); + iounmap(ts->ts_base); + input_unregister_device(ts->input_dev); + kzfree(ts); + + return 0; +} + +static const struct of_device_id ft5406_match[] = { + { .compatible = "rpi,rpi-ft5406", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ft5406_match); + +static struct platform_driver ft5406_driver = { + .driver = { + .name = "rpi-ft5406", + .owner = THIS_MODULE, + .of_match_table = ft5406_match, + }, + .probe = ft5406_probe, + .remove = ft5406_remove, +}; + +module_platform_driver(ft5406_driver); + +MODULE_AUTHOR("Gordon Hollingworth"); +MODULE_DESCRIPTION("Touchscreen driver for memory based FT5406"); +MODULE_LICENSE("GPL"); diff -Nur '--exclude=.git' linux-stable/drivers/irqchip/irq-bcm2835.c raspilinux/drivers/irqchip/irq-bcm2835.c --- linux-stable/drivers/irqchip/irq-bcm2835.c 2015-12-26 20:45:00.811945674 +0100 +++ raspilinux/drivers/irqchip/irq-bcm2835.c 2015-12-26 19:08:31.532630578 +0100 @@ -56,7 +56,7 @@ #include "irqchip.h" /* Put the bank and irq (32 bits) into the hwirq */ -#define MAKE_HWIRQ(b, n) ((b << 5) | (n)) +#define MAKE_HWIRQ(b, n) (((b) << 5) | (n)) #define HWIRQ_BANK(i) (i >> 5) #define HWIRQ_BIT(i) BIT(i & 0x1f) @@ -72,9 +72,13 @@ | SHORTCUT1_MASK | SHORTCUT2_MASK) #define REG_FIQ_CONTROL 0x0c +#define REG_FIQ_ENABLE 0x80 +#define REG_FIQ_DISABLE 0 #define NR_BANKS 3 #define IRQS_PER_BANK 32 +#define NUMBER_IRQS MAKE_HWIRQ(NR_BANKS, 0) +#define FIQ_START (NR_IRQS_BANK0 + MAKE_HWIRQ(NR_BANKS - 1, 0)) static int reg_pending[] __initconst = { 0x00, 0x04, 0x08 }; static int reg_enable[] __initconst = { 0x18, 0x10, 0x14 }; @@ -98,14 +102,38 @@ static void __exception_irq_entry bcm2835_handle_irq( struct pt_regs *regs); +static inline unsigned int hwirq_to_fiq(unsigned long hwirq) +{ + hwirq -= NUMBER_IRQS; + /* + * The hwirq numbering used in this driver is: + * BASE (0-7) GPU1 (32-63) GPU2 (64-95). + * This differ from the one used in the FIQ register: + * GPU1 (0-31) GPU2 (32-63) BASE (64-71) + */ + if (hwirq >= 32) + return hwirq - 32; + + return hwirq + 64; +} + static void armctrl_mask_irq(struct irq_data *d) { - writel_relaxed(HWIRQ_BIT(d->hwirq), intc.disable[HWIRQ_BANK(d->hwirq)]); + if (d->hwirq >= NUMBER_IRQS) + writel_relaxed(REG_FIQ_DISABLE, intc.base + REG_FIQ_CONTROL); + else + writel_relaxed(HWIRQ_BIT(d->hwirq), + intc.disable[HWIRQ_BANK(d->hwirq)]); } static void armctrl_unmask_irq(struct irq_data *d) { - writel_relaxed(HWIRQ_BIT(d->hwirq), intc.enable[HWIRQ_BANK(d->hwirq)]); + if (d->hwirq >= NUMBER_IRQS) + writel_relaxed(REG_FIQ_ENABLE | hwirq_to_fiq(d->hwirq), + intc.base + REG_FIQ_CONTROL); + else + writel_relaxed(HWIRQ_BIT(d->hwirq), + intc.enable[HWIRQ_BANK(d->hwirq)]); } static struct irq_chip armctrl_chip = { @@ -150,8 +178,9 @@ panic("%s: unable to map IC registers\n", node->full_name); - intc.domain = irq_domain_add_linear(node, MAKE_HWIRQ(NR_BANKS, 0), - &armctrl_ops, NULL); + intc.base = base; + intc.domain = irq_domain_add_linear(node, NUMBER_IRQS * 2, + &armctrl_ops, NULL); if (!intc.domain) panic("%s: unable to create IRQ domain\n", node->full_name); @@ -168,8 +197,20 @@ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } } - set_handle_irq(bcm2835_handle_irq); + + /* Make a duplicate irq range which is used to enable FIQ */ + for (b = 0; b < NR_BANKS; b++) { + for (i = 0; i < bank_irqs[b]; i++) { + irq = irq_create_mapping(intc.domain, + MAKE_HWIRQ(b, i) + NUMBER_IRQS); + BUG_ON(irq <= 0); + irq_set_chip(irq, &armctrl_chip); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + } + init_FIQ(FIQ_START); + return 0; } diff -Nur '--exclude=.git' linux-stable/drivers/leds/leds-gpio.c raspilinux/drivers/leds/leds-gpio.c --- linux-stable/drivers/leds/leds-gpio.c 2015-12-26 20:45:00.827944200 +0100 +++ raspilinux/drivers/leds/leds-gpio.c 2015-12-26 19:08:31.568627221 +0100 @@ -41,6 +41,13 @@ led_dat->platform_gpio_blink_set(led_dat->gpiod, led_dat->new_level, NULL, NULL); led_dat->blinking = 0; + } else if (led_dat->cdev.flags & SET_GPIO_INPUT) { + gpiod_direction_input(led_dat->gpiod); + led_dat->cdev.flags &= ~SET_GPIO_INPUT; + } + else if (led_dat->cdev.flags & SET_GPIO_OUTPUT) { + gpiod_direction_output(led_dat->gpiod, led_dat->new_level); + led_dat->cdev.flags &= ~SET_GPIO_OUTPUT; } else gpiod_set_value_cansleep(led_dat->gpiod, led_dat->new_level); } @@ -61,7 +68,8 @@ * seem to have a reliable way to know if we're already in one; so * let's just assume the worst. */ - if (led_dat->can_sleep) { + if (led_dat->can_sleep || + (led_dat->cdev.flags & (SET_GPIO_INPUT | SET_GPIO_OUTPUT) )) { led_dat->new_level = level; schedule_work(&led_dat->work); } else { @@ -74,6 +82,13 @@ } } +static enum led_brightness gpio_led_get(struct led_classdev *led_cdev) +{ + struct gpio_led_data *led_dat = + container_of(led_cdev, struct gpio_led_data, cdev); + return gpiod_get_value_cansleep(led_dat->gpiod) ? LED_FULL : LED_OFF; +} + static int gpio_blink_set(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off) { @@ -130,6 +145,7 @@ led_dat->cdev.blink_set = gpio_blink_set; } led_dat->cdev.brightness_set = gpio_led_set; + led_dat->cdev.brightness_get = gpio_led_get; if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) state = !!gpiod_get_value_cansleep(led_dat->gpiod); else diff -Nur '--exclude=.git' linux-stable/drivers/leds/trigger/Kconfig raspilinux/drivers/leds/trigger/Kconfig --- linux-stable/drivers/leds/trigger/Kconfig 2015-12-26 20:45:00.831943831 +0100 +++ raspilinux/drivers/leds/trigger/Kconfig 2015-12-26 19:08:31.572626848 +0100 @@ -108,4 +108,11 @@ This enables direct flash/torch on/off by the driver, kernel space. If unsure, say Y. +config LEDS_TRIGGER_INPUT + tristate "LED Input Trigger" + depends on LEDS_TRIGGERS + help + This allows the GPIOs assigned to be LEDs to be initialised to inputs. + If unsure, say Y. + endif # LEDS_TRIGGERS diff -Nur '--exclude=.git' linux-stable/drivers/leds/trigger/ledtrig-input.c raspilinux/drivers/leds/trigger/ledtrig-input.c --- linux-stable/drivers/leds/trigger/ledtrig-input.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/leds/trigger/ledtrig-input.c 2015-12-26 19:08:31.572626848 +0100 @@ -0,0 +1,54 @@ +/* + * Set LED GPIO to Input "Trigger" + * + * Copyright 2015 Phil Elwell + * + * Based on Nick Forbes's ledtrig-default-on.c. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include "../leds.h" + +static void input_trig_activate(struct led_classdev *led_cdev) +{ + led_cdev->flags |= SET_GPIO_INPUT; + led_set_brightness_async(led_cdev, 0); +} + +static void input_trig_deactivate(struct led_classdev *led_cdev) +{ + led_cdev->flags |= SET_GPIO_OUTPUT; + led_set_brightness_async(led_cdev, 0); +} + +static struct led_trigger input_led_trigger = { + .name = "input", + .activate = input_trig_activate, + .deactivate = input_trig_deactivate, +}; + +static int __init input_trig_init(void) +{ + return led_trigger_register(&input_led_trigger); +} + +static void __exit input_trig_exit(void) +{ + led_trigger_unregister(&input_led_trigger); +} + +module_init(input_trig_init); +module_exit(input_trig_exit); + +MODULE_AUTHOR("Phil Elwell "); +MODULE_DESCRIPTION("Set LED GPIO to Input \"trigger\""); +MODULE_LICENSE("GPL"); diff -Nur '--exclude=.git' linux-stable/drivers/leds/trigger/Makefile raspilinux/drivers/leds/trigger/Makefile --- linux-stable/drivers/leds/trigger/Makefile 2015-12-26 20:38:45.362548671 +0100 +++ raspilinux/drivers/leds/trigger/Makefile 2015-12-26 19:08:31.572626848 +0100 @@ -8,3 +8,4 @@ obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o +obj-$(CONFIG_LEDS_TRIGGER_INPUT) += ledtrig-input.o diff -Nur '--exclude=.git' linux-stable/drivers/mailbox/bcm2835-mailbox.c raspilinux/drivers/mailbox/bcm2835-mailbox.c --- linux-stable/drivers/mailbox/bcm2835-mailbox.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/mailbox/bcm2835-mailbox.c 2015-12-26 19:08:31.576626475 +0100 @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2010,2015 Broadcom + * Copyright (C) 2013-2014 Lubomir Rintel + * Copyright (C) 2013 Craig McGeachie + * + * This program is free software; you can 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 device provides a mechanism for writing to the mailboxes, + * that are shared between the ARM and the VideoCore processor + * + * Parts of the driver are based on: + * - arch/arm/mach-bcm2708/vcio.c file written by Gray Girling that was + * obtained from branch "rpi-3.6.y" of git://github.com/raspberrypi/ + * linux.git + * - drivers/mailbox/bcm2835-ipc.c by Lubomir Rintel at + * https://github.com/hackerspace/rpi-linux/blob/lr-raspberry-pi/drivers/ + * mailbox/bcm2835-ipc.c + * - documentation available on the following web site: + * https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Mailboxes */ +#define ARM_0_MAIL0 0x00 +#define ARM_0_MAIL1 0x20 + +/* + * Mailbox registers. We basically only support mailbox 0 & 1. We + * deliver to the VC in mailbox 1, it delivers to us in mailbox 0. See + * BCM2835-ARM-Peripherals.pdf section 1.3 for an explanation about + * the placement of memory barriers. + */ +#define MAIL0_RD (ARM_0_MAIL0 + 0x00) +#define MAIL0_POL (ARM_0_MAIL0 + 0x10) +#define MAIL0_STA (ARM_0_MAIL0 + 0x18) +#define MAIL0_CNF (ARM_0_MAIL0 + 0x1C) +#define MAIL1_WRT (ARM_0_MAIL1 + 0x00) +#define MAIL1_STA (ARM_0_MAIL1 + 0x18) + +/* On ARCH_BCM270x these come through (arm_control.h ) */ +#ifndef ARM_MS_FULL +/* Status register: FIFO state. */ +#define ARM_MS_FULL BIT(31) +#define ARM_MS_EMPTY BIT(30) + +/* Configuration register: Enable interrupts. */ +#define ARM_MC_IHAVEDATAIRQEN BIT(0) +#endif + +struct bcm2835_mbox { + void __iomem *regs; + spinlock_t lock; + struct mbox_controller controller; +}; + +static struct bcm2835_mbox *bcm2835_link_mbox(struct mbox_chan *link) +{ + return container_of(link->mbox, struct bcm2835_mbox, controller); +} + +static irqreturn_t bcm2835_mbox_irq(int irq, void *dev_id) +{ + struct bcm2835_mbox *mbox = dev_id; + struct device *dev = mbox->controller.dev; + struct mbox_chan *link = &mbox->controller.chans[0]; + + while (!(readl(mbox->regs + MAIL0_STA) & ARM_MS_EMPTY)) { + u32 msg = readl(mbox->regs + MAIL0_RD); + dev_dbg(dev, "Reply 0x%08X\n", msg); + mbox_chan_received_data(link, &msg); + } + return IRQ_HANDLED; +} + +static int bcm2835_send_data(struct mbox_chan *link, void *data) +{ + struct bcm2835_mbox *mbox = bcm2835_link_mbox(link); + u32 msg = *(u32 *)data; + + spin_lock(&mbox->lock); + writel(msg, mbox->regs + MAIL1_WRT); + dev_dbg(mbox->controller.dev, "Request 0x%08X\n", msg); + spin_unlock(&mbox->lock); + return 0; +} + +static int bcm2835_startup(struct mbox_chan *link) +{ + struct bcm2835_mbox *mbox = bcm2835_link_mbox(link); + + /* Enable the interrupt on data reception */ + writel(ARM_MC_IHAVEDATAIRQEN, mbox->regs + MAIL0_CNF); + + return 0; +} + +static void bcm2835_shutdown(struct mbox_chan *link) +{ + struct bcm2835_mbox *mbox = bcm2835_link_mbox(link); + + writel(0, mbox->regs + MAIL0_CNF); +} + +static bool bcm2835_last_tx_done(struct mbox_chan *link) +{ + struct bcm2835_mbox *mbox = bcm2835_link_mbox(link); + bool ret; + + spin_lock(&mbox->lock); + ret = !(readl(mbox->regs + MAIL1_STA) & ARM_MS_FULL); + spin_unlock(&mbox->lock); + return ret; +} + +static const struct mbox_chan_ops bcm2835_mbox_chan_ops = { + .send_data = bcm2835_send_data, + .startup = bcm2835_startup, + .shutdown = bcm2835_shutdown, + .last_tx_done = bcm2835_last_tx_done +}; + +static struct mbox_chan *bcm2835_mbox_index_xlate(struct mbox_controller *mbox, + const struct of_phandle_args *sp) +{ + if (sp->args_count != 0) + return NULL; + + return &mbox->chans[0]; +} + +static int bcm2835_mbox_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int ret = 0; + struct resource *iomem; + struct bcm2835_mbox *mbox; + + mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL); + if (mbox == NULL) + return -ENOMEM; + spin_lock_init(&mbox->lock); + + ret = devm_request_irq(dev, platform_get_irq(pdev, 0), + bcm2835_mbox_irq, 0, dev_name(dev), mbox); + if (ret) { + dev_err(dev, "Failed to register a mailbox IRQ handler: %d\n", + ret); + return -ENODEV; + } + + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mbox->regs = devm_ioremap_resource(&pdev->dev, iomem); + if (IS_ERR(mbox->regs)) { + ret = PTR_ERR(mbox->regs); + dev_err(&pdev->dev, "Failed to remap mailbox regs: %d\n", ret); + return ret; + } + + mbox->controller.txdone_poll = true; + mbox->controller.txpoll_period = 5; + mbox->controller.ops = &bcm2835_mbox_chan_ops; + mbox->controller.of_xlate = &bcm2835_mbox_index_xlate; + mbox->controller.dev = dev; + mbox->controller.num_chans = 1; + mbox->controller.chans = devm_kzalloc(dev, + sizeof(*mbox->controller.chans), GFP_KERNEL); + if (!mbox->controller.chans) + return -ENOMEM; + + ret = mbox_controller_register(&mbox->controller); + if (ret) + return ret; + + platform_set_drvdata(pdev, mbox); + dev_info(dev, "mailbox enabled\n"); + + return ret; +} + +static int bcm2835_mbox_remove(struct platform_device *pdev) +{ + struct bcm2835_mbox *mbox = platform_get_drvdata(pdev); + mbox_controller_unregister(&mbox->controller); + return 0; +} + +static const struct of_device_id bcm2835_mbox_of_match[] = { + { .compatible = "brcm,bcm2835-mbox", }, + {}, +}; +MODULE_DEVICE_TABLE(of, bcm2835_mbox_of_match); + +static struct platform_driver bcm2835_mbox_driver = { + .driver = { + .name = "bcm2835-mbox", + .owner = THIS_MODULE, + .of_match_table = bcm2835_mbox_of_match, + }, + .probe = bcm2835_mbox_probe, + .remove = bcm2835_mbox_remove, +}; + +static int __init bcm2835_mbox_init(void) +{ + return platform_driver_register(&bcm2835_mbox_driver); +} +arch_initcall(bcm2835_mbox_init); + +static void __init bcm2835_mbox_exit(void) +{ + platform_driver_unregister(&bcm2835_mbox_driver); +} +module_exit(bcm2835_mbox_exit); + +MODULE_AUTHOR("Lubomir Rintel "); +MODULE_DESCRIPTION("BCM2835 mailbox IPC driver"); +MODULE_LICENSE("GPL v2"); diff -Nur '--exclude=.git' linux-stable/drivers/mailbox/Kconfig raspilinux/drivers/mailbox/Kconfig --- linux-stable/drivers/mailbox/Kconfig 2015-12-26 20:45:00.835943462 +0100 +++ raspilinux/drivers/mailbox/Kconfig 2015-12-26 19:08:31.576626475 +0100 @@ -60,4 +60,13 @@ An implementation of the Altera Mailbox soft core. It is used to send message between processors. Say Y here if you want to use the Altera mailbox support. + +config BCM2835_MBOX + tristate "BCM2835 Mailbox" + depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 + help + An implementation of the BCM2385 Mailbox. It is used to invoke + the services of the Videocore. Say Y here if you want to use the + BCM2835 Mailbox. + endif diff -Nur '--exclude=.git' linux-stable/drivers/mailbox/mailbox.c raspilinux/drivers/mailbox/mailbox.c --- linux-stable/drivers/mailbox/mailbox.c 2015-12-26 20:45:00.835943462 +0100 +++ raspilinux/drivers/mailbox/mailbox.c 2015-12-26 19:08:31.576626475 +0100 @@ -304,13 +304,23 @@ unsigned long flags; int ret; - if (!dev || !dev->of_node) { + if (!dev) { pr_debug("%s: No owner device node\n", __func__); return ERR_PTR(-ENODEV); } mutex_lock(&con_mutex); + if (!dev->of_node) { + chan = NULL; + /* pick the first controller in the list */ + list_for_each_entry(mbox, &mbox_cons, node) { + chan = &mbox->chans[0]; + break; + } + goto skip_dt; + } + if (of_parse_phandle_with_args(dev->of_node, "mboxes", "#mbox-cells", index, &spec)) { dev_dbg(dev, "%s: can't parse \"mboxes\" property\n", __func__); @@ -327,6 +337,7 @@ of_node_put(spec.np); +skip_dt: if (!chan || chan->cl || !try_module_get(mbox->dev->driver->owner)) { dev_dbg(dev, "%s: mailbox not free\n", __func__); mutex_unlock(&con_mutex); diff -Nur '--exclude=.git' linux-stable/drivers/mailbox/Makefile raspilinux/drivers/mailbox/Makefile --- linux-stable/drivers/mailbox/Makefile 2015-12-26 20:45:00.835943462 +0100 +++ raspilinux/drivers/mailbox/Makefile 2015-12-26 19:08:31.576626475 +0100 @@ -11,3 +11,5 @@ obj-$(CONFIG_PCC) += pcc.o obj-$(CONFIG_ALTERA_MBOX) += mailbox-altera.o + +obj-$(CONFIG_BCM2835_MBOX) += bcm2835-mailbox.o diff -Nur '--exclude=.git' linux-stable/drivers/media/platform/bcm2835/bcm2835-camera.c raspilinux/drivers/media/platform/bcm2835/bcm2835-camera.c --- linux-stable/drivers/media/platform/bcm2835/bcm2835-camera.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/media/platform/bcm2835/bcm2835-camera.c 2015-12-26 19:08:31.672617523 +0100 @@ -0,0 +1,1843 @@ +/* + * Broadcom BM2835 V4L2 driver + * + * Copyright © 2013 Raspberry Pi (Trading) Ltd. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Authors: Vincent Sanders + * Dave Stevenson + * Simon Mellor + * Luke Diamand + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mmal-common.h" +#include "mmal-encodings.h" +#include "mmal-vchiq.h" +#include "mmal-msg.h" +#include "mmal-parameters.h" +#include "bcm2835-camera.h" + +#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) + +#define MAX_VIDEO_MODE_WIDTH 1280 +#define MAX_VIDEO_MODE_HEIGHT 720 + +MODULE_DESCRIPTION("Broadcom 2835 MMAL video capture"); +MODULE_AUTHOR("Vincent Sanders"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(BM2835_MMAL_VERSION); + +int bcm2835_v4l2_debug; +module_param_named(debug, bcm2835_v4l2_debug, int, 0644); +MODULE_PARM_DESC(bcm2835_v4l2_debug, "Debug level 0-2"); + +int max_video_width = MAX_VIDEO_MODE_WIDTH; +int max_video_height = MAX_VIDEO_MODE_HEIGHT; +module_param(max_video_width, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(max_video_width, "Threshold for video mode"); +module_param(max_video_height, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(max_video_height, "Threshold for video mode"); + +/* Gstreamer bug https://bugzilla.gnome.org/show_bug.cgi?id=726521 + * v4l2src does bad (and actually wrong) things when the vidioc_enum_framesizes + * function says type V4L2_FRMSIZE_TYPE_STEPWISE, which we do by default. + * It's happier if we just don't say anything at all, when it then + * sets up a load of defaults that it thinks might work. + * If gst_v4l2src_is_broken is non-zero, then we remove the function from + * our function table list (actually switch to an alternate set, but same + * result). + */ +int gst_v4l2src_is_broken = 0; +module_param(gst_v4l2src_is_broken, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(gst_v4l2src_is_broken, "If non-zero, enable workaround for Gstreamer"); + +static struct bm2835_mmal_dev *gdev; /* global device data */ + +#define FPS_MIN 1 +#define FPS_MAX 90 + +/* timeperframe: min/max and default */ +static const struct v4l2_fract + tpf_min = {.numerator = 1, .denominator = FPS_MAX}, + tpf_max = {.numerator = 1, .denominator = FPS_MIN}, + tpf_default = {.numerator = 1000, .denominator = 30000}; + +/* video formats */ +static struct mmal_fmt formats[] = { + { + .name = "4:2:0, planar, YUV", + .fourcc = V4L2_PIX_FMT_YUV420, + .flags = 0, + .mmal = MMAL_ENCODING_I420, + .depth = 12, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 1, + }, + { + .name = "4:2:2, packed, YUYV", + .fourcc = V4L2_PIX_FMT_YUYV, + .flags = 0, + .mmal = MMAL_ENCODING_YUYV, + .depth = 16, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 2, + }, + { + .name = "RGB24 (LE)", + .fourcc = V4L2_PIX_FMT_RGB24, + .flags = 0, + .mmal = MMAL_ENCODING_BGR24, + .depth = 24, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 3, + }, + { + .name = "JPEG", + .fourcc = V4L2_PIX_FMT_JPEG, + .flags = V4L2_FMT_FLAG_COMPRESSED, + .mmal = MMAL_ENCODING_JPEG, + .depth = 8, + .mmal_component = MMAL_COMPONENT_IMAGE_ENCODE, + .ybbp = 0, + }, + { + .name = "H264", + .fourcc = V4L2_PIX_FMT_H264, + .flags = V4L2_FMT_FLAG_COMPRESSED, + .mmal = MMAL_ENCODING_H264, + .depth = 8, + .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE, + .ybbp = 0, + }, + { + .name = "MJPEG", + .fourcc = V4L2_PIX_FMT_MJPEG, + .flags = V4L2_FMT_FLAG_COMPRESSED, + .mmal = MMAL_ENCODING_MJPEG, + .depth = 8, + .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE, + .ybbp = 0, + }, + { + .name = "4:2:2, packed, YVYU", + .fourcc = V4L2_PIX_FMT_YVYU, + .flags = 0, + .mmal = MMAL_ENCODING_YVYU, + .depth = 16, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 2, + }, + { + .name = "4:2:2, packed, VYUY", + .fourcc = V4L2_PIX_FMT_VYUY, + .flags = 0, + .mmal = MMAL_ENCODING_VYUY, + .depth = 16, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 2, + }, + { + .name = "4:2:2, packed, UYVY", + .fourcc = V4L2_PIX_FMT_UYVY, + .flags = 0, + .mmal = MMAL_ENCODING_UYVY, + .depth = 16, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 2, + }, + { + .name = "4:2:0, planar, NV12", + .fourcc = V4L2_PIX_FMT_NV12, + .flags = 0, + .mmal = MMAL_ENCODING_NV12, + .depth = 12, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 1, + }, + { + .name = "RGB24 (BE)", + .fourcc = V4L2_PIX_FMT_BGR24, + .flags = 0, + .mmal = MMAL_ENCODING_RGB24, + .depth = 24, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 3, + }, + { + .name = "4:2:0, planar, YVU", + .fourcc = V4L2_PIX_FMT_YVU420, + .flags = 0, + .mmal = MMAL_ENCODING_YV12, + .depth = 12, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 1, + }, + { + .name = "4:2:0, planar, NV21", + .fourcc = V4L2_PIX_FMT_NV21, + .flags = 0, + .mmal = MMAL_ENCODING_NV21, + .depth = 12, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 1, + }, + { + .name = "RGB32 (BE)", + .fourcc = V4L2_PIX_FMT_BGR32, + .flags = 0, + .mmal = MMAL_ENCODING_BGRA, + .depth = 32, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 4, + }, +}; + +static struct mmal_fmt *get_format(struct v4l2_format *f) +{ + struct mmal_fmt *fmt; + unsigned int k; + + for (k = 0; k < ARRAY_SIZE(formats); k++) { + fmt = &formats[k]; + if (fmt->fourcc == f->fmt.pix.pixelformat) + break; + } + + if (k == ARRAY_SIZE(formats)) + return NULL; + + return &formats[k]; +} + +/* ------------------------------------------------------------------ + Videobuf queue operations + ------------------------------------------------------------------*/ + +static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); + unsigned long size; + + /* refuse queue setup if port is not configured */ + if (dev->capture.port == NULL) { + v4l2_err(&dev->v4l2_dev, + "%s: capture port not configured\n", __func__); + return -EINVAL; + } + + size = dev->capture.port->current_buffer.size; + if (size == 0) { + v4l2_err(&dev->v4l2_dev, + "%s: capture port buffer size is zero\n", __func__); + return -EINVAL; + } + + if (*nbuffers < (dev->capture.port->current_buffer.num + 2)) + *nbuffers = (dev->capture.port->current_buffer.num + 2); + + *nplanes = 1; + + sizes[0] = size; + + /* + * videobuf2-vmalloc allocator is context-less so no need to set + * alloc_ctxs array. + */ + + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n", + __func__, dev); + + return 0; +} + +static int buffer_prepare(struct vb2_buffer *vb) +{ + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue); + unsigned long size; + + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n", + __func__, dev); + + BUG_ON(dev->capture.port == NULL); + BUG_ON(dev->capture.fmt == NULL); + + size = dev->capture.stride * dev->capture.height; + if (vb2_plane_size(vb, 0) < size) { + v4l2_err(&dev->v4l2_dev, + "%s data will not fit into plane (%lu < %lu)\n", + __func__, vb2_plane_size(vb, 0), size); + return -EINVAL; + } + + return 0; +} + +static inline bool is_capturing(struct bm2835_mmal_dev *dev) +{ + return dev->capture.camera_port == + &dev-> + component[MMAL_COMPONENT_CAMERA]->output[MMAL_CAMERA_PORT_CAPTURE]; +} + +static void buffer_cb(struct vchiq_mmal_instance *instance, + struct vchiq_mmal_port *port, + int status, + struct mmal_buffer *buf, + unsigned long length, u32 mmal_flags, s64 dts, s64 pts) +{ + struct bm2835_mmal_dev *dev = port->cb_ctx; + + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n", + __func__, status, buf, length, mmal_flags, pts); + + if (status != 0) { + /* error in transfer */ + if (buf != NULL) { + /* there was a buffer with the error so return it */ + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + } + return; + } else if (length == 0) { + /* stream ended */ + if (buf != NULL) { + /* this should only ever happen if the port is + * disabled and there are buffers still queued + */ + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + pr_debug("Empty buffer"); + } else if (dev->capture.frame_count) { + /* grab another frame */ + if (is_capturing(dev)) { + pr_debug("Grab another frame"); + vchiq_mmal_port_parameter_set( + instance, + dev->capture. + camera_port, + MMAL_PARAMETER_CAPTURE, + &dev->capture. + frame_count, + sizeof(dev->capture.frame_count)); + } + } else { + /* signal frame completion */ + complete(&dev->capture.frame_cmplt); + } + } else { + if (dev->capture.frame_count) { + if (dev->capture.vc_start_timestamp != -1 && + pts != 0) { + s64 runtime_us = pts - + dev->capture.vc_start_timestamp; + u32 div = 0; + u32 rem = 0; + + div = + div_u64_rem(runtime_us, USEC_PER_SEC, &rem); + buf->vb.v4l2_buf.timestamp.tv_sec = + dev->capture.kernel_start_ts.tv_sec - 1 + + div; + buf->vb.v4l2_buf.timestamp.tv_usec = + dev->capture.kernel_start_ts.tv_usec + rem; + + if (buf->vb.v4l2_buf.timestamp.tv_usec >= + USEC_PER_SEC) { + buf->vb.v4l2_buf.timestamp.tv_sec++; + buf->vb.v4l2_buf.timestamp.tv_usec -= + USEC_PER_SEC; + } + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "Convert start time %d.%06d and %llu " + "with offset %llu to %d.%06d\n", + (int)dev->capture.kernel_start_ts. + tv_sec, + (int)dev->capture.kernel_start_ts. + tv_usec, + dev->capture.vc_start_timestamp, pts, + (int)buf->vb.v4l2_buf.timestamp.tv_sec, + (int)buf->vb.v4l2_buf.timestamp. + tv_usec); + } else { + v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); + } + + vb2_set_plane_payload(&buf->vb, 0, length); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + + if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS && + is_capturing(dev)) { + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "Grab another frame as buffer has EOS"); + vchiq_mmal_port_parameter_set( + instance, + dev->capture. + camera_port, + MMAL_PARAMETER_CAPTURE, + &dev->capture. + frame_count, + sizeof(dev->capture.frame_count)); + } + } else { + /* signal frame completion */ + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + complete(&dev->capture.frame_cmplt); + } + } +} + +static int enable_camera(struct bm2835_mmal_dev *dev) +{ + int ret; + if (!dev->camera_use_count) { + ret = vchiq_mmal_component_enable( + dev->instance, + dev->component[MMAL_COMPONENT_CAMERA]); + if (ret < 0) { + v4l2_err(&dev->v4l2_dev, + "Failed enabling camera, ret %d\n", ret); + return -EINVAL; + } + } + dev->camera_use_count++; + v4l2_dbg(1, bcm2835_v4l2_debug, + &dev->v4l2_dev, "enabled camera (refcount %d)\n", + dev->camera_use_count); + return 0; +} + +static int disable_camera(struct bm2835_mmal_dev *dev) +{ + int ret; + if (!dev->camera_use_count) { + v4l2_err(&dev->v4l2_dev, + "Disabled the camera when already disabled\n"); + return -EINVAL; + } + dev->camera_use_count--; + if (!dev->camera_use_count) { + unsigned int i = 0xFFFFFFFF; + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "Disabling camera\n"); + ret = + vchiq_mmal_component_disable( + dev->instance, + dev->component[MMAL_COMPONENT_CAMERA]); + if (ret < 0) { + v4l2_err(&dev->v4l2_dev, + "Failed disabling camera, ret %d\n", ret); + return -EINVAL; + } + vchiq_mmal_port_parameter_set( + dev->instance, + &dev->component[MMAL_COMPONENT_CAMERA]->control, + MMAL_PARAMETER_CAMERA_NUM, &i, + sizeof(i)); + } + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "Camera refcount now %d\n", dev->camera_use_count); + return 0; +} + +static void buffer_queue(struct vb2_buffer *vb) +{ + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue); + struct mmal_buffer *buf = container_of(vb, struct mmal_buffer, vb); + int ret; + + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "%s: dev:%p buf:%p\n", __func__, dev, buf); + + buf->buffer = vb2_plane_vaddr(&buf->vb, 0); + buf->buffer_size = vb2_plane_size(&buf->vb, 0); + + ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, buf); + if (ret < 0) + v4l2_err(&dev->v4l2_dev, "%s: error submitting buffer\n", + __func__); +} + +static int start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); + int ret; + int parameter_size; + + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n", + __func__, dev); + + /* ensure a format has actually been set */ + if (dev->capture.port == NULL) + return -EINVAL; + + if (enable_camera(dev) < 0) { + v4l2_err(&dev->v4l2_dev, "Failed to enable camera\n"); + return -EINVAL; + } + + /*init_completion(&dev->capture.frame_cmplt); */ + + /* enable frame capture */ + dev->capture.frame_count = 1; + + /* if the preview is not already running, wait for a few frames for AGC + * to settle down. + */ + if (!dev->component[MMAL_COMPONENT_PREVIEW]->enabled) + msleep(300); + + /* enable the connection from camera to encoder (if applicable) */ + if (dev->capture.camera_port != dev->capture.port + && dev->capture.camera_port) { + ret = vchiq_mmal_port_enable(dev->instance, + dev->capture.camera_port, NULL); + if (ret) { + v4l2_err(&dev->v4l2_dev, + "Failed to enable encode tunnel - error %d\n", + ret); + return -1; + } + } + + /* Get VC timestamp at this point in time */ + parameter_size = sizeof(dev->capture.vc_start_timestamp); + if (vchiq_mmal_port_parameter_get(dev->instance, + dev->capture.camera_port, + MMAL_PARAMETER_SYSTEM_TIME, + &dev->capture.vc_start_timestamp, + ¶meter_size)) { + v4l2_err(&dev->v4l2_dev, + "Failed to get VC start time - update your VC f/w\n"); + + /* Flag to indicate just to rely on kernel timestamps */ + dev->capture.vc_start_timestamp = -1; + } else + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "Start time %lld size %d\n", + dev->capture.vc_start_timestamp, parameter_size); + + v4l2_get_timestamp(&dev->capture.kernel_start_ts); + + /* enable the camera port */ + dev->capture.port->cb_ctx = dev; + ret = + vchiq_mmal_port_enable(dev->instance, dev->capture.port, buffer_cb); + if (ret) { + v4l2_err(&dev->v4l2_dev, + "Failed to enable capture port - error %d. " + "Disabling camera port again\n", ret); + + vchiq_mmal_port_disable(dev->instance, + dev->capture.camera_port); + if (disable_camera(dev) < 0) { + v4l2_err(&dev->v4l2_dev, "Failed to disable camera\n"); + return -EINVAL; + } + return -1; + } + + /* capture the first frame */ + vchiq_mmal_port_parameter_set(dev->instance, + dev->capture.camera_port, + MMAL_PARAMETER_CAPTURE, + &dev->capture.frame_count, + sizeof(dev->capture.frame_count)); + return 0; +} + +/* abort streaming and wait for last buffer */ +static void stop_streaming(struct vb2_queue *vq) +{ + int ret; + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); + + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n", + __func__, dev); + + init_completion(&dev->capture.frame_cmplt); + dev->capture.frame_count = 0; + + /* ensure a format has actually been set */ + if (dev->capture.port == NULL) { + v4l2_err(&dev->v4l2_dev, + "no capture port - stream not started?\n"); + return; + } + + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "stopping capturing\n"); + + /* stop capturing frames */ + vchiq_mmal_port_parameter_set(dev->instance, + dev->capture.camera_port, + MMAL_PARAMETER_CAPTURE, + &dev->capture.frame_count, + sizeof(dev->capture.frame_count)); + + /* wait for last frame to complete */ + ret = wait_for_completion_timeout(&dev->capture.frame_cmplt, HZ); + if (ret <= 0) + v4l2_err(&dev->v4l2_dev, + "error %d waiting for frame completion\n", ret); + + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "disabling connection\n"); + + /* disable the connection from camera to encoder */ + ret = vchiq_mmal_port_disable(dev->instance, dev->capture.camera_port); + if (!ret && dev->capture.camera_port != dev->capture.port) { + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "disabling port\n"); + ret = vchiq_mmal_port_disable(dev->instance, dev->capture.port); + } else if (dev->capture.camera_port != dev->capture.port) { + v4l2_err(&dev->v4l2_dev, "port_disable failed, error %d\n", + ret); + } + + if (disable_camera(dev) < 0) + v4l2_err(&dev->v4l2_dev, "Failed to disable camera\n"); +} + +static void bm2835_mmal_lock(struct vb2_queue *vq) +{ + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); + mutex_lock(&dev->mutex); +} + +static void bm2835_mmal_unlock(struct vb2_queue *vq) +{ + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); + mutex_unlock(&dev->mutex); +} + +static struct vb2_ops bm2835_mmal_video_qops = { + .queue_setup = queue_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .start_streaming = start_streaming, + .stop_streaming = stop_streaming, + .wait_prepare = bm2835_mmal_unlock, + .wait_finish = bm2835_mmal_lock, +}; + +/* ------------------------------------------------------------------ + IOCTL operations + ------------------------------------------------------------------*/ + +/* overlay ioctl */ +static int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct mmal_fmt *fmt; + + if (f->index >= ARRAY_SIZE(formats)) + return -EINVAL; + + fmt = &formats[f->index]; + + strlcpy(f->description, fmt->name, sizeof(f->description)); + f->pixelformat = fmt->fourcc; + f->flags = fmt->flags; + + return 0; +} + +static int vidioc_g_fmt_vid_overlay(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct bm2835_mmal_dev *dev = video_drvdata(file); + + f->fmt.win = dev->overlay; + + return 0; +} + +static int vidioc_try_fmt_vid_overlay(struct file *file, void *priv, + struct v4l2_format *f) +{ + /* Only support one format so get the current one. */ + vidioc_g_fmt_vid_overlay(file, priv, f); + + /* todo: allow the size and/or offset to be changed. */ + return 0; +} + +static int vidioc_s_fmt_vid_overlay(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct bm2835_mmal_dev *dev = video_drvdata(file); + + vidioc_try_fmt_vid_overlay(file, priv, f); + + dev->overlay = f->fmt.win; + + /* todo: program the preview port parameters */ + return 0; +} + +static int vidioc_overlay(struct file *file, void *f, unsigned int on) +{ + int ret; + struct bm2835_mmal_dev *dev = video_drvdata(file); + struct vchiq_mmal_port *src; + struct vchiq_mmal_port *dst; + struct mmal_parameter_displayregion prev_config = { + .set = MMAL_DISPLAY_SET_LAYER | MMAL_DISPLAY_SET_ALPHA | + MMAL_DISPLAY_SET_DEST_RECT | MMAL_DISPLAY_SET_FULLSCREEN, + .layer = PREVIEW_LAYER, + .alpha = 255, + .fullscreen = 0, + .dest_rect = { + .x = dev->overlay.w.left, + .y = dev->overlay.w.top, + .width = dev->overlay.w.width, + .height = dev->overlay.w.height, + }, + }; + + if ((on && dev->component[MMAL_COMPONENT_PREVIEW]->enabled) || + (!on && !dev->component[MMAL_COMPONENT_PREVIEW]->enabled)) + return 0; /* already in requested state */ + + src = + &dev->component[MMAL_COMPONENT_CAMERA]-> + output[MMAL_CAMERA_PORT_PREVIEW]; + + if (!on) { + /* disconnect preview ports and disable component */ + ret = vchiq_mmal_port_disable(dev->instance, src); + if (!ret) + ret = + vchiq_mmal_port_connect_tunnel(dev->instance, src, + NULL); + if (ret >= 0) + ret = vchiq_mmal_component_disable( + dev->instance, + dev->component[MMAL_COMPONENT_PREVIEW]); + + disable_camera(dev); + return ret; + } + + /* set preview port format and connect it to output */ + dst = &dev->component[MMAL_COMPONENT_PREVIEW]->input[0]; + + ret = vchiq_mmal_port_set_format(dev->instance, src); + if (ret < 0) + goto error; + + ret = vchiq_mmal_port_parameter_set(dev->instance, dst, + MMAL_PARAMETER_DISPLAYREGION, + &prev_config, sizeof(prev_config)); + if (ret < 0) + goto error; + + if (enable_camera(dev) < 0) + goto error; + + ret = vchiq_mmal_component_enable( + dev->instance, + dev->component[MMAL_COMPONENT_PREVIEW]); + if (ret < 0) + goto error; + + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "connecting %p to %p\n", + src, dst); + ret = vchiq_mmal_port_connect_tunnel(dev->instance, src, dst); + if (!ret) + ret = vchiq_mmal_port_enable(dev->instance, src, NULL); +error: + return ret; +} + +static int vidioc_g_fbuf(struct file *file, void *fh, + struct v4l2_framebuffer *a) +{ + /* The video overlay must stay within the framebuffer and can't be + positioned independently. */ + struct bm2835_mmal_dev *dev = video_drvdata(file); + struct vchiq_mmal_port *preview_port = + &dev->component[MMAL_COMPONENT_CAMERA]-> + output[MMAL_CAMERA_PORT_PREVIEW]; + a->flags = V4L2_FBUF_FLAG_OVERLAY; + a->fmt.width = preview_port->es.video.width; + a->fmt.height = preview_port->es.video.height; + a->fmt.pixelformat = V4L2_PIX_FMT_YUV420; + a->fmt.bytesperline = preview_port->es.video.width; + a->fmt.sizeimage = (preview_port->es.video.width * + preview_port->es.video.height * 3)>>1; + a->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M; + + return 0; +} + +/* input ioctls */ +static int vidioc_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + /* only a single camera input */ + if (inp->index != 0) + return -EINVAL; + + inp->type = V4L2_INPUT_TYPE_CAMERA; + sprintf(inp->name, "Camera %u", inp->index); + return 0; +} + +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) +{ + *i = 0; + return 0; +} + +static int vidioc_s_input(struct file *file, void *priv, unsigned int i) +{ + if (i != 0) + return -EINVAL; + + return 0; +} + +/* capture ioctls */ +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct bm2835_mmal_dev *dev = video_drvdata(file); + u32 major; + u32 minor; + + vchiq_mmal_version(dev->instance, &major, &minor); + + strcpy(cap->driver, "bm2835 mmal"); + snprintf(cap->card, sizeof(cap->card), "mmal service %d.%d", + major, minor); + + snprintf(cap->bus_info, sizeof(cap->bus_info), + "platform:%s", dev->v4l2_dev.name); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | + V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + + return 0; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct mmal_fmt *fmt; + + if (f->index >= ARRAY_SIZE(formats)) + return -EINVAL; + + fmt = &formats[f->index]; + + strlcpy(f->description, fmt->name, sizeof(f->description)); + f->pixelformat = fmt->fourcc; + f->flags = fmt->flags; + + return 0; +} + +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct bm2835_mmal_dev *dev = video_drvdata(file); + + f->fmt.pix.width = dev->capture.width; + f->fmt.pix.height = dev->capture.height; + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.pixelformat = dev->capture.fmt->fourcc; + f->fmt.pix.bytesperline = dev->capture.stride; + f->fmt.pix.sizeimage = dev->capture.buffersize; + + if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_RGB24) + f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; + else if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_JPEG) + f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; + else + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + f->fmt.pix.priv = 0; + + v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix, + __func__); + return 0; +} + +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct bm2835_mmal_dev *dev = video_drvdata(file); + struct mmal_fmt *mfmt; + + mfmt = get_format(f); + if (!mfmt) { + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "Fourcc format (0x%08x) unknown.\n", + f->fmt.pix.pixelformat); + f->fmt.pix.pixelformat = formats[0].fourcc; + mfmt = get_format(f); + } + + f->fmt.pix.field = V4L2_FIELD_NONE; + + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "Clipping/aligning %dx%d format %08X\n", + f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.pixelformat); + + v4l_bound_align_image(&f->fmt.pix.width, MIN_WIDTH, MAX_WIDTH, 1, + &f->fmt.pix.height, MIN_HEIGHT, MAX_HEIGHT, 1, 0); + f->fmt.pix.bytesperline = f->fmt.pix.width * mfmt->ybbp; + + /* Image buffer has to be padded to allow for alignment, even though + * we then remove that padding before delivering the buffer. + */ + f->fmt.pix.sizeimage = ((f->fmt.pix.height+15)&~15) * + (((f->fmt.pix.width+31)&~31) * mfmt->depth) >> 3; + + if ((mfmt->flags & V4L2_FMT_FLAG_COMPRESSED) && + f->fmt.pix.sizeimage < MIN_BUFFER_SIZE) + f->fmt.pix.sizeimage = MIN_BUFFER_SIZE; + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) + f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG) + f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; + else + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + f->fmt.pix.priv = 0; + + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "Now %dx%d format %08X\n", + f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.pixelformat); + + v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix, + __func__); + return 0; +} + +static int mmal_setup_components(struct bm2835_mmal_dev *dev, + struct v4l2_format *f) +{ + int ret; + struct vchiq_mmal_port *port = NULL, *camera_port = NULL; + struct vchiq_mmal_component *encode_component = NULL; + struct mmal_fmt *mfmt = get_format(f); + + BUG_ON(!mfmt); + + if (dev->capture.encode_component) { + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "vid_cap - disconnect previous tunnel\n"); + + /* Disconnect any previous connection */ + vchiq_mmal_port_connect_tunnel(dev->instance, + dev->capture.camera_port, NULL); + dev->capture.camera_port = NULL; + ret = vchiq_mmal_component_disable(dev->instance, + dev->capture. + encode_component); + if (ret) + v4l2_err(&dev->v4l2_dev, + "Failed to disable encode component %d\n", + ret); + + dev->capture.encode_component = NULL; + } + /* format dependant port setup */ + switch (mfmt->mmal_component) { + case MMAL_COMPONENT_CAMERA: + /* Make a further decision on port based on resolution */ + if (f->fmt.pix.width <= max_video_width + && f->fmt.pix.height <= max_video_height) + camera_port = port = + &dev->component[MMAL_COMPONENT_CAMERA]-> + output[MMAL_CAMERA_PORT_VIDEO]; + else + camera_port = port = + &dev->component[MMAL_COMPONENT_CAMERA]-> + output[MMAL_CAMERA_PORT_CAPTURE]; + break; + case MMAL_COMPONENT_IMAGE_ENCODE: + encode_component = dev->component[MMAL_COMPONENT_IMAGE_ENCODE]; + port = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0]; + camera_port = + &dev->component[MMAL_COMPONENT_CAMERA]-> + output[MMAL_CAMERA_PORT_CAPTURE]; + break; + case MMAL_COMPONENT_VIDEO_ENCODE: + encode_component = dev->component[MMAL_COMPONENT_VIDEO_ENCODE]; + port = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0]; + camera_port = + &dev->component[MMAL_COMPONENT_CAMERA]-> + output[MMAL_CAMERA_PORT_VIDEO]; + break; + default: + break; + } + + if (!port) + return -EINVAL; + + if (encode_component) + camera_port->format.encoding = MMAL_ENCODING_OPAQUE; + else + camera_port->format.encoding = mfmt->mmal; + + camera_port->format.encoding_variant = 0; + camera_port->es.video.width = f->fmt.pix.width; + camera_port->es.video.height = f->fmt.pix.height; + camera_port->es.video.crop.x = 0; + 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 = 0; + camera_port->es.video.frame_rate.den = 1; + camera_port->es.video.color_space = MMAL_COLOR_SPACE_JPEG_JFIF; + + ret = vchiq_mmal_port_set_format(dev->instance, camera_port); + + if (!ret + && camera_port == + &dev->component[MMAL_COMPONENT_CAMERA]-> + output[MMAL_CAMERA_PORT_VIDEO]) { + bool overlay_enabled = + !!dev->component[MMAL_COMPONENT_PREVIEW]->enabled; + struct vchiq_mmal_port *preview_port = + &dev->component[MMAL_COMPONENT_CAMERA]-> + output[MMAL_CAMERA_PORT_PREVIEW]; + /* Preview and encode ports need to match on resolution */ + if (overlay_enabled) { + /* Need to disable the overlay before we can update + * the resolution + */ + ret = + vchiq_mmal_port_disable(dev->instance, + preview_port); + if (!ret) + ret = + vchiq_mmal_port_connect_tunnel( + dev->instance, + preview_port, + NULL); + } + preview_port->es.video.width = f->fmt.pix.width; + preview_port->es.video.height = f->fmt.pix.height; + preview_port->es.video.crop.x = 0; + 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 = + 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( + dev->instance, + preview_port, + &dev->component[MMAL_COMPONENT_PREVIEW]->input[0]); + if (!ret) + ret = vchiq_mmal_port_enable(dev->instance, + preview_port, + NULL); + } + } + + if (ret) { + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "%s failed to set format %dx%d %08X\n", __func__, + f->fmt.pix.width, f->fmt.pix.height, + f->fmt.pix.pixelformat); + /* ensure capture is not going to be tried */ + dev->capture.port = NULL; + } else { + if (encode_component) { + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "vid_cap - set up encode comp\n"); + + /* configure buffering */ + camera_port->current_buffer.size = + camera_port->recommended_buffer.size; + camera_port->current_buffer.num = + camera_port->recommended_buffer.num; + + ret = + vchiq_mmal_port_connect_tunnel( + dev->instance, + camera_port, + &encode_component->input[0]); + if (ret) { + v4l2_dbg(1, bcm2835_v4l2_debug, + &dev->v4l2_dev, + "%s failed to create connection\n", + __func__); + /* ensure capture is not going to be tried */ + dev->capture.port = NULL; + } else { + port->es.video.width = f->fmt.pix.width; + port->es.video.height = f->fmt.pix.height; + port->es.video.crop.x = 0; + port->es.video.crop.y = 0; + port->es.video.crop.width = f->fmt.pix.width; + port->es.video.crop.height = f->fmt.pix.height; + port->es.video.frame_rate.num = + dev->capture.timeperframe.denominator; + port->es.video.frame_rate.den = + dev->capture.timeperframe.numerator; + + port->format.encoding = mfmt->mmal; + port->format.encoding_variant = 0; + /* Set any encoding specific parameters */ + switch (mfmt->mmal_component) { + case MMAL_COMPONENT_VIDEO_ENCODE: + port->format.bitrate = + dev->capture.encode_bitrate; + break; + case MMAL_COMPONENT_IMAGE_ENCODE: + /* Could set EXIF parameters here */ + break; + default: + break; + } + ret = vchiq_mmal_port_set_format(dev->instance, + port); + if (ret) + v4l2_dbg(1, bcm2835_v4l2_debug, + &dev->v4l2_dev, + "%s failed to set format %dx%d fmt %08X\n", + __func__, + f->fmt.pix.width, + f->fmt.pix.height, + f->fmt.pix.pixelformat + ); + } + + if (!ret) { + ret = vchiq_mmal_component_enable( + dev->instance, + encode_component); + if (ret) { + v4l2_dbg(1, bcm2835_v4l2_debug, + &dev->v4l2_dev, + "%s Failed to enable encode components\n", + __func__); + } + } + if (!ret) { + /* configure buffering */ + port->current_buffer.num = 1; + port->current_buffer.size = + f->fmt.pix.sizeimage; + if (port->format.encoding == + MMAL_ENCODING_JPEG) { + v4l2_dbg(1, bcm2835_v4l2_debug, + &dev->v4l2_dev, + "JPG - buf size now %d was %d\n", + f->fmt.pix.sizeimage, + port->current_buffer.size); + port->current_buffer.size = + (f->fmt.pix.sizeimage < + (100 << 10)) + ? (100 << 10) : f->fmt.pix. + sizeimage; + } + v4l2_dbg(1, bcm2835_v4l2_debug, + &dev->v4l2_dev, + "vid_cap - cur_buf.size set to %d\n", + f->fmt.pix.sizeimage); + port->current_buffer.alignment = 0; + } + } else { + /* configure buffering */ + camera_port->current_buffer.num = 1; + camera_port->current_buffer.size = f->fmt.pix.sizeimage; + camera_port->current_buffer.alignment = 0; + } + + if (!ret) { + dev->capture.fmt = mfmt; + dev->capture.stride = f->fmt.pix.bytesperline; + dev->capture.width = camera_port->es.video.crop.width; + dev->capture.height = camera_port->es.video.crop.height; + dev->capture.buffersize = port->current_buffer.size; + + /* select port for capture */ + dev->capture.port = port; + dev->capture.camera_port = camera_port; + dev->capture.encode_component = encode_component; + v4l2_dbg(1, bcm2835_v4l2_debug, + &dev->v4l2_dev, + "Set dev->capture.fmt %08X, %dx%d, stride %d, size %d", + port->format.encoding, + dev->capture.width, dev->capture.height, + dev->capture.stride, dev->capture.buffersize); + } + } + + /* todo: Need to convert the vchiq/mmal error into a v4l2 error. */ + return ret; +} + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + int ret; + struct bm2835_mmal_dev *dev = video_drvdata(file); + struct mmal_fmt *mfmt; + + /* try the format to set valid parameters */ + ret = vidioc_try_fmt_vid_cap(file, priv, f); + if (ret) { + v4l2_err(&dev->v4l2_dev, + "vid_cap - vidioc_try_fmt_vid_cap failed\n"); + return ret; + } + + /* if a capture is running refuse to set format */ + if (vb2_is_busy(&dev->capture.vb_vidq)) { + v4l2_info(&dev->v4l2_dev, "%s device busy\n", __func__); + return -EBUSY; + } + + /* If the format is unsupported v4l2 says we should switch to + * a supported one and not return an error. */ + mfmt = get_format(f); + if (!mfmt) { + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "Fourcc format (0x%08x) unknown.\n", + f->fmt.pix.pixelformat); + f->fmt.pix.pixelformat = formats[0].fourcc; + mfmt = get_format(f); + } + + ret = mmal_setup_components(dev, f); + 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; + + 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; + + /* fill in stepwise (step=1.0 is requred by V4L2 spec) */ + fival->stepwise.min = tpf_min; + fival->stepwise.max = tpf_max; + fival->stepwise.step = (struct v4l2_fract) {1, 1}; + + return 0; +} + +static int vidioc_g_parm(struct file *file, void *priv, + struct v4l2_streamparm *parm) +{ + struct bm2835_mmal_dev *dev = video_drvdata(file); + + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + parm->parm.capture.timeperframe = dev->capture.timeperframe; + parm->parm.capture.readbuffers = 1; + return 0; +} + +#define FRACT_CMP(a, OP, b) \ + ((u64)(a).numerator * (b).denominator OP \ + (u64)(b).numerator * (a).denominator) + +static int vidioc_s_parm(struct file *file, void *priv, + struct v4l2_streamparm *parm) +{ + struct bm2835_mmal_dev *dev = video_drvdata(file); + struct v4l2_fract tpf; + struct mmal_parameter_rational fps_param; + + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + tpf = parm->parm.capture.timeperframe; + + /* tpf: {*, 0} resets timing; clip to [min, max]*/ + tpf = tpf.denominator ? tpf : tpf_default; + tpf = FRACT_CMP(tpf, <, tpf_min) ? tpf_min : tpf; + tpf = FRACT_CMP(tpf, >, tpf_max) ? tpf_max : tpf; + + dev->capture.timeperframe = tpf; + parm->parm.capture.timeperframe = tpf; + parm->parm.capture.readbuffers = 1; + + 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; +} + +static const struct v4l2_ioctl_ops camera0_ioctl_ops = { + /* overlay */ + .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay, + .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, + .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, + .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, + .vidioc_overlay = vidioc_overlay, + .vidioc_g_fbuf = vidioc_g_fbuf, + + /* inputs */ + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + + /* capture */ + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + + /* buffer management */ + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_enum_framesizes = vidioc_enum_framesizes, + .vidioc_enum_frameintervals = vidioc_enum_frameintervals, + .vidioc_g_parm = vidioc_g_parm, + .vidioc_s_parm = vidioc_s_parm, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static const struct v4l2_ioctl_ops camera0_ioctl_ops_gstreamer = { + /* overlay */ + .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay, + .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, + .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, + .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, + .vidioc_overlay = vidioc_overlay, + .vidioc_g_fbuf = vidioc_g_fbuf, + + /* inputs */ + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + + /* capture */ + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + + /* buffer management */ + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + /* Remove this function ptr to fix gstreamer bug + .vidioc_enum_framesizes = vidioc_enum_framesizes, */ + .vidioc_enum_frameintervals = vidioc_enum_frameintervals, + .vidioc_g_parm = vidioc_g_parm, + .vidioc_s_parm = vidioc_s_parm, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +/* ------------------------------------------------------------------ + Driver init/finalise + ------------------------------------------------------------------*/ + +static const struct v4l2_file_operations camera0_fops = { + .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = vb2_fop_release, + .read = vb2_fop_read, + .poll = vb2_fop_poll, + .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ + .mmap = vb2_fop_mmap, +}; + +static struct video_device vdev_template = { + .name = "camera0", + .fops = &camera0_fops, + .ioctl_ops = &camera0_ioctl_ops, + .release = video_device_release_empty, +}; + +static int set_camera_parameters(struct vchiq_mmal_instance *instance, + struct vchiq_mmal_component *camera) +{ + int ret; + struct mmal_parameter_camera_config cam_config = { + .max_stills_w = MAX_WIDTH, + .max_stills_h = MAX_HEIGHT, + .stills_yuv422 = 1, + .one_shot_stills = 1, + .max_preview_video_w = (max_video_width > 1920) ? + max_video_width : 1920, + .max_preview_video_h = (max_video_height > 1088) ? + max_video_height : 1088, + .num_preview_video_frames = 3, + .stills_capture_circular_buffer_height = 0, + .fast_preview_resume = 0, + .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RAW_STC + }; + + ret = vchiq_mmal_port_parameter_set(instance, &camera->control, + MMAL_PARAMETER_CAMERA_CONFIG, + &cam_config, sizeof(cam_config)); + return ret; +} + +/* MMAL instance and component init */ +static int __init mmal_init(struct bm2835_mmal_dev *dev) +{ + int ret; + struct mmal_es_format *format; + u32 bool_true = 1; + + ret = vchiq_mmal_init(&dev->instance); + if (ret < 0) + return ret; + + /* get the camera component ready */ + ret = vchiq_mmal_component_init(dev->instance, "ril.camera", + &dev->component[MMAL_COMPONENT_CAMERA]); + if (ret < 0) + goto unreg_mmal; + + if (dev->component[MMAL_COMPONENT_CAMERA]->outputs < + MMAL_CAMERA_PORT_COUNT) { + ret = -EINVAL; + goto unreg_camera; + } + + ret = set_camera_parameters(dev->instance, + dev->component[MMAL_COMPONENT_CAMERA]); + if (ret < 0) + goto unreg_camera; + + format = + &dev->component[MMAL_COMPONENT_CAMERA]-> + output[MMAL_CAMERA_PORT_PREVIEW].format; + + format->encoding = MMAL_ENCODING_OPAQUE; + format->encoding_variant = MMAL_ENCODING_I420; + + format->es->video.width = 1024; + format->es->video.height = 768; + format->es->video.crop.x = 0; + format->es->video.crop.y = 0; + format->es->video.crop.width = 1024; + format->es->video.crop.height = 768; + format->es->video.frame_rate.num = 0; /* Rely on fps_range */ + format->es->video.frame_rate.den = 1; + + format = + &dev->component[MMAL_COMPONENT_CAMERA]-> + output[MMAL_CAMERA_PORT_VIDEO].format; + + format->encoding = MMAL_ENCODING_OPAQUE; + format->encoding_variant = MMAL_ENCODING_I420; + + format->es->video.width = 1024; + format->es->video.height = 768; + format->es->video.crop.x = 0; + format->es->video.crop.y = 0; + format->es->video.crop.width = 1024; + format->es->video.crop.height = 768; + format->es->video.frame_rate.num = 0; /* Rely on fps_range */ + format->es->video.frame_rate.den = 1; + + vchiq_mmal_port_parameter_set(dev->instance, + &dev->component[MMAL_COMPONENT_CAMERA]-> + output[MMAL_CAMERA_PORT_VIDEO], + MMAL_PARAMETER_NO_IMAGE_PADDING, + &bool_true, sizeof(bool_true)); + + format = + &dev->component[MMAL_COMPONENT_CAMERA]-> + output[MMAL_CAMERA_PORT_CAPTURE].format; + + format->encoding = MMAL_ENCODING_OPAQUE; + + format->es->video.width = 2592; + format->es->video.height = 1944; + format->es->video.crop.x = 0; + format->es->video.crop.y = 0; + format->es->video.crop.width = 2592; + format->es->video.crop.height = 1944; + 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; + dev->capture.height = format->es->video.height; + 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; + + vchiq_mmal_port_parameter_set(dev->instance, + &dev->component[MMAL_COMPONENT_CAMERA]-> + output[MMAL_CAMERA_PORT_CAPTURE], + MMAL_PARAMETER_NO_IMAGE_PADDING, + &bool_true, sizeof(bool_true)); + + /* get the preview component ready */ + ret = vchiq_mmal_component_init( + dev->instance, "ril.video_render", + &dev->component[MMAL_COMPONENT_PREVIEW]); + if (ret < 0) + goto unreg_camera; + + if (dev->component[MMAL_COMPONENT_PREVIEW]->inputs < 1) { + ret = -EINVAL; + pr_debug("too few input ports %d needed %d\n", + dev->component[MMAL_COMPONENT_PREVIEW]->inputs, 1); + goto unreg_preview; + } + + /* get the image encoder component ready */ + ret = vchiq_mmal_component_init( + dev->instance, "ril.image_encode", + &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]); + if (ret < 0) + goto unreg_preview; + + if (dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs < 1) { + ret = -EINVAL; + v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n", + dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs, + 1); + goto unreg_image_encoder; + } + + /* get the video encoder component ready */ + ret = vchiq_mmal_component_init(dev->instance, "ril.video_encode", + &dev-> + component[MMAL_COMPONENT_VIDEO_ENCODE]); + if (ret < 0) + goto unreg_image_encoder; + + if (dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs < 1) { + ret = -EINVAL; + v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n", + dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs, + 1); + goto unreg_vid_encoder; + } + + { + 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, + &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control, + MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, + &enable, sizeof(enable)); + + vchiq_mmal_port_parameter_set(dev->instance, + &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control, + MMAL_PARAMETER_MINIMISE_FRAGMENTATION, + &enable, + sizeof(enable)); + } + ret = bm2835_mmal_set_all_camera_controls(dev); + if (ret < 0) + goto unreg_vid_encoder; + + return 0; + +unreg_vid_encoder: + pr_err("Cleanup: Destroy video encoder\n"); + vchiq_mmal_component_finalise( + dev->instance, + dev->component[MMAL_COMPONENT_VIDEO_ENCODE]); + +unreg_image_encoder: + pr_err("Cleanup: Destroy image encoder\n"); + vchiq_mmal_component_finalise( + dev->instance, + dev->component[MMAL_COMPONENT_IMAGE_ENCODE]); + +unreg_preview: + pr_err("Cleanup: Destroy video render\n"); + vchiq_mmal_component_finalise(dev->instance, + dev->component[MMAL_COMPONENT_PREVIEW]); + +unreg_camera: + pr_err("Cleanup: Destroy camera\n"); + vchiq_mmal_component_finalise(dev->instance, + dev->component[MMAL_COMPONENT_CAMERA]); + +unreg_mmal: + vchiq_mmal_finalise(dev->instance); + return ret; +} + +static int __init bm2835_mmal_init_device(struct bm2835_mmal_dev *dev, + struct video_device *vfd) +{ + int ret; + + *vfd = vdev_template; + if (gst_v4l2src_is_broken) { + v4l2_info(&dev->v4l2_dev, + "Work-around for gstreamer issue is active.\n"); + vfd->ioctl_ops = &camera0_ioctl_ops_gstreamer; + } + + vfd->v4l2_dev = &dev->v4l2_dev; + + vfd->lock = &dev->mutex; + + vfd->queue = &dev->capture.vb_vidq; + + /* video device needs to be able to access instance data */ + video_set_drvdata(vfd, dev); + + ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); + if (ret < 0) + return ret; + + v4l2_info(vfd->v4l2_dev, + "V4L2 device registered as %s - stills mode > %dx%d\n", + video_device_node_name(vfd), max_video_width, max_video_height); + + return 0; +} + +static struct v4l2_format default_v4l2_format = { + .fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG, + .fmt.pix.width = 1024, + .fmt.pix.bytesperline = 1024, + .fmt.pix.height = 768, + .fmt.pix.sizeimage = 1024*768, +}; + +static int __init bm2835_mmal_init(void) +{ + int ret; + struct bm2835_mmal_dev *dev; + struct vb2_queue *q; + + dev = kzalloc(sizeof(*gdev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + /* setup device defaults */ + dev->overlay.w.left = 150; + dev->overlay.w.top = 50; + dev->overlay.w.width = 1024; + dev->overlay.w.height = 768; + dev->overlay.clipcount = 0; + dev->overlay.field = V4L2_FIELD_NONE; + + dev->capture.fmt = &formats[3]; /* JPEG */ + + /* v4l device registration */ + snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), + "%s", BM2835_MMAL_MODULE_NAME); + ret = v4l2_device_register(NULL, &dev->v4l2_dev); + if (ret) + goto free_dev; + + /* setup v4l controls */ + ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler); + if (ret < 0) + goto unreg_dev; + dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler; + + /* mmal init */ + ret = mmal_init(dev); + if (ret < 0) + goto unreg_dev; + + /* initialize queue */ + q = &dev->capture.vb_vidq; + memset(q, 0, sizeof(*q)); + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; + q->drv_priv = dev; + q->buf_struct_size = sizeof(struct mmal_buffer); + q->ops = &bm2835_mmal_video_qops; + q->mem_ops = &vb2_vmalloc_memops; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + ret = vb2_queue_init(q); + if (ret < 0) + goto unreg_dev; + + /* v4l2 core mutex used to protect all fops and v4l2 ioctls. */ + mutex_init(&dev->mutex); + + /* initialise video devices */ + ret = bm2835_mmal_init_device(dev, &dev->vdev); + if (ret < 0) + goto unreg_dev; + + /* Really want to call vidioc_s_fmt_vid_cap with the default + * format, but currently the APIs don't join up. + */ + ret = mmal_setup_components(dev, &default_v4l2_format); + if (ret < 0) { + v4l2_err(&dev->v4l2_dev, + "%s: could not setup components\n", __func__); + goto unreg_dev; + } + + v4l2_info(&dev->v4l2_dev, + "Broadcom 2835 MMAL video capture ver %s loaded.\n", + BM2835_MMAL_VERSION); + + gdev = dev; + return 0; + +unreg_dev: + v4l2_ctrl_handler_free(&dev->ctrl_handler); + v4l2_device_unregister(&dev->v4l2_dev); + +free_dev: + kfree(dev); + + v4l2_err(&dev->v4l2_dev, + "%s: error %d while loading driver\n", + BM2835_MMAL_MODULE_NAME, ret); + + return ret; +} + +static void __exit bm2835_mmal_exit(void) +{ + if (!gdev) + return; + + v4l2_info(&gdev->v4l2_dev, "unregistering %s\n", + video_device_node_name(&gdev->vdev)); + + video_unregister_device(&gdev->vdev); + + if (gdev->capture.encode_component) { + v4l2_dbg(1, bcm2835_v4l2_debug, &gdev->v4l2_dev, + "mmal_exit - disconnect tunnel\n"); + vchiq_mmal_port_connect_tunnel(gdev->instance, + gdev->capture.camera_port, NULL); + vchiq_mmal_component_disable(gdev->instance, + gdev->capture.encode_component); + } + vchiq_mmal_component_disable(gdev->instance, + gdev->component[MMAL_COMPONENT_CAMERA]); + + vchiq_mmal_component_finalise(gdev->instance, + gdev-> + component[MMAL_COMPONENT_VIDEO_ENCODE]); + + vchiq_mmal_component_finalise(gdev->instance, + gdev-> + component[MMAL_COMPONENT_IMAGE_ENCODE]); + + vchiq_mmal_component_finalise(gdev->instance, + gdev->component[MMAL_COMPONENT_PREVIEW]); + + vchiq_mmal_component_finalise(gdev->instance, + gdev->component[MMAL_COMPONENT_CAMERA]); + + vchiq_mmal_finalise(gdev->instance); + + v4l2_ctrl_handler_free(&gdev->ctrl_handler); + + v4l2_device_unregister(&gdev->v4l2_dev); + + kfree(gdev); +} + +module_init(bm2835_mmal_init); +module_exit(bm2835_mmal_exit); diff -Nur '--exclude=.git' linux-stable/drivers/media/platform/bcm2835/bcm2835-camera.h raspilinux/drivers/media/platform/bcm2835/bcm2835-camera.h --- linux-stable/drivers/media/platform/bcm2835/bcm2835-camera.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/media/platform/bcm2835/bcm2835-camera.h 2015-12-26 19:08:31.672617523 +0100 @@ -0,0 +1,126 @@ +/* + * Broadcom BM2835 V4L2 driver + * + * Copyright © 2013 Raspberry Pi (Trading) Ltd. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Authors: Vincent Sanders + * Dave Stevenson + * Simon Mellor + * Luke Diamand + * + * core driver device + */ + +#define V4L2_CTRL_COUNT 28 /* number of v4l controls */ + +enum { + MMAL_COMPONENT_CAMERA = 0, + MMAL_COMPONENT_PREVIEW, + MMAL_COMPONENT_IMAGE_ENCODE, + MMAL_COMPONENT_VIDEO_ENCODE, + MMAL_COMPONENT_COUNT +}; + +enum { + MMAL_CAMERA_PORT_PREVIEW = 0, + MMAL_CAMERA_PORT_VIDEO, + MMAL_CAMERA_PORT_CAPTURE, + MMAL_CAMERA_PORT_COUNT +}; + +#define PREVIEW_LAYER 2 + +extern int bcm2835_v4l2_debug; + +struct bm2835_mmal_dev { + /* v4l2 devices */ + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct mutex mutex; + + /* 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; + 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; + struct vchiq_mmal_component *component[MMAL_COMPONENT_COUNT]; + int camera_use_count; + + struct v4l2_window overlay; + + struct { + unsigned int width; /* width */ + unsigned int height; /* height */ + unsigned int stride; /* stride */ + unsigned int buffersize; /* buffer size with padding */ + struct mmal_fmt *fmt; + 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; + + struct vb2_queue vb_vidq; + + /* VC start timestamp for streaming */ + s64 vc_start_timestamp; + /* Kernel start timestamp for streaming */ + struct timeval kernel_start_ts; + + struct vchiq_mmal_port *port; /* port being used for capture */ + /* camera port being used for capture */ + struct vchiq_mmal_port *camera_port; + /* component being used for encode */ + struct vchiq_mmal_component *encode_component; + /* number of frames remaining which driver should capture */ + unsigned int frame_count; + /* last frame completion */ + struct completion frame_cmplt; + + } capture; + +}; + +int bm2835_mmal_init_controls( + struct bm2835_mmal_dev *dev, + 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 */ + +#define v4l2_dump_pix_format(level, debug, dev, pix_fmt, desc) \ +{ \ + v4l2_dbg(level, debug, dev, \ +"%s: w %u h %u field %u pfmt 0x%x bpl %u sz_img %u colorspace 0x%x priv %u\n", \ + desc == NULL ? "" : desc, \ + (pix_fmt)->width, (pix_fmt)->height, (pix_fmt)->field, \ + (pix_fmt)->pixelformat, (pix_fmt)->bytesperline, \ + (pix_fmt)->sizeimage, (pix_fmt)->colorspace, (pix_fmt)->priv); \ +} diff -Nur '--exclude=.git' linux-stable/drivers/media/platform/bcm2835/controls.c raspilinux/drivers/media/platform/bcm2835/controls.c --- linux-stable/drivers/media/platform/bcm2835/controls.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/media/platform/bcm2835/controls.c 2015-12-26 19:08:31.672617523 +0100 @@ -0,0 +1,1324 @@ +/* + * Broadcom BM2835 V4L2 driver + * + * Copyright © 2013 Raspberry Pi (Trading) Ltd. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Authors: Vincent Sanders + * Dave Stevenson + * Simon Mellor + * Luke Diamand + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mmal-common.h" +#include "mmal-vchiq.h" +#include "mmal-parameters.h" +#include "bcm2835-camera.h" + +/* The supported V4L2_CID_AUTO_EXPOSURE_BIAS values are from -4.0 to +4.0. + * MMAL values are in 1/6th increments so the MMAL range is -24 to +24. + * V4L2 docs say value "is expressed in terms of EV, drivers should interpret + * the values as 0.001 EV units, where the value 1000 stands for +1 EV." + * V4L2 is limited to a max of 32 values in a menu, so count in 1/3rds from + * -4 to +4 + */ +static const s64 ev_bias_qmenu[] = { + -4000, -3667, -3333, + -3000, -2667, -2333, + -2000, -1667, -1333, + -1000, -667, -333, + 0, 333, 667, + 1000, 1333, 1667, + 2000, 2333, 2667, + 3000, 3333, 3667, + 4000 +}; + +/* Supported ISO values + * ISOO = auto ISO + */ +static const s64 iso_qmenu[] = { + 0, 100, 200, 400, 800, +}; + +static const s64 mains_freq_qmenu[] = { + V4L2_CID_POWER_LINE_FREQUENCY_DISABLED, + V4L2_CID_POWER_LINE_FREQUENCY_50HZ, + V4L2_CID_POWER_LINE_FREQUENCY_60HZ, + V4L2_CID_POWER_LINE_FREQUENCY_AUTO +}; + +/* Supported video encode modes */ +static const s64 bitrate_mode_qmenu[] = { + (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, +}; + +enum bm2835_mmal_ctrl_type { + MMAL_CONTROL_TYPE_STD, + MMAL_CONTROL_TYPE_STD_MENU, + MMAL_CONTROL_TYPE_INT_MENU, + MMAL_CONTROL_TYPE_CLUSTER, /* special cluster entry */ +}; + +struct bm2835_mmal_v4l2_ctrl; + +typedef int(bm2835_mmal_v4l2_ctrl_cb)( + struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl); + +struct bm2835_mmal_v4l2_ctrl { + u32 id; /* v4l2 control identifier */ + enum bm2835_mmal_ctrl_type type; + /* control minimum value or + * mask for MMAL_CONTROL_TYPE_STD_MENU */ + s32 min; + s32 max; /* maximum value of control */ + s32 def; /* default value of control */ + s32 step; /* step size of the control */ + const s64 *imenu; /* integer menu array */ + u32 mmal_id; /* mmal parameter id */ + bm2835_mmal_v4l2_ctrl_cb *setter; + bool ignore_errors; +}; + +struct v4l2_to_mmal_effects_setting { + u32 v4l2_effect; + u32 mmal_effect; + s32 col_fx_enable; + s32 col_fx_fixed_cbcr; + u32 u; + u32 v; + u32 num_effect_params; + u32 effect_params[MMAL_MAX_IMAGEFX_PARAMETERS]; +}; + +static const struct v4l2_to_mmal_effects_setting + v4l2_to_mmal_effects_values[] = { + { V4L2_COLORFX_NONE, MMAL_PARAM_IMAGEFX_NONE, + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, + { V4L2_COLORFX_BW, MMAL_PARAM_IMAGEFX_NONE, + 1, 0, 128, 128, 0, {0, 0, 0, 0, 0} }, + { V4L2_COLORFX_SEPIA, MMAL_PARAM_IMAGEFX_NONE, + 1, 0, 87, 151, 0, {0, 0, 0, 0, 0} }, + { V4L2_COLORFX_NEGATIVE, MMAL_PARAM_IMAGEFX_NEGATIVE, + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, + { V4L2_COLORFX_EMBOSS, MMAL_PARAM_IMAGEFX_EMBOSS, + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, + { V4L2_COLORFX_SKETCH, MMAL_PARAM_IMAGEFX_SKETCH, + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, + { V4L2_COLORFX_SKY_BLUE, MMAL_PARAM_IMAGEFX_PASTEL, + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, + { V4L2_COLORFX_GRASS_GREEN, MMAL_PARAM_IMAGEFX_WATERCOLOUR, + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, + { V4L2_COLORFX_SKIN_WHITEN, MMAL_PARAM_IMAGEFX_WASHEDOUT, + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, + { V4L2_COLORFX_VIVID, MMAL_PARAM_IMAGEFX_SATURATION, + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, + { V4L2_COLORFX_AQUA, MMAL_PARAM_IMAGEFX_NONE, + 1, 0, 171, 121, 0, {0, 0, 0, 0, 0} }, + { V4L2_COLORFX_ART_FREEZE, MMAL_PARAM_IMAGEFX_HATCH, + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, + { V4L2_COLORFX_SILHOUETTE, MMAL_PARAM_IMAGEFX_FILM, + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, + { V4L2_COLORFX_SOLARIZATION, MMAL_PARAM_IMAGEFX_SOLARIZE, + 0, 0, 0, 0, 5, {1, 128, 160, 160, 48} }, + { V4L2_COLORFX_ANTIQUE, MMAL_PARAM_IMAGEFX_COLOURBALANCE, + 0, 0, 0, 0, 3, {108, 274, 238, 0, 0} }, + { V4L2_COLORFX_SET_CBCR, MMAL_PARAM_IMAGEFX_NONE, + 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*/ + +static int ctrl_set_rational(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) +{ + struct mmal_parameter_rational rational_value; + struct vchiq_mmal_port *control; + + control = &dev->component[MMAL_COMPONENT_CAMERA]->control; + + rational_value.num = ctrl->val; + rational_value.den = 100; + + return vchiq_mmal_port_parameter_set(dev->instance, control, + mmal_ctrl->mmal_id, + &rational_value, + sizeof(rational_value)); +} + +static int ctrl_set_value(struct bm2835_mmal_dev *dev, + 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; + + u32_value = ctrl->val; + + return vchiq_mmal_port_parameter_set(dev->instance, control, + mmal_ctrl->mmal_id, + &u32_value, sizeof(u32_value)); +} + +static int ctrl_set_value_menu(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) +{ + u32 u32_value; + struct vchiq_mmal_port *control; + + if (ctrl->val > mmal_ctrl->max || ctrl->val < mmal_ctrl->min) + return 1; + + control = &dev->component[MMAL_COMPONENT_CAMERA]->control; + + u32_value = mmal_ctrl->imenu[ctrl->val]; + + return vchiq_mmal_port_parameter_set(dev->instance, control, + mmal_ctrl->mmal_id, + &u32_value, sizeof(u32_value)); +} + +static int ctrl_set_value_ev(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) +{ + s32 s32_value; + struct vchiq_mmal_port *control; + + control = &dev->component[MMAL_COMPONENT_CAMERA]->control; + + s32_value = (ctrl->val-12)*2; /* Convert from index to 1/6ths */ + + return vchiq_mmal_port_parameter_set(dev->instance, control, + mmal_ctrl->mmal_id, + &s32_value, sizeof(s32_value)); +} + +static int ctrl_set_rotate(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) +{ + int ret; + u32 u32_value; + struct vchiq_mmal_component *camera; + + camera = dev->component[MMAL_COMPONENT_CAMERA]; + + u32_value = ((ctrl->val % 360) / 90) * 90; + + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[0], + mmal_ctrl->mmal_id, + &u32_value, sizeof(u32_value)); + if (ret < 0) + return ret; + + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[1], + mmal_ctrl->mmal_id, + &u32_value, sizeof(u32_value)); + if (ret < 0) + return ret; + + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[2], + mmal_ctrl->mmal_id, + &u32_value, sizeof(u32_value)); + + return ret; +} + +static int ctrl_set_flip(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) +{ + int ret; + u32 u32_value; + struct vchiq_mmal_component *camera; + + if (ctrl->id == V4L2_CID_HFLIP) + dev->hflip = ctrl->val; + else + dev->vflip = ctrl->val; + + camera = dev->component[MMAL_COMPONENT_CAMERA]; + + if (dev->hflip && dev->vflip) + u32_value = MMAL_PARAM_MIRROR_BOTH; + else if (dev->hflip) + u32_value = MMAL_PARAM_MIRROR_HORIZONTAL; + else if (dev->vflip) + u32_value = MMAL_PARAM_MIRROR_VERTICAL; + else + u32_value = MMAL_PARAM_MIRROR_NONE; + + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[0], + mmal_ctrl->mmal_id, + &u32_value, sizeof(u32_value)); + if (ret < 0) + return ret; + + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[1], + mmal_ctrl->mmal_id, + &u32_value, sizeof(u32_value)); + if (ret < 0) + return ret; + + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[2], + mmal_ctrl->mmal_id, + &u32_value, sizeof(u32_value)); + + return ret; + +} + +static int ctrl_set_exposure(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) +{ + enum mmal_parameter_exposuremode exp_mode = dev->exposure_mode_user; + u32 shutter_speed = 0; + struct vchiq_mmal_port *control; + int ret = 0; + + control = &dev->component[MMAL_COMPONENT_CAMERA]->control; + + if (mmal_ctrl->mmal_id == MMAL_PARAMETER_SHUTTER_SPEED) { + /* V4L2 is in 100usec increments. + * MMAL is 1usec. + */ + dev->manual_shutter_speed = ctrl->val * 100; + } else if (mmal_ctrl->mmal_id == MMAL_PARAMETER_EXPOSURE_MODE) { + switch (ctrl->val) { + case V4L2_EXPOSURE_AUTO: + exp_mode = MMAL_PARAM_EXPOSUREMODE_AUTO; + break; + + case V4L2_EXPOSURE_MANUAL: + exp_mode = MMAL_PARAM_EXPOSUREMODE_OFF; + break; + } + 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); + + return ret; +} + +static int ctrl_set_metering_mode(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) +{ + switch (ctrl->val) { + case V4L2_EXPOSURE_METERING_AVERAGE: + dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE; + break; + + case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED: + dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT; + break; + + case V4L2_EXPOSURE_METERING_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: + dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX; + break; + */ + + } + + 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, + 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_CID_POWER_LINE_FREQUENCY_DISABLED: + u32_value = MMAL_PARAM_FLICKERAVOID_OFF; + break; + case V4L2_CID_POWER_LINE_FREQUENCY_50HZ: + u32_value = MMAL_PARAM_FLICKERAVOID_50HZ; + break; + case V4L2_CID_POWER_LINE_FREQUENCY_60HZ: + u32_value = MMAL_PARAM_FLICKERAVOID_60HZ; + break; + case V4L2_CID_POWER_LINE_FREQUENCY_AUTO: + u32_value = MMAL_PARAM_FLICKERAVOID_AUTO; + break; + } + + return vchiq_mmal_port_parameter_set(dev->instance, control, + mmal_ctrl->mmal_id, + &u32_value, sizeof(u32_value)); +} + +static int ctrl_set_awb_mode(struct bm2835_mmal_dev *dev, + 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_WHITE_BALANCE_MANUAL: + u32_value = MMAL_PARAM_AWBMODE_OFF; + break; + + case V4L2_WHITE_BALANCE_AUTO: + u32_value = MMAL_PARAM_AWBMODE_AUTO; + break; + + case V4L2_WHITE_BALANCE_INCANDESCENT: + u32_value = MMAL_PARAM_AWBMODE_INCANDESCENT; + break; + + case V4L2_WHITE_BALANCE_FLUORESCENT: + u32_value = MMAL_PARAM_AWBMODE_FLUORESCENT; + break; + + case V4L2_WHITE_BALANCE_FLUORESCENT_H: + u32_value = MMAL_PARAM_AWBMODE_TUNGSTEN; + break; + + case V4L2_WHITE_BALANCE_HORIZON: + u32_value = MMAL_PARAM_AWBMODE_HORIZON; + break; + + case V4L2_WHITE_BALANCE_DAYLIGHT: + u32_value = MMAL_PARAM_AWBMODE_SUNLIGHT; + break; + + case V4L2_WHITE_BALANCE_FLASH: + u32_value = MMAL_PARAM_AWBMODE_FLASH; + break; + + case V4L2_WHITE_BALANCE_CLOUDY: + u32_value = MMAL_PARAM_AWBMODE_CLOUDY; + break; + + case V4L2_WHITE_BALANCE_SHADE: + u32_value = MMAL_PARAM_AWBMODE_SHADE; + break; + + } + + return vchiq_mmal_port_parameter_set(dev->instance, control, + mmal_ctrl->mmal_id, + &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) +{ + int ret = -EINVAL; + int i, j; + struct vchiq_mmal_port *control; + struct mmal_parameter_imagefx_parameters imagefx; + + for (i = 0; i < ARRAY_SIZE(v4l2_to_mmal_effects_values); i++) { + if (ctrl->val == v4l2_to_mmal_effects_values[i].v4l2_effect) { + + imagefx.effect = + v4l2_to_mmal_effects_values[i].mmal_effect; + imagefx.num_effect_params = + v4l2_to_mmal_effects_values[i].num_effect_params; + + if (imagefx.num_effect_params > MMAL_MAX_IMAGEFX_PARAMETERS) + imagefx.num_effect_params = MMAL_MAX_IMAGEFX_PARAMETERS; + + for (j = 0; j < imagefx.num_effect_params; j++) + imagefx.effect_parameter[j] = + v4l2_to_mmal_effects_values[i].effect_params[j]; + + dev->colourfx.enable = + v4l2_to_mmal_effects_values[i].col_fx_enable; + if (!v4l2_to_mmal_effects_values[i].col_fx_fixed_cbcr) { + dev->colourfx.u = + v4l2_to_mmal_effects_values[i].u; + dev->colourfx.v = + v4l2_to_mmal_effects_values[i].v; + } + + control = &dev->component[MMAL_COMPONENT_CAMERA]->control; + + ret = vchiq_mmal_port_parameter_set( + dev->instance, control, + MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, + &imagefx, sizeof(imagefx)); + if (ret) + goto exit; + + ret = vchiq_mmal_port_parameter_set( + dev->instance, control, + MMAL_PARAMETER_COLOUR_EFFECT, + &dev->colourfx, sizeof(dev->colourfx)); + } + } + +exit: + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "mmal_ctrl:%p ctrl id:0x%x ctrl val:%d imagefx:0x%x color_effect:%s u:%d v:%d ret %d(%d)\n", + mmal_ctrl, ctrl->id, ctrl->val, imagefx.effect, + dev->colourfx.enable ? "true" : "false", + dev->colourfx.u, dev->colourfx.v, + ret, (ret == 0 ? 0 : -EINVAL)); + return (ret == 0 ? 0 : EINVAL); +} + +static int ctrl_set_colfx(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) +{ + int ret = -EINVAL; + struct vchiq_mmal_port *control; + + control = &dev->component[MMAL_COMPONENT_CAMERA]->control; + + dev->colourfx.enable = (ctrl->val & 0xff00) >> 8; + dev->colourfx.enable = ctrl->val & 0xff; + + ret = vchiq_mmal_port_parameter_set(dev->instance, control, + MMAL_PARAMETER_COLOUR_EFFECT, + &dev->colourfx, sizeof(dev->colourfx)); + + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, + "%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); +} + +static int ctrl_set_bitrate(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) +{ + int ret; + struct vchiq_mmal_port *encoder_out; + + dev->capture.encode_bitrate = ctrl->val; + + encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0]; + + ret = vchiq_mmal_port_parameter_set(dev->instance, encoder_out, + mmal_ctrl->mmal_id, + &ctrl->val, sizeof(ctrl->val)); + ret = 0; + return ret; +} + +static int ctrl_set_bitrate_mode(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) +{ + u32 bitrate_mode; + struct vchiq_mmal_port *encoder_out; + + encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0]; + + dev->capture.encode_bitrate_mode = ctrl->val; + switch (ctrl->val) { + default: + case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR: + bitrate_mode = MMAL_VIDEO_RATECONTROL_VARIABLE; + break; + case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR: + bitrate_mode = MMAL_VIDEO_RATECONTROL_CONSTANT; + break; + } + + vchiq_mmal_port_parameter_set(dev->instance, encoder_out, + mmal_ctrl->mmal_id, + &bitrate_mode, + sizeof(bitrate_mode)); + return 0; +} + +static int ctrl_set_image_encode_output(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) +{ + u32 u32_value; + struct vchiq_mmal_port *jpeg_out; + + jpeg_out = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0]; + + u32_value = ctrl->val; + + return vchiq_mmal_port_parameter_set(dev->instance, jpeg_out, + mmal_ctrl->mmal_id, + &u32_value, sizeof(u32_value)); +} + +static int ctrl_set_video_encode_param_output(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) +{ + u32 u32_value; + struct vchiq_mmal_port *vid_enc_ctl; + + vid_enc_ctl = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0]; + + u32_value = ctrl->val; + + return vchiq_mmal_port_parameter_set(dev->instance, vid_enc_ctl, + mmal_ctrl->mmal_id, + &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 (!scene) + return -EINVAL; + 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 = + container_of(ctrl->handler, struct bm2835_mmal_dev, + ctrl_handler); + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl = ctrl->priv; + int ret; + + if ((mmal_ctrl == NULL) || + (mmal_ctrl->id != ctrl->id) || + (mmal_ctrl->setter == NULL)) { + pr_warn("mmal_ctrl:%p ctrl id:%d\n", mmal_ctrl, ctrl->id); + return -EINVAL; + } + + 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; +} + +static const struct v4l2_ctrl_ops bm2835_mmal_ctrl_ops = { + .s_ctrl = bm2835_mmal_s_ctrl, +}; + + + +static const struct bm2835_mmal_v4l2_ctrl v4l2_ctrls[V4L2_CTRL_COUNT] = { + { + V4L2_CID_SATURATION, MMAL_CONTROL_TYPE_STD, + -100, 100, 0, 1, NULL, + MMAL_PARAMETER_SATURATION, + &ctrl_set_rational, + false + }, + { + V4L2_CID_SHARPNESS, MMAL_CONTROL_TYPE_STD, + -100, 100, 0, 1, NULL, + MMAL_PARAMETER_SHARPNESS, + &ctrl_set_rational, + false + }, + { + V4L2_CID_CONTRAST, MMAL_CONTROL_TYPE_STD, + -100, 100, 0, 1, NULL, + MMAL_PARAMETER_CONTRAST, + &ctrl_set_rational, + false + }, + { + V4L2_CID_BRIGHTNESS, MMAL_CONTROL_TYPE_STD, + 0, 100, 50, 1, NULL, + MMAL_PARAMETER_BRIGHTNESS, + &ctrl_set_rational, + false + }, + { + V4L2_CID_ISO_SENSITIVITY, MMAL_CONTROL_TYPE_INT_MENU, + 0, ARRAY_SIZE(iso_qmenu) - 1, 0, 1, iso_qmenu, + MMAL_PARAMETER_ISO, + &ctrl_set_value_menu, + false + }, + { + V4L2_CID_IMAGE_STABILIZATION, MMAL_CONTROL_TYPE_STD, + 0, 1, 0, 1, NULL, + MMAL_PARAMETER_VIDEO_STABILISATION, + &ctrl_set_value, + false + }, +/* { + 0, MMAL_CONTROL_TYPE_CLUSTER, 3, 1, 0, NULL, 0, NULL + }, */ + { + V4L2_CID_EXPOSURE_AUTO, MMAL_CONTROL_TYPE_STD_MENU, + ~0x03, 3, V4L2_EXPOSURE_AUTO, 0, NULL, + MMAL_PARAMETER_EXPOSURE_MODE, + &ctrl_set_exposure, + false + }, +/* todo this needs mixing in with set exposure + { + V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU, + }, + */ + { + V4L2_CID_EXPOSURE_ABSOLUTE, MMAL_CONTROL_TYPE_STD, + /* Units of 100usecs */ + 1, 1*1000*10, 100*10, 1, NULL, + MMAL_PARAMETER_SHUTTER_SPEED, + &ctrl_set_exposure, + false + }, + { + V4L2_CID_AUTO_EXPOSURE_BIAS, MMAL_CONTROL_TYPE_INT_MENU, + 0, ARRAY_SIZE(ev_bias_qmenu) - 1, + (ARRAY_SIZE(ev_bias_qmenu)+1)/2 - 1, 0, ev_bias_qmenu, + MMAL_PARAMETER_EXPOSURE_COMP, + &ctrl_set_value_ev, + 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, + MMAL_PARAMETER_EXP_METERING_MODE, + &ctrl_set_metering_mode, + false + }, + { + V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, + MMAL_CONTROL_TYPE_STD_MENU, + ~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, + &ctrl_set_image_effect, + false + }, + { + V4L2_CID_COLORFX_CBCR, MMAL_CONTROL_TYPE_STD, + 0, 0xffff, 0x8080, 1, NULL, + MMAL_PARAMETER_COLOUR_EFFECT, + &ctrl_set_colfx, + false + }, + { + V4L2_CID_ROTATE, MMAL_CONTROL_TYPE_STD, + 0, 360, 0, 90, NULL, + MMAL_PARAMETER_ROTATION, + &ctrl_set_rotate, + false + }, + { + V4L2_CID_HFLIP, MMAL_CONTROL_TYPE_STD, + 0, 1, 0, 1, NULL, + MMAL_PARAMETER_MIRROR, + &ctrl_set_flip, + false + }, + { + V4L2_CID_VFLIP, MMAL_CONTROL_TYPE_STD, + 0, 1, 0, 1, NULL, + MMAL_PARAMETER_MIRROR, + &ctrl_set_flip, + false + }, + { + V4L2_CID_MPEG_VIDEO_BITRATE_MODE, MMAL_CONTROL_TYPE_STD_MENU, + 0, ARRAY_SIZE(bitrate_mode_qmenu) - 1, + 0, 0, bitrate_mode_qmenu, + MMAL_PARAMETER_RATECONTROL, + &ctrl_set_bitrate_mode, + false + }, + { + V4L2_CID_MPEG_VIDEO_BITRATE, MMAL_CONTROL_TYPE_STD, + 25*1000, 25*1000*1000, 10*1000*1000, 25*1000, NULL, + MMAL_PARAMETER_VIDEO_BIT_RATE, + &ctrl_set_bitrate, + false + }, + { + V4L2_CID_JPEG_COMPRESSION_QUALITY, MMAL_CONTROL_TYPE_STD, + 1, 100, + 30, 1, NULL, + MMAL_PARAMETER_JPEG_Q_FACTOR, + &ctrl_set_image_encode_output, + false + }, + { + V4L2_CID_POWER_LINE_FREQUENCY, MMAL_CONTROL_TYPE_STD_MENU, + 0, ARRAY_SIZE(mains_freq_qmenu) - 1, + 1, 1, NULL, + MMAL_PARAMETER_FLICKER_AVOID, + &ctrl_set_flicker_avoidance, + false + }, + { + V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, MMAL_CONTROL_TYPE_STD, + 0, 1, + 0, 1, NULL, + MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, + &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<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) { + 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) +{ + int c; + const struct bm2835_mmal_v4l2_ctrl *ctrl; + + v4l2_ctrl_handler_init(hdl, V4L2_CTRL_COUNT); + + for (c = 0; c < V4L2_CTRL_COUNT; c++) { + ctrl = &v4l2_ctrls[c]; + + switch (ctrl->type) { + case MMAL_CONTROL_TYPE_STD: + dev->ctrls[c] = v4l2_ctrl_new_std(hdl, + &bm2835_mmal_ctrl_ops, ctrl->id, + ctrl->min, ctrl->max, ctrl->step, ctrl->def); + 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<ctrls[c] = v4l2_ctrl_new_std_menu(hdl, + &bm2835_mmal_ctrl_ops, ctrl->id, + ctrl->max, mask, ctrl->def); + break; + } + + case MMAL_CONTROL_TYPE_INT_MENU: + dev->ctrls[c] = v4l2_ctrl_new_int_menu(hdl, + &bm2835_mmal_ctrl_ops, ctrl->id, + ctrl->max, ctrl->def, ctrl->imenu); + break; + + case MMAL_CONTROL_TYPE_CLUSTER: + /* skip this entry when constructing controls */ + continue; + } + + if (hdl->error) + break; + + dev->ctrls[c]->priv = (void *)ctrl; + } + + if (hdl->error) { + pr_err("error adding control %d/%d id 0x%x\n", c, + V4L2_CTRL_COUNT, ctrl->id); + return hdl->error; + } + + for (c = 0; c < V4L2_CTRL_COUNT; c++) { + ctrl = &v4l2_ctrls[c]; + + switch (ctrl->type) { + case MMAL_CONTROL_TYPE_CLUSTER: + v4l2_ctrl_auto_cluster(ctrl->min, + &dev->ctrls[c+1], + ctrl->max, + ctrl->def); + break; + + case MMAL_CONTROL_TYPE_STD: + case MMAL_CONTROL_TYPE_STD_MENU: + case MMAL_CONTROL_TYPE_INT_MENU: + break; + } + + } + + return 0; +} diff -Nur '--exclude=.git' linux-stable/drivers/media/platform/bcm2835/Kconfig raspilinux/drivers/media/platform/bcm2835/Kconfig --- linux-stable/drivers/media/platform/bcm2835/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/media/platform/bcm2835/Kconfig 2015-12-26 19:08:31.672617523 +0100 @@ -0,0 +1,25 @@ +# Broadcom VideoCore IV v4l2 camera support + +config VIDEO_BCM2835 + bool "Broadcom BCM2835 camera interface driver" + depends on VIDEO_V4L2 && (ARCH_BCM2708 || ARCH_BCM2709 || ARCH_BCM2835) + ---help--- + Say Y here to enable camera host interface devices for + Broadcom BCM2835 SoC. This operates over the VCHIQ interface + to a service running on VideoCore. + + +if VIDEO_BCM2835 + +config VIDEO_BCM2835_MMAL + tristate "Broadcom BM2835 MMAL camera interface driver" + depends on BCM2708_VCHIQ + select VIDEOBUF2_VMALLOC + ---help--- + This is a V4L2 driver for the Broadcom BCM2835 MMAL camera host interface + + To compile this driver as a module, choose M here: the + module will be called bcm2835-v4l2.o + + +endif # VIDEO_BM2835 diff -Nur '--exclude=.git' linux-stable/drivers/media/platform/bcm2835/Makefile raspilinux/drivers/media/platform/bcm2835/Makefile --- linux-stable/drivers/media/platform/bcm2835/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/media/platform/bcm2835/Makefile 2015-12-26 19:08:31.672617523 +0100 @@ -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 '--exclude=.git' linux-stable/drivers/media/platform/bcm2835/mmal-common.h raspilinux/drivers/media/platform/bcm2835/mmal-common.h --- linux-stable/drivers/media/platform/bcm2835/mmal-common.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/media/platform/bcm2835/mmal-common.h 2015-12-26 19:08:31.672617523 +0100 @@ -0,0 +1,53 @@ +/* + * Broadcom BM2835 V4L2 driver + * + * Copyright © 2013 Raspberry Pi (Trading) Ltd. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Authors: Vincent Sanders + * Dave Stevenson + * Simon Mellor + * Luke Diamand + * + * MMAL structures + * + */ + +#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24)) +#define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l') + +/** Special value signalling that time is not known */ +#define MMAL_TIME_UNKNOWN (1LL<<63) + +/* mapping between v4l and mmal video modes */ +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 */ + u32 ybbp; /* depth of first Y plane for planar formats */ +}; + +/* buffer for one video frame */ +struct mmal_buffer { + /* v4l buffer data -- must be first */ + struct vb2_buffer vb; + + /* list of buffers available */ + struct list_head list; + + void *buffer; /* buffer pointer */ + unsigned long buffer_size; /* size of allocated buffer */ +}; + +/* */ +struct mmal_colourfx { + s32 enable; + u32 u; + u32 v; +}; diff -Nur '--exclude=.git' linux-stable/drivers/media/platform/bcm2835/mmal-encodings.h raspilinux/drivers/media/platform/bcm2835/mmal-encodings.h --- linux-stable/drivers/media/platform/bcm2835/mmal-encodings.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/media/platform/bcm2835/mmal-encodings.h 2015-12-26 19:08:31.672617523 +0100 @@ -0,0 +1,127 @@ +/* + * Broadcom BM2835 V4L2 driver + * + * Copyright © 2013 Raspberry Pi (Trading) Ltd. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Authors: Vincent Sanders + * Dave Stevenson + * Simon Mellor + * Luke Diamand + */ +#ifndef MMAL_ENCODINGS_H +#define MMAL_ENCODINGS_H + +#define MMAL_ENCODING_H264 MMAL_FOURCC('H', '2', '6', '4') +#define MMAL_ENCODING_H263 MMAL_FOURCC('H', '2', '6', '3') +#define MMAL_ENCODING_MP4V MMAL_FOURCC('M', 'P', '4', 'V') +#define MMAL_ENCODING_MP2V MMAL_FOURCC('M', 'P', '2', 'V') +#define MMAL_ENCODING_MP1V MMAL_FOURCC('M', 'P', '1', 'V') +#define MMAL_ENCODING_WMV3 MMAL_FOURCC('W', 'M', 'V', '3') +#define MMAL_ENCODING_WMV2 MMAL_FOURCC('W', 'M', 'V', '2') +#define MMAL_ENCODING_WMV1 MMAL_FOURCC('W', 'M', 'V', '1') +#define MMAL_ENCODING_WVC1 MMAL_FOURCC('W', 'V', 'C', '1') +#define MMAL_ENCODING_VP8 MMAL_FOURCC('V', 'P', '8', ' ') +#define MMAL_ENCODING_VP7 MMAL_FOURCC('V', 'P', '7', ' ') +#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', ' ') +#define MMAL_ENCODING_PNG MMAL_FOURCC('P', 'N', 'G', ' ') +#define MMAL_ENCODING_PPM MMAL_FOURCC('P', 'P', 'M', ' ') +#define MMAL_ENCODING_TGA MMAL_FOURCC('T', 'G', 'A', ' ') +#define MMAL_ENCODING_BMP MMAL_FOURCC('B', 'M', 'P', ' ') + +#define MMAL_ENCODING_I420 MMAL_FOURCC('I', '4', '2', '0') +#define MMAL_ENCODING_I420_SLICE MMAL_FOURCC('S', '4', '2', '0') +#define MMAL_ENCODING_YV12 MMAL_FOURCC('Y', 'V', '1', '2') +#define MMAL_ENCODING_I422 MMAL_FOURCC('I', '4', '2', '2') +#define MMAL_ENCODING_I422_SLICE MMAL_FOURCC('S', '4', '2', '2') +#define MMAL_ENCODING_YUYV MMAL_FOURCC('Y', 'U', 'Y', 'V') +#define MMAL_ENCODING_YVYU MMAL_FOURCC('Y', 'V', 'Y', 'U') +#define MMAL_ENCODING_UYVY MMAL_FOURCC('U', 'Y', 'V', 'Y') +#define MMAL_ENCODING_VYUY MMAL_FOURCC('V', 'Y', 'U', 'Y') +#define MMAL_ENCODING_NV12 MMAL_FOURCC('N', 'V', '1', '2') +#define MMAL_ENCODING_NV21 MMAL_FOURCC('N', 'V', '2', '1') +#define MMAL_ENCODING_ARGB MMAL_FOURCC('A', 'R', 'G', 'B') +#define MMAL_ENCODING_RGBA MMAL_FOURCC('R', 'G', 'B', 'A') +#define MMAL_ENCODING_ABGR MMAL_FOURCC('A', 'B', 'G', 'R') +#define MMAL_ENCODING_BGRA MMAL_FOURCC('B', 'G', 'R', 'A') +#define MMAL_ENCODING_RGB16 MMAL_FOURCC('R', 'G', 'B', '2') +#define MMAL_ENCODING_RGB24 MMAL_FOURCC('R', 'G', 'B', '3') +#define MMAL_ENCODING_RGB32 MMAL_FOURCC('R', 'G', 'B', '4') +#define MMAL_ENCODING_BGR16 MMAL_FOURCC('B', 'G', 'R', '2') +#define MMAL_ENCODING_BGR24 MMAL_FOURCC('B', 'G', 'R', '3') +#define MMAL_ENCODING_BGR32 MMAL_FOURCC('B', 'G', 'R', '4') + +/** SAND Video (YUVUV128) format, native format understood by VideoCore. + * This format is *not* opaque - if requested you will receive full frames + * of YUV_UV video. + */ +#define MMAL_ENCODING_YUVUV128 MMAL_FOURCC('S', 'A', 'N', 'D') + +/** VideoCore opaque image format, image handles are returned to + * the host but not the actual image data. + */ +#define MMAL_ENCODING_OPAQUE MMAL_FOURCC('O', 'P', 'Q', 'V') + +/** An EGL image handle + */ +#define MMAL_ENCODING_EGL_IMAGE MMAL_FOURCC('E', 'G', 'L', 'I') + +/* }@ */ + +/** \name Pre-defined audio encodings */ +/* @{ */ +#define MMAL_ENCODING_PCM_UNSIGNED_BE MMAL_FOURCC('P', 'C', 'M', 'U') +#define MMAL_ENCODING_PCM_UNSIGNED_LE MMAL_FOURCC('p', 'c', 'm', 'u') +#define MMAL_ENCODING_PCM_SIGNED_BE MMAL_FOURCC('P', 'C', 'M', 'S') +#define MMAL_ENCODING_PCM_SIGNED_LE MMAL_FOURCC('p', 'c', 'm', 's') +#define MMAL_ENCODING_PCM_FLOAT_BE MMAL_FOURCC('P', 'C', 'M', 'F') +#define MMAL_ENCODING_PCM_FLOAT_LE MMAL_FOURCC('p', 'c', 'm', 'f') + +/* Pre-defined H264 encoding variants */ + +/** ISO 14496-10 Annex B byte stream format */ +#define MMAL_ENCODING_VARIANT_H264_DEFAULT 0 +/** ISO 14496-15 AVC stream format */ +#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', ' ') + + +/** \defgroup MmalColorSpace List of pre-defined video color spaces + * This defines a list of common color spaces. This list isn't exhaustive and + * is only provided as a convenience to avoid clients having to use FourCC + * codes directly. However components are allowed to define and use their own + * FourCC codes. + */ +/* @{ */ + +/** Unknown color space */ +#define MMAL_COLOR_SPACE_UNKNOWN 0 +/** ITU-R BT.601-5 [SDTV] */ +#define MMAL_COLOR_SPACE_ITUR_BT601 MMAL_FOURCC('Y', '6', '0', '1') +/** ITU-R BT.709-3 [HDTV] */ +#define MMAL_COLOR_SPACE_ITUR_BT709 MMAL_FOURCC('Y', '7', '0', '9') +/** JPEG JFIF */ +#define MMAL_COLOR_SPACE_JPEG_JFIF MMAL_FOURCC('Y', 'J', 'F', 'I') +/** Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */ +#define MMAL_COLOR_SPACE_FCC MMAL_FOURCC('Y', 'F', 'C', 'C') +/** Society of Motion Picture and Television Engineers 240M (1999) */ +#define MMAL_COLOR_SPACE_SMPTE240M MMAL_FOURCC('Y', '2', '4', '0') +/** ITU-R BT.470-2 System M */ +#define MMAL_COLOR_SPACE_BT470_2_M MMAL_FOURCC('Y', '_', '_', 'M') +/** ITU-R BT.470-2 System BG */ +#define MMAL_COLOR_SPACE_BT470_2_BG MMAL_FOURCC('Y', '_', 'B', 'G') +/** JPEG JFIF, but with 16..255 luma */ +#define MMAL_COLOR_SPACE_JFIF_Y16_255 MMAL_FOURCC('Y', 'Y', '1', '6') +/* @} MmalColorSpace List */ + +#endif /* MMAL_ENCODINGS_H */ diff -Nur '--exclude=.git' linux-stable/drivers/media/platform/bcm2835/mmal-msg-common.h raspilinux/drivers/media/platform/bcm2835/mmal-msg-common.h --- linux-stable/drivers/media/platform/bcm2835/mmal-msg-common.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/media/platform/bcm2835/mmal-msg-common.h 2015-12-26 19:08:31.672617523 +0100 @@ -0,0 +1,50 @@ +/* + * Broadcom BM2835 V4L2 driver + * + * Copyright © 2013 Raspberry Pi (Trading) Ltd. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Authors: Vincent Sanders + * Dave Stevenson + * Simon Mellor + * Luke Diamand + */ + +#ifndef MMAL_MSG_COMMON_H +#define MMAL_MSG_COMMON_H + +enum mmal_msg_status { + MMAL_MSG_STATUS_SUCCESS = 0, /**< Success */ + MMAL_MSG_STATUS_ENOMEM, /**< Out of memory */ + MMAL_MSG_STATUS_ENOSPC, /**< Out of resources other than memory */ + MMAL_MSG_STATUS_EINVAL, /**< Argument is invalid */ + MMAL_MSG_STATUS_ENOSYS, /**< Function not implemented */ + MMAL_MSG_STATUS_ENOENT, /**< No such file or directory */ + MMAL_MSG_STATUS_ENXIO, /**< No such device or address */ + MMAL_MSG_STATUS_EIO, /**< I/O error */ + MMAL_MSG_STATUS_ESPIPE, /**< Illegal seek */ + MMAL_MSG_STATUS_ECORRUPT, /**< Data is corrupt \attention */ + MMAL_MSG_STATUS_ENOTREADY, /**< Component is not ready */ + MMAL_MSG_STATUS_ECONFIG, /**< Component is not configured */ + MMAL_MSG_STATUS_EISCONN, /**< Port is already connected */ + MMAL_MSG_STATUS_ENOTCONN, /**< Port is disconnected */ + MMAL_MSG_STATUS_EAGAIN, /**< Resource temporarily unavailable. */ + MMAL_MSG_STATUS_EFAULT, /**< Bad address */ +}; + +struct mmal_rect { + s32 x; /**< x coordinate (from left) */ + s32 y; /**< y coordinate (from top) */ + s32 width; /**< width */ + s32 height; /**< height */ +}; + +struct mmal_rational { + s32 num; /**< Numerator */ + s32 den; /**< Denominator */ +}; + +#endif /* MMAL_MSG_COMMON_H */ diff -Nur '--exclude=.git' linux-stable/drivers/media/platform/bcm2835/mmal-msg-format.h raspilinux/drivers/media/platform/bcm2835/mmal-msg-format.h --- linux-stable/drivers/media/platform/bcm2835/mmal-msg-format.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/media/platform/bcm2835/mmal-msg-format.h 2015-12-26 19:08:31.672617523 +0100 @@ -0,0 +1,81 @@ +/* + * Broadcom BM2835 V4L2 driver + * + * Copyright © 2013 Raspberry Pi (Trading) Ltd. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Authors: Vincent Sanders + * Dave Stevenson + * Simon Mellor + * Luke Diamand + */ + +#ifndef MMAL_MSG_FORMAT_H +#define MMAL_MSG_FORMAT_H + +#include "mmal-msg-common.h" + +/* MMAL_ES_FORMAT_T */ + + +struct mmal_audio_format { + u32 channels; /**< Number of audio channels */ + u32 sample_rate; /**< Sample rate */ + + u32 bits_per_sample; /**< Bits per sample */ + u32 block_align; /**< Size of a block of data */ +}; + +struct mmal_video_format { + u32 width; /**< Width of frame in pixels */ + u32 height; /**< Height of frame in rows of pixels */ + struct mmal_rect crop; /**< Visible region of the frame */ + struct mmal_rational frame_rate; /**< Frame rate */ + struct mmal_rational par; /**< Pixel aspect ratio */ + + /* FourCC specifying the color space of the video stream. See the + * \ref MmalColorSpace "pre-defined color spaces" for some examples. + */ + u32 color_space; +}; + +struct mmal_subpicture_format { + u32 x_offset; + u32 y_offset; +}; + +union mmal_es_specific_format { + struct mmal_audio_format audio; + struct mmal_video_format video; + struct mmal_subpicture_format subpicture; +}; + +/** Definition of an elementary stream format (MMAL_ES_FORMAT_T) */ +struct mmal_es_format { + u32 type; /* enum mmal_es_type */ + + u32 encoding; /* FourCC specifying encoding of the elementary stream.*/ + u32 encoding_variant; /* FourCC specifying the specific + * encoding variant of the elementary + * stream. + */ + + union mmal_es_specific_format *es; /* TODO: pointers in + * message serialisation?!? + */ + /* Type specific + * information for the + * elementary stream + */ + + u32 bitrate; /**< Bitrate in bits per second */ + u32 flags; /**< Flags describing properties of the elementary stream. */ + + u32 extradata_size; /**< Size of the codec specific data */ + u8 *extradata; /**< Codec specific data */ +}; + +#endif /* MMAL_MSG_FORMAT_H */ diff -Nur '--exclude=.git' linux-stable/drivers/media/platform/bcm2835/mmal-msg.h raspilinux/drivers/media/platform/bcm2835/mmal-msg.h --- linux-stable/drivers/media/platform/bcm2835/mmal-msg.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/media/platform/bcm2835/mmal-msg.h 2015-12-26 19:08:31.672617523 +0100 @@ -0,0 +1,404 @@ +/* + * Broadcom BM2835 V4L2 driver + * + * Copyright © 2013 Raspberry Pi (Trading) Ltd. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Authors: Vincent Sanders + * Dave Stevenson + * Simon Mellor + * Luke Diamand + */ + +/* all the data structures which serialise the MMAL protocol. note + * these are directly mapped onto the recived message data. + * + * BEWARE: They seem to *assume* pointers are u32 and that there is no + * structure padding! + * + * NOTE: this implementation uses kernel types to ensure sizes. Rather + * than assigning values to enums to force their size the + * implementation uses fixed size types and not the enums (though the + * comments have the actual enum type + */ + +#define VC_MMAL_VER 15 +#define VC_MMAL_MIN_VER 10 +#define VC_MMAL_SERVER_NAME MAKE_FOURCC("mmal") + +/* max total message size is 512 bytes */ +#define MMAL_MSG_MAX_SIZE 512 +/* with six 32bit header elements max payload is therefore 488 bytes */ +#define MMAL_MSG_MAX_PAYLOAD 488 + +#include "mmal-msg-common.h" +#include "mmal-msg-format.h" +#include "mmal-msg-port.h" + +enum mmal_msg_type { + MMAL_MSG_TYPE_QUIT = 1, + MMAL_MSG_TYPE_SERVICE_CLOSED, + MMAL_MSG_TYPE_GET_VERSION, + MMAL_MSG_TYPE_COMPONENT_CREATE, + MMAL_MSG_TYPE_COMPONENT_DESTROY, /* 5 */ + MMAL_MSG_TYPE_COMPONENT_ENABLE, + MMAL_MSG_TYPE_COMPONENT_DISABLE, + MMAL_MSG_TYPE_PORT_INFO_GET, + MMAL_MSG_TYPE_PORT_INFO_SET, + MMAL_MSG_TYPE_PORT_ACTION, /* 10 */ + MMAL_MSG_TYPE_BUFFER_FROM_HOST, + MMAL_MSG_TYPE_BUFFER_TO_HOST, + MMAL_MSG_TYPE_GET_STATS, + MMAL_MSG_TYPE_PORT_PARAMETER_SET, + MMAL_MSG_TYPE_PORT_PARAMETER_GET, /* 15 */ + MMAL_MSG_TYPE_EVENT_TO_HOST, + MMAL_MSG_TYPE_GET_CORE_STATS_FOR_PORT, + MMAL_MSG_TYPE_OPAQUE_ALLOCATOR, + MMAL_MSG_TYPE_CONSUME_MEM, + MMAL_MSG_TYPE_LMK, /* 20 */ + MMAL_MSG_TYPE_OPAQUE_ALLOCATOR_DESC, + MMAL_MSG_TYPE_DRM_GET_LHS32, + MMAL_MSG_TYPE_DRM_GET_TIME, + MMAL_MSG_TYPE_BUFFER_FROM_HOST_ZEROLEN, + MMAL_MSG_TYPE_PORT_FLUSH, /* 25 */ + MMAL_MSG_TYPE_HOST_LOG, + MMAL_MSG_TYPE_MSG_LAST +}; + +/* port action request messages differ depending on the action type */ +enum mmal_msg_port_action_type { + MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0, /* Unkown action */ + MMAL_MSG_PORT_ACTION_TYPE_ENABLE, /* Enable a port */ + MMAL_MSG_PORT_ACTION_TYPE_DISABLE, /* Disable a port */ + MMAL_MSG_PORT_ACTION_TYPE_FLUSH, /* Flush a port */ + MMAL_MSG_PORT_ACTION_TYPE_CONNECT, /* Connect ports */ + MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT, /* Disconnect ports */ + MMAL_MSG_PORT_ACTION_TYPE_SET_REQUIREMENTS, /* Set buffer requirements*/ +}; + +struct mmal_msg_header { + u32 magic; + u32 type; /** enum mmal_msg_type */ + + /* Opaque handle to the control service */ + struct mmal_control_service *control_service; + + struct mmal_msg_context *context; /** a u32 per message context */ + u32 status; /** The status of the vchiq operation */ + u32 padding; +}; + +/* Send from VC to host to report version */ +struct mmal_msg_version { + u32 flags; + u32 major; + u32 minor; + u32 minimum; +}; + +/* request to VC to create component */ +struct mmal_msg_component_create { + void *client_component; /* component context */ + char name[128]; + u32 pid; /* For debug */ +}; + +/* reply from VC to component creation request */ +struct mmal_msg_component_create_reply { + u32 status; /** enum mmal_msg_status - how does this differ to + * the one in the header? + */ + u32 component_handle; /* VideoCore handle for component */ + u32 input_num; /* Number of input ports */ + u32 output_num; /* Number of output ports */ + u32 clock_num; /* Number of clock ports */ +}; + +/* request to VC to destroy a component */ +struct mmal_msg_component_destroy { + u32 component_handle; +}; + +struct mmal_msg_component_destroy_reply { + u32 status; /** The component destruction status */ +}; + + +/* request and reply to VC to enable a component */ +struct mmal_msg_component_enable { + u32 component_handle; +}; + +struct mmal_msg_component_enable_reply { + u32 status; /** The component enable status */ +}; + + +/* request and reply to VC to disable a component */ +struct mmal_msg_component_disable { + u32 component_handle; +}; + +struct mmal_msg_component_disable_reply { + u32 status; /** The component disable status */ +}; + +/* request to VC to get port information */ +struct mmal_msg_port_info_get { + u32 component_handle; /* component handle port is associated with */ + u32 port_type; /* enum mmal_msg_port_type */ + u32 index; /* port index to query */ +}; + +/* reply from VC to get port info request */ +struct mmal_msg_port_info_get_reply { + u32 status; /** enum mmal_msg_status */ + u32 component_handle; /* component handle port is associated with */ + u32 port_type; /* enum mmal_msg_port_type */ + u32 port_index; /* port indexed in query */ + s32 found; /* unused */ + u32 port_handle; /**< Handle to use for this port */ + struct mmal_port port; + struct mmal_es_format format; /* elementry stream format */ + union mmal_es_specific_format es; /* es type specific data */ + u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; /* es extra data */ +}; + +/* request to VC to set port information */ +struct mmal_msg_port_info_set { + u32 component_handle; + u32 port_type; /* enum mmal_msg_port_type */ + u32 port_index; /* port indexed in query */ + struct mmal_port port; + struct mmal_es_format format; + union mmal_es_specific_format es; + u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; +}; + +/* reply from VC to port info set request */ +struct mmal_msg_port_info_set_reply { + u32 status; + u32 component_handle; /* component handle port is associated with */ + u32 port_type; /* enum mmal_msg_port_type */ + u32 index; /* port indexed in query */ + s32 found; /* unused */ + u32 port_handle; /**< Handle to use for this port */ + struct mmal_port port; + struct mmal_es_format format; + union mmal_es_specific_format es; + u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; +}; + + +/* port action requests that take a mmal_port as a parameter */ +struct mmal_msg_port_action_port { + u32 component_handle; + u32 port_handle; + u32 action; /* enum mmal_msg_port_action_type */ + struct mmal_port port; +}; + +/* port action requests that take handles as a parameter */ +struct mmal_msg_port_action_handle { + u32 component_handle; + u32 port_handle; + u32 action; /* enum mmal_msg_port_action_type */ + u32 connect_component_handle; + u32 connect_port_handle; +}; + +struct mmal_msg_port_action_reply { + u32 status; /** The port action operation status */ +}; + + + + +/* MMAL buffer transfer */ + +/** Size of space reserved in a buffer message for short messages. */ +#define MMAL_VC_SHORT_DATA 128 + +/** Signals that the current payload is the end of the stream of data */ +#define MMAL_BUFFER_HEADER_FLAG_EOS (1<<0) +/** Signals that the start of the current payload starts a frame */ +#define MMAL_BUFFER_HEADER_FLAG_FRAME_START (1<<1) +/** Signals that the end of the current payload ends a frame */ +#define MMAL_BUFFER_HEADER_FLAG_FRAME_END (1<<2) +/** Signals that the current payload contains only complete frames (>1) */ +#define MMAL_BUFFER_HEADER_FLAG_FRAME \ + (MMAL_BUFFER_HEADER_FLAG_FRAME_START|MMAL_BUFFER_HEADER_FLAG_FRAME_END) +/** Signals that the current payload is a keyframe (i.e. self decodable) */ +#define MMAL_BUFFER_HEADER_FLAG_KEYFRAME (1<<3) +/** Signals a discontinuity in the stream of data (e.g. after a seek). + * Can be used for instance by a decoder to reset its state */ +#define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY (1<<4) +/** Signals a buffer containing some kind of config data for the component + * (e.g. codec config data) */ +#define MMAL_BUFFER_HEADER_FLAG_CONFIG (1<<5) +/** Signals an encrypted payload */ +#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED (1<<6) +/** Signals a buffer containing side information */ +#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO (1<<7) +/** Signals a buffer which is the snapshot/postview image from a stills + * capture + */ +#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT (1<<8) +/** Signals a buffer which contains data known to be corrupted */ +#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED (1<<9) +/** Signals that a buffer failed to be transmitted */ +#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED (1<<10) + +struct mmal_driver_buffer { + u32 magic; + u32 component_handle; + u32 port_handle; + void *client_context; +}; + +/* buffer header */ +struct mmal_buffer_header { + struct mmal_buffer_header *next; /* next header */ + void *priv; /* framework private data */ + u32 cmd; + void *data; + u32 alloc_size; + u32 length; + u32 offset; + u32 flags; + s64 pts; + s64 dts; + void *type; + void *user_data; +}; + +struct mmal_buffer_header_type_specific { + union { + struct { + u32 planes; + u32 offset[4]; + u32 pitch[4]; + u32 flags; + } video; + } u; +}; + +struct mmal_msg_buffer_from_host { + /* The front 32 bytes of the buffer header are copied + * back to us in the reply to allow for context. This + * area is used to store two mmal_driver_buffer structures to + * allow for multiple concurrent service users. + */ + /* control data */ + struct mmal_driver_buffer drvbuf; + + /* referenced control data for passthrough buffer management */ + struct mmal_driver_buffer drvbuf_ref; + struct mmal_buffer_header buffer_header; /* buffer header itself */ + struct mmal_buffer_header_type_specific buffer_header_type_specific; + s32 is_zero_copy; + s32 has_reference; + + /** allows short data to be xfered in control message */ + u32 payload_in_message; + u8 short_data[MMAL_VC_SHORT_DATA]; +}; + + +/* port parameter setting */ + +#define MMAL_WORKER_PORT_PARAMETER_SPACE 96 + +struct mmal_msg_port_parameter_set { + u32 component_handle; /* component */ + u32 port_handle; /* port */ + u32 id; /* Parameter ID */ + u32 size; /* Parameter size */ + uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE]; +}; + +struct mmal_msg_port_parameter_set_reply { + u32 status; /** enum mmal_msg_status todo: how does this + * differ to the one in the header? + */ +}; + +/* port parameter getting */ + +struct mmal_msg_port_parameter_get { + u32 component_handle; /* component */ + u32 port_handle; /* port */ + u32 id; /* Parameter ID */ + u32 size; /* Parameter size */ +}; + +struct mmal_msg_port_parameter_get_reply { + u32 status; /* Status of mmal_port_parameter_get call */ + u32 id; /* Parameter ID */ + u32 size; /* Parameter size */ + uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE]; +}; + +/* event messages */ +#define MMAL_WORKER_EVENT_SPACE 256 + +struct mmal_msg_event_to_host { + void *client_component; /* component context */ + + u32 port_type; + u32 port_num; + + u32 cmd; + u32 length; + u8 data[MMAL_WORKER_EVENT_SPACE]; + struct mmal_buffer_header *delayed_buffer; +}; + +/* all mmal messages are serialised through this structure */ +struct mmal_msg { + /* header */ + struct mmal_msg_header h; + /* payload */ + union { + struct mmal_msg_version version; + + struct mmal_msg_component_create component_create; + struct mmal_msg_component_create_reply component_create_reply; + + struct mmal_msg_component_destroy component_destroy; + struct mmal_msg_component_destroy_reply component_destroy_reply; + + struct mmal_msg_component_enable component_enable; + struct mmal_msg_component_enable_reply component_enable_reply; + + struct mmal_msg_component_disable component_disable; + struct mmal_msg_component_disable_reply component_disable_reply; + + struct mmal_msg_port_info_get port_info_get; + struct mmal_msg_port_info_get_reply port_info_get_reply; + + struct mmal_msg_port_info_set port_info_set; + struct mmal_msg_port_info_set_reply port_info_set_reply; + + struct mmal_msg_port_action_port port_action_port; + struct mmal_msg_port_action_handle port_action_handle; + struct mmal_msg_port_action_reply port_action_reply; + + struct mmal_msg_buffer_from_host buffer_from_host; + + struct mmal_msg_port_parameter_set port_parameter_set; + struct mmal_msg_port_parameter_set_reply + port_parameter_set_reply; + struct mmal_msg_port_parameter_get + port_parameter_get; + struct mmal_msg_port_parameter_get_reply + port_parameter_get_reply; + + struct mmal_msg_event_to_host event_to_host; + + u8 payload[MMAL_MSG_MAX_PAYLOAD]; + } u; +}; diff -Nur '--exclude=.git' linux-stable/drivers/media/platform/bcm2835/mmal-msg-port.h raspilinux/drivers/media/platform/bcm2835/mmal-msg-port.h --- linux-stable/drivers/media/platform/bcm2835/mmal-msg-port.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/media/platform/bcm2835/mmal-msg-port.h 2015-12-26 19:08:31.672617523 +0100 @@ -0,0 +1,107 @@ +/* + * Broadcom BM2835 V4L2 driver + * + * Copyright © 2013 Raspberry Pi (Trading) Ltd. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Authors: Vincent Sanders + * Dave Stevenson + * Simon Mellor + * Luke Diamand + */ + +/* MMAL_PORT_TYPE_T */ +enum mmal_port_type { + MMAL_PORT_TYPE_UNKNOWN = 0, /**< Unknown port type */ + MMAL_PORT_TYPE_CONTROL, /**< Control port */ + MMAL_PORT_TYPE_INPUT, /**< Input port */ + MMAL_PORT_TYPE_OUTPUT, /**< Output port */ + MMAL_PORT_TYPE_CLOCK, /**< Clock port */ +}; + +/** The port is pass-through and doesn't need buffer headers allocated */ +#define MMAL_PORT_CAPABILITY_PASSTHROUGH 0x01 +/** The port wants to allocate the buffer payloads. + * This signals a preference that payload allocation should be done + * on this port for efficiency reasons. */ +#define MMAL_PORT_CAPABILITY_ALLOCATION 0x02 +/** The port supports format change events. + * This applies to input ports and is used to let the client know + * whether the port supports being reconfigured via a format + * change event (i.e. without having to disable the port). */ +#define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE 0x04 + +/* mmal port structure (MMAL_PORT_T) + * + * most elements are informational only, the pointer values for + * interogation messages are generally provided as additional + * strucures within the message. When used to set values only teh + * buffer_num, buffer_size and userdata parameters are writable. + */ +struct mmal_port { + void *priv; /* Private member used by the framework */ + const char *name; /* Port name. Used for debugging purposes (RO) */ + + u32 type; /* Type of the port (RO) enum mmal_port_type */ + u16 index; /* Index of the port in its type list (RO) */ + u16 index_all; /* Index of the port in the list of all ports (RO) */ + + u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */ + struct mmal_es_format *format; /* Format of the elementary stream */ + + u32 buffer_num_min; /* Minimum number of buffers the port + * requires (RO). This is set by the + * component. + */ + + u32 buffer_size_min; /* Minimum size of buffers the port + * requires (RO). This is set by the + * component. + */ + + u32 buffer_alignment_min; /* Minimum alignment requirement for + * the buffers (RO). A value of + * zero means no special alignment + * requirements. This is set by the + * component. + */ + + u32 buffer_num_recommended; /* Number of buffers the port + * recommends for optimal + * performance (RO). A value of + * zero means no special + * recommendation. This is set + * by the component. + */ + + u32 buffer_size_recommended; /* Size of buffers the port + * recommends for optimal + * performance (RO). A value of + * zero means no special + * recommendation. This is set + * by the component. + */ + + u32 buffer_num; /* Actual number of buffers the port will use. + * This is set by the client. + */ + + u32 buffer_size; /* Actual maximum size of the buffers that + * will be sent to the port. This is set by + * the client. + */ + + void *component; /* Component this port belongs to (Read Only) */ + + void *userdata; /* Field reserved for use by the client */ + + u32 capabilities; /* Flags describing the capabilities of a + * port (RO). Bitwise combination of \ref + * portcapabilities "Port capabilities" + * values. + */ + +}; diff -Nur '--exclude=.git' linux-stable/drivers/media/platform/bcm2835/mmal-parameters.h raspilinux/drivers/media/platform/bcm2835/mmal-parameters.h --- linux-stable/drivers/media/platform/bcm2835/mmal-parameters.h 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/media/platform/bcm2835/mmal-parameters.h 2015-12-26 19:08:31.672617523 +0100 @@ -0,0 +1,656 @@ +/* + * Broadcom BM2835 V4L2 driver + * + * Copyright © 2013 Raspberry Pi (Trading) Ltd. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Authors: Vincent Sanders + * Dave Stevenson + * Simon Mellor + * Luke Diamand + */ + +/* common parameters */ + +/** @name Parameter groups + * Parameters are divided into groups, and then allocated sequentially within + * a group using an enum. + * @{ + */ + +/** Common parameter ID group, used with many types of component. */ +#define MMAL_PARAMETER_GROUP_COMMON (0<<16) +/** Camera-specific parameter ID group. */ +#define MMAL_PARAMETER_GROUP_CAMERA (1<<16) +/** Video-specific parameter ID group. */ +#define MMAL_PARAMETER_GROUP_VIDEO (2<<16) +/** Audio-specific parameter ID group. */ +#define MMAL_PARAMETER_GROUP_AUDIO (3<<16) +/** Clock-specific parameter ID group. */ +#define MMAL_PARAMETER_GROUP_CLOCK (4<<16) +/** Miracast-specific parameter ID group. */ +#define MMAL_PARAMETER_GROUP_MIRACAST (5<<16) + +/* Common parameters */ +enum mmal_parameter_common_type { + MMAL_PARAMETER_UNUSED /**< Never a valid parameter ID */ + = MMAL_PARAMETER_GROUP_COMMON, + MMAL_PARAMETER_SUPPORTED_ENCODINGS, /**< MMAL_PARAMETER_ENCODING_T */ + MMAL_PARAMETER_URI, /**< MMAL_PARAMETER_URI_T */ + + /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */ + MMAL_PARAMETER_CHANGE_EVENT_REQUEST, + + /** MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_ZERO_COPY, + + /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */ + MMAL_PARAMETER_BUFFER_REQUIREMENTS, + + MMAL_PARAMETER_STATISTICS, /**< MMAL_PARAMETER_STATISTICS_T */ + MMAL_PARAMETER_CORE_STATISTICS, /**< MMAL_PARAMETER_CORE_STATISTICS_T */ + MMAL_PARAMETER_MEM_USAGE, /**< MMAL_PARAMETER_MEM_USAGE_T */ + MMAL_PARAMETER_BUFFER_FLAG_FILTER, /**< MMAL_PARAMETER_UINT32_T */ + MMAL_PARAMETER_SEEK, /**< MMAL_PARAMETER_SEEK_T */ + MMAL_PARAMETER_POWERMON_ENABLE, /**< MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_LOGGING, /**< MMAL_PARAMETER_LOGGING_T */ + MMAL_PARAMETER_SYSTEM_TIME, /**< MMAL_PARAMETER_UINT64_T */ + MMAL_PARAMETER_NO_IMAGE_PADDING /**< MMAL_PARAMETER_BOOLEAN_T */ +}; + +/* camera parameters */ + +enum mmal_parameter_camera_type { + /* 0 */ + /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */ + MMAL_PARAMETER_THUMBNAIL_CONFIGURATION + = MMAL_PARAMETER_GROUP_CAMERA, + MMAL_PARAMETER_CAPTURE_QUALITY, /**< Unused? */ + MMAL_PARAMETER_ROTATION, /**< @ref MMAL_PARAMETER_INT32_T */ + MMAL_PARAMETER_EXIF_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_EXIF, /**< @ref MMAL_PARAMETER_EXIF_T */ + MMAL_PARAMETER_AWB_MODE, /**< @ref MMAL_PARAM_AWBMODE_T */ + MMAL_PARAMETER_IMAGE_EFFECT, /**< @ref MMAL_PARAMETER_IMAGEFX_T */ + MMAL_PARAMETER_COLOUR_EFFECT, /**< @ref MMAL_PARAMETER_COLOURFX_T */ + MMAL_PARAMETER_FLICKER_AVOID, /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */ + MMAL_PARAMETER_FLASH, /**< @ref MMAL_PARAMETER_FLASH_T */ + MMAL_PARAMETER_REDEYE, /**< @ref MMAL_PARAMETER_REDEYE_T */ + MMAL_PARAMETER_FOCUS, /**< @ref MMAL_PARAMETER_FOCUS_T */ + MMAL_PARAMETER_FOCAL_LENGTHS, /**< Unused? */ + MMAL_PARAMETER_EXPOSURE_COMP, /**< @ref MMAL_PARAMETER_INT32_T */ + MMAL_PARAMETER_ZOOM, /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */ + MMAL_PARAMETER_MIRROR, /**< @ref MMAL_PARAMETER_MIRROR_T */ + + /* 0x10 */ + MMAL_PARAMETER_CAMERA_NUM, /**< @ref MMAL_PARAMETER_UINT32_T */ + MMAL_PARAMETER_CAPTURE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_EXPOSURE_MODE, /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */ + MMAL_PARAMETER_EXP_METERING_MODE, /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */ + MMAL_PARAMETER_FOCUS_STATUS, /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */ + MMAL_PARAMETER_CAMERA_CONFIG, /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */ + MMAL_PARAMETER_CAPTURE_STATUS, /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */ + MMAL_PARAMETER_FACE_TRACK, /**< @ref MMAL_PARAMETER_FACE_TRACK_T */ + MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_JPEG_Q_FACTOR, /**< @ref MMAL_PARAMETER_UINT32_T */ + MMAL_PARAMETER_FRAME_RATE, /**< @ref MMAL_PARAMETER_FRAME_RATE_T */ + MMAL_PARAMETER_USE_STC, /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */ + MMAL_PARAMETER_CAMERA_INFO, /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */ + MMAL_PARAMETER_VIDEO_STABILISATION, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_FACE_TRACK_RESULTS, /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */ + MMAL_PARAMETER_ENABLE_RAW_CAPTURE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + + /* 0x20 */ + MMAL_PARAMETER_DPF_FILE, /**< @ref MMAL_PARAMETER_URI_T */ + MMAL_PARAMETER_ENABLE_DPF_FILE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_DPF_FAIL_IS_FATAL, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_CAPTURE_MODE, /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */ + MMAL_PARAMETER_FOCUS_REGIONS, /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */ + MMAL_PARAMETER_INPUT_CROP, /**< @ref MMAL_PARAMETER_INPUT_CROP_T */ + MMAL_PARAMETER_SENSOR_INFORMATION, /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */ + MMAL_PARAMETER_FLASH_SELECT, /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */ + MMAL_PARAMETER_FIELD_OF_VIEW, /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */ + MMAL_PARAMETER_HIGH_DYNAMIC_RANGE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION, /**< @ref MMAL_PARAMETER_DRC_T */ + MMAL_PARAMETER_ALGORITHM_CONTROL, /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */ + MMAL_PARAMETER_SHARPNESS, /**< @ref MMAL_PARAMETER_RATIONAL_T */ + MMAL_PARAMETER_CONTRAST, /**< @ref MMAL_PARAMETER_RATIONAL_T */ + MMAL_PARAMETER_BRIGHTNESS, /**< @ref MMAL_PARAMETER_RATIONAL_T */ + MMAL_PARAMETER_SATURATION, /**< @ref MMAL_PARAMETER_RATIONAL_T */ + + /* 0x30 */ + MMAL_PARAMETER_ISO, /**< @ref MMAL_PARAMETER_UINT32_T */ + MMAL_PARAMETER_ANTISHAKE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + + /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */ + MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, + + /** @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_CAMERA_BURST_CAPTURE, + + /** @ref MMAL_PARAMETER_UINT32_T */ + MMAL_PARAMETER_CAMERA_MIN_ISO, + + /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */ + MMAL_PARAMETER_CAMERA_USE_CASE, + + /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_CAPTURE_STATS_PASS, + + /** @ref MMAL_PARAMETER_UINT32_T */ + MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG, + + /** @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_ENABLE_REGISTER_FILE, + + /** @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL, + + /** @ref MMAL_PARAMETER_CONFIGFILE_T */ + MMAL_PARAMETER_CONFIGFILE_REGISTERS, + + /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */ + MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS, + MMAL_PARAMETER_JPEG_ATTACH_LOG, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_ZERO_SHUTTER_LAG, /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */ + MMAL_PARAMETER_FPS_RANGE, /**< @ref MMAL_PARAMETER_FPS_RANGE_T */ + MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP, /**< @ref MMAL_PARAMETER_INT32_T */ + + /* 0x40 */ + 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_CUSTOM_AWB_GAINS, /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */ +}; + +struct mmal_parameter_rational { + s32 num; /**< Numerator */ + s32 den; /**< Denominator */ +}; + +enum mmal_parameter_camera_config_timestamp_mode { + MMAL_PARAM_TIMESTAMP_MODE_ZERO = 0, /* Always timestamp frames as 0 */ + MMAL_PARAM_TIMESTAMP_MODE_RAW_STC, /* Use the raw STC value + * for the frame timestamp + */ + MMAL_PARAM_TIMESTAMP_MODE_RESET_STC, /* Use the STC timestamp + * but subtract the + * timestamp of the first + * frame sent to give a + * zero based timestamp. + */ +}; + +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 */ + u32 max_stills_w; /* Max size of stills capture */ + u32 max_stills_h; + u32 stills_yuv422; /* Allow YUV422 stills capture */ + u32 one_shot_stills; /* Continuous or one shot stills captures. */ + + u32 max_preview_video_w; /* Max size of the preview or video + * capture frames + */ + u32 max_preview_video_h; + u32 num_preview_video_frames; + + /** Sets the height of the circular buffer for stills capture. */ + u32 stills_capture_circular_buffer_height; + + /** Allows preview/encode to resume as fast as possible after the stills + * input frame has been received, and then processes the still frame in + * the background whilst preview/encode has resumed. + * Actual mode is controlled by MMAL_PARAMETER_CAPTURE_MODE. + */ + u32 fast_preview_resume; + + /** Selects algorithm for timestamping frames if + * there is no clock component connected. + * enum mmal_parameter_camera_config_timestamp_mode + */ + s32 use_stc_timestamp; +}; + + +enum mmal_parameter_exposuremode { + MMAL_PARAM_EXPOSUREMODE_OFF, + MMAL_PARAM_EXPOSUREMODE_AUTO, + MMAL_PARAM_EXPOSUREMODE_NIGHT, + MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW, + MMAL_PARAM_EXPOSUREMODE_BACKLIGHT, + MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT, + MMAL_PARAM_EXPOSUREMODE_SPORTS, + MMAL_PARAM_EXPOSUREMODE_SNOW, + MMAL_PARAM_EXPOSUREMODE_BEACH, + MMAL_PARAM_EXPOSUREMODE_VERYLONG, + MMAL_PARAM_EXPOSUREMODE_FIXEDFPS, + MMAL_PARAM_EXPOSUREMODE_ANTISHAKE, + MMAL_PARAM_EXPOSUREMODE_FIREWORKS, +}; + +enum mmal_parameter_exposuremeteringmode { + MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE, + MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT, + MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT, + MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX, +}; + +enum mmal_parameter_awbmode { + MMAL_PARAM_AWBMODE_OFF, + MMAL_PARAM_AWBMODE_AUTO, + MMAL_PARAM_AWBMODE_SUNLIGHT, + MMAL_PARAM_AWBMODE_CLOUDY, + MMAL_PARAM_AWBMODE_SHADE, + MMAL_PARAM_AWBMODE_TUNGSTEN, + MMAL_PARAM_AWBMODE_FLUORESCENT, + MMAL_PARAM_AWBMODE_INCANDESCENT, + MMAL_PARAM_AWBMODE_FLASH, + MMAL_PARAM_AWBMODE_HORIZON, +}; + +enum mmal_parameter_imagefx { + MMAL_PARAM_IMAGEFX_NONE, + MMAL_PARAM_IMAGEFX_NEGATIVE, + MMAL_PARAM_IMAGEFX_SOLARIZE, + MMAL_PARAM_IMAGEFX_POSTERIZE, + MMAL_PARAM_IMAGEFX_WHITEBOARD, + MMAL_PARAM_IMAGEFX_BLACKBOARD, + MMAL_PARAM_IMAGEFX_SKETCH, + MMAL_PARAM_IMAGEFX_DENOISE, + MMAL_PARAM_IMAGEFX_EMBOSS, + MMAL_PARAM_IMAGEFX_OILPAINT, + MMAL_PARAM_IMAGEFX_HATCH, + MMAL_PARAM_IMAGEFX_GPEN, + MMAL_PARAM_IMAGEFX_PASTEL, + MMAL_PARAM_IMAGEFX_WATERCOLOUR, + MMAL_PARAM_IMAGEFX_FILM, + MMAL_PARAM_IMAGEFX_BLUR, + MMAL_PARAM_IMAGEFX_SATURATION, + MMAL_PARAM_IMAGEFX_COLOURSWAP, + MMAL_PARAM_IMAGEFX_WASHEDOUT, + MMAL_PARAM_IMAGEFX_POSTERISE, + MMAL_PARAM_IMAGEFX_COLOURPOINT, + MMAL_PARAM_IMAGEFX_COLOURBALANCE, + MMAL_PARAM_IMAGEFX_CARTOON, +}; + +enum MMAL_PARAM_FLICKERAVOID_T { + MMAL_PARAM_FLICKERAVOID_OFF, + MMAL_PARAM_FLICKERAVOID_AUTO, + MMAL_PARAM_FLICKERAVOID_50HZ, + MMAL_PARAM_FLICKERAVOID_60HZ, + 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, + MMAL_VIDEO_RATECONTROL_VARIABLE, + MMAL_VIDEO_RATECONTROL_CONSTANT, + MMAL_VIDEO_RATECONTROL_VARIABLE_SKIP_FRAMES, + 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 { + /** @ref MMAL_DISPLAYREGION_T */ + MMAL_PARAMETER_DISPLAYREGION = MMAL_PARAMETER_GROUP_VIDEO, + + /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */ + MMAL_PARAMETER_SUPPORTED_PROFILES, + + /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */ + MMAL_PARAMETER_PROFILE, + + /** @ref MMAL_PARAMETER_UINT32_T */ + MMAL_PARAMETER_INTRAPERIOD, + + /** @ref MMAL_PARAMETER_VIDEO_RATECONTROL_T */ + MMAL_PARAMETER_RATECONTROL, + + /** @ref MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T */ + MMAL_PARAMETER_NALUNITFORMAT, + + /** @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_MINIMISE_FRAGMENTATION, + + /** @ref MMAL_PARAMETER_UINT32_T. + * Setting the value to zero resets to the default (one slice per frame). + */ + MMAL_PARAMETER_MB_ROWS_PER_SLICE, + + /** @ref MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T */ + MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION, + + /** @ref MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T */ + MMAL_PARAMETER_VIDEO_EEDE_ENABLE, + + /** @ref MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T */ + MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE, + + /** @ref MMAL_PARAMETER_BOOLEAN_T. Request an I-frame. */ + MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME, + /** @ref MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T */ + MMAL_PARAMETER_VIDEO_INTRA_REFRESH, + + /** @ref MMAL_PARAMETER_BOOLEAN_T. */ + MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, + + /** @ref MMAL_PARAMETER_UINT32_T. Run-time bit rate control */ + MMAL_PARAMETER_VIDEO_BIT_RATE, + + /** @ref MMAL_PARAMETER_FRAME_RATE_T */ + MMAL_PARAMETER_VIDEO_FRAME_RATE, + + /** @ref MMAL_PARAMETER_UINT32_T. */ + MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, + + /** @ref MMAL_PARAMETER_UINT32_T. */ + MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, + + /** @ref MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T. */ + MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL, + + MMAL_PARAMETER_EXTRA_BUFFERS, /**< @ref MMAL_PARAMETER_UINT32_T. */ + /** @ref MMAL_PARAMETER_UINT32_T. + * Changing this parameter from the default can reduce frame rate + * because image buffers need to be re-pitched. + */ + MMAL_PARAMETER_VIDEO_ALIGN_HORIZ, + + /** @ref MMAL_PARAMETER_UINT32_T. + * Changing this parameter from the default can reduce frame rate + * because image buffers need to be re-pitched. + */ + MMAL_PARAMETER_VIDEO_ALIGN_VERT, + + /** @ref MMAL_PARAMETER_BOOLEAN_T. */ + MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES, + + /** @ref MMAL_PARAMETER_UINT32_T. */ + MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, + + /**< @ref MMAL_PARAMETER_UINT32_T. */ + MMAL_PARAMETER_VIDEO_ENCODE_QP_P, + + /**< @ref MMAL_PARAMETER_UINT32_T. */ + MMAL_PARAMETER_VIDEO_ENCODE_RC_SLICE_DQUANT, + + /** @ref MMAL_PARAMETER_UINT32_T */ + MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS, + + /** @ref MMAL_PARAMETER_UINT32_T. */ + MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE, + + /* H264 specific parameters */ + + /** @ref MMAL_PARAMETER_BOOLEAN_T. */ + MMAL_PARAMETER_VIDEO_ENCODE_H264_DISABLE_CABAC, + + /** @ref MMAL_PARAMETER_BOOLEAN_T. */ + MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_LATENCY, + + /** @ref MMAL_PARAMETER_BOOLEAN_T. */ + MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS, + + /** @ref MMAL_PARAMETER_UINT32_T. */ + MMAL_PARAMETER_VIDEO_ENCODE_H264_DEBLOCK_IDC, + + /** @ref MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T. */ + MMAL_PARAMETER_VIDEO_ENCODE_H264_MB_INTRA_MODE, + + /** @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN, + + /** @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_VIDEO_ENCODE_PRECODE_FOR_QP, + + /** @ref MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T. */ + MMAL_PARAMETER_VIDEO_DRM_INIT_INFO, + + /** @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO, + + /** @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT, + + /** @ref MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T. */ + MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER, + + /** @ref MMAL_PARAMETER_BYTES_T */ + MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3, + + /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_VIDEO_ENCODE_H264_VCL_HRD_PARAMETERS, + + /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG, + + /**< @ref MMAL_PARAMETER_BOOLEAN_T */ + MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER +}; + +/** Valid mirror modes */ +enum mmal_parameter_mirror { + MMAL_PARAM_MIRROR_NONE, + MMAL_PARAM_MIRROR_VERTICAL, + MMAL_PARAM_MIRROR_HORIZONTAL, + MMAL_PARAM_MIRROR_BOTH, +}; + +enum mmal_parameter_displaytransform { + MMAL_DISPLAY_ROT0 = 0, + MMAL_DISPLAY_MIRROR_ROT0 = 1, + MMAL_DISPLAY_MIRROR_ROT180 = 2, + MMAL_DISPLAY_ROT180 = 3, + MMAL_DISPLAY_MIRROR_ROT90 = 4, + MMAL_DISPLAY_ROT270 = 5, + MMAL_DISPLAY_ROT90 = 6, + MMAL_DISPLAY_MIRROR_ROT270 = 7, +}; + +enum mmal_parameter_displaymode { + MMAL_DISPLAY_MODE_FILL = 0, + MMAL_DISPLAY_MODE_LETTERBOX = 1, +}; + +enum mmal_parameter_displayset { + MMAL_DISPLAY_SET_NONE = 0, + MMAL_DISPLAY_SET_NUM = 1, + MMAL_DISPLAY_SET_FULLSCREEN = 2, + MMAL_DISPLAY_SET_TRANSFORM = 4, + MMAL_DISPLAY_SET_DEST_RECT = 8, + MMAL_DISPLAY_SET_SRC_RECT = 0x10, + MMAL_DISPLAY_SET_MODE = 0x20, + MMAL_DISPLAY_SET_PIXEL = 0x40, + MMAL_DISPLAY_SET_NOASPECT = 0x80, + MMAL_DISPLAY_SET_LAYER = 0x100, + MMAL_DISPLAY_SET_COPYPROTECT = 0x200, + MMAL_DISPLAY_SET_ALPHA = 0x400, +}; + +struct mmal_parameter_displayregion { + /** Bitfield that indicates which fields are set and should be + * used. All other fields will maintain their current value. + * \ref MMAL_DISPLAYSET_T defines the bits that can be + * combined. + */ + u32 set; + + /** Describes the display output device, with 0 typically + * being a directly connected LCD display. The actual values + * will depend on the hardware. Code using hard-wired numbers + * (e.g. 2) is certain to fail. + */ + + u32 display_num; + /** Indicates that we are using the full device screen area, + * rather than a window of the display. If zero, then + * dest_rect is used to specify a region of the display to + * use. + */ + + s32 fullscreen; + /** Indicates any rotation or flipping used to map frames onto + * the natural display orientation. + */ + u32 transform; /* enum mmal_parameter_displaytransform */ + + /** Where to display the frame within the screen, if + * fullscreen is zero. + */ + struct vchiq_mmal_rect dest_rect; + + /** Indicates which area of the frame to display. If all + * values are zero, the whole frame will be used. + */ + struct vchiq_mmal_rect src_rect; + + /** If set to non-zero, indicates that any display scaling + * should disregard the aspect ratio of the frame region being + * displayed. + */ + s32 noaspect; + + /** Indicates how the image should be scaled to fit the + * display. \code MMAL_DISPLAY_MODE_FILL \endcode indicates + * that the image should fill the screen by potentially + * cropping the frames. Setting \code mode \endcode to \code + * MMAL_DISPLAY_MODE_LETTERBOX \endcode indicates that all the + * source region should be displayed and black bars added if + * necessary. + */ + u32 mode; /* enum mmal_parameter_displaymode */ + + /** If non-zero, defines the width of a source pixel relative + * to \code pixel_y \endcode. If zero, then pixels default to + * being square. + */ + u32 pixel_x; + + /** If non-zero, defines the height of a source pixel relative + * to \code pixel_x \endcode. If zero, then pixels default to + * being square. + */ + u32 pixel_y; + + /** Sets the relative depth of the images, with greater values + * being in front of smaller values. + */ + u32 layer; + + /** Set to non-zero to ensure copy protection is used on + * output. + */ + s32 copyprotect_required; + + /** Level of opacity of the layer, where zero is fully + * transparent and 255 is fully opaque. + */ + u32 alpha; +}; + +#define MMAL_MAX_IMAGEFX_PARAMETERS 5 + +struct mmal_parameter_imagefx_parameters { + enum mmal_parameter_imagefx effect; + u32 num_effect_params; + u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS]; +}; diff -Nur '--exclude=.git' linux-stable/drivers/media/platform/bcm2835/mmal-vchiq.c raspilinux/drivers/media/platform/bcm2835/mmal-vchiq.c --- linux-stable/drivers/media/platform/bcm2835/mmal-vchiq.c 1970-01-01 01:00:00.000000000 +0100 +++ raspilinux/drivers/media/platform/bcm2835/mmal-vchiq.c 2015-12-26 19:08:31.672617523 +0100 @@ -0,0 +1,1916 @@ +/* + * Broadcom BM2835 V4L2 driver + * + * Copyright © 2013 Raspberry Pi (Trading) Ltd. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Authors: Vincent Sanders + * Dave Stevenson + * Simon Mellor + * Luke Diamand + * + * V4L2 driver MMAL vchiq interface code + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mmal-common.h" +#include "mmal-vchiq.h" +#include "mmal-msg.h" + +#define USE_VCHIQ_ARM +#include "interface/vchi/vchi.h" + +/* maximum number of components supported */ +#define VCHIQ_MMAL_MAX_COMPONENTS 4 + +/*#define FULL_MSG_DUMP 1*/ + +#ifdef DEBUG +static const char *const msg_type_names[] = { + "UNKNOWN", + "QUIT", + "SERVICE_CLOSED", + "GET_VERSION", + "COMPONENT_CREATE", + "COMPONENT_DESTROY", + "COMPONENT_ENABLE", + "COMPONENT_DISABLE", + "PORT_INFO_GET", + "PORT_INFO_SET", + "PORT_ACTION", + "BUFFER_FROM_HOST", + "BUFFER_TO_HOST", + "GET_STATS", + "PORT_PARAMETER_SET", + "PORT_PARAMETER_GET", + "EVENT_TO_HOST", + "GET_CORE_STATS_FOR_PORT", + "OPAQUE_ALLOCATOR", + "CONSUME_MEM", + "LMK", + "OPAQUE_ALLOCATOR_DESC", + "DRM_GET_LHS32", + "DRM_GET_TIME", + "BUFFER_FROM_HOST_ZEROLEN", + "PORT_FLUSH", + "HOST_LOG", +}; +#endif + +static const char *const port_action_type_names[] = { + "UNKNOWN", + "ENABLE", + "DISABLE", + "FLUSH", + "CONNECT", + "DISCONNECT", + "SET_REQUIREMENTS", +}; + +#if defined(DEBUG) +#if defined(FULL_MSG_DUMP) +#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE) \ + do { \ + pr_debug(TITLE" type:%s(%d) length:%d\n", \ + msg_type_names[(MSG)->h.type], \ + (MSG)->h.type, (MSG_LEN)); \ + print_hex_dump(KERN_DEBUG, "<h.type], \ + (MSG)->h.type, (MSG_LEN)); \ + } +#endif +#else +#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE) +#endif + +/* normal message context */ +struct mmal_msg_context { + union { + struct { + /* work struct for defered callback - must come first */ + struct work_struct work; + /* mmal instance */ + struct vchiq_mmal_instance *instance; + /* mmal port */ + struct vchiq_mmal_port *port; + /* actual buffer used to store bulk reply */ + struct mmal_buffer *buffer; + /* amount of buffer used */ + unsigned long buffer_used; + /* MMAL buffer flags */ + u32 mmal_flags; + /* Presentation and Decode timestamps */ + s64 pts; + s64 dts; + + int status; /* context status */ + + } bulk; /* bulk data */ + + struct { + /* message handle to release */ + VCHI_HELD_MSG_T msg_handle; + /* pointer to received message */ + struct mmal_msg *msg; + /* received message length */ + u32 msg_len; + /* completion upon reply */ + struct completion cmplt; + } sync; /* synchronous response */ + } u; + +}; + +struct vchiq_mmal_instance { + VCHI_SERVICE_HANDLE_T handle; + + /* ensure serialised access to service */ + struct mutex vchiq_mutex; + + /* ensure serialised access to bulk operations */ + struct mutex bulk_mutex; + + /* vmalloc page to receive scratch bulk xfers into */ + void *bulk_scratch; + + /* component to use next */ + int component_idx; + struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS]; +}; + +static struct mmal_msg_context *get_msg_context(struct vchiq_mmal_instance + *instance) +{ + struct mmal_msg_context *msg_context; + + /* todo: should this be allocated from a pool to avoid kmalloc */ + msg_context = kmalloc(sizeof(*msg_context), GFP_KERNEL); + memset(msg_context, 0, sizeof(*msg_context)); + + return msg_context; +} + +static void release_msg_context(struct mmal_msg_context *msg_context) +{ + kfree(msg_context); +} + +/* deals with receipt of event to host message */ +static void event_to_host_cb(struct vchiq_mmal_instance *instance, + struct mmal_msg *msg, u32 msg_len) +{ + pr_debug("unhandled event\n"); + pr_debug("component:%p port type:%d num:%d cmd:0x%x length:%d\n", + msg->u.event_to_host.client_component, + msg->u.event_to_host.port_type, + msg->u.event_to_host.port_num, + msg->u.event_to_host.cmd, msg->u.event_to_host.length); +} + +/* workqueue scheduled callback + * + * we do this because it is important we do not call any other vchiq + * sync calls from witin the message delivery thread + */ +static void buffer_work_cb(struct work_struct *work) +{ + struct mmal_msg_context *msg_context = (struct mmal_msg_context *)work; + + msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance, + msg_context->u.bulk.port, + msg_context->u.bulk.status, + msg_context->u.bulk.buffer, + msg_context->u.bulk.buffer_used, + msg_context->u.bulk.mmal_flags, + msg_context->u.bulk.dts, + msg_context->u.bulk.pts); + + /* release message context */ + release_msg_context(msg_context); +} + +/* enqueue a bulk receive for a given message context */ +static int bulk_receive(struct vchiq_mmal_instance *instance, + struct mmal_msg *msg, + struct mmal_msg_context *msg_context) +{ + unsigned long rd_len; + unsigned long flags = 0; + int ret; + + /* bulk mutex stops other bulk operations while we have a + * receive in progress - released in callback + */ + ret = mutex_lock_interruptible(&instance->bulk_mutex); + if (ret != 0) + return ret; + + rd_len = msg->u.buffer_from_host.buffer_header.length; + + /* take buffer from queue */ + spin_lock_irqsave(&msg_context->u.bulk.port->slock, flags); + if (list_empty(&msg_context->u.bulk.port->buffers)) { + spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags); + pr_err("buffer list empty trying to submit bulk receive\n"); + + /* todo: this is a serious error, we should never have + * commited a buffer_to_host operation to the mmal + * port without the buffer to back it up (underflow + * handling) and there is no obvious way to deal with + * this - how is the mmal servie going to react when + * we fail to do the xfer and reschedule a buffer when + * it arrives? perhaps a starved flag to indicate a + * waiting bulk receive? + */ + + mutex_unlock(&instance->bulk_mutex); + + return -EINVAL; + } + + msg_context->u.bulk.buffer = + list_entry(msg_context->u.bulk.port->buffers.next, + struct mmal_buffer, list); + list_del(&msg_context->u.bulk.buffer->list); + + spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags); + + /* ensure we do not overrun the available buffer */ + if (rd_len > msg_context->u.bulk.buffer->buffer_size) { + rd_len = msg_context->u.bulk.buffer->buffer_size; + pr_warn("short read as not enough receive buffer space\n"); + /* todo: is this the correct response, what happens to + * the rest of the message data? + */ + } + + /* store length */ + msg_context->u.bulk.buffer_used = rd_len; + msg_context->u.bulk.mmal_flags = + msg->u.buffer_from_host.buffer_header.flags; + msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts; + msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts; + + // only need to flush L1 cache here, as VCHIQ takes care of the L2 + // cache. + __cpuc_flush_dcache_area(msg_context->u.bulk.buffer->buffer, rd_len); + + /* queue the bulk submission */ + vchi_service_use(instance->handle); + ret = vchi_bulk_queue_receive(instance->handle, + msg_context->u.bulk.buffer->buffer, + /* Actual receive needs to be a multiple + * of 4 bytes + */ + (rd_len + 3) & ~3, + VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | + VCHI_FLAGS_BLOCK_UNTIL_QUEUED, + msg_context); + + vchi_service_release(instance->handle); + + if (ret != 0) { + /* callback will not be clearing the mutex */ + mutex_unlock(&instance->bulk_mutex); + } + + return ret; +} + +/* enque a dummy bulk receive for a given message context */ +static int dummy_bulk_receive(struct vchiq_mmal_instance *instance, + struct mmal_msg_context *msg_context) +{ + int ret; + + /* bulk mutex stops other bulk operations while we have a + * receive in progress - released in callback + */ + ret = mutex_lock_interruptible(&instance->bulk_mutex); + if (ret != 0) + return ret; + + /* zero length indicates this was a dummy transfer */ + msg_context->u.bulk.buffer_used = 0; + + /* queue the bulk submission */ + vchi_service_use(instance->handle); + + ret = vchi_bulk_queue_receive(instance->handle, + instance->bulk_scratch, + 8, + VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | + VCHI_FLAGS_BLOCK_UNTIL_QUEUED, + msg_context); + + vchi_service_release(instance->handle); + + if (ret != 0) { + /* callback will not be clearing the mutex */ + mutex_unlock(&instance->bulk_mutex); + } + + return ret; +} + +/* data in message, memcpy from packet into output buffer */ +static int inline_receive(struct vchiq_mmal_instance *instance, + struct mmal_msg *msg, + struct mmal_msg_context *msg_context) +{ + unsigned long flags = 0; + + /* take buffer from queue */ + spin_lock_irqsave(&msg_context->u.bulk.port->slock, flags); + if (list_empty(&msg_context->u.bulk.port->buffers)) { + spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags); + pr_err("buffer list empty trying to receive inline\n"); + + /* todo: this is a serious error, we should never have + * commited a buffer_to_host operation to the mmal + * port without the buffer to back it up (with + * underflow handling) and there is no obvious way to + * deal with this. Less bad than the bulk case as we + * can just drop this on the floor but...unhelpful + */ + return -EINVAL; + } + + msg_context->u.bulk.buffer = + list_entry(msg_context->u.bulk.port->buffers.next, + struct mmal_buffer, list); + list_del(&msg_context->u.bulk.buffer->list); + + spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags); + + memcpy(msg_context->u.bulk.buffer->buffer, + msg->u.buffer_from_host.short_data, + msg->u.buffer_from_host.payload_in_message); + + msg_context->u.bulk.buffer_used = + msg->u.buffer_from_host.payload_in_message; + + return 0; +} + +/* queue the buffer availability with MMAL_MSG_TYPE_BUFFER_FROM_HOST */ +static int +buffer_from_host(struct vchiq_mmal_instance *instance, + struct vchiq_mmal_port *port, struct mmal_buffer *buf) +{ + struct mmal_msg_context *msg_context; + struct mmal_msg m; + int ret; + + pr_debug("instance:%p buffer:%p\n", instance->handle, buf); + + /* bulk mutex stops other bulk operations while we + * have a receive in progress + */ + if (mutex_lock_interruptible(&instance->bulk_mutex)) + return -EINTR; + + /* get context */ + msg_context = get_msg_context(instance); + if (msg_context == NULL) + return -ENOMEM; + + /* store bulk message context for when data arrives */ + msg_context->u.bul