How can I use mcp2515 & device tree? - linux-device-driver

My Kernel Source writes platform data to device tree.(kernel version 3.10.9)
The board used is Exynos5422.
So I wrote mcp2515 platform data parameter to .dts
dts:
spi_1: spi#12d30000 {
status = "okay";
spi-src-clk = <0>;
num-cs = <1>;
gpios = <&gpa2 4 0>,
<&gpa2 6 0>,
<&gpa2 7 0>;
can1: mcp251x#0{
compatible ="microchip,mcp2515";
reg = <0>;
spi-max-frequency = <2000000>;
pinctrl-names = "default";
pinctr-0=<&mcp_irq>;
interrupts = < 0 0 0 >;
interrupt-parent = <&gpx1>;
irq_gpio = <&gpx1 5 0>;
reset_gpio = <&gph0 1 0>;
controller-data {
cs-gpio = <&gpa2 5 0>;
samsung,spi-feedback-delay = <0>;
};
};
};
mcp_irq: mcp_irq {
samsung,pins = "gpx1-5";
samsung,pin-function = <0xf>;
samsung,pin-pud = <3>;
samsung,pin-drv = <3>;
};
When the following assignment fails, pdata is null, resulting in fatal error below.
struct mcp251x_platform_data *pdata = spi->dev.platform_data
mcp251x.c:
if (!pdata) {
/* Platform data is required for osc freq */
goto error_out;
}
Settings:
What am I missing?

Related

Problem in AXI GPIO interrupt handling in ZYNQ

I have a custom ZYNQ7000-based board. I want to insert an AXI GPIO that directly generate an interrupt. I want to handle the interrupt in a kernel module. All things sound to be correct but it does not work.
My Toolset:
Petalinux 2021.2 installed on Ubuntu 20.04.03
Vivado 2021.2
I have only one interrupt that I connect it to the processor interrupt input.
I connect a push button to AXI GPIO 1 and configure it to generate interrupt.
Based on my pl-DTS file
/ {
amba_pl: amba_pl {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges ;
axi_gpio_0: gpio#41200000 {
#gpio-cells = <3>;
clock-names = "s_axi_aclk";
clocks = <&clkc 15>;
compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
gpio-controller ;
reg = <0x41200000 0x10000>;
xlnx,all-inputs = <0x0>;
xlnx,all-inputs-2 = <0x0>;
xlnx,all-outputs = <0x1>;
xlnx,all-outputs-2 = <0x0>;
xlnx,dout-default = <0x00000000>;
xlnx,dout-default-2 = <0x00000000>;
xlnx,gpio-width = <0x4>;
xlnx,gpio2-width = <0x20>;
xlnx,interrupt-present = <0x0>;
xlnx,is-dual = <0x0>;
xlnx,tri-default = <0xFFFFFFFF>;
xlnx,tri-default-2 = <0xFFFFFFFF>;
};
axi_gpio_1: gpio#41210000 {
#gpio-cells = <3>;
#interrupt-cells = <2>;
clock-names = "s_axi_aclk";
clocks = <&clkc 15>;
compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
gpio-controller;
interrupt-controller;
interrupt-names = "ip2intc_irpt";
interrupt-parent = <&intc>;
interrupts = <0 29 4>;
reg = <0x41210000 0x10000>;
xlnx,all-inputs = <0x1>;
xlnx,all-inputs-2 = <0x0>;
xlnx,all-outputs = <0x0>;
xlnx,all-outputs-2 = <0x0>;
xlnx,dout-default = <0x00000000>;
xlnx,dout-default-2 = <0x00000000>;
xlnx,gpio-width = <0x1>;
xlnx,gpio2-width = <0x20>;
xlnx,interrupt-present = <0x1>;
xlnx,is-dual = <0x0>;
xlnx,tri-default = <0xFFFFFFFF>;
xlnx,tri-default-2 = <0xFFFFFFFF>;
};
};
};
The interrupt should be at 61 (29 + 32 = 61): interrupts = <0 29 4>;.
I enable the interrupt enable register and global interrupt register.
I want to write a kernel module and register the axi-gpio interrupt in that and register a ISR to handle it. the main part of my code is as follows:
if (request_irq(IRQ_NUM, isr, 0, DEVICE_NAME, NULL)) {
printk(KERN_ERR "my_init: Cannot register IRQ %d\n", IRQ_NUM);
return -EIO;
} else {
printk(KERN_INFO "my_init: Registered IRQ %d\n", IRQ_NUM);
}
printk(KERN_INFO "my_init: Initialize Module \"%s\"\n", DEVICE_NAME);
pdev = platform_device_register_simple(DEVICE_NAME, 0, NULL, 0);
if (pdev == NULL) {
printk(KERN_WARNING "my_init: Adding platform device \"%s\" failed\n", DEVICE_NAME);
kfree(pdev);
return -ENODEV;
}
PROBLEMS:
Interrupt 61 could not be registered.
In fact, I found "all free interrupts" and tried "all" with my axi-gpio. None of them works correctly.
I do not want to use GPIO-keys or UIO because they need a blocking read BUT I want to write a kernel module and register the axi-gpio interrupt in that by interrupt request function (request_irq()) and register a ISR for it.
I searched and read all previous problems in the Xilinx and other venders. I tried all solutions but I cannot find anything.
BTW:
The connection between push button and processor is okay because I could activate it by the GPIO-keys. GPIO-keys interrupt catches the push button actions.

