write MAC address to I.MX 8M Plus from Linux user space - linux

I have a I.MX 8M Plus chip on my PCB and I need to write to it a MAC address from Linux user space.
The Linux kernel uses NVMEM driver(drivers/nvmem/ocotp.c) rather than FSL_OTP driver. The dts include the ocotp device support.
ocotp: efuse#30350000 {
compatible = "fsl,imx8mp-ocotp", "fsl,imx8mm-ocotp", "syscon";
reg = <0x30350000 0x10000>;
clocks = <&clk IMX8MP_CLK_OCOTP_ROOT>;
/* For nvmem subnodes */
#address-cells = <1>;
#size-cells = <1>;
imx8mp_uid: unique-id#420 {
reg = <0x8 0x8>;
};
cpu_speed_grade: speed-grade#10 {
reg = <0x10 4>;
};
eth_mac1: mac-address#640 {
reg = <0x90 6>;
};
eth_mac2: mac-address#650 {
reg = <0x96 6>;
};
The nvmem in the sysfs entry is /sys/devices/platform/soc#0/{SOME_ID}.bus/{SOME_ID}.ocotp-ctrl/imx-ocotp0/nvmem
The patch mentioned in the https://community.nxp.com/t5/i-MX-Processors/OCOTP-write-support-on-i-mx8m/m-p/825028?commentID=1161... is already present.
Could you please let me know how to write the MAC address from userspace (eg. Aa:Bb:Cc:Dd:Ee:Ff).I need to assign mac addresses to mac1(mac-address#640) and mac2(mac-address#650) I dont want to write the MAC address from uboot or using UUU.

Related

How to match a Linux driver with a hardware device

I am writing a Linux driver for some custom hardware. My questions is how does Linux match the hardware to my driver. The hardware's DT entry is
nvme_host_sys#43c00000 {
clock-names = "sys_clk_p", "sys_clk_n", "aclk";
clocks = <0x13 0x13 0x13>;
compatible = "xlnx,nvme-host-sys-1.0";
interrupt-names = "intr";
interrupt-parent = <0x4>;
interrupts = <0x0 0x1d 0x4>;
reg = <0x43c00000 0x80000>;
phandle = <0x38>;
};
I can insert my driver using modprobe and that works fine as I can see the printk in the init being written. I can also create an entry in /dev using mknod and that also works fine. But is the driver now associated with the hardware? Do I need to do something else? Thanks
I found the solution. In the driver code we just need to add the following :-
static struct of_device_id nvmedrv_of_match[] = {
{ .compatible = "xlnx,nvme-host-sys-1.0", },
{ /* end of list */ },
};

Enable RS485 mode for max310x SPI-UART converter

