From a706eb240d93f8932fa84142c7d3a967d5e9c032 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 5 May 2016 20:36:09 -0500 Subject: [PATCH 01/21] ev3dev: cumulative ev3dev changes to arm arch code This contains all of the changes to /arch/arm/ from the ev3dev v3.16 kernel branch. --- .../boot/dts/da850-lego-ev3-adafruit18.dts | 37 + arch/arm/boot/dts/da850-lego-ev3-color.dts | 37 + arch/arm/boot/dts/da850-lego-ev3-lms2012.dts | 549 +++++++++++ arch/arm/boot/dts/ti/davinci/Makefile | 5 +- .../boot/dts/ti/davinci/da850-lego-ev3.dts | 493 +++++++++- arch/arm/configs/ev3dev_defconfig | 346 +++++++ arch/arm/include/asm/fiq.h | 4 + arch/arm/kernel/fiq.c | 87 ++ arch/arm/mach-davinci/Kconfig | 18 + arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/legoev3-dt.c | 146 +++ arch/arm/mach-davinci/legoev3-fiq.c | 914 ++++++++++++++++++ arch/arm/mach-davinci/legoev3-fiq.h | 69 ++ localversion | 1 + 14 files changed, 2704 insertions(+), 5 deletions(-) create mode 100644 arch/arm/boot/dts/da850-lego-ev3-adafruit18.dts create mode 100644 arch/arm/boot/dts/da850-lego-ev3-color.dts create mode 100644 arch/arm/boot/dts/da850-lego-ev3-lms2012.dts create mode 100644 arch/arm/configs/ev3dev_defconfig create mode 100644 arch/arm/mach-davinci/legoev3-dt.c create mode 100644 arch/arm/mach-davinci/legoev3-fiq.c create mode 100644 arch/arm/mach-davinci/legoev3-fiq.h create mode 120000 localversion diff --git a/arch/arm/boot/dts/da850-lego-ev3-adafruit18.dts b/arch/arm/boot/dts/da850-lego-ev3-adafruit18.dts new file mode 100644 index 0000000000000..2f55df8ee149a --- /dev/null +++ b/arch/arm/boot/dts/da850-lego-ev3-adafruit18.dts @@ -0,0 +1,37 @@ +/* + * Device tree for LEGO MINDSTORMS EV3 with Adafruit 1.8" Color TFT + * + * Copyright (C) 2018 David Lechner + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, version 2. + */ + +#include "da850-lego-ev3.dts" + +/ { + backlight: backlight { + compatible = "gpio-backlight"; + gpios = <&gpio 44 GPIO_ACTIVE_HIGH>; + }; +}; + +&spi1 { + /delete-property/cs-gpios; + + display@0 { + status = "disabled"; + }; + + display@1{ + compatible = "jianda,jd-t18003-t01"; + /* not actually using CS */ + reg = <1>; + spi-max-frequency = <32000000>; + dc-gpios = <&gpio 43 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio 80 GPIO_ACTIVE_HIGH>; + backlight = <&backlight>; + rotation = <270>; + }; +}; diff --git a/arch/arm/boot/dts/da850-lego-ev3-color.dts b/arch/arm/boot/dts/da850-lego-ev3-color.dts new file mode 100644 index 0000000000000..845d9abc90945 --- /dev/null +++ b/arch/arm/boot/dts/da850-lego-ev3-color.dts @@ -0,0 +1,37 @@ +/* + * Device tree for LEGO MINDSTORMS EV3 with Adafruit 1.8" Color TFT + * + * Copyright (C) 2018 David Lechner + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, version 2. + */ + +#include "da850-lego-ev3.dts" + +/ { + backlight: backlight { + compatible = "gpio-backlight"; + gpios = <&gpio 44 GPIO_ACTIVE_HIGH>; + }; +}; + +&spi1 { + /delete-property/cs-gpios; + + display@0 { + status = "disabled"; + }; + + display@1{ + compatible = "jianda,jd-t18003-t01"; + /* not actually using CS */ + reg = <1>; + spi-max-frequency = <32000000>; + dc-gpios = <&gpio 43 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio 80 GPIO_ACTIVE_HIGH>; + backlight = <&backlight>; + rotation = <90>; + }; +}; diff --git a/arch/arm/boot/dts/da850-lego-ev3-lms2012.dts b/arch/arm/boot/dts/da850-lego-ev3-lms2012.dts new file mode 100644 index 0000000000000..2736c72a59f71 --- /dev/null +++ b/arch/arm/boot/dts/da850-lego-ev3-lms2012.dts @@ -0,0 +1,549 @@ +/* + * Device tree for LEGO MINDSTORMS EV3 + lms2012-compat + * + * Copyright (C) 2016 David Lechner + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, version 2. + */ + +/dts-v1/; +#include +#include +#include + +#include "da850.dtsi" + +/ { + compatible = "lego,ev3", "ti,da850"; + model = "LEGO MINDSTORMS EV3 + lms2012-compat"; + + aliases { + serial0 = &serial0; + serial1 = &serial1; + serial2 = &serial2; + }; + + memory@c0000000 { + device_type = "memory"; + reg = <0xc0000000 0x04000000>; + }; + + /* + * The buttons on the EV3 are mapped to keyboard keys. + */ + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + label = "EV3 brick buttons"; + + pinctrl-0 = <&button_pinmux>, <&button_pinconf>; + pinctrl-names = "default"; + + center { + label = "Center"; + linux,code = ; + gpios = <&gpio 29 GPIO_ACTIVE_HIGH>; + }; + left { + label = "Left"; + linux,code = ; + gpios = <&gpio 102 GPIO_ACTIVE_HIGH>; + }; + back { + label = "Back"; + linux,code = ; + gpios = <&gpio 106 GPIO_ACTIVE_HIGH>; + }; + right { + label = "Right"; + linux,code = ; + gpios = <&gpio 124 GPIO_ACTIVE_HIGH>; + }; + down { + label = "Down"; + linux,code = ; + gpios = <&gpio 126 GPIO_ACTIVE_HIGH>; + }; + up { + label = "Up"; + linux,code = ; + gpios = <&gpio 127 GPIO_ACTIVE_HIGH>; + }; + }; + + /* + * The EV3 has two built-in bi-color LEDs behind the buttons. + */ + leds { + compatible = "gpio-leds"; + + left_green { + label = "led0:green:brick-status"; + /* GP6[13] */ + gpios = <&gpio 103 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + }; + + right_red { + label = "led1:red:brick-status"; + /* GP6[7] */ + gpios = <&gpio 108 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + }; + + left_red { + label = "led0:red:brick-status"; + /* GP6[12] */ + gpios = <&gpio 109 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + }; + + right_green { + label = "led1:green:brick-status"; + /* GP6[14] */ + gpios = <&gpio 110 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + }; + }; + + /* + * The EV3 is powered down by turning off the main 5V supply. + */ + gpio-poweroff { + compatible = "gpio-poweroff"; + gpios = <&gpio 107 GPIO_ACTIVE_LOW>; + }; + + /* + * This is a 5V current limiting regulator that is shared by USB, + * the sensor (input) ports, the motor (output) ports and the ADC. + */ + vcc5v: regulator1 { + compatible = "regulator-fixed"; + regulator-name = "vcc5v"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio 101 0>; + over-current-gpios = <&gpio 99 GPIO_ACTIVE_LOW>; + enable-active-high; + regulator-boot-on; + }; + + /* + * This is a simple voltage divider on VCC5V to provide a 2.5V + * reference signal to the ADC. + */ + adc_ref: regulator2 { + compatible = "regulator-fixed"; + regulator-name = "adc_ref"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-boot-on; + vin-supply = <&vcc5v>; + }; + + sound { + compatible = "ev3dev,ev3-sound"; + label = "LEGO MINDSTORMS EV3 Speaker"; + enable-gpios = <&gpio 111 GPIO_ACTIVE_HIGH>; + pwms = <&ehrpwm0 1 1 PWM_POLARITY_INVERTED>; + pwm-names = "speaker"; + }; + + /* Dummy devices to handle input pin mux */ + + lms2012_compat_in1: lms2012-compat-in1 { + compatible = "ev3dev,lms2012-compat-in-port"; + #in-port-cells = <0>; + pinctrl-names = "default", "i2c"; + pinctrl-0 = <&in1_uart_pins>; + pinctrl-1 = <&in1_i2c_pins>; + }; + + lms2012_compat_in2: lms2012-compat-in2 { + compatible = "ev3dev,lms2012-compat-in-port"; + #in-port-cells = <0>; + pinctrl-names = "default", "i2c"; + pinctrl-0 = <&in2_uart_pins>; + pinctrl-1 = <&in2_i2c_pins>; + }; + + lms2012_compat_in3: lms2012-compat-in3 { + compatible = "ev3dev,lms2012-compat-in-port"; + #in-port-cells = <0>; + pinctrl-names = "default", "i2c"; + pinctrl-0 = <&in3_uart_pins>; + pinctrl-1 = <&in3_i2c_pins>; + }; + + lms2012_compat_in4: lms2012-compat-in4 { + compatible = "ev3dev,lms2012-compat-in-port"; + #in-port-cells = <0>; + pinctrl-names = "default", "i2c"; + pinctrl-0 = <&in4_uart_pins>; + pinctrl-1 = <&in4_i2c_pins>; + }; + + lms2012_compat: lms2012-compat { + compatible = "ev3dev,lms2012-compat"; + + /* MOSI, MISO, CLK, CS */ + spi-gpios = <&gpio 133 0>, <&gpio 134 0>, <&gpio 24 0>, + <&gpio 130 0>; + + /* IN PIN1 x 4, PIN6 x 4, OUT PIN5 x 4, N/C, N/C, BATT_I, BATT_V */ + adc-channels = <6 8 10 12 5 7 9 11 1 0 13 14 15 2 3 4>; + + /* ADCBATEN, SW_RECHARGE */ + adc-gpios = <&gpio 6 0>, <&gpio 136 0>; + + /* PIN1 */ + in1-pin1-gpios = <&gpio 138 0>; + in2-pin1-gpios = <&gpio 140 0>; + in3-pin1-gpios = <&gpio 137 0>; + in4-pin1-gpios = <&gpio 100 0>; + + /* PIN2 */ + in1-pin2-gpios = <&gpio 34 0>; + in2-pin2-gpios = <&gpio 143 0>; + in3-pin2-gpios = <&gpio 123 0>; + in4-pin2-gpios = <&gpio 120 0>; + + /* PIN5, PIN6, BUF_ENA */ + in1-gpios = <&gpio 2 0>, <&gpio 15 0>, <&gpio 139 0>; + in2-gpios = <&gpio 14 0>, <&gpio 13 0>, <&gpio 142 0>; + in3-gpios = <&gpio 12 0>, <&gpio 30 0>, <&gpio 121 0>; + in4-gpios = <&gpio 1 0>, <&gpio 31 0>, <&gpio 122 0>; + + /* IN1, IN2, IN3, IN4 */ + in-tty-names = "ttyS1", "ttyS0", "ttySU1", "ttySU0"; + + /* IN1, IN2, IN3, IN4 */ + in-i2cs = <3>, <4>, <5>, <6>; + + /* IN1, IN2, IN3, IN4 */ + in-in-ports = <&lms2012_compat_in1>, <&lms2012_compat_in2>, + <&lms2012_compat_in3>, <&lms2012_compat_in4>; + + /* PIN1, PIN2, PIN5W, PIN5R, PIN6 */ + outA-gpios = <&gpio 63 0>, <&gpio 54 0>, <&gpio 84 0>, + <&gpio 91 GPIO_ACTIVE_LOW>, + <&gpio 4 GPIO_ACTIVE_LOW>; + outB-gpios = <&gpio 33 0>, <&gpio 3 0>, <&gpio 37 0>, + <&gpio 88 GPIO_ACTIVE_LOW>, + <&gpio 41 GPIO_ACTIVE_LOW>; + outC-gpios = <&gpio 104 0>, <&gpio 89 0>, <&gpio 56 0>, + <&gpio 93 GPIO_ACTIVE_LOW>, + <&gpio 62 GPIO_ACTIVE_LOW>; + outD-gpios = <&gpio 83 0>, <&gpio 90 0>, <&gpio 95 0>, + <&gpio 105 GPIO_ACTIVE_LOW>, + <&gpio 40 GPIO_ACTIVE_LOW>; + + /* Using 13.2 kHz to match official firmware */ + pwms = <&ehrpwm1 1 75758 PWM_POLARITY_INVERTED>, + <&ehrpwm1 0 75758 PWM_POLARITY_INVERTED>, + <&ecap0 0 75758 PWM_POLARITY_INVERTED>, + <&ecap1 0 75758 PWM_POLARITY_INVERTED>; + pwm-names = "outA", "outB", "outC", "outD"; + }; +}; + +&pmx_core { + status = "okay"; + pinctrl-0 = <&fixed_pins>; + pinctrl-names = "default"; + + in1_uart_pins: pinmux-in1-uart { + pinctrl-single,bits = < + /* UART1_TXD */ + 0x10 0x20000000 0xf0000000 + >; + }; + + in1_i2c_pins: pinmux-in1-i2c { + pinctrl-single,bits = < + /* GP1[0] */ + 0x10 0x80000000 0xf0000000 + >; + }; + + in2_uart_pins: pinmux-in2-uart { + pinctrl-single,bits = < + /* UART0_TXD */ + 0x0c 0x00200000 0x00f00000 + >; + }; + + in2_i2c_pins: pinmux-in2-i2c { + pinctrl-single,bits = < + /* GP8[3] */ + 0x0c 0x00400000 0x00f00000 + >; + }; + + in3_uart_pins: pinmux-in3-uart { + pinctrl-single,bits = < + /* AXR4 */ + 0x08 0x00001000 0x0000f000 + >; + }; + + in3_i2c_pins: pinmux-in3-i2c { + pinctrl-single,bits = < + /* GP1[12] */ + 0x08 0x00004000 0x0000f000 + >; + }; + + in4_uart_pins: pinmux-in4-uart { + pinctrl-single,bits = < + /* AXR3 */ + 0x08 0x00010000 0x000f0000 + >; + }; + + in4_i2c_pins: pinmux-in4-i2c { + pinctrl-single,bits = < + /* GP1[11] */ + 0x08 0x00040000 0x000f0000 + >; + }; + + button_pinmux: pinmux-buttons { + pinctrl-single,bits = < + /* + * GP1[13] + */ + 0x08 0x00000400 0x00000f00 + /* + * GP6[10] + */ + 0x34 0x00800000 0x00f00000 + /* + * GP6[6] + */ + 0x38 0x00000080 0x000000f0 + /* + * GP7[12], GP7[14], GP7[15] + */ + 0x40 0x00808800 0x00f0ff00 + >; + }; + + fixed_pins: pinmux-fixed { + pinctrl-single,bits = < + /* + * UART2_CTS, UART2_RTS, AHCLKX, AHCLKR, GP0[12], + * GP0[13], GP0[14], GP0[15] + */ + 0x00 0x44118888 0xffffffff + /* + * ECAP1_AWPWM, GP0[1], GP0[2], GP0[3], GP0[4], GP0[5], + * GP0[6], ECAP2_APWM2 + */ + 0x04 0x48888884 0xffffffff + /* + * ECAP0_APWM0, AXR1, AXR2, GP1[14], GP1[15] + */ + 0x08 0x21100048 0xfff000ff + /* + * GP8[2], UART0_RXD, GP8[5], GP8[6], EPWM0B, GP1[8] + */ + 0x0c 0x04024424 0x0f0fffff + /* + * UART1_RXD, UART2_TXD, UART2_RXD, I2C0_SDA, I2C0_SCL, + * SPI0_SCS[0] + */ + 0x10 0x02222210 0x0ffffff0 + /* + * GP2[8], GP2[9], SPI1_SIMO, GP2[11], GP2[12], + * SPI1_CLK, EPWM1B, EPWM1A + */ + 0x14 0x88188122 0xffffffff + /* + * GP2[0], GP2[1], GP2[2], GP2[5], GP2[7] + */ + 0x18 0x88800808 0xfff00f0f + /* + * GP3[8], GP3[14], GP3[15] + */ + 0x1c 0x80000088 0xf00000ff + /* + * GP3[2], GP3[3], GP3[4], GP3[5], GP3[6] + */ + 0x20 0x00888880 0x00fffff0 + /* + * GP4[9], GP4[10], GP4[14] + */ + 0x24 0x08800080 0x0ff000f0 + /* + * MMCSD0_DAT[3], MMCSD0_DAT[2], MMCSD0_DAT[1], + * MMCSD0_DAT[0], MMCSD0_CMD, MMCSD0_CLK + */ + 0x28 0x00222222 0x00ffffff + /* + * GP5[8], GP5[9], GP5[10], GP5[11], GP5[13], GP5[14], + * GP5[15] + */ + 0x2c 0x88880888 0xffff0fff + /* + * GP5[0], GP5[2], GP5[3], GP5[4], GP5[7] + */ + 0x30 0x80888008 0xf0fff00f + /* + * GP6[8], GP6[9], GP6[11], GP6[12], GP6[13], GP6[14], + * GP6[15] + */ + 0x34 0x88088888 0xff0fffff + /* + * GP6[7] + */ + 0x38 0x00000008 0x0000000f + /* + * GP7[10], GP7[11], GP6[5] + */ + 0x40 0x88000080 0xff0000f0 + /* + * BOOT2, BOOT3, BOOT4, BOOT5, BOOT6, BOOT7, GP7[8], + * GP7[9] + */ + 0x44 0x00000088 0xffffffff + /* + * GP8[10], GP8[11], GP8[12], GP8[14], GP8[15], BOOT0, + * BOOT1 + */ + 0x48 0x88808800 0xfff0ffff + /* + * RTCK, GP6[2], GP6[3], GP6[4], GP8[8], GP8[9] + */ + 0x4c 0x00088888 0xf00fffff + >; + }; +}; + +&pinconf { + status = "okay"; + pinctrl-0 = <&pinconf_bias_groups>; + pinctrl-names = "default"; + + pinconf_bias_groups: bias-groups { + disable { + groups = "cp0", "cp1", "cp2", "cp3", "cp4", + "cp6", "cp7", "cp8", "cp9", "cp10", "cp11", + "cp12", "cp13", "cp14", "cp15", "cp16", "cp17", + "cp18", "cp19", "cp20", "cp21", "cp22", "cp23", + "cp26", "cp27", "cp29", "cp30", "cp31"; + bias-disable; + }; + }; + + /* + * Buttons have external pull down resistors, so bias has to be disabled + * in order for them to work correctly. + */ + button_pinconf: buttons { + disable { + groups = "cp5", "cp24", "cp25", "cp28"; + bias-disable; + }; + }; +}; + +&serial0 { + #tty-cells = <0>; + status = "okay"; +}; + +&serial1 { + #tty-cells = <0>; + status = "okay"; +}; + +/* Bluetooth */ +&serial2 { + status = "okay"; + auto-flow-control; +}; + +&rtc0 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + clock-frequency = <400000>; + + /* + * EEPROM contains the first stage bootloader, HW ID and Bluetooth MAC. + */ + eeprom@50 { + compatible = "at24,24c128"; + pagesize = <64>; + read-only; + reg = <0x50>; + }; +}; + +&wdt { + status = "okay"; +}; + +&mmc0 { + status = "okay"; + max-frequency = <50000000>; + bus-width = <4>; + cd-gpios = <&gpio 94 GPIO_ACTIVE_LOW>; +}; + +&ehrpwm0 { + status = "okay"; +}; + +&ehrpwm1 { + status = "okay"; +}; + +&ecap0 { + status = "okay"; +}; + +&ecap1 { + status = "okay"; +}; + +&ecap2 { + status = "okay"; +}; + +&spi1 { + status = "okay"; + cs-gpios = <&gpio 44 GPIO_ACTIVE_LOW>; + + lcd@0 { + compatible = "lego,ev3-lcd"; + reg = <0>; + spi-max-frequency = <10000000>; + rst-gpios = <&gpio 80 GPIO_ACTIVE_LOW>; + a0-gpios = <&gpio 43 GPIO_ACTIVE_HIGH>; + }; +}; + +&gpio { + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; + vbus-supply = <&vcc5v>; +}; diff --git a/arch/arm/boot/dts/ti/davinci/Makefile b/arch/arm/boot/dts/ti/davinci/Makefile index c0e388eb3dd1d..6ee548b29e14c 100644 --- a/arch/arm/boot/dts/ti/davinci/Makefile +++ b/arch/arm/boot/dts/ti/davinci/Makefile @@ -3,4 +3,7 @@ dtb-$(CONFIG_ARCH_DAVINCI) += \ da850-lcdk.dtb \ da850-enbw-cmc.dtb \ da850-evm.dtb \ - da850-lego-ev3.dtb + da850-lego-ev3.dtb \ + da850-lego-ev3-adafruit18.dtb \ + da850-lego-ev3-color.dtb \ + da850-lego-ev3-lms2012.dtb diff --git a/arch/arm/boot/dts/ti/davinci/da850-lego-ev3.dts b/arch/arm/boot/dts/ti/davinci/da850-lego-ev3.dts index 173401c58d534..bea8b79e9d3e5 100644 --- a/arch/arm/boot/dts/ti/davinci/da850-lego-ev3.dts +++ b/arch/arm/boot/dts/ti/davinci/da850-lego-ev3.dts @@ -17,7 +17,9 @@ model = "LEGO MINDSTORMS EV3"; aliases { + serial0 = &serial0; serial1 = &serial1; + serial2 = &serial2; }; memory@c0000000 { @@ -25,6 +27,176 @@ reg = <0xc0000000 0x04000000>; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + pru_suart_reserved: serial@80000000 { + compatible = "shared-dma-pool"; + reg = <0x80000000 0x2000>; + no-map; + }; + + }; + + soc@1c00000 { + pru_rproc: remote-processor@30000 { + compatible = "ev3dev,da850-pruss"; + ranges = <0x0 0x30000 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + + power-domains = <&psc0 13>; + + pru_intc: intc { + compatible = "ev3dev,da850-pru-intc"; + reg = <0x4000 0x3000>; + interrupts = <3>, <4>, <5>, <6>, <7>, <8>, <9>, + <10>; + interrupt-controller; + #interrupt-cells = <3>; + }; + + pru0: pru0 { + status = "disabled"; + compatible = "ev3dev,da850-pru-rproc"; + reg = <0x0 0x200>, <0x7000 0x400>, + <0x8000 0x1000>; + reg-names = "dram", "ctrl", "iram"; + interrupt-parent = <&pru_intc>; + interrupts = <63 0xffffffff 0>, + <62 0xffffffff 2>; + interrupt-names = "vq-to-pru", "vq-from-pru"; + }; + + pru1: pru1 { + compatible = "ev3dev,da850-pru-rproc"; + reg = <0x2000 0x200>, <0x7800 0x400>, + <0xc000 0x1000>; + reg-names = "dram", "ctrl", "iram"; + interrupt-parent = <&pru_intc>; + interrupts = <61 0xffffffff 1>, + <60 0xffffffff 4>; + interrupt-names = "vq-to-pru", "vq-from-pru"; + firmware = "ev3-pru1.fw"; + + vdevs { + #address-cells = <1>; + #size-cells = <0>; + + rpmsg@0 { + compatible = "virtio,rpmsg"; + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + tacho: ev3-tacho-rpmsg@0 { + compatible = "ev3dev,ev3-pru-tacho"; + reg = <0>; + #io-channel-cells = <1>; + + /* hacking in LED pwm with tacho for now */ + pwm-gpios = <&gpio 103 GPIO_ACTIVE_HIGH>, + <&gpio 108 GPIO_ACTIVE_HIGH>, + <&gpio 109 GPIO_ACTIVE_HIGH>, + <&gpio 110 GPIO_ACTIVE_HIGH>; + }; + + i2c@3 { + compatible = "ev3dev,ev3-pru-i2c"; + reg = <3>; + }; + + i2c@4 { + compatible = "ev3dev,ev3-pru-i2c"; + reg = <4>; + }; + + i2c@5 { + compatible = "ev3dev,ev3-pru-i2c"; + reg = <5>; + }; + + i2c@6 { + compatible = "ev3dev,ev3-pru-i2c"; + reg = <6>; + }; + }; + }; + }; + }; + + pru_suart: serial@30000 { + compatible = "ev3dev,omapl-pru-suart"; + reg = <0x30000 0x200>, <0x37000 0x400>, <0x38000 0x1000>, + //<0x32000 0x200>, <0x37800 0x400>, <0x3c000 0x1000>, + <0x100000 0x3000>; + reg-names = "pru0-dram", "pru0-ctrl", "pru0-iram", + //"pru1-dram", "pru1-ctrl", "pru1-iram", + "mcasp"; + + clocks = <&psc0 13>, <&psc1 7>; + clock-names = "pruss", "mcasp"; + + interrupt-parent = <&pru_intc>; + interrupts = <31 0xffffffff 0>, + <32 0xffffffff 0>, + //<33 0xffffffff 1>, + <34 0xffffffff 2>, + <35 0xffffffff 2>, + <36 0xffffffff 3>, + <37 0xffffffff 3>; + //<38 0xffffffff 4>, + //<39 0xffffffff 4>, + //<40 0xffffffff 5>, + //<41 0xffffffff 5>, + //<42 0xffffffff 6>, + //<33 0xffffffff 6>, + //<34 0xffffffff 7>, + //<45 0xffffffff 7>, + //<46 0xffffffff 8>, + //<47 0xffffffff 8>, + //<48 0xffffffff 9>, + //<49 0xffffffff 9>, + //<50 0xffffffff 1>; + interrupt-names = "mcasp", + "arm-to-pru0", + //"arm-to-pru1", + "suart0-tx", + "suart0-rx", + "suart1-tx", + "suart1-rx"; + //"suart2-tx", + //"suart2-rx", + //"suart3-tx", + //"suart3-rx", + //"suart4-tx", + //"suart4-rx", + //"suart5-tx", + //"suart5-rx", + //"suart6-tx", + //"suart6-rx", + //"suart7-tx", + //"suart7-rx", + //"pru-to-pru"; + memory-region = <&pru_suart_reserved>; + }; + }; + + board { + pinctrl-0 = <&hw_id_pinconf>; + pinctrl-names = "default"; + compatible = "lego,ev3-board"; + hw-id-gpios = <&gpio 53 GPIO_ACTIVE_HIGH>, /* HWID0 */ + <&gpio 52 GPIO_ACTIVE_HIGH>, /* HWID1 */ + <&gpio 50 GPIO_ACTIVE_HIGH>, /* HWID2 */ + <&gpio 74 GPIO_ACTIVE_HIGH>; /* HWID3 */ + + nvmem-cells = <&hw_id>; + nvmem-cell-names = "hw-id"; + }; + /* * The buttons on the EV3 are mapped to keyboard keys. */ @@ -75,6 +247,7 @@ * The EV3 has two built-in bi-color LEDs behind the buttons. */ leds { + status = "disabled"; compatible = "gpio-leds"; left_green { @@ -115,11 +288,13 @@ }; sound { - compatible = "pwm-beeper"; + compatible = "ev3dev,ev3-sound"; pinctrl-names = "default"; pinctrl-0 = <&ehrpwm0b_pins>; + label = "LEGO MINDSTORMS EV3 Speaker"; + enable-gpios = <&gpio 111 GPIO_ACTIVE_HIGH>; pwms = <&ehrpwm0 1 1000000 0>; - amp-supply = <&>; + pwm-names = "speaker"; }; cvdd: regulator0 { @@ -163,6 +338,7 @@ * This is the amplifier for the speaker. */ amp: regulator3 { + status = "disabled"; compatible = "regulator-fixed"; regulator-name = "amp"; gpio = <&gpio 111 GPIO_ACTIVE_HIGH>; @@ -179,6 +355,166 @@ rechargeable-gpios = <&gpio 136 GPIO_ACTIVE_LOW>; }; + ev3_ports: ev3-ports { + compatible = "ev3dev,ev3-ports"; + + in1 { + pinctrl-names = "default", "i2c", "uart"; + pinctrl-0 = <&in1_pins>, <&in1_i2c_pins>; + pinctrl-1 = <&in1_pins>, <&in1_i2c_pins>; + pinctrl-2 = <&in1_pins>, <&in1_uart_pins>; + + compatible = "ev3dev,ev3-input-port"; + io-channels = <&adc 6>, <&adc 5>; + io-channel-names = "pin1", "pin6"; + pin1-gpios = <&gpio 138 0>; + pin2-gpios = <&gpio 34 0>; + pin5-gpios = <&gpio 2 0>; + pin6-gpios = <&gpio 15 0>; + buf-ena-gpios = <&gpio 139 GPIO_ACTIVE_LOW>; + ev3dev,tty-name = "ttyS1"; + ev3dev,i2c-adapter = <3>; + }; + + in2 { + pinctrl-names = "default", "i2c", "uart"; + pinctrl-0 = <&in2_pins>, <&in2_i2c_pins>; + pinctrl-1 = <&in2_pins>, <&in2_i2c_pins>; + pinctrl-2 = <&in2_pins>, <&in2_uart_pins>; + + compatible = "ev3dev,ev3-input-port"; + io-channels = <&adc 8>, <&adc 7>; + io-channel-names = "pin1", "pin6"; + pin1-gpios = <&gpio 140 0>; + pin2-gpios = <&gpio 143 0>; + pin5-gpios = <&gpio 14 0>; + pin6-gpios = <&gpio 13 0>; + buf-ena-gpios = <&gpio 142 GPIO_ACTIVE_LOW>; + ev3dev,tty-name = "ttyS0"; + ev3dev,i2c-adapter = <4>; + }; + + in3 { + pinctrl-names = "default", "i2c", "uart"; + pinctrl-0 = <&in3_pins>, <&in3_i2c_pins>; + pinctrl-1 = <&in3_pins>, <&in3_i2c_pins>; + pinctrl-2 = <&in3_pins>, <&in3_uart_pins>; + + compatible = "ev3dev,ev3-input-port"; + io-channels = <&adc 10>, <&adc 9>; + io-channel-names = "pin1", "pin6"; + pin1-gpios = <&gpio 137 0>; + pin2-gpios = <&gpio 123 0>; + pin5-gpios = <&gpio 12 0>; + pin6-gpios = <&gpio 30 0>; + buf-ena-gpios = <&gpio 121 GPIO_ACTIVE_LOW>; + ev3dev,tty-name = "ttySU1"; + ev3dev,i2c-adapter = <5>; + }; + + in4 { + pinctrl-names = "default", "i2c", "uart"; + pinctrl-0 = <&in4_pins>, <&in4_i2c_pins>; + pinctrl-1 = <&in4_pins>, <&in4_i2c_pins>; + pinctrl-2 = <&in4_pins>, <&in4_uart_pins>; + + compatible = "ev3dev,ev3-input-port"; + io-channels = <&adc 12>, <&adc 11>; + io-channel-names = "pin1", "pin6"; + pin1-gpios = <&gpio 100 0>; + pin2-gpios = <&gpio 120 0>; + pin5-gpios = <&gpio 1 0>; + pin6-gpios = <&gpio 31 0>; + buf-ena-gpios = <&gpio 122 GPIO_ACTIVE_LOW>; + ev3dev,tty-name = "ttySU0"; + ev3dev,i2c-adapter = <6>; + }; + + outA { + pinctrl-names = "default"; + pinctrl-0 = <&ehrpwm1b_pins>; + + compatible = "ev3dev,ev3-output-port"; + io-channels = <&adc 1>; + io-channel-names = "pin5"; + pin1-gpios = <&gpio 63 0>; + pin2-gpios = <&gpio 54 0>; + pin5-det-gpios = <&gpio 84 0>; + pin5-gpios = <&gpio 91 GPIO_ACTIVE_LOW>; + pin6-gpios = <&gpio 4 GPIO_ACTIVE_LOW>; + pwms = <&ehrpwm1 1 75758 PWM_POLARITY_INVERTED>; + pwm-names = "motor"; + + motor { + io-channels = <&tacho 0>, <&tacho 1>; + io-channel-names = "count", "rate"; + }; + }; + + outB { + pinctrl-names = "default"; + pinctrl-0 = <&ehrpwm1a_pins>; + + compatible = "ev3dev,ev3-output-port"; + io-channels = <&adc 0>; + io-channel-names = "pin5"; + pin1-gpios = <&gpio 33 0>; + pin2-gpios = <&gpio 3 0>; + pin5-det-gpios = <&gpio 37 0>; + pin5-gpios = <&gpio 88 GPIO_ACTIVE_LOW>; + pin6-gpios = <&gpio 41 GPIO_ACTIVE_LOW>; + pwms = <&ehrpwm1 0 75758 PWM_POLARITY_INVERTED>; + pwm-names = "motor"; + + motor { + io-channels = <&tacho 2>, <&tacho 3>; + io-channel-names = "count", "rate"; + }; + }; + + outC { + pinctrl-names = "default"; + pinctrl-0 = <&ecap0_pins>; + + compatible = "ev3dev,ev3-output-port"; + io-channels = <&adc 13>; + io-channel-names = "pin5"; + pin1-gpios = <&gpio 104 0>; + pin2-gpios = <&gpio 89 0>; + pin5-det-gpios = <&gpio 56 0>; + pin5-gpios = <&gpio 93 GPIO_ACTIVE_LOW>; + pin6-gpios = <&gpio 62 GPIO_ACTIVE_LOW>; + pwms = <&ecap0 0 75758 PWM_POLARITY_INVERTED>; + pwm-names = "motor"; + + motor { + io-channels = <&tacho 4>, <&tacho 5>; + io-channel-names = "count", "rate"; + }; + }; + + outD { + pinctrl-names = "default"; + pinctrl-0 = <&ecap1_pins>; + + compatible = "ev3dev,ev3-output-port"; + io-channels = <&adc 14>; + io-channel-names = "pin5"; + pin1-gpios = <&gpio 83 0>; + pin2-gpios = <&gpio 90 0>; + pin5-det-gpios = <&gpio 95 0>; + pin5-gpios = <&gpio 105 GPIO_ACTIVE_LOW>; + pin6-gpios = <&gpio 40 GPIO_ACTIVE_LOW>; + pwms = <&ecap1 0 75758 PWM_POLARITY_INVERTED>; + pwm-names = "motor"; + + motor { + io-channels = <&tacho 6>, <&tacho 7>; + io-channel-names = "count", "rate"; + }; + }; + }; + bt_slow_clk: bt-clock { pinctrl-names = "default"; pinctrl-0 = <&ecap2_pins>, <&bt_clock_bias>; @@ -232,6 +568,8 @@ }; &pmx_core { + pinctrl-0 = <&fixed_pins>; + pinctrl-names = "default"; status = "okay"; ev3_lcd_pins: lcd-pins { @@ -240,11 +578,128 @@ 0x14 0x00100100 0x00f00f00 >; }; + + fixed_pins: pinmux-fixed { + pinctrl-single,bits = < + /* + * AHCLKX, AHCLKR + */ + 0x00 0x00110000 0x00ff0000 + /* + * GP2[0] + */ + 0x18 0x80000000 0xf0000000 + /* + * GP5[2] + */ + 0x30 0x00800000 0x00f00000 + /* + * RTCK, GP6[2] + */ + 0x4c 0x00080000 0xf00f0000 + >; + }; + in1_pins: pinmux-in1 { + pinctrl-single,bits = < + /* UART1_RXD */ + 0x10 0x02000000 0x0f000000 + >; + }; + + in1_uart_pins: pinmux-in1-uart { + pinctrl-single,bits = < + /* UART1_TXD */ + 0x10 0x20000000 0xf0000000 + >; + }; + + in1_i2c_pins: pinmux-in1-i2c { + pinctrl-single,bits = < + /* GP1[0] */ + 0x10 0x80000000 0xf0000000 + >; + }; + + in2_pins: pinmux-in2 { + pinctrl-single,bits = < + /* UART0_RXD */ + 0x0c 0x00020000 0x000f0000 + >; + }; + + in2_uart_pins: pinmux-in2-uart { + pinctrl-single,bits = < + /* UART0_TXD */ + 0x0c 0x00200000 0x00f00000 + >; + }; + + in2_i2c_pins: pinmux-in2-i2c { + pinctrl-single,bits = < + /* GP8[3] */ + 0x0c 0x00400000 0x00f00000 + >; + }; + + in3_pins: pinmux-in3 { + pinctrl-single,bits = < + /* AXR2 */ + 0x08 0x00100000 0x00f00000 + >; + }; + + in3_uart_pins: pinmux-in3-uart { + pinctrl-single,bits = < + /* AXR4 */ + 0x08 0x00001000 0x0000f000 + >; + }; + + in3_i2c_pins: pinmux-in3-i2c { + pinctrl-single,bits = < + /* GP1[12] */ + 0x08 0x00004000 0x0000f000 + >; + }; + + in4_pins: pinmux-in4 { + pinctrl-single,bits = < + /* AXR1 */ + 0x08 0x01000000 0x0f000000 + >; + }; + + in4_uart_pins: pinmux-in4-uart { + pinctrl-single,bits = < + /* AXR3 */ + 0x08 0x00010000 0x000f0000 + >; + }; + + in4_i2c_pins: pinmux-in4-i2c { + pinctrl-single,bits = < + /* GP1[11] */ + 0x08 0x00040000 0x000f0000 + >; + }; }; &pinconf { + pinctrl-0 = <&pinconf_bias_groups>; + pinctrl-names = "default"; status = "okay"; + pinconf_bias_groups: bias-groups { + disable { + groups = "cp0", "cp1", "cp3", "cp4", + "cp6", "cp7", "cp8", "cp9", "cp10", "cp11", + "cp12", "cp13", "cp14", "cp15", "cp16", + "cp18", "cp19", "cp21", "cp22", "cp23", + "cp26", "cp27", "cp29", "cp30", "cp31"; + bias-disable; + }; + }; + /* Buttons have external pulldown resistors */ button_bias: button-bias-groups { disable { @@ -266,13 +721,25 @@ bias-disable; }; }; + + hw_id_pinconf: hw-id { + disable { + groups = "cp17"; + bias-disable; + }; + }; +}; + +/* Input port 2 */ +&serial0 { + #tty-cells = <0>; + status = "okay"; }; /* Input port 1 */ &serial1 { + #tty-cells = <0>; status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&serial1_rxtx_pins>; }; &serial2 { @@ -312,6 +779,11 @@ #address-cells = <1>; #size-cells = <1>; + /* Hardware ID + Bluetooth MAC address */ + hw_id: hw-id@0x3F00 { + reg = <0x3F00 12>; + }; + bdaddr: bdaddr@3f06 { reg = <0x3f06 0x06>; }; @@ -337,6 +809,7 @@ pinctrl-0 = <&spi0_pins>, <&spi0_cs0_pin>, <&spi0_cs3_pin>; flash@0 { + status = "disabled"; compatible = "n25q128a13", "jedec,spi-nor"; reg = <0>; spi-max-frequency = <50000000>; @@ -400,6 +873,14 @@ }; }; +&ecap0 { + status = "okay"; +}; + +&ecap1 { + status = "okay"; +}; + &ecap2 { status = "okay"; }; @@ -408,6 +889,10 @@ status = "okay"; }; +&ehrpwm1 { + status = "okay"; +}; + &gpio { status = "okay"; diff --git a/arch/arm/configs/ev3dev_defconfig b/arch/arm/configs/ev3dev_defconfig new file mode 100644 index 0000000000000..faf51733d6ff8 --- /dev/null +++ b/arch/arm/configs/ev3dev_defconfig @@ -0,0 +1,346 @@ +CONFIG_LOCALVERSION="-ev3" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_CGROUPS=y +CONFIG_NAMESPACES=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y +CONFIG_ARCH_DAVINCI=y +CONFIG_ARCH_DAVINCI_DA850=y +# CONFIG_MACH_DAVINCI_DA850_EVM is not set +CONFIG_MACH_DAVINCI_LEGOEV3=y +CONFIG_LEGOEV3_FIQ=y +CONFIG_AEABI=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CPU_IDLE=y +# CONFIG_SUSPEND is not set +CONFIG_PM=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_EFI_PARTITION is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ZSMALLOC=y +CONFIG_PGTABLE_MAPPING=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_BRIDGE=m +CONFIG_BT=y +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_HIDP=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_LL=y +CONFIG_CFG80211=m +CONFIG_MAC80211=m +CONFIG_MAC80211_DEBUG_MENU=y +CONFIG_RFKILL=y +# CONFIG_UEVENT_HELPER is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_EXTRA_FIRMWARE="PRU_SUART.bin ev3-pru1.fw" +CONFIG_EXTRA_FIRMWARE_DIR="drivers/lego/ev3/firmware" +CONFIG_LEGO_DRIVERS=y +CONFIG_LEGOEV3_I2C=y +CONFIG_LEGOEV3_SOUND=y +CONFIG_NXT_ANALOG_SENSORS=m +CONFIG_EV3_ANALOG_SENSORS=m +CONFIG_NXT_I2C_SENSORS=m +CONFIG_EV3_UART_SENSORS=m +CONFIG_LEGO_SERVO_MOTORS=m +CONFIG_LMS2012_COMPAT=m +CONFIG_WEDO=m +CONFIG_BRICKPI=m +CONFIG_BOARD_INFO=y +CONFIG_SERIAL_SUART_OMAPL_PRU=y +CONFIG_TI_PRU_RPROC_EV3DEV=y +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_ZRAM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=4 +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_93CX6=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=m +CONFIG_CHR_DEV_SG=y +CONFIG_NETDEVICES=y +CONFIG_TUN=m +# CONFIG_ETHERNET is not set +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_NET_CDC_EEM=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_NET1080 is not set +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_IPHETH=m +CONFIG_ATH9K_HTC=m +CONFIG_AR5523=m +CONFIG_MT7601U=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_RTL8187=m +# CONFIG_RTL_CARDS is not set +CONFIG_RTL8192CU=m +CONFIG_RTL8XXXU=m +CONFIG_USB_ZD1201=m +CONFIG_ZD1211RW=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_GPIO_POLLED=y +CONFIG_KEYBOARD_XTKBD=m +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=m +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=3 +CONFIG_SERIAL_8250_RUNTIME_UARTS=3 +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_DEV_BUS=y +CONFIG_TTY_PRINTK=y +CONFIG_HW_RANDOM=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_DAVINCI=y +CONFIG_SPI=y +CONFIG_SPI_DAVINCI=y +CONFIG_PINCTRL_DA850_PUPD=y +CONFIG_PINCTRL_SINGLE=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCF857X=m +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_BATTERY_LEGO_EV3=y +CONFIG_HWMON=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_PCF8591=m +CONFIG_WATCHDOG=y +CONFIG_DAVINCI_WATCHDOG=y +CONFIG_SSB=m +CONFIG_TPS6507X=m +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_GPIO=y +CONFIG_RC_CORE=m +CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_STV06XX=m +CONFIG_USB_GSPCA_SPCA561=m +CONFIG_USB_GSPCA_ZC3XX=m +CONFIG_DRM=y +CONFIG_DRM_TINYDRM=y +CONFIG_TINYDRM_ST7586=y +CONFIG_TINYDRM_ST7735R=y +CONFIG_BACKLIGHT_GPIO=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +# CONFIG_LOGO_LINUX_CLUT224 is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_HRTIMER=m +# CONFIG_SND_VERBOSE_PROCFS is not set +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_VIRMIDI=m +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=m +CONFIG_HID_BATTERY_STRENGTH=y +CONFIG_HIDRAW=y +CONFIG_HID_SONY=m +CONFIG_SONY_FF=y +CONFIG_HID_WIIMOTE=m +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_MON=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_ACM=m +CONFIG_USB_STORAGE=y +CONFIG_USBIP_CORE=m +CONFIG_USBIP_VHCI_HCD=m +CONFIG_USBIP_HOST=m +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_GADGET=y +CONFIG_USB_MUSB_DA8XX=y +CONFIG_MUSB_PIO_ONLY=y +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_LEGOTOWER=m +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_CONFIGFS=m +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_ACM=y +CONFIG_USB_CONFIGFS_OBEX=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_EEM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_UAC1=y +CONFIG_USB_CONFIGFS_F_UAC2=y +CONFIG_USB_CONFIGFS_F_MIDI=y +CONFIG_USB_CONFIGFS_F_HID=y +CONFIG_USB_CONFIGFS_F_UVC=y +CONFIG_USB_CONFIGFS_F_PRINTER=y +CONFIG_USB_ETH=m +CONFIG_USB_ETH_EEM=y +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_USB_MIDI_GADGET=m +CONFIG_USB_CDC_COMPOSITE=m +CONFIG_MMC=y +CONFIG_MMC_DAVINCI=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_LEDS_TRIGGER_TRANSIENT=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set +CONFIG_RTC_DRV_DS1307=m +CONFIG_DMADEVICES=y +CONFIG_STAGING=y +CONFIG_R8712U=y +CONFIG_FB_TFT=y +CONFIG_FB_TFT_ST7735R=y +CONFIG_COMMON_CLK_PWM=y +CONFIG_RPMSG_CHAR=m +CONFIG_IIO=y +CONFIG_IIO_BUFFER_CB=y +CONFIG_IIO_SW_DEVICE=m +CONFIG_TI_ADS7950=y +CONFIG_TCS3472=m +CONFIG_IIO_INTERRUPT_TRIGGER=m +CONFIG_IIO_SYSFS_TRIGGER=m +CONFIG_PWM=y +CONFIG_PWM_TIECAP=y +CONFIG_PWM_TIEHRPWM=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_F2FS_FS=m +CONFIG_FANOTIFY=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=m +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CRAMFS=y +CONFIG_NFS_FS=m +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=m +CONFIG_NFS_V4_1=y +CONFIG_NFSD=m +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_LZ4=y +# CONFIG_CRYPTO_HW is not set +CONFIG_CRC_CCITT=y +CONFIG_CRC_T10DIF=m +CONFIG_CRC_ITU_T=y +CONFIG_XZ_DEC=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_6x11=y +CONFIG_FONT_MINI_4x6=y +CONFIG_DEBUG_FS=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_FTRACE is not set +# CONFIG_ARM_UNWIND is not set diff --git a/arch/arm/include/asm/fiq.h b/arch/arm/include/asm/fiq.h index 6bdfb4a473220..4c8a2729ffe9d 100644 --- a/arch/arm/include/asm/fiq.h +++ b/arch/arm/include/asm/fiq.h @@ -34,9 +34,13 @@ struct fiq_handler { void *dev_id; }; +typedef void (*fiq_c_handler_t)(void); + extern int claim_fiq(struct fiq_handler *f); extern void release_fiq(struct fiq_handler *f); extern void set_fiq_handler(void *start, unsigned int length); +extern fiq_c_handler_t get_fiq_c_handler(void); +extern void set_fiq_c_handler(fiq_c_handler_t); extern void enable_fiq(int fiq); extern void disable_fiq(int fiq); diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index d2c8e53135397..3d92850936101 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -9,6 +9,8 @@ * * FIQ support re-written by Russell King to be more generic * + * FIQ handler in C support written by Andy Green + * * We now properly support a method by which the FIQ handlers can * be stacked onto the vector. We still do not support sharing * the FIQ vector itself. @@ -104,6 +106,89 @@ void set_fiq_handler(void *start, unsigned int length) flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length); } +/* ---------------------------- FIQ handler in C ---------------------------- */ +/* + * Major Caveats for using this + * ---------------------------- + * + * 1) it CANNOT touch any vmalloc()'d memory, only memory + * that was kmalloc()'d. Static allocations in the monolithic kernel + * are kmalloc()'d so they are okay. You can touch memory-mapped IO, but + * the pointer for it has to have been stored in kmalloc'd memory. The + * reason for this is simple: every now and then Linux turns off interrupts + * and reorders the paging tables. If a FIQ happens during this time, the + * virtual memory space can be partly or entirely disordered or missing. + * + * 2) Because vmalloc() is used when a module is inserted, THIS FIQ + * ISR HAS TO BE IN THE MONOLITHIC KERNEL, not a module. But the way + * it is set up, you can all to enable and disable it from your module + * and intercommunicate with it through struct fiq_ipc + * fiq_ipc which you can define in + * asm/archfiq_ipc_type.h. The reason is the same as above, a + * FIQ could happen while even the ISR is not present in virtual memory + * space due to pagetables being changed at the time. + * + * 3) You can't call any Linux API code except simple macros + * - understand that FIQ can come in at any time, no matter what + * state of undress the kernel may privately be in, thinking it + * locked the door by turning off interrupts... FIQ is an + * unstoppable monster force (which is its value) + * - they are not vmalloc()'d memory safe + * - they might do crazy stuff like sleep: FIQ pisses fire and + * is not interested in 'sleep' that the weak seem to need + * - calling APIs from FIQ can re-enter un-renterable things + * - summary: you cannot interoperate with linux APIs directly in the FIQ ISR + * + * If you follow these rules, it is fantastic, an extremely powerful, solid, + * genuine hard realtime feature. + */ + +static void (*current_fiq_c_isr)(void); + +#define FIQ_C_ISR_STACK_SIZE 256 + +static void __attribute__((naked)) __jump_to_isr(void) +{ + asm __volatile__ ("mov pc, r8"); +} + + +static void __attribute__((naked)) __actual_isr(void) +{ + asm __volatile__ ( + "stmdb sp!, {r0-r12, lr};" + "mov fp, sp;" + ); + + current_fiq_c_isr(); + + asm __volatile__ ( + "ldmia sp!, {r0-r12, lr};" + "subs pc, lr, #4;" + ); +} + +fiq_c_handler_t get_fiq_c_handler(void) +{ + return current_fiq_c_isr; +} + +void set_fiq_c_handler(fiq_c_handler_t isr) +{ + struct pt_regs regs; + + memset(®s, 0, sizeof(regs)); + regs.ARM_r8 = (unsigned long) __actual_isr; + regs.ARM_sp = 0xffff001c + FIQ_C_ISR_STACK_SIZE; + + set_fiq_handler(__jump_to_isr, 4); + + current_fiq_c_isr = isr; + + set_fiq_regs(®s); +} +/* ---------------------------- FIQ handler in C ---------------------------- */ + int claim_fiq(struct fiq_handler *f) { int ret = 0; @@ -150,6 +235,8 @@ void disable_fiq(int fiq) } EXPORT_SYMBOL(set_fiq_handler); +EXPORT_SYMBOL(get_fiq_c_handler); +EXPORT_SYMBOL(set_fiq_c_handler); EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */ EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */ EXPORT_SYMBOL(claim_fiq); diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 6cd6d29a2c9dd..7af380ca6be3a 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -27,6 +27,24 @@ config ARCH_DAVINCI_DA850 config ARCH_DAVINCI_DA8XX bool +config MACH_DAVINCI_LEGOEV3 + bool "LEGO MINDSTORMS EV3 Programmable Brick" + depends on ARCH_DAVINCI_DA850 + select DAVINCI_MUX + select CONFIG_DA850_UI_NONE + help + Say Y here to select the LEGO MINDSTORMS EV3 Programmable Brick . + Information on this board may be found at + http://mindstorms.lego.com/ + +config LEGOEV3_FIQ + bool "FIQ backend for LEGO Mindstorms EV3 input ports" + depends on MACH_DAVINCI_LEGOEV3 + select FIQ + help + Say Y here to enable the FIQ (fast interrupt) backend for the I2C + implementation used by the input ports on the LEGO Mindstorms EV3. + config DAVINCI_MUX bool "DAVINCI multiplexing support" depends on ARCH_DAVINCI diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 7a210db669f48..015fc7972cadb 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -13,6 +13,9 @@ obj-$(CONFIG_DAVINCI_MUX) += mux.o obj-$(CONFIG_ARCH_DAVINCI_DA850) += da850.o pdata-quirks.o obj-y += da8xx-dt.o +obj-$(CONFIG_MACH_DAVINCI_LEGOEV3) += legoev3-dt.o + +obj-$(CONFIG_LEGOEV3_FIQ) += legoev3-fiq.o # Power Management obj-$(CONFIG_HAVE_CLK) += pm_domain.o diff --git a/arch/arm/mach-davinci/legoev3-dt.c b/arch/arm/mach-davinci/legoev3-dt.c new file mode 100644 index 0000000000000..88789ebba2130 --- /dev/null +++ b/arch/arm/mach-davinci/legoev3-dt.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ + * + * Modified from mach-omap/omap2/board-generic.c + */ +#include +#include +#include +#include + +#include + +#include "common.h" +#include "da8xx.h" + +#include "legoev3-fiq.h" +#include "board-legoev3.h" +#include "cp_intc.h" + +#define LEGOEV3_DT 1 +#include <../../../drivers/lego/ev3/legoev3_i2c.h> + + +#define DA8XX_EHRPWM0_BASE 0x01F00000 + +static struct legoev3_fiq_platform_data legoev3_in_port_i2c_platform_data = { + .intc_mem_base = DA8XX_CP_INTC_BASE, + .intc_mem_size = 0x608, + .gpio_mem_base = DA8XX_GPIO_BASE, + .gpio_mem_size = 0xD8, + .ehrpwm_mem_base = DA8XX_EHRPWM0_BASE, + .ehrpwm_mem_size = 0x1FFF, + .timer_irq = IRQ_DA8XX_TINT34_1, + .ehrpwm_irq = IRQ_DA8XX_EHRPWM0, + .status_gpio = EV3_FIQ_STAT_PIN, +}; + +static struct platform_device legoev3_in_port_i2c_fiq = { + .name = "legoev3-fiq", + .id = -1, + .dev = { + .platform_data = &legoev3_in_port_i2c_platform_data, + }, +}; + +static struct i2c_legoev3_platform_data legoev3_i2c3_data = { + .sda_pin = EV3_IN1_PIN6_PIN, + .scl_pin = EV3_IN1_I2C_CLK_PIN, + .port_id = EV3_PORT_IN1, +}; + +static struct platform_device legoev3_i2c3_device = { + .name = "i2c-legoev3", + .dev = { + .platform_data = &legoev3_i2c3_data, + }, + .id = 3, +}; + +static struct i2c_legoev3_platform_data legoev3_i2c4_data = { + .sda_pin = EV3_IN2_PIN6_PIN, + .scl_pin = EV3_IN2_I2C_CLK_PIN, + .port_id = EV3_PORT_IN2, +}; + +static struct platform_device legoev3_i2c4_device = { + .name = "i2c-legoev3", + .dev = { + .platform_data = &legoev3_i2c4_data, + }, + .id = 4, +}; + +static struct i2c_legoev3_platform_data legoev3_i2c5_data = { + .sda_pin = EV3_IN3_PIN6_PIN, + .scl_pin = EV3_IN3_I2C_CLK_PIN, + .port_id = EV3_PORT_IN3, +}; + +static struct platform_device legoev3_i2c5_device = { + .name = "i2c-legoev3", + .dev = { + .platform_data = &legoev3_i2c5_data, + }, + .id = 5, +}; + +static struct i2c_legoev3_platform_data legoev3_i2c6_data = { + .sda_pin = EV3_IN4_PIN6_PIN, + .scl_pin = EV3_IN4_I2C_CLK_PIN, + .port_id = EV3_PORT_IN4, +}; + +static struct platform_device legoev3_i2c6_device = { + .name = "i2c-legoev3", + .dev = { + .platform_data = &legoev3_i2c6_data, + }, + .id = 6, +}; + +static void __init legoev3_init_machine(void) +{ + int ret; + + davinci_pm_init(); + pdata_quirks_init(); + + ret = platform_device_register(&legoev3_in_port_i2c_fiq); + if (ret) + pr_warn("%s: FIQ I2C backend registration failed: %d\n", + __func__, ret); + + ret = platform_device_register(&legoev3_i2c3_device); + if (ret) + pr_warn("%s: Input port 1 I2C registration failed: %d\n", + __func__, ret); + + ret = platform_device_register(&legoev3_i2c4_device); + if (ret) + pr_warn("%s: Input port 2 I2C registration failed: %d\n", + __func__, ret); + + ret = platform_device_register(&legoev3_i2c5_device); + if (ret) + pr_warn("%s: Input port 3 I2C registration failed: %d\n", + __func__, ret); + + ret = platform_device_register(&legoev3_i2c6_device); + if (ret) + pr_warn("%s: Input port 4 I2C registration failed: %d\n", + __func__, ret); +} + +static const char *const legoev3_dt_compat[] __initconst = { + "lego,ev3", + NULL, +}; + +DT_MACHINE_START(DA850_DT, "LEGO MINDSTORMS EV3") + .map_io = da850_init, + .init_machine = legoev3_init_machine, + .dt_compat = legoev3_dt_compat, + .init_late = davinci_init_late, +MACHINE_END diff --git a/arch/arm/mach-davinci/legoev3-fiq.c b/arch/arm/mach-davinci/legoev3-fiq.c new file mode 100644 index 0000000000000..037da8e08a7a1 --- /dev/null +++ b/arch/arm/mach-davinci/legoev3-fiq.c @@ -0,0 +1,914 @@ +/* + * FIQ backend for I2C bus driver for LEGO MINDSTORMS EV3 + * Copyright (C) 2013-2015 David Lechner + * + * Based on davinci_iic.c from lms2012 + * That file does not contain a copyright, but comes from the LEGO Group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * In order to achieve realtime performance for sound playback and I2C + * on the input ports, we use FIQs (fast interrupts). These interrupts + * can interrupt any regular IRQ, which is what makes it possible to get + * the near-realtime performance, but this also makes them dangerous, + * so be sure you know what you are doing before making changes here. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "cp_intc.h" + +enum transfer_states { + TRANSFER_IDLE, + TRANSFER_START, + TRANSFER_START2, + TRANSFER_ADDR, + TRANSFER_WRITE, + TRANSFER_READ, + TRANSFER_WBIT, + TRANSFER_RBIT, + TRANSFER_WACK, + TRANSFER_RACK, + TRANSFER_STOP, + TRANSFER_STOP2, + TRANSFER_STOP3, + TRANSFER_RESTART, + TRANSFER_WAIT, + TRANSFER_COMPLETE, +}; + +enum fiq_timer_restart { + FIQ_TIMER_NORESTART, + FIQ_TIMER_RESTART, +}; + +enum fiq_i2c_pin { + FIQ_I2C_PIN_SDA, + FIQ_I2C_PIN_SCL, + NUM_FIQ_I2C_PIN +}; + +struct legoev3_fiq_gpio { + int dir_reg; + int set_reg; + int clr_reg; + int in_reg; + int reg_mask; +}; + +struct legoev3_fiq_port_i2c_data { + struct legoev3_fiq_gpio gpio[NUM_FIQ_I2C_PIN]; + void (*complete)(int, void *); + void *context; + struct i2c_msg msgs[2]; + struct i2c_msg *xfer_msgs; + unsigned num_msg; + unsigned cur_msg; + unsigned wait_cycles; + int xfer_result; + u16 buf_offset; + u8 bit_mask; + u8 data_byte; + enum transfer_states transfer_state; + unsigned clock_state:1; + unsigned nacked:1; +}; + +struct legoev3_fiq_ehrpwm_data { + u8 *dma_area; + int volume; + unsigned playback_ptr; + size_t frame_bytes; + size_t buffer_bytes; + snd_pcm_uframes_t period_size; + unsigned callback_count; + void (*period_elapsed)(void *); + void *period_elapsed_data; + unsigned requested_flag:1; + unsigned period_elapsed_flag:1; +}; + +struct legoev3_fiq_data { + struct legoev3_fiq_port_i2c_data port_data[NUM_EV3_PORT_IN]; + struct legoev3_fiq_ehrpwm_data ehrpwm_data; + struct platform_device *pdev; + struct fiq_handler fiq_handler; + struct legoev3_fiq_gpio status_gpio; + void __iomem *gpio_base; + void __iomem *intc_base; + void __iomem *ehrpwm_base; + int timer_irq; + int ehrpwm_irq; + int status_gpio_irq; + int port_req_flags; +}; + +static struct legoev3_fiq_data legoev3_fiq_init_data = { + .fiq_handler = { + .name = "legoev3-fiq-handler", + }, +}; + +static struct legoev3_fiq_data *legoev3_fiq_data; + +/* + * IMPORTANT: The following functions called from an fiq (fast interrupt). + * They cannot call any linux API functions. This is why we have our own + * gpio and fiq ack functions. + * + * See set_fiq_c_handler in arch/arm/kernel/fiq.c for more details on + * this and other important restrictions. + */ + +static inline bool fiq_gpio_get_value(struct legoev3_fiq_gpio *gpio) +{ + return (__raw_readl(legoev3_fiq_data->gpio_base + gpio->in_reg) + & gpio->reg_mask) ? 1 : 0; +} + +static inline void fiq_gpio_set_value(struct legoev3_fiq_gpio *gpio, bool value) +{ + if (value) + __raw_writel(gpio->reg_mask, + legoev3_fiq_data->gpio_base + gpio->set_reg); + else + __raw_writel(gpio->reg_mask, + legoev3_fiq_data->gpio_base + gpio->clr_reg); +} + +static inline void fiq_gpio_dir_in(struct legoev3_fiq_gpio *gpio) +{ + int dir = __raw_readl(legoev3_fiq_data->gpio_base + gpio->dir_reg); + dir |= gpio->reg_mask; + __raw_writel(dir, legoev3_fiq_data->gpio_base + gpio->dir_reg); +} + +static inline void fiq_gpio_dir_out(struct legoev3_fiq_gpio *gpio, bool value) +{ + int dir; + + fiq_gpio_set_value(gpio, value); + dir = __raw_readl(legoev3_fiq_data->gpio_base + gpio->dir_reg); + dir &= ~gpio->reg_mask; + __raw_writel(dir, legoev3_fiq_data->gpio_base + gpio->dir_reg); +} + +#define SICR 0x24 /* System Interrupt Status Indexed Clear Register */ +static inline void legoev3_fiq_ack(int irq) +{ + __raw_writel(irq, legoev3_fiq_data->intc_base + SICR); +} + +#define EISR 0x28 /* System Interrupt Enable Indexed Set Register */ +static inline void legoev3_fiq_enable(int irq) +{ + __raw_writel(irq, legoev3_fiq_data->intc_base + EISR); +} + +#define EICR 0x2C /* System Interrupt Enable Indexed Clear Register */ +static inline void legoev3_fiq_disable(int irq) +{ + __raw_writel(irq, legoev3_fiq_data->intc_base + EICR); +} + +#define GPIR 0x80 /* Global Prioritized Index Register */ +static inline int legoev3_fiq_get_irq(void) +{ + return __raw_readl(legoev3_fiq_data->intc_base + GPIR); +} + +#define TBPRD 0xA /* Time-Base Period Register */ +static inline int fiq_ehrpwm_get_period_ticks(void) +{ + return __raw_readw(legoev3_fiq_data->ehrpwm_base + TBPRD); +} + +#define CMPB 0x14 /* Counter-Compare B Register */ +static inline void fiq_ehrpwm_set_duty_ticks(unsigned ticks) +{ + __raw_writew(ticks, legoev3_fiq_data->ehrpwm_base + CMPB); +} + +#define ETSEL 0x32 /* Event-Trigger Selection Register */ +#define INTEN (BIT(3)) /* Interrupt enable bit */ +#define INTSEL_MASK (BIT(2)|BIT(1)|BIT(0)) /* Interrupt selection mask */ +#define INTSEL_TBPRD 2 +static inline void fiq_ehrpwm_et_int_enable(void) +{ + short dir = __raw_readw(legoev3_fiq_data->ehrpwm_base + ETSEL); + dir |= INTEN; + __raw_writew(dir, legoev3_fiq_data->ehrpwm_base + ETSEL); +} + +static inline void fiq_ehrpwm_et_int_disable(void) +{ + short dir = __raw_readw(legoev3_fiq_data->ehrpwm_base + ETSEL); + dir &= ~INTEN; + __raw_writew(dir, legoev3_fiq_data->ehrpwm_base + ETSEL); +} + +static inline bool fiq_ehrpwm_et_int_is_enabled(void) +{ + short dir = __raw_readw(legoev3_fiq_data->ehrpwm_base + ETSEL); + return !!(dir & INTEN); +} + +#define ETPS 0x34 /* Event-Trigger Prescale Register */ +#define INTPRD_MASK (BIT(1)|BIT(0)) +static inline void fiq_ehrpwm_et_int_set_period(unsigned char period) +{ + short dir = __raw_readw(legoev3_fiq_data->ehrpwm_base + ETSEL); + dir &= ~INTSEL_MASK; + dir |= INTSEL_TBPRD; + __raw_writew(dir, legoev3_fiq_data->ehrpwm_base + ETSEL); + + dir = __raw_readw(legoev3_fiq_data->ehrpwm_base + ETPS); + dir &= ~INTPRD_MASK; + dir |= period & INTPRD_MASK; + __raw_writew(dir, legoev3_fiq_data->ehrpwm_base + ETPS); +} + +#define ETFLG 0x36 /* Event-Trigger Flag Register */ +static inline int fiq_ehrpwm_test_irq(void) +{ + return __raw_readw(legoev3_fiq_data->ehrpwm_base + ETFLG) & 0x1; +} + +#define ETCLR 0x38 /* Event-Trigger Clear Register */ +static inline void fiq_ehrpwm_clear_irq(void) +{ + __raw_writew(0x1, legoev3_fiq_data->ehrpwm_base + ETCLR); +} + +static enum fiq_timer_restart +legoev3_fiq_timer_callback(struct legoev3_fiq_port_i2c_data *data) +{ + struct i2c_msg *msg = &data->msgs[data->cur_msg]; + + fiq_gpio_set_value(&data->gpio[FIQ_I2C_PIN_SCL], data->clock_state); + + switch (data->transfer_state) { + case TRANSFER_START: + /* + * Make sure to SYNC into Timer settings + * to ensure first bit time having full length + */ + data->cur_msg = 0; + data->xfer_result = data->num_msg; + data->transfer_state = TRANSFER_START2; + break; + + case TRANSFER_START2: + /* Generate start condition - sda low to high while clk high */ + fiq_gpio_dir_out(&data->gpio[FIQ_I2C_PIN_SDA], 0); + data->clock_state = 0; + data->nacked = false; + data->transfer_state = TRANSFER_ADDR; + break; + + case TRANSFER_ADDR: + data->data_byte = (msg->addr << 1); + if (msg->flags & I2C_M_RD) + data->data_byte |= 1; + data->buf_offset = 0; + /* no break */ + + case TRANSFER_WRITE: + if (data->transfer_state == TRANSFER_WRITE) + data->data_byte = msg->buf[data->buf_offset++]; + data->transfer_state = TRANSFER_WBIT; + data->bit_mask = 0x80; + /* no break */ + + case TRANSFER_WBIT: + if (!data->clock_state) { + fiq_gpio_dir_out(&data->gpio[FIQ_I2C_PIN_SDA], + data->data_byte & data->bit_mask); + data->bit_mask >>= 1; + } + + if (!data->bit_mask && data->clock_state) + data->transfer_state = TRANSFER_RACK; + data->clock_state ^= 1; + break; + + case TRANSFER_READ: + fiq_gpio_dir_in(&data->gpio[FIQ_I2C_PIN_SDA]); + data->transfer_state = TRANSFER_RBIT; + data->bit_mask = 0x80; + data->data_byte = 0; + /* no break */ + + case TRANSFER_RBIT: + if (data->clock_state) { + data->data_byte |= fiq_gpio_get_value(&data->gpio[FIQ_I2C_PIN_SDA]) + ? data->bit_mask : 0; + data->bit_mask >>= 1; + + if (!data->bit_mask) { + msg->buf[data->buf_offset++] = data->data_byte; + data->transfer_state = TRANSFER_WACK; + } + } + data->clock_state ^= 1; + break; + + case TRANSFER_RACK: + if (!data->clock_state) { + fiq_gpio_dir_in(&data->gpio[FIQ_I2C_PIN_SDA]); + } else { + if (!fiq_gpio_get_value(&data->gpio[FIQ_I2C_PIN_SDA])) { + if (data->buf_offset < msg->len) { + data->wait_cycles = 4; + data->transfer_state = TRANSFER_WAIT; + } + else + data->transfer_state = TRANSFER_STOP; + } else { + data->nacked = true; + data->xfer_result = -ENXIO; + data->transfer_state = TRANSFER_STOP; + } + } + data->clock_state ^= 1; + break; + + case TRANSFER_WACK: + if (!data->clock_state) { + /* ACK (or NACK the last byte read) */ + fiq_gpio_dir_out(&data->gpio[FIQ_I2C_PIN_SDA], + data->buf_offset == msg->len); + } else { + if (data->buf_offset < msg->len) { + data->wait_cycles = 2; + data->transfer_state = TRANSFER_WAIT; + } else + data->transfer_state = TRANSFER_STOP; + } + data->clock_state ^= 1; + break; + + case TRANSFER_WAIT: + if (data->wait_cycles--) + break; + else if (msg->flags & I2C_M_RD) + data->transfer_state = TRANSFER_READ; + else + data->transfer_state = TRANSFER_WRITE; + break; + + case TRANSFER_STOP: + /* + * Note: The official LEGO firmware does not generate stop + * condition except for in the middle of reads (see below). + * We are going by the book and doing a stop when we are + * supposed to. We can change it back if there are problems. + */ + fiq_gpio_dir_out(&data->gpio[FIQ_I2C_PIN_SDA], 0); + + if (data->clock_state) + data->transfer_state = TRANSFER_STOP2; + data->clock_state = 1; + break; + + case TRANSFER_STOP2: + if ((data->cur_msg + 1) < data->num_msg && !data->nacked) { + /* + * This is some non-standard i2c weirdness for + * compatibility with the NXT ultrasonic sensor. + * + * Normal i2c would just send a restart (sda high + * to low while clk is high) between writing the + * address and reading the data. Instead, we send + * a stop (sda low to high while clk is high) and + * then do an extra clock cycle (low then high) + * before sending a start and reading the data. + */ + fiq_gpio_dir_out(&data->gpio[FIQ_I2C_PIN_SDA], 1); + data->clock_state ^= 1; + if (data->clock_state) { + data->cur_msg++; + data->transfer_state = TRANSFER_RESTART; + } + } else { + data->transfer_state = TRANSFER_STOP3; + } + break; + + case TRANSFER_RESTART: + data->transfer_state = TRANSFER_START2; + break; + + case TRANSFER_STOP3: + /* + * Generate stop condition - sda low to high while clock + * is high. Leave sda in input position when not in use so + * that we can detect when a sensor is disconnected. (Device + * detection is implemented in the ev3-input-ports driver.) + */ + fiq_gpio_dir_in(&data->gpio[FIQ_I2C_PIN_SDA]); + data->transfer_state = TRANSFER_COMPLETE; + /* no break */ + + case TRANSFER_COMPLETE: + /* + * Keep toggling the status gpio until the gpio irq handler + * acks it by setting transfer_state to TRANSFER_IDLE. + */ + fiq_gpio_set_value(&legoev3_fiq_data->status_gpio, + !fiq_gpio_get_value(&legoev3_fiq_data->status_gpio)); + break; + case TRANSFER_IDLE: + return FIQ_TIMER_NORESTART; + + default: + break; + } + + return FIQ_TIMER_RESTART; +} + +static void legoev3_fiq_ehrpwm_callback(struct legoev3_fiq_ehrpwm_data *data) +{ + int sample; + unsigned long duty_ticks, period_ticks; + + if (unlikely(!data->requested_flag || !data->dma_area)) + return; + + period_ticks = fiq_ehrpwm_get_period_ticks(); + + sample = *(short *)(data->dma_area + data->playback_ptr); + sample = (sample * data->volume) >> 8; + duty_ticks = ((sample + 0x7FFF) * period_ticks) >> 16; + + fiq_ehrpwm_set_duty_ticks(duty_ticks); + + /* + * FIXME: Setting the buffer data to 0 here because there is a tendency + * to replay part of a sample at the end of playback. If we can figure + * out how to detect the end of playback, we wouldn't need to do this. + */ + *(short *)(data->dma_area + data->playback_ptr) = 0; + + data->playback_ptr += data->frame_bytes; + if (data->playback_ptr >= data->buffer_bytes) + data->playback_ptr = 0; + + if (++data->callback_count >= data->period_size) + { + data->callback_count = 0; + data->period_elapsed_flag = 1; + } + + /* toggle gpio to trigger callback */ + if (data->period_elapsed_flag) + fiq_gpio_set_value(&legoev3_fiq_data->status_gpio, + !fiq_gpio_get_value(&legoev3_fiq_data->status_gpio)); +} + +void legoev3_fiq_handler(void) +{ + int irq = legoev3_fiq_get_irq(); + + if (irq == legoev3_fiq_data->timer_irq) { + struct legoev3_fiq_port_i2c_data *port_data; + int restart_timer = 0; + int i; + + for (i = 0; i < NUM_EV3_PORT_IN; i++) { + if (!(legoev3_fiq_data->port_req_flags & BIT(i))) + continue; + port_data = &legoev3_fiq_data->port_data[i]; + if (port_data != TRANSFER_IDLE) + restart_timer |= legoev3_fiq_timer_callback(port_data); + } + + if (!restart_timer) + legoev3_fiq_disable(legoev3_fiq_data->timer_irq); + + legoev3_fiq_ack(legoev3_fiq_data->timer_irq); + } + if (fiq_ehrpwm_test_irq()) { + legoev3_fiq_ehrpwm_callback(&legoev3_fiq_data->ehrpwm_data); + legoev3_fiq_ack(legoev3_fiq_data->ehrpwm_irq); + fiq_ehrpwm_clear_irq(); + } +} + +/* --------------- END OF CODE THAT IS CALLED IN FIQ CONTEXT -----------------*/ + +static void legoev3_fiq_set_gpio(int gpio_pin, struct legoev3_fiq_gpio *gpio) +{ + int bank = gpio_pin >> 4; + int bank_offset = (bank >> 1) * 0x28; + int index = gpio_pin & 0xF; + + gpio->dir_reg = bank_offset + 0x10; + gpio->set_reg = bank_offset + 0x18; + gpio->clr_reg = bank_offset + 0x1C; + gpio->in_reg = bank_offset + 0x20; + gpio->reg_mask = BIT(index + (bank & 1) * 16); +} + +static irqreturn_t legoev3_fiq_gpio_irq_i2c_port_callback(int irq, void *port_data) +{ + struct legoev3_fiq_port_i2c_data *data = port_data; + int i; + + local_fiq_disable(); + + if (data->transfer_state == TRANSFER_COMPLETE) { + for (i = 0; i < data->num_msg; i++) + memcpy(&data->xfer_msgs[i], &data->msgs[i], + sizeof(struct i2c_msg)); + fiq_gpio_set_value(&legoev3_fiq_data->status_gpio, 0); + data->transfer_state = TRANSFER_IDLE; + if (data->complete) + data->complete(data->xfer_result, data->context); + } + local_fiq_enable(); + + return IRQ_HANDLED; +} + +/** + * legoev3_fiq_request_port - Requests ownership of the I2C backend for the + * specified port. + * @port_id: The port identifier. + * @sda_pin: The GPIO pin to use for the I2C data line. This GPIO should + * already be requested and set high by the calling code and not + * touched again until legoev3_fiq_release_port is called. + * @scl_pin: The GPIO pin to use for the I2C clock line. Same notes apply + * as on the sda_pin. + * + * Returns 0 if the port is available or -EBUSY if it has already be requested. + */ +int legoev3_fiq_request_port(enum legoev3_input_port_id port_id, int sda_pin, + int scl_pin) +{ + struct legoev3_fiq_port_i2c_data *data; + int ret; + + if (!legoev3_fiq_data) + return -EPROBE_DEFER; + if (legoev3_fiq_data->port_req_flags & BIT(port_id)) + return -EBUSY; + + data = &legoev3_fiq_data->port_data[port_id]; + legoev3_fiq_set_gpio(sda_pin, &data->gpio[FIQ_I2C_PIN_SDA]); + legoev3_fiq_set_gpio(scl_pin, &data->gpio[FIQ_I2C_PIN_SCL]); + + ret = request_irq(legoev3_fiq_data->status_gpio_irq, + legoev3_fiq_gpio_irq_i2c_port_callback, + IRQF_TRIGGER_RISING | IRQF_SHARED, + legoev3_fiq_data->pdev->name, data); + if (ret < 0) { + dev_err(&legoev3_fiq_data->pdev->dev, + "Unable to claim irq %d; error %d\n", + legoev3_fiq_data->status_gpio_irq, ret); + return ret; + } + + data->transfer_state = TRANSFER_IDLE; + data->clock_state = 1; + legoev3_fiq_data->port_req_flags |= BIT(port_id); + + return 0; +} +EXPORT_SYMBOL_GPL(legoev3_fiq_request_port); + +/** + * legoev3_fiq_release_port- Releases ownership of the I2C backend for the + * specified port. + * @port_id: The port identifier. + */ +void legoev3_fiq_release_port(enum legoev3_input_port_id port_id) +{ + struct legoev3_fiq_port_i2c_data *data; + + if (!legoev3_fiq_data) + return; + + data = &legoev3_fiq_data->port_data[port_id]; + data->transfer_state = TRANSFER_IDLE; + legoev3_fiq_data->port_req_flags &= ~BIT(port_id); + free_irq(legoev3_fiq_data->status_gpio_irq, data); +} +EXPORT_SYMBOL_GPL(legoev3_fiq_release_port); + +/** + * legoev3_fiq_start_xfer- Start an I2C transfer on the specified port. + * @port_id: The port identifier that was previously requested. + * @msgs: The message data to transfer. + * @num_msg: Number of messages in msgs[]. + * @complete: Function to call when transfer is complete. + * @context: Pointer that is passed as an argument to the complete function. + * + * You should only call this for a port that returned successfully from + * legoev3_fiq_request_port. + */ +int legoev3_fiq_start_xfer(enum legoev3_input_port_id port_id, + struct i2c_msg msgs[], int num_msg, + void (*complete)(int, void *), void *context) +{ + struct legoev3_fiq_port_i2c_data *data; + int i; + + if (!legoev3_fiq_data) + return -ENODEV; + if (port_id >= NUM_EV3_PORT_IN) + return -EINVAL; + if (num_msg < 1 || num_msg > 2) + return -EINVAL; + if (!(legoev3_fiq_data->port_req_flags & BIT(port_id))) + return -EINVAL; + + data = &legoev3_fiq_data->port_data[port_id]; + if (data->transfer_state != TRANSFER_IDLE) + return -EBUSY; + + /* copy the messages so that fiq has exclusive access */ + for (i = 0; i < num_msg; i++) + memcpy(&data->msgs[i], &msgs[i], sizeof(struct i2c_msg)); + /* + * we also have to hang on to the real messages so that we can + * copy any data read back to them when the transfer is complete. + */ + data->xfer_msgs = msgs; + data->num_msg = num_msg; + data->complete = complete; + data->context = context; + data->transfer_state = TRANSFER_START; + legoev3_fiq_enable(legoev3_fiq_data->timer_irq); + + return 0; +} +EXPORT_SYMBOL_GPL(legoev3_fiq_start_xfer); + +void legoev3_fiq_cancel_xfer(enum legoev3_input_port_id port_id) +{ + struct legoev3_fiq_port_i2c_data *data; + + if (!legoev3_fiq_data) + return; + if (port_id >= NUM_EV3_PORT_IN) + return; + + data = &legoev3_fiq_data->port_data[port_id]; + data->transfer_state = TRANSFER_IDLE; +} +EXPORT_SYMBOL_GPL(legoev3_fiq_cancel_xfer); + +static irqreturn_t +legoev3_fiq_gpio_irq_period_elapsed_callback(int irq, void *ehrpwm_data) +{ + struct legoev3_fiq_ehrpwm_data *data = ehrpwm_data; + + local_fiq_disable(); + if (data->period_elapsed) { + data->period_elapsed(data->period_elapsed_data); + data->period_elapsed_flag = 0; + fiq_gpio_set_value(&legoev3_fiq_data->status_gpio, 0); + } + local_fiq_enable(); + + return IRQ_HANDLED; +} + +int legoev3_fiq_ehrpwm_int_enable(void) +{ + if (!legoev3_fiq_data || !legoev3_fiq_data->ehrpwm_data.requested_flag) + return -ENODEV; + + fiq_ehrpwm_et_int_enable(); + return 0; +} +EXPORT_SYMBOL_GPL(legoev3_fiq_ehrpwm_int_enable); + +int legoev3_fiq_ehrpwm_int_disable(void) +{ + if (!legoev3_fiq_data || !legoev3_fiq_data->ehrpwm_data.requested_flag) + return -ENODEV; + + fiq_ehrpwm_et_int_disable(); + return 0; +} +EXPORT_SYMBOL_GPL(legoev3_fiq_ehrpwm_int_disable); + +bool legoev3_fiq_ehrpwm_int_is_enabled(void) +{ + if (!legoev3_fiq_data || !legoev3_fiq_data->ehrpwm_data.requested_flag) + return false; + + return fiq_ehrpwm_et_int_is_enabled(); +} +EXPORT_SYMBOL_GPL(legoev3_fiq_ehrpwm_int_is_enabled); + +/* + * Only called when the ehrpwm interrupt is configured as regular IRQ and + * not as a FIQ. In other words, this is for debugging (when assigned to IRQ) + * and serves as a dummy callback during normal usage (when assigned to FIQ). + */ +static irqreturn_t legoev3_fiq_ehrpwm_et_callback(int irq, void *data) +{ + fiq_c_handler_t handler = get_fiq_c_handler(); + + if (handler) + handler(); + + return IRQ_HANDLED; +} + +int legoev3_fiq_ehrpwm_request(void) +{ + int err; + + if (!legoev3_fiq_data) + return -ENODEV; + + if (legoev3_fiq_data->ehrpwm_data.requested_flag) + return -EBUSY; + legoev3_fiq_data->ehrpwm_data.requested_flag = 1; + + err = request_irq(legoev3_fiq_data->status_gpio_irq, + legoev3_fiq_gpio_irq_period_elapsed_callback, + IRQF_TRIGGER_RISING | IRQF_SHARED, + legoev3_fiq_data->pdev->name, + &legoev3_fiq_data->ehrpwm_data); + if (err) { + dev_err(&legoev3_fiq_data->pdev->dev, + "Unable to claim irq %d; error %d\n", + legoev3_fiq_data->status_gpio_irq, err); + legoev3_fiq_data->ehrpwm_data.requested_flag = 0; + return err; + } + + err = request_irq(legoev3_fiq_data->ehrpwm_irq, + legoev3_fiq_ehrpwm_et_callback, 0, + "legoev3_fiq_ehrpwm_debug", + &legoev3_fiq_data->ehrpwm_data); + if (err) + dev_warn(&legoev3_fiq_data->pdev->dev, + "Failed to request ehrpwm irq."); + + return 0; +} +EXPORT_SYMBOL_GPL(legoev3_fiq_ehrpwm_request); + +void legoev3_fiq_ehrpwm_release(void) +{ + if (!legoev3_fiq_data) + return; + + local_fiq_disable(); + free_irq(legoev3_fiq_data->status_gpio_irq, + &legoev3_fiq_data->ehrpwm_data); + free_irq(legoev3_fiq_data->ehrpwm_irq, &legoev3_fiq_data->ehrpwm_data); + legoev3_fiq_data->ehrpwm_data.period_elapsed_flag = 0; + legoev3_fiq_data->ehrpwm_data.requested_flag = 0; + local_fiq_enable(); +} +EXPORT_SYMBOL_GPL(legoev3_fiq_ehrpwm_release); + +int legoev3_fiq_ehrpwm_prepare(struct snd_pcm_substream *substream, int volume, + unsigned char int_period, + void (*period_elapsed)(void *), void *context) +{ + struct legoev3_fiq_ehrpwm_data *data; + + if (!legoev3_fiq_data || !legoev3_fiq_data->ehrpwm_data.requested_flag) + return -ENODEV; + + if (int_period > 3) + return -EINVAL; + + data = &legoev3_fiq_data->ehrpwm_data; + + local_fiq_disable(); + + data->dma_area = substream->runtime->dma_area; + data->playback_ptr = 0; + data->volume = volume; + data->frame_bytes = frames_to_bytes(substream->runtime, 1); + data->buffer_bytes = snd_pcm_lib_buffer_bytes(substream); + data->period_size = substream->runtime->period_size; + data->callback_count = 0; + data->period_elapsed = period_elapsed; + data->period_elapsed_data = context; + data->period_elapsed_flag = 0; + fiq_ehrpwm_et_int_set_period(int_period); + + local_fiq_enable(); + + return 0; +} +EXPORT_SYMBOL_GPL(legoev3_fiq_ehrpwm_prepare); + +unsigned legoev3_fiq_ehrpwm_get_playback_ptr(void) +{ + return legoev3_fiq_data->ehrpwm_data.playback_ptr; +} +EXPORT_SYMBOL_GPL(legoev3_fiq_ehrpwm_get_playback_ptr); + +void legoev3_fiq_ehrpwm_set_volume(int volume) +{ + legoev3_fiq_data->ehrpwm_data.volume = volume; +} +EXPORT_SYMBOL_GPL(legoev3_fiq_ehrpwm_set_volume); + +static int legoev3_fiq_probe(struct platform_device *pdev) +{ + struct legoev3_fiq_data *fiq_data; + struct legoev3_fiq_platform_data *pdata; + int ret; + + if (legoev3_fiq_data) + return -EINVAL; + + fiq_data = &legoev3_fiq_init_data; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data.\n"); + return -EINVAL; + } + + fiq_data->gpio_base = devm_ioremap(&pdev->dev, pdata->gpio_mem_base, + pdata->gpio_mem_size); + if (WARN_ON(!fiq_data->gpio_base)) + return -EADDRNOTAVAIL; + + fiq_data->intc_base = devm_ioremap(&pdev->dev, pdata->intc_mem_base, + pdata->intc_mem_size); + if (WARN_ON(!fiq_data->intc_base)) + return -EADDRNOTAVAIL; + + fiq_data->ehrpwm_base = devm_ioremap(&pdev->dev, pdata->ehrpwm_mem_base, + pdata->ehrpwm_mem_size); + if (WARN_ON(!fiq_data->ehrpwm_base)) + return -EADDRNOTAVAIL; + + fiq_data->timer_irq = pdata->timer_irq; + fiq_data->ehrpwm_irq = pdata->ehrpwm_irq; + + ret = gpio_request_one(pdata->status_gpio, GPIOF_INIT_LOW, "fiq status"); + if (ret < 0) { + if (ret != -EPROBE_DEFER) { + dev_err(&pdev->dev, + "Unable to request GPIO %d, error %d\n", + pdata->status_gpio, ret); + } + return ret; + } + legoev3_fiq_set_gpio(pdata->status_gpio, &fiq_data->status_gpio); + + ret = gpio_to_irq(pdata->status_gpio); + if (ret < 0) { + dev_err(&pdev->dev, + "Unable to get irq number for GPIO %d, error %d\n", + pdata->status_gpio, ret); + goto err_gpio_to_irq; + } + fiq_data->status_gpio_irq = ret; + + ret = claim_fiq(&fiq_data->fiq_handler); + if (ret < 0) + goto err_claim_fiq; + set_fiq_c_handler(legoev3_fiq_handler); + + fiq_data->pdev = pdev; + legoev3_fiq_data = fiq_data; + + cp_intc_fiq_enable(); + + return 0; + +err_claim_fiq: +err_gpio_to_irq: + gpio_free(pdata->status_gpio); + + return ret; +} + +static struct platform_driver legoev3_fiq_driver = { + .probe = legoev3_fiq_probe, + .driver = { + .name = "legoev3-fiq", + .owner = THIS_MODULE, + }, +}; +module_platform_driver(legoev3_fiq_driver); diff --git a/arch/arm/mach-davinci/legoev3-fiq.h b/arch/arm/mach-davinci/legoev3-fiq.h new file mode 100644 index 0000000000000..dba799602de38 --- /dev/null +++ b/arch/arm/mach-davinci/legoev3-fiq.h @@ -0,0 +1,69 @@ +/* + * FIQ backend for I2C bus driver for LEGO Mindstorms EV3 + * Copyright (C) 2013-2014 David Lechner + * + * Based on davinci_iic.c from lms2012 + * The file does not contain a copyright, but comes from the LEGO Group + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __MACH_LEGOEV3_FIQ_H +#define __MACH_LEGOEV3_FIQ_H + +#include +#include + +#define LEGOEV3_DT 1 +#include <../../../drivers/lego/ev3/legoev3_i2c.h> + +/** + * struct legoev3_fiq_platform_data - platform specific data + * @intc_mem_base: Base memory address of interrupt controller. + * @intc_mem_size: Size of interrupt memory. + * @gpio_mem_base: Base memory address of GPIO controller. + * @gpio_mem_size: Size of GPIO memory. + * @ehrpwm_mem_base: Base memory address of EHRPWM controller. + * @ehrowm_mem_size: Size of EHROWM memory. + * @timer_irq: Timer interrupt for I2C callback. + * @ehrpwm_irq: EHRPWM interrupt for sound callback. + * @status_gpio: GPIO that is not physically connected that can be used to + * to generate interrupts so that the FIQ can notify external code + * that its status has changed. + */ +struct legoev3_fiq_platform_data { + unsigned intc_mem_base; + unsigned intc_mem_size; + unsigned gpio_mem_base; + unsigned gpio_mem_size; + unsigned ehrpwm_mem_base; + unsigned ehrpwm_mem_size; + unsigned timer_irq; + unsigned ehrpwm_irq; + int status_gpio; +}; + +extern int legoev3_fiq_request_port(enum legoev3_input_port_id port_id, + int sda_pin, int scl_pin); +extern void legoev3_fiq_release_port(enum legoev3_input_port_id port_id); +extern int legoev3_fiq_start_xfer(enum legoev3_input_port_id port_id, + struct i2c_msg msgs[], int num_msg, + void (*complete)(int, void *), void *context); +extern void legoev3_fiq_cancel_xfer(enum legoev3_input_port_id port_id); +extern int legoev3_fiq_ehrpwm_request(void); +extern void legoev3_fiq_ehrpwm_release(void); +extern int legoev3_fiq_ehrpwm_prepare(struct snd_pcm_substream *substream, + int volume, unsigned char int_period, + void (*period_elapsed)(void *), + void *context); +extern void legoev3_fiq_ehrpwm_ramp(struct snd_pcm_substream *substream, + int direction, unsigned ramp_ms); +extern unsigned legoev3_fiq_ehrpwm_get_playback_ptr(void); +extern void legoev3_fiq_ehrpwm_set_volume(int volume); +extern int legoev3_fiq_ehrpwm_int_enable(void); +extern int legoev3_fiq_ehrpwm_int_disable(void); +extern bool legoev3_fiq_ehrpwm_int_is_enabled(void); + +#endif /* __MACH_LEGOEV3_FIQ_H */ diff --git a/localversion b/localversion new file mode 120000 index 0000000000000..d1c3243e21683 --- /dev/null +++ b/localversion @@ -0,0 +1 @@ +drivers/lego/localversion \ No newline at end of file From b22732380401ec9fda91639e8cec28b34348eb47 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 5 May 2016 20:57:41 -0500 Subject: [PATCH 02/21] lego-linux-drivers submodule --- .gitignore | 1 + .gitmodules | 3 +++ drivers/Kconfig | 2 ++ drivers/Makefile | 3 +++ drivers/lego | 1 + 5 files changed, 10 insertions(+) create mode 100644 .gitmodules create mode 160000 drivers/lego diff --git a/.gitignore b/.gitignore index 86a1ba0d90353..8cf9b9bbbd748 100644 --- a/.gitignore +++ b/.gitignore @@ -112,6 +112,7 @@ modules.order !.get_maintainer.ignore !.gitattributes !.gitignore +!.gitmodules !.kunitconfig !.mailmap !.pylintrc diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000..aa18025fc3742 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "drivers/lego"] + path = drivers/lego + url = https://github.com/ev3dev/lego-linux-drivers diff --git a/drivers/Kconfig b/drivers/Kconfig index 4915a63866b01..5a91017a143c7 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -19,6 +19,8 @@ config PC104 source "drivers/base/Kconfig" +source "drivers/lego/Kconfig" + source "drivers/bus/Kconfig" source "drivers/cache/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 8e1ffa4358d5f..6c45d15c005c6 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -197,3 +197,6 @@ obj-$(CONFIG_DPLL) += dpll/ obj-$(CONFIG_DIBS) += dibs/ obj-$(CONFIG_S390) += s390/ + +# this must come last to avoid depedency issues +obj-$(CONFIG_LEGO_DRIVERS) += lego/ diff --git a/drivers/lego b/drivers/lego new file mode 160000 index 0000000000000..5f2f1c686d887 --- /dev/null +++ b/drivers/lego @@ -0,0 +1 @@ +Subproject commit 5f2f1c686d887c16ad52678d3796bb08a19aa55c From 97e0cdb0101b5a86a7cb7496d4848a36af1516a2 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 5 May 2016 20:53:31 -0500 Subject: [PATCH 03/21] ev3dev boot logo --- drivers/video/logo/Kconfig | 10 + drivers/video/logo/Makefile | 2 + drivers/video/logo/logo.c | 6 + drivers/video/logo/logo_ev3dev_clut224.ppm | 483 +++++++++++++++++++++ drivers/video/logo/logo_ev3dev_mono.pbm | 95 ++++ include/linux/linux_logo.h | 2 + 6 files changed, 598 insertions(+) create mode 100644 drivers/video/logo/logo_ev3dev_clut224.ppm create mode 100644 drivers/video/logo/logo_ev3dev_mono.pbm diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig index ce6bb753522d2..1bd996c511d47 100644 --- a/drivers/video/logo/Kconfig +++ b/drivers/video/logo/Kconfig @@ -30,6 +30,16 @@ config LOGO_LINUX_CLUT224 bool "Standard 224-color Linux logo" default y +config LOGO_EV3DEV_MONO + bool "ev3dev black and white logo" + depends on MACH_DAVINCI_LEGOEV3 + default y + +config LOGO_EV3DEV_CLUT224 + bool "ev3dev color logo" + depends on MACH_DAVINCI_LEGOEV3 + default y + config LOGO_DEC_CLUT224 bool "224-color Digital Equipment Corporation Linux logo" depends on MACH_DECSTATION || ALPHA diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile index 895c60b8402ea..24c31805a1b88 100644 --- a/drivers/video/logo/Makefile +++ b/drivers/video/logo/Makefile @@ -5,6 +5,8 @@ obj-$(CONFIG_LOGO) += logo.o obj-$(CONFIG_LOGO_LINUX_MONO) += logo_linux_mono.o obj-$(CONFIG_LOGO_LINUX_VGA16) += logo_linux_vga16.o obj-$(CONFIG_LOGO_LINUX_CLUT224) += logo_linux_clut224.o +obj-$(CONFIG_LOGO_EV3DEV_MONO) += logo_ev3dev_mono.o +obj-$(CONFIG_LOGO_EV3DEV_CLUT224) += logo_ev3dev_clut224.o obj-$(CONFIG_LOGO_DEC_CLUT224) += logo_dec_clut224.o obj-$(CONFIG_LOGO_MAC_CLUT224) += logo_mac_clut224.o obj-$(CONFIG_LOGO_PARISC_CLUT224) += logo_parisc_clut224.o diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c index 141f15a9a4590..d08236699b4c7 100644 --- a/drivers/video/logo/logo.c +++ b/drivers/video/logo/logo.c @@ -49,6 +49,9 @@ const struct linux_logo * __ref fb_find_logo(int depth) return NULL; if (depth >= 1) { +#ifdef CONFIG_LOGO_EV3DEV_MONO + logo = &logo_ev3dev_mono; +#endif #ifdef CONFIG_LOGO_LINUX_MONO /* Generic Linux logo */ logo = &logo_linux_mono; @@ -71,6 +74,9 @@ const struct linux_logo * __ref fb_find_logo(int depth) } if (depth >= 8) { +#ifdef CONFIG_LOGO_EV3DEV_CLUT224 + logo = &logo_ev3dev_clut224; +#endif #ifdef CONFIG_LOGO_LINUX_CLUT224 /* Generic Linux logo */ logo = &logo_linux_clut224; diff --git a/drivers/video/logo/logo_ev3dev_clut224.ppm b/drivers/video/logo/logo_ev3dev_clut224.ppm new file mode 100644 index 0000000000000..53abcc350a61b --- /dev/null +++ b/drivers/video/logo/logo_ev3dev_clut224.ppm @@ -0,0 +1,483 @@ +P3 +120 24 +255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 255 0 0 255 0 +0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 0 255 0 +0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 +255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 +255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 0 0 0 0 0 255 0 255 255 0 255 +255 0 255 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 255 0 255 255 0 255 255 0 255 255 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 255 0 +0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 +0 0 0 0 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 +255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 255 0 255 +255 0 255 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 255 255 0 255 255 0 255 255 0 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 255 0 +0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 +0 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 +255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 255 0 255 +255 0 255 255 0 255 255 0 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 255 255 0 255 255 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 +0 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 0 255 255 0 255 255 0 255 255 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 0 255 255 0 255 255 0 255 255 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 0 255 255 0 255 255 0 255 255 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 0 255 255 0 255 255 0 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 +0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 255 255 0 255 255 0 255 255 0 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 255 +255 0 255 255 0 255 255 0 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 +0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 255 0 255 255 0 255 255 0 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 255 255 0 255 +255 0 255 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 0 255 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 +0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 255 0 255 255 0 255 255 0 255 255 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 255 255 0 255 +255 0 255 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 +0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 +0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 255 0 255 255 0 255 255 0 255 +0 0 0 0 0 0 0 0 0 255 0 255 255 0 255 255 0 255 +255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 +0 255 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 255 0 255 255 0 255 255 0 255 +255 0 255 0 0 0 0 0 0 255 0 255 255 0 255 255 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 +0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 255 255 0 255 +255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 +0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 0 255 255 0 255 +255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 +0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 +255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 255 +255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 255 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 +255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 +255 255 0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 0 255 255 0 255 255 0 255 255 0 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 +255 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 +255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 +255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 +0 255 255 0 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 0 255 255 0 255 255 0 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/drivers/video/logo/logo_ev3dev_mono.pbm b/drivers/video/logo/logo_ev3dev_mono.pbm new file mode 100644 index 0000000000000..2d3f337ae35df --- /dev/null +++ b/drivers/video/logo/logo_ev3dev_mono.pbm @@ -0,0 +1,95 @@ +P1 +# CREATOR: GIMP PNM Filter Version 1.1 +178 36 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000111111111111111000000000 +0000001110000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000100000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000010000000000000 +0100000000000000100000100000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000001000000000000001000000000000001000001000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000010000000 +0000001000000000000000100000100000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0011111111111111100000000011101011111111100010000000011111101000001000 +0111111111111111000000000111111000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000001000000000100000100000001 +0000010000000000001000000010000000000000000010000000001000001000000010 +0000100000000000000000000000000000000000000000000000000000000000000000 +0000000000001000000000010000010000001000001000001000000010000001000000 +0000000010010000000000100000100000010000010000000000000000000000000000 +0000000000000000000000000000000000000000000000000010000000000010000010 +0000100000100000100000000100000100000000000000100100000000000100000100 +0001000001000000000000000000000000000000000000000000000000000000000000 +0000000000000000010000000000001000001000010000010000001000000001000010 +0000000000000010100000000000010000010000100000100000000000000000000000 +0000000000000000000000000000000000000000000000000000000100000111000001 +0000010001000001000000101110000010001000001110000000101000001110000010 +0000100010000010000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000110000000000000100000000000 +0000000000000000000000000000000000000000001100000000000001000000000000 +0000000000000000000000000000000000000000000000000000000000000000010000 +0000000000101000001010000100000000000000000000100000000000100000100000 +0000000001010000010100001000000000000000000000000000000000000000000000 +0000000000000000000000000000000001000000000000001001000011000001000000 +0000000010000010000010000010000010000000000000010010000110000010000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0100000000000001000100000100001000000000000000000000100000000000100000 +1000000000000010001000001000010000000000000000000000000000000000000000 +0000000000000000000000000000000000000001000000011111110000100000000010 +0000111111111000000010000000111010000010000000111111100001000000000100 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000001000000000000000001000000010000000000000000000010001000 +0000000000000010000000000000000010000000100000000000000000000000000000 +0000000000000000000000000000000000000000000000000000010000000000001000 +0100000010000010000000000000010000100000000000000010100000000000010000 +1000000100000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000100000000000100000100000100000100000000000000100 +0001000000000000001001000000000001000001000001000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000001000000000 +0010000010000100000010000000000000100000010000000010000010010000000000 +0100000100001000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000011111111110100000011111000000101111111111 +1110000000111111100011101000111111111101000000111110000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000 \ No newline at end of file diff --git a/include/linux/linux_logo.h b/include/linux/linux_logo.h index e37699b7e8393..0e96ee182bc67 100644 --- a/include/linux/linux_logo.h +++ b/include/linux/linux_logo.h @@ -33,6 +33,8 @@ struct linux_logo { extern const struct linux_logo logo_linux_mono; extern const struct linux_logo logo_linux_vga16; extern const struct linux_logo logo_linux_clut224; +extern const struct linux_logo logo_ev3dev_mono; +extern const struct linux_logo logo_ev3dev_clut224; extern const struct linux_logo logo_dec_clut224; extern const struct linux_logo logo_mac_clut224; extern const struct linux_logo logo_parisc_clut224; From 7169c2af974609ab32aa826cc654e8824967a8e0 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 5 May 2016 21:36:04 -0500 Subject: [PATCH 04/21] add I2C_CLASS_LEGOEV3 --- drivers/i2c/i2c-core-base.c | 19 +++++++++++-------- include/linux/i2c.h | 1 + 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index ae7e9c8b65a65..a5d62534d09aa 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -2451,20 +2451,23 @@ static int i2c_detect_address(struct i2c_client *temp_client, int addr = temp_client->addr; int err; - /* Make sure the address is valid */ - err = i2c_check_7bit_addr_validity_strict(addr); - if (err) { - dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n", - addr); - return err; + /* Make sure the address is valid - LEGO devices can break the rules */ + if (!(driver->class & I2C_CLASS_LEGOEV3)) { + err = i2c_check_7bit_addr_validity_strict(addr); + if (err) { + dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n", + addr); + return err; + } } /* Skip if already in use (7 bit, no need to encode flags) */ if (i2c_check_addr_busy(adapter, addr)) return 0; - /* Make sure there is something at this address */ - if (!i2c_default_probe(adapter, addr)) + /* Make sure there is something at this address - skip for LEGO drivers */ + if (!(driver->class & I2C_CLASS_LEGOEV3) + && !i2c_default_probe(adapter, addr)) return 0; /* Finally call the custom detection function */ diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 20fd41b51d5c8..5e947041f7fb4 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -871,6 +871,7 @@ static inline void i2c_mark_adapter_resumed(struct i2c_adapter *adap) #define I2C_CLASS_HWMON (1<<0) /* lm_sensors, ... */ /* Warn users that the adapter doesn't support classes anymore */ #define I2C_CLASS_DEPRECATED (1<<8) +#define I2C_CLASS_LEGOEV3 (1<<31) /* LEGO EV3 sensors */ /* Internal numbers to terminate lists */ #define I2C_CLIENT_END 0xfffeU From 770412e84e07cf3a3d12877758c3283632200273 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 5 May 2016 21:50:09 -0500 Subject: [PATCH 05/21] add default_screen_mode parameter for vt This is needed to correctly display the boot logo with a white background on a monochrome display. --- drivers/tty/vt/vt.c | 14 ++++++++++---- include/linux/vt_kern.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 6e0089b85c270..5726e94566d92 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -38,7 +38,7 @@ * * - Arno Griffioen * - David Carter - * + * * The abstract console driver provides a generic interface for a text * console. It supports VGA text mode, frame buffer based graphical consoles * and special graphics processors that are only accessible through some @@ -158,9 +158,12 @@ static void unblank_screen(void); int default_utf8 = true; module_param(default_utf8, int, S_IRUGO | S_IWUSR); -int global_cursor_default = -1; +int global_cursor_default = 0; module_param(global_cursor_default, int, S_IRUGO | S_IWUSR); EXPORT_SYMBOL(global_cursor_default); +int default_screen_mode = -1; +module_param(default_screen_mode, int, S_IRUGO | S_IWUSR); +EXPORT_SYMBOL(default_screen_mode); static int cur_default = CUR_UNDERLINE; module_param(cur_default, int, S_IRUGO | S_IWUSR); @@ -1095,9 +1098,12 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ goto err_free; /* If no drivers have overridden us and the user didn't pass a - boot option, default to displaying the cursor */ + boot option, default to displaying the cursor and normal + screen mode */ if (global_cursor_default == -1) global_cursor_default = 1; + if (default_screen_mode == -1) + default_screen_mode = 1; vc_init(vc, 1); vcs_make_sysfs(currcons); @@ -2224,7 +2230,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear) vc->vc_disp_ctrl = 0; vc->vc_toggle_meta = 0; - vc->vc_decscnm = 0; + vc->vc_decscnm = default_screen_mode; vc->vc_decom = 0; vc->vc_decawm = 1; vc->vc_deccm = global_cursor_default; diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index d008c3d0a9bbf..d47d075710487 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -130,6 +130,7 @@ int vty_init(const struct file_operations *console_fops); extern bool vt_dont_switch; extern int default_utf8; extern int global_cursor_default; +extern int default_screen_mode; struct vt_spawn_console { spinlock_t lock; From 96d2417dad3fabe399addc10724afba51bbd3a54 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sun, 14 Dec 2014 22:36:10 -0600 Subject: [PATCH 06/21] add LEGO WeDo to hid-ids.h and make the hid driver ignore it --- drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-quirks.c | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index c4589075a5ed6..5cf146c17ef20 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -782,6 +782,9 @@ #define USB_VENDOR_ID_LCPOWER 0x1241 #define USB_DEVICE_ID_LCPOWER_LC1000 0xf767 +#define USB_VENDOR_ID_LEGO 0x0694 +#define USB_DEVICE_ID_LEGO_WEDO 0x0003 + #define USB_VENDOR_ID_LD 0x0f11 #define USB_DEVICE_ID_LD_CASSY 0x1000 #define USB_DEVICE_ID_LD_CASSY2 0x1001 diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index c89a015686c07..cca9a9914975e 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -843,6 +843,7 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_KYE, 0x0058) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LEGO, USB_DEVICE_ID_LEGO_WEDO) }, { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) }, { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY2) }, { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, From 50ddaa58c452eaa3d10e892006aecfa5b3a7ec45 Mon Sep 17 00:00:00 2001 From: vs7 Date: Mon, 16 Nov 2015 08:24:58 +0100 Subject: [PATCH 07/21] HID: sony: Enable Bluetooth Gasia third-party PS3 controllers --- drivers/hid/hid-sony.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index b966e4044238c..abfcce6dec883 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1184,6 +1184,21 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev) static const u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; u8 *buf; int ret; + unsigned char enable_gasia[] = { + 0xA2, + 0x01, + /* 0x00, right-timeout, right-force, left-timeout, left-force */ + 0x00, 0x00, 0x00, 0x00, 0x00, /* rumble values */ + 0x00, 0x00, 0x00, 0x00, 0x02, /* 0x02=LED1 .. 0x10=LED4 */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED 4 */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED 3 */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED 2 */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED 1 */ + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + }; buf = kmemdup(report, sizeof(report), GFP_KERNEL); if (!buf) @@ -1191,6 +1206,9 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev) ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report), HID_FEATURE_REPORT, HID_REQ_SET_REPORT); + hid_hw_raw_request(hdev, enable_gasia[0], enable_gasia, + sizeof(enable_gasia), HID_FEATURE_REPORT, + HID_REQ_SET_REPORT); kfree(buf); From 0e022f783741330c8291f0be02abe14a8a38af3a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 2 Jan 2017 21:24:10 -0600 Subject: [PATCH 08/21] usb: musb: da8xx: Add special endpoint config for ev3dev The lms2012 software expects USB to be able to handle 1024 byte packets on USB ep1. There is no existing configuration for this in the kernel, so we have to add our own. The maxpacket values come from the official LEGO firmware source code: https://github.com/mindboards/ev3sources/blob/master/extra/linux-03.20.00.13/drivers/usb/musb/musb_core.c#L1065 Issue: ev3dev/lms2012-compat#49 --- drivers/usb/musb/da8xx.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 4209f438ba184..47f2d25094acf 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -500,7 +500,20 @@ static const struct platform_device_info da8xx_dev_info = { .dma_mask = DMA_BIT_MASK(32), }; +/* special config to match official LEGO firmware */ +static struct musb_fifo_cfg ev3dev_cfg[] = { + { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 1024, }, + { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 1024, }, + { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64 , }, + { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 64 , }, + { .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 1024, }, + /* TODO: what about ep3 FIFO_RX? */ + { .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 128, }, +}; + static const struct musb_hdrc_config da8xx_config = { + .fifo_cfg = ev3dev_cfg, + .fifo_cfg_size = ARRAY_SIZE(ev3dev_cfg), .ram_bits = 10, .num_eps = 5, .multipoint = 1, From fb5ef22e10a0a619a2e9919eed1153292cbb21e2 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 22 Aug 2016 17:47:48 -0500 Subject: [PATCH 09/21] i2c: expose adapter probe and remove probed functions Publicly expose functions for detecting devices and removing detected devices. Currently an i2c adapter only probes/detects new devices when the adapter is added or when a new i2c driver is added. This adds a new function, i2c_adapter_probe(), that allows detecting sensors at any time. Furthermore, the function i2c_adapter_remove_probed() is added to remove the devices added by i2c_adapter_probe() at any time. The intended use of these functions is for LEGO MINDSTORMS sensors. These are hot-plugable I2C devices. When a sensor is connected, i2c_adapter_probe() is called to automatically configure the sensor. When the sensor is disconnected, i2c_adapter_remove_probed() is called to remove the automatically configured device. Signed-off-by: David Lechner --- drivers/i2c/i2c-core-base.c | 45 +++++++++++++++++++++++++++++++------ include/linux/i2c.h | 3 +++ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index a5d62534d09aa..b828eb2340949 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -1516,6 +1516,23 @@ int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr) } EXPORT_SYMBOL_GPL(i2c_handle_smbus_host_notify); +/** + * i2c_adapter_probe - probe adapter for clients + * @adap: The i2c adapter. + * + * This calls the detect function of each driver that matches the class of the + * adapter. This function is called when an adapter is added, so there is no + * need to call this manually, unless you have hot-plugable i2c devices that + * are connected after the adapter is created. + */ +void i2c_adapter_probe(struct i2c_adapter *adap) +{ + mutex_lock(&core_lock); + bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); + mutex_unlock(&core_lock); +} +EXPORT_SYMBOL(i2c_adapter_probe); + static int i2c_register_adapter(struct i2c_adapter *adap) { int res = -EINVAL; @@ -1598,9 +1615,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap) i2c_scan_static_board_info(adap); /* Notify drivers */ - mutex_lock(&core_lock); - bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); - mutex_unlock(&core_lock); + i2c_adapter_probe(adap); return 0; @@ -1744,6 +1759,25 @@ static int __process_removed_adapter(struct device_driver *d, void *data) return 0; } +/** + * i2c_adapter_remove_probed - Remove clients that were automatically detected. + * @adap: The i2c adapter. + * + * This removes all i2c clients from this adapter that were added via driver + * detect() functions. This function is called when an adapter is removed, so + * there is no need to call this manually, unless you have hot-plugable i2c + * devices that are disconnected before the adapter is destroyed. + * + * Any clients that were added manually (e.g. via sysfs) are not removed. + */ +void i2c_adapter_remove_probed(struct i2c_adapter *adap) +{ + mutex_lock(&core_lock); + bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_removed_adapter); + mutex_unlock(&core_lock); +} +EXPORT_SYMBOL(i2c_adapter_remove_probed); + /** * i2c_del_adapter - unregister I2C adapter * @adap: the adapter being unregistered @@ -1768,10 +1802,7 @@ void i2c_del_adapter(struct i2c_adapter *adap) i2c_acpi_remove_space_handler(adap); /* Tell drivers about this removal */ - mutex_lock(&core_lock); - bus_for_each_drv(&i2c_bus_type, NULL, adap, - __process_removed_adapter); - mutex_unlock(&core_lock); + i2c_adapter_remove_probed(adap); /* Remove devices instantiated from sysfs */ mutex_lock_nested(&adap->userspace_clients_lock, diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 5e947041f7fb4..d527dad62bc32 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -891,6 +891,9 @@ int devm_i2c_add_adapter(struct device *dev, struct i2c_adapter *adapter); void i2c_del_adapter(struct i2c_adapter *adap); int i2c_add_numbered_adapter(struct i2c_adapter *adap); +extern void i2c_adapter_probe(struct i2c_adapter *adap); +extern void i2c_adapter_remove_probed(struct i2c_adapter *adap); + int i2c_register_driver(struct module *owner, struct i2c_driver *driver); void i2c_del_driver(struct i2c_driver *driver); From 6e2c0b37d46352772a3b773c47e6615ca1deaf83 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 31 Jul 2017 16:57:44 -0500 Subject: [PATCH 10/21] fbdev: set default margin color to white ev3dev: doing this so we don't waste space in the kernel command line. This is the same as setting fbcon=margin:7 --- drivers/video/fbdev/core/fbcon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index e7e07eb2142eb..29aba6399bf38 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -168,7 +168,8 @@ static int info_idx = -1; /* console rotation */ static int initial_rotation = -1; -static int margin_color; +static int fbcon_has_sysfs; +static int margin_color = 7; static const struct consw fb_con; From 75894dcc8decf1bb8363e0969c459354b05ef5d3 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 13 Jul 2018 17:49:01 -0500 Subject: [PATCH 11/21] iio: trigger: add in-kernel function for setting hrtimer sampling frequency --- drivers/iio/trigger/iio-trig-hrtimer.c | 59 ++++++++++++++++++++------ include/linux/iio/sw_trigger.h | 3 ++ 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/drivers/iio/trigger/iio-trig-hrtimer.c b/drivers/iio/trigger/iio-trig-hrtimer.c index 82c72baccb623..a020f6fb1bebb 100644 --- a/drivers/iio/trigger/iio-trig-hrtimer.c +++ b/drivers/iio/trigger/iio-trig-hrtimer.c @@ -33,6 +33,50 @@ static const struct config_item_type iio_hrtimer_type = { .ct_owner = THIS_MODULE, }; +static struct iio_sw_trigger_type iio_trig_hrtimer; + +static int __iio_hrtimer_set_sampling_frequency(struct iio_hrtimer_info *info, + int integer, int fract) +{ + u64 val, period; + + val = fract + 1000ULL * integer; /* mHz */ + + if (!val || val > UINT_MAX) + return -EINVAL; + + info->sampling_frequency[0] = integer; /* Hz */ + info->sampling_frequency[1] = fract * 1000; /* uHz */ + period = PSEC_PER_SEC; + do_div(period, val); + info->period = period; /* nS */ + + return 0; +} + +/** + * iio_hrtimer_set_sampling_frequency - set the sampling frequency + * @sw_trigger: a hrtimer trigger + * @freq: the sampling rate in Hz + * + * Returns 0 on success or -EINVAL if the trigger is not an hrtimer trigger + * or the frequency is out of range. + */ +int iio_hrtimer_set_sampling_frequency(struct iio_sw_trigger *sw_trigger, + unsigned long freq) +{ + struct iio_hrtimer_info *info; + + + if (sw_trigger->trigger_type != &iio_trig_hrtimer) + return -EINVAL; + + info = iio_trigger_get_drvdata(sw_trigger->trigger); + + return __iio_hrtimer_set_sampling_frequency(info, freq, 0); +} +EXPORT_SYMBOL_GPL(iio_hrtimer_set_sampling_frequency); + static ssize_t iio_hrtimer_show_sampling_frequency(struct device *dev, struct device_attribute *attr, @@ -53,8 +97,6 @@ ssize_t iio_hrtimer_store_sampling_frequency(struct device *dev, { struct iio_trigger *trig = to_iio_trigger(dev); struct iio_hrtimer_info *info = iio_trigger_get_drvdata(trig); - unsigned long long val; - u64 period; int integer, fract, ret; ret = iio_str_to_fixpoint(buf, 100, &integer, &fract); @@ -63,16 +105,9 @@ ssize_t iio_hrtimer_store_sampling_frequency(struct device *dev, if (integer < 0 || fract < 0) return -ERANGE; - val = fract + 1000ULL * integer; /* mHz */ - - if (!val || val > UINT_MAX) - return -EINVAL; - - info->sampling_frequency[0] = integer; /* Hz */ - info->sampling_frequency[1] = fract * 1000; /* uHz */ - period = PSEC_PER_SEC; - do_div(period, val); - info->period = period; /* nS */ + ret = __iio_hrtimer_set_sampling_frequency(info, integer, fract); + if (ret) + return ret; return len; } diff --git a/include/linux/iio/sw_trigger.h b/include/linux/iio/sw_trigger.h index bc77f88df303a..76a8e882960c9 100644 --- a/include/linux/iio/sw_trigger.h +++ b/include/linux/iio/sw_trigger.h @@ -61,4 +61,7 @@ void iio_swt_group_init_type_name(struct iio_sw_trigger *t, #endif } +int iio_hrtimer_set_sampling_frequency(struct iio_sw_trigger *sw_trigger, + unsigned long freq); + #endif /* __IIO_SW_TRIGGER */ From ace645153174c901479abe763b222c2c38dd48f5 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 26 Jul 2018 16:07:33 -0500 Subject: [PATCH 12/21] ev3dev hack: trigger UART Rx earlier this helps improve EV3 UART sensors overflowing the hardware FIFO at the expense of more CPU usage --- drivers/tty/serial/8250/8250_port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 719faf92aa8ae..af8ec00f37675 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -257,7 +257,7 @@ static const struct serial8250_config uart_config[] = { .fifo_size = 16, .tx_loadsz = 16, .fcr = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO | - UART_FCR_R_TRIG_10, + UART_FCR_R_TRIG_00, .rxtrig_bytes = {1, 4, 8, 14}, .flags = UART_CAP_FIFO | UART_CAP_AFE, }, From 98e16e0b33364a6dc4687998dbfdda32aee43358 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 23 Feb 2019 14:58:43 -0600 Subject: [PATCH 13/21] ev3dev hack: add fixed timer trigger to ADC We need to poll the ADC every 100ms, so add a hrtimer tirgger when the driver is probed. --- drivers/iio/adc/ti-ads7950.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c index bbe1ce5777895..d93b9c9fd1d27 100644 --- a/drivers/iio/adc/ti-ads7950.c +++ b/drivers/iio/adc/ti-ads7950.c @@ -27,7 +27,9 @@ #include #include +#include #include +#include #include #include @@ -74,6 +76,7 @@ struct ti_ads7950_state { struct mutex slock; struct gpio_chip chip; + struct iio_sw_trigger *hrtimer_trigger; struct regulator *reg; unsigned int vref_mv; @@ -637,6 +640,15 @@ static int ti_ads7950_probe(struct spi_device *spi) goto error_cleanup_ring; } + /* Hack to create continuous polling mode */ + st->hrtimer_trigger = iio_sw_trigger_create("hrtimer", dev_name(&spi->dev)); + if (IS_ERR(st->hrtimer_trigger)) { + ret = PTR_ERR(st->hrtimer_trigger); + goto error_iio_device; + } + + iio_trigger_set_immutable(indio_dev, st->hrtimer_trigger->trigger); + /* Add GPIO chip */ st->chip.label = dev_name(&st->spi->dev); st->chip.parent = &st->spi->dev; From b748f26f1f0beb5c1be919d758915bfee8d5997e Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 6 Aug 2018 13:07:35 -0500 Subject: [PATCH 14/21] ev3dev hack: hid-sony: change default poll interval for PS4 controller EV3 doesn't have enough CPU power to handle more frequent polling --- drivers/hid/hid-playstation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 128aa6abd10be..3cdcc3c6408a9 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -373,7 +373,7 @@ struct dualsense_output_report { */ #define DS4_OUTPUT_HWCTL_BT_POLL_MASK 0x3F /* Default to 4ms poll interval, which is same as USB (not adjustable). */ -#define DS4_BT_DEFAULT_POLL_INTERVAL_MS 4 +#define DS4_BT_DEFAULT_POLL_INTERVAL_MS 10 /* changed for ev3dev */ #define DS4_OUTPUT_HWCTL_CRC32 0x40 #define DS4_OUTPUT_HWCTL_HID 0x80 From 8ffc16bf60c1c3b220aafda40c48ce922cf40e3d Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 30 Mar 2024 17:36:38 -0500 Subject: [PATCH 15/21] ev3dev hack: add more line discipline constants Signed-off-by: David Lechner --- include/uapi/linux/tty.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/tty.h b/include/uapi/linux/tty.h index 68aeae2addeca..aec638cb84c65 100644 --- a/include/uapi/linux/tty.h +++ b/include/uapi/linux/tty.h @@ -39,8 +39,10 @@ #define N_MCTP 28 /* MCTP-over-serial */ #define N_DEVELOPMENT 29 /* Manual out-of-tree testing */ #define N_CAN327 30 /* ELM327 based OBD-II interfaces */ +#define N_LEGOEV3 31 /* LEGO MINDSTORMS EV3 UART Sensor */ +#define N_D_UART 32 /* LMS2012 UART */ /* Always the newest line discipline + 1 */ -#define NR_LDISCS 31 +#define NR_LDISCS 33 #endif /* _UAPI_LINUX_TTY_H */ From eb218e48df363c412f624cf00a095892e29ddf94 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 1 Apr 2024 09:06:49 -0500 Subject: [PATCH 16/21] remoteproc: add page lookup for TI PRU to ELF loader This adds a special handler to the default remoteproc ELF firmware loader that looks up the memory page on TI PRU firmware files. These processors have multiple memory maps that share the same address space, so we need to know the page in addition to the physical address in order to translate the address to a local CPU address. Signed-off-by: David Lechner --- include/linux/skbuff.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index a7cc3d1f4fd11..e4b66434a6fc8 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -915,7 +915,7 @@ struct sk_buff { * want to keep them across layers you have to do a skb_clone() * first. This is owned by whoever has the skb queued ATM. */ - char cb[48] __aligned(8); + char cb[64] __aligned(8); union { struct { From 275a3af05a70a8e4334fbb2f50e6637e3947c4ab Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 1 Apr 2024 09:07:39 -0500 Subject: [PATCH 17/21] ev3dev hack: expose fiq in interupt controller --- drivers/irqchip/irq-davinci-cp-intc.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/irqchip/irq-davinci-cp-intc.c b/drivers/irqchip/irq-davinci-cp-intc.c index 00cdcc90f614e..c47dee3f6e06e 100644 --- a/drivers/irqchip/irq-davinci-cp-intc.c +++ b/drivers/irqchip/irq-davinci-cp-intc.c @@ -244,3 +244,19 @@ static int __init davinci_cp_intc_of_init(struct device_node *node, return davinci_cp_intc_do_init(&res, num_irqs, node); } IRQCHIP_DECLARE(cp_intc, "ti,cp-intc", davinci_cp_intc_of_init); + +/* ev3dev hacks */ + +void cp_intc_fiq_enable(void); +void cp_intc_fiq_enable(void) +{ + davinci_cp_intc_write(0, DAVINCI_CP_INTC_HOST_ENABLE_IDX_SET); +} +EXPORT_SYMBOL_GPL(cp_intc_fiq_enable); + +void cp_intc_fiq_disable(void); +void cp_intc_fiq_disable(void) +{ + davinci_cp_intc_write(0, DAVINCI_CP_INTC_HOST_ENABLE_IDX_CLR); +} +EXPORT_SYMBOL_GPL(cp_intc_fiq_disable); From e4ee764104ce39dac6657f584023c4185d74c97b Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 1 Apr 2024 09:51:59 -0500 Subject: [PATCH 18/21] fixup! ev3dev: cumulative ev3dev changes to arm arch code --- .../davinci}/da850-lego-ev3-adafruit18.dts | 0 .../{ => ti/davinci}/da850-lego-ev3-color.dts | 0 .../davinci}/da850-lego-ev3-lms2012.dts | 0 .../boot/dts/ti/davinci/da850-lego-ev3.dts | 2 +- arch/arm/configs/ev3dev_defconfig | 69 +++++-------------- arch/arm/mach-davinci/legoev3-dt.c | 21 +++++- arch/arm/mach-davinci/legoev3-fiq.c | 13 ++-- arch/arm/mach-davinci/legoev3-fiq.h | 3 + 8 files changed, 45 insertions(+), 63 deletions(-) rename arch/arm/boot/dts/{ => ti/davinci}/da850-lego-ev3-adafruit18.dts (100%) rename arch/arm/boot/dts/{ => ti/davinci}/da850-lego-ev3-color.dts (100%) rename arch/arm/boot/dts/{ => ti/davinci}/da850-lego-ev3-lms2012.dts (100%) diff --git a/arch/arm/boot/dts/da850-lego-ev3-adafruit18.dts b/arch/arm/boot/dts/ti/davinci/da850-lego-ev3-adafruit18.dts similarity index 100% rename from arch/arm/boot/dts/da850-lego-ev3-adafruit18.dts rename to arch/arm/boot/dts/ti/davinci/da850-lego-ev3-adafruit18.dts diff --git a/arch/arm/boot/dts/da850-lego-ev3-color.dts b/arch/arm/boot/dts/ti/davinci/da850-lego-ev3-color.dts similarity index 100% rename from arch/arm/boot/dts/da850-lego-ev3-color.dts rename to arch/arm/boot/dts/ti/davinci/da850-lego-ev3-color.dts diff --git a/arch/arm/boot/dts/da850-lego-ev3-lms2012.dts b/arch/arm/boot/dts/ti/davinci/da850-lego-ev3-lms2012.dts similarity index 100% rename from arch/arm/boot/dts/da850-lego-ev3-lms2012.dts rename to arch/arm/boot/dts/ti/davinci/da850-lego-ev3-lms2012.dts diff --git a/arch/arm/boot/dts/ti/davinci/da850-lego-ev3.dts b/arch/arm/boot/dts/ti/davinci/da850-lego-ev3.dts index bea8b79e9d3e5..ca8dabfc76f7c 100644 --- a/arch/arm/boot/dts/ti/davinci/da850-lego-ev3.dts +++ b/arch/arm/boot/dts/ti/davinci/da850-lego-ev3.dts @@ -780,7 +780,7 @@ #size-cells = <1>; /* Hardware ID + Bluetooth MAC address */ - hw_id: hw-id@0x3F00 { + hw_id: hw-id@3F00 { reg = <0x3F00 12>; }; diff --git a/arch/arm/configs/ev3dev_defconfig b/arch/arm/configs/ev3dev_defconfig index faf51733d6ff8..b517875676d55 100644 --- a/arch/arm/configs/ev3dev_defconfig +++ b/arch/arm/configs/ev3dev_defconfig @@ -2,14 +2,13 @@ CONFIG_LOCALVERSION="-ev3" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y -CONFIG_NO_HZ=y +CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y CONFIG_PREEMPT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=15 CONFIG_CGROUPS=y -CONFIG_NAMESPACES=y CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set @@ -17,31 +16,23 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_LZO is not set # CONFIG_RD_LZ4 is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS_ALL=y -CONFIG_EMBEDDED=y +# CONFIG_ARCH_MULTI_V7 is not set CONFIG_ARCH_DAVINCI=y CONFIG_ARCH_DAVINCI_DA850=y -# CONFIG_MACH_DAVINCI_DA850_EVM is not set CONFIG_MACH_DAVINCI_LEGOEV3=y CONFIG_LEGOEV3_FIQ=y CONFIG_AEABI=y -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CPU_IDLE=y # CONFIG_SUSPEND is not set CONFIG_PM=y +CONFIG_STRICT_KERNEL_RWX=y +CONFIG_STRICT_MODULE_RWX=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y -# CONFIG_BLK_DEV_BSG is not set CONFIG_PARTITION_ADVANCED=y # CONFIG_EFI_PARTITION is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_ZSMALLOC=y -CONFIG_PGTABLE_MAPPING=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -75,7 +66,6 @@ CONFIG_CFG80211=m CONFIG_MAC80211=m CONFIG_MAC80211_DEBUG_MENU=y CONFIG_RFKILL=y -# CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y # CONFIG_STANDALONE is not set @@ -83,18 +73,16 @@ CONFIG_EXTRA_FIRMWARE="PRU_SUART.bin ev3-pru1.fw" CONFIG_EXTRA_FIRMWARE_DIR="drivers/lego/ev3/firmware" CONFIG_LEGO_DRIVERS=y CONFIG_LEGOEV3_I2C=y +# CONFIG_LEGOEV3_PRU is not set CONFIG_LEGOEV3_SOUND=y CONFIG_NXT_ANALOG_SENSORS=m CONFIG_EV3_ANALOG_SENSORS=m CONFIG_NXT_I2C_SENSORS=m CONFIG_EV3_UART_SENSORS=m CONFIG_LEGO_SERVO_MOTORS=m -CONFIG_LMS2012_COMPAT=m +# CONFIG_LMS2012_COMPAT is not set CONFIG_WEDO=m -CONFIG_BRICKPI=m CONFIG_BOARD_INFO=y -CONFIG_SERIAL_SUART_OMAPL_PRU=y -CONFIG_TI_PRU_RPROC_EV3DEV=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_BLOCK=y @@ -107,6 +95,7 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=m CONFIG_CHR_DEV_SG=y +# CONFIG_BLK_DEV_BSG is not set CONFIG_NETDEVICES=y CONFIG_TUN=m # CONFIG_ETHERNET is not set @@ -122,13 +111,6 @@ CONFIG_PPP_SYNC_TTY=m CONFIG_USB_PEGASUS=m CONFIG_USB_RTL8150=m CONFIG_USB_RTL8152=m -CONFIG_USB_NET_CDC_EEM=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_NET1080 is not set -CONFIG_USB_NET_QMI_WWAN=m CONFIG_USB_IPHETH=m CONFIG_ATH9K_HTC=m CONFIG_AR5523=m @@ -143,11 +125,8 @@ CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RTL8187=m # CONFIG_RTL_CARDS is not set -CONFIG_RTL8192CU=m CONFIG_RTL8XXXU=m -CONFIG_USB_ZD1201=m CONFIG_ZD1211RW=m -CONFIG_USB_NET_RNDIS_WLAN=m CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y CONFIG_KEYBOARD_GPIO_POLLED=y @@ -167,17 +146,13 @@ CONFIG_SERIAL_8250_NR_UARTS=3 CONFIG_SERIAL_8250_RUNTIME_UARTS=3 CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SERIAL_DEV_BUS=y -CONFIG_TTY_PRINTK=y CONFIG_HW_RANDOM=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_DAVINCI=y CONFIG_SPI=y CONFIG_SPI_DAVINCI=y CONFIG_PINCTRL_DA850_PUPD=y -CONFIG_PINCTRL_SINGLE=y -CONFIG_GPIO_SYSFS=y -CONFIG_GPIO_PCA953X=y -CONFIG_GPIO_PCF857X=m +CONFIG_GPIOLIB=y CONFIG_POWER_RESET=y CONFIG_POWER_RESET_GPIO=y CONFIG_BATTERY_LEGO_EV3=y @@ -186,8 +161,6 @@ CONFIG_SENSORS_LM75=m CONFIG_SENSORS_PCF8591=m CONFIG_WATCHDOG=y CONFIG_DAVINCI_WATCHDOG=y -CONFIG_SSB=m -CONFIG_TPS6507X=m CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_GPIO=y @@ -196,15 +169,11 @@ CONFIG_MEDIA_SUPPORT=m CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=m -CONFIG_USB_STV06XX=m -CONFIG_USB_GSPCA_SPCA561=m -CONFIG_USB_GSPCA_ZC3XX=m CONFIG_DRM=y -CONFIG_DRM_TINYDRM=y CONFIG_TINYDRM_ST7586=y CONFIG_TINYDRM_ST7735R=y +CONFIG_FB=y CONFIG_BACKLIGHT_GPIO=y -CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set @@ -271,7 +240,6 @@ CONFIG_USB_MIDI_GADGET=m CONFIG_USB_CDC_COMPOSITE=m CONFIG_MMC=y CONFIG_MMC_DAVINCI=y -CONFIG_LEDS_CLASS=y CONFIG_LEDS_GPIO=y CONFIG_LEDS_PWM=y CONFIG_LEDS_TRIGGER_TIMER=y @@ -282,17 +250,17 @@ CONFIG_RTC_CLASS=y # CONFIG_RTC_HCTOSYS is not set CONFIG_RTC_DRV_DS1307=m CONFIG_DMADEVICES=y -CONFIG_STAGING=y -CONFIG_R8712U=y -CONFIG_FB_TFT=y -CONFIG_FB_TFT_ST7735R=y CONFIG_COMMON_CLK_PWM=y +CONFIG_REMOTEPROC=y CONFIG_RPMSG_CHAR=m +CONFIG_RPMSG_VIRTIO=y CONFIG_IIO=y CONFIG_IIO_BUFFER_CB=y CONFIG_IIO_SW_DEVICE=m +CONFIG_IIO_SW_TRIGGER=y CONFIG_TI_ADS7950=y CONFIG_TCS3472=m +CONFIG_IIO_HRTIMER_TRIGGER=y CONFIG_IIO_INTERRUPT_TRIGGER=m CONFIG_IIO_SYSFS_TRIGGER=m CONFIG_PWM=y @@ -305,7 +273,6 @@ CONFIG_BTRFS_FS=m CONFIG_BTRFS_FS_POSIX_ACL=y CONFIG_F2FS_FS=m CONFIG_FANOTIFY=y -CONFIG_AUTOFS4_FS=y CONFIG_FUSE_FS=m CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y @@ -323,12 +290,11 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ASCII=m CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=y -CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CCM=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_ARC4=y -CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_LZ4=y # CONFIG_CRYPTO_HW is not set CONFIG_CRC_CCITT=y @@ -340,7 +306,4 @@ CONFIG_FONT_8x8=y CONFIG_FONT_6x11=y CONFIG_FONT_MINI_4x6=y CONFIG_DEBUG_FS=y -# CONFIG_SCHED_DEBUG is not set -# CONFIG_DEBUG_PREEMPT is not set -# CONFIG_FTRACE is not set -# CONFIG_ARM_UNWIND is not set +CONFIG_UNWINDER_FRAME_POINTER=y diff --git a/arch/arm/mach-davinci/legoev3-dt.c b/arch/arm/mach-davinci/legoev3-dt.c index 88789ebba2130..7c47bc2058002 100644 --- a/arch/arm/mach-davinci/legoev3-dt.c +++ b/arch/arm/mach-davinci/legoev3-dt.c @@ -15,8 +15,7 @@ #include "da8xx.h" #include "legoev3-fiq.h" -#include "board-legoev3.h" -#include "cp_intc.h" +#include "irqs.h" #define LEGOEV3_DT 1 #include <../../../drivers/lego/ev3/legoev3_i2c.h> @@ -24,6 +23,24 @@ #define DA8XX_EHRPWM0_BASE 0x01F00000 +/* Convert GPIO signal to GPIO pin number */ +#define GPIO_TO_PIN(bank, gpio) (16 * (bank) + (gpio)) + +/* + * Used by FIQ handler routine to notify the OS when status has changed. See + * arch/arm/mach-davinci/legoev3-fiq.c. This pin is TP4 in the lms2012 source + * code, so it should be safe to use. + */ +#define EV3_FIQ_STAT_PIN GPIO_TO_PIN(2, 7) +#define EV3_IN1_PIN6_PIN GPIO_TO_PIN(0, 15) +#define EV3_IN1_I2C_CLK_PIN GPIO_TO_PIN(1, 0) +#define EV3_IN2_PIN6_PIN GPIO_TO_PIN(0, 13) +#define EV3_IN2_I2C_CLK_PIN GPIO_TO_PIN(8, 3) +#define EV3_IN3_PIN6_PIN GPIO_TO_PIN(1, 14) +#define EV3_IN3_I2C_CLK_PIN GPIO_TO_PIN(1, 12) +#define EV3_IN4_PIN6_PIN GPIO_TO_PIN(1, 15) +#define EV3_IN4_I2C_CLK_PIN GPIO_TO_PIN(1, 11) + static struct legoev3_fiq_platform_data legoev3_in_port_i2c_platform_data = { .intc_mem_base = DA8XX_CP_INTC_BASE, .intc_mem_size = 0x608, diff --git a/arch/arm/mach-davinci/legoev3-fiq.c b/arch/arm/mach-davinci/legoev3-fiq.c index 037da8e08a7a1..4414ad2b79963 100644 --- a/arch/arm/mach-davinci/legoev3-fiq.c +++ b/arch/arm/mach-davinci/legoev3-fiq.c @@ -27,9 +27,8 @@ #include #include -#include -#include "cp_intc.h" +#include "legoev3-fiq.h" enum transfer_states { TRANSFER_IDLE, @@ -284,14 +283,14 @@ legoev3_fiq_timer_callback(struct legoev3_fiq_port_i2c_data *data) if (msg->flags & I2C_M_RD) data->data_byte |= 1; data->buf_offset = 0; - /* no break */ + fallthrough; case TRANSFER_WRITE: if (data->transfer_state == TRANSFER_WRITE) data->data_byte = msg->buf[data->buf_offset++]; data->transfer_state = TRANSFER_WBIT; data->bit_mask = 0x80; - /* no break */ + fallthrough; case TRANSFER_WBIT: if (!data->clock_state) { @@ -310,7 +309,7 @@ legoev3_fiq_timer_callback(struct legoev3_fiq_port_i2c_data *data) data->transfer_state = TRANSFER_RBIT; data->bit_mask = 0x80; data->data_byte = 0; - /* no break */ + fallthrough; case TRANSFER_RBIT: if (data->clock_state) { @@ -421,7 +420,7 @@ legoev3_fiq_timer_callback(struct legoev3_fiq_port_i2c_data *data) */ fiq_gpio_dir_in(&data->gpio[FIQ_I2C_PIN_SDA]); data->transfer_state = TRANSFER_COMPLETE; - /* no break */ + fallthrough; case TRANSFER_COMPLETE: /* @@ -480,7 +479,7 @@ static void legoev3_fiq_ehrpwm_callback(struct legoev3_fiq_ehrpwm_data *data) !fiq_gpio_get_value(&legoev3_fiq_data->status_gpio)); } -void legoev3_fiq_handler(void) +static void legoev3_fiq_handler(void) { int irq = legoev3_fiq_get_irq(); diff --git a/arch/arm/mach-davinci/legoev3-fiq.h b/arch/arm/mach-davinci/legoev3-fiq.h index dba799602de38..7a4b5152a60b0 100644 --- a/arch/arm/mach-davinci/legoev3-fiq.h +++ b/arch/arm/mach-davinci/legoev3-fiq.h @@ -66,4 +66,7 @@ extern int legoev3_fiq_ehrpwm_int_enable(void); extern int legoev3_fiq_ehrpwm_int_disable(void); extern bool legoev3_fiq_ehrpwm_int_is_enabled(void); +void cp_intc_fiq_enable(void); +void cp_intc_fiq_disble(void); + #endif /* __MACH_LEGOEV3_FIQ_H */ From 67b682e3c2922662b7fdb5f112ff8dd073ae36eb Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 1 Apr 2024 09:55:48 -0500 Subject: [PATCH 19/21] fixup! lego-linux-drivers submodule --- drivers/lego | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/lego b/drivers/lego index 5f2f1c686d887..2e9d81c37bcf7 160000 --- a/drivers/lego +++ b/drivers/lego @@ -1 +1 @@ -Subproject commit 5f2f1c686d887c16ad52678d3796bb08a19aa55c +Subproject commit 2e9d81c37bcf7c9df237ae8e7bb3fc28d6dc3d2f From 372d96ace472c9b3d99cf6d97c69f7a1462be110 Mon Sep 17 00:00:00 2001 From: project516 <138796702+Project516@users.noreply.github.com> Date: Fri, 12 Dec 2025 13:58:42 -0600 Subject: [PATCH 20/21] Updates to get ev3-kernel to compile with 6.12.60 --- .gitmodules | 2 +- arch/arm/mach-davinci/legoev3-fiq.c | 5 ++++- drivers/lego | 2 +- scripts/Makefile.package | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index aa18025fc3742..a8f05e704a0a5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "drivers/lego"] path = drivers/lego - url = https://github.com/ev3dev/lego-linux-drivers + url = https://github.com/project516/lego-linux-drivers diff --git a/arch/arm/mach-davinci/legoev3-fiq.c b/arch/arm/mach-davinci/legoev3-fiq.c index 4414ad2b79963..40146b7b6061a 100644 --- a/arch/arm/mach-davinci/legoev3-fiq.c +++ b/arch/arm/mach-davinci/legoev3-fiq.c @@ -864,7 +864,10 @@ static int legoev3_fiq_probe(struct platform_device *pdev) fiq_data->timer_irq = pdata->timer_irq; fiq_data->ehrpwm_irq = pdata->ehrpwm_irq; - ret = gpio_request_one(pdata->status_gpio, GPIOF_INIT_LOW, "fiq status"); + ret = gpio_request(pdata->status_gpio, "fiq status"); + if (!ret) { + ret = gpio_direction_output(pdata->status_gpio, 0); + } if (ret < 0) { if (ret != -EPROBE_DEFER) { dev_err(&pdev->dev, diff --git a/drivers/lego b/drivers/lego index 2e9d81c37bcf7..bec2d381b8fbc 160000 --- a/drivers/lego +++ b/drivers/lego @@ -1 +1 @@ -Subproject commit 2e9d81c37bcf7c9df237ae8e7bb3fc28d6dc3d2f +Subproject commit bec2d381b8fbceb2c8e59f4234c8066e3d6493e3 diff --git a/scripts/Makefile.package b/scripts/Makefile.package index 74bcb9e7f7a45..dd955bdf69910 100644 --- a/scripts/Makefile.package +++ b/scripts/Makefile.package @@ -123,7 +123,7 @@ bindeb-pkg: private build-type := binary deb-pkg srcdeb-pkg: debian-orig bindeb-pkg: debian deb-pkg srcdeb-pkg bindeb-pkg: - +$(strip dpkg-buildpackage \ + +$(strip dpkg-buildpackage -d \ --build=$(build-type) --no-pre-clean --unsigned-changes \ $(if $(findstring source, $(build-type)), \ --unsigned-source --compression=$(KDEB_SOURCE_COMPRESS)) \ From b0d7fd485c7bb6f0aa3df1b980b6c014f622bdd2 Mon Sep 17 00:00:00 2001 From: project516 <138796702+Project516@users.noreply.github.com> Date: Tue, 6 Jan 2026 16:19:16 +0000 Subject: [PATCH 21/21] switch submodule to ev3dev source --- .gitmodules | 3 ++- drivers/lego | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index a8f05e704a0a5..05874e779552f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "drivers/lego"] path = drivers/lego - url = https://github.com/project516/lego-linux-drivers + url = https://github.com/ev3dev/lego-linux-drivers + branch = ev3dev-trixie diff --git a/drivers/lego b/drivers/lego index bec2d381b8fbc..2e9d81c37bcf7 160000 --- a/drivers/lego +++ b/drivers/lego @@ -1 +1 @@ -Subproject commit bec2d381b8fbceb2c8e59f4234c8066e3d6493e3 +Subproject commit 2e9d81c37bcf7c9df237ae8e7bb3fc28d6dc3d2f