Get device tree node properties from tty_struct structure - linux-kernel

Is it possible to get device tree node properties of a tty device from its tty_struct structure?
The goal would be to retrieve some custom properties of the serial port from the device tree and use them in a line discipline that I'm going to link to the serial port.
This is the device tree node of the uart I'm using.
uart2: serial#021e8000 {
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021e8000 0x4000>;
interrupts = <0 27 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_UART_IPG>,
<&clks IMX6QDL_CLK_UART_SERIAL>;
clock-names = "ipg", "per";
dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
dma-names = "rx", "tx";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart2>;
status = "okay";
master = <0>;
baudrate = 9600;
};
This is part of the c code in the line discipline I'm working on.
static struct tty_ldisc_ops my_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "custom_ldisc",
.open = my_ldisc_open,
...
};
static int my_ldisc_open(struct tty_struct *tty)
{
// here I would like to access "master" and
// "baudrate" properties
}
Using ldattach on ttymxc1 (tty device on uart2) with my_ldisc as discipline,
my_ldisc_open() is called, but the parameter *tty seems to have no references
to the uart2 device tree node.

Related

How can I use the 'no-map' property of reserved-memory in device tree? Still accessed with virtual address

I have this device tree.
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
axpu_reserved_mem: axpursvd#90000000 {
no-map;
reg = <0x0 0x90000000 0x0 0x30000000>;
};
};
axpu#50000000 {
compatible = "ab21-axpu";
reg = <0 0x50000000 0 0x10000000>;
...
memory-region = <&axpu_reserved_mem>;
};
With simple test, in the probe function, I did something like this (reduced).
struct axpu_dev {
struct device *dev;
void __iomem *base;
u64 paddr;
u64 vaddr;
};
static int axpu_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct axpu_dev *axpu;
struct device_node *np;
int rc;
int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
axpu = devm_kzalloc(dev, sizeof(*axpu), GFP_KERNEL);
axpu->dev = dev;
axpu->base = devm_ioremap(dev, res->start, resource_size(res));
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
devm_request_irq(dev, res->start, axpu_irq_handler, IRQF_TRIGGER_HIGH, "axpu_irq", axpu);
np = of_parse_phandle(dev->of_node, "memory-region", 0);
rc = of_address_to_resource(np, 0, res);
axpu->paddr = res->start;
axpu->vaddr = memremap(res->start, resource_size(res), MEMREMAP_WB);
platform_set_drvdata(pdev, axpu);
axpu_init(axpu);
return sysfs_create_group(&dev->kobj, &axpu_attr_group);
}
and in the axpu_init function, I access it with virtual address.
static void axpu_init(struct axpu_dev *axpu)
{
printk("testing reserved memory ..\n");
writel_relaxed(0x12345678, axpu->vaddr + 0);
writel_relaxed(0x23456789, axpu->vaddr + 8);
printk("read-back data = %llx, %llx\n", readl_relaxed(axpu->vaddr + 0), readl_relaxed(axpu->vaddr + 8));
}
When I execute it, it runs ok.
/ # insmod axpu.ko
axpu_probe called!
MEM : res->start = 50000000, res->end = 5fffffff, res->name = axpu#50000000
axpu->base = ffffffc010000000
IRQ : res->start = 15, res->end = 15, res->name = axpu#50000000
axpu_dev 50000000.axpu: Allocated reserved memory, vaddr: 0xFFFFFFC080000000, paddr: 0x90000000
writing 0x12345678 at non-mapped reserved memory 0x90000000, 0x90000008 ..
read-back data = 12345678, 23456789
I have put no-map in the reserved memory sub-node. But is accessible with virtual address.
But if I try it with physical address, it crashes as below.
------------[ cut here ]------------
Ignoring spurious kernel translation fault at virtual address 0000000090000000
WARNING: CPU: 0 PID: 27 at arch/arm64/mm/fault.c:311 __do_kernel_fault+0x108/0x150
odules linked in: axpu(+)
CPU: 0 PID: 27 Comm: insmod Not tainted 5.10.0-rc5 #548
Hardware name: ETRI ab21m (DT)
pstate: 60400009 (nZCv daif +PAN -UAO -TCO BTYPE=--)
pc : __do_kernel_fault+0x108/0x150
lr : __do_kernel_fault+0x108/0x150
The document says about no-map :
no-map (optional) - empty property
- Indicates the operating system must not create a virtual mapping
of the region as part of its standard mapping of system memory,
nor permit speculative access to it under any circumstances other
than under the control of the device driver using the region.
Then what is wrong with my device tree?