In my application I need RS485 interfaces. I am using some UARTs from am3352 but I need few more, so I'm trying to expand using SPI and max3109 chip.
I have successfully added max3109 to my device tree using module max310x - it shows two devices: /dev/ttyMAX0 and /dev/ttyMAX1. Here is the device tree fragment:
&spi1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
num_cs = <1>;
cs-gpios = <&gpio2 17 0>;
ti,pindir-d0-out-d1-in;
max310x_0: max0#0 {
compatible = "maxim,max3109";
reg = <0>;
spi-max-frequency = <24000000>;
clocks = <&clk1m8>;
clock-names = "xtal";
interrupt-parent = <&gpio2>;
interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
gpio-controller;
#gpio-cells = <2>;
clk1m8: clk1m8 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <1843200>;
};
};
};
and the pins:
spi1_pins: pinmux_spi1_pins {
pinctrl-single,pins = <
0x108 (PIN_INPUT_PULLUP | MUX_MODE2) /* (H16) gmii1_col.spi1_sclk */
0x10c (PIN_INPUT_PULLUP | MUX_MODE2) /* (H17) gmii1_crs.spi1_d0 */
0x110 (PIN_INPUT_PULLUP | MUX_MODE2) /* (J15) gmii1_rxer.spi1_d1 */
>;
};
UARTs from max3109 are connected to rs232/rs485 converter with max3109's RTSn pins conected to both DE and RE pins.
The problem: UARTS on max3109 seems to work fine - both rs485 are transmitting data, but not reciving. Problem is that RTS is always at 0V level...
In UARTs from am3352 I am using in device tree the following property: "linux,rs485-enabled-at-boot-time". But adding it to main max310x_0 node is not giving any effect - this node is the expander node (containing 2 UARTs and gpio-controller), not the UART itself.
My idea is that I need to add a child-nodes for each UART and in it place the property "linux,rs485-enabled-at-boot-time". But I don't have a clue how to do it. I tried something like this:
&spi1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
num_cs = <1>;
cs-gpios = <&gpio2 17 0>;
ti,pindir-d0-out-d1-in;
max310x_0: max0#0 {
compatible = "maxim,max3109";
reg = <0>;
spi-max-frequency = <24000000>;
clocks = <&clk1m8>;
clock-names = "xtal";
interrupt-parent = <&gpio2>;
interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
gpio-controller;
#gpio-cells = <2>;
clk1m8: clk1m8 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <1843200>;
};
ttyMAX0 {
linux,rs485-enabled-at-boot-time;
};
ttyMAX1 {
linux,rs485-enabled-at-boot-time;
};
};
};
but it didn't worked.
My question: How am I supposed to add those child-nodes (if that's the proper way) and what should I place in them to make RTS work?
EDIT:
after sawdust suggestion it seems it's impossible to add rs485 mode in device tree.
So I tried to add this functionality to device tree and I think I'm starting to understand how things work down in here. To start with something I'm printing port.flags value to dmesg and it seems my little insertion works (a bit) - it changes the value depending on presence of linux,rs485-enabled-at-boot-time parameter in device tree.
Here is the code I have inserted:
if (of_property_read_bool(dev->of_node, "linux,rs485-enabled-at-boot-time"))
s->p[i].port.flags |= SER_RS485_ENABLED;
printk("s->p[i].port.flags is: %d\n",s->p[i].port.flags);
The value of port.flags toggles from 134225920 to 134225921 depending on presence of linux,rs485-enabled-at-boot-time.
but the RTS pin still have constant 0V on my oscilloscope...
I'm trying to figure out if SER_RS485_RTS_ON_SEND and SER_RS485_RTS_AFTER_SEND have something to do with this, but I'm prete sure it's only for reverting RTS signal.
After few attempts IOCTL was the best and easiest solution. Here is some example code that helped me much. https://gist.github.com/amarburg/07564916d8d32e20e6ae375c1c83a995
It's basic example how to turn RS485 mode on and off using IOCTL and read it's current mode. Works with both CPUs internal UARTS and MAX3109.

Linux Kernel Platform Driver: Modifications to _probe() for multiple Devices

What modifications must be done to a Linux kernel driver to support (equal) multiple devices(myipcore) on a SoC (defined in the device tree) instead of only one?
In my application: only one process will open the appropriate /dev/myipcoreX file!
Device Tree:
amba: amba {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges;
axi_myipcore1: myipcore#A0001000 {
compatible = "xy,my-ip-core-1.00";
status = "disabled";
interrupt-parent = <&gic>;
interrupts = <0 89 1>;
reg = <0x0 0xA0001000 0x0 0x14>;
};
axi_myipcore2: myipcore#A0002000 {
compatible = "xy,my-ip-core-1.00";
status = "disabled";
interrupt-parent = <&gic>;
interrupts = <0 90 1>;
reg = <0x0 0xA0002000 0x0 0x14>;
};
....
}
For each device tree entry the _probe() function of the driver is called. How to get dynamically the next minor number for alloc_chrdev_region() and how to execute class_create() only once?
Or do I have to modify the device tree?
You see, I'm looking for the central theme....

Adding entry for an i2c device connected on i2c mux in linux device tree

I am using freescale powerpc 85xx processor with linux 2.6.32.
The i2c subsytem is mapped at address 0x03000 inside the ccsr registers. I want to add an RTC device,DS1338 (i2c addr: 0x68) connected to an I2c mux (address: 0x76) on channel 5 (selected by writing 0xfd on control register).
Without adding the device in the dts file, the rtc device won't bind to driver.
I have the following entry in my device tree right now:
i2c#3000 { /* I2C 1 */
#address-cells = <1>;
#size-cells = <0>;
cell-index = <0>;
compatible = "fsl-i2c";
reg = <0x3000 0x100>;
interrupts = <43 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
What would it look like after adding the above information. Had it been a device directly on the i2c bus and not through mux, I would have added something like this:
i2c#3000 { /* I2C 1 */
#address-cells = <1>;
#size-cells = <0>;
cell-index = <0>;
compatible = "fsl-i2c";
reg = <0x3000 0x100>;
interrupts = <43 2>;
interrupt-parent = <&mpic>;
rtc:rtc#68 {
compatible = "dallas,ds1307";
reg = <0x68>;
};
dfsrr;
};
Now with the mux in the path, and having to select channel, I don't think I know how to make an entry.

linux: spidev is not shown in /dev

I did the following steps in order to use spidev in Linux- kernel 3.14.28 compiled on arm imx6Q (SMARC board, by Yocto-Project):
In kernel configuration, I enabled SPIDEV: CONFIG_SPI_SPIDEV=y.
In device tree, I added the following lines:
&smarc_spi0 {
spidev#1 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "linux, spidev";
spi-max-frequency = <20000000>;
reg = <1>;
};
};
I compiled my Linux successfully, and still can't see /dev/spidev0.1 appear in /dev folder.
Any idea?
I found out the problem: compatible string wasn't accurate..
I had extra space between "linux," and "spidev"..
The appropriate way is:
compatible = "linux,spidev";

Resources