I have a Ti's AM335x custom board. I want to define some pins as gpios and be able to set them as input and output in its Linux userspace.
I defined pins in am33xx_pinmux and then referenced it with the bone-pinmux-helper. The problem is I can set it with these commands on the terminal but it doesn't work.
echo 4 > /sys/class/gpios/export
echo out > /sys/class/gpios/gpio4/direction
echo 1 > /sys/class/gpios/value
here is a brief of my code for just two pins gpio0_4 gpio0_5, each pin must become available to set as input or output in userspace.
#include "am33xx.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>
&am33xx_pinmux {
pinctrl-names = "default";
DATA_OUT_A00:DATA_OUT_A00 {
pinctrl-single,pins = <0x158 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) >; /*gpio0_4*/
};
DATA_OUT_A01:DATA_OUT_A01 {
pinctrl-single,pins = <0x15C (PIN_OUTPUT_PULLDOWN | MUX_MODE7) >; /*gpio0_5*/
};
...
}
...
&ocp {
test_helper: helper {
compatible = "bone-pinmux-helper";
status = "okay";
pinctrl-names = "DATA_OUT_A00", "DATA_OUT_A01";
pinctrl-0 = <&DATA_OUT_A00>;
pinctrl-1 = <&DATA_OUT_A01>;
}
}
EDIT:-------------------
I'm using main Ti kernel 4.9 version. If I want to define these two pins as output this DTS works fine but ONLY for output mode. I can export pins as input but when I read its value it always returns zero.
#include "am33xx.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>
/ {
model = "My Custom board C335x";
compatible = "ti,am33xx";
cpus {
cpu#0 {
cpu0-supply = <&vdd_core>;
};
};
...
gpio-leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&led_pins>;
// the following two blocks make the pins available in /sys/class/leds
// if removed can be accessd with /sys/class/gpios
test_led1 {
label = "test";
gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
test_led2 {
label = "test";
gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
};
}
&am33xx_pinmux {
pinctrl-names = "default";
led_pins: pinmux_led_pins {
pinctrl-single,pins = <
0x158 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /*gpio0_4*/
0x15C (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /*gpio0_5*/
>;
};
...
}
If I leave these pins in the DTS file, I still can export them but I can't get any input or set a value as output to them.
Related
I constantly get this error, no matter what I'm doing... I have an ILI9488 with 4-wire SPI and a GT911 capacitive Touch driver on an ESP32 (2MB, no PSRAM, arduino core).
this is my main.ino-file:
#include <lvgl.h>
#include <TFT_eSPI.h>
#include <Wire.h>
#include "Goodix.h"
#define INT_PIN 26
#define RST_PIN 15
#define SDA_PIN 22
#define SCL_PIN 16
Goodix touch = Goodix();
#define DISPLAY_BUF_SIZE 480 * 10
static uint16_t display_widht = 480;
static uint16_t display_height = 320;
TFT_eSPI tft = TFT_eSPI(); /* TFT instance */
bool touched = false;
GTPoint touchDat;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[ DISPLAY_BUF_SIZE];
lv_disp_drv_t disp_drv; //display driver
lv_indev_drv_t touch_drv; //touchpad driver
void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p ){
uint32_t w = ( area->x2 - area->x1 + 1 );
uint32_t h = ( area->y2 - area->y1 + 1 );
tft.startWrite();
tft.setAddrWindow( area->x1, area->y1, w, h );
tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
tft.endWrite();
lv_disp_flush_ready( disp );
}
void handleTouch(int8_t contacts, GTPoint* points) {
Serial.printf("Contacts: %d\n", contacts);
if(contacts > 0) touched = true;
else touched = false;
for (uint8_t i = 0; i < contacts; i++) {
touchDat = points[0];
Serial.printf("C%d: %d %d \n", points[i].trackId, points[i].x, points[i].y);
}
}
/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * touch_drv, lv_indev_data_t * data ){
if( !touched ) //kein Touch
{
data->state = LV_INDEV_STATE_REL;
}
else //touch!
{
data->state = LV_INDEV_STATE_PR;
/*Set the coordinates*/
data->point.x = touchDat.x;
data->point.y = touchDat.y;
}
}
void i2cInit(){
Wire.setPins(SDA_PIN, SCL_PIN);
Wire.setClock(400000);
Wire.begin();
delay(100);
}
void touchInit() {
touch.setHandler(handleTouch);
touch.setRes(display_widht, display_height);
touch.setRotation(3);
touch.begin(INT_PIN, RST_PIN, GOODIX_I2C_ADDR_28);
Serial.print("Check ACK on addr request on 0x");
Serial.print(touch.i2cAddr, HEX);
Wire.beginTransmission(touch.i2cAddr);
if (!Wire.endTransmission()) {
Serial.println(": SUCCESS");
} else {
Serial.print(": ERROR!");
}
}
void tftInit(){
tft.begin();
tft.setRotation(3);
lv_disp_draw_buf_init( &draw_buf, buf, NULL, DISPLAY_BUF_SIZE ); //init draw Buffer
/*Initialize the display*/
static lv_disp_drv_t disp_drv;
lv_disp_drv_init( &disp_drv );
/*Change the following line to your display resolution*/
disp_drv.hor_res = display_widht;
disp_drv.ver_res = display_height;
disp_drv.flush_cb = my_disp_flush;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register( &disp_drv );
/*Initialize the input device driver*/
static lv_indev_drv_t touch_drv;
lv_indev_drv_init( &touch_drv );
touch_drv.type = LV_INDEV_TYPE_POINTER;
touch_drv.read_cb = my_touchpad_read;
lv_indev_drv_register( &touch_drv );
//create simple label
lv_obj_t *label = lv_label_create( lv_scr_act() );
lv_label_set_text( label, "Hello World!!" );
lv_obj_align( label, LV_ALIGN_CENTER, 0, 0 );
}
void setup() {
Serial.begin(115200); /* prepare for possible serial debug */
i2cInit();
touchInit(); //initialize touch
lv_init();
}
void loop() {
touch.loop();
lv_task_handler(); /* let the GUI do its work */
delay(5);
}
these are my main.ino and lv_config.h-files:
https://gist.github.com/kokospalme/a65448c1d10704066b9c6d2350c84a6d
even if I change LV_MEM_SIZE to something small like 1 or 10, I get the error, that " region `dram0_0_seg' overflowed by 22272 bytes". What am I doing wrong?
I've written an I2C driver. I want to make the GPIO which it uses configurable from the device tree.
My device tree entry is currently:
&i2c1 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
status = "okay";
...
myi2c: myi2c#43 {
compatible = "fsl,myi2c";
reg = <0x43>;
};
I'd like to add this line into the myi2c stanza:
myi2c-gpios = <&gpio4 29 GPIO_ACTIVE_HIGH>;
I can see how to do this, if I was writing a platform driver:
static int gpio_init_probe(struct platform_device *pdev)
{
int i = 0;
printk("GPIO example init\n");
/* "greenled" label is matching the device tree declaration. OUT_LOW is the value at init */
green = devm_gpiod_get(&pdev->dev, "greenled", GPIOD_OUT_LOW);
but in my driver's i2c_probe(), I have no access to a struct platform_device *:
static int myi2c_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
How can I read the value of myi2c-gpios from the device tree and use it in my i2c driver?
I found this driver to use as an example:
static int sn65dsi84_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
...
struct gpio_desc *enable_gpio;
enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_HIGH);
if (enable_gpio)
gpiod_set_value_cansleep(enable_gpio, 1);
and its device tree is:
&i2c2 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
dsi_lvds_bridge: sn65dsi84#2c {
status = "disabled";
reg = <0x2c>;
compatible = "ti,sn65dsi84";
enable-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>;
So devm_gpiod_get_optional() seems to be the answer.
I'm working on a Cyclone V SOC FPGA from Altera with a double Cortex-A9 processor. The embedded system (linux-socfpga 4.16) is created with Buildroot-2018.05.
I use a "top" device tree at boot time for processor component and a device-tree overlay to configure the FPGA part of the component and load the associated drivers. The overlay will be attach to the base_fpga_region of the top DT.
top device tree
/dts-v1/;
/ {
model = "MY_PROJECT"; /* appended from boardinfo */
compatible = "altr,socfpga-cyclone5", "altr,socfpga"; /* appended from boardinfo */
#address-cells = <1>;
#size-cells = <1>;
cpus {
[...]
}; //end cpus
memory {
device_type = "memory";
reg = <0xffff0000 0x00010000>,
<0x00000000 0x80000000>;
}; //end memory
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
mem_dma_reserved {
compatible = "shared-dma-pool";
no-map;
reg = <0x78000000 0x8000000>;
};
};
soc: soc {
device_type = "soc";
ranges;
#address-cells = <1>;
#size-cells = <1>;
compatible = "altr,avalon", "simple-bus";
bus-frequency = <0>;
fpgabridge1: fpgabridge#1 {
compatible = "altr,socfpga-lwhps2fpga-bridge";
resets = <&hps_rstmgr 97>; /* appended from boardinfo */
clocks = <&l4_main_clk>; /* appended from boardinfo */
#address-cells = <1>;
#size-cells = <1>;
ranges;
bridge-enable = <1>;
label = "lwhps2fpga";
reset-names = "lwhps2fpga";
reg = <0xff200000 0x200000>;
reg-names = "axi_h2f_lw";
}; //end fpgabridge#1 (fpgabridge1)
base_fpga_region: base_fpga_region {
compatible = "fpga-region";
#address-cells = <0x2>;
#size-cells = <0x1>;
fpga-mgr = <&hps_fpgamgr>;
fpga-bridges = <&fpgabridge1>;
ranges = <0x0 0x0 0xff200000 0x200000>;
}; //end base_fpga_region (base_fpga_region)
etc......
Device tree overlay
/dts-v1/ /plugin/;
/{
fragment#0 {
target-path = "/soc/base_fpga_region";
#address-cells = <2>;
#size-cells = <1>;
__overlay__ {
#address-cells = <2>;
#size-cells = <1>;
firmware-name = "my_project.rbf";
my_dma_0: dma#0x000000000 {
compatible = "my_company,my_dma-0.1";
reg = <0x00000000 0x0000000 0x00000014>;
memory-region = <&mem_dma_reserved>;
}; //end dma#0x000000000 (my_dma_0)
};
};
};
my problem is to link the mem_dma_reserved from the top DT to the memory-region in the overlay.
I assume that while converting dts to dtbo with the -# option, the overlay shall get the phandle for mem_dma_reserved with the __fixups__ option. I've created the dtbo file and converted it again in dts to see what is done during the compilation :
dtc -# -I dts -O dtb -o overlay.dtbo overlay.dts
dtc -I dtb -O dts -o overlay_recovery.dts overlay.dtbo
device tree overlay regenerated
/dts-v1/;
/ {
fragment#0 {
target-path = "/soc/base_fpga_region";
#address-cells = <0x2>;
#size-cells = <0x1>;
__overlay__ {
#address-cells = <0x2>;
#size-cells = <0x1>;
firmware-name = "my_project.rbf";
dma#0x000000000 {
compatible = "my_company,my_dma-0.1";
reg = <0x0 0x0 0x14>;
memory-region = <0xffffffff>; // phandle converted to 0xffffffff, cannot resolve unless the __fixup__ function does it.
linux,phandle = <0x2>;
phandle = <0x2>;
};
};
};
__symbols__ {
my_dma_0 = "/fragment#0/__overlay__/dma#0x000000000";
};
__fixups__ {
mem_dma_reserved = "/fragment#0/__overlay__/dma#0x000000000:memory-region:0";
};
};
We can see that the phandle for the memory-region is 0xFFFFFFFF because the overlay doesn't know about the <&mem_dma_reserved> node. the fixup part shall be able to get back the phandle at loading time, but it isn't working and I get this error :
[ 27.434730] OF: resolver: of_resolve_phandles: no symbols in root of device tree.
[ 27.440401] OF: resolver: overlay phandle fixup failed: -22
[ 27.445993] create_overlay: Failed to resolve tree
I have made the same regeneration from dtb to dts on the top DT. I have seen that the phandle of the reserved memory is actually 0x6. I have written <0x6> instead of <&mem_dma_reserved> in the device tree overlay and with this configuration, everything loads !
How can I make the overlay find the <&mem_dma_reserved> automatically without doing it by hand ?
EDIT
As pointed by ikwzm I have added in the top device tree the following lines :
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
mem_dma_reserved: mem_dma_reserved { // add a label
compatible = "shared-dma-pool";
no-map;
reg = <0x78000000 0x8000000>;
};
};
[...]
// add the whole symbol block
__symbols__ {
mem_dma_reserved = "/reserved-memory/mem_dma_reserved ";
};
The errors are now gone, but :
I was expecting the driver for my_dma to be loaded during the operation.
I checked that the device tree overlay is well taken into account with :
ls /sys/firmware/devicetree/base/soc/base_fpga_region/
my_dma_0
other_stuff
cat /sys/firmware/devicetree/base/soc/base_fpga_region/my_dma_0/memory-region
//nothing//
The memory region doesn't seem to be attached.
What I have missed ?
When making the top dtb, did you attach the option --symbol (or -#) to the dtc command?
Add a label (symbol) to mem_dma_reserved as follows.
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
mem_dma_reserved: mem_dma_reserved {
compatible = "shared-dma-pool";
no-map;
reg = <0x78000000 0x8000000>;
};
};
When dtb is created with the --symbol option dtc command, __symbols__{...}; is added as follows, and mem_dma_reserved = "/reserved-memory/ mem_dma_reserved"; should be found in it.
__symbols__ {
:
:
:
mem_dma_reserved = "/reserved-memory/mem_dma_reserved";
usb_phy0 = "/phy0";
};
Hello I am looking at this documentation.
https://www.kernel.org/doc/html/v4.11/driver-api/i2c.html
My goal is simply to write some data to an EEPROM using an I2C bus. I am a bit confused on which functions to use and how to populate the structures that are needed for those functions.
My guess is that I will need to create an i2c_client to represent the EEPROM. I have the location of the EEPROM from this device tree.
&i2c0 {
status = "okay";
clock-frequency = <400000>;
pinctrl-names = "default";
i2cswitch#74 {
compatible = "nxp,pca9548";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x74>;
i2c#2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
eeprom#54 {
compatible = "at,24c08";
reg = <0x54>;
};
};
};
};
How would I go about filling the i2c_client struct with this data?
Then I am guessing I would use this function
int i2c_master_send(const struct i2c_client * client, const char * buf, int count)
And provid it the client struct and a string that I want to write as well as the length of that string with the stipulation it is less than 64k. In this case the CPU is the master?
What header files will I need to included to use the functions and structs that are provided by the documentation?
Thanks.
I am trying to learn to write a i2c driver on raspberry pi board and i have taken groove LCD back-light.Here driver.probe is not getting called whereas driver's inserted in system as i can see in dmesg.
Init code of driver is getting called, and code =>
static int lcd_probe(struct i2c_client *i2c_client, const struct i2c_device_id *i2c_id)
{
int ret = 0;
//struct lcd_data *lcd_data;
// struct device *dev = &i2c_client->dev;
// lcd_data->client = i2c_client;
pr_debug("lcd_probe : calling the probe\n");
pr_debug("lcd_probe : i2c_client->addr = %d, i2c_client_name = %s\n",
i2c_client->addr, i2c_client->name);
return ret;
}
static struct i2c_device_id lcd_id[] = {
{"lcd", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, lcd_id);
static struct i2c_driver lcd_driver = {
.driver = {
.name = "lcd",
.owner = THIS_MODULE,
},
.probe = lcd_probe,
// .remove = lcd_remove,
// .attach_adapter = lcd_attach,
.detect = lcd_detect,
.id_table = lcd_id,
};
static int __init lcd_init(void)
{
pr_debug("lcd_init : calling init\n");
return (i2c_add_driver(&lcd_driver));
}
and dmesg =>
[ 1.971009] lcd_init : calling init
But driver.probe is not registering in i2c subsystem.
board file initialization =>
Board init code =>
/** start aartyaa lcd i2c driver */
printk(KERN_INFO "board file registering i2c lcd device\n");
i2c_register_board_info_dt(1, lcd_i2c_devices, ARRAY_SIZE(lcd_i2c_devices));
i2c_board_info code =>
/** aaryaa i2c lcd struct */
static struct i2c_board_info __initdata lcd_i2c_devices[] = {
{
.type = "lcd",
.addr = 0x62,
},
};
i added debugs in i2c_register_device
and i found driver prove device is not getting called. dmesg i have linked
dmesg link
It seems that i need to register in platform also ..
How probe gets called in i2c ... ?
Any help will be appreciated.
Thank you...!!!