Device tree phandle hex to reference node

Is it possible to derive the reference node from a phandle?
For example, my RPI 4 has this:
mmcnr#7e300000 {
compatible = "brcm,bcm2835-mmc\0brcm,bcm2835-sdhci";
reg = <0x7e300000 0x100>;
interrupts = <0x00 0x7e 0x04>;
clocks = <0x07 0x1c>;
dmas = <0x0b 0x0b>;
dma-names = "rx-tx";
brcm,overclock-50 = <0x00>;
non-removable;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <0x1f>;
bus-width = <0x04>;
phandle = <0x38>;
};
How do I know what node 0x38 is?
You can iterate through all the nodes using of_find_all_nodes() starting by passing parameter to this function as NULL. This function returns device_node .. You can compare the returned device_node->phandle with 0x38, if it matches. That is the node

Interrupt parameter: device tree configuration?

I am currently writing a device tree node to configure SCISIS752 Dual Channel UART with I2C which is connected to the slave address 0x4d. I am also using a clock of 1.8432MHz. The IRQ pin of SCISIS752 is attached to an IO Expander GPIO which is gpiopin 456 in my case.
I am using yocto to create the linux distro. My linux kernel version 4.18.25-yocto-standard
My dts configuration:
/dts-v1/;
#include "am33xx.dtsi"
#include "am335x-bone-common.dtsi"
#include "am335x-boneblack-common.dtsi"
/ {
model = "TI AM335x BeagleBone Black";
compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
};
&am33xx_pinmux {
pinctrl-0 = <&gpio_pins>;
i2c1_pins_default: i2c1_pins_default {
pinctrl-single,pins = <
AM33XX_IOPAD(0x984, PIN_INPUT_PULLUP | MUX_MODE3) /* (D15) uart1_txd.I2C1_SCL */
AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE3) /* (D16) uart1_rxd.I2C1_SDA */
>;};
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins_default>;
status = "okay";
clock-frequency = <400000>;
pcf8574a_38: pcf8574a#38 {
compatible = "nxp,pcf8574a";
reg = <0x38>;
gpio-controller;
#gpio-cells = <2>;
};
sc16is752#4d {
compatible = "nxp,sc16is752";
reg = <0x4d>;
clocks = <&sc16is752_clk>;
interrupt-parent = <&gpio3>;
interrupts = <7 2>;
gpio-controller;
#gpio-cells = <2>;
sc16is752_clk: sc16is752_clk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <1843200>;
};};
};
I am confused on setting the values of interrupt-parent and interrupts to make this configuration work.
I cannot see your entire device tree, nor do I know what kernel you are running... so I can't point to where your exact problem is. But I can provide some guidance in troubleshooting...
First, it appears you've copied your node from the kernel documentation in Documentation/devicetree/bindings/serial/nxp,sc16is7xx.txt. That is a point of reference, but it's simply meant to illustrate.
There is nothing magical about the device tree. It is parsed by drivers in the kernel to describe the electrical configuration. Which means, anytime you're not sure how something works, all you need to do is look at the driver to see how it parses it.
I happen to have the 4.19.0 source code on me. I found your NXP driver in drivers/tty/serial/sc16is7xx.c. I confirmed through the compatible list that it supports nxp,sc16is752.
Start at the probe sc16is7xx_i2c_probe() where the driver is entered and you will immediately see that an IRQ value is being passed in through the i2c_client structure and then setup by the call to devm_request_irq() in sc16is7xx_probe(). This means that the interrupt DT properties aren't processed in this driver. They are passed to it.
You then need to read: https://www.kernel.org/doc/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt to understand how interrupt controllers work. Does your &gpio3 meet the requirements? Is it configured as an interrupt controller? Does the it even exist?

