LinuxQuestions.org
Did you know LQ has a Linux Hardware Compatibility List?
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Hardware > Linux - Embedded & Single-board computer
User Name
Password
Linux - Embedded & Single-board computer This forum is for the discussion of Linux on both embedded devices and single-board computers (such as the Raspberry Pi, BeagleBoard and PandaBoard). Discussions involving Arduino, plug computers and other micro-controller like devices are also welcome.

Notices

Reply
 
Search this Thread
Old 11-15-2010, 05:02 PM   #1
mj1856
LQ Newbie
 
Registered: Nov 2010
Posts: 6

Rep: Reputation: 0
How to reverse sda/scl pins in s3c2410 i2c drivers?


Hi. I'm working with a custom s3c2410 board, and I have an interesting delima. The company I work for had this board made a long time ago, and they based everything on the 2.4.18 kernel from the old Mizi Linux. I've been working with getting everything working on a standard 2.6 kernel. So far so good - I've had success in many areas, but I'm stuck on one major problem.

The original designers opted to not use the RTC internal to the s3c2410. Instead, they attached an s35390a to the i2c bus. The problem is that when they wired it up, they messed up and swapped the SDA and SCL lines. So when I try to load the driver, of course it can't find the device at all. I need a software solution - cutting the lines on the PCB and rewiring them is not an option, due to the vast quantity already produced.

Now the old 2.4 kernel appears to be working ok, but they did not use any standard driver. They hacked apart the rtc driver and put their own codes in. Not acceptable in my book. I should just be able to use the standard s35390a driver under 2.6. I haven't been able to follow their hacks well enough to figure out how they dealt with the swapped lines. Not sure if it would even help anyway.

So the question is, how do I tell the i2c bus that I have a device with swapped pins? It is the only device on the bus, so I'm ok swapping the i2c pins themselves.

I found in /arch/arm/plat/s3c24xx/setup-i2c.c where the default gpios are configured for the i2c bus:

void s3c_i2c0_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPE15_IICSDA);
s3c_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPE14_IICSCL);
}

I tried changing them such as:

void s3c_i2c0_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPE15_IICSDA);
s3c_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPE14_IICSCL);
}

But that doesn't seem to help at all. I just get the following in my startup dmesg either way:

rtc-s35390a 0-0030: error resetting chip
rtc-s35390a: probe of 0-0030 failed with error -5
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)

I have the board config all set to go for the standard s35390a driver, I just can't figure out how to swap the lines.

Any help is greatly appreciated.

-Matt
 
Old 11-16-2010, 05:57 AM   #2
petaflot
LQ Newbie
 
Registered: Jun 2010
Posts: 9

Rep: Reputation: 0
what you did makes sense.

you might want to try to swap the pins the hardware way JUST FOR ONE BOARD, to make sure your driver works ok the way it's intended to do.

if that test is successful, check the datasheet of the s3c2410. can the pins really be assigned dynamically? if not, you're screwed. if yes, you missed something in the source.
 
Old 11-16-2010, 01:33 PM   #3
mj1856
LQ Newbie
 
Registered: Nov 2010
Posts: 6

Original Poster
Rep: Reputation: 0
Ok, based on your recomendation, I tried swapping the pins on my test board and leaving the i2c driver alone. It still doesn't work, so I think there is something else going on here with the s3c2410-i2c driver, or with my external rtc.

I've been using the i2ctools from the lmsensors project to help with testing. Specifically, i2cdetect and i2cdump.

The good news is that I get the same results from i2cdetect using either the software swap (as posted above), or the phsical hardware swap. So, I would guess that the software swap will indeed work once I figure the rest out.

The bad news is now that with the pins wrong, i2cdetect completes but shows no results. With the pins correct, i2cdetect hangs and immediately starts throwing this error repeatedly:

s3c-i2c s3c2410-i2c: cannot get bus (error -110)

Any ideas?

One other thing - the RTC chip is labeled S35390, but the only linux driver is for S35390A. I can't even find a datasheet on S35390, only the "A" model. I assume that the difference isn't important for my purposes, but who knows. At any rate, the driver doesn't even load because of the i2c problems, so I don't think it's important.

The only thing I could find on google about the error -100 is an old patch to openmoko - which basically implemented suspend/resume functions. I found that similar code is already implemented in the current 2.6.36 kernel I'm using, but it only invokes with CONFIG_PM enabled (power management). I re-build my kernel to enable CONFIG_PM and tried again, but got the same results.

Any other ideas?
Thanks,
Matt
 
Old 11-17-2010, 12:40 PM   #4
petaflot
LQ Newbie
 
Registered: Jun 2010
Posts: 9

Rep: Reputation: 0
do you have the hardware to see what's on the lines? an oscilloscope or a tool like http://dangerousprototypes.com/docs/Bus_Pirate would be needed, as well as good knowledge of what's supposed to happen.

if googleing the error code doesn't work, read the source (luke).

maybe your test board is broken. now you know the soft swapping works, try another board? maybe it helps.
 
Old 11-17-2010, 06:22 PM   #5
mj1856
LQ Newbie
 