gpio_keys + pinctrl: pin already requested: failed with error -22

I have an Orange Pi Zero 2 board and I'm trying to add some joystick through GPIO.
I have found an example Device Tree overlay and modified it to my needs (see below attached version). It is also loaded and applied at startup, but yielts an error and no node is found under /dev/input/. Instead it results in the following error message posted to DMESG:
[ 1.533942] sun50i-h616-pinctrl 300b000.pinctrl: pin PC8 already requested by gpio-keys-user; cannot claim for 300b000.pinctrl:72
[ 1.533967] gpio-keys gpio-keys-user: failed to get gpio: -22
[ 1.533975] gpio-keys: probe of gpio-keys-user failed with error -22
It seems as if pinctrl and gpio-keys block each other.
If I remove the pinctrl section, adding the input device works fine, but it doesn' detect useful events, because it seems as if the GPIO pin has not been setup (i.e. pull-up is not configured).
Does anybody have an idea what I'm doing wrong?
Here's my dts file:
/dts-v1/;
/plugin/;
/ {
compatible = "allwinner,sun50i-h616";
fragment#0 {
target = <&pio>;
__overlay__ {
custom-buttons: custom-buttons {
pins = "PC5","PC6","PC8";
function = "gpio_in";
bias-pull-up;
};
};
};
fragment#1 {
target-path = "/";
__overlay__ {
gpio-keys-user {
compatible = "gpio-keys";
pinctrl-names = "default";
pinctrl-0 = <&custom-buttons>;
play_button {
label = "GPIO Key 1";
linux,code = <25>;
gpios = <&pio 0 69 1>;
};
vol_up_button {
label = "GPIO Key 2";
linux,code = <22>;
gpios = <&pio 0 70 1>;
};
vol_down_button {
label = "GPIO Key 3";
linux,code = <32>;
gpios = <&pio 0 72 1>;
};
};
};
};
};

Why MaxTouch amtel_mxt_ts driver can't register interrupt on Yocto BeagleBone am335x?

