2009-07-30 06:13:27 I2C Driver in uClinux 2008R1.5
Patrick Hotz (GERMANY)
Message: 78192
Hi,
after lots of tests with finished drivers without success i want to write my own driver for a I2C-Chip.
I have read the documentation for writing clients but i cant get some tests running.
I have added this into my board config file:
static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
{
.driver_name = "tsc2003",
.addr = 0x48,
.irq = IRQ_PG0,
},
};
and this
static int __init cm_bf537_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
platform_add_devices(cm_bf537_devices, ARRAY_SIZE(cm_bf537_devices));
i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info));
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
#endif
#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
#endif
return 0;
}
My driver is at time only a test:
#include <linux/module.h>
#include <linux/hrtimer.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
static int tsc2003_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
printk("tsc2007_probe\n");
return(0);
}
static int tsc2003_remove(struct i2c_client *client)
{
printk("tsc2003_remove\n");
return 0;
}
static struct i2c_driver tsc2003_driver = {
.driver = {
.name = "tsc2003",
},
/* iff driver uses driver model ("new style") binding model: */
.probe = tsc2003_probe,
.remove = tsc2003_remove,
};
static int __init tsc2003_init(void)
{
return i2c_add_driver(&tsc2003_driver);
}
static void __exit tsc2003_exit(void)
{
i2c_del_driver(&tsc2003_driver);
}
module_init(tsc2003_init);
module_exit(tsc2003_exit);
My question is following:
On bootup i see a message "i2c /dev entries driver" so i think there sould be someting working...
But why cant i see the printk in my driver?
This is my first driver so i would be lucky if someone can write me a short running sample or something like that.
Regards,
Patrick
TranslateQuoteReplyEditDelete
2009-07-30 06:43:06 I2C Driver in uClinux 2008R1.5
Michael Hennerich (GERMANY)
Message: 78195 Your drivers probe() get's only called in case a client with 0x48 is present on the bus.
(on the name field matches)
Use u-boot iprobe command to test if this is really the case.
In this example below:
There are i2c clients with 0x18 and 0x50 present.
U-Boot 2008.10-svn1961 (ADI-2009R1-rc2) (Jul 7 2009 - 10:38:43)
CPU: ADSP bf537-0.2 (Detected Rev: 0.3) (bypass boot)
Board: ADI BF537 stamp board
Support: blackfin.uclinux.org/
Clock: VCO: 500 MHz, Core: 500 MHz, System: 125 MHz
RAM: 64 MB
Flash: 4 MB
In: serial
Out: serial
Err: serial
Net: Blackfin EMAC
MAC: 4E:03:4E:03:4E:03
Hit any key to stop autoboot: 0
bfin> iprobe
Valid chip addresses: 18 50
bfin
QuoteReplyEditDelete
2009-07-30 07:58:55 Re: I2C Driver in uClinux 2008R1.5
Patrick Hotz (GERMANY)
Message: 78198
OK, i have checked this with iprobe and is shows "Valid chip addresses: 48".
So this should work?
I have also written a few days ago a short program which is using the "/dev/i2c-X" device to read values from the chip, this is working without problems.
I dont know what i can try.
Maybe you can hav a short look to my config...
Patrick
20090730.config
TranslateQuoteReplyEditDelete
2009-07-30 08:00:31 Re: I2C Driver in uClinux 2008R1.5
Patrick Hotz (GERMANY)
Message: 78199
I forgot:
i have checked the SDA and SCL with my scope, there is no activity
TranslateQuoteReplyEditDelete
2009-07-30 08:19:53 I2C Driver in uClinux 2008R1.5
Michael Hennerich (GERMANY)
Message: 78201 Looks like you are using 2.6.22 - it might be the case that the new style i2c client binding doesn't work in 2.6.22.
>static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
> {
> .driver_name = "tsc2003",
> .addr = 0x48,
> .irq = IRQ_PG0,
> },
>};
Can you test with 2009R1?
And please you the I2C_BOARD_INFO macro.
.driver_name changed to .type after 2.6.22
/**
* I2C_BOARD_INFO - macro used to list an i2c device and its address
* @dev_type: identifies the device type
* @dev_addr: the device's address on the bus.
*
* This macro initializes essential fields of a struct i2c_board_info,
* declaring what has been provided on a particular board. Optional
* fields (such as associated irq, or device-specific platform_data)
* are provided using conventional syntax.
*/
#define I2C_BOARD_INFO(dev_type, dev_addr) \
.type = dev_type, .addr = (dev_addr)
QuoteReplyEditDelete
2009-07-30 09:01:15 Re: I2C Driver in uClinux 2008R1.5
Patrick Hotz (GERMANY)
Message: 78203
Hi,
the kernel is 2.6.22-18-ADI-2008R1-svn.....
I have tested the same on uClinux-dist2010R1-pre and there is the same problem.
The struct i have changed to this one:
static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
{
I2C_BOARD_INFO("tsc2003", 0x48),
.irq = IRQ_PG0,
},
};
TranslateQuoteReplyEditDelete
2009-07-30 09:13:58 Re: I2C Driver in uClinux 2008R1.5
Michael Hennerich (GERMANY)
Message: 78204 Didn't you mention that you once saw "platform data is required"?
This means that the kernel called probe() and that you only failed to initialize .platform_data.
-Michael
QuoteReplyEditDelete
2009-07-30 09:33:54 Re: I2C Driver in uClinux 2008R1.5
Patrick Hotz (GERMANY)
Message: 78205
yes, a few days ago i tried the driver tsc2007.c from the trunk and there was the problem with the platform data.
But this was only a test if this driver is running and i can try to port this driver to the 2008-dist.
But the driver has some more problems that i cant port it to the older dist i use.
So i thought it is the best way to write a complete new driver for the 2008-dist.
So i need a example to write a i2c-driver in the 2.6.22-18 kernel..
Regards,
Patrick
TranslateQuoteReplyEditDelete
2009-07-30 09:54:54 Re: I2C Driver in uClinux 2008R1.5
Patrick Hotz (GERMANY)
Message: 78206
Now i have tried to copy only the needed things for a driver from the tsc2007.c
I have only changed the 7 into a 3 and the kernel shows no printk on bootup if i set the tsc2003 in my board-config...
I dont know where is the difference between the two drivers because the tsc2003.c is only a copy from the tsc2007.c
Patrick
tsc2003.c
tsc2007.c
TranslateQuoteReplyEditDelete
2009-07-30 09:59:03 Re: I2C Driver in uClinux 2008R1.5
Michael Hennerich (GERMANY)
Message: 78207 I would consider moving to the 2009R1 Release branch - I'm sure this driver is working there!
If you can't update to 2009R1 use the old style i2c driver binding-
As an example take a look at any of the i2c client drivers in 2008R1.
I know drivers/input/joystick/ad7142.c is a example that works.
-Michael
QuoteReplyEditDelete
2009-07-30 10:05:20 Re: I2C Driver in uClinux 2008R1.5
Michael Hennerich (GERMANY)
Message: 78211 I wonder where you initialize struct i2c_driver .id_table ?
-Michael
QuoteReplyEditDelete
2009-07-30 10:15:28 Re: I2C Driver in uClinux 2008R1.5
Patrick Hotz (GERMANY)
Message: 78215
What is the .id_table exactly? i haven't found anything about this....
But just i have tried the attach and detach version and it looks to be working.... i can see the printk...
Now i will try to modifi the ad7142.c driver to my chip.
Thank you
TranslateQuoteReplyEditDelete
2009-07-30 10:23:22 Re: I2C Driver in uClinux 2008R1.5
Michael Hennerich (GERMANY)
Message: 78216 struct i2c_device_id idtable[] holds the name and a general purpose id
of your driver.
This name must match with the one given with I2C_BOARD_INFO() in your
platform file.
If they don't match your drivers probe function won't get called!
-Michael
QuoteReplyEditDelete
2009-07-31 06:18:01 Re: I2C Driver in uClinux 2008R1.5
Patrick Hotz (GERMANY)
Message: 78246
Hi,
i am working forward with my driver...
i have running the probe, request an irq and read from the chip.
The problem i have now is following:
I read the values from chip a first time at "probe" to enable the irq.
later i want to read the same values again if a irq occours.
This is my irq:
static irqreturn_t tsc2007_irq(int irq, void *_data)
{
printk("IRQ_%d: tsc2007_irq\n", irq);
struct tsc2003 *data = _data;
disable_irq(irq);
tsc2007_read_values(data);
enable_irq(irq);
return IRQ_HANDLED;
}
If the irq occous the kernel chrashes:
IRQ_66: tsc2007_irq
tsc2007_xfer
client->flags = 0
client->addr = 48
client->name = tsc2003
client->irq = 66
BUG: scheduling while atomic: adiVP/0x00010000/67
Hardware Trace:
0 Target : <0x0010367c> { _dump_stack + 0x0 }
Source : <0xffa01de6> { _schedule + 0x502 }
1 Target : <0xffa01de2> { _schedule + 0x4fe }
Source : <0x0010c14e> { _printk + 0x16 }
2 Target : <0x0010c14a> { _printk + 0x12 }
Source : <0x0010c000> { _vprintk + 0x1b8 }
3 Target : <0x0010bff4> { _vprintk + 0x1ac }
Source : <0xffa00fde> { _evt_timer + 0x2 }
4 Target : <0xffa00fdc> { _evt_timer + 0x0 }
Source : <0x0010bff2> { _vprintk + 0x1aa }
5 Target : <0x0010bfe2> { _vprintk + 0x19a }
Source : <0x0010be30> { _wake_up_klogd + 0x24 }
6 Target : <0x0010be0c> { _wake_up_klogd + 0x0 }
Source : <0x0010c538> { _release_console_sem + 0x1f4 }
7 Target : <0x0010c52a> { _release_console_sem + 0x1e6 }
Source : <0x0010c51c> { _release_console_sem + 0x1d8 }
8 Target : <0x0010c512> { _release_console_sem + 0x1ce }
Source : <0x0010c504> { _release_console_sem + 0x1c0 }
9 Target : <0x0010c4e4> { _release_console_sem + 0x1a0 }
Source : <0x0010c3ca> { _release_console_sem + 0x86 }
10 Target : <0x0010c39a> { _release_console_sem + 0x56 }
Source : <0x0010c4c6> { _release_console_sem + 0x182 }
11 Target : <0x0010c4c0> { _release_console_sem + 0x17c }
Source : <0x0010bd06> { __call_console_drivers + 0x7e }
12 Target : <0x0010bd00> { __call_console_drivers + 0x78 }
Source : <0x0010bcc2> { __call_console_drivers + 0x3a }
13 Target : <0x0010bcb2> { __call_console_drivers + 0x2a }
Source : <0x0010bca2> { __call_console_drivers + 0x1a }
14 Target : <0x0010bc88> { __call_console_drivers + 0x0 }
Source : <0x0010c4bc> { _release_console_sem + 0x178 }
15 Target : <0x0010c4b2> { _release_console_sem + 0x16e }
Source : <0x0010c450> { _release_console_sem + 0x10c }
Stack from 01a93ca8:
003c260c ffa01dea 01a92000 0023281a 003c22a8 01eb620c 00010000 00000043
001984a8 00000000 00000042 01a93d18 0023281a 01a92000 01ee2204 00292634
00000002 01ee2204 00000048 00000001 00000000 00000042 01a93d50 00000001
01eb6080 001093b8 01ee2208 01ee2208 00000003 001d61ee 01ee2000 01ee2024
00000003 000000f0 00003d7f 00003d90 001987e2 002c03c2 001d3724 ffffffd4
01ee203c 00348c00 01ee205c 00000000 00000048 00000001 00293048 00293048
Call Trace:
[<00198ae2>] _vscnprintf+0x16/0x24
[<0010bfe2>] _vprintk+0x19a/0x2f0
[<0010bfe2>] _vprintk+0x19a/0x2f0
[<0010bfe2>] _vprintk+0x19a/0x2f0
[<001d3bd8>] _i2c_smbus_read_word_data+0x2c/0x48
[<0012b8aa>] ___alloc_pages+0x46/0x230
[<001085a6>] ___activate_task+0x1a/0x34
[<001d2e2c>] _tsc2007_read_values+0x64/0x36c
[<001d3158>] _tsc2007_irq+0x24/0x34
[<00125f58>] _handle_IRQ_event+0x34/0x5c
[<00126dc6>] _handle_edge_irq+0x7e/0xf4
[<001076de>] _bfin_demux_gpio_irq+0x96/0xb0
[<00107410>] _safe_speculative_execution+0x0/0x8
[<002abd7e>] _bfin_init_mmr_debugfs+0x5e6e/0x7074
[<002abd7e>] _bfin_init_mmr_debugfs+0x5e6e/0x7074
[<002a9844>] _bfin_init_mmr_debugfs+0x3934/0x7074
[<002abd7e>] _bfin_init_mmr_debugfs+0x5e6e/0x7074
[<002abd9a>] _bfin_init_mmr_debugfs+0x5e8a/0x7074
[<002acec7>] _bfin_init_mmr_debugfs+0x6fb7/0x7074
[<002ae181>] _console_setup+0xdd/0xf0
[<002acec6>] _bfin_init_mmr_debugfs+0x6fb6/0x7074
[<002ae174>] _console_setup+0xd0/0xf0
I dont know the reason...
Maybe someone can help me.
Patrick
tsc2003.c
TranslateQuoteReplyEditDelete
2009-07-31 06:57:58 Re: I2C Driver in uClinux 2008R1.5
Michael Hennerich (GERMANY)
Message: 78248 Don't read or write I2C from interrupt context!!!
Schedule a workqueue and read from kthread context.
-Michael
QuoteReplyEditDelete
2009-08-03 02:25:16 Re: I2C Driver in uClinux 2008R1.5
Patrick Hotz (GERMANY)
Message: 78285
Hi,
iḿ working forward with my new driver.
Now the reads from the chip are ok and i can print a position.
The next step is to try if the touches are sent to a program which is using the mouse-function.
Is there any testprogram which i can try? I havn found ts-calibrate in 2008R1....
I'm also not shure if the "input_report_abs" is correctly used....
Attached is my driver.
Regards,
Patrick
tsc2003.c
TranslateQuoteReplyEditDelete
2009-08-03 06:11:01 Re: I2C Driver in uClinux 2008R1.5
Patrick Hotz (GERMANY)
Message: 78302
Hi,
forget my last post. I have compiled the tslib and set the variables described in ad7879 in docs.
The problem i have now is following:
If i press the touch for a few seconds the kernel is sometimes hanging (maybe there is too moch traffic on i2c because i read continously the values if the touch is pressed).
The other problem is that the ts_calibrate sometimes dont register the touches (i think this is a problem of the function"tsc2003_send_event")
can you have a short look? maybe there is a simple way to complete the driver...
Regards,
Patrick
tsc2003.c
TranslateQuoteReplyEditDelete
2009-08-03 08:43:13 Re: I2C Driver in uClinux 2008R1.5
Robin Getz (UNITED STATES)
Message: 78306
Patrick:
No.
If you need help with tsc2003 - please contact the manufacture (which is not us).
If you want to switch to a supported touchscreen controller (ad7877 or ad7879) - we would be more than happy to support you.
-Robin
QuoteReplyEditDelete
2009-08-03 10:00:44 Re: I2C Driver in uClinux 2008R1.5
Patrick Hotz (GERMANY)
Message: 78312
Robin:
there is no problem with the tsc-chip directly. The problem is how to send the values to the input-device which is only kernel-software.
I have seen that there are much similarities with the 7877 or 7879.....
What i want to know is why the input-device is not accepting the values i sent with "input_report_abs" followed by "input_sync"....
Now let me show the function:
(this function is likely the same as in ad7877.c function "ad7877_rx")
static void touch_send_event(void *tsc)
{
struct touch*ts = tsc;
struct input_dev *input = ts->input;
int rt;
int x, y, z1, z2;
x = ts->x;
y = ts->y;
z1 = ts->z1;
z2 = ts->z2;
/* range filtering */
if (x == MAX_12BIT)
{
x = 0;
}
if (likely(x && z1))
{
/* compute touch pressure resistance using equation #1 */
rt = z2;
rt -= z1;
rt *= x;
rt *= X_PLATE_OHMS; // is 1000
rt /= z1;
rt = (rt + 2047) >> 12;
}
else
{
rt = 0;
}
if(rt)
{
input_report_abs(input, ABS_X, x);
input_report_abs(input, ABS_Y, y);
input_report_abs(input, ABS_PRESSURE, rt);
input_sync(input);
}
}
The values i get are following:
x => from 80 to 3960
y => from 50 tp 3980
z1 => from 5 to 3940
z2 => from 8 to 3910
Now i run "event_test /dev/input/event0":
Supported events:
Event type 0 (Reset)
Event code 0 (Reset)
Event code 1 (Key)
Event code 3 (Absolute)
Event type 1 (Key)
Event code 330 (Touch)
Event type 3 (Absolute)
Event code 0 (X)
Value 3869
Min 0
Max 4095
Event code 1 (Y)
Value 1856
Min 0
Max 4095
Event code 24 (Pressure)
Value -182
Min 0
Max 4095
Testing ... (interrupt to exit)
Event: time 1249314627.384328, type 3 (Absolute), code 0 (X), value 2570
Event: time 1249314627.384361, type 3 (Absolute), code 1 (Y), value 1215
Event: time 1249314627.384380, type 3 (Absolute), code 24 (Pressure), value -452
Event: time 1249314627.384399, type 0 (Reset), code 0 (Reset), value 0
Event: time 1249314627.394622, type 3 (Absolute), code 0 (X), value 2575
Event: time 1249314627.394643, type 3 (Absolute), code 1 (Y), value 1208
Event: time 1249314627.394662, type 3 (Absolute), code 24 (Pressure), value -459
Event: time 1249314627.394681, type 0 (Reset), code 0 (Reset), value 0
Event: time 1249314627.405057, type 3 (Absolute), code 0 (X), value 2559
Event: time 1249314627.405079, type 3 (Absolute), code 1 (Y), value 1159
Event: time 1249314627.405099, type 3 (Absolute), code 24 (Pressure), value 376
Event: time 1249314627.405118, type 0 (Reset), code 0 (Reset), value 0
Event: time 1249314627.415379, type 3 (Absolute), code 1 (Y), value 1142
Event: time 1249314627.415401, type 3 (Absolute), code 24 (Pressure), value 329
Event: time 1249314627.415420, type 0 (Reset), code 0 (Reset), value 0
Event: time 1249314627.426097, type 3 (Absolute), code 0 (X), value 2551
Event: time 1249314627.426119, type 3 (Absolute), code 1 (Y), value 1146
Event: time 1249314627.426139, type 3 (Absolute), code 24 (Pressure), value 363
Event: time 1249314627.426157, type 0 (Reset), code 0 (Reset), value 0
Event: time 1249314627.436442, type 3 (Absolute), code 0 (X), value 2541
Event: time 1249314627.436464, type 3 (Absolute), code 1 (Y), value 1121
Event: time 1249314627.436483, type 3 (Absolute), code 24 (Pressure), value 374
This values are looking ok for me, so i want to calibrate the touch in the next step...
I follow the instructions from here " docs.blackfin.uclinux.org/doku.php?id=linux-kernel:drivers:ad7879&s[]=touchscreen" under "Touchscreen calibration"
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_CONSOLEDEVICE=none
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_CALIBFILE=/etc/pointercl
export TSLIB_TSDEVICE=/dev/input/event0
ts_calibrate
xres = 800, yres = 480
nothing happens if i touch..........
therefore i think this has nothing to do with the chip..... this must be a linux-kernel problem....
Patrick
TranslateQuoteReplyEditDelete
2009-08-03 10:21:52 Re: I2C Driver in uClinux 2008R1.5
Michael Hennerich (GERMANY)
Message: 78314 You need to report
input_report_abs(input, ABS_PRESSURE, 0);
as well
This is typically done upon PEN_UP
-Michael
QuoteReplyEditDelete
2009-08-03 13:05:19 Re: I2C Driver in uClinux 2008R1.5
Robin Getz (UNITED STATES)
Message: 78317
Patrick:
Like I have said - our example works - the ad7877 & the ad7879. We and other have validated them on numerous hardware platforms. If you deviate from our recommended hardware - we may not be able to provide the support you are looking for (like reviewing drivers).
-Robin