I am porting a project into Yocto 3.10.17 from Linaro 3.0.35.
The PMIC is used to issue the system reset, but it needs an I2C interface.
The problem is that I2C support is shut down by the time mxc_restart(...) is called.
In Linaro they simply re-muxed the pins and bitbanged the message out to I2C2 using GPIO...
However, those APIs for the IOMUX no longer exist under the device tree implementation...
For the sake of not writing a whole lot of new code, I am inclined to port the equivalent steps, but I need guidance regarding how to access the IOMUX; particularly this far into the shutdown cycle.
So, ideally, I want to use the IOMUX to re-assign the pads used for I2C2 during runtime as GPIO; I can then use the GPIO to send the necessary I2C command.
I have been unable to find example code for obtaining the IOMUX device, and I am not sure it is even there at this late stage in the shutdown process.
Furthermore, I have run across apparent moves to eliminate the pinctrl_get/put APIs - so I am not sure I want to use them in the long run, even if I can get an appropriate device pointer... These pointers seem a bit circular and I am not sure where to begin... To get a pinctrl I need a device, to get a device I need a driver, to get a driver I seem to need a bus, and I have not run across a way to get a bus without a device -- yet...
So, if someone can help me break this circle and access the IOMUX controller, it would be immensely appreciated.
However, if this is impractical then I suppose I can brute-force the IOMUX settings from my restart module...
I am just hoping someone might suggest a slightly more elegant solution.
Hi,
Can you share a piece of code of the Linaro implementation? I looked at our 3.0.35 version and I have not found any bitbanging implementation of the I2C in the mxc_restart function,
Regards,
Alejandro
I can reply with relevant fragments... These changes are for a custom SOM, there was no reason to mainline them.
In 3.0.35 a function call was added to arch_reset based on kernel config for this board.
That function makes the following calls:
mxc_iomux_v3_setup_pad(MX6Q_PAD_EIM_EB2__GPIO_2_30);
mxc_iomux_v3_setup_pad(MX6Q_PAD_EIM_D16__GPIO_3_16);
---- These calls are not really compatible with the 3.10.17 device tree structure, and it is this part I am struggling with.
This was done for reset due to the eMMC not getting reset properly with the CPU - it is a board work-around.
I have modified the 3.10.17 code to add a function call to the mxc_restart(...) function in the same way.
My quick and dirty brute force work around has been to get hold of the IOMUX register set and simply write the IOMUX values I need to do this.
In the end, the system is about to reset, so stomping here makes little difference a few microseconds later...
I get the IOMUX registers with the following calls:
/* Get the (one and only) IOMUXC node */
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-iomuxc");
iomux_base = of_iomap(np, 0);
However, I am interested if there is a more elegant solution using whatever parts of Linux are still running when mxc_restart(...) is called.
To do so, there should be the moral equivalents of the mxc_iomux_v3_setup_pad(...) API somewhere.
Referring to my original query, I do have a device node at this point. If the IOMUXC device driver is still running my questions would be:
1- How to I go from having an IOMUXC node pointer to an IOMUXC device pointer, or platform device pointer (whichever is needed)
2- Does the IOMUXC even have the APIs equivalent to mxc_iomux_v3_setup_pad(...) anymore?
3- Are those APIs going to be canned by some well-meaning community which does not want to maintain an interface that pretty much nobody (but my project) uses.
Steve
(edited to add how I get the IOMUXC registers pointer).
If you are curious, the bitbanging itself is done like this:
After re-muxing the pins, it gets GPIO pins IMX_GPIO_NR(2, 30) and IMX_GPIO_NR(3, 16) for clock and data, respectively.
gpio_request(clkGpio, "i2c2-clk");
gpio_request(dataGpio, "i2c2-data");
It then bitbangs the command to the PMIC (an ltc3676) to power-cycle the unit.
It outputs 0 using gpio_direction_output(xxxGpio, 0) to actively drive a 0.
It outputs 1 using gpio_direction_input(xxxGpio) or and letting the pull-up do its job.
It reads using gpio_get_value(dataGpio) after setting the direction to input.
The details of that code should be completely irrelevant to the IOMUX related question.