I need to integrate a Maxtouch Touchpanel (atmel_mxt_ts) Driver to an BeagleBoneBlack based Yocto Dunfell 3.1 with linux-ti-staging Kernel 5.4 system. The driver is set as loadable kernel module. The Yocto project integrates meta-ti and meta-arm from the dunfell branches.
The Interrupt should use gpio0[30] at address 0x870 on the BeagleBones P9 header. For that I set the mode ofthe gpio to 7.
I wrote a DTS to the sources and add the resulting DTB it to be loaded at startup. So far everything is working. The DTB is created and loaded during boot up.
The only problem is that when the driver is loaded by the kernel it complains about to be unable to register the interrupt.
[ 2.823173] atmel_mxt_ts 1-004a: Failed to register interrupt
[ 3.040633] atmel_mxt_ts: probe of 1-004a failed with error -22
Can anyone explain what I'm doing wrong?
This is my main DTS file
/*
* Copyright (C) 2015 Jumpnow Technologies, LLC - http://jumpnowtek.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"
#include "bbb-i2c1.dtsi"
#include "bbb-dcan1.dtsi"
/ {
model = "TI AM335x BeagleBone Black";
compatible = "ti,am335x-bone-black", "ti,am33xx";
};
&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";
};
&am33xx_pinmux {
touch_pins: touch_pins {
pinctrl-single,pins = <
AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLDOWN, MUX_MODE7) /* P9.11 0x870 Touch IRQ */
AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_OUTPUT_PULLUP, MUX_MODE7) /* P9.30 0x998 Touch RST */
>;
};
can_pins: can_pins {
pinctrl-single,pins = <
AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_INPUT_PULLUP, MUX_MODE2) /* P9.24 0x984 CAN rx */
AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_OUTPUT_PULLUP, MUX_MODE2) /* P9.26 0x980 CAN tx */
>;
};
};
&dcan0 {
status = "disabled";
};
&rtc {
system-power-controller;
};
&i2c1 {
status = "okay";
pinctrl-names = "default";
clock-frequency = <100000>;
atmel_mxt_ts#4a {
status = "okay";
compatible = "atmel,atmel_mxt_ts";
reg = <0x4a>;
interrupt-parent = <&gpio0>; /* P9.11 gpio0
interrupts = <30>; /* gpio0[30], Falling edge only 0x02*/
pinctrl-names = "default";
pinctrl-0 = <&touch_pins>;
};
};
&i2c2 {
status = "okay";
};
&dcan1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&can_pins>;
};
and this is the content of bbb-i2c1.dtsi
&am33xx_pinmux {
i2c1_pins: i2c1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x958, SLEWCTRL_SLOW | PIN_INPUT_PULLUP | MUX_MODE2) /* P9.18, i2c1_sda */
AM33XX_IOPAD(0x95c, SLEWCTRL_SLOW | PIN_INPUT_PULLUP | MUX_MODE2) /* P9.17, i2c1_scl */
>;
};
};
&i2c1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
clock-frequency = <100000>;
};
and this is the content of bbb-dcan1.dtsi
&am33xx_pinmux {
dcan1_pins: dcan1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x984, PIN_INPUT_PULLUP | MUX_MODE2) /* P9.24, ddcan1_rx */
AM33XX_IOPAD(0x980, PIN_OUTPUT_PULLUP | MUX_MODE2) /* P9.26, ddcan1_tx */
>;
};
};
&dcan1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&dcan1_pins>;
};
Thanks for your support
Found the bug by myself. It was a missing closing command tag here
interrupt-parent = <&gpio0>; /* P9.11 gpio0
I opened a multiline comment without closing and all included attributes were not set

Linux Device Tree for 2 i2c devices on same bus

I have 2 port expanders connected to the the I2C of my chip. I am able to configure one port expander from NXP and is able to toggle the gpios. But the second one is from microchip and it is not showing gpios listed as in the previous case. Please let me know how to configure this correctly.
&i2c1 {
#address-cells = <1>;
#size-cells = <0>;
clock-frequency = <100000>;
pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1>;
scl-gpios = <&lsio_gpio0 xx GPIO_ACTIVE_HIGH>;
sda-gpios = <&lsio_gpio0 xx GPIO_ACTIVE_HIGH>;
status = "okay";
mcp23017: gpio#10 {
compatible = "microchip,mcp23017";
reg = <0x10>;
gpio-controller;
#gpio-cells = <2>;
};
pca6416: gpio#11 {
compatible = "ti,tca6416";
reg = <0x11>;
gpio-controller;
#gpio-cells = <2>;
};

Why does platform_get_irq fail to get irq in my mailbox-altera driver?

I'm new to do Linux driver development.
I encounter the problem of failing to get irq when I try to use driver mailbox-altera.
On my platform DTS related to mailbox is as follows:
hps_bridges: bridge#0xc0000000 {
compatible = "altr,bridge-17.1", "simple-bus";
reg = <0xc0000000 0x20000000>,
<0xff200000 0x00200000>;
reg-names = "axi_h2f", "axi_h2f_lw";
#address-cells = <2>;
#size-cells = <1>;
ranges = <0x00000000 0x00020000 0xc0020000 0x00004000>,
<0x00000001 0x00000030 0xff200030 0x00000010>,
<0x00000001 0x00000020 0xff200020 0x00000010>,
<0x00000001 0x00000000 0xff200000 0x00000020>,
<0x00000001 0x00010000 0xff210000 0x00004000>;
...
bci_avalon_mailbox_simple_master_hps: mailbox#0x100000030 {
compatible = "altr,bci_avalon_mailbox_simple-17.0", "altr,mailbox-1.0";
reg = <0x00000001 0x00000030 0x00000010>;
interrupt-parent = <&nios2_gen2_master>;
interrupts = <11>;
#mbox-cells = <1>; /* embeddedsw.dts.params.#mbox-cells type NUMBER */
linux,mailbox-name = "bci_avalon_mailbox_simple_master_hps";
}; //end mailbox#0x100000030 (bci_avalon_mailbox_simple_master_hps)
bci_avalon_mailbox_simple_hps_master: mailbox#0x100000020 {
compatible = "altr,bci_avalon_mailbox_simple-17.0", "altr,mailbox-1.0";
reg = <0x00000001 0x00000020 0x00000010>;
interrupt-parent = <&nios2_gen2_master>;
interrupts = <12>;
#mbox-cells = <1>; /* embeddedsw.dts.params.#mbox-cells type NUMBER */
linux,mailbox-name = "bci_avalon_mailbox_simple_hps_master";
}; //end mailbox#0x100000020 (bci_avalon_mailbox_simple_hps_master)
...
}
How did I trace I fail to get irq--add logs as below:
My logs are:
#insmod mailbox-altera.ko
dev->num_resources=1.
resource[0] type=512.
start=0xff200030, size=16.
dev->num_resources=1.
resource[0] type=512.
platform_get_irq return -6.
dev->num_resources=1.
resource[0] type=512.
start=0xff200020, size=16.
dev->num_resources=1.
resource[0] type=512.
platform_get_irq return -6.
which indicates that the memory region I get in driver exactly match the description of DTS, but platform_get_irq fails, because there is only one resource(which is type of IORESOURCE_MEM ) in the mailbox device.
As DTS description, shouldn't I get the interrupts = <11> or <12> information in software when I trigger the driver? What should I do to get the irq ID I expected?