Registered: Nov 2010
Posts: 6

Original Poster
Rep: Reputation: 0
No scope or bus pirate, but I do have a simple logic probe. Maybe I can figure out what's going on physically.

From the source, looks like that error is from my i2c bus driver and the error is a simple timeout trying to set the i2c bus to master mode.

Source: http://bit.ly/b7JlFt

I'm starting to wonder if the device is wired backwards because the cpu is hooked up backwards too, so really it's wired correctly. (two wrongs make a right in some countries...) So maybe it's not backwards at all and I'm just having driver issues.

Anyone know if the s35390 is a different animal than the s35390a? The only drivers I see anywhere are for the "a" model, so that's what I'm trying to use.

Either way, wouldn't i2cdetect find something out there even if I had the wrong driver?

I've been researching all I can about i2c and so far it looks like I'm doing it right, so I'm not sure what to try next.

Regards,
Matt
 
Old 11-17-2010, 06:31 PM   #6
mj1856
LQ Newbie
 
Registered: Nov 2010
Posts: 6

Original Poster
Rep: Reputation: 0
I suppose it would help if I posted the related sections of my machine config (from /arch/arm/mach-s3c2410/mach-myboard.c)

static struct i2c_board_info myboard_i2c_devs[] __initdata = {
{
I2C_BOARD_INFO("s35390a", 0x30),
},
};

static void __init myboard_machine_init(void)
{
...
i2c_register_board_info(0, myboard_i2c_devs, ARRAY_SIZE(myboard_i2c_devs));
...
}

-Matt
 
Old 11-18-2010, 02:44 PM   #7
mj1856
LQ Newbie
 
Registered: Nov 2010
Posts: 6

Original Poster
Rep: Reputation: 0
Solved

I did some testing and got it to work.

Basically, I disabled the i2c bus drivers and then used the /sys/class/gpio interface to toggle the pins while testing the output with a logic probe on the lines to my rtc. Using this method, I was able to confirm the pins were indeed swaped (SDA on GPE14 and SCL on GPE15). While this wasn't the key to the solution, I thought I would post this simple techinique in case others may find it useful.

What actually solved my problem was switching from the s3c-i2c driver to the generic i2c-gpio driver. I tried this on a whim without thinking much would come of it, but it worked! Maybe someone can shed light on why. I tried the same pin and delay settings in the s3c-i2c driver without success. No changes were necessary to the rtc configuration. Here is my device setup for the i2c-gpio driver:

static struct i2c_gpio_platform_data myboard_i2c_gpio_data = {
.sda_pin = S3C2410_GPE(14),
.scl_pin = S3C2410_GPE(15),
.udelay = 50, /* 10 kHz */
};

static struct platform_device myboard_i2c_gpio = {
.name = "i2c-gpio",
.id = 0,
.dev = {
.platform_data = &myboard_i2c_gpio_data,
},
};

Then it's just a matter of adding &myboard_i2c_gpio to the device list.

Any idea why the gpio-i2c driver worked but the s3c-i2c driver didn't?

Anyway, thanks for the help.
-Matt
 
Old 11-19-2010, 05:17 AM   #8
petaflot
LQ Newbie
 
Registered: Jun 2010
Posts: 9

Rep: Reputation: 0
thanks for the update. for your question, you might get an answer on the i2c kernel mailing list...

linux-i2c at vger.kernel.org
 
Old 11-23-2010, 12:15 AM   #9
l2y3n2
LQ Newbie
 
Registered: Oct 2009
Posts: 6

Rep: Reputation: 0
Quote:
Originally Posted by mj1856 View Post
void s3c_i2c0_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPE15_IICSDA);
s3c_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPE14_IICSCL);
}

I tried changing them such as:

void s3c_i2c0_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPE15_IICSDA);
s3c_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPE14_IICSCL);
}
-Matt
What you do here is simply configure the input/output status for GPIO GPE14 and GPE15 (Defined in arch/arm/mach-s3c2410/include/mach/regs-gpio.h), but the actual i2c output is controller by I2C Controller and would not invert SCL/SDA signals at all.

In fact you can't invert the two pins if you are using the hardware controller (it doesn't support it).

The only solution is to use gpio-base emulation as you did(it use the same pins but your data is sent/recv through i2c-bus by kernel, pulling up/down the two pins to emulate i2c output).

That way needs more cpu instructions but since your i2c is a rtc device, that's ok (it only reads once at boot-up and writes to at shut-down).
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
can i use I/o Port pins of a processor as four SPI pins? i sunr2007 Linux - Embedded & Single-board computer 3 08-20-2009 01:23 AM
[Drivers] probing I2C devices kamou Programming 0 03-13-2009 04:45 AM
Reverse engineering windows printer drivers hacker supreme Programming 4 02-04-2007 10:10 AM
LXer: Linux: Reverse Engineering Wireless Drivers LXer Syndicated Linux News 0 06-09-2006 09:33 AM
mount USB devices, sda, manually/statically assign sda? Oxyacetylene Debian 3 12-20-2004 02:45 PM


All times are GMT -5. The time now is 01:34 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration