I'm trying to add a new the gpio controller driver in u-boot. I've actually added and enabled the driver but it needs a small fix and I'm not able to figure out how to handle this. I'm somewhat new to the u-boot and gpio frameworks.
My problem is, there are two gpio controllers i.e My dts file looks like the below
gpio1:gpio#505050505 {
/* this bank has hw pins 0 - 29 */
ngpio = 30;
};
gpio0:gpio#a0a0a0a0 {
/* this bank has hw pins 0 - 19*/
ngpio = 20;
};
In the driver probe function, i see that gpio1 is probed first and then the gpio0 is probed. Due to this probe(dt parsing) order, the pin mapping created is as shown below
pin 0 - 29 mapped to gpio1 hw pins 0 - 29 and
Pin 30 - 49 mapped to gpio0 hw pins 0 - 19
but my requirement is to have it reversed, i.e
pin 0 - 19 mapped to gpio0 hw pins 0 - 19 and
pin 20 - 49 mapped to gpio1 hw pins 0 - 29
and i can't change the dt node entry order(req from client).
I've already looked into aliases section where the bus nos. are assigned. I wanted to know if there is any field in dt node which determines the order or anything in uboot gpio framework which can determine the pin mapping.
Related
I am using dwapb gpio driver under aarch64 linux. Port A of the gpio device supports interrupt. In my configuration, the sdhc host acts as the consumer of gpio, i.e., sdhc's interrupt signal is connected to pin 7 on port a, thus interrupts from sdhc has the following path:
sdhc -> gpio -> gic -> cpu.
The sdhc uses level-sensitive trigger method (which is the default config of gpio). For interrupt polarity, the default setting is active-low. If I use the default setting, after enabling the interrupt on the gpio pin, the pin voltage is 3v3 (measured using multimeter). It seems that it's reasonable, that the pin voltage is set to high, while waiting active-low interrupt signals.
The problem I am facing is when I configure the polarity to active-high. In this case, right after enable the pin, the voltage is also 3v3, which causes immediate irq storm to the kernel. Apparently, the voltage on the pin should be 0 after enabling the interrupt on this pin. But I am not able to get this done.
I tried to the following steps for enabling the irq for ACTIVE-HIGH:
change the pin direction to "output"
change the pin value to 0
change the pin direction to "input"
enable the interrupt of the pin
I was hoping that steps 1~3 will keep the pin voltage to 0 after step 4, but it seems that it's not the case. No matter what value I set before step 4, after step 4, the pin voltage will change to 3v3 (measured by multimeter).
Is there a way to get the ACTIVE-HIGH work properly?
I'm trying to use Linux Infrared Remote Control LIRC library to record a custom signal from remote control and save it in a file. Then I will use these signals to send it back again through ir tx using raspberry pi
when I run test ir rx mode2 -d /dev/lirc1 the output seems good .
Using driver default on device /dev/lirc1
Trying device: /dev/lirc1
Using device: /dev/lirc1
space 16777215
pulse 9044
space 4463
pulse 601
space 1641
pulse 628
space 532
pulse 575
space 558
pulse 577
space 530
pulse 603
But when I open the /etc/lirc/lircd.conf file, this happens:
# Type of device controlled
# (TV, VCR, Audio, DVD, Satellite, Cable, HTPC, ...) :
# Device(s) controlled by this remote:
begin remote
name fan
bits 0
flags CONST_LENGTH
eps 0
aeps 0
one 0 0
zero 0 0
gap 50000
toggle_bit_mask 0x0
frequency 38000
begin codes
KEY_POWER 0x0
KEY_0 0x0
KEY_1 0x0
end codes
end remote
All saved keys are zeroes, so how do I solve this problem?
Your LIRC driver is configured and seems ok from this side. However it is worth double checking the driver has been set up correctly as I think this is the problem.
Assuming you are using T95m/T95N remote:
0x140 KEY_POWER
0x155 KEY_POWER
0x101 KEY_0
0x14e KEY_1
Try editing your etc/lirc/lircd.conf with the above values running it(blast some IR commands) and seeing if it turns the values back to 0x0 after.
I would suggest that you declare the transmitter GPIO pin first then the receiver
like this :
dtoverlay=gpio-ir-tx,gpio_pin=17
dtoverlay=gpio-ir,gpio_pin=18
and i would double check /etc/lirc/lirc_options.conf as TeeJay suggested
this fixed my problem on raspberrypi 3+
can someone explain the device tree settings? What they will do on i.MX6 Processor?
Thanks!
vbus1_regulator: regulator#1 {
compatible = "regulator-fixed";
regulator-name = "vbus1_regulator";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
&usbotg {
vbus-supply = <&vbus1_regulator>;
dr_mode = "host";
status = "okay";
};
The USB protocol defines two roles - host and client. With USB OTG (on-the-go) a device can have both host and client capabilities. See:
http://www.usb.org/developers/onthego/
https://www.maximintegrated.com/en/app-notes/index.mvp/id/1822
In order for the device to work as a host, it needs to provide power for the client device connected to it, as required by the USB standard.
That being said, the &usbotg node is:
Using the _vbus1_regulator_ as USB power supply.
Forcing the USB OTG port to work as host by setting the dr_mode property to host.
Enabling the node by setting the status to okay.
Please see the Linux kernel device-tree bindings documentation for more details:
https://www.kernel.org/doc/Documentation/devicetree/bindings/usb/fsl-usb.txt
And the vbus1_regulator node is:
Using the kernel driver compatible to regulator-fixed: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/regulator/fixed.c?h=v4.19-rc1#n196
Setting the name of the regulator to vbus1_regulator.
Defining the minimum and maximum voltages to the same value of 5000000 micro volts, which as the same as 5 volts. Both are the same due to the nature of a fixed voltage regulator - you have a single fixed output voltage value.
Using a GPIO pin (declared elsewhere) to control the regulator (switch on/off).
Defining that the GPIO level must be high in order to activate the regulator. If this property is omitted, that it is assumed that the regulator is active on logic level low.
Please see the Linux kernel device-tree bindings documentaiton for more details:
https://www.kernel.org/doc/Documentation/devicetree/bindings/regulator/fixed-regulator.txt
I am facing an interesting problem. I like to set a pin of my cpu. So far I created a module for controlling the pin. This module is setting the default pin configuration(high). The default pin configuration becomes active when the module is loaded. That is working fine.
Now I like to enable my default pin configuration right away from the start of boot process. To archive that I wrote a patch for the ATMEL bootloader(at91bootstrap) and the uboot(u-boot-at91). This works fine till the moment the kernel starts. At the kernel start the pins is set to the ATMEL default. They pins are defined in the device tree as gpios.
I think I have two possibilities:
1st - patch the /init/main.c at the "right" spot. Where is the right spot?
2nd - modify the device tree to set the GPIOs to an other default value. How to "re set" an gpio a value?
When you modify the pin in u-boot level; it will be override by the kernel. /init/main.c is worse idea and so I think you should not followed this approach
In kernel level if you you want to set the GPIO pin, there are two possibilities (apart from your module)
1) Kernel board file.
2) Device tree file.
Suppose if you want to set the SDIO pin as GPIO in i.MX6 board then you need to modify the code like this.
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_leds>;
red {
gpios = <&gpio7 0 0>;
default-state = "on";
};
MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 //set the pin as GPIO
For the default state of the pin please refer the datasheet of your processor. And one pin may have different functionalities.
And if you want to use the same pin for some other functionalities instead of GPIO then you can choose on of the below configuration.
MX6QDL_PAD_SD3_DAT5__UART2_RX_DATA //UART2 RX Data pin
MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 //As a GPIO pin
MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA // UART1 RX data
MX6QDL_PAD_SD3_DAT6__SD3_DATA6 //SDIO pin which is default in this case
Please add more details if you are looking for something more (like pin number and device tree file name).
I read this excellent DIY article on writing Linux device drivers, but am still not seeing the "forest through the trees" on a major item here. Ultimately the end user software (in user space) needs to communicate with the hardware (that the device drivers are driving/wrapping/adapting). Hardware is driven by electricity, and hence software commands need to be translated into hi/lo signals (1s and 0s) that get pushed out onto a circuit and into the connected hardware. A stupid simple example:
# Send a connected LED device a command to turn on at the software layer:
led.turnOn();
# In the device driver, somehow, translate this to 0x01 (1, or 00000001):
void turnOn() {
int signal = 1;
# Now, *somehow*, push this to the hardware with the following pinout (see below):
}
# Pinout
0 ----------------> /----------\
0 ----------------> | |
0 ----------------> | |
0 ----------------> | Hardware |
0 ----------------> | |
0 ----------------> | |
0 ----------------> | |
1 ----------------> \----------/
What I'm not seeing is: in the device driver C code, how do I read/write bytes/data to and from the underlying hardware device?
The only theory I could see is that perhaps, because Linux devices are seen as "files" (dev/led) to the user space, perhaps writing data, such as 0x01, to dev/led is how we send commands to connected devices; and perhaps reading data from devices is how we read data off of them.
Am I heading in the right direction here, or way off track?
It really depends on the nature of the device and how it is connected to the system - it could be memory-mapped, or mapped to some kind of addressable I/O space, or on a bus such as PCI-e or USB, for example. The whole point is to abstract this in the driver so that the programmer doesn't have to care about the low-level details.
For a PCI device for example the board might be mapped to a physical address range. Within this range you might access certain registers to control the hardware. Suppose you have a simple I/O card with a single 32 bit register and the card is mapped to physical address 0xf0000000. The register is used to control 32 LED outputs and you want to turn on LED 0:
volatile uint32_t * const my_card_register = (uint32_t *) 0xf0000000;
// address of PCI card register
*my_card_register |= 0x00000001; // set bit 0 in register to turn on LED