How to use a device node that has been disabled in the kernel device tree?

I'm new to the concepts of kernel and device trees. I have a samsung artik module that runs fedora 24. I need to test one of it's I2S peripherals (it has 3 I2S peripherals). The default I2S is driving the main audio jack and is working fine. I have to test the secondary I2S that is available on a set of gpio pins and we have managed to connect it to an AMP board (TAS5731 EVM of texas instruments) via wires. Now the problem is that the amp board is not detected as an audio device. On further investigation I found out that the I2S peripheral is 'disabled' by default in the device tree. Here is the relevant portions of the device tree:
i2s#c0056000 {
reg = <0xc0056000 0x1000>;
frame-bit = <0x20>;
dmas = <0x3b 0xe 0x3b 0xf>;
pinctrl-0 = <0x3f>;
compatible = "nexell,nexell-i2s";
clock-names = "i2s1";
reset-names = "i2s-reset";
mclk-in = <0x0>;
master-mode = <0x1>;
clocks = <0x3e>;
pre-supply-mclk = <0x1>;
resets = <0x10 0x18>;
sample-rate = <0xbb80>;
status = "**disabled**";
dma-names = "tx", "rx";
pinctrl-names = "default";
trans-mode = <0x0>;
};
.
.
.
i2s1 {
nexell,pin-function = <0x3>;
phandle = <0x3f>;
nexell,pin-pull = <0x0>;
nexell,pins = "gpioa-28", "gpioa-30", "gpiob-0", "gpiob-6", "gpiob-9";
nexell,pin-strength = <0x0>;
linux,phandle = <0x3f>;
};
My question is, can I enable the peripheral without having to compile the kernel again, that is, from within the running kernel? If not, what are the alternate ways to get it running? Thanks a lot.

What is the meaning of a phandle when used as device tree node name?

This code snippet comes from the device tree for the RIoTBoard (/arch/arm/boot/dts/imx6dl-riotboard.dts)
&hdmi {
ddc-i2c-bus = <&i2c2>;
status = "okay";
};
I have gone through the device tree documentation both on devicetree.org and in the documentation/devicetree folder of the linux kernel, but I am not able to find any description of the meaning of a phandle when used as node name.
You can understand phandle as some kind of pointer for the node which points to the definition of that node which is either kept in the same file or the other file.
I can explain phandle concept taking example from the below link for AM33xx SoC
clocks file:
http://lxr.free-electrons.com/source/arch/arm/boot/dts/am33xx-clocks.dtsi
Below is the functional clock for watchdog:
wdt1_fck: wdt1_fck {
#clock-cells = <0>;
compatible = "ti,mux-clock";
clocks = <&clk_rc32k_ck>, <&clkdiv32k_ick>;
reg = <0x0538>;
};
Now wdt1_fck has two parent clocks sources: clk_rc32k_ck and clkdiv32k_ick
These are phandles or you can say pointers to their clock definitions:
clk_rc32k_ck: clk_rc32k_ck {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32000>;
};
clkdiv32k_ick: clkdiv32k_ick {
#clock-cells = <0>;
compatible = "ti,gate-clock";
clocks = <&clkdiv32k_ck>;
ti,bit-shift = <1>;
reg = <0x014c>;
};
So basically phandle enables to use the definitions of nodes across the files.
I'll answer with a example:
label:node {
#address-cell = <1>;
#size-cells = <0>;
}
&label {
proporties = <2>;
};
Means:
label:node {
#address-cell = <1>;
#size-cells = <0>;
proporties = <2>;
}
I think the question is more about the &hdmi part of the example, using an & reference for a node name in particular. The & in device tree files has two meanings: one for items in an array, and another for items outside an array.
In an array, the & reference will expand to a phandle.
Outside an arry, the & reference will expand to the path of the node you're referring to.
More information is available here:
https://elinux.org/Device_Tree_Mysteries#Labels
https://elinux.org/Device_Tree_Mysteries#Label_as_a_phandle_vs_Label_as_a_path

Resources