Has anybody ported Chipsee 7 inch LCD on Linux kernel 3.14 or later ?
Is there any patch available for the same ?
If no patches any suggestion porting Chipsee LCD support from Linux kernel 3.8 to Linux kernel 3.14 ?
Update:
`/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
#include "am33xx.dtsi"
#include "am335x-bone-common.dtsi"
&ldo3_reg {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
/*
&mmc1 {
vmmc-supply = <&vmmcsd_fixed>;
};
&mmc2 {
vmmc-supply = <&vmmcsd_fixed>;
pinctrl-names = "default";
pinctrl-0 = <&emmc_pins>;
bus-width = <8>;
status = "okay";
ti,vcc-aux-disable-is-sleep;
};
*/
&am33xx_pinmux {
userled_pins: pinmux_userled_pins {
pinctrl-single,pins = <
0x98 0x7 /* gpmc_wen.gpio2_4, OUTPUT | MODE7 */
0x9c 0x7 /* gpmc_ben0_cle.gpio2_5, OUTPUT | MODE7 */
>;
};
i2c0_pins: pinmux_i2c0_pins {
pinctrl-single,pins = <
0x188 0x70 /* i2c0_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */
0x18c 0x70 /* i2c0_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */
>;
};
i2c1_pins: pinmux_i2c1_pins {
pinctrl-single,pins = <
0x158 0x72 /* spi0_d1.i2c1_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
0x15c 0x72 /* spi0_cs0.i2c1_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
>;
};
mmc1_pins: pinmux_mmc1_pins {
pinctrl-single,pins = <
0x160 0x2f /* GPIO0_6 (PIN_INPUT | MUX_MODE7) */
>;
};
rstctl_pins: pinmux_rstctl_pins {
pinctrl-single,pins = <
/* eMMC_RSTn */
0x50 0x17 /* gpmc_a4.gpio1_20, OUTPUT | MODE7 | PULLUP */
>;
};
chipsee_lcd_pins: pinmux_chipsee_lcd_pins {
pinctrl-single,pins = <
0xa0 0x00 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xa4 0x00 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xa8 0x00 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xac 0x00 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xb0 0x00 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xb4 0x00 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xb8 0x00 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xbc 0x00 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xc0 0x00 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xc4 0x00 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xc8 0x00 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xcc 0x00 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xd0 0x00 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xd4 0x00 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xd8 0x00 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xdc 0x00 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0x3c 0x11 /* gpmc_ad15.lcd_data16, OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT */
0x38 0x11 /* gpmc_ad14.lcd_data17, OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT */
0x34 0x11 /* gpmc_ad13.lcd_data18, OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT */
0x30 0x11 /* gpmc_ad12.lcd_data19, OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT */
0x2c 0x11 /* gpmc_ad11.lcd_data20, OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT */
0x28 0x11 /* gpmc_ad10.lcd_data21, OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT */
0x24 0x11 /* gpmc_ad9.lcd_data22, OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT */
0x20 0x11 /* gpmc_ad8.lcd_data23, OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT */
0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
>;
};
pwm_bl_pins: pinmux_pwm_bl_pins {
pinctrl-single,pins = <
0x48 0x06 /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
>;
};
chipsee_gpio_pins: pinmux_chipsee_gpio_pins {
pinctrl-single,pins = <
0x044 0x27 /* CAP_TSC gpmc_a1.gpio1_17, INPUT | MODE7 */
0x094 0x07 /* BUZZER gpmc_oen_ren.gpio2_3 OUTPUT | MODE7 */
>;
};
chipsee_gpio_keys_pins: pinmux_chipsee_gpio_keys_pins {
pinctrl-single,pins = <
0x164 0x2f /* KEY_LEFT ecap0_in_pwm0_out.gpio0_7, INPUT | PULLDIS | MODE7 */
0x078 0x2f /* KEY_RIGHT gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
0x040 0x2f /* KEY_UP gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
0x04c 0x2f /* KEY_DOWN gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
0x1a4 0x2f /* KEY_ENTER mcasp0_fxr.gpio3_19, INPUT | PULLDIS | MODE7 */
>;
};
chipsee_uart1_pins: pinmux_chipsee_uart1_pins {
pinctrl-single,pins = <
0x180 0x20 /* uart1_rxd.uart1_rxd INPUT | MODE0 */
0x184 0x00 /* uart1_txd.uart1_txd OUTPUT | MODE0 */
>;
};
chipsee_uart2_pins: pinmux_chipsee_uart2_pins {
pinctrl-single,pins = <
0x150 0x21 /* spi0_sclk.uart2_rxd INPUT | MODE1 */
0x154 0x01 /* spi0_d0.uart2_txd OUTPUT | MODE1 */
>;
};
chipsee_uart4_pins: pinmux_chipsee_uart4_pins {
pinctrl-single,pins = <
0x070 0x26 /* gpmc_wait0.uart4_rxd INPUT | MODE6 */
0x074 0x06 /* gpmc_wpn.uart4_txd OUTPUT | MODE6 */
>;
};
chipsee_dcan0_pins: pinmux_chipsee_dcan0_pins {
pinctrl-single,pins = <
0x178 0x02 /* uart1_ctsn.d_can0_tx OUTPUT | MODE2 */
0x17c 0x32 /* uart1_rtsn.d_can0_rx INPUT_PULLUP | MODE2 */
>;
};
chipsee_audio_pins: pinmux_chipsee_audio_pins {
pinctrl-single,pins = <
0x190 0x20 /* mcasp0_aclkx.mcasp0_aclkx, INPUT | MODE0 */
0x194 0x20 /* mcasp0_fsx.mcasp0_fsx, INPUT | MODE0 */
0x198 0x20 /* mcasp0_axr0.mcasp0_axr0, INPUT | MODE0 */
0x19c 0x22 /* mcasp0_ahclkr.mcasp0_axr2, INPUT | MODE2 */
>;
};
};
/*
* To consider voltage drop between PMIC and SoC,
* tolerance value is reduced to 2% from 4% and
* voltage value is increased as a precaution.
*/
/* kHz uV */
/*
&cpus {
&cpu#0 {
operating-points = <
1000000 1350000
800000 1300000
600000 1112000
300000 969000
>;
};
};
*/
/{
ocp {
uartt0:serial#44e09000 {
status = "okay";
};
/*
epwmss1: epwmss#48302000 {
status = "okay";
ehrpwm1: ehrpwm#48302200 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pwm_bl_pins>;
};
};
*/
/* backlight {
compatible = "pwm-backlight";
pwms = <&ehrpwm1 0 500000 0>;
brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
default-brightness-level = <101>;
};
index to the array above
*/
gpio-leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&userled_pins>;
led0 {
label = "beaglebone:green:usr0";
gpios = <&gpio3 4 0>;
linux,default-trigger = "heartbeat";
default-state = "off";
};
led1 {
label = "beaglebone:green:usr1";
gpios = <&gpio3 5 0>;
linux,default-trigger = "mmc0";
default-state = "off";
};
};
gpio_keys {
compatible = "gpio-keys";
pinctrl-names = "default";
pinctrl-0 = <&chipsee_gpio_keys_pins>;
#address-cells = <1>;
#size-cells = <0>;
button#1 {
debounce_interval = <50>;
linux,code = <105>;
label = "left";
gpios = <&gpio1 7 0x1>;
gpio-key,wakeup;
autorepeat;
};
button#2 {
debounce_interval = <50>;
linux,code = <106>;
label = "right";
gpios = <&gpio2 28 0x1>;
gpio-key,wakeup;
autorepeat;
};
button#3 {
debounce_interval = <50>;
linux,code = <103>;
label = "up";
gpios = <&gpio2 16 0x1>;
gpio-key,wakeup;
autorepeat;
};
button#4 {
debounce_interval = <50>;
linux,code = <108>;
label = "down";
gpios = <&gpio2 19 0x1>;
gpio-key,wakeup;
autorepeat;
};
button#5 {
debounce_interval = <50>;
linux,code = <28>;
label = "enter";
gpios = <&gpio3 19 0x1>;
gpio-key,wakeup;
};
};
gpio_setups {
compatible = "gpio-of-helper";
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&chipsee_gpio_pins>;
/* declare your gpios */
cap_touch_int {
gpio-name = "cap_touch_int";
gpio = <&gpio2 17 0x00>;
input;
};
buzzer {
gpio-name = "buzzer";
gpio = <&gpio3 3 0x00>;
output;
init-low;
};
};
rtc#44e3e000 {
ti,system-power-controller;
status = "okay";
};
panel {
compatible = "tilcdc,panel";
pinctrl-names = "default";
pinctrl-0 = <&chipsee_lcd_pins>;
panel-info {
ac-bias = <255>;
ac-bias-intrpt = <0>;
dma-burst-sz = <16>;
bpp = <32>;
fdd = <0x80>;
tft-alt-mode = <0>;
stn-565-mode = <0>;
mono-8bit-mode = <0>;
sync-edge = <0>;
sync-ctrl = <0>;
raster-order = <1>;
fifo-th = <0>;
};
display-timings {
native-mode = <&timing0>;
timing0: 1024x600 {
hactive = <1024>;
vactive = <600>;
hback-porch = <45>;
hfront-porch = <1>;
hsync-len = <30>;
vback-porch = <22>;
vfront-porch = <12>;
vsync-len = <2>;
clock-frequency = <36000000>;
hsync-active = <1>;
vsync-active = <1>;
};
};
};
fb {
compatible = "ti,am33xx-tilcdc";
reg = <0x4830e000 0x1000>;
interrupt-parent = <&intc>;
interrupts = <36>;
ti,hwmods = "lcdc";
ti,allow-non-reduced-blanking-modes;
};
tscadc {
compatible = "ti,ti-tscadc";
reg = <0x44e0d000 0x1000>;
interrupt-parent = <&intc>;
interrupts = <16>;
ti,hwmods = "adc_tsc";
status = "okay";
tsc {
ti,wires = <4>;
ti,x-plate-resistance = <200>;
ti,steps-to-config= <5>;
ti,x-min= <0xCB>;
ti,x-max= <0xFFF>;
ti,x-inverted= <0>;
ti,y-min= <0xC8>;
ti,y-max= <0xFFF>;
ti,y-inverted= <0>;
};
adc {
ti,adc-channels = <4 5 6 7>;
};
};
sound {
compatible = "ti,da830-evm-audio";
ti,model = "DA830 EVM";
ti,audio-codec = <&tlv320aic3x>;
ti,mcasp-controller = <&mcasp0>;
ti,codec-clock-rate = <12000000>;
ti,audio-routing =
"Headphone Jack", "HPLOUT",
"Headphone Jack", "HPROUT",
"MIC3L", "Mic Bias 2V",
"MIC3R", "Mic Bias 2V",
"Mic Bias 2V", "Mic Jack";
};
};
};
&mcasp0 {
pinctrl-names = "default";
pinctrl-0 = <&chipsee_audio_pins>;
status = "okay";
op-mode = <0>; /* MCASP_IIS_MODE */
tdm-slots = <2>;
num-serializer = <16>;
serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
1 0 2 0
0 0 0 0
0 0 0 0
0 0 0 0
>;
tx-num-evt = <1>;
rx-num-evt = <1>;
};
&i2c0 {
status = "okay";
clock-frequency = <400000>;
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
tps: tps#24 {
reg = <0x24>;
};
baseboard_eeprom: baseboard_eeprom#50 {
compatible = "at,24c256";
reg = <0x50>;
};
};
&i2c1 {
status = "okay";
clock-frequency = <400000>;
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
ft5x06_ts: ft5x06_ts#38 {
compatible = "ft5x06_ts";
reg = <0x38>;
interrupt-parent = <&gpio2>;
interrupts = <17>;
};
tlv320aic3x: tlv320aic3x#1b {
compatible = "ti,tlv320aic3x";
reg = <0x1b>;
status = "okay";
};
};
#include "tps65217.dtsi"
&tps {
ti,pmic-shutdown-controller;
interrupt-parent = <&intc>;
interrupts = <7>; /* NNMI */
regulators {
dcdc1_reg: regulator#0 {
regulator-always-on;
};
dcdc2_reg: regulator#1 {
/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
regulator-name = "vdd_mpu";
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <1325000>;
regulator-boot-on;
regulator-always-on;
};
dcdc3_reg: regulator#2 {
/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
regulator-name = "vdd_core";
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <1150000>;
regulator-boot-on;
regulator-always-on;
};
ldo1_reg: regulator#3 {
regulator-always-on;
};
ldo2_reg: regulator#4 {
regulator-always-on;
};
ldo3_reg: regulator#5 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
ldo4_reg: regulator#6 {
regulator-always-on;
};
};
};
&uart1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&chipsee_uart1_pins>;
};
&uart2 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&chipsee_uart2_pins>;
};
&uart4 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&chipsee_uart4_pins>;
};
&dcan0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&chipsee_dcan0_pins>;
};
&cpsw_emac0 {
phy_id = <&davinci_mdio>, <0>;
};
&cpsw_emac1 {
phy_id = <&davinci_mdio>, <1>;
};
&mmc1 {
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins>;
bus-width = <0x4>;
cd-gpios = <&gpio1 6 0>; /* gpio1 is misnamed, 0 == GPIO_ACTIVE_HIGH */
cd-inverted;
status = "okay";
vmmc-supply = <&ldo3_reg>;
ti,vcc-aux-disable-is-sleep;
};
&edma {
ti,edma-xbar-event-map = <32 12>, /* gpevt2 -> 12 */
<30 20>; /* xdma_event_intr2 -> 20 */
};
&sham {
status = "okay";
};
&aes {
status = "okay";
};
&usb {
interface_type = <1>;
power = <250>;
status = "okay";
};
&ldo3_reg {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
/*
rstctl {
status = "okay";
compatible = "gpio-rctrl";
pinctrl-names = "default";
pinctrl-0 = <&rstctl_pins>;
#reset-cells = <2>;
gpios = <&gpio2 20 0x00>;
gpio-names = "eMMC_RSTn";
};
*/
&mmc1 {
vmmc-supply = <&vmmcsd_fixed>;
};
/*
&mmc2 {
vmmc-supply = <&vmmcsd_fixed>;
bus-width = <8>;
ti,non-removable;
status = "disabled";
reset = <&rstctl 0 0>;
reset-names = "eMMC_RSTn-CONSUMER";
};
*/
`
After changing devicetree as above, i get following output,
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
hw perfevents: enabled with ARMv7 Cortex-A8 PMU driver, 5 counters available
futex hash table entries: 256 (order: -1, 3072 bytes)
NFS: Registering the id_resolver key type
Key type id_resolver registered
Key type id_legacy registered
msgmni has been set to 987
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 252)
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
pinctrl-single 44e10800.pinmux: 142 pins at pa f9e10800 size 568
omap_uart 44e09000.serial: no wakeirq for uart0
44e09000.serial: ttyO0 at MMIO 0x44e09000 (irq = 88, base_baud = 3000000) is a O MAP UART0
omap_uart 48022000.serial: no wakeirq for uart0
48022000.serial: ttyO1 at MMIO 0x48022000 (irq = 89, base_baud = 3000000) is a O MAP UART1
console [ttyO1] enabled
omap_uart 48024000.serial: no wakeirq for uart0
48024000.serial: ttyO2 at MMIO 0x48024000 (irq = 90, base_baud = 3000000) is a O MAP UART2
omap_uart 481a8000.serial: no wakeirq for uart0
481a8000.serial: ttyO4 at MMIO 0x481a8000 (irq = 61, base_baud = 3000000) is a O MAP UART4
[drm] Initialized drm 1.1.0 20060810
brd: module loaded
mtdoops: mtd device (mtddev=name/number) must be supplied
usbcore: registered new interface driver kaweth
pegasus: v0.9.3 (2013/04/25), Pegasus/Pegasus II USB Ethernet driver
usbcore: registered new interface driver pegasus
usbcore: registered new interface driver rtl8150
usbcore: registered new interface driver asix
usbcore: registered new interface driver ax88179_178a
usbcore: registered new interface driver cdc_ether
usbcore: registered new interface driver dm9601
usbcore: registered new interface driver smsc75xx
usbcore: registered new interface driver smsc95xx
usbcore: registered new interface driver net1080
usbcore: registered new interface driver cdc_subset
usbcore: registered new interface driver zaurus
usbcore: registered new interface driver MOSCHIP usb-ethernet driver
usbcore: registered new interface driver int51x1
usbcore: registered new interface driver cdc_ncm
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ehci-omap: OMAP-EHCI Host Controller driver
usbcore: registered new interface driver usb-storage
mousedev: PS/2 mouse device common for all mice
omap_rtc 44e3e000.rtc: rtc core: registered 44e3e000.rtc as rtc0
i2c /dev entries driver
omap_wdt: OMAP Watchdog Timer Rev 0x01: initial timeout 60 sec
48060000.mmc supply vmmc_aux not found, using dummy regulator
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
oprofile: using arm/armv7
u32 classifier
Actions configured
TCP: cubic registered
NET: Registered protocol family 10
sit: IPv6 over IPv4 tunneling driver
NET: Registered protocol family 17
Key type dns_resolver registered
ThumbEE CPU extension supported.
bio: create slab <bio-1> at 1
Btrfs loaded
vmmcsd_fixed: disabling
regulator-dummy: disabling
tilcdc 4830e000.fb: no encoders/connectors found
tilcdc 4830e000.fb: failed to initialize mode setting
DCDC1: at 1500 mV
vdd_mpu: 925 <--> 1325 mV at 1100 mV
vdd_core: 925 <--> 1150 mV at 1100 mV
LDO1: at 1800 mV
LDO2: at 3300 mV
LDO3: 1800 mV
LDO4: at 3300 mV
tps65217 0-0024: TPS65217 ID 0xe version 1.2
omap_i2c 44e0b000.i2c: bus 0 rev0.11 at 400 kHz
omap_i2c 4802a000.i2c: bus 1 rev0.11 at 400 kHz
console [netcon0] enabled
netconsole: network logging started
davinci_mdio 4a101000.mdio: davinci mdio revision 1.6
davinci_mdio 4a101000.mdio: detected phy mask fffffffe
libphy: 4a101000.mdio: probed
davinci_mdio 4a101000.mdio: phy[0]: device 4a101000.mdio:00, driver SMSC LAN8710 /LAN8720
Detected MACID = 90:59:af:5b:ec:e5
input: gpio_keys.5 as /devices/ocp.3/gpio_keys.5/input/input0
omap_rtc 44e3e000.rtc: setting system clock to 2000-01-01 00:00:00 UTC (94668480 0)
VFS: Cannot open root device "mmcblk0p2" or unknown-block(0,0): error -6
Please append a correct "root=" boot option; here are the available partitions:
VFS: Unable to mount root fs on unknown-block(0,0)
User configuration error - no valid root filesystem found
Kernel panic - not syncing: Invalid configuration from end user prevents continu ing
CPU: 0 PID: 1 Comm: swapper Not tainted 3.14.0-yocto-standard #1
[<c0014fa8>] (unwind_backtrace) from [<c00123d8>] (show_stack+0x20/0x24)
[<c00123d8>] (show_stack) from [<c06b8bc4>] (dump_stack+0x20/0x28)
[<c06b8bc4>] (dump_stack) from [<c06b48f8>] (panic+0x8c/0x1c8)
[<c06b48f8>] (panic) from [<c09c1194>] (mount_block_root+0x1fc/0x244)
[<c09c1194>] (mount_block_root) from [<c09c13ac>] (mount_root+0xe8/0x10c)
[<c09c13ac>] (mount_root) from [<c09c1534>] (prepare_namespace+0x164/0x1c4)
[<c09c1534>] (prepare_namespace) from [<c09c0d4c>] (kernel_init_freeable+0x228/0 x278)
[<c09c0d4c>] (kernel_init_freeable) from [<c06b3c54>] (kernel_init+0x1c/0xf4)
[<c06b3c54>] (kernel_init) from [<c000e338>] (ret_from_fork+0x14/0x20)
¦¦¦¦¦¦¦¦¦¦¦
Related
I've written an I2C driver. I want to make the GPIO which it uses configurable from the device tree.
My device tree entry is currently:
&i2c1 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
status = "okay";
...
myi2c: myi2c#43 {
compatible = "fsl,myi2c";
reg = <0x43>;
};
I'd like to add this line into the myi2c stanza:
myi2c-gpios = <&gpio4 29 GPIO_ACTIVE_HIGH>;
I can see how to do this, if I was writing a platform driver:
static int gpio_init_probe(struct platform_device *pdev)
{
int i = 0;
printk("GPIO example init\n");
/* "greenled" label is matching the device tree declaration. OUT_LOW is the value at init */
green = devm_gpiod_get(&pdev->dev, "greenled", GPIOD_OUT_LOW);
but in my driver's i2c_probe(), I have no access to a struct platform_device *:
static int myi2c_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
How can I read the value of myi2c-gpios from the device tree and use it in my i2c driver?
I found this driver to use as an example:
static int sn65dsi84_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
...
struct gpio_desc *enable_gpio;
enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_HIGH);
if (enable_gpio)
gpiod_set_value_cansleep(enable_gpio, 1);
and its device tree is:
&i2c2 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
dsi_lvds_bridge: sn65dsi84#2c {
status = "disabled";
reg = <0x2c>;
compatible = "ti,sn65dsi84";
enable-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>;
So devm_gpiod_get_optional() seems to be the answer.
I am programing my esp32 to be able to advertise my custom services/characteristics. I am failry new to esp idf and I am struggling to program bluetooth using nimBLE. during building,there is no error thrown but while monitoring, i receive the following error from the function in main:
I (391) heap_init: At 3FFB6388 len 00001C78 (7 KiB): DRAM
I (397) heap_init: At 3FFB9A20 len 00004108 (16 KiB): DRAM
I (403) heap_init: At 3FFC49F0 len 0001B610 (109 KiB): DRAM
I (409) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (415) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (422) heap_init: At 40096DB0 len 00009250 (36 KiB): IRAM
I (429) spi_flash: detected chip: generic
I (433) spi_flash: flash io: dio
I (438) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (484) BTDM_INIT: BT controller compile version [1342a48]
I (484) system_api: Base MAC address is not set
I (484) system_api: read default base MAC address from EFUSE
I (494) phy_init: phy_version 4670,719f9f6,Feb 18 2021,17:07:07
ESP_ERROR_CHECK failed: esp_err_t 0x3 (ERROR) at 0x4008e6f4
0x4008e6f4: _esp_error_check_failed at C:/Users/Kanimba/Desktop/esp-idf/components/esp_common/src/esp_err.c:41
file: "../main/main.c" line 35
func: app_main
expression: gatt_svrs_init()
abort() was called at PC 0x4008e6f7 on core 0
0x4008e6f7: _esp_error_check_failed at C:/Users/Kanimba/Desktop/esp-idf/components/esp_common/src/esp_err.c:42
Backtrace:0x4008f64b:0x3ffbc340 0x4008fe1d:0x3ffbc360 0x400951f2:0x3ffbc380 0x4008e6f7:0x3ffbc3f0 0x400d5a86:0x3ffbc410 0x401205ed:0x3ffbc430 0x40092e45:0x3ffbc450
0x4008f64b: panic_abort at C:/Users/Kanimba/Desktop/esp-idf/components/esp_system/panic.c:356
0x4008fe1d: esp_system_abort at C:/Users/Kanimba/Desktop/esp-idf/components/esp_system/system_api.c:112
0x400951f2: abort at C:/Users/Kanimba/Desktop/esp-idf/components/newlib/abort.c:46
0x4008e6f7: _esp_error_check_failed at C:/Users/Kanimba/Desktop/esp-idf/components/esp_common/src/esp_err.c:42
0x400d5a86: app_main at C:\Users\Kanimba\Desktop\work_project\esp\embedded-test-ble\build/../main/main.c:35 (discriminator 1)
0x401205ed: main_task at C:/Users/Kanimba/Desktop/esp-idf/components/freertos/port/port_common.c:133 (discriminator 2)
0x40092e45: vPortTaskWrapper at C:/Users/Kanimba/Desktop/esp-idf/components/freertos/port/xtensa/port.c:168
whereby gatt_svrs_init() is called to initializes the following;
int gatt_svrs_init(void) {
int rc;
ble_svc_gap_init();
ble_svc_gatt_init();
rc = ble_gatts_count_cfg(gatt_svsc);
if (rc != 0) {
return rc;
}
rc = ble_gatts_add_svcs(gatt_svsc);
if (rc != 0) {
return rc;
}
return 0;
}
my main,c file looks like this
#include "config.h"
#include "gatt_svr.h"
#include "esp_log.h"
#include "esp_nimble_hci.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "nvs_flash.h"
void app_main() {
int rc;
/* initalise non-valatile storage NVS*/
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
/* initialise nimble */
ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init());
/* initialise apache port to nimble */
nimble_port_init();
/*Initialize the NimBLE host configuration */
ble_hs_cfg.reset_cb = ble_on_reset;
ble_hs_cfg.sync_cb = ble_on_sync;
ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb;
ble_hs_cfg.store_status_cb =
ble_store_util_status_rr; // said to not be useful, need to do more,
ESP_ERROR_CHECK(gatt_svrs_init());
// assert(rc == 0);
/*set the default device name*/
ESP_ERROR_CHECK(ble_svc_gap_device_name_set(DEVICE_NAME));
// storing configuration "quite not sure how this function works"
ble_store_config_init();
nimble_port_freertos_init(host_task);
}
and the structure of the service:
static const struct ble_gatt_svc_def gatt_svsc[] = {
{/* Device info service/ SIG */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = BLE_UUID16_DECLARE(DEVICE_INFO_SERVICE),
.characteristics =
(struct ble_gatt_chr_def[]){
{/* manufacturer name characteristic */
.uuid = BLE_UUID16_DECLARE(MANUFACTURER_NAME),
.flags = BLE_GATT_CHR_F_READ,
.access_cb = gatt_svr_access_device_info},
{/*serial number characteristic */
.uuid = BLE_UUID16_DECLARE(DEVICE_SERIAL_NUMBER),
.flags = BLE_GATT_CHR_F_READ,
.access_cb = gatt_svr_access_device_info},
{/*software version characteristic */
.uuid = BLE_UUID16_DECLARE(SOFTWARE_VERSION),
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
.access_cb = gatt_svr_access_device_info},
{0}}},
{.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = &DEVICE_STATE_SERVICE.u,
.characteristics =
(struct ble_gatt_chr_def[]){{
/* manufacturer name characteristic
*/
.uuid = &CURRENT_SPECTRUM.u,
.flags = BLE_GATT_CHR_F_READ,
},
{
/* manufacturer name characteristic
*/
.uuid = &DEVICE_TEMPERATURE.u,
.flags = BLE_GATT_CHR_F_READ,
},
{
/* manufacturer name characteristic
*/
.uuid = &CURRENT_INTESITY.u,
.flags = BLE_GATT_CHR_F_READ,
},
{0}}},
{.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = &MANUAL_SERVICE.u,
.characteristics =
(struct ble_gatt_chr_def[]){{
/* manula spectrum characteristic */
.uuid = &MANUAL_SPECTRUM.u,
.flags = BLE_GATT_CHR_F_READ,
},
{
/* light intensity characteristic */
.uuid = &LIGHT_INTESITY.u,
.flags = BLE_GATT_CHR_F_READ,
},
{
/* manual power characteristic */
.uuid = &MANUAL_POWER.u,
.flags = BLE_GATT_CHR_F_READ,
},
{0}}},
{.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = &SCHEDULER_SERVICE.u,
.characteristics =
(struct ble_gatt_chr_def[]){{
/* Start_stage characteristic */
.uuid = &STAGE_START.u,
.flags = BLE_GATT_CHR_F_WRITE,
},
{
/* start day hours characteristic */
.uuid = &DAY_START_HOURS.u,
.flags = BLE_GATT_CHR_F_WRITE,
},
{
/* manufacturer name characteristic
*/
.uuid = &DAY_END_HOURS.u,
.flags = BLE_GATT_CHR_F_WRITE,
},
{
/* Light intensity characteristic */
.uuid = &LIGHT_INTESITY.u,
.flags = BLE_GATT_CHR_F_WRITE,
},
{0}}},
{0}};
I think there should be a access_cb associated for a characteristic which has a read or write flag . Can you try adding a access_cb to the characteristic with UUID SCHEDULER_SERVICE , MANUAL_SERVICE and DEVICE_STATE_SERVICE to see if it helps.
I am currently refactoring a driver for the AMD Sensor Fusion Hub.
The original driver can be found here.
When sending commands to the device, the chip takes some time to process the request. I wasusing a hack using msleep to wait for the device to respond. However I'd like to cleanly implement IRQ handling. As a template I looked into the implementation of drivers/i2c/busses/i2c-amd-mp2-pci.c and came up with the following stub interrupt handling.
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* AMD Sensor Fusion Hub (SFH) PCIe driver
*
* Authors: Shyam Sundar S K <Shyam-sundar.S-k#amd.com>
* Nehal Bakulchandra Shah <Nehal-bakulchandra.Shah#amd.com>
* Richard Neumann <mail#richard-neumann.de>
*/
#include <linux/bitops.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/types.h>
#include "amd-sfh-pci.h"
/**
* amd_sfh_get_sensor_mask - Returns the sensors mask.
* #pci_dev: The Sensor Fusion Hub PCI device
*
* Returns an unsigned integer representing the bitmask to match
* the sensors connected to the Sensor Fusion Hub.
*/
int amd_sfh_get_sensor_mask(struct pci_dev *pci_dev)
{
int sensor_mask;
struct amd_sfh_dev *sfh_dev = pci_get_drvdata(pci_dev);
sensor_mask = readl(sfh_dev->mmio + AMD_SFH_SENSOR_MASK);
/* Correct bit shift in firmware register */
sensor_mask = sensor_mask >> 4;
if (!sensor_mask)
dev_err(&pci_dev->dev, "no sensors marked active on device\n");
return sensor_mask;
}
EXPORT_SYMBOL_GPL(amd_sfh_get_sensor_mask);
/**
* amd_sfh_start_sensor- Starts the respective sensor.
* #pci_dev: The Sensor Fusion Hub PCI device
* #sensor_idx: The sensor's index
* #dma_handle: The DMA handle
*/
void amd_sfh_start_sensor(struct pci_dev *pci_dev, enum sensor_idx sensor_idx,
dma_addr_t dma_handle)
{
struct amd_sfh_dev *sfh_dev = pci_get_drvdata(pci_dev);
union amd_sfh_cmd command;
union amd_sfh_parm parameter;
command.ul = 0;
command.s.cmd_id = enable_sensor;
command.s.period = PERIOD;
command.s.sensor_id = sensor_idx;
parameter.ul = 0;
parameter.s.buffer_layout = 1;
parameter.s.buffer_length = 16;
writeq(dma_handle, sfh_dev->mmio + AMD_SFH_ADDR);
writel(parameter.ul, sfh_dev->mmio + AMD_SFH_PARM);
writel(command.ul, sfh_dev->mmio + AMD_SFH_CMD);
}
EXPORT_SYMBOL_GPL(amd_sfh_start_sensor);
/**
* amd_sfh_stop_sensor- Stops the respective sensor.
* #pci_dev: The Sensor Fusion Hub PCI device
* #sensor_idx: The sensor's index
*/
void amd_sfh_stop_sensor(struct pci_dev *pci_dev, enum sensor_idx sensor_idx)
{
struct amd_sfh_dev *sfh_dev = pci_get_drvdata(pci_dev);
union amd_sfh_cmd command;
command.ul = 0;
command.s.cmd_id = disable_sensor;
command.s.period = 0;
command.s.sensor_id = sensor_idx;
writeq(0x0, sfh_dev->mmio + AMD_SFH_ADDR);
writel(command.ul, sfh_dev->mmio + AMD_SFH_CMD);
}
EXPORT_SYMBOL_GPL(amd_sfh_stop_sensor);
/**
* amd_sfh_stop_all_sensors- Stops all sensors on the SFH.
* #pci_dev: The Sensor Fusion Hub PCI device
*/
static void amd_sfh_stop_all_sensors(struct pci_dev *pci_dev)
{
struct amd_sfh_dev *sfh_dev = pci_get_drvdata(pci_dev);
union amd_sfh_cmd command;
command.ul = 0;
command.s.cmd_id = stop_all_sensors;
command.s.period = 0;
command.s.sensor_id = 0;
writel(command.ul, sfh_dev->mmio + AMD_SFH_CMD);
}
/**
* amd_sfh_irq_isr - IRQ handler
* #irq: The IRQ number received
* #dev: The underlying device
*/
static irqreturn_t amd_sfh_irq_isr(int irq, void *dev)
{
struct amd_sfh_dev *sfh_dev = dev;
dev_info(&sfh_dev->pci_dev->dev, "got IRQ: %d\n", irq);
return IRQ_NONE;
}
/**
* amd_sfh_pci_init - Initializes the PCI device
* #sfh_dev: The device data
* #pci_dev: The PCI device
*/
static int amd_sfh_pci_init(struct amd_sfh_dev *sfh_dev,
struct pci_dev *pci_dev)
{
int rc;
pci_set_drvdata(pci_dev, sfh_dev);
rc = pcim_enable_device(pci_dev);
if (rc)
goto err_pci_enable;
rc = pcim_iomap_regions(pci_dev, BIT(2), pci_name(pci_dev));
if (rc)
goto err_pci_enable;
sfh_dev->pci_dev = pci_dev;
sfh_dev->mmio = pcim_iomap_table(pci_dev)[2];
pci_set_master(pci_dev);
rc = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(64));
if (rc) {
rc = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
if (rc)
goto err_dma_mask;
}
/* Set up intx irq */
writel(0, sfh_dev->mmio + AMD_P2C_MSG_INTEN);
pci_intx(pci_dev, 1);
dev_info(&pci_dev->dev, "available interrupt: %d\n", pci_dev->irq);
rc = devm_request_irq(&pci_dev->dev, pci_dev->irq, amd_sfh_irq_isr,
0, dev_name(&pci_dev->dev), sfh_dev);
if (rc)
dev_err(&pci_dev->dev, "Failure requesting irq %i: %d\n",
pci_dev->irq, rc);
return rc;
err_dma_mask:
pci_clear_master(pci_dev);
err_pci_enable:
return rc;
}
static int amd_sfh_pci_probe(struct pci_dev *pci_dev,
const struct pci_device_id *id)
{
int rc;
struct amd_sfh_dev *sfh_dev;
sfh_dev = devm_kzalloc(&pci_dev->dev, sizeof(*sfh_dev), GFP_KERNEL);
if (!sfh_dev)
return -ENOMEM;
rc = amd_sfh_pci_init(sfh_dev, pci_dev);
if (rc)
return rc;
pm_runtime_set_autosuspend_delay(&pci_dev->dev, 1000);
pm_runtime_use_autosuspend(&pci_dev->dev);
pm_runtime_put_autosuspend(&pci_dev->dev);
pm_runtime_allow(&pci_dev->dev);
dev_info(&pci_dev->dev, "SFH device registered.\n");
return 0;
}
static void amd_sfh_pci_remove(struct pci_dev *pci_dev)
{
struct amd_sfh_dev *sfh_dev = pci_get_drvdata(pci_dev);
amd_sfh_stop_all_sensors(sfh_dev->pci_dev);
pm_runtime_forbid(&pci_dev->dev);
pm_runtime_get_noresume(&pci_dev->dev);
pci_intx(pci_dev, 0);
pci_clear_master(pci_dev);
}
static const struct pci_device_id amd_sfh_pci_tbl[] = {
{PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_SFH)},
{0}
};
MODULE_DEVICE_TABLE(pci, amd_sfh_pci_tbl);
static struct pci_driver amd_sfh_pci_driver = {
.name = "amd-sfh-pci",
.id_table = amd_sfh_pci_tbl,
.probe = amd_sfh_pci_probe,
.remove = amd_sfh_pci_remove,
};
module_pci_driver(amd_sfh_pci_driver);
/**
* amd_sfh_find_device - Returns the first best AMD SFH device.
*/
struct amd_sfh_dev *amd_sfh_find_device(void)
{
struct device *dev;
struct pci_dev *pci_dev;
dev = driver_find_next_device(&amd_sfh_pci_driver.driver, NULL);
if (!dev)
return NULL;
pci_dev = to_pci_dev(dev);
return pci_get_drvdata(pci_dev);
}
EXPORT_SYMBOL_GPL(amd_sfh_find_device);
MODULE_DESCRIPTION("AMD(R) Sensor Fusion Hub PCI driver");
MODULE_AUTHOR("Shyam Sundar S K <Shyam-sundar.S-k#amd.com>");
MODULE_AUTHOR("Nehal Bakulchandra Shah <Nehal-bakulchandra.Shah#amd.com>");
MODULE_AUTHOR("Richard Neumann <mail#richard-neumann.de>");
MODULE_LICENSE("Dual BSD/GPL");
However the dev_info from amd_sfh_irq_isr is never logged, so I suspect that the IRQ is never triggered when writing to the device registers. What can be the reason for that and what can I do to correctly implement the IRQ handling?
PS
dmesg output:
[ 2272.642762] amd-sfh-pci 0000:04:00.7: available interrupt: 56
[ 2272.642840] amd-sfh-pci 0000:04:00.7: SFH device registered.
Update
The device seems to support MSI:
04:00.7 Non-VGA unclassified device [0000]: Advanced Micro Devices, Inc. [AMD] Raven/Raven2/Renoir Sensor Fusion Hub [1022:15e4]
Subsystem: Hewlett-Packard Company Raven/Raven2/Renoir Sensor Fusion Hub [103c:8496]
Flags: bus master, fast devsel, latency 0, IRQ 56
Memory at fc800000 (32-bit, non-prefetchable) [size=1M]
Memory at fcc8c000 (32-bit, non-prefetchable) [size=8K]
Capabilities: [48] Vendor Specific Information: Len=08 <?>
Capabilities: [50] Power Management version 3
Capabilities: [64] Express Endpoint, MSI 00
Capabilities: [a0] MSI: Enable- Count=1/2 Maskable- 64bit+
Capabilities: [c0] MSI-X: Enable- Count=2 Masked-
Capabilities: [100] Vendor Specific Information: ID=0001 Rev=1 Len=010 <?>
Kernel modules: amd_sfh_pci
But the interrupts are still not received / handled:
static void amd_sfh_debug(struct pci_dev *pci_dev)
{
bool msi;
msi = pci_dev_msi_enabled(pci_dev);
pci_info(pci_dev, "MSI: %s\n", msi ? "true" : "false");
pci_info(pci_dev, "No MSI: %s\n", pci_dev->no_msi ? "true" : "false");
}
/**
* amd_sfh_handle_irq - Handles IRQs.
* #irq: The interrupt request to be handled
* #dev: The driver data
*
* Returns an appropriate IRQ return type.
*/
static irqreturn_t amd_sfh_handle_irq(int irq, void *dev)
{
struct amd_sfh_dev *privdata = dev;
pci_info(privdata->pci_dev, "got IRQ: %d\n", irq);
return IRQ_NONE;
}
static int amd_sfh_setup_irq(struct amd_sfh_dev *privdata)
{
int rc, vecs, irq;
struct pci_dev *pci_dev = privdata->pci_dev;
vecs = pci_alloc_irq_vectors(pci_dev, 1, 3, PCI_IRQ_ALL_TYPES);
if (vecs < 0)
return vecs;
pci_info(pci_dev, "allocated %d IRQ vectors\n", vecs);
for (irq = 0; irq < vecs; irq++) {
pci_info(pci_dev, "requesting IRQ: %d\n", irq);
rc = devm_request_irq(&pci_dev->dev,
pci_irq_vector(pci_dev, irq),
amd_sfh_handle_irq, 0, "sfh-irq",
privdata);
if (rc) {
pci_err(pci_dev, "failed to get IRQ\n");
goto free_irq_vectors;
}
}
return 0;
free_irq_vectors:
pci_free_irq_vectors(pci_dev);
return rc;
}
static int amd_sfh_pci_init(struct amd_sfh_dev *privdata,
struct pci_dev *pci_dev)
{
int rc;
pci_set_drvdata(pci_dev, privdata);
rc = pcim_enable_device(pci_dev);
if (rc)
return rc;
rc = pcim_iomap_regions(pci_dev, BIT(2), pci_name(pci_dev));
if (rc)
return rc;
privdata->pci_dev = pci_dev;
privdata->mmio = pcim_iomap_table(pci_dev)[2];
pci_set_master(pci_dev);
rc = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(64));
if (rc) {
rc = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
if (rc)
goto clear_master;
}
/* Setup IRQ */
amd_sfh_debug(pci_dev);
rc = amd_sfh_setup_irq(privdata);
if (rc)
goto clear_master;
amd_sfh_debug(pci_dev);
/* End of IRQ setup */
pci_info(pci_dev, "AMD Sensor Fusion Hub device initialized\n");
return 0;
clear_master:
pci_clear_master(pci_dev);
return rc;
}
dmesg:
[ 6.954524] amd-sfh-pci 0000:04:00.7: enabling device (0000 -> 0002)
[ 6.954641] amd-sfh-pci 0000:04:00.7: MSI: false
[ 6.954642] amd-sfh-pci 0000:04:00.7: No MSI: false
[ 6.954791] amd-sfh-pci 0000:04:00.7: allocated 2 IRQ vectors
[ 6.954792] amd-sfh-pci 0000:04:00.7: requesting IRQ: 0
[ 6.954825] amd-sfh-pci 0000:04:00.7: requesting IRQ: 1
[ 6.954860] amd-sfh-pci 0000:04:00.7: MSI: true
[ 6.954861] amd-sfh-pci 0000:04:00.7: No MSI: false
[ 6.954861] amd-sfh-pci 0000:04:00.7: AMD Sensor Fusion Hub device initialized
[ 6.969691] amd-sfh-pci 0000:04:00.7: [Firmware Bug]: No sensors marked active!
[ 6.971265] amd-sfh-pci 0000:04:00.7: sensor mask: 0x000001
[ 7.548189] hid-generic 0018:03FE:0001.0001: hidraw0: I2C HID v0.01 Device [amd-sfh-accel] on
The original documentation from AMD mentiones interrupts but is not too specific as to how they are being generated.
By try-and-error I found that I needed to set the P2C register 0x10690 to 1 in order to enable interrupts on the device. Whith this set, the device is flooding the driver with interrupts. I'm still figuring out how to make the device generate interrupts only on actual write events to the C2P registers.
Okay, I found out, how:
https://github.com/conqp/linux/blob/5ba797452a794100d65d103e8eb53f64ae14d1d0/drivers/hid/amd-sfh-hid/amd-sfh-pci.c#L301
I'm working on a Cyclone V SOC FPGA from Altera with a double Cortex-A9 processor. The embedded system (linux-socfpga 4.16) is created with Buildroot-2018.05.
I use a "top" device tree at boot time for processor component and a device-tree overlay to configure the FPGA part of the component and load the associated drivers. The overlay will be attach to the base_fpga_region of the top DT.
top device tree
/dts-v1/;
/ {
model = "MY_PROJECT"; /* appended from boardinfo */
compatible = "altr,socfpga-cyclone5", "altr,socfpga"; /* appended from boardinfo */
#address-cells = <1>;
#size-cells = <1>;
cpus {
[...]
}; //end cpus
memory {
device_type = "memory";
reg = <0xffff0000 0x00010000>,
<0x00000000 0x80000000>;
}; //end memory
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
mem_dma_reserved {
compatible = "shared-dma-pool";
no-map;
reg = <0x78000000 0x8000000>;
};
};
soc: soc {
device_type = "soc";
ranges;
#address-cells = <1>;
#size-cells = <1>;
compatible = "altr,avalon", "simple-bus";
bus-frequency = <0>;
fpgabridge1: fpgabridge#1 {
compatible = "altr,socfpga-lwhps2fpga-bridge";
resets = <&hps_rstmgr 97>; /* appended from boardinfo */
clocks = <&l4_main_clk>; /* appended from boardinfo */
#address-cells = <1>;
#size-cells = <1>;
ranges;
bridge-enable = <1>;
label = "lwhps2fpga";
reset-names = "lwhps2fpga";
reg = <0xff200000 0x200000>;
reg-names = "axi_h2f_lw";
}; //end fpgabridge#1 (fpgabridge1)
base_fpga_region: base_fpga_region {
compatible = "fpga-region";
#address-cells = <0x2>;
#size-cells = <0x1>;
fpga-mgr = <&hps_fpgamgr>;
fpga-bridges = <&fpgabridge1>;
ranges = <0x0 0x0 0xff200000 0x200000>;
}; //end base_fpga_region (base_fpga_region)
etc......
Device tree overlay
/dts-v1/ /plugin/;
/{
fragment#0 {
target-path = "/soc/base_fpga_region";
#address-cells = <2>;
#size-cells = <1>;
__overlay__ {
#address-cells = <2>;
#size-cells = <1>;
firmware-name = "my_project.rbf";
my_dma_0: dma#0x000000000 {
compatible = "my_company,my_dma-0.1";
reg = <0x00000000 0x0000000 0x00000014>;
memory-region = <&mem_dma_reserved>;
}; //end dma#0x000000000 (my_dma_0)
};
};
};
my problem is to link the mem_dma_reserved from the top DT to the memory-region in the overlay.
I assume that while converting dts to dtbo with the -# option, the overlay shall get the phandle for mem_dma_reserved with the __fixups__ option. I've created the dtbo file and converted it again in dts to see what is done during the compilation :
dtc -# -I dts -O dtb -o overlay.dtbo overlay.dts
dtc -I dtb -O dts -o overlay_recovery.dts overlay.dtbo
device tree overlay regenerated
/dts-v1/;
/ {
fragment#0 {
target-path = "/soc/base_fpga_region";
#address-cells = <0x2>;
#size-cells = <0x1>;
__overlay__ {
#address-cells = <0x2>;
#size-cells = <0x1>;
firmware-name = "my_project.rbf";
dma#0x000000000 {
compatible = "my_company,my_dma-0.1";
reg = <0x0 0x0 0x14>;
memory-region = <0xffffffff>; // phandle converted to 0xffffffff, cannot resolve unless the __fixup__ function does it.
linux,phandle = <0x2>;
phandle = <0x2>;
};
};
};
__symbols__ {
my_dma_0 = "/fragment#0/__overlay__/dma#0x000000000";
};
__fixups__ {
mem_dma_reserved = "/fragment#0/__overlay__/dma#0x000000000:memory-region:0";
};
};
We can see that the phandle for the memory-region is 0xFFFFFFFF because the overlay doesn't know about the <&mem_dma_reserved> node. the fixup part shall be able to get back the phandle at loading time, but it isn't working and I get this error :
[ 27.434730] OF: resolver: of_resolve_phandles: no symbols in root of device tree.
[ 27.440401] OF: resolver: overlay phandle fixup failed: -22
[ 27.445993] create_overlay: Failed to resolve tree
I have made the same regeneration from dtb to dts on the top DT. I have seen that the phandle of the reserved memory is actually 0x6. I have written <0x6> instead of <&mem_dma_reserved> in the device tree overlay and with this configuration, everything loads !
How can I make the overlay find the <&mem_dma_reserved> automatically without doing it by hand ?
EDIT
As pointed by ikwzm I have added in the top device tree the following lines :
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
mem_dma_reserved: mem_dma_reserved { // add a label
compatible = "shared-dma-pool";
no-map;
reg = <0x78000000 0x8000000>;
};
};
[...]
// add the whole symbol block
__symbols__ {
mem_dma_reserved = "/reserved-memory/mem_dma_reserved ";
};
The errors are now gone, but :
I was expecting the driver for my_dma to be loaded during the operation.
I checked that the device tree overlay is well taken into account with :
ls /sys/firmware/devicetree/base/soc/base_fpga_region/
my_dma_0
other_stuff
cat /sys/firmware/devicetree/base/soc/base_fpga_region/my_dma_0/memory-region
//nothing//
The memory region doesn't seem to be attached.
What I have missed ?
When making the top dtb, did you attach the option --symbol (or -#) to the dtc command?
Add a label (symbol) to mem_dma_reserved as follows.
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
mem_dma_reserved: mem_dma_reserved {
compatible = "shared-dma-pool";
no-map;
reg = <0x78000000 0x8000000>;
};
};
When dtb is created with the --symbol option dtc command, __symbols__{...}; is added as follows, and mem_dma_reserved = "/reserved-memory/ mem_dma_reserved"; should be found in it.
__symbols__ {
:
:
:
mem_dma_reserved = "/reserved-memory/mem_dma_reserved";
usb_phy0 = "/phy0";
};
I have a Ti's AM335x custom board. I want to define some pins as gpios and be able to set them as input and output in its Linux userspace.
I defined pins in am33xx_pinmux and then referenced it with the bone-pinmux-helper. The problem is I can set it with these commands on the terminal but it doesn't work.
echo 4 > /sys/class/gpios/export
echo out > /sys/class/gpios/gpio4/direction
echo 1 > /sys/class/gpios/value
here is a brief of my code for just two pins gpio0_4 gpio0_5, each pin must become available to set as input or output in userspace.
#include "am33xx.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>
&am33xx_pinmux {
pinctrl-names = "default";
DATA_OUT_A00:DATA_OUT_A00 {
pinctrl-single,pins = <0x158 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) >; /*gpio0_4*/
};
DATA_OUT_A01:DATA_OUT_A01 {
pinctrl-single,pins = <0x15C (PIN_OUTPUT_PULLDOWN | MUX_MODE7) >; /*gpio0_5*/
};
...
}
...
&ocp {
test_helper: helper {
compatible = "bone-pinmux-helper";
status = "okay";
pinctrl-names = "DATA_OUT_A00", "DATA_OUT_A01";
pinctrl-0 = <&DATA_OUT_A00>;
pinctrl-1 = <&DATA_OUT_A01>;
}
}
EDIT:-------------------
I'm using main Ti kernel 4.9 version. If I want to define these two pins as output this DTS works fine but ONLY for output mode. I can export pins as input but when I read its value it always returns zero.
#include "am33xx.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>
/ {
model = "My Custom board C335x";
compatible = "ti,am33xx";
cpus {
cpu#0 {
cpu0-supply = <&vdd_core>;
};
};
...
gpio-leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&led_pins>;
// the following two blocks make the pins available in /sys/class/leds
// if removed can be accessd with /sys/class/gpios
test_led1 {
label = "test";
gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
test_led2 {
label = "test";
gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
};
}
&am33xx_pinmux {
pinctrl-names = "default";
led_pins: pinmux_led_pins {
pinctrl-single,pins = <
0x158 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /*gpio0_4*/
0x15C (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /*gpio0_5*/
>;
};
...
}
If I leave these pins in the DTS file, I still can export them but I can't get any input or set a value as output to them.