Skip to contentSkip to conversation

U-boot-V2: Introduce I2C support for SDP3430

PATCH New Menon 5 participants 43 messages Jun 18, 2008 – Jun 25, 2008

Subsystems (8)
lore
Share & tools
lore

Menon

#0 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

Hi Sascha,

This series of patches introduce I2C support in U-Boot v2. This support is similar to the one in 2.6.26 rc5 kernel. i2ctools diagnostics introduced is based on http://www.lm-sensors.org/wiki/I2CTools

The benefit is that we can backport drivers present in linux kernel to u-boot v2 with very little effort.

In the case of OMAP, just the i2c-core and adapter driver comprises of around 6k size addition. Tools add up further.

The complete patch series is available here:
http://linux.omap.com/pub/patches/rfc/u-boot-v2/i2c-20080617/

This series contains the following patches:

[Patch 1/9] U-boot-V2:ID: Sync mod_devicetable [Patch 2/9] U-boot-V2:ARM: Introduce additional bitops [Patch 3/9] U-boot-V2:ID: Introduce idr [Patch 4/9] U-boot-V2:I2C: Introduce core [Patch 5/9] U-boot-V2:I2C:Algos: Introduce I2c Algos [Patch 6/9] U-boot-V2:Commands: Introduce i2c commands [Patch 7/9] U-boot-V2:ARM:OMAP: Introduce OMAP classes [Patch 8/9] U-boot-V2:I2C:Busses: Add I2c OMAP Adapter [Patch 9/9] U-boot-V2:Boards:SDP3430 enable i2c bus1

Regards,
Nishanth Menon

#1 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

Quoted 5 lines · Nishanth

Hi Sascha,

This series of patches introduce I2C support in U-Boot v2. This support is similar to the one in 2.6.26 rc5 kernel. i2ctools diagnostics introduced is based on http://www.lm-sensors.org/wiki/I2CTools

The benefit is that we can backport drivers present in linux kernel to u-boot v2 with very little effort.

Do we really want to bloat U-Boot with these huge Linux drivers? U-Boot already has I2C support that works pretty well. Your patchset is overkill, IMHO.

Signature · 2 lines
Timur Tabi
Linux kernel developer at Freescale
#2 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

Timur,

Quoted 10 lines

-----Original Message-----
From: Timur Tabi [mailto:timur at freescale.com]
Sent: Wednesday, June 18, 2008 9:55 AM
To: Menon, Nishanth
Cc: Sascha Hauer; Laurent Desnogues; Kamat, Nishant; philip.balister at gmail.com; u-boot- users at lists.sourceforge.net
Subject: Re: [U-Boot-Users] [Patch 0/9] U-boot-V2: Introduce I2C support for SDP3430

Do we really want to bloat U-Boot with these huge Linux drivers? U-Boot already has I2C support that works pretty well. Your patchset is overkill, IMHO.

Please see U-boot v2 here: http://www.denx.de/cgi-bin/gitweb.cgi?p=u-boot/u-boot-v2.git;a=tree;f=drivers;h=2b524fc7692e5ee0b99843df17a911dd54c84e73;hb=78c2fde77a953351aac8d7e92336eb37b64c0985

It does not have i2c support. And IMHO, using kernel like i2c addition in U-Boot v2 is appropriate. Why this is not a bloat U-Boot v2?
A) Now, if you just want i2c_transfer without any device interface, you don't need to compile in the CHARDEV.
B) Since we use a different linking strategy in U-Boot-v2 which uses gcc link stage to decide which functions be retained and which not, it is pretty neat to see all unused functionality disappear.
C) kernel has additional bus and class types which are useful when we think in terms of varied features, in u-boot v2, we don't have a bus and class, just a plain device+driver interface like the kernel + ioctls to allow "apps" to invoke functionality within the driver for the device. Very linux like, call it a micro-linux ;). So kernel i2c architecture fits u_boot v2 better that u-boot v1's architecture.
D) U-boot v2 has insmod + rmmod -> though this is still to be fixed, once it is fully functioning, you can loadb just the module feature you need. In fact, you could even have a filesystem with just modules....
E) Ofcourse, we work in a single threaded, no interrupt mode in u-boot v2+ don't care for any power management -> more savings there

Now, lets look at how much does it add? As I mentioned, having a flexible i2c architecture adds as little as 6K (including using i2c_transfer, having i2c-core and omap i2c adapter). I do not honestly feel that it is a bloat.

Regards,
Nishanth Menon

#3 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

Quoted 9 lines · Nishanth

Timur,

Quoted 8 lines

-----Original Message-----
From: Timur Tabi [mailto:timur at freescale.com]
Sent: Wednesday, June 18, 2008 9:55 AM
To: Menon, Nishanth
Cc: Sascha Hauer; Laurent Desnogues; Kamat, Nishant; philip.balister at gmail.com; u-boot- users at lists.sourceforge.net
Subject: Re: [U-Boot-Users] [Patch 0/9] U-boot-V2: Introduce I2C support for SDP3430

Quoted 7 lines
Quoted 2 lines

Do we really want to bloat U-Boot with these huge Linux drivers? U-Boot already has I2C support that works pretty well. Your patchset is overkill, IMHO.

Please see U-boot v2 here: http://www.denx.de/cgi-bin/gitweb.cgi?p=u-boot/u-boot-v2.git;a=tree;f=drivers;h=2b524fc7692e5ee0b99843df17a911dd54c84e73;hb=78c2fde77a953351aac8d7e92336eb37b64c0985

It does not have i2c support. And IMHO, using kernel like i2c addition in U-Boot v2 is appropriate. Why this is not a bloat U-Boot v2?
A) Now, if you just want i2c_transfer without any device interface, you don't need to compile in the CHARDEV.
B) Since we use a different linking strategy in U-Boot-v2 which uses gcc link stage to decide which functions be retained and which not, it is pretty neat to see all unused functionality disappear.

Note that this is only true when modules are disabled. Once modules are enabled, every function marked with EXPORT_MODULE gets linked in as you don't know which functions will be needed later. So please check your build with modules enabled.

Sascha

Signature · 4 lines
Pengutronix e.K. - Linux Solutions for Science and Industry
-----------------------------------------------------------
Kontakt-Informationen finden Sie im Header dieser Mail oder
auf der Webseite -> http://www.pengutronix.de/impressum/ <-
#4 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

Sascha,

Quoted 7 lines

-----Original Message-----
From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
Sent: Wednesday, June 18, 2008 10:28 AM
To: Menon, Nishanth
Cc: Timur Tabi; Laurent Desnogues; Kamat, Nishant; philip.balister at gmail.com; u-boot- users at lists.sourceforge.net
Subject: Re: [U-Boot-Users] [Patch 0/9] U-boot-V2: Introduce I2C support for SDP3430

Quoted 7 lines
Quoted 1 line

B) Since we use a different linking strategy in U-Boot-v2 which uses gcc link stage to decide which

functions be retained and which not, it is pretty neat to see all unused functionality disappear.

Note that this is only true when modules are disabled. Once modules are enabled, every function marked with EXPORT_MODULE gets linked in as you don't know which functions will be needed later. So please check your build with modules enabled.

True, in fact it will hit everything in the system. But with the same argument, the i2c module itself could then be made a module. That will help on size as required. Most default boot configuration of u-boot might probably prefer to keep things limited to not having modules and keeping size, in which case, this point might help.

Regards,
Nishanth Menon

#5 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

In reply to Menon
Quoted 1 line · Nishanth

Please see U-boot v2 here:

Sorry, I didn't notice that your patch is for U-Boot V2.

Quoted 1 line

It does not have i2c support. And IMHO, using kernel like i2c addition in U-Boot v2 is appropriate. Why this is not a bloat U-Boot v2?

If it isn't, then it means that U-Boot V2 will be pretty bloated in general.

Quoted 5 lines

A) Now, if you just want i2c_transfer without any device interface, you don't need to compile in the CHARDEV.
B) Since we use a different linking strategy in U-Boot-v2 which uses gcc link stage to decide which functions be retained and which not, it is pretty neat to see all unused functionality disappear.
C) kernel has additional bus and class types which are useful when we think in terms of varied features, in u-boot v2, we don't have a bus and class, just a plain device+driver interface like the kernel + ioctls to allow "apps" to invoke functionality within the driver for the device. Very linux like, call it a micro-linux ;). So kernel i2c architecture fits u_boot v2 better that u-boot v1's architecture.
D) U-boot v2 has insmod + rmmod -> though this is still to be fixed, once it is fully functioning, you can loadb just the module feature you need. In fact, you could even have a filesystem with just modules....
E) Ofcourse, we work in a single threaded, no interrupt mode in u-boot v2+ don't care for any power management -> more savings there

Sounds to me like U-Boot V2 is just a repacked Linux kernel. We could probably save ourselves a lot of trouble if we just took the DDR and CPU register initialization code in U-Boot and moved it to the kernel.

Signature · 2 lines
Timur Tabi
Linux kernel developer at Freescale
#6 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

Timur,

Quoted 9 lines

-----Original Message-----
From: Timur Tabi [mailto:timur at freescale.com]
Sent: Wednesday, June 18, 2008 10:40 AM
To: Menon, Nishanth
Cc: Sascha Hauer; Laurent Desnogues; Kamat, Nishant; philip.balister at gmail.com; u-boot- users at lists.sourceforge.net
Subject: Re: [U-Boot-Users] [Patch 0/9] U-boot-V2: Introduce I2C support for SDP3430

Sounds to me like U-Boot V2 is just a repacked Linux kernel.

Lol... not entirely true.. I'd say it is inspired by Linux kernel. In fact lots of stuff we have in kernel which are not required in a boot support scenario has been pared down.. we don't have multiple schedulers, process et.al. IMHO, u-boot v2 is neat, it will need lot of our effort is making it better :). A call for more folks to pitch in? ;)

I have a boot loader which does basic stuff and a usable prompt in around 30 something K. which kind of neat in itself.

Quoted 3 lines

We could probably
save ourselves a lot of trouble if we just took the DDR and CPU register initialization code in U-Boot and moved it to the kernel.

This may not be possible in all configurations. Where possible, platforms can choose to do it - yes - I would probably not need to do camera configurations in u-boot on my SOC - I will push it off to kernel. I might however need to talk i2c to my USB transceiver here to do USBTTY or USBNET. Doing cpu and clock inits may not be enough in u-boot in that case.

Regards,
Nishanth Menon

#7 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

In reply to Timur Tabi
Quoted 16 lines · Timur Tabi
Quoted 1 line · Nishanth

Please see U-boot v2 here:

Sorry, I didn't notice that your patch is for U-Boot V2.

Quoted 1 line

It does not have i2c support. And IMHO, using kernel like i2c addition in U-Boot v2 is appropriate. Why this is not a bloat U-Boot v2?

If it isn't, then it means that U-Boot V2 will be pretty bloated in general.

Quoted 5 lines

A) Now, if you just want i2c_transfer without any device interface, you don't need to compile in the CHARDEV.
B) Since we use a different linking strategy in U-Boot-v2 which uses gcc link stage to decide which functions be retained and which not, it is pretty neat to see all unused functionality disappear.
C) kernel has additional bus and class types which are useful when we think in terms of varied features, in u-boot v2, we don't have a bus and class, just a plain device+driver interface like the kernel + ioctls to allow "apps" to invoke functionality within the driver for the device. Very linux like, call it a micro-linux ;). So kernel i2c architecture fits u_boot v2 better that u-boot v1's architecture.
D) U-boot v2 has insmod + rmmod -> though this is still to be fixed, once it is fully functioning, you can loadb just the module feature you need. In fact, you could even have a filesystem with just modules....
E) Ofcourse, we work in a single threaded, no interrupt mode in u-boot v2+ don't care for any power management -> more savings there

Quoted 3 lines

Sounds to me like U-Boot V2 is just a repacked Linux kernel. We could probably save ourselves a lot of trouble if we just took the DDR and CPU register initialization code in U-Boot and moved it to the kernel.

I've thought about going this way...
But the Linux Kernel typically has around 1M and still you don't have a shell. U-Boot-v2 is not bigger in code size than V1 with similar functionality.
You're right, I took a lot of code (and ideas) from the Linux Kernel, but I'm too unsure if it's a good idea to adopt full-featured frameworks like I2C from the kernel. BTW U-Boot-v1 does the same thing with NAND support for example.

Sascha

Signature · 4 lines
Pengutronix e.K. - Linux Solutions for Science and Industry
-----------------------------------------------------------
Kontakt-Informationen finden Sie im Header dieser Mail oder
auf der Webseite -> http://www.pengutronix.de/impressum/ <-
#8 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

Sascha,

Quoted 11 lines

-----Original Message-----
From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
Sent: Wednesday, June 18, 2008 10:58 AM
To: Timur Tabi
Cc: Menon, Nishanth; Laurent Desnogues; Kamat, Nishant; philip.balister at gmail.com; u-boot- users at lists.sourceforge.net
Subject: Re: [U-Boot-Users] [Patch 0/9] U-boot-V2: Introduce I2C support for SDP3430

but I'm too unsure if it's a good idea to adopt full-featured frameworks like I2C from the kernel. BTW U-Boot-v1 does the same thing with NAND support for example.

Hmm... flexibility Vs size.. the age old argument ;). When I started considering i2c I pulled code from U-Boot v1 and started putting in u-boot v2, then realized I was barking up the wrong tree. I then realized that probably it is better to pull in the linux i2c arch in to u-boot v2 and add flags to enable/disable features to control the size. Having a Kconfig does help a ton. The "new style" drivers were perfect to fit into u-boot-v2 architecture + I get to enable folks who already have linux drivers to pull it down to u-boot v2 with very little effort. The learning curve is smaller, infact, almost non-existant.

I think the best choice is selective addition as the need arises. We may not need V4L2 and similar things.. Where we can make compatibility happen, that would be good IMHO. We can then proceed with customizing and improving it to our needs. Why reinvent the wheel?

Regards,
Nishanth Menon

#9 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

Quoted 1 line · Nishanth

Hmm... flexibility Vs size.. the age old argument ;).

Well, the code we have in u2 today has shown that you can get both, if done carefully :)

Quoted 9 lines

When I started considering i2c I pulled code from U-Boot v1 and started putting in u-boot v2, then realized I was barking up the wrong tree. I then realized that probably it is better to pull in the linux i2c arch in to u-boot v2 and add flags to enable/disable features to control the size. Having a Kconfig does help a ton. The "new style" drivers were perfect to fit into u-boot-v2 architecture + I get to enable folks who already have linux drivers to pull it down to u-boot v2 with very little effort. The learning curve is smaller, infact, almost non-existant.

Right; nevertheless, don't forget that this is a bootloader, and our aim is to have a codebase which is as clear as possible right from the beginning.

Quoted 4 lines

I think the best choice is selective addition as the need arises. We may not need V4L2 and similar things.. Where we can make compatibility happen, that would be good IMHO. We can then proceed with customizing and improving it to our needs. Why reinvent the wheel?

We might need a wheel with slightly different requirements :-)

So I suppose the right way to proceed is:

- let's first define use cases for what you want to achieve with the i2c support in u-boot-v2

- let's have a look at how it would integrate into the device/driver model and how the user-visible API would look like

- write a small framework for i2c, with host+algo+device parts, heavily inspired by the best of Linux and the best of u-boot/u-boot-v2.

That worked out very well for the features we currently have in u2.

Robert

Signature · 5 lines
 Dipl.-Ing. Robert Schwebel | http://www.pengutronix.de
 Pengutronix - Linux Solutions for Science and Industry
   Handelsregister:  Amtsgericht Hildesheim, HRA 2686
     Hannoversche Str. 2, 31134 Hildesheim, Germany
   Phone: +49-5121-206917-0 |  Fax: +49-5121-206917-9
#10 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

Robert,

Quoted 13 lines

-----Original Message-----
From: Robert Schwebel [mailto:r.schwebel at pengutronix.de]
Sent: Wednesday, June 18, 2008 1:38 PM
To: Menon, Nishanth
Cc: Sascha Hauer; Timur Tabi; Laurent Desnogues; Kamat, Nishant; philip.balister at gmail.com; u-boot- users at lists.sourceforge.net
Subject: Re: [U-Boot-Users] [Patch 0/9] U-boot-V2: Introduce I2C support for SDP3430

So I suppose the right way to proceed is:

- let's first define use cases for what you want to achieve with the i2c support in u-boot-v2

Quoted 7 lines

- let's have a look at how it would integrate into the device/driver model and how the user-visible API would look like

- write a small framework for i2c, with host+algo+device parts, heavily inspired by the best of Linux and the best of u-boot/u-boot-v2.

That worked out very well for the features we currently have in u2.

What issues do you see with the proposed patch set I have send out - other than it bases itself on Linux kernel? It meets the following requirements:
a) does meet all the use cases folks need with i2c:
i) bare bone i2c arch -> don't use client drivers, just stick around with adapter and use i2c_transfer or smbus ops which ever you'd like. ii) someone wants to write a client for a commonly used device ->eeprom or the like.. feel free to do so.
iii) does it support multiple buses? Oh yeah it does. So does it support multiples speed busses too.
b) does it fit in device-driver model? Yep it does.
c) Is it small? I don't see 6K a big overhead considering similar addition due to devfs or nand support.. in fact my adapter driver could be eating a chunk of that 6K.

Regards,
Nishanth Menon

#11 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

Hi,

Quoted 2 lines · Nishanth

What issues do you see with the proposed patch set I have send out - other than it bases itself on Linux kernel?

I've commented your first patch in the series; in short:

- It shows nicely that it is easy to copy things over from Linux - that's a good sign that we didn't do too many things the wrong way. But note, it is *not* the main intention of u-boot-v2 to be a Linux clone. It is a bootloader, and it tries to be one with a neat design, combining the best of POSIX, Linux and U-Boot-v1. Copying *ideas* is good, but let's do it in a way that it still is u-boot.

- Please don't bring in things which are not part of the current code base. If you add code for subsystems, the subsystems must be there first and *then* their users. Otherwhise we bloat the codebase and we disable the possibility to add *real* support for PCI, USB and S390 later :-)

Quoted 10 lines

It meets the following requirements:

a) does meet all the use cases folks need with i2c:

i) bare bone i2c arch -> don't use client drivers, just stick around with adapter and use i2c_transfer or smbus ops which ever you'd like.

ii) someone wants to write a client for a commonly used device ->eeprom or the like.. feel free to do so.

No problem with that.

Quoted 2 lines

iii) does it support multiple buses? Oh yeah it does. So does it support multiples speed busses too.

That's also a requirement.

Quoted 1 line

b) does it fit in device-driver model? Yep it does.

Sure.

Quoted 3 lines

c) Is it small? I don't see 6K a big overhead considering similar addition due to devfs or nand support.. in fact my adapter driver could be eating a chunk of that 6K.

See above. Check how Sascha's code for console, serial or clocksource looks like. It really *looks* like Linux from the outside, but it is much, much smaller and better aligned for bootloader use.

Back to my proposal:

Quoted 10 lines
Quoted 10 lines

So I suppose the right way to proceed is:

- let's first define use cases for what you want to achieve with the i2c support in u-boot-v2

- let's have a look at how it would integrate into the device/driver model and how the user-visible API would look like

- write a small framework for i2c, with host+algo+device parts, heavily inspired by the best of Linux and the best of u-boot/u-boot-v2.

Which part of i2c do we actually *need* in the bootloader? What's *your* use case?

I assume we need i2c host controllers, that's quite clear. We also need an abstraction for i2c devices. The only devices I have seen which really needed a bootloader driver are

a) eeproms
b) RTCs
c) analog/digital in/outputs (i.e. gpio expanders)

Other use cases?

Robert

Signature · 5 lines
 Dipl.-Ing. Robert Schwebel | http://www.pengutronix.de
 Pengutronix - Linux Solutions for Science and Industry
   Handelsregister:  Amtsgericht Hildesheim, HRA 2686
     Hannoversche Str. 2, 31134 Hildesheim, Germany
   Phone: +49-5121-206917-0 |  Fax: +49-5121-206917-9
#12 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

Robert,

Quoted 17 lines

-----Original Message-----
From: Robert Schwebel [mailto:r.schwebel at pengutronix.de]
Sent: Wednesday, June 18, 2008 2:12 PM
To: Menon, Nishanth
Cc: Robert Schwebel; Sascha Hauer; Timur Tabi; Laurent Desnogues; Kamat, Nishant; philip.balister at gmail.com; u-boot-users at lists.sourceforge.net
Subject: Re: [U-Boot-Users] [Patch 0/9] U-boot-V2: Introduce I2C support for SDP3430

I've commented your first patch in the series; in short:

- It shows nicely that it is easy to copy things over from Linux - that's a good sign that we didn't do too many things the wrong way. But note, it is *not* the main intention of u-boot-v2 to be a Linux clone. It is a bootloader, and it tries to be one with a neat design, combining the best of POSIX, Linux and U-Boot-v1. Copying *ideas* is good, but let's do it in a way that it still is u-boot.

Quoted 5 lines

- Please don't bring in things which are not part of the current code base. If you add code for subsystems, the subsystems must be there first and *then* their users. Otherwhise we bloat the codebase and we disable the possibility to add *real* support for PCI, USB and S390 later :-)

Acked. Yep will redo that :).

Quoted 2 lines

Which part of i2c do we actually *need* in the bootloader? What's *your* use case?

I need i2c_transfer -yes - I can customize the changes just for that. I do like i2c_transfers, adapters, clients etc.. my immediate need is rather simple -> i2c_transfers.

Quoted 10 lines

I assume we need i2c host controllers, that's quite clear. We also need an abstraction for i2c devices. The only devices I have seen which really needed a bootloader driver are

a) eeproms
b) RTCs
c) analog/digital in/outputs (i.e. gpio expanders)

Other use cases?

USB Transceivers, power management devices.

Do we need SMBUS support? I don't. probably algos would be a good idea for other SOCs.

Are we ok with i2ctools movement here?

Regards,
Nishanth Menon

#13 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

Quoted 7 lines · Nishanth
Quoted 5 lines

- Please don't bring in things which are not part of the current code base. If you add code for subsystems, the subsystems must be there first and *then* their users. Otherwhise we bloat the codebase and we disable the possibility to add *real* support for PCI, USB and S390 later :-)

Acked. Yep will redo that :).

Yea, looking forward especially for PCI patches :-)

Quoted 6 lines
Quoted 2 lines

Which part of i2c do we actually *need* in the bootloader? What's *your* use case?

I need i2c_transfer -yes - I can customize the changes just for that. I do like i2c_transfers, adapters, clients etc.. my immediate need is rather simple -> i2c_transfers.

Ok, so let's start with that.

Quoted 11 lines
Quoted 9 lines

I assume we need i2c host controllers, that's quite clear. We also need an abstraction for i2c devices. The only devices I have seen which really needed a bootloader driver are

a) eeproms
b) RTCs
c) analog/digital in/outputs (i.e. gpio expanders)

Other use cases?

USB Transceivers, power management devices.

Yes, but I think what we most of all need is the i2c communication with the device. We should think about if the abstraction of the devices *behind* the bus brings us anything; note that you can do lots of things in scripts in u-boot-v2. Linke writing a shell function for your usb transceivers which just encapsulates the right predefined i2c_read/write operations.

Quoted 1 line

Are we ok with i2ctools movement here?

Hmm? How do you mean that?

rsc

Signature · 5 lines
 Dipl.-Ing. Robert Schwebel | http://www.pengutronix.de
 Pengutronix - Linux Solutions for Science and Industry
   Handelsregister:  Amtsgericht Hildesheim, HRA 2686
     Hannoversche Str. 2, 31134 Hildesheim, Germany
   Phone: +49-5121-206917-0 |  Fax: +49-5121-206917-9
#14 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

Robert,

Quoted 9 lines

-----Original Message-----
From: Robert Schwebel [mailto:r.schwebel at pengutronix.de]
Sent: Wednesday, June 18, 2008 3:44 PM
To: Menon, Nishanth
Cc: Sascha Hauer; Timur Tabi; Laurent Desnogues; Kamat, Nishant; philip.balister at gmail.com; u-boot- users at lists.sourceforge.net
Subject: Re: [U-Boot-Users] [Patch 0/9] U-boot-V2: Introduce I2C support for SDP3430

Yea, looking forward especially for PCI patches :-)

;) not in my immediate future at least :D

Quoted 10 lines

Yes, but I think what we most of all need is the i2c communication with the device. We should think about if the abstraction of the devices *behind* the bus brings us anything; note that you can do lots of things in scripts in u-boot-v2. Linke writing a shell function for your usb transceivers which just encapsulates the right predefined i2c_read/write operations.

Quoted 1 line

Are we ok with i2ctools movement here?

Hmm? How do you mean that?

I2cdetect, i2cget, i2cset, i2cdump -> see patch 6. They are handy little tools for debug. I2cdev will be required to provide a device interface.

Regards,
Nishanth Menon

#15 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

In reply to Robert Schwebel

Hi Folks,
This is the series of redo for the I2C related patches. This series contains the following:

[Patch 1/9]U-boot-V2:ID: Add i2c_device_id [Patch 2/9]U-boot-V2:ID: Introduce idr [Patch 3/9]U-boot-V2:I2C: Introduce core [Patch 4/9]U-boot-V2:I2C: Introduce i2c-dev [Patch 5/9]U-boot-V2:cmd: add I2C commands [Patch 6/9]U-boot-V2:cmd: I2C commands support [Patch 7/9]U-boot-V2:ARM:OMAP: OMAP classes [Patch 8/9]U-boot-V2:I2C:Busses: OMAP I2C Adapter [Patch 9/9]U-boot-V2:Boards:SDP3430 I2C bus1

This series depends on the bitops and __KERNEL__ cleanup patches send earlier today. As discussed, These patches add only I2C, SMBUS and other features are to be added at a later point of time.

Regards,
Nishanth Menon

#16 lore raw

PATCH 1/9 U-boot-V2:ID: Add i2c_device_id

In reply to Robert Schwebel

Introduce device_id for I2C. This will allow for
clients to register at a later stage with
multiple IDs. Currently introduced for i2c-dev's
generic client support

---
 include/linux/mod_devicetable.h |   25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
include/linux/mod_devicetable.h 2008-06-19 08:39:34.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +25 -0
Index: u-boot-v2.git/include/linux/mod_devicetable.h
===================================================================
@@ -0,0 +1,25 @@
+/*
+ * Device tables which are exported via
+ * scripts/mod/file2alias.c.  You must keep that file in sync with this
+ * header.
+ */
+
+#ifndef LINUX_MOD_DEVICETABLE_H
+#define LINUX_MOD_DEVICETABLE_H
+
+#ifdef __U_BOOT__
+#include <linux/types.h>
+typedef unsigned long kernel_ulong_t;
+#endif
+
+#define I2C_NAME_SIZE  20
+#define I2C_MODULE_PREFIX "i2c:"
+
+struct i2c_device_id {
+       char name[I2C_NAME_SIZE];
+       kernel_ulong_t driver_data      /* Data private to the driver */
+                       __attribute__((aligned(sizeof(kernel_ulong_t))));
+};
+
+
+#endif /* LINUX_MOD_DEVICETABLE_H */
#17 lore raw

PATCH 2/9 U-boot-V2:ID: Introduce idr

In reply to Robert Schwebel

Introduce selected ID table translation functions
from Linux kernel.

---
 include/linux/idr.h |   91 ++++++++++++
 lib/Makefile        |    1
 lib/idr.c           |  392 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 484 insertions(+)
include/linux/idr.h 2008-06-19 08:41:21.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +91 -0
Index: u-boot-v2.git/include/linux/idr.h
===================================================================
@@ -0,0 +1,91 @@
+/**
+ * @file
+ * @brief Small id to pointer translation service avoiding fixed sized
+ * tables.
+ *
+ * FileName: include/linux/idr.h
+ *
+ */
+/* Originally from Linux kernel. Ported to U-boot-v2.
+ * (C) Copyright 2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <[email protected]>
+ */
+/*
+ *
+ * 2002-10-18  written by Jim Houston jim.houston at ccur.com
+ *     Copyright (C) 2002 by Concurrent Computer Corporation
+ *     Distributed under the GNU GPL license version 2.
+ */
+
+#ifndef __IDR_H__
+#define __IDR_H__
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <init.h>
+
+#if BITS_PER_LONG == 32
+# define IDR_BITS 5
+# define IDR_FULL 0xfffffffful
+/** We can only use two of the bits in the top level because there is
+   only one possible bit in the top level (5 bits * 7 levels = 35
+   bits, but you only use 31 bits in the id). */
+# define TOP_LEVEL_FULL (IDR_FULL >> 30)
+#elif BITS_PER_LONG == 64
+# define IDR_BITS 6
+# define IDR_FULL 0xfffffffffffffffful
+/** We can only use two of the bits in the top level because there is
+   only one possible bit in the top level (6 bits * 6 levels = 36
+   bits, but you only use 31 bits in the id). */
+# define TOP_LEVEL_FULL (IDR_FULL >> 62)
+#else
+# error "BITS_PER_LONG is not 32 or 64"
+#endif
+
+#define IDR_SIZE (1 << IDR_BITS)
+#define IDR_MASK ((1 << IDR_BITS)-1)
+
+#define MAX_ID_SHIFT (sizeof(int)*8 - 1)
+#define MAX_ID_BIT (1U << MAX_ID_SHIFT)
+#define MAX_ID_MASK (MAX_ID_BIT - 1)
+
+/** Leave the possibility of an incomplete final layer */
+#define MAX_LEVEL ((MAX_ID_SHIFT + IDR_BITS - 1) / IDR_BITS)
+
+/** Number of id_layer structs to leave in free list */
+#define IDR_FREE_MAX (MAX_LEVEL + MAX_LEVEL)
+
+struct idr_layer {
+       unsigned long            bitmap; /** A zero bit means "space here" */
+       struct idr_layer        *ary[1 << IDR_BITS];
+       int                      count;  /** When zero, we can release it */
+};
+
+struct idr {
+       struct idr_layer *top;
+       struct idr_layer *id_free;
+       int               layers;
+       int               id_free_cnt;
+};
+
+#define IDR_INIT(name)                                         \
+{                                                              \
+       .top            = NULL,                                 \
+       .id_free        = NULL,                                 \
+       .layers         = 0,                                    \
+       .id_free_cnt    = 0,                                    \
+}
+#define DEFINE_IDR(name)       struct idr name = IDR_INIT(name)
+
+/**
+ * This is what we export.
+ */
+
+void *idr_find(struct idr *idp, int id);
+int idr_pre_get(struct idr *idp);
+int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
+void idr_remove(struct idr *idp, int id);
+void idr_init(struct idr *idp);
+
+#endif /* __IDR_H__ */
lib/idr.c 2008-06-19 08:42:27.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +392 -0

392 lines not on this page · raw message

lib/Makefile 2008-06-19 08:40:15.000000000 -0500 renamed from lib/Makefile 2008-06-19 08:40:01.000000000 -0500 +1 -0
Index: u-boot-v2.git/lib/Makefile
===================================================================
@@ -16,6 +16,7 @@
 obj-y                  += stringlist.o
 obj-y                  += recursive_action.o
 obj-y                  += make_directory.o
+obj-y                  += idr.o
 obj-$(CONFIG_BZLIB)    += bzlib.o bzlib_crctable.o bzlib_decompress.o bzlib_huffman.o bzlib_randtable.o
 obj-$(CONFIG_ZLIB)     += zlib.o gunzip.o
 obj-$(CONFIG_CRC32)    += crc32.o
#18 lore raw

PATCH 3/9 U-boot-V2:I2C: Introduce core

In reply to Robert Schwebel

First part of this patch introduces i2c-core. The codebase is sourced from 2.6.25 rc5 kernel contains ONLY i2c support. SMBUS is to be added on a need basis

---
 drivers/Kconfig             |    1
 drivers/Makefile            |    1
 drivers/i2c/Kconfig         |   39 ++++
 drivers/i2c/Makefile        |   10 +
 drivers/i2c/busses/Kconfig  |    7
 drivers/i2c/busses/Makefile |    9 +
 drivers/i2c/i2c-core.c      |  387 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/i2c-core.h      |   37 ++++
 include/driver.h            |    4
 include/linux/i2c.h         |  299 +++++++++++++++++++++++++++++++++
 10 files changed, 793 insertions(+), 1 deletion(-)
drivers/i2c/i2c-core.c 2008-06-19 08:42:46.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +387 -0
Index: u-boot-v2.git/drivers/i2c/i2c-core.c
===================================================================
@@ -0,0 +1,387 @@
+/**
+ * @file
+ * @brief a device driver for the iic-bus interface
+ *
+ * FileName: drivers/i2c/i2c-core.c
+ *
+ */
+/* Originally from Linux kernel. Ported to U-boot-v2.
+ * (C) Copyright 2006-2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <[email protected]>
+ */
+/* ------------------------------------------------------------------------- */
+/*   Copyright (C) 1995-99 Simon G. Vogl
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
+/* ------------------------------------------------------------------------- */
+
+/* With some changes from Ky??sti M?$lkki <[email protected]>.
+   All SMBus-related things are written by Frodo Looijaard <[email protected]>
+   SMBus 2.0 support by Mark Studebaker <[email protected]> and
+   Jean Delvare <[email protected]> */
+
+#include <common.h>
+#include <errno.h>
+#include <list.h>
+#include <init.h>
+#include <driver.h>
+#include <malloc.h>
+#include <string.h>
+#include <linux/i2c.h>
+#include <linux/idr.h>
+
+#include "i2c-core.h"
+
+#ifdef CONFIG_I2C_DEBUG_CORE
+#define DBG_MODULE_NAME "i2c-core"
+#define dev_dbg(ARGS...) fprintf(stdout, ARGS);
+#define dev_warn(ARGS...) fprintf(stderr, ARGS);
+#define dbg_entry(FORMAT, ARGS...) fprintf(stdout,\
+               DBG_MODULE_NAME"%s:%d:Entry:"FORMAT"\n",\
+               __func__, __LINE__, ARGS)
+#define dbg_exit(FORMAT, ARGS...) fprintf(stdout,\
+               DBG_MODULE_NAME"%s:%d:Exit:"FORMAT"\n",\
+               __func__, __LINE__, ARGS)
+#else
+#define dev_dbg(ARGS...)
+#define dev_warn(ARGS...)
+#define dbg_entry(FORMAT, ARGS...)
+#define dbg_exit(FORMAT, ARGS...)
+#endif
+#define dev_err(ARGS...) fprintf(stderr, ARGS);
+
+static DEFINE_IDR(i2c_adapter_idr);
+
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * @brief When traversing the driver model tree, perhaps using driver model
+ * iterators like @device_for_each_child(), you can't assume very much
+ * about the nodes you find.  Use this function to avoid oopses caused
+ * by wrongly treating some non-I2C device as an i2c_client.
+ *
+ * @param dev device, probably from some driver model iterator
+ *
+ * @return return parameter as i2c_client, or NULL
+ */
+struct i2c_client *i2c_verify_client(struct device_d *dev)
+{
+       dbg_entry("dev=%x", (u32) dev);
+       return (dev->type == DEVICE_TYPE_I2C) ? to_i2c_client(dev) : NULL;
+}
+EXPORT_SYMBOL(i2c_verify_client);
+
+static int i2c_register_adapter(struct i2c_adapter *adap)
+{
+       int res = 0;
+       dbg_entry("adap=%x", (u32) adap);
+
+       INIT_LIST_HEAD(&adap->clients);
+
+       /* Add the adapter to the driver core.
+        * If the parent pointer is not set up,
+        * we add this adapter to the host bus.
+        */
+       res = register_device(&adap->dev);
+       if (res)
+               goto out_list;
+
+       dev_dbg("adapter [%s] registered\n", adap->name);
+
+out_unlock:
+       return res;
+
+out_list:
+       idr_remove(&i2c_adapter_idr, adap->nr);
+       goto out_unlock;
+}
+
+/**
+ * @brief declare i2c adapter, use dynamic bus number
+ *
+ * This routine is used to declare an I2C adapter when its bus number
+ * doesn't matter.  Examples: for I2C adapters dynamically added by
+ * USB links or PCI plugin cards.
+ *
+ * @param adapter  the adapter to add
+ *
+ * @return When this returns zero, a new bus number was allocated and stored
+ * in adap->nr, and the specified adapter became available for clients.
+ * Otherwise, a negative errno value is returned.
+ */
+int i2c_add_adapter(struct i2c_adapter *adapter)
+{
+       int id, res = 0;
+       dbg_entry("adapter=%x", (u32) adapter);
+
+retry:
+       if (idr_pre_get(&i2c_adapter_idr) == 0)
+               return -ENOMEM;
+
+       /* "above" here means "above or equal to", sigh */
+       res = idr_get_new_above(&i2c_adapter_idr, adapter,
+                               __i2c_first_dynamic_bus_num, &id);
+
+       if (res < 0) {
+               if (res == -EAGAIN)
+                       goto retry;
+               return res;
+       }
+
+       adapter->nr = id;
+       return i2c_register_adapter(adapter);
+}
+EXPORT_SYMBOL(i2c_add_adapter);
+
+/**
+ * @brief declare i2c adapter, use static bus number
+ *
+ * This routine is used to declare an I2C adapter when its bus number
+ * matters.  For example, use it for I2C adapters from system-on-chip CPUs,
+ * or otherwise built in to the system's mainboard, and where i2c_board_info
+ * is used to properly configure I2C devices.
+ *
+ * If no devices have pre-been declared for this bus, then be sure to
+ * register the adapter before any dynamically allocated ones.  Otherwise
+ * the required bus ID may not be available.
+ *
+ * @param adap adapter to register (with adap->nr initialized)
+ *
+ * @return When this returns zero, the specified adapter became available for
+ * clients using the bus number provided in adap->nr.  Also, the table
+ * of I2C devices pre-declared using i2c_register_board_info() is scanned,
+ * and the appropriate driver model device nodes are created.  Otherwise, a
+ * negative errno value is returned.
+ */
+int i2c_add_numbered_adapter(struct i2c_adapter *adap)
+{
+       int id;
+       int status;
+
+       dbg_entry("adap=%x", (u32) adap);
+       if (adap->nr & ~MAX_ID_MASK)
+               return -EINVAL;
+
+retry:
+       if (idr_pre_get(&i2c_adapter_idr) == 0)
+               return -ENOMEM;
+
+       /* "above" here means "above or equal to", sigh;
+        * we need the "equal to" result to force the result
+        */
+       status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);
+       if (status == 0 && id != adap->nr) {
+               status = -EBUSY;
+               idr_remove(&i2c_adapter_idr, id);
+       }
+       if (status == -EAGAIN)
+               goto retry;
+
+       if (status == 0)
+               status = i2c_register_adapter(adap);
+       return status;
+}
+EXPORT_SYMBOL(i2c_add_numbered_adapter);
+
+/**
+ * @brief unregister I2C adapter
+ *
+ * This unregisters an I2C adapter which was previously registered
+ * by @i2c_add_adapter or @i2c_add_numbered_adapter.
+ *
+ * @param adap  the adapter being unregistered
+ *
+ * @return success or failure in removal
+ */
+int i2c_del_adapter(struct i2c_adapter *adap)
+{
+       struct list_head *item, *_n;
+       struct i2c_client *client;
+       int res = 0;
+
+       dbg_entry("adap=%x", (u32) adap);
+       /* First make sure that this adapter was ever added */
+       if (idr_find(&i2c_adapter_idr, adap->nr) != adap) {
+               dev_err("i2c-core: attempting to delete unregistered "
+                       "adapter [%s]\n", adap->name);
+               res = -EINVAL;
+               goto out_unlock;
+       }
+
+       /* detach any active clients. This must be done first, because
+        * it can fail; in which case we give up. */
+       list_for_each_safe(item, _n, &adap->clients) {
+               struct i2c_driver *driver;
+
+               client = list_entry(item, struct i2c_client, list);
+               driver = client->driver;
+
+               /* new style, follow standard driver model
+                * Place holder
+               if (!driver) {
+                       i2c_unregister_device(client);
+                       continue;
+               }
+               */
+
+       }
+
+       /* clean up the sysfs representation */
+       unregister_device(&adap->dev);
+
+       /* free bus id */
+       idr_remove(&i2c_adapter_idr, adap->nr);
+
+       dev_dbg("adapter [%s] unregistered\n", adap->name);
+
+out_unlock:
+       return res;
+}
+EXPORT_SYMBOL(i2c_del_adapter);
+/**
+ * @brief find the adapter for an id
+ *  Also increase the adapter refcount
+ *
+ * @param id id to search
+ *
+ * @return adapter else NULL
+ */
+struct i2c_adapter *i2c_get_adapter(int id)
+{
+       struct i2c_adapter *adapter;
+       dbg_entry("id=%x", id);
+
+       adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);
+
+       return adapter;
+}
+EXPORT_SYMBOL(i2c_get_adapter);
+
+/**
+ * @brief  return the usage of get_adapter -> reduce refcount
+ *
+ * @param adap adapter to return
+ *
+ * @return none
+ */
+void i2c_put_adapter(struct i2c_adapter *adap)
+{
+       dbg_entry("adap=%x", (u32) adap);
+       /* Empty function for the timebeing.. */
+}
+EXPORT_SYMBOL(i2c_put_adapter);
+
+/* ------------------------------------------------------------------------- */
+
+/* ----------------------------------------------------
+ * the functional interface to the i2c busses.
+ * ----------------------------------------------------
+ */
+
+/**
+ * @brief do i2c_transfer to an adapter
+ *
+ * @param adap adapter
+ * @param msgs the messages
+ * @param num number of messages
+ *
+ * @return result of transfer
+ */
+int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+       int ret;
+
+       dbg_entry("adap=%x msg=%x num=%x", (u32) adap, (u32) msgs, num);
+       if (adap->algo->master_xfer) {
+#ifdef DEBUG
+               for (ret = 0; ret < num; ret++) {
+                       dev_dbg("master_xfer[%d] %c, addr=0x%02x, "
+                               "len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
+                               ? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
+                               (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
+               }
+#endif
+
+               ret = adap->algo->master_xfer(adap, msgs, num);
+               return ret;
+       } else {
+               dev_dbg("I2C level transfers not supported\n");
+               return -ENOSYS;
+       }
+}
+EXPORT_SYMBOL(i2c_transfer);
+
+/**
+ * @brief send few bytes to a client
+ *
+ * @param client client to send data to
+ * @param buf buffer data
+ * @param count num bytes
+ *
+ * @return result of operation
+ */
+int i2c_master_send(struct i2c_client *client, const char *buf, int count)
+{
+       int ret;
+       struct i2c_adapter *adap = client->adapter;
+       struct i2c_msg msg;
+
+       dbg_entry("client=%x buf=%x count=%x", (u32) client, (u32) buf,
+                 (u32) count);
+       msg.addr = client->addr;
+       msg.flags = client->flags & I2C_M_TEN;
+       msg.len = count;
+       msg.buf = (char *)buf;
+
+       ret = i2c_transfer(adap, &msg, 1);
+
+       /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+          transmitted, else error code. */
+       return (ret == 1) ? count : ret;
+}
+EXPORT_SYMBOL(i2c_master_send);
+
+/**
+ * @brief read a few bytes from client
+ *
+ * @param client client
+ * @param buf buffer
+ * @param count num bytes to read
+ *
+ * @return result of operation
+ */
+int i2c_master_recv(struct i2c_client *client, char *buf, int count)
+{
+       struct i2c_adapter *adap = client->adapter;
+       struct i2c_msg msg;
+       int ret;
+
+       dbg_entry("client=%x buf=%x count=%x", (u32) client, (u32) buf,
+                 (u32) count);
+       msg.addr = client->addr;
+       msg.flags = client->flags & I2C_M_TEN;
+       msg.flags |= I2C_M_RD;
+       msg.len = count;
+       msg.buf = buf;
+
+       ret = i2c_transfer(adap, &msg, 1);
+
+       /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+          transmitted, else error code. */
+       return (ret == 1) ? count : ret;
+}
+EXPORT_SYMBOL(i2c_master_recv);
drivers/i2c/Kconfig 2008-06-19 08:42:46.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +39 -0
Index: u-boot-v2.git/drivers/i2c/Kconfig
===================================================================
@@ -0,0 +1,39 @@
+#
+# I2C subsystem configuration
+#
+
+menuconfig I2C
+       tristate "I2C support"
+       ---help---
+         I2C (pronounce: I-square-C) is a slow serial bus protocol used in
+         many micro controller applications and developed by Philips.  SMBus,
+         or System Management Bus is a subset of the I2C protocol.  More
+         information is contained in the directory <file:Documentation/i2c/>,
+         especially in the file called "summary" there.
+
+         If you want I2C support, you should say Y here and also to the
+         specific driver for your bus adapter(s) below.
+
+         This I2C support can also be built as a module.  If so, the module
+         will be called i2c-core.
+
+if I2C
+
+source drivers/i2c/busses/Kconfig
+
+config I2C_DEBUG_CORE
+       bool "I2C Core debugging messages"
+       help
+         Say Y here if you want the I2C core to produce a bunch of debug
+         messages to the system log.  Select this if you are having a
+         problem with I2C support and want to see more of what is going on.
+
+config I2C_DEBUG_BUS
+       bool "I2C Bus debugging messages"
+       help
+         Say Y here if you want the I2C bus drivers to produce a bunch of
+         debug messages to the system log.  Select this if you are having
+         a problem with I2C support and want to see more of what is going
+         on.
+
+endif # I2C
drivers/i2c/Makefile 2008-06-19 08:42:46.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +10 -0
Index: u-boot-v2.git/drivers/i2c/Makefile
===================================================================
@@ -0,0 +1,10 @@
+#
+# Makefile for the i2c core.
+#
+
+obj-$(CONFIG_I2C)              += i2c-core.o
+obj-y                          += busses/
+
+ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
drivers/i2c/busses/Kconfig 2008-06-19 08:42:46.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +7 -0
Index: u-boot-v2.git/drivers/i2c/busses/Kconfig
===================================================================
@@ -0,0 +1,7 @@
+#
+# Sensor device configuration
+#
+
+menu "I2C Hardware Bus support"
+
+endmenu
drivers/i2c/busses/Makefile 2008-06-19 08:42:46.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +9 -0
Index: u-boot-v2.git/drivers/i2c/busses/Makefile
===================================================================
@@ -0,0 +1,9 @@
+#
+# Makefile for the i2c bus drivers.
+#
+
+obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
+
+ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
drivers/i2c/i2c-core.h 2008-06-19 08:42:46.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +37 -0
Index: u-boot-v2.git/drivers/i2c/i2c-core.h
===================================================================
@@ -0,0 +1,37 @@
+/**
+ * @file
+ * @brief - interfaces internal to the I2C framework
+ *
+ * FileName: drivers/i2c/i2c-core.h
+ *
+ */
+/* Originally from Linux kernel. Ported to U-boot-v2.
+ * (C) Copyright 2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <[email protected]>
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __i2C_CORE_H
+#define  __i2C_CORE_H
+
+/* board_lock protects board_list and first_dynamic_bus_num.
+ * only i2c core components are allowed to use these symbols.
+ */
+extern struct list_head        __i2c_board_list;
+extern int             __i2c_first_dynamic_bus_num;
+
+#endif         /*  __i2C_CORE_H */
include/linux/i2c.h 2008-06-19 08:42:46.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +299 -0

299 lines not on this page · raw message

drivers/Kconfig 2008-06-19 08:42:46.000000000 -0500 renamed from drivers/Kconfig 2008-06-19 08:40:01.000000000 -0500 +1 -0
Index: u-boot-v2.git/drivers/Kconfig
===================================================================
@@ -3,6 +3,7 @@
 source "drivers/serial/Kconfig"
 source "drivers/net/Kconfig"
 source "drivers/spi/Kconfig"
+source "drivers/i2c/Kconfig"
 
 menu "flash drivers                 "
 
drivers/Makefile 2008-06-19 08:42:46.000000000 -0500 renamed from drivers/Makefile 2008-06-19 08:40:01.000000000 -0500 +1 -0
Index: u-boot-v2.git/drivers/Makefile
===================================================================
@@ -2,6 +2,7 @@
 obj-y  += serial/
 obj-y  += nand/
 obj-$(CONFIG_SPI) += spi/
+obj-$(CONFIG_I2C) += i2c/
 obj-$(CONFIG_DRIVER_CFI_OLD) += cfi_flash.o
 obj-$(CONFIG_DRIVER_CFI_NEW) += cfi_flash_new.o
 obj-$(CONFIG_DRIVER_CFI_INTEL) += cfi_flash_intel.o
include/driver.h 2008-06-19 08:42:46.000000000 -0500 renamed from include/driver.h 2008-06-19 08:40:00.000000000 -0500 +3 -1
Index: u-boot-v2.git/include/driver.h
===================================================================
@@ -34,7 +34,9 @@
 #define DEVICE_TYPE_BLOCK      4
 #define DEVICE_TYPE_FS         5
 #define DEVICE_TYPE_MIIPHY     6
-#define MAX_DEVICE_TYPE         6
+#define DEVICE_TYPE_I2C                7
+#define DEVICE_TYPE_I2CDEV     8
+#define MAX_DEVICE_TYPE         8
 
 #include <param.h>
#19 lore raw

PATCH 4/9 U-boot-V2:I2C: Introduce i2c-dev

In reply to Robert Schwebel

I2C by default does not expose a device interface for the adapters registering in the system. This is usually not needed unless we need to debug something. in which case, this is a handy little layer when used in conjunction with the i2c commands.

---
 drivers/i2c/Kconfig     |   10 +
 drivers/i2c/Makefile    |    1
 drivers/i2c/i2c-core.c  |   12 +
 drivers/i2c/i2c-core.h  |    4
 drivers/i2c/i2c-dev.c   |  439 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/i2c-dev.h |   71 +++++++
 6 files changed, 537 insertions(+)
include/linux/i2c-dev.h 2008-06-19 08:42:58.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +71 -0
Index: u-boot-v2.git/include/linux/i2c-dev.h
===================================================================
@@ -0,0 +1,71 @@
+/**
+ * @file
+ * @brief i2c-bus driver, "char device" interface
+ *
+ * FileName: include/linux/i2c-dev.h
+ *
+ */
+/* Originally from Linux kernel. Ported to U-boot-v2.
+ * (C) Copyright 2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <[email protected]>
+ */
+/*
+    Copyright (C) 1995-97 Simon G. Vogl
+    Copyright (C) 1998-99 Frodo Looijaard <[email protected]>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _LINUX_I2C_DEV_H
+#define _LINUX_I2C_DEV_H
+
+#include <linux/types.h>
+
+/* /dev/i2c-X ioctl commands.  The ioctl's parameter is always an
+ * unsigned long, except for:
+ *     - I2C_FUNCS, takes pointer to an unsigned long
+ *     - I2C_RDWR, takes pointer to struct i2c_rdwr_ioctl_data
+ *     - I2C_SMBUS, takes pointer to struct i2c_smbus_ioctl_data
+ */
+#define I2C_RETRIES    0x0701  /* number of times a device address should
+                                  be polled when not acknowledging */
+#define I2C_TIMEOUT    0x0702  /* set timeout in jiffies - call with int */
+
+/* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses
+ * are NOT supported! (due to code brokenness)
+ */
+#define I2C_SLAVE      0x0703  /* Use this slave address */
+#define I2C_SLAVE_FORCE        0x0706  /* Use this slave address, even if it
+                                  is already in use by a driver! */
+#define I2C_TENBIT     0x0704  /* 0 for 7 bit addrs, != 0 for 10 bit */
+
+#define I2C_FUNCS      0x0705  /* Get the adapter functionality mask */
+
+#define I2C_RDWR       0x0707  /* Combined R/W transfer (one STOP only) */
+
+#define I2C_PEC                0x0708  /* != 0 to use PEC with SMBus */
+
+/* This is the structure as used in the I2C_RDWR ioctl call */
+struct i2c_rdwr_ioctl_data {
+       struct i2c_msg *msgs;   /* pointers to i2c_msgs */
+       u32 nmsgs;                      /* number of i2c_msgs */
+};
+
+#define  I2C_RDRW_IOCTL_MAX_MSGS       42
+
+#define I2C_DEV_NAME "i2cd"
+
+#endif /* _LINUX_I2C_DEV_H */
drivers/i2c/i2c-dev.c 2008-06-19 08:42:58.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +439 -0

439 lines not on this page · raw message

drivers/i2c/Kconfig 2008-06-19 08:42:58.000000000 -0500 renamed from drivers/i2c/Kconfig 2008-06-19 08:42:46.000000000 -0500 +10 -0
Index: u-boot-v2.git/drivers/i2c/Kconfig
===================================================================
@@ -19,6 +19,16 @@
 
 if I2C
 
+config I2C_CHARDEV
+       tristate "I2C device interface"
+       help
+         Say Y here to use i2c-* device files, usually found in the /dev
+         directory on your system.  They make it possible to have applications
+         to use the I2C bus.
+
+         This support is also available as a module.  If so, the module
+         will be called i2c-dev.
+
 source drivers/i2c/busses/Kconfig
 
 config I2C_DEBUG_CORE
drivers/i2c/Makefile 2008-06-19 08:42:58.000000000 -0500 renamed from drivers/i2c/Makefile 2008-06-19 08:42:46.000000000 -0500 +1 -0
Index: u-boot-v2.git/drivers/i2c/Makefile
===================================================================
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_I2C)              += i2c-core.o
+obj-$(CONFIG_I2C_CHARDEV)      += i2c-dev.o
 obj-y                          += busses/
 
 ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
drivers/i2c/i2c-core.c 2008-06-19 08:42:58.000000000 -0500 renamed from drivers/i2c/i2c-core.c 2008-06-19 08:42:46.000000000 -0500 +12 -0
Index: u-boot-v2.git/drivers/i2c/i2c-core.c
===================================================================
@@ -102,6 +102,10 @@
 
        dev_dbg("adapter [%s] registered\n", adap->name);
 
+#ifdef CONFIG_I2C_CHARDEV
+       i2cdev_attach_adapter(adap);
+#endif
+
 out_unlock:
        return res;
 
@@ -222,6 +226,14 @@
                goto out_unlock;
        }
 
+#ifdef CONFIG_I2C_CHARDEV
+       res = i2cdev_detach_adapter(adap);
+       if (res) {
+               dev_err("adapter in use\n");
+               goto out_unlock;
+       }
+#endif
+
        /* detach any active clients. This must be done first, because
         * it can fail; in which case we give up. */
        list_for_each_safe(item, _n, &adap->clients) {
drivers/i2c/i2c-core.h 2008-06-19 08:42:58.000000000 -0500 renamed from drivers/i2c/i2c-core.h 2008-06-19 08:42:46.000000000 -0500 +4 -0
Index: u-boot-v2.git/drivers/i2c/i2c-core.h
===================================================================
@@ -34,4 +34,8 @@
 extern struct list_head        __i2c_board_list;
 extern int             __i2c_first_dynamic_bus_num;
 
+/* Automatically called by i2c-Core..*/
+int i2cdev_attach_adapter(struct i2c_adapter *adap);
+int i2cdev_detach_adapter(struct i2c_adapter *adap);
+
 #endif         /*  __i2C_CORE_H */
#20 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

In reply to Robert Schwebel

Introduce I2c commands from i2c-tools. This allows for Diagnostics capability. Supports ONLY i2c busses at the moment.

This code is based on
http://www.lm-sensors.org/wiki/I2CTools
This closely follows the functionality, options and man page documentation

---
 commands/i2c.c | 1268 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1268 insertions(+)
commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +1268 -0
Index: u-boot-v2.git/commands/i2c.c
===================================================================
@@ -0,0 +1,1268 @@
+/**
+ * @file
+ * @brief I2C related applications
+ *
+ * FileName: commands/i2c.c
+ * This provides i2cdump, i2cdetect, i2cset and i2cget appplications
+ * The code originates from the i2c-tools located here:
+ * http://www.lm-sensors.org/wiki/I2CTools
+ *
+ * This file merges the userspace headers and applications to a single
+ * entity as we do not maintain a userspace/kernel space isolation
+ *
+ * NOTE: 10-bit addresses are NOT supported!
+ */
+/*
+ * (C) Copyright 2006-2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <[email protected]>
+ *
+ * This application is based on the following:
+ *
+ * i2cbusses: Print the installed i2c busses for both 2.4 and 2.6 kernels.
+ *            Part of user-space programs to access for I2C
+ *            devices.
+ * Copyright (c) 1999-2003  Frodo Looijaard <[email protected]> and
+ *                          Mark D. Studebaker <[email protected]>
+ * Copyright (C) 2008       Jean Delvare <[email protected]>
+ * i2cdump.c - a user-space program to dump I2C registers
+ * Copyright (C) 2002-2003  Frodo Looijaard <[email protected]>, and
+ *                          Mark D. Studebaker <[email protected]>
+ * Copyright (C) 2004-2008  Jean Delvare <[email protected]>
+ * i2cget.c - A user-space program to read an I2C register.
+ * Copyright (C) 2005-2008  Jean Delvare <[email protected]>
+ * i2cset.c - A user-space program to write an I2C register.
+ * Copyright (C) 2001-2003  Frodo Looijaard <[email protected]>, and
+ *                          Mark D. Studebaker <[email protected]>
+ * Copyright (C) 2004-2008  Jean Delvare <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <types.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <fs.h>
+#include <errno.h>
+#include <linux/stat.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include "i2c.h"
+
+#define MISSING_FUNC_FMT "Error: Adapter does not have %s capability\n"
+
+/*************** Lib Functions *************/
+
+/**
+ * @brief Parse an I2CBUS command line argument
+ *
+ * @param i2cbus_arg arg to busparam
+ *
+ * @return the corresponding bus number,
+ * or a negative value if the bus is invalid.
+ */
+int lookup_i2c_bus(const char *i2cbus_arg)
+{
+       long i2cbus;
+       char *end;
+
+       if (i2cbus_arg == NULL) {
+               fprintf(stderr, "no bus arg! expect 0-9\n");
+               return -1;
+       }
+       if (strlen(i2cbus_arg) > 2) {
+               fprintf(stderr, "bad bus arg! expect 0-9 saw %s\n", i2cbus_arg);
+               return -2;
+       }
+       i2cbus = simple_strtol(i2cbus_arg, &end, 0);
+       if ((*i2cbus_arg != '0') && (i2cbus == 0)) {
+               fprintf(stderr, "bad bus arg! expect 0-9, saw %s\n",
+                       i2cbus_arg);
+               return -2;
+       }
+       if (i2cbus < 0 || i2cbus > 0xff) {
+               fprintf(stderr, "Error: I2C bus out of range (0-255)!\n");
+               return -3;
+       }
+
+       return i2cbus;
+}
+
+/**
+ * @brief open a given i2cdevice
+ *
+ * @param i2cbus bus index
+ * @param filename return the devfs filename for the bus
+ * @param quiet be silent?
+ *
+ * @return return value of open
+ */
+int open_i2c_dev(const int i2cbus, char *filename, const int quiet)
+{
+       int file;
+
+       sprintf(filename, "/dev/" I2C_DEV_NAME "%d", i2cbus);
+       file = open(filename, O_RDWR);
+
+       if (file < 0 && !quiet) {
+               perror(filename);
+               fprintf(stderr, "Error: Could not open file "
+                       "`%s'\n", filename);
+       }
+
+       return file;
+}
+
+/**
+ * @brief Parse a CHIP-ADDRESS command line argument
+ *
+ * @param address_arg -user provided argument
+ *
+ * @return The corresponding chip address,
+ *          or a negative value if the address is invalid.
+ */
+int parse_i2c_address(const char *address_arg)
+{
+       long address;
+       char *end;
+
+       address = simple_strtol(address_arg, &end, 0);
+       if (*end || !*address_arg) {
+               fprintf(stderr, "Error: Chip address is not a number!\n");
+               return -1;
+       }
+       if (address < 0x03 || address > 0x77) {
+               fprintf(stderr, "Error: Chip address out of range "
+                       "(0x03-0x77)!\n");
+               return -2;
+       }
+
+       return address;
+}
+
+/**
+ * @brief force the slave address
+ *
+ * @param file file id
+ * @param address address to set
+ * @param force force address
+ *
+ * @return returns result of ioctl
+ */
+int set_slave_addr(int file, int address, int force)
+{
+       /* With force, let the user read from/write to the registers
+          even when a driver is also running */
+       if (ioctl(file, force ? I2C_SLAVE_FORCE : I2C_SLAVE, (void *)address) <
+           0) {
+               perror(NULL);
+               fprintf(stderr,
+                       "Error: Could not set address to 0x%02x\n", address);
+               return -errno;
+       }
+
+       return 0;
+}
+
+/**
+ * @brief check functionality of the adapter
+ *
+ * @param file file index
+ * @param size size of the same
+ * @param daddress device address
+ * @param pec pec
+ *
+ * @return result of ioctl check negative if failed
+ */
+int check_funcs(int file, int size, int daddress, int pec)
+{
+       unsigned long funcs;
+
+       /* check adapter functionality */
+       if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
+               perror(NULL);
+               fprintf(stderr, "Error: Could not get the adapter "
+                       "functionality matrix\n");
+               return -1;
+       }
+
+       if (!(funcs & I2C_FUNC_I2C)) {
+               fprintf(stderr, MISSING_FUNC_FMT, "I2C support");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int read_i2c(int file, uchar daddr, u16 addr, u8 reg_width, char *buffer,
+            size_t count)
+{
+       struct i2c_msg msg[2] = {
+               {daddr, 0, reg_width, (u8 *) &addr},
+               {daddr, 0 | I2C_M_RD, count, buffer}
+       };
+       struct i2c_rdwr_ioctl_data data = {
+               .msgs = msg,
+               .nmsgs = 2,
+       };
+       return ioctl(file, I2C_RDWR, &data);
+}
+
+int write_i2c(int file, uchar daddr, u16 addr, u8 reg_width, char *buffer,
+             size_t count)
+{
+       unsigned char *temp_buf;
+       struct i2c_msg msg = { daddr, 0, count + reg_width, NULL };
+       struct i2c_rdwr_ioctl_data data = {
+               .msgs = &msg,
+               .nmsgs = 1,
+       };
+       int ret;
+       temp_buf = malloc(count + reg_width);
+       if (temp_buf == NULL)
+               return -ENOMEM;
+       memcpy(temp_buf, &addr, reg_width);
+       memcpy(temp_buf + reg_width, buffer, count);
+       msg.buf = temp_buf;
+       ret = ioctl(file, I2C_RDWR, &data);
+       free(temp_buf);
+       return ret;
+}
+
+/****************** Test implementations **************/
+#ifdef CONFIG_CMD_I2C_DETECT
+
+#define MODE_AUTO      0
+#define MODE_QUICK     1
+#define MODE_READ      2
+#define MODE_FUNC      3
+
+static const __maybe_unused char cmd_i2cdetect_help_s[] =
+    "Usage:\n"
+    "a) i2cdetect [-a] [-q|-r] I2CBUS [FIRST LAST]\n"
+    "Where:\n"
+    "  -a : all addresses (default scans from 0x03 - 0x77)\n"
+    "  -q : use write-risky at times\n"
+    "  -r : use read-risky@times\n"
+    "  If provided, FIRST and LAST limit the probing range.\n"
+    "b) i2cdetect -F I2CBUS\n"
+    "Where:\n"
+    "  -F : Show functionality of the device\n"
+    "\n"
+    "I2CBUS is an integer representing the bus index\n"
+    "these are present as 'xx' of /dev/" I2C_DEV_NAME
+    "xx\n" "WARN:\n"
+    "This program can confuse your I2C bus, cause data loss and worse!\n";
+
+#ifdef CONFIG_LONGHELP
+static void cmd_i2cdetect_help(void)
+{
+       fprintf(stderr, "%s", cmd_i2cdetect_help_s);
+}
+#else
+#define cmd_i2cdetect_help()
+#endif
+
+/**
+ * @brief scan the i2c bus
+ *
+ * @param file file index
+ * @param mode what mode to scan it with
+ * @param first start address
+ * @param last end address
+ *
+ * @return negative if scan failed, else return 0
+ */
+static int scan_i2c_bus(int file, int mode, int first, int last)
+{
+       int i, j;
+       int res;
+       unsigned char dummy = 0x0;
+
+       printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n");
+
+       for (i = 0; i < 128; i += 16) {
+               printf("%02x: ", i);
+               for (j = 0; j < 16; j++) {
+
+                       /* Skip unwanted addresses */
+                       if (i + j < first || i + j > last) {
+                               printf("   ");
+                               continue;
+                       }
+
+                       /* Set slave address */
+                       if (ioctl(file, I2C_SLAVE, (void *)(i + j)) < 0) {
+                               if (errno == EBUSY) {
+                                       printf("UU ");
+                                       continue;
+                               } else {
+                                       perror(NULL);
+                                       fprintf(stderr, "Error: Could not set "
+                                               "address to 0x%02x\n", i + j);
+                                       return -1;
+                               }
+                       }
+
+                       /* Probe this address */
+                       switch (mode) {
+                       case MODE_QUICK:
+                               /* Attempt a 0 byte write -can lock up many
+                                * devices */
+                               res = write_i2c(file, i + j, 0x0, 1, NULL, 0);
+                               break;
+                       case MODE_READ:
+                               /* This is known to lock on various
+                                  write-only chips (mainly clock chips) */
+                               res = read_i2c(file, i + j, 0x0, 1, &dummy, 1);
+                               break;
+                       default:
+                               if ((i + j >= 0x30 && i + j <= 0x37)
+                                   || (i + j >= 0x50 && i + j <= 0x5F))
+                                       res =
+                                           read_i2c(file, i + j, 0x0, 1,
+                                                    &dummy, 1);
+                               else
+                                       res =
+                                           write_i2c(file, i + j, 0x0, 1, NULL,
+                                                     0);
+                       }
+
+                       if (res < 0)
+                               printf("-- ");
+                       else
+                               printf("%02x ", i + j);
+               }
+               printf("\n");
+       }
+
+       return 0;
+}
+
+struct func {
+       long value;
+       const char *name;
+};
+
+static const struct func all_func[] = {
+       {.value = I2C_FUNC_I2C,
+        .name = "I2C"},
+       {.value = 0,
+        .name = ""}
+};
+
+/**
+ * @brief print the functionality of the adapter
+ *
+ * @param funcs the ioctl returned value
+ *
+ * @return none
+ */
+static void print_functionality(unsigned long funcs)
+{
+       int i;
+       for (i = 0; all_func[i].value; i++) {
+               printf("%-32s %s\n", all_func[i].name,
+                      (funcs & all_func[i].value) ? "yes" : "no");
+       }
+}
+
+static int do_cmd_i2c_detect(cmd_tbl_t *cmdtp, int argc, char *argv[])
+{
+       char *end;
+       int i2cbus, file = 0, res = 0;
+       char filename[PATH_MAX];
+       unsigned long funcs;
+       int mode = MODE_AUTO;
+       int first = 0x03, last = 0x77;
+       int flags = 0;
+
+       /* handle (optional) flags first */
+       while (1 + flags < argc && argv[1 + flags][0] == '-') {
+               switch (argv[1 + flags][1]) {
+               case 'F':
+                       if (mode != MODE_AUTO && mode != MODE_FUNC) {
+                               fprintf(stderr, "Error: Different modes "
+                                       "specified!\n");
+                               goto quit_i2cdetect;
+                       }
+                       mode = MODE_FUNC;
+                       break;
+               case 'r':
+                       if (mode == MODE_QUICK) {
+                               fprintf(stderr, "Error: Different modes "
+                                       "specified!\n");
+                               goto quit_i2cdetect;
+                       }
+                       mode = MODE_READ;
+                       break;
+               case 'q':
+                       if (mode == MODE_READ) {
+                               fprintf(stderr, "Error: Different modes "
+                                       "specified!\n");
+                               goto quit_i2cdetect;
+                       }
+                       mode = MODE_QUICK;
+                       break;
+               case 'a':
+                       first = 0x00;
+                       last = 0x7F;
+                       break;
+               default:
+                       fprintf(stderr, "Error: Unsupported option "
+                               "\"%s\"!\n", argv[1 + flags]);
+                       goto quit_i2cdetect;
+               }
+               flags++;
+       }
+
+       if (argc < flags + 2) {
+               fprintf(stderr, "Error: No i2c-bus specified!\n");
+               goto quit_i2cdetect;
+       }
+       i2cbus = lookup_i2c_bus(argv[flags + 1]);
+       if (i2cbus < 0) {
+               fprintf(stderr, "Error: bus not found!\n");
+               goto quit_i2cdetect;
+       }
+
+       /* read address range if present */
+       if (argc == flags + 4 && mode != MODE_FUNC) {
+               int tmp;
+
+               tmp = simple_strtol(argv[flags + 2], &end, 0);
+               if (*end) {
+                       fprintf(stderr, "Error: FIRST argment not a "
+                               "number!\n");
+                       goto quit_i2cdetect;
+               }
+               if (tmp < first || tmp > last) {
+                       fprintf(stderr, "Error: FIRST argument out of range "
+                               "(0x%02x-0x%02x)!\n", first, last);
+                       goto quit_i2cdetect;
+               }
+               first = tmp;
+
+               tmp = simple_strtol(argv[flags + 3], &end, 0);
+               if (*end) {
+                       fprintf(stderr, "Error: LAST argment not a "
+                               "number!\n");
+                       goto quit_i2cdetect;
+               }
+               if (tmp < first || tmp > last) {
+                       fprintf(stderr, "Error: LAST argument out of range "
+                               "(0x%02x-0x%02x)!\n", first, last);
+                       goto quit_i2cdetect;
+               }
+               last = tmp;
+       } else if (argc != flags + 2) {
+               goto quit_i2cdetect;
+       }
+
+       file = open_i2c_dev(i2cbus, filename, 0);
+       if (file < 0)
+               return 1;
+
+       res = 1;
+       if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
+               perror(filename);
+               fprintf(stderr, "Error: Could not get the adapter "
+                       "functionality matrix\n");
+               goto ret;
+       }
+
+       /* Special case, we only list the implemented functionalities */
+       if (mode == MODE_FUNC) {
+               printf("Functionalities implemented by %s:\n", filename);
+               print_functionality(funcs);
+               res = 0;
+               goto ret;
+       }
+
+       res = scan_i2c_bus(file, mode, first, last);
+ret:
+       if (file >= 0)
+               close(file);
+       return res ? 1 : 0;
+
+quit_i2cdetect:
+       /* Exit after printing help */
+       cmd_i2cdetect_help();
+       goto ret;
+}
+
+U_BOOT_CMD_START(i2cdetect)
+    .maxargs = 6,
+    .cmd = do_cmd_i2c_detect,
+    .usage = "program to scan for I2C devices",
+    U_BOOT_CMD_HELP(cmd_i2cdetect_help_s)
+U_BOOT_CMD_END
+#endif                         /* CONFIG_CMD_I2C_DETECT */
+
+#ifdef CONFIG_CMD_I2C_DUMP
+static const __maybe_unused char cmd_i2cdump_help_s[] =
+    "Usage: i2cdump [-f] [-r first-last] I2CBUS ADDRESS [MODE]\n"
+    "Where:\n"
+    " -f : Force set the slave address\n"
+    " -r : first-last the range of addresses which will be dumped\n"
+    "I2CBUS is an integer representing the bus index\n"
+    "  these are present as 'xx' of /dev/" I2C_DEV_NAME "xx\n"
+    "ADDRESS is an integer representing device address (0x03 - 0x77)\n"
+    "MODE is one of:\n"
+    "  b (byte, default)\n"
+    "  w (word)\n"
+    "  W (word on even register addresses)\n"
+    "  Append p for PEC\n"
+    "WARN: i2cdump can be dangerous if used improperly.\n";
+
+#ifdef CONFIG_LONGHELP
+static const __maybe_unused char cmd_i2c_ext_help_s[] =
+    "Most notably, the c mode "
+    "starts with WRITING a byte to the chip. On most chips it will be stored\n"
+    "in the address pointer register, which is OK, but some chips with a\n"
+    "single register or no (visible)register at all will most likely see this\n"
+    "as a real WRITE, resulting in possible misbehavior or corruption. Do not\n"
+    "use i2cdump on random addresses. Anyway, it is of little use unless you\n"
+    "have good knowledge of the chip you??(tm)re working with and an idea of \n"
+    "what you are looking for.\n";
+static void cmd_i2dump_help(void)
+{
+       fprintf(stderr, "%s", cmd_i2cdump_help_s);
+       fprintf(stderr, "%s", cmd_i2c_ext_help_s);
+}
+#else
+#define cmd_i2dump_help()
+#endif
+
+static int do_cmd_i2c_dump(cmd_tbl_t *cmdtp, int argc, char *argv[])
+{
+       char *end;
+       int i, j, res, i2cbus, address, size, file = -1;
+       char filename[PATH_MAX];
+       int block[256];
+       int pec = 0, even = 0;
+       int flags = 0;
+       int force = 0;
+       const char *range = NULL;
+       int first = 0x00, last = 0xff;
+
+       /* handle (optional) flags first */
+       while (1 + flags < argc && argv[1 + flags][0] == '-') {
+               switch (argv[1 + flags][1]) {
+               case 'f':
+                       force = 1;
+                       break;
+               case 'r':
+                       range = argv[1 + (++flags)];
+                       break;
+               default:
+                       fprintf(stderr, "Error: Unsupported option "
+                               "\"%s\"!\n", argv[1 + flags]);
+                       goto quit_i2cdump;
+               }
+               flags++;
+       }
+
+       if (argc < flags + 2) {
+               fprintf(stderr, "Error: No i2c-bus specified!\n");
+               goto quit_i2cdump;
+       }
+       i2cbus = lookup_i2c_bus(argv[flags + 1]);
+       if (i2cbus < 0) {
+               fprintf(stderr, "Error: Bus not found!\n");
+               goto quit_i2cdump;
+       }
+
+       if (argc < flags + 3) {
+               fprintf(stderr, "Error: No address specified!\n");
+               goto quit_i2cdump;
+       }
+       address = parse_i2c_address(argv[flags + 2]);
+       if (address < 0) {
+               fprintf(stderr, "Error: Badd address\n");
+               goto quit_i2cdump;
+       }
+
+       if (argc < flags + 4) {
+               fprintf(stderr, "No size specified (using byte-data access)\n");
+               size = I2C_SMBUS_BYTE_DATA;
+       } else if (!strncmp(argv[flags + 3], "b", 1)) {
+               size = I2C_SMBUS_BYTE_DATA;
+               pec = argv[flags + 3][1] == 'p';
+       } else if (!strncmp(argv[flags + 3], "w", 1)) {
+               size = I2C_SMBUS_WORD_DATA;
+               pec = argv[flags + 3][1] == 'p';
+       } else if (!strncmp(argv[flags + 3], "W", 1)) {
+               size = I2C_SMBUS_WORD_DATA;
+               even = 1;
+       } else {
+               fprintf(stderr, "Error: Invalid mode!\n");
+               goto quit_i2cdump;
+       }
+
+       /* Parse optional range string */
+       if (range) {
+               char *dash;
+
+               first = simple_strtol(range, &dash, 0);
+               if ((dash == range) || (*dash != '-') || (first < 0) ||
+                               (first > 0xff)) {
+                       fprintf(stderr, "Error: Invalid range parameter!\n");
+                       goto quit_i2cdump;
+               }
+               last = simple_strtol(++dash, &end, 0);
+               if ((end == dash) || (*end != '\0') || (last < first) ||
+                               (last > 0xff)) {
+                       fprintf(stderr, "Error: Invalid range parameter!\n");
+                       goto quit_i2cdump;
+               }
+
+               /* Check mode constraints */
+               switch (size) {
+               case I2C_SMBUS_BYTE:
+               case I2C_SMBUS_BYTE_DATA:
+                       break;
+               case I2C_SMBUS_WORD_DATA:
+                       if (!even || (!(first % 2) && last % 2))
+                               break;
+                       /* Fall through */
+               default:
+                       fprintf(stderr,
+                               "Error: Range parameter not compatible"
+                               "with selected mode!\n");
+                       goto quit_i2cdump;
+               }
+       }
+
+       file = open_i2c_dev(i2cbus, filename, 0);
+       if (file < 0 || check_funcs(file, size, address, pec)
+           || set_slave_addr(file, address, force))
+               goto quit_i2cdump;
+
+       if (pec) {
+               if (ioctl(file, I2C_PEC, (void *)1) < 0) {
+                       perror(filename);
+                       fprintf(stderr, "Error: Could not set PEC\n");
+                       goto quit_i2cdump;
+               }
+       }
+
+       /* handle all but word data */
+       if (size != I2C_SMBUS_WORD_DATA || even) {
+               printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f"
+                      "    0123456789abcdef\n");
+               for (i = 0; i < 256; i += 16) {
+                       if (i / 16 < first / 16)
+                               continue;
+                       if (i / 16 > last / 16)
+                               break;
+
+                       printf("%02x: ", i);
+                       for (j = 0; j < 16; j++) {
+                               /* Skip unwanted registers */
+                               if (i + j < first || i + j > last) {
+                                       printf("   ");
+                                       if (size == I2C_SMBUS_WORD_DATA) {
+                                               printf("   ");
+                                               j++;
+                                       }
+                                       continue;
+                               }
+
+                               if (size == I2C_SMBUS_BYTE_DATA) {
+                                       u8 buf;
+                                       res =
+                                           read_i2c(file, address, i + j, 1,
+                                                    &buf, 1);
+                                       block[i + j] = buf;
+
+                               } else if (size == I2C_SMBUS_WORD_DATA) {
+                                       u8 buf[2];
+                                       res =
+                                           read_i2c(file, address, i + j,
+                                                    (even) ? 2 : 1, buf, 2);
+                                       if (res < 0) {
+                                               block[i + j] = res;
+                                               block[i + j + 1] = res;
+                                       } else {
+                                               block[i + j] = buf[0];
+                                               block[i + j + 1] = buf[1];
+                                       }
+                               } else
+                                       res = block[i + j];
+
+                               if (res < 0) {
+                                       printf("XX ");
+                                       if (size == I2C_SMBUS_WORD_DATA)
+                                               printf("XX ");
+                               } else {
+                                       printf("%02x ", block[i + j]);
+                                       if (size == I2C_SMBUS_WORD_DATA)
+                                               printf("%02x ",
+                                                      block[i + j + 1]);
+                               }
+                               if (size == I2C_SMBUS_WORD_DATA)
+                                       j++;
+                       }
+                       printf("   ");
+
+                       for (j = 0; j < 16; j++) {
+                               /* Skip unwanted registers */
+                               if (i + j < first || i + j > last) {
+                                       printf(" ");
+                                       continue;
+                               }
+
+                               res = block[i + j];
+                               if (res < 0)
+                                       printf("X");
+                               else if ((res & 0xff) == 0x00
+                                        || (res & 0xff) == 0xff)
+                                       printf(".");
+                               else if ((res & 0xff) < 32
+                                        || (res & 0xff) >= 127)
+                                       printf("?");
+                               else
+                                       printf("%c", res & 0xff);
+                       }
+                       printf("\n");
+               }
+       } else {
+               printf("     0,8  1,9  2,a  3,b  4,c  5,d  6,e  7,f\n");
+               for (i = 0; i < 256; i += 8) {
+                       if (i / 8 < first / 8)
+                               continue;
+                       if (i / 8 > last / 8)
+                               break;
+
+                       printf("%02x: ", i);
+                       for (j = 0; j < 8; j++) {
+                               u16 buf;
+                               /* Skip unwanted registers */
+                               if (i + j < first || i + j > last) {
+                                       printf("     ");
+                                       continue;
+                               }
+
+                               res =
+                                   read_i2c(file, address, i + j, 1,
+                                            (u8 *) &buf, 2);
+                               if (res < 0)
+                                       printf("XXXX ");
+                               else
+                                       printf("%04x ", buf & 0xffff);
+                       }
+                       printf("\n");
+               }
+       }
+       return 0;
+
+quit_i2cdump:
+       /* Quit after providing help info */
+       cmd_i2dump_help();
+       if (file >= 0)
+               close(file);
+       return 1;
+}
+
+U_BOOT_CMD_START(i2cdump)
+    .maxargs = 8,
+    .cmd = do_cmd_i2c_dump,
+    .usage = "program to dump I2C registers",
+    U_BOOT_CMD_HELP(cmd_i2cdump_help_s)
+U_BOOT_CMD_END
+#endif                         /* CONFIG_CMD_I2C_DUMP */
+
+#ifdef CONFIG_CMD_I2C_GET
+static const __maybe_unused char cmd_i2cget_help_s[] =
+    "Usage: i2cget [-y] [-f] I2CBUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]\n"
+    "Where:\n"
+    "  -y : will allow to get from 0x50 to 0x57 with pec enabled\n"
+    "  -f : Force set the slave address\n"
+    "I2CBUS is an integer representing the bus index\n"
+    "  these are present as 'xx' of /dev/" I2C_DEV_NAME "xx\n"
+    "CHIP-ADDRESS is an integer representing device address (0x03 - 0x77)\n"
+    "DATA-ADDRESS is an integer representing register offset.\n"
+    "  (0x00 - 0xFF). If omitted, the currently active register\n"
+    "  will be read (if that makes sense for the considered chip).\n"
+    "MODE is one of:\n"
+    "  b (read byte data, default)\n"
+    "  w (read word data)\n"
+    "  c (write byte/read byte)\n"
+    "  Append p for PEC\n"
+    "WARN: i2cget can be extremely dangerous if used improperly.\n";
+
+#ifdef CONFIG_LONGHELP
+static const __maybe_unused char cmd_i2cget_help_add_s[] =
+    "I2C"
+    "are designed in such a way that an read transaction can be seen\n"
+    "as a write transaction by certain chips. This is particularly true if\n"
+    "setting mode to cp (write byte/read byte with PEC). Be extremely careful\n"
+    "using this program.\n";
+static void cmd_i2get_help(void)
+{
+       fprintf(stderr, "%s", cmd_i2cget_help_s);
+       fprintf(stderr, "%s", cmd_i2cget_help_add_s);
+}
+#else
+#define cmd_i2get_help()
+#endif
+
+/**
+ * @brief  confirm if user can really proceed without badly hurting..
+ *
+ * @param filename
+ * @param address
+ * @param size
+ * @param daddress
+ * @param pec
+ *
+ * @return 0 if dont proceed, 1 if ok to go ahead
+ */
+static int confirm_get(const char *filename, int address, int size,
+                      int daddress, int pec)
+{
+       /* Don't let the user break his/her EEPROMs */
+       if (address >= 0x50 && address <= 0x57 && pec) {
+               fprintf(stderr, "STOP! EEPROMs are I2C devices, not "
+                       "SMBus devices. Using PEC\non I2C devices may "
+                       "result in unexpected results, such as\n"
+                       "trashing the contents of EEPROMs. We can't "
+                       "let you do that, sorry.\n");
+               return 0;
+       }
+
+       return 1;
+}
+
+/**
+ * @brief read from I2C chip registers
+ *
+ * @param cmdtp
+ * @param argc
+ * @param argv
+ *
+ * @return
+ */
+static int do_cmd_i2c_get(cmd_tbl_t *cmdtp, int argc, char *argv[])
+{
+       char *end;
+       int res, i2cbus, address, size, file = -1;
+       int daddress;
+       char filename[PATH_MAX];
+       int pec = 0;
+       int flags = 0;
+       int force = 0, yes = 0;
+
+       /* handle (optional) flags first */
+       while (1 + flags < argc && argv[1 + flags][0] == '-') {
+               switch (argv[1 + flags][1]) {
+               case 'f':
+                       force = 1;
+                       break;
+               case 'y':
+                       yes = 1;
+                       break;
+               default:
+                       fprintf(stderr, "Error: Unsupported option "
+                               "\"%s\"!\n", argv[1 + flags]);
+                       goto quit_i2cget;
+               }
+               flags++;
+       }
+
+       if (argc < flags + 3) {
+               fprintf(stderr, "Error: Not enough args\n");
+               goto quit_i2cget;
+       }
+
+       i2cbus = lookup_i2c_bus(argv[flags + 1]);
+       if (i2cbus < 0) {
+               fprintf(stderr, "Error: Bad bus!\n");
+               goto quit_i2cget;
+       }
+
+       address = parse_i2c_address(argv[flags + 2]);
+       if (address < 0) {
+               fprintf(stderr, "Error: Bad address!\n");
+               goto quit_i2cget;
+       }
+
+       if (argc > flags + 3) {
+               size = I2C_SMBUS_BYTE_DATA;
+               daddress = simple_strtol(argv[flags + 3], &end, 0);
+               if (*end || daddress < 0 || daddress > 0xff) {
+                       fprintf(stderr, "Error: Data address invalid!\n");
+                       goto quit_i2cget;
+               }
+       } else {
+               size = I2C_SMBUS_BYTE;
+               daddress = -1;
+       }
+
+       if (argc > flags + 4) {
+               switch (argv[flags + 4][0]) {
+               case 'b':
+                       size = I2C_SMBUS_BYTE_DATA;
+                       break;
+               case 'w':
+                       size = I2C_SMBUS_WORD_DATA;
+                       break;
+               case 'c':
+                       size = I2C_SMBUS_BYTE;
+                       break;
+               default:
+                       fprintf(stderr, "Error: Invalid mode!\n");
+                       goto quit_i2cget;
+               }
+               pec = argv[flags + 4][1] == 'p';
+       }
+
+       file = open_i2c_dev(i2cbus, filename, 0);
+       if (file < 0 || check_funcs(file, size, daddress, pec)
+           || set_slave_addr(file, address, force))
+               goto quit_i2cget;
+
+       if (!yes && !confirm_get(filename, address, size, daddress, pec)) {
+               res = 0;
+               goto ret1;
+       }
+
+       if (pec && ioctl(file, I2C_PEC, (void *)1) < 0) {
+               perror(filename);
+               fprintf(stderr, "Error: Could not set PEC\n");
+               goto quit_i2cget;
+       }
+
+       switch (size) {
+       case I2C_SMBUS_BYTE:
+               res = read_i2c(file, address, daddress, 1, NULL, 0);
+               break;
+       default:
+               {
+                       u16 new_val;
+                       res =
+                           read_i2c(file, address, daddress, 1,
+                                    (u8 *) &new_val,
+                                    (size == I2C_SMBUS_WORD_DATA) ? 2 : 1);
+                       if (res >= 0)
+                               res = new_val;
+               }
+       }
+ret1:
+       close(file);
+
+       if (res < 0) {
+               fprintf(stderr, "Error: Read failed\n");
+               return 2;
+       }
+
+       printf("0x%0*x\n", size == I2C_SMBUS_WORD_DATA ? 4 : 2, res);
+
+       return 0;
+
+quit_i2cget:
+       cmd_i2get_help();
+       if (file >= 0)
+               close(file);
+       return 1;
+}
+
+U_BOOT_CMD_START(i2cget)
+    .maxargs = 7,
+    .cmd = do_cmd_i2c_get,
+    .usage = "program to read an I2C register",
+    U_BOOT_CMD_HELP(cmd_i2cget_help_s)
+U_BOOT_CMD_END
+#endif                         /* CONFIG_CMD_I2C_GET */
+
+#ifdef CONFIG_CMD_I2C_SET
+static const __maybe_unused char cmd_i2cset_help_s[] =
+    "Usage: i2cset [-y] [-f] I2CBUS CHIP-ADDRESS  DATA-ADDRESS [VALUE"
+    " [MODE [MASK]]]\n"
+    "Where:\n"
+    "  -y : will allow to set 0x50 to 0x57 with pec enabled\n"
+    "  -f : Force set the slave address\n"
+    "I2CBUS is an integer representing the bus index\n"
+    "  these are present as 'xx' of /dev/" I2C_DEV_NAME
+    "xx\n"
+    "CHIP-ADDRESS is an integer representing device address (0x03 - 0x77)\n"
+    "DATA-ADDRESS is an integer representing register on chip.\n"
+    "  (0x00 - 0xFF).\n"
+    "VALUE is the value to be written, if ignored, an short write is issued.\n"
+    "MODE is one of:\n"
+    "  b (read byte data, default)\n"
+    "  w (read word data)\n"
+    "  Append p for PEC\n"
+    "MASK if specified,describes which bits of value will be actually written\n"
+    "WARN:\n" "i2cset can be extremely dangerous if used improperly.\n";
+
+#ifdef CONFIG_LONGHELP
+static const __maybe_unused char cmd_i2cset_help_add_s[] =
+    "It can confuse "
+    "your I2C bus, cause data loss, or have more serious side effects.\n"
+    "Writing to a serial EEPROM on a memory DIMM (chip addresses between\n"
+    "0x50 and 0x57) may DESTROY your memory, leaving your system unbootable!\n"
+    "Be extremely careful using this program.\n";
+static void cmd_i2set_help(void)
+{
+       fprintf(stderr, "%s", cmd_i2cset_help_s);
+       fprintf(stderr, "%s", cmd_i2cset_help_add_s);
+}
+#else
+#define cmd_i2set_help()
+#endif
+
+/**
+ * @brief confirm we can write to the reg without killing the user
+ *
+ * @param filename
+ * @param address
+ * @param size
+ * @param daddress
+ * @param value
+ * @param vmask
+ * @param pec
+ *
+ * @return
+ */
+static int confirm_set(const char *filename, int address, int size,
+                      int daddress, int value, int vmask, int pec)
+{
+       if (address >= 0x50 && address <= 0x57) {
+               fprintf(stderr, "DANGEROUS! Writing to a serial "
+                       "EEPROM on a memory DIMM\nmay render your "
+                       "memory USELESS and make your system " "UNBOOTABLE!\n");
+               return 0;
+       }
+       return 1;
+}
+
+/**
+ * @brief set I2C registers
+ *
+ * @param cmdtp
+ * @param argc
+ * @param argv
+ *
+ * @return
+ */
+static int do_cmd_i2c_set(cmd_tbl_t *cmdtp, int argc, char *argv[])
+{
+       char *end;
+       int res, i2cbus, address, size, file = -1;
+       int value, daddress, vmask = 0;
+       char filename[PATH_MAX];
+       int pec = 0;
+       int flags = 0;
+       int force = 0, yes = 0;
+
+       /* handle (optional) flags first */
+       while (1 + flags < argc && argv[1 + flags][0] == '-') {
+               switch (argv[1 + flags][1]) {
+               case 'f':
+                       force = 1;
+                       break;
+               case 'y':
+                       yes = 1;
+                       break;
+               default:
+                       fprintf(stderr, "Error: Unsupported option "
+                               "\"%s\"!\n", argv[1 + flags]);
+                       goto quit_i2cset;
+               }
+               flags++;
+       }
+
+       if (argc < flags + 4) {
+               fprintf(stderr, "Error: Not enough arguments\n");
+               goto quit_i2cset;
+       }
+
+       i2cbus = lookup_i2c_bus(argv[flags + 1]);
+       if (i2cbus < 0) {
+               fprintf(stderr, "Error: Invalid Bus!\n");
+               goto quit_i2cset;
+       }
+
+       address = parse_i2c_address(argv[flags + 2]);
+       if (address < 0) {
+               fprintf(stderr, "Error: Invalid address!\n");
+               goto quit_i2cset;
+       }
+
+       daddress = simple_strtol(argv[flags + 3], &end, 0);
+       if (*end || daddress < 0 || daddress > 0xff) {
+               fprintf(stderr, "Error: Data address invalid!\n");
+               goto quit_i2cset;
+       }
+
+       if (argc > flags + 4) {
+               size = I2C_SMBUS_BYTE_DATA;
+               value = simple_strtol(argv[flags + 4], &end, 0);
+               if (*end || value < 0) {
+                       fprintf(stderr, "Error: Data value invalid!\n");
+                       goto quit_i2cset;
+               }
+       } else {
+               size = I2C_SMBUS_BYTE;
+               value = -1;
+       }
+
+       if (argc > flags + 5) {
+               switch (argv[flags + 5][0]) {
+               case 'b':
+                       size = I2C_SMBUS_BYTE_DATA;
+                       break;
+               case 'w':
+                       size = I2C_SMBUS_WORD_DATA;
+                       break;
+               default:
+                       fprintf(stderr, "Error: Invalid mode!\n");
+                       goto quit_i2cset;
+               }
+               pec = argv[flags + 5][1] == 'p';
+       }
+
+       if (argc > flags + 6) {
+               vmask = simple_strtol(argv[flags + 6], &end, 0);
+               if (*end || vmask == 0) {
+                       fprintf(stderr, "Error: Data value mask invalid!\n");
+                       goto quit_i2cset;
+               }
+       }
+
+       if ((size == I2C_SMBUS_BYTE_DATA && value > 0xff)
+           || (size == I2C_SMBUS_WORD_DATA && value > 0xffff)) {
+               fprintf(stderr, "Error: Data value out of range!\n");
+               goto quit_i2cset;
+       }
+
+       file = open_i2c_dev(i2cbus, filename, 0);
+       if (file < 0 || check_funcs(file, size, daddress, pec)
+           || set_slave_addr(file, address, force))
+               goto quit_i2cset;
+
+       if (!yes && !confirm_set(filename, address, size, daddress,
+                                value, vmask, pec)) {
+               close(file);
+               return 0;
+       }
+
+       if (vmask) {
+               int oldvalue;
+               u16 dat;
+               oldvalue =
+                   read_i2c(file, address, daddress, 1, (u8 *) &dat,
+                            (size == I2C_SMBUS_WORD_DATA) ? 2 : 1);
+
+               if (oldvalue < 0) {
+                       fprintf(stderr, "Error: Failed to read old value\n");
+                       goto quit_i2cset;
+               }
+               oldvalue = dat;
+
+               value = (value & vmask) | (oldvalue & ~vmask);
+
+               fprintf(stderr, "Old value 0x%0*x, write mask "
+                       "0x%0*x: Will write 0x%0*x to register "
+                       "0x%02x\n",
+                       size == I2C_SMBUS_WORD_DATA ? 4 : 2, oldvalue,
+                       size == I2C_SMBUS_WORD_DATA ? 4 : 2, vmask,
+                       size == I2C_SMBUS_WORD_DATA ? 4 : 2, value, daddress);
+
+       }
+
+       if (pec && ioctl(file, I2C_PEC, (void *)1) < 0) {
+               perror(filename);
+               fprintf(stderr, "Error: Could not set PEC\n");
+               goto quit_i2cset;
+       }
+
+       switch (size) {
+       case I2C_SMBUS_BYTE:
+               res = write_i2c(file, address, daddress, 1, NULL, 0);
+               break;
+       default:
+               res =
+                   write_i2c(file, address, daddress, 1,
+                             (u8 *) &value,
+                             (size == I2C_SMBUS_WORD_DATA) ? 2 : 1);
+       }
+       if (res < 0) {
+               fprintf(stderr, "Error: Write failed\n");
+               goto quit_i2cset;
+       }
+
+       if (pec) {
+               if (ioctl(file, I2C_PEC, (void *)0) < 0) {
+                       perror(filename);
+                       fprintf(stderr, "Error: Could not clear PEC\n");
+                       goto quit_i2cset;
+               }
+       }
+
+       switch (size) {
+       case I2C_SMBUS_BYTE:
+               /* No readback */
+               break;
+       default:
+               {
+                       u16 new_val;
+                       res =
+                           read_i2c(file, address, daddress, 1,
+                                    (u8 *) &new_val,
+                                    (size == I2C_SMBUS_WORD_DATA) ? 2 : 1);
+                       if (res >= 0)
+                               res = new_val;
+               }
+       }
+       close(file);
+
+       if (size == I2C_SMBUS_BYTE)     /* We're done */
+               return 0;
+
+       if (res < 0) {
+               printf("Warning - readback failed\n");
+       } else if (res != value) {
+               printf("Warning - data mismatch - wrote "
+                      "0x%0*x, read back 0x%0*x\n",
+                      size == I2C_SMBUS_WORD_DATA ? 4 : 2, value,
+                      size == I2C_SMBUS_WORD_DATA ? 4 : 2, res);
+       } else {
+               printf("Value 0x%0*x written, readback matched\n",
+                      size == I2C_SMBUS_WORD_DATA ? 4 : 2, value);
+       }
+
+       return 0;
+quit_i2cset:
+       if (file >= 0)
+               close(file);
+       cmd_i2set_help();
+       return 1;
+}
+
+U_BOOT_CMD_START(i2cset)
+    .maxargs = 8,
+    .cmd = do_cmd_i2c_set,
+    .usage = "program to write an I2C register",
+    U_BOOT_CMD_HELP(cmd_i2cset_help_s)
+U_BOOT_CMD_END
+#endif                         /* CONFIG_CMD_I2C_SET */
#21 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

Quoted 8 lines · In message <[email protected]> you…

Introduce I2c commands from i2c-tools. This allows for Diagnostics capability. Supports ONLY i2c busses at the moment.

This code is based on
http://www.lm-sensors.org/wiki/I2CTools
This closely follows the functionality, options and man page documentation

Please indent by TABs.

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Diplomacy is the art of saying "nice doggy" until you can find a rock.
#22 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

Wolfgang,

Quoted 8 lines

-----Original Message-----
From: wd at denx.de [mailto:wd at denx.de]
Sent: Thursday, June 19, 2008 3:33 PM
To: Menon, Nishanth
Cc: Sascha Hauer; u-boot-users at lists.sourceforge.net
Subject: Re: [U-Boot-Users] [Patch 5/9]U-boot-V2:cmd: add I2C commands

Please indent by TABs.

Is'nt checkpatch supposed to catch such issues?
I do get 10 warning all of the nature of:

WARNING: consider using strict_strtol in preference to simple_strtol #1167: FILE: commands/i2c.c:1145:
+ vmask = simple_strtol(argv[flags + 6], &end, 0);

But there are no tab warnings. Since we don't have strict_strol, I have Ignored this warning for u-boot v2.

Regards,
Nishanth Menon

#23 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

Quoted 3 lines · In message <[email protected]> you…
Quoted 2 lines

Please indent by TABs.

Is'nt checkpatch supposed to catch such issues?

IIRC it catches only indentations >= 8 columns.

Best regards,

Wolfgang Denk

Signature · 6 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
The perversity of nature is nowhere better demonstrated by  the  fact
that,  when  exposed to the same atmosphere, bread becomes hard while
crackers become soft.
#24 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

In reply to Menon
Quoted 8 lines · Nishanth

Introduce I2c commands from i2c-tools. This allows for Diagnostics capability. Supports ONLY i2c busses at the moment.

This code is based on
http://www.lm-sensors.org/wiki/I2CTools
This closely follows the functionality, options and man page documentation

Some overall comments first.

You seem to register a device for each bus and do all access to slave devices through the bus. It would be better if we register a new device for each slave device. Slave devices could either be hardwired by a board setup or, if the board maintainer or user is brave, through an autodetect mechanism.
Once we have a device for each slave most of this patch can be removed since you can use the generic md/mm commands for reading registers. In the device tree this could look like this:

/dev/i2cbus0 # bus 0

	/dev/i2cbus0_50 	# device 0x50 on bus 0...
		/dev/eeprom0	# which happens to be an eeprom

Please resist to introduce a new command for each type of device.

more inline...

Sascha

Quoted 273 lines
---
 commands/i2c.c | 1268 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1268 insertions(+)

Index: u-boot-v2.git/commands/i2c.c
===================================================================

commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +261 -0
@@ -0,0 +1,1268 @@
+/**
+ * @file
+ * @brief I2C related applications
+ *
+ * FileName: commands/i2c.c
+ * This provides i2cdump, i2cdetect, i2cset and i2cget appplications
+ * The code originates from the i2c-tools located here:
+ * http://www.lm-sensors.org/wiki/I2CTools
+ *
+ * This file merges the userspace headers and applications to a single
+ * entity as we do not maintain a userspace/kernel space isolation
+ *
+ * NOTE: 10-bit addresses are NOT supported!
+ */
+/*
+ * (C) Copyright 2006-2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <[email protected]>
+ *
+ * This application is based on the following:
+ *
+ * i2cbusses: Print the installed i2c busses for both 2.4 and 2.6 kernels.
+ *            Part of user-space programs to access for I2C
+ *            devices.
+ * Copyright (c) 1999-2003  Frodo Looijaard <[email protected]> and
+ *                          Mark D. Studebaker <[email protected]>
+ * Copyright (C) 2008       Jean Delvare <[email protected]>
+ * i2cdump.c - a user-space program to dump I2C registers
+ * Copyright (C) 2002-2003  Frodo Looijaard <[email protected]>, and
+ *                          Mark D. Studebaker <[email protected]>
+ * Copyright (C) 2004-2008  Jean Delvare <[email protected]>
+ * i2cget.c - A user-space program to read an I2C register.
+ * Copyright (C) 2005-2008  Jean Delvare <[email protected]>
+ * i2cset.c - A user-space program to write an I2C register.
+ * Copyright (C) 2001-2003  Frodo Looijaard <[email protected]>, and
+ *                          Mark D. Studebaker <[email protected]>
+ * Copyright (C) 2004-2008  Jean Delvare <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <types.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <fs.h>
+#include <errno.h>
+#include <linux/stat.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include "i2c.h"
+
+#define MISSING_FUNC_FMT "Error: Adapter does not have %s capability\n"
+
+/*************** Lib Functions *************/
+
+/**
+ * @brief Parse an I2CBUS command line argument
+ *
+ * @param i2cbus_arg arg to busparam
+ *
+ * @return the corresponding bus number,
+ * or a negative value if the bus is invalid.
+ */
+int lookup_i2c_bus(const char *i2cbus_arg)
+{
+       long i2cbus;
+       char *end;
+
+       if (i2cbus_arg == NULL) {
+               fprintf(stderr, "no bus arg! expect 0-9\n");
+               return -1;
+       }
+       if (strlen(i2cbus_arg) > 2) {
+               fprintf(stderr, "bad bus arg! expect 0-9 saw %s\n", i2cbus_arg);
+               return -2;
+       }
+       i2cbus = simple_strtol(i2cbus_arg, &end, 0);
+       if ((*i2cbus_arg != '0') && (i2cbus == 0)) {
+               fprintf(stderr, "bad bus arg! expect 0-9, saw %s\n",
+                       i2cbus_arg);
+               return -2;
+       }
+       if (i2cbus < 0 || i2cbus > 0xff) {
+               fprintf(stderr, "Error: I2C bus out of range (0-255)!\n");
+               return -3;
+       }
+
+       return i2cbus;
+}
+
+/**
+ * @brief open a given i2cdevice
+ *
+ * @param i2cbus bus index
+ * @param filename return the devfs filename for the bus
+ * @param quiet be silent?
+ *
+ * @return return value of open
+ */
+int open_i2c_dev(const int i2cbus, char *filename, const int quiet)
+{
+       int file;
+
+       sprintf(filename, "/dev/" I2C_DEV_NAME "%d", i2cbus);
+       file = open(filename, O_RDWR);
+
+       if (file < 0 && !quiet) {
+               perror(filename);
+               fprintf(stderr, "Error: Could not open file "
+                       "`%s'\n", filename);
+       }
+
+       return file;
+}
+
+/**
+ * @brief Parse a CHIP-ADDRESS command line argument
+ *
+ * @param address_arg -user provided argument
+ *
+ * @return The corresponding chip address,
+ *          or a negative value if the address is invalid.
+ */
+int parse_i2c_address(const char *address_arg)
+{
+       long address;
+       char *end;
+
+       address = simple_strtol(address_arg, &end, 0);
+       if (*end || !*address_arg) {
+               fprintf(stderr, "Error: Chip address is not a number!\n");
+               return -1;
+       }
+       if (address < 0x03 || address > 0x77) {
+               fprintf(stderr, "Error: Chip address out of range "
+                       "(0x03-0x77)!\n");
+               return -2;
+       }
+
+       return address;
+}
+
+/**
+ * @brief force the slave address
+ *
+ * @param file file id
+ * @param address address to set
+ * @param force force address
+ *
+ * @return returns result of ioctl
+ */
+int set_slave_addr(int file, int address, int force)
+{
+       /* With force, let the user read from/write to the registers
+          even when a driver is also running */
+       if (ioctl(file, force ? I2C_SLAVE_FORCE : I2C_SLAVE, (void *)address) <
+           0) {
+               perror(NULL);
+               fprintf(stderr,
+                       "Error: Could not set address to 0x%02x\n", address);
+               return -errno;
+       }
+
+       return 0;
+}
+
+/**
+ * @brief check functionality of the adapter
+ *
+ * @param file file index
+ * @param size size of the same
+ * @param daddress device address
+ * @param pec pec
+ *
+ * @return result of ioctl check negative if failed
+ */
+int check_funcs(int file, int size, int daddress, int pec)
+{
+       unsigned long funcs;
+
+       /* check adapter functionality */
+       if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
+               perror(NULL);
+               fprintf(stderr, "Error: Could not get the adapter "
+                       "functionality matrix\n");
+               return -1;
+       }
+
+       if (!(funcs & I2C_FUNC_I2C)) {
+               fprintf(stderr, MISSING_FUNC_FMT, "I2C support");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int read_i2c(int file, uchar daddr, u16 addr, u8 reg_width, char *buffer,
+            size_t count)
+{
+       struct i2c_msg msg[2] = {
+               {daddr, 0, reg_width, (u8 *) &addr},
+               {daddr, 0 | I2C_M_RD, count, buffer}
+       };
+       struct i2c_rdwr_ioctl_data data = {
+               .msgs = msg,
+               .nmsgs = 2,
+       };
+       return ioctl(file, I2C_RDWR, &data);
+}
+
+int write_i2c(int file, uchar daddr, u16 addr, u8 reg_width, char *buffer,
+             size_t count)
+{
+       unsigned char *temp_buf;
+       struct i2c_msg msg = { daddr, 0, count + reg_width, NULL };
+       struct i2c_rdwr_ioctl_data data = {
+               .msgs = &msg,
+               .nmsgs = 1,
+       };
+       int ret;
+       temp_buf = malloc(count + reg_width);
+       if (temp_buf == NULL)
+               return -ENOMEM;
+       memcpy(temp_buf, &addr, reg_width);
+       memcpy(temp_buf + reg_width, buffer, count);
+       msg.buf = temp_buf;
+       ret = ioctl(file, I2C_RDWR, &data);
+       free(temp_buf);
+       return ret;
+}
+
+/****************** Test implementations **************/
+#ifdef CONFIG_CMD_I2C_DETECT
+
+#define MODE_AUTO      0
+#define MODE_QUICK     1
+#define MODE_READ      2
+#define MODE_FUNC      3
+
+static const __maybe_unused char cmd_i2cdetect_help_s[] =
+    "Usage:\n"
+    "a) i2cdetect [-a] [-q|-r] I2CBUS [FIRST LAST]\n"
+    "Where:\n"
+    "  -a : all addresses (default scans from 0x03 - 0x77)\n"

commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 line 271

Quoted 10 lines
commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +10 -0
+    "  -q : use write-risky at times\n"
+    "  -r : use read-risky at times\n"
+    "  If provided, FIRST and LAST limit the probing range.\n"
+    "b) i2cdetect -F I2CBUS\n"
+    "Where:\n"
+    "  -F : Show functionality of the device\n"
+    "\n"
+    "I2CBUS is an integer representing the bus index\n"
+    "these are present as 'xx' of /dev/" I2C_DEV_NAME
+    "xx\n" "WARN:\n"

This requires documentation and implementation. Why not -f <filename>?

commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 line 281

Quoted 10 lines
commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +10 -0
+    "This program can confuse your I2C bus, cause data loss and worse!\n";
+
+#ifdef CONFIG_LONGHELP
+static void cmd_i2cdetect_help(void)
+{
+       fprintf(stderr, "%s", cmd_i2cdetect_help_s);
+}
+#else
+#define cmd_i2cdetect_help()
+#endif

You do not need this ifdef...

Quoted 143 lines
commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +143 -0
+
+/**
+ * @brief scan the i2c bus
+ *
+ * @param file file index
+ * @param mode what mode to scan it with
+ * @param first start address
+ * @param last end address
+ *
+ * @return negative if scan failed, else return 0
+ */
+static int scan_i2c_bus(int file, int mode, int first, int last)
+{
+       int i, j;
+       int res;
+       unsigned char dummy = 0x0;
+
+       printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n");
+
+       for (i = 0; i < 128; i += 16) {
+               printf("%02x: ", i);
+               for (j = 0; j < 16; j++) {
+
+                       /* Skip unwanted addresses */
+                       if (i + j < first || i + j > last) {
+                               printf("   ");
+                               continue;
+                       }
+
+                       /* Set slave address */
+                       if (ioctl(file, I2C_SLAVE, (void *)(i + j)) < 0) {
+                               if (errno == EBUSY) {
+                                       printf("UU ");
+                                       continue;
+                               } else {
+                                       perror(NULL);
+                                       fprintf(stderr, "Error: Could not set "
+                                               "address to 0x%02x\n", i + j);
+                                       return -1;
+                               }
+                       }
+
+                       /* Probe this address */
+                       switch (mode) {
+                       case MODE_QUICK:
+                               /* Attempt a 0 byte write -can lock up many
+                                * devices */
+                               res = write_i2c(file, i + j, 0x0, 1, NULL, 0);
+                               break;
+                       case MODE_READ:
+                               /* This is known to lock on various
+                                  write-only chips (mainly clock chips) */
+                               res = read_i2c(file, i + j, 0x0, 1, &dummy, 1);
+                               break;
+                       default:
+                               if ((i + j >= 0x30 && i + j <= 0x37)
+                                   || (i + j >= 0x50 && i + j <= 0x5F))
+                                       res =
+                                           read_i2c(file, i + j, 0x0, 1,
+                                                    &dummy, 1);
+                               else
+                                       res =
+                                           write_i2c(file, i + j, 0x0, 1, NULL,
+                                                     0);
+                       }
+
+                       if (res < 0)
+                               printf("-- ");
+                       else
+                               printf("%02x ", i + j);
+               }
+               printf("\n");
+       }
+
+       return 0;
+}
+
+struct func {
+       long value;
+       const char *name;
+};
+
+static const struct func all_func[] = {
+       {.value = I2C_FUNC_I2C,
+        .name = "I2C"},
+       {.value = 0,
+        .name = ""}
+};
+
+/**
+ * @brief print the functionality of the adapter
+ *
+ * @param funcs the ioctl returned value
+ *
+ * @return none
+ */
+static void print_functionality(unsigned long funcs)
+{
+       int i;
+       for (i = 0; all_func[i].value; i++) {
+               printf("%-32s %s\n", all_func[i].name,
+                      (funcs & all_func[i].value) ? "yes" : "no");
+       }
+}
+
+static int do_cmd_i2c_detect(cmd_tbl_t *cmdtp, int argc, char *argv[])
+{
+       char *end;
+       int i2cbus, file = 0, res = 0;
+       char filename[PATH_MAX];
+       unsigned long funcs;
+       int mode = MODE_AUTO;
+       int first = 0x03, last = 0x77;
+       int flags = 0;
+
+       /* handle (optional) flags first */
+       while (1 + flags < argc && argv[1 + flags][0] == '-') {
+               switch (argv[1 + flags][1]) {
+               case 'F':
+                       if (mode != MODE_AUTO && mode != MODE_FUNC) {
+                               fprintf(stderr, "Error: Different modes "
+                                       "specified!\n");
+                               goto quit_i2cdetect;
+                       }
+                       mode = MODE_FUNC;
+                       break;
+               case 'r':
+                       if (mode == MODE_QUICK) {
+                               fprintf(stderr, "Error: Different modes "
+                                       "specified!\n");
+                               goto quit_i2cdetect;
+                       }
+                       mode = MODE_READ;
+                       break;
+               case 'q':
+                       if (mode == MODE_READ) {
+                               fprintf(stderr, "Error: Different modes "
+                                       "specified!\n");
+                               goto quit_i2cdetect;
+                       }
+                       mode = MODE_QUICK;
+                       break;
+               case 'a':

commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 line 434

Quoted 10 lines
commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +10 -0
+                       first = 0x00;
+                       last = 0x7F;
+                       break;
+               default:
+                       fprintf(stderr, "Error: Unsupported option "
+                               "\"%s\"!\n", argv[1 + flags]);
+                       goto quit_i2cdetect;
+               }
+               flags++;
+       }

Please use getopt instead.

Quoted 63 lines
commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +63 -0
+
+       if (argc < flags + 2) {
+               fprintf(stderr, "Error: No i2c-bus specified!\n");
+               goto quit_i2cdetect;
+       }
+       i2cbus = lookup_i2c_bus(argv[flags + 1]);
+       if (i2cbus < 0) {
+               fprintf(stderr, "Error: bus not found!\n");
+               goto quit_i2cdetect;
+       }
+
+       /* read address range if present */
+       if (argc == flags + 4 && mode != MODE_FUNC) {
+               int tmp;
+
+               tmp = simple_strtol(argv[flags + 2], &end, 0);
+               if (*end) {
+                       fprintf(stderr, "Error: FIRST argment not a "
+                               "number!\n");
+                       goto quit_i2cdetect;
+               }
+               if (tmp < first || tmp > last) {
+                       fprintf(stderr, "Error: FIRST argument out of range "
+                               "(0x%02x-0x%02x)!\n", first, last);
+                       goto quit_i2cdetect;
+               }
+               first = tmp;
+
+               tmp = simple_strtol(argv[flags + 3], &end, 0);
+               if (*end) {
+                       fprintf(stderr, "Error: LAST argment not a "
+                               "number!\n");
+                       goto quit_i2cdetect;
+               }
+               if (tmp < first || tmp > last) {
+                       fprintf(stderr, "Error: LAST argument out of range "
+                               "(0x%02x-0x%02x)!\n", first, last);
+                       goto quit_i2cdetect;
+               }
+               last = tmp;
+       } else if (argc != flags + 2) {
+               goto quit_i2cdetect;
+       }
+
+       file = open_i2c_dev(i2cbus, filename, 0);
+       if (file < 0)
+               return 1;
+
+       res = 1;
+       if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
+               perror(filename);
+               fprintf(stderr, "Error: Could not get the adapter "
+                       "functionality matrix\n");
+               goto ret;
+       }
+
+       /* Special case, we only list the implemented functionalities */
+       if (mode == MODE_FUNC) {
+               printf("Functionalities implemented by %s:\n", filename);
+               print_functionality(funcs);
+               res = 0;
+               goto ret;
+       }

commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 line 507

Quoted 10 lines
commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +10 -0
+
+       res = scan_i2c_bus(file, mode, first, last);
+ret:
+       if (file >= 0)
+               close(file);
+       return res ? 1 : 0;
+
+quit_i2cdetect:
+       /* Exit after printing help */
+       cmd_i2cdetect_help();

If you want to print the help text here call u_boot_cmd_usage(cmdtp).

Quoted 64 lines
commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +64 -0
+       goto ret;
+}
+
+U_BOOT_CMD_START(i2cdetect)
+    .maxargs = 6,
+    .cmd = do_cmd_i2c_detect,
+    .usage = "program to scan for I2C devices",
+    U_BOOT_CMD_HELP(cmd_i2cdetect_help_s)
+U_BOOT_CMD_END
+#endif                         /* CONFIG_CMD_I2C_DETECT */
+
+#ifdef CONFIG_CMD_I2C_DUMP
+static const __maybe_unused char cmd_i2cdump_help_s[] =
+    "Usage: i2cdump [-f] [-r first-last] I2CBUS ADDRESS [MODE]\n"
+    "Where:\n"
+    " -f : Force set the slave address\n"
+    " -r : first-last the range of addresses which will be dumped\n"
+    "I2CBUS is an integer representing the bus index\n"
+    "  these are present as 'xx' of /dev/" I2C_DEV_NAME "xx\n"
+    "ADDRESS is an integer representing device address (0x03 - 0x77)\n"
+    "MODE is one of:\n"
+    "  b (byte, default)\n"
+    "  w (word)\n"
+    "  W (word on even register addresses)\n"
+    "  Append p for PEC\n"
+    "WARN: i2cdump can be dangerous if used improperly.\n";
+
+#ifdef CONFIG_LONGHELP
+static const __maybe_unused char cmd_i2c_ext_help_s[] =
+    "Most notably, the c mode "
+    "starts with WRITING a byte to the chip. On most chips it will be stored\n"
+    "in the address pointer register, which is OK, but some chips with a\n"
+    "single register or no (visible)register at all will most likely see this\n"
+    "as a real WRITE, resulting in possible misbehavior or corruption. Do not\n"
+    "use i2cdump on random addresses. Anyway, it is of little use unless you\n"
+    "have good knowledge of the chip you??(tm)re working with and an idea of \n"
+    "what you are looking for.\n";
+static void cmd_i2dump_help(void)
+{
+       fprintf(stderr, "%s", cmd_i2cdump_help_s);
+       fprintf(stderr, "%s", cmd_i2c_ext_help_s);
+}
+#else
+#define cmd_i2dump_help()
+#endif
+
+static int do_cmd_i2c_dump(cmd_tbl_t *cmdtp, int argc, char *argv[])
+{
+       char *end;
+       int i, j, res, i2cbus, address, size, file = -1;
+       char filename[PATH_MAX];
+       int block[256];
+       int pec = 0, even = 0;
+       int flags = 0;
+       int force = 0;
+       const char *range = NULL;
+       int first = 0x00, last = 0xff;
+
+       /* handle (optional) flags first */
+       while (1 + flags < argc && argv[1 + flags][0] == '-') {
+               switch (argv[1 + flags][1]) {
+               case 'f':
+                       force = 1;
+                       break;

commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 line 581

Quoted 10 lines
commands/i2c.c 2008-06-19 09:31:37.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +10 -0
+               case 'r':
+                       range = argv[1 + (++flags)];
+                       break;
+               default:
+                       fprintf(stderr, "Error: Unsupported option "
+                               "\"%s\"!\n", argv[1 + flags]);
+                       goto quit_i2cdump;
+               }
+               flags++;
+       }

getopt instead

<snip>

Signature · 4 lines
Pengutronix e.K. - Linux Solutions for Science and Industry
-----------------------------------------------------------
Kontakt-Informationen finden Sie im Header dieser Mail oder
auf der Webseite -> http://www.pengutronix.de/impressum/ <-
#25 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

Sascha,

Quoted 7 lines

-----Original Message-----
From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
Sent: Friday, June 20, 2008 5:29 AM
To: Menon, Nishanth
Cc: u-boot-users at lists.sourceforge.net
Subject: Re: [Patch 5/9]U-boot-V2:cmd: add I2C commands

Quoted 5 lines

Some overall comments first.

You seem to register a device for each bus and do all access to slave devices through the bus. It would be better if we register a new device for each slave device.

No. that is not a good strategy. Many reasons why not to do it as the cmds are a debug tool:
a) I am not interested in registering camera and all devices I may have in code. Yet, the handy little tool is good to do some basic debug of the device.
b) Every client behaves in a different way. Camera for example may follow CCI specification, in which case, they would have 8, 16 ,32 bit regs all in the same device. In fact it may be near impossible to write a generic driver for them all. We cannot predict what we want to do for every device out there.
c) Devices wanting to expose their own app may choose to do so. Yes, I get the comment:

Quoted 1 line

Please resist to introduce a new command for each type of device.

d) It is wasteful to generate multiple device nodes when someone smart enough to understand I2C specification will also know that the common denominator for all devices is the I2C bus.
e) Creating device node for each client node requires extensive client mechanism in I2C which has no "use case" for me.
f) 7 bit addressing allows 127 devices, and I have 3 busses. 127*3 device nodes as a theoretical max is outrageous. When just 3 device nodes could have done the same job. In short, the common access mechanism of exposing the bus and allowing users to Do i2c accesses to the devices in the manner of choosing would be the most generic Method to do it. In fact U-Boot v1 also does something similar.

Quoted 10 lines

Slave devices could either be hardwired by a
board setup or, if the board maintainer or user is brave, through an autodetect mechanism.
Once we have a device for each slave most of this patch can be removed since you can use the generic md/mm commands for reading registers. In the device tree this could look like this:

/dev/i2cbus0                    # bus 0
        /dev/i2cbus0_50         # device 0x50 on bus 0...
                /dev/eeprom0    # which happens to be an eeprom

A) who would decide this would be a eeprom?
B) why should /dev/i2cbus0_50 be any different from /dev/eeprom?
C) you are looking at 3 different device nodes when a single one would suffice.

Note that complex development platforms like mine may have upto 30-40 devices on the bus. I have power monitoring ADC chips on buses which I really don?t care about during boot, yet May want to debug intermittently.

What do we achieve by introducing i2c device based nodes?

Will look at comments if we are aligned on this basic infrastructure. (overall I think the Rest of the comments are valid, even though I'd wish you'd stop putting the entire patch In the mail.. lots of scrolling down to reach your comment ;) )..

Regards,
Nishanth Menon

#26 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

Quoted 8 lines · Nishanth

Sascha,

Quoted 7 lines

-----Original Message-----
From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
Sent: Friday, June 20, 2008 5:29 AM
To: Menon, Nishanth
Cc: u-boot-users at lists.sourceforge.net
Subject: Re: [Patch 5/9]U-boot-V2:cmd: add I2C commands

Quoted 7 lines
Quoted 5 lines

Some overall comments first.

You seem to register a device for each bus and do all access to slave devices through the bus. It would be better if we register a new device for each slave device.

No. that is not a good strategy. Many reasons why not to do it as the cmds are a debug tool:

Just like md/mm are

Quoted 6 lines

a) I am not interested in registering camera and all devices I may have in code. Yet, the handy little tool is good to do some basic debug of the device.
b) Every client behaves in a different way. Camera for example may follow CCI specification, in which case, they would have 8, 16 ,32 bit regs all in the same device. In fact it may be near impossible to write a generic driver for them all. We cannot predict what we want to do for every device out there.

Lets see:

+int read_i2c(int file, uchar daddr, u16 addr, u8 reg_width, char *buffer,
+ size_t count)

+int write_i2c(int file, uchar daddr, u16 addr, u8 reg_width, char *buffer,
+ size_t count)

These arguments map nicely to md/mm

Quoted 6 lines

c) Devices wanting to expose their own app may choose to do so. Yes, I get the comment:

Quoted 1 line

Please resist to introduce a new command for each type of device.

d) It is wasteful to generate multiple device nodes when someone smart enough to understand I2C specification will also know that the common denominator for all devices is the I2C bus.

I do not understand why this is wasteful. It may be wasteful in terms of malloc space, but all boards I know have more than enough memory for the bootloader.

Quoted 4 lines

e) Creating device node for each client node requires extensive client mechanism in I2C which has no "use case" for me.
f) 7 bit addressing allows 127 devices, and I have 3 busses. 127*3 device nodes as a theoretical max is outrageous. When just 3 device nodes could have done the same job.

I did not mean for every possible device but for each device that is actually present, or even from the present ones only the ones which are of use for u-boot.
If you want to access a device which you know is present but U-Boot does not know about it, then add a command like

i2c add /dev/i2cbus0 0x50

which would create the device node that you need to access device 0x50 on i2cbus0.

Quoted 12 lines

In short, the common access mechanism of exposing the bus and allowing users to Do i2c accesses to the devices in the manner of choosing would be the most generic Method to do it. In fact U-Boot v1 also does something similar.

Quoted 7 lines

Slave devices could either be hardwired by a
board setup or, if the board maintainer or user is brave, through an autodetect mechanism.
Once we have a device for each slave most of this patch can be removed since you can use the generic md/mm commands for reading registers. In the device tree this could look like this:

Quoted 4 lines
Quoted 3 lines
/dev/i2cbus0                    # bus 0
        /dev/i2cbus0_50         # device 0x50 on bus 0...
                /dev/eeprom0    # which happens to be an eeprom

A) who would decide this would be a eeprom?

The board setup code in this case as eeproms are not probable.

Quoted 1 line

B) why should /dev/i2cbus0_50 be any different from /dev/eeprom?

issuing md on /dev/i2cbus0_50 would let you read the registers of the chip, which of course happen to be the contents of the eeprom, so this might be a bad example. Consider an A/D converter; reading /dev/i2cbus0_xy would give you the register space while /dev/adxy would give you the digital values (provided a client driver is present). Thus /dev/adxy would require a driver whereas /dev/i2cbus0_xy does not.

Quoted 7 lines

C) you are looking at 3 different device nodes when a single one would suffice.

Note that complex development platforms like mine may have upto 30-40 devices on the bus. I have power monitoring ADC chips on buses which I really don???t care about during boot, yet May want to debug intermittently.

What do we achieve by introducing i2c device based nodes?

- An overview over the system for those who are not familiar with it. You may know the devices that are connected to the bus on your board, I don't. One of the benefits in U-Boot-V2 for me is that many different systems behave similarly although they have a very different hardware.
- when md/mm are usable on a device it also means that cp/memcmp/cat or any other file command is usable.
- reduction in code size since you can reuse what's already there (like file commands instead of new commands). That's one of the points that make U-Boot-V1 bigger than it has to be.

Quoted 4 lines

Will look at comments if we are aligned on this basic infrastructure. (overall I think the Rest of the comments are valid, even though I'd wish you'd stop putting the entire patch In the mail.. lots of scrolling down to reach your comment ;) )..

You are lucky, I already had to remove some lines as I hit the list limit ;)

Regards,
Sascha

Signature · 4 lines
Pengutronix e.K. - Linux Solutions for Science and Industry
-----------------------------------------------------------
Kontakt-Informationen finden Sie im Header dieser Mail oder
auf der Webseite -> http://www.pengutronix.de/impressum/ <-
#27 lore raw

PATCH 4/9 U-boot-V2:I2C: Introduce i2c-dev

I2C by default does not expose a device interface for the adapters registering in the system. This is usually not needed unless we need to debug something. in which case, this is a handy little layer when used in conjunction with the i2c commands. This layer has changed

This is based on the discussion here:
http://www.nabble.com/-Patch-0-9--U-boot-V2%3A-
Introduce-I2C-support-for-SDP3430-to17981717.html
#a18029740

Patches 4 and 5 in the previous series have changed, 6 is redundant and removed from the series.

---
 drivers/i2c/Kconfig     |   10
 drivers/i2c/Makefile    |    1
 drivers/i2c/i2c-core.c  |   12
 drivers/i2c/i2c-core.h  |    4
 drivers/i2c/i2c-dev.c   |  813 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/i2c-dev.h |   43 ++
 6 files changed, 883 insertions(+)
include/linux/i2c-dev.h 2008-06-20 21:09:57.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +43 -0
Index: u-boot-v2.git/include/linux/i2c-dev.h
===================================================================
@@ -0,0 +1,43 @@
+/**
+ * @file
+ * @brief i2c-bus driver, "char device" interface
+ *
+ * FileName: include/linux/i2c-dev.h
+ *
+ */
+/* Originally from Linux kernel. Ported to U-boot-v2.
+ * (C) Copyright 2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <[email protected]>
+ */
+/*
+    Copyright (C) 1995-97 Simon G. Vogl
+    Copyright (C) 1998-99 Frodo Looijaard <[email protected]>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _LINUX_I2C_DEV_H
+#define _LINUX_I2C_DEV_H
+
+/* For command access */
+#define I2C_SLAVE_ADD  0x0703  /* Create a new slave device */
+#define I2C_SLAVE_REM  0x0706  /* Remove a new slave device */
+
+/******* For the platforms to use *********/
+int i2cdev_new(unsigned int, unsigned int);
+int i2cdev_remove(unsigned int, unsigned int);
+
+#endif /* _LINUX_I2C_DEV_H */
drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +813 -0

813 lines not on this page · raw message

drivers/i2c/Kconfig 2008-06-20 21:09:57.000000000 -0500 renamed from drivers/i2c/Kconfig 2008-06-20 21:09:55.000000000 -0500 +10 -0
Index: u-boot-v2.git/drivers/i2c/Kconfig
===================================================================
@@ -19,6 +19,16 @@
 
 if I2C
 
+config I2C_CHARDEV
+       tristate "I2C device interface"
+       help
+         Say Y here to use i2c-* device files, usually found in the /dev
+         directory on your system.  They make it possible to have applications
+         to use the I2C bus.
+
+         This support is also available as a module.  If so, the module
+         will be called i2c-dev.
+
 source drivers/i2c/busses/Kconfig
 
 config I2C_DEBUG_CORE
drivers/i2c/Makefile 2008-06-20 21:09:57.000000000 -0500 renamed from drivers/i2c/Makefile 2008-06-20 21:09:55.000000000 -0500 +1 -0
Index: u-boot-v2.git/drivers/i2c/Makefile
===================================================================
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_I2C)              += i2c-core.o
+obj-$(CONFIG_I2C_CHARDEV)      += i2c-dev.o
 obj-y                          += busses/
 
 ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
drivers/i2c/i2c-core.c 2008-06-20 21:09:57.000000000 -0500 renamed from drivers/i2c/i2c-core.c 2008-06-20 21:09:55.000000000 -0500 +12 -0
Index: u-boot-v2.git/drivers/i2c/i2c-core.c
===================================================================
@@ -102,6 +102,10 @@
 
        dev_dbg("adapter [%s] registered\n", adap->name);
 
+#ifdef CONFIG_I2C_CHARDEV
+       i2cdev_attach_adapter(adap);
+#endif
+
 out_unlock:
        return res;
 
@@ -222,6 +226,14 @@
                goto out_unlock;
        }
 
+#ifdef CONFIG_I2C_CHARDEV
+       res = i2cdev_detach_adapter(adap);
+       if (res) {
+               dev_err("adapter in use\n");
+               goto out_unlock;
+       }
+#endif
+
        /* detach any active clients. This must be done first, because
         * it can fail; in which case we give up. */
        list_for_each_safe(item, _n, &adap->clients) {
drivers/i2c/i2c-core.h 2008-06-20 21:09:57.000000000 -0500 renamed from drivers/i2c/i2c-core.h 2008-06-20 21:09:55.000000000 -0500 +4 -0
Index: u-boot-v2.git/drivers/i2c/i2c-core.h
===================================================================
@@ -34,4 +34,8 @@
 extern struct list_head        __i2c_board_list;
 extern int             __i2c_first_dynamic_bus_num;
 
+/* Automatically called by i2c-Core..*/
+int i2cdev_attach_adapter(struct i2c_adapter *adap);
+int i2cdev_detach_adapter(struct i2c_adapter *adap);
+
 #endif         /*  __i2C_CORE_H */
#28 lore raw

PATCH 4/9 U-boot-V2:I2C: Introduce i2c-dev

Quoted 147 lines · Nishanth

I2C by default does not expose a device interface for the adapters registering in the system. This is usually not needed unless we need to debug something. in which case, this is a handy little layer when used in conjunction with the i2c commands. This layer has changed

This is based on the discussion here:
http://www.nabble.com/-Patch-0-9--U-boot-V2%3A-
Introduce-I2C-support-for-SDP3430-to17981717.html
#a18029740

Patches 4 and 5 in the previous series have changed, 6 is redundant and removed from the series.

---
 drivers/i2c/Kconfig     |   10
 drivers/i2c/Makefile    |    1
 drivers/i2c/i2c-core.c  |   12
 drivers/i2c/i2c-core.h  |    4
 drivers/i2c/i2c-dev.c   |  813 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/i2c-dev.h |   43 ++
 6 files changed, 883 insertions(+)

Index: u-boot-v2.git/include/linux/i2c-dev.h
===================================================================

include/linux/i2c-dev.h 2008-06-20 21:09:57.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +43 -0
@@ -0,0 +1,43 @@
+/**
+ * @file
+ * @brief i2c-bus driver, "char device" interface
+ *
+ * FileName: include/linux/i2c-dev.h
+ *
+ */
+/* Originally from Linux kernel. Ported to U-boot-v2.
+ * (C) Copyright 2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <[email protected]>
+ */
+/*
+    Copyright (C) 1995-97 Simon G. Vogl
+    Copyright (C) 1998-99 Frodo Looijaard <[email protected]>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _LINUX_I2C_DEV_H
+#define _LINUX_I2C_DEV_H
+
+/* For command access */
+#define I2C_SLAVE_ADD  0x0703  /* Create a new slave device */
+#define I2C_SLAVE_REM  0x0706  /* Remove a new slave device */
+
+/******* For the platforms to use *********/
+int i2cdev_new(unsigned int, unsigned int);
+int i2cdev_remove(unsigned int, unsigned int);
+
+#endif /* _LINUX_I2C_DEV_H */

Index: u-boot-v2.git/drivers/i2c/i2c-dev.c
===================================================================

drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +67 -0
@@ -0,0 +1,813 @@
+/**
+ * @file
+ * @brief i2c-bus driver, "char device" interface
+ *
+ * FileName: drivers/i2c/i2c-dev.c
+ *
+ * It is very important to note the following:
+ * read to an i2cbus device is a 0 byte read operation. writes
+ * are not supported to i2cbus device.
+ *
+ * i2cdev devices on the other hand translate all read/write to
+ * 1 byte read/write operations as per i2c spec.
+ *
+ * Note: both of these can confuse certain devices on I2C bus.
+ * USE WITH CAUTION.
+ */
+/* Originally from Linux kernel. Ported to U-boot-v2.
+ * Note: even though we borrow i2c-dev from linux, there are
+ * major differences in operations.
+ *
+ * (C) Copyright 2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <[email protected]>
+ */
+/*
+    Copyright (C) 1995-97 Simon G. Vogl
+    Copyright (C) 1998-99 Frodo Looijaard <[email protected]>
+    Copyright (C) 2003 Greg Kroah-Hartman <[email protected]>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* Note that this is a complete rewrite of Simon Vogl's i2c-dev module.
+   But I have used so much of his original code and ideas that it seems
+   only fair to recognize him as co-author -- Frodo */
+
+#include <common.h>
+#include <errno.h>
+#include <list.h>
+#include <init.h>
+#include <driver.h>
+#include <malloc.h>
+#include <string.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+
+#include "i2c-core.h"
+
+#ifdef CONFIG_I2C_DEBUG_DEV
+#define DBG_MODULE_NAME "i2cdev"
+#define dev_dbg(ARGS...) fprintf(stdout, ARGS);
+#define dev_warn(ARGS...) fprintf(stderr, ARGS);
+#define dbg_entry(FORMAT, ARGS...) fprintf(stdout,\
+               DBG_MODULE_NAME"%s:%d:Entry:"FORMAT"\n",\
+               __func__, __LINE__, ARGS)

drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 line 77

Quoted 10 lines
drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +10 -0
+#define dbg_exit(FORMAT, ARGS...) fprintf(stdout,\
+               DBG_MODULE_NAME"%s:%d:Exit:"FORMAT"\n",\
+               __func__, __LINE__, ARGS)
+#else
+#define dev_dbg(ARGS...)
+#define dev_warn(ARGS...)
+#define dbg_entry(FORMAT, ARGS...)
+#define dbg_exit(FORMAT, ARGS...)
+#endif
+#define dev_err(ARGS...) fprintf(stderr, ARGS);

Note to self: We need a better set of debug macros. debug is ok, but the name is poorly chosen and not sufficient. Drivers shouldn't add their own macros.

Quoted 17 lines
drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +17 -0
+
+#define I2C_BUS_NAME "i2cbus"
+#define I2C_DEV_NAME "i2cdev"
+
+static struct i2c_driver i2cdev_driver;
+
+/**
+ * An i2c_bus represents an i2c_adapter ... an I2C or SMBus master, not a
+ * slave (i2c_client) with which messages will be exchanged.  It's coupled
+ * with a character special file which is accessed by user mode drivers.
+ *
+ */
+struct i2cdev_bus {
+       struct list_head list;
+       struct i2c_adapter *adap;
+       struct device_d dev;
+};

drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 line 104

Quoted 10 lines
drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +10 -0
+
+/**
+ * contains the internal structure for a device node this is the i2c device
+ */
+struct i2cdev_dev {
+       struct list_head list;
+       struct device_d dev;
+};
+
+#define I2C_MINORS     256

This seems to be an artificial limitation.

Quoted 16 lines
drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +16 -0
+static LIST_HEAD(i2c_bus_list);
+static LIST_HEAD(i2c_dev_list);
+
+/** A structure to store the various functions supported by the adapter */
+struct func {
+       long value;
+       const char *name;
+};
+static const struct func all_func[] = {
+       {.value = I2C_FUNC_I2C,
+        .name = "I2C"},
+       {.value = 0,
+        .name = ""}
+};
+
+/* ------------------------------------------------------------------------- */

drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 line 130

Quoted 10 lines
drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +10 -0
+
+/**
+ * @brief search and get a bus given a bus adapter index.
+ *
+ * @param index  adapter index
+ *
+ * @return bus node if found
+ */
+static struct i2cdev_bus *i2c_bus_get_by_minor(unsigned index)
+{

Better get_by_bus_id()?

Quoted 189 lines
drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +189 -0
+       struct i2cdev_bus *i2cdev_bus;
+
+       dbg_entry("index=%x", index);
+
+       list_for_each_entry(i2cdev_bus, &i2c_bus_list, list) {
+               if (i2cdev_bus->adap->nr == index)
+                       goto found;
+       }
+       i2cdev_bus = NULL;
+found:
+       return i2cdev_bus;
+}
+
+/**
+ * @brief get a free i2cbus node
+ * allocates memory and links up to bus node list.
+ *
+ * @param adap adapter to allocate a node for
+ *
+ * @return if success, return node, else NULL
+ */
+static struct i2cdev_bus *get_free_i2c_bus(struct i2c_adapter *adap)
+{
+       struct i2cdev_bus *i2cdev_bus;
+       dbg_entry("adap=%x", (u32) adap);
+
+       if (adap->nr >= I2C_MINORS) {
+               dev_err("i2c-dev: Out of device minors (%d)\n", adap->nr);
+               return NULL;
+       }
+
+       i2cdev_bus = calloc(1, sizeof(*i2cdev_bus));
+       if (!i2cdev_bus)
+               return NULL;
+       i2cdev_bus->adap = adap;
+
+       list_add_tail(&i2cdev_bus->list, &i2c_bus_list);
+       return i2cdev_bus;
+}
+
+/**
+ * @brief releases the i2cdev_bus list.
+ *
+ * @param i2cdev_bus item to be released
+ *
+ * @return none
+ */
+static void return_i2c_bus(struct i2cdev_bus *i2cdev_bus)
+{
+       dbg_entry("i2cdev_bus=%x", (u32) i2cdev_bus);
+       list_del(&i2cdev_bus->list);
+       free(i2cdev_bus);
+}
+
+/**
+ * @brief tiny little helper to check if address is proper.
+ *
+ * @param dev  device node
+ * @param addrp address
+ *
+ * @return 0 is no driver already linked, else -EBUSY
+ */
+static int i2cdev_check(struct device_d *dev, void *addrp)
+{
+       struct i2c_client *client = i2c_verify_client(dev);
+
+       dbg_entry("dev=%x addrp=%x", (u32) dev, (u32) addrp);
+       if (!client || client->addr != *(unsigned int *)addrp)
+               return 0;
+
+       return dev->driver ? -EBUSY : 0;
+}
+
+/**
+ * @brief This address checking function differs from the one in i2c-core
+ * in that it considers an address with a registered device, but no driver
+ * bound to it, as NOT busy.
+ *
+ * @param adapter  adapter to attach to
+ * @param addr device address
+ *
+ * @return device present or not.
+ */
+static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
+{
+       int ret = 0;
+       struct device_d *child;
+       dbg_entry("adapter=%x addr=%x", (u32) adapter, (u32) addr);
+       device_for_each_child((&(adapter->dev)), child) {
+               ret = i2cdev_check(child, &addr);
+               if (ret)
+                       break;
+       }
+       return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * @brief read function for a bus.
+ *
+ * This allows for a functionality like i2cdetect.
+ * Offset of each byte corresponds to the device address
+ * each offset without a device will be set with 0xFF indicating empty.
+ * (This is coz 0x0 is a valid address..)
+ * any offset with data will have that address filled with corresponding dev
+ * address
+ *
+ * @param dev bus device.
+ * @param buffer buffer to return data
+ * @param count bytes to read
+ * @param offset device address
+ * @param flags any special flags?
+ *
+ * @return reult of operation
+ */
+static ssize_t i2cbus_read(struct device_d *dev, void *buffer, size_t count,
+                          ulong offset, ulong flags)
+{
+       struct i2c_client *client = (struct i2c_client *)dev->priv;
+       unsigned char addr = 0;
+       unsigned char reg_address = 0;
+       unsigned char tmp = 0;
+       char *buf = (char *)buffer;
+       int idx = 0;
+       struct i2c_msg msgs[2] = {
+               {0, 0, 1, &addr},
+               /* Attempt a 0 byte read */
+               {0, 0 | I2C_M_RD, 0, &tmp}
+       };
+       dbg_entry("dev=%x buffer=%x count=%x offset=%x flags=%x", (u32) dev,
+                 (u32) buffer, (u32) count, (u32) offset, (u32) flags);
+
+       if (offset > dev->size) {
+               dev_err("Request=%d size=%d!\n", offset, dev->size);
+               return -EINVAL;
+       }
+       count = min(count, dev->size - offset);
+       /* Set all defaults to 0xFF */
+       memset(buf, 0xFF, count);
+       while (idx < count) {
+               reg_address = (unsigned char)offset + idx;
+               msgs[0].addr = msgs[1].addr = reg_address;
+
+               /* is this address being used? */
+               if (!i2cdev_check_addr(client->adapter, reg_address)) {
+                       /* No client driver? aha! we shalt access thee! */
+                       if (i2c_transfer(client->adapter, msgs, 2) >= 0)
+                               *buf = reg_address;
+               } else
+                       /* Client driver present.. probable that device exists!
+                        * we dare not access it though :( - dunno how it's
+                        * gonna behave
+                        */
+                       *buf = reg_address;
+               buf++;
+               idx++;
+       }
+       return idx;
+}
+
+/**
+ * @brief display a short summary of the adapter
+ *
+ * @param dev -dev
+ *
+ * @return none
+ */
+static void i2cbus_shortinfo(struct device_d *dev)
+{
+       struct i2c_adapter *adap;
+       struct i2cdev_bus *i2cdev_bus;
+       i2cdev_bus = i2c_bus_get_by_minor(dev->map_base);
+       if (!i2cdev_bus) {
+               dev_err("did not get bus\n");
+               return;
+       }
+       adap = i2c_get_adapter(i2cdev_bus->adap->nr);
+       if (!adap) {
+               dev_err("No such adapter!\n");
+               return;
+       }
+       fprintf(stdout, "Adapter Name: %s\n", adap->name);
+}
+
+/**
+ * @brief show detailed info of the adapter
+ *
+ * @param dev system dev

drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 line 329

Quoted 10 lines
drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +10 -0
+ *
+ * @return none
+ */
+static void i2cbus_showinfo(struct device_d *dev)
+{
+       struct i2c_adapter *adap;
+       struct i2cdev_bus *i2cdev_bus;
+       unsigned long funcs;
+       int i;
+       i2cdev_bus = i2c_bus_get_by_minor(dev->map_base);

The function is called get_by_minor, the argument name in the declaration indicates that it is passed an index and here it gets passed map_base. There is something mixed up here.
*dev should lead you directly to the bus without having to use the help of a function which loops over busses.

drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 line 308

Quoted 5 lines
drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +5 -0
+       if (!i2cdev_bus) {
+               dev_err("did not get bus\n");
+               return;
+       }
+       adap = i2c_get_adapter(i2cdev_bus->adap->nr);

I guess i2c_get_adapter() returns nothing different than i2cdev_bus->adap.
i2cdev_bus and i2c_adapter seem to have a 1:1 relationship, so just move the fields into one struct.

Quoted 4 lines
drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +4 -0
+int i2cdev_attach_adapter(struct i2c_adapter *adap)
+{
+       struct device_d *dev;
+       struct i2cdev_bus *i2cdev_bus;

drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 line 677

Quoted 10 lines
drivers/i2c/i2c-dev.c 2008-06-20 21:16:25.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +10 -0
+       int res;
+       dbg_entry("adap=%x", (u32) adap);
+       i2cdev_bus = get_free_i2c_bus(adap);
+       if (!i2cdev_bus) {
+               dev_err("Did not get free dev-adap %d\n", adap->nr);
+               return -ENOMEM;
+       }
+       dev = &i2cdev_bus->dev;
+       /* Store my adapter number in mapbase for retrieval */
+       dev->map_base = adap->nr;

Ah ok, I understand. Please do not hijack this field for other uses than it was intended to.

Regards,
Sascha

Signature · 4 lines
Pengutronix e.K. - Linux Solutions for Science and Industry
-----------------------------------------------------------
Kontakt-Informationen finden Sie im Header dieser Mail oder
auf der Webseite -> http://www.pengutronix.de/impressum/ <-
#29 lore raw

PATCH 4/9 U-boot-V2:I2C: Introduce i2c-dev

I2C by default does not expose a device interface for the adapters registering in the system. This is usually not needed unless we need to debug something. in which case, this is a handy little layer when used in conjunction with the i2c commands. This layer has changed

New fixes include not using map_base etc and similar review comments from Sascha.

---
 drivers/i2c/Kconfig     |   18 +
 drivers/i2c/Makefile    |    1
 drivers/i2c/i2c-core.c  |   12
 drivers/i2c/i2c-core.h  |    4
 drivers/i2c/i2c-dev.c   |  828 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/i2c-dev.h |   43 ++
 6 files changed, 906 insertions(+)
include/linux/i2c-dev.h 2008-06-24 19:38:02.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +43 -0
Index: u-boot-v2.git/include/linux/i2c-dev.h
===================================================================
@@ -0,0 +1,43 @@
+/**
+ * @file
+ * @brief i2c-bus driver, "char device" interface
+ *
+ * FileName: include/linux/i2c-dev.h
+ *
+ */
+/* Originally from Linux kernel. Ported to U-boot-v2.
+ * (C) Copyright 2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <[email protected]>
+ */
+/*
+    Copyright (C) 1995-97 Simon G. Vogl
+    Copyright (C) 1998-99 Frodo Looijaard <[email protected]>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _LINUX_I2C_DEV_H
+#define _LINUX_I2C_DEV_H
+
+/* For command access */
+#define I2C_SLAVE_ADD  0x0703  /* Create a new slave device */
+#define I2C_SLAVE_REM  0x0706  /* Remove a new slave device */
+
+/******* For the platforms to use *********/
+int i2cdev_new(unsigned int, unsigned int);
+int i2cdev_remove(unsigned int, unsigned int);
+
+#endif /* _LINUX_I2C_DEV_H */
drivers/i2c/i2c-dev.c 2008-06-24 19:42:35.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +828 -0

828 lines not on this page · raw message

drivers/i2c/Kconfig 2008-06-24 19:38:02.000000000 -0500 renamed from drivers/i2c/Kconfig 2008-06-24 19:37:44.000000000 -0500 +18 -0
Index: u-boot-v2.git/drivers/i2c/Kconfig
===================================================================
@@ -19,6 +19,16 @@
 
 if I2C
 
+config I2C_CHARDEV
+       tristate "I2C device interface"
+       help
+         Say Y here to use i2c-* device files, usually found in the /dev
+         directory on your system.  They make it possible to have applications
+         to use the I2C bus.
+
+         This support is also available as a module.  If so, the module
+         will be called i2c-dev.
+
 source drivers/i2c/busses/Kconfig
 
 config I2C_DEBUG_CORE
@@ -28,6 +38,14 @@
          messages to the system log.  Select this if you are having a
          problem with I2C support and want to see more of what is going on.
 
+config I2C_DEBUG_DEV
+       bool "I2C Dev debugging messages"
+       depends on I2C_CHARDEV
+       help
+         Say Y here if you want the I2C dev to produce a bunch of debug
+         messages to the system log.  Select this if you are having a
+         problem with I2C support and want to see more of what is going on.
+
 config I2C_DEBUG_BUS
        bool "I2C Bus debugging messages"
        help
drivers/i2c/Makefile 2008-06-24 19:38:02.000000000 -0500 renamed from drivers/i2c/Makefile 2008-06-24 19:37:44.000000000 -0500 +1 -0
Index: u-boot-v2.git/drivers/i2c/Makefile
===================================================================
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_I2C)              += i2c-core.o
+obj-$(CONFIG_I2C_CHARDEV)      += i2c-dev.o
 obj-y                          += busses/
 
 ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
drivers/i2c/i2c-core.c 2008-06-24 19:38:02.000000000 -0500 renamed from drivers/i2c/i2c-core.c 2008-06-24 19:37:58.000000000 -0500 +12 -0
Index: u-boot-v2.git/drivers/i2c/i2c-core.c
===================================================================
@@ -94,6 +94,10 @@
 
        debug("adapter [%s] registered\n", adap->name);
 
+#ifdef CONFIG_I2C_CHARDEV
+       i2cdev_attach_adapter(adap);
+#endif
+
 out_unlock:
        return res;
 
@@ -214,6 +218,14 @@
                goto out_unlock;
        }
 
+#ifdef CONFIG_I2C_CHARDEV
+       res = i2cdev_detach_adapter(adap);
+       if (res) {
+               dev_err("adapter in use\n");
+               goto out_unlock;
+       }
+#endif
+
        /* detach any active clients. This must be done first, because
         * it can fail; in which case we give up. */
        list_for_each_safe(item, _n, &adap->clients) {
drivers/i2c/i2c-core.h 2008-06-24 19:38:02.000000000 -0500 renamed from drivers/i2c/i2c-core.h 2008-06-24 19:37:44.000000000 -0500 +4 -0
Index: u-boot-v2.git/drivers/i2c/i2c-core.h
===================================================================
@@ -34,4 +34,8 @@
 extern struct list_head        __i2c_board_list;
 extern int             __i2c_first_dynamic_bus_num;
 
+/* Automatically called by i2c-Core..*/
+int i2cdev_attach_adapter(struct i2c_adapter *adap);
+int i2cdev_detach_adapter(struct i2c_adapter *adap);
+
 #endif         /*  __i2C_CORE_H */
#30 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

In reply to Sascha Hauer

Sascha,

Summary: Ok, you sold the idea to me.

Quoted 11 lines

-----Original Message-----
From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
Sent: Friday, June 20, 2008 10:17 AM
To: Menon, Nishanth
Cc: u-boot-users at lists.sourceforge.net
Subject: Re: [Patch 5/9]U-boot-V2:cmd: add I2C commands +int write_i2c(int file, uchar daddr, u16 addr, u8 reg_width, char *buffer,
+ size_t count)

These arguments map nicely to md/mm

Not exactly as of date (we can have register width as 16 bit and data width as 8 bit). But yeah, we can easily make md/mm do it. Yep, I have used md to dump nand and cp to write data.

Quoted 11 lines
Quoted 1 line

What do we achieve by introducing i2c device based nodes?

- An overview over the system for those who are not familiar with it. You may know the devices that are connected to the bus on your board, I don't. One of the benefits in U-Boot-V2 for me is that many different systems behave similarly although they have a very different hardware.
- when md/mm are usable on a device it also means that cp/memcmp/cat or any other file command is usable.
- reduction in code size since you can reuse what's already there (like file commands instead of new commands). That's one of the points that make U-Boot-V1 bigger than it has to be.

Ok, getting down to implementation level, here is the proposal as I understand:
1: I2c bus device node:
1.a: For every bus registered, a default device is registered /dev/i2cbusX. 1.b: this will be done by enabling CHARDEV config
2: Device Nodes:
2.a: created only when CHARDEV config is enabled.
2.b: board files can optionally register default devices. That will appear
as: /dev/i2cbusX_Y where X=busID and Y=device address in hex.
2.c: new command i2cadd <options> -f /dev/i2cbusX -d device address in hex

Usage:
md /dev/i2cbusX will do i2cdetect. (writes and any other access will not be supported). In future when smbus is supported, what ever the bus's default feature is, that will be used. This will attempt a 0 byte read only. (What about buses on which we'd want to do detect based on 0 byte writes?).

devinfo /dev/i2cbusX will display i2c functionality.

i2cadd -f /dev/i2cbusX -d 0x49 will create /dev/i2cbusX_49 With default features: 8 bit reg access access, 8 bit data. Other Options:
Register addressing: 8 or 16 bit
Anything else we can think of..

devinfo /dev/i2cbusX_Y will give device information.

md /dev/i2cbusX_Y will do the equivalent of i2cdump and i2cget

mm /dev/i2cbusX_Y will do the equivalent of i2cset.

The risk I see is in trying to do i2cdetect with equivalent of -q - quick read. I don't have aneed for it, but does anyone else have? Another risk in using generic commands.. folks are going to want some custom feature and extension to the generic commands.. that is a good thing, and something we can take in when the need comes.

md/mm might need further changes to handle access sizes.

Does this strategy work ok for eeproms?

The only negative I see is that folks need an additional command to create a device node. Not too bad a tradeoff considering the other stuff we could do..

Regards,
Nishanth Menon

#31 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

Quoted 14 lines · Nishanth

Sascha,

Summary: Ok, you sold the idea to me.

Quoted 10 lines

-----Original Message-----
From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
Sent: Friday, June 20, 2008 10:17 AM
To: Menon, Nishanth
Cc: u-boot-users at lists.sourceforge.net
Subject: Re: [Patch 5/9]U-boot-V2:cmd: add I2C commands +int write_i2c(int file, uchar daddr, u16 addr, u8 reg_width, char *buffer,
+ size_t count)

Quoted 2 lines
Quoted 1 line

These arguments map nicely to md/mm

Not exactly as of date (we can have register width as 16 bit and data width as 8 bit). But yeah, we can easily make md/mm do it. Yep, I have used md to dump nand and cp to write data.

Are you aware of device parameters? Well, you are, they are used for setting the mac address and stuff like that. Maybe this would be a possibility for the user to change the address width.

Quoted 12 lines
Quoted 12 lines
Quoted 2 lines

What do we achieve by introducing i2c device based nodes?

- An overview over the system for those who are not familiar with it. You may know the devices that are connected to the bus on your board, I don't. One of the benefits in U-Boot-V2 for me is that many different systems behave similarly although they have a very different hardware.
- when md/mm are usable on a device it also means that cp/memcmp/cat or any other file command is usable.
- reduction in code size since you can reuse what's already there (like file commands instead of new commands). That's one of the points that make U-Boot-V1 bigger than it has to be.

Quoted 6 lines

Ok, getting down to implementation level, here is the proposal as I understand:
1: I2c bus device node:
1.a: For every bus registered, a default device is registered /dev/i2cbusX. 1.b: this will be done by enabling CHARDEV config
2: Device Nodes:
2.a: created only when CHARDEV config is enabled.

I don't think that this has to be dependent on an additional config option. I mean, is there something sensible left when this option is disabled?

Quoted 3 lines

2.b: board files can optionally register default devices. That will appear
as: /dev/i2cbusX_Y where X=busID and Y=device address in hex. 2.c: new command i2cadd <options> -f /dev/i2cbusX -d device address in hex

I haven't thought that to the end, that was just an idea, but it looks plausible. Please use 0 as base to simple_strtoul() so that the base is determined by the prefix.

Quoted 3 lines

Usage:
md /dev/i2cbusX will do i2cdetect. (writes and any other access will not be supported). In future when smbus is supported, what ever the bus's default feature is, that will be used. This will attempt a 0 byte read only. (What about buses on which we'd want to do detect based on 0 byte writes?).

Hm, what should the output look like for 'md /dev/i2cbusX'? How about another command:

i2cdetect -f /dev/i2cbusX
- try to detect slave devices on a bus and register them.

or maybe just 'i2cadd -d -f /dev/i2cbusX' (d for detect) instead of another command.

Quoted 2 lines

devinfo /dev/i2cbusX will display i2c functionality.

whereas devinfo /dev/i2cbusX_Y could show the access mode (7bit/10bit addressing) and give the user a chance to change it.

Quoted 13 lines

i2cadd -f /dev/i2cbusX -d 0x49 will create /dev/i2cbusX_49 With default features: 8 bit reg access access, 8 bit data. Other Options:
Register addressing: 8 or 16 bit
Anything else we can think of..

devinfo /dev/i2cbusX_Y will give device information.

md /dev/i2cbusX_Y will do the equivalent of i2cdump and i2cget

mm /dev/i2cbusX_Y will do the equivalent of i2cset.

Quoted 7 lines

The risk I see is in trying to do i2cdetect with equivalent of -q - quick read. I don't have aneed for it, but does anyone else have? Another risk in using generic commands.. folks are going to want some custom feature and extension to the generic commands.. that is a good thing, and something we can take in when the need comes.

md/mm might need further changes to handle access sizes.

It shouldn't need any changes, at least no i2c specific ones. If it does, we did something wrong.

Quoted 2 lines

Does this strategy work ok for eeproms?

Why not? When we have a eeprom slave driver together with a /dev/eepromX device node, everything should be fine.

Quoted 3 lines

The only negative I see is that folks need an additional command to create a device node.

Normally they wouldn't need it because mostly the board would register all devices available on the system. This may not be true for your board, but most boards I have only have an eeprom, a rtc and only a few other devices connected to the i2c bus. It's not a big memory penalty to register them.

Regards,
Sascha

Signature · 4 lines
Pengutronix e.K. - Linux Solutions for Science and Industry
-----------------------------------------------------------
Kontakt-Informationen finden Sie im Header dieser Mail oder
auf der Webseite -> http://www.pengutronix.de/impressum/ <-
#32 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

Sascha,

Quoted 10 lines

-----Original Message-----
From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
Sent: Monday, June 23, 2008 2:40 AM
To: Menon, Nishanth
Cc: u-boot-users at lists.sourceforge.net
Subject: Re: [Patch 5/9]U-boot-V2:cmd: add I2C commands

Are you aware of device parameters? Well, you are, they are used for setting the mac address and stuff like that. Maybe this would be a possibility for the user to change the address width.

Oh yeah, that would work just perfectly for our needs. Probably additional patches can add that functionality.

Quoted 4 lines

I don't think that this has to be dependent on an additional config option. I mean, is there something sensible left when this option is disabled?

Look at the makefile -> i2c-core.c which provides the basic Infrastructure(i2c_transfer) is retained. Not all configurations need i2c-dev. It is merely a debug tool. It is good to isolate it out.

Quoted 3 lines

I haven't thought that to the end, that was just an idea, but it looks plausible. Please use 0 as base to simple_strtoul() so that the base is determined by the prefix.

I recommend a step by step approach, lets add features to the patches I Proposed in a phased manner. Do comment on the patch(try2 and 3) I have send.

Quoted 1 line

Hm, what should the output look like for 'md /dev/i2cbusX'? How about

Do check the dox comments in patch try2/3. I have given a sample output.

Quoted 4 lines

another command:

i2cdetect -f /dev/i2cbusX
- try to detect slave devices on a bus and register them.

This would be redundant. md command just works fine.

Quoted 3 lines

or maybe just 'i2cadd -d -f /dev/i2cbusX' (d for detect) instead of another command.

This is a possible direction we could take, but -d will basically add i2cdetect feature when none is required at the moment.

Quoted 2 lines

whereas devinfo /dev/i2cbusX_Y could show the access mode (7bit/10bit addressing) and give the user a chance to change it.

We can add more information in show_info. Register width, data width being The few of them. Current patches don't have that support, but is easy to Introduce when we need them.

Quoted 2 lines

It shouldn't need any changes, at least no i2c specific ones. If it does, we did something wrong.

Yes, I agree.

Quoted 11 lines
Quoted 4 lines

The only negative I see is that folks need an additional command to create a device node.

Normally they wouldn't need it because mostly the board would register all devices available on the system. This may not be true for your board, but most boards I have only have an eeprom, a rtc and only a few other devices connected to the i2c bus. It's not a big memory penalty to register them.

Yes, you are right.

The current patches I have send provide the basic framework, all things we Discussed above can be added in phases as our needs come in.

Regards,
Nishanth Menon

#33 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

In reply to Sascha Hauer

i2cdev command is introduced here. This allows
for device creation for doing i2c ops.

This is based on the discussion here:
http://www.nabble.com/-Patch-0-9--U-boot-V2%3A-
Introduce-I2C-support-for-SDP3430-to17981717.html
#a18029740

---
 Documentation/commands.dox |    1
 commands/Kconfig           |    4
 commands/i2c.c             |  211 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 216 insertions(+)
Documentation/commands.dox 2008-06-20 21:09:59.000000000 -0500 renamed from Documentation/commands.dox 2008-06-20 21:09:53.000000000 -0500 +1 -0
Index: u-boot-v2.git/Documentation/commands.dox
===================================================================
@@ -20,5 +20,6 @@
  - @subpage setenv_command
  - @subpage sh_command
  - @subpage unprotect_command
+ - @subpage page_do_cmd_i2cdev
 
 */
commands/Kconfig 2008-06-20 21:11:16.000000000 -0500 renamed from commands/Kconfig 2008-06-20 21:09:53.000000000 -0500 +4 -0
Index: u-boot-v2.git/commands/Kconfig
===================================================================
@@ -180,6 +180,10 @@
        prompt "nand"
 endmenu
 
+config CMD_I2C
+       depends on I2C_CHARDEV
+       tristate
+       prompt "i2cdev"
 
 menu "booting                       "
 
commands/i2c.c 2008-06-20 21:09:59.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +211 -0

211 lines not on this page · raw message

#34 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

Quoted 2 lines · In message <[email protected]> you…

i2cdev command is introduced here. This allows
for device creation for doing i2c ops.

...

commands/i2c.c 2008-06-20 21:09:59.000000000 -0500 line 52

Quoted 8 lines
commands/i2c.c 2008-06-20 21:09:59.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +8 -0
+static const __maybe_unused char cmd_i2cdev_s[] =
+    "Usage:\n"
+    "  i2cdev [-a|-r] -b bus_dev -d dev_addr \n"
+    "Where:\n"
+    "-a                Add a new device node\n"
+    "-r                Remove existing device node\n"
+    "-b bus_dev        i2c bus device to operate on\n"
+    "-d dev_addr       Device address for which to create\n";

Indentation is by TABs, i. e. in columns of 8, 16, ...

Please stick to the Coding Style requirements!

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
                  Nail here --X-- for new monitor.
#35 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

i2cdev command is introduced here. This allows
for device creation for doing i2c ops. With tab
indents corrected.

---
 Documentation/commands.dox |    1
 commands/Kconfig           |    4
 commands/i2c.c             |  211 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 216 insertions(+)
Documentation/commands.dox 2008-06-21 09:54:22.000000000 -0500 renamed from Documentation/commands.dox 2008-06-21 09:53:22.000000000 -0500 +1 -0
Index: u-boot.v2/Documentation/commands.dox
===================================================================
@@ -20,5 +20,6 @@
  - @subpage setenv_command
  - @subpage sh_command
  - @subpage unprotect_command
+ - @subpage page_do_cmd_i2cdev
 
 */
commands/Kconfig 2008-06-21 09:54:22.000000000 -0500 renamed from commands/Kconfig 2008-06-21 09:53:22.000000000 -0500 +4 -0
Index: u-boot.v2/commands/Kconfig
===================================================================
@@ -180,6 +180,10 @@
        prompt "nand"
 endmenu
 
+config CMD_I2C
+       depends on I2C_CHARDEV
+       tristate
+       prompt "i2cdev"
 
 menu "booting                       "
 
commands/i2c.c 2008-06-21 10:42:55.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +211 -0

211 lines not on this page · raw message

#36 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

Quoted 3 lines · Nishanth

i2cdev command is introduced here. This allows
for device creation for doing i2c ops. With tab
indents corrected.

Nice and short ;) , just one comment...

+

Quoted 26 lines
commands/i2c.c 2008-06-21 10:42:55.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +26 -0
+       while ((opt = getopt(argc, argv, "arb:d:")) > 0) {
+               switch (opt) {
+               case 'a':
+                       if (rem) {
+                               fprintf(stderr,
+                                       "you cannot add when you selected "
+                                       "delete!\n");
+                               goto fail_ret;
+                       }
+                       add = 1;
+                       break;
+               case 'r':
+                       if (add) {
+                               fprintf(stderr,
+                                       "you cannot delete when you selected "
+                                       "add!\n");
+                               goto fail_ret;
+                       }
+                       rem = 1;
+                       break;
+               case 'b':
+                       bus_dev = optarg;
+                       break;
+               case 'd':
+                       dev_addr = (int)simple_strtoul(optarg, NULL, 10);
+                       if (dev_addr > 0xFF) {

commands/i2c.c 2008-06-21 10:42:55.000000000 -0500 line 97

Quoted 10 lines
commands/i2c.c 2008-06-21 10:42:55.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +10 -0
+                               fprintf(stderr, "I2C address are b/w 0 and "
+                                       "0x7f\n");
+                               goto fail_ret;
+                       }
+                       break;
+               default:
+                       fprintf(stderr, "unknown arg %s\n", opt);
+                       goto fail_ret;
+               }
+       }

Instead of two seperate if claues above:

if (add && rem) {
	printf("both remove and add are selected\n");
	goto fail_ret;
}

Regards,
Sascha

Signature · 4 lines
Pengutronix e.K. - Linux Solutions for Science and Industry
-----------------------------------------------------------
Kontakt-Informationen finden Sie im Header dieser Mail oder
auf der Webseite -> http://www.pengutronix.de/impressum/ <-
#37 lore raw

PATCH 5/9 U-boot-V2:cmd: add I2C commands

i2cdev command is introduced here. This allows
for device creation for doing i2c ops.

This is based on the discussion here:
http://www.nabble.com/-Patch-0-9--U-boot-V2%3A-
Introduce-I2C-support-for-SDP3430-to17981717.html
#a18029740

Comments from sacha incorporated.

---
 Documentation/commands.dox |    1
 commands/Kconfig           |    4
 commands/i2c.c             |  204 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 209 insertions(+)
Documentation/commands.dox 2008-06-24 17:00:03.000000000 -0500 renamed from Documentation/commands.dox 2008-06-24 16:59:06.000000000 -0500 +1 -0
Index: u-boot-v2.git/Documentation/commands.dox
===================================================================
@@ -20,5 +20,6 @@
  - @subpage setenv_command
  - @subpage sh_command
  - @subpage unprotect_command
+ - @subpage page_do_cmd_i2cdev
 
 */
commands/Kconfig 2008-06-24 19:27:43.000000000 -0500 renamed from commands/Kconfig 2008-06-24 16:59:05.000000000 -0500 +4 -0
Index: u-boot-v2.git/commands/Kconfig
===================================================================
@@ -180,6 +180,10 @@
        prompt "nand"
 endmenu
 
+config CMD_I2C
+       depends on I2C_CHARDEV
+       tristate
+       prompt "i2cdev"
 
 menu "booting                       "
 
commands/i2c.c 2008-06-24 18:07:17.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +204 -0

204 lines not on this page · raw message

#38 lore raw

PATCH 6/9 U-boot-V2:cmd: I2C commands support

In reply to Robert Schwebel

This adds i2c documentation, build options
for i2c commands and a support header.

---
 Documentation/commands.dox |    4
 commands/Kconfig           |   31 +++++
 commands/i2c.c             |  233 +++++++++++++++++++++++++++++++++++++++++++++
 commands/i2c.h             |   65 ++++++++++++
 4 files changed, 333 insertions(+)
commands/i2c.h 2008-06-19 09:31:42.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +65 -0
Index: u-boot-v2.git/commands/i2c.h
===================================================================
@@ -0,0 +1,65 @@
+/**
+ * @file
+ * @brief I2C Commands specific header.
+ *
+ * FileName: commands/i2c.h
+ * This provides i2cdump, i2cdetect, i2cset and i2cget appplications
+ * The code originates from the i2c-tools located here:
+ * http://www.lm-sensors.org/wiki/I2CTools
+ * This is used by the c file
+ */
+/*
+ * (C) Copyright 2006-2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <[email protected]>
+ *
+ * This application is based on the following:
+ *
+ * i2cbusses: Print the installed i2c busses for both 2.4 and 2.6 kernels.
+ *            Part of user-space programs to access for I2C
+ *            devices.
+ * Copyright (c) 1999-2003  Frodo Looijaard <[email protected]> and
+ *                          Mark D. Studebaker <[email protected]>
+ * Copyright (C) 2008       Jean Delvare <[email protected]>
+ * i2cdump.c - a user-space program to dump I2C registers
+ * Copyright (C) 2002-2003  Frodo Looijaard <[email protected]>, and
+ *                          Mark D. Studebaker <[email protected]>
+ * Copyright (C) 2004-2008  Jean Delvare <[email protected]>
+ * i2cget.c - A user-space program to read an I2C register.
+ * Copyright (C) 2005-2008  Jean Delvare <[email protected]>
+ * i2cset.c - A user-space program to write an I2C register.
+ * Copyright (C) 2001-2003  Frodo Looijaard <[email protected]>, and
+ *                          Mark D. Studebaker <[email protected]>
+ * Copyright (C) 2004-2008  Jean Delvare <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
+ */
+
+#ifndef __CMD_I2C_H
+#define __CMD_I2C_H
+
+/*********** "USER SPACE I2C Access APIs" ************/
+
+int lookup_i2c_bus(const char *i2cbus_arg);
+int open_i2c_dev(const int i2cbus, char *filename, const int quiet);
+int parse_i2c_address(const char *address_arg);
+int set_slave_addr(int file, int address, int force);
+int check_funcs(int file, int size, int daddress, int pec);
+int read_i2c(int file, uchar daddr, u16 addr, u8 reg_width, char *buffer,
+            size_t count);
+int write_i2c(int file, uchar daddr, u16 addr, u8 reg_width, char *buffer,
+             size_t count);
+#endif /* __CMD_I2C_H */
Documentation/commands.dox 2008-06-19 09:31:42.000000000 -0500 renamed from Documentation/commands.dox 2008-06-19 09:29:03.000000000 -0500 +4 -0
Index: u-boot-v2.git/Documentation/commands.dox
===================================================================
@@ -20,5 +20,9 @@
  - @subpage setenv_command
  - @subpage sh_command
  - @subpage unprotect_command
+ - @subpage page_do_cmd_i2c_detect
+ - @subpage page_do_cmd_i2c_dump
+ - @subpage page_do_cmd_i2c_get
+ - @subpage page_do_cmd_i2c_set
 
 */
commands/Kconfig 2008-06-19 09:31:42.000000000 -0500 renamed from commands/Kconfig 2008-06-19 09:29:03.000000000 -0500 +31 -0
Index: u-boot-v2.git/commands/Kconfig
===================================================================
@@ -180,6 +180,37 @@
        prompt "nand"
 endmenu
 
+menu "i2c                           "
+       depends on I2C_CHARDEV
+
+config CMD_I2C
+       bool
+       default n
+
+config CMD_I2C_DETECT
+       tristate
+       default y
+       select CMD_I2C
+       prompt "i2cdetect"
+
+config CMD_I2C_DUMP
+       tristate
+       default y
+       select CMD_I2C
+       prompt "i2cdump"
+
+config CMD_I2C_GET
+       tristate
+       default y
+       select CMD_I2C
+       prompt "i2cget"
+
+config CMD_I2C_SET
+       tristate
+       default y
+       select CMD_I2C
+       prompt "i2cset"
+endmenu
 
 menu "booting                       "
 
commands/i2c.c 2008-06-19 09:32:57.000000000 -0500 renamed from commands/i2c.c 2008-06-19 09:31:49.000000000 -0500 +233 -0

254 lines not on this page · raw message

#39 lore raw

PATCH 7/9 U-boot-V2:ARM:OMAP: OMAP classes

In reply to Robert Schwebel

Introduce cpu_is_xxxx macros similar to the one in 2.6.26 rc5 kernel, this allows for compile time optimization of CPU specific code in common drivers. Resending this for keeping the series

---
 include/asm-arm/arch-omap/silicon.h |   28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
include/asm-arm/arch-omap/silicon.h 2008-06-19 08:51:07.000000000 -0500 renamed from include/asm-arm/arch-omap/silicon.h 2008-06-19 08:39:58.000000000 -0500 +28 -0
Index: u-boot-v2.git/include/asm-arm/arch-omap/silicon.h
===================================================================
@@ -24,6 +24,34 @@
 /* Each platform silicon header comes here */
 #ifdef CONFIG_ARCH_OMAP3
 #include <asm/arch/omap3-silicon.h>
+#define cpu_is_omap34xx() 1
+#else
+#define cpu_is_omap34xx() 0
+#endif
+
+/* The following architectures are TBD */
+#ifdef CONFIG_ARCH_OMAP2430
+#define cpu_is_omap2430() 1
+#else
+#define cpu_is_omap2430() 0
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2420
+#define cpu_is_omap2420() 1
+#else
+#define cpu_is_omap2420() 0
+#endif
+
+#ifdef CONFIG_ARCH_OMAP16XX
+#define cpu_is_omap16xx() 1
+#else
+#define cpu_is_omap16xx() 0
+#endif
+
+#ifdef CONFIG_ARCH_OMAP15XX
+#define cpu_is_omap15xx() 1
+#else
+#define cpu_is_omap15xx() 0
 #endif
 
 /* If Architecture specific init functions are present */
#40 lore raw

PATCH 8/9 U-boot-V2:I2C:Busses: OMAP I2C Adapter

In reply to Robert Schwebel

Introduce the i2c adapter for OMAP i2c controller
This is mostly a port from 2.6.26 rc5 kernel at:
http://git.kernel.org/git/?p=linux/kernel/git/tmlind/linux-omap-2.6.git

---
 drivers/i2c/busses/Kconfig      |    7
 drivers/i2c/busses/i2c-omap.c   |  678 ++++++++++++++++++++++++++++++++++++++++
 include/asm-arm/arch-omap/i2c.h |  154 +++++++++
 3 files changed, 839 insertions(+)
drivers/i2c/busses/i2c-omap.c 2008-06-19 08:51:23.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +678 -0
Index: u-boot-v2.git/drivers/i2c/busses/i2c-omap.c
===================================================================
@@ -0,0 +1,678 @@
+/**
+ * @file
+ * @brief OMAP I2C Adapter driver
+ *
+ * FileName: drivers/i2c/busses/i2c-omap.c
+ *
+ */
+/*
+ * (C) Copyright 2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <[email protected]>
+ *
+ * based on Linux kernel omap i2c adapter driver
+ *
+ * Copyright (C) 2003 MontaVista Software, Inc.
+ * Copyright (C) 2005 Nokia Corporation
+ * Copyright (C) 2004 - 2007 Texas Instruments.
+ *
+ * Originally written by MontaVista Software, Inc.
+ * Additional contributions by:
+ *     Tony Lindgren <[email protected]>
+ *     Imre Deak <[email protected]>
+ *     Juha Yrjola <[email protected]>
+ *     Syed Khasim <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <common.h>
+#include <config.h>
+#include <errno.h>
+#include <init.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <clock.h>
+#include <linux/i2c.h>
+#include <asm/io.h>
+#include <asm/arch/silicon.h>
+#include <asm/arch/i2c.h>
+
+/*---------------------- Debug Messages -------------------------------------*/
+#ifdef CONFIG_I2C_DEBUG_BUS
+#define DBG_MODULE_NAME "omap-i2c"
+#define dev_dbg(ARGS...) fprintf(stdout, ARGS);
+#define dev_warn(ARGS...) fprintf(stderr, ARGS);
+#define dbg_entry(FORMAT, ARGS...) fprintf(stdout,\
+               DBG_MODULE_NAME"%s:%d:Entry:"FORMAT"\n",\
+               __func__, __LINE__, ARGS)
+#define dbg_exit(FORMAT, ARGS...) fprintf(stdout,\
+               DBG_MODULE_NAME"%s:%d:Exit:"FORMAT"\n",\
+               __func__, __LINE__, ARGS)
+#else
+#define dev_dbg(ARGS...)
+#define dev_warn(ARGS...)
+#define dbg_entry(FORMAT, ARGS...)
+#define dbg_exit(FORMAT, ARGS...)
+#endif
+#define dev_err(ARGS...) fprintf(stderr, ARGS);
+
+/*---------------------- Defines --------------------------------------------*/
+/* Hack to enable zero length transfers and smbus quick until clean fix
+   is available */
+#define OMAP_HACK
+
+/*---------------------- Private Data Structures ----------------------------*/
+struct omap_i2c_dev {
+       unsigned long base;     /* virtual */
+       u32 speed;              /* Speed of bus in Khz */
+       u32 fclk;               /* Functional clock speed */
+       u16 cmd_err;
+       u8 *buf;
+       size_t buf_len;
+       struct i2c_adapter adapter;
+       u8 fifo_size;           /* use as flag and value
+                                * fifo_size==0 implies no fifo
+                                * if set, should be trsh+1
+                                */
+       unsigned rev1:1;
+       unsigned b_hw:1;        /* bad h/w fixes */
+};
+
+/*---------------------- Implementation -------------------------------------*/
+
+static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
+                                     int reg, u16 val)
+{
+       dbg_entry("i2c_dev=%x reg=%x val=%x", (u32) i2c_dev, reg, val);
+       __raw_writew(val, i2c_dev->base + reg);
+}
+
+static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
+{
+       dbg_entry("i2c_dev=%x reg=%x", (u32) i2c_dev, reg);
+       return __raw_readw(i2c_dev->base + reg);
+}
+
+static int omap_i2c_init(struct omap_i2c_dev *dev)
+{
+       u16 psc = 0, scll = 0, sclh = 0;
+       u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
+       unsigned long fclk_rate = 12000000;
+       unsigned long internal_clk = 0;
+
+       dbg_entry("dev=%x", (u32) dev);
+       if (!dev->rev1) {
+               /* For some reason we need to set the EN bit before the
+                * reset done bit gets set. */
+               uint64_t timeout = OMAP_I2C_TIMEOUT;
+               uint64_t start;
+
+               start = get_time_ns();
+               omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST);
+               omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
+               while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) &
+                        OMAP_I2C_SYSS_RDONE)) {
+                       if (is_timeout(start, timeout)) {
+                               dev_err("timeout waiting for bus ready\n");
+                               return -ETIMEDOUT;
+                       }
+               }
+       }
+       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+
+       if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+
+               /* HSI2C controller internal clk rate should be 19.2 Mhz */
+               if (dev->speed > 400)
+                       internal_clk = 19200;
+               else if (dev->speed > 100)
+                       internal_clk = 9600;
+               else
+                       internal_clk = 4000;
+               fclk_rate = dev->fclk / 1000;
+
+               /* Compute prescaler divisor */
+               psc = fclk_rate / internal_clk;
+               psc = psc - 1;
+
+               /* If configured for High Speed */
+               if (dev->speed > 400) {
+                       /* For first phase of HS mode */
+                       fsscll = internal_clk / (400 * 2) - 7;
+                       fssclh = internal_clk / (400 * 2) - 5;
+
+                       /* For second phase of HS mode */
+                       hsscll = fclk_rate / (dev->speed * 2) - 7;
+                       hssclh = fclk_rate / (dev->speed * 2) - 5;
+               } else {
+                       /* To handle F/S modes */
+                       fsscll = internal_clk / (dev->speed * 2) - 7;
+                       fssclh = internal_clk / (dev->speed * 2) - 5;
+               }
+               scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll;
+               sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh;
+               dev_dbg("base=%x,fclk=%d fclk_rate =%d, iclk=%d dev->speed=%d\n"
+                       "psc=%x fsscll=%x fssclh=%x hsscll=%x hssclh=%x\n"
+                       "scll=%x sclh=%x\n",
+                       dev->base, dev->fclk, fclk_rate, internal_clk,
+                       dev->speed, psc, fsscll, fssclh, hsscll, hssclh,
+                       scll, sclh);
+       } else {
+               /* Program desired operating rate */
+               fclk_rate /= (psc + 1) * 1000;
+               if (psc > 2)
+                       psc = 2;
+               scll = fclk_rate / (dev->speed * 2) - 7 + psc;
+               sclh = fclk_rate / (dev->speed * 2) - 7 + psc;
+       }
+
+       /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
+       omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
+
+       /* SCL low and high time values */
+       omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
+       omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
+
+       if (dev->fifo_size)
+               /* Note: setup required fifo size - 1 */
+               omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
+                               (dev->fifo_size - 1) << 8 |     /* RTRSH */
+                               OMAP_I2C_BUF_RXFIF_CLR |
+                               (dev->fifo_size - 1) |          /* XTRSH */
+                               OMAP_I2C_BUF_TXFIF_CLR);
+
+       /* DO NOT Enable interrupts -we work in polling mode */
+       omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
+
+       /* Take the I2C module out of reset: */
+       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
+
+       return 0;
+}
+
+/*
+ * Waiting on Bus Busy
+ */
+static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)
+{
+       uint64_t start, timeout;
+
+       dbg_entry("dev=%x", (u32) dev);
+
+       timeout = OMAP_I2C_TIMEOUT;
+       start = get_time_ns();
+
+       while (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
+               if (is_timeout(start, timeout)) {
+                       dev_err("timeout waiting for bus ready\n");
+                       return -ETIMEDOUT;
+               }
+       }
+
+       return 0;
+}
+
+static int omap_i2c_rev1_wait_event(struct omap_i2c_dev *dev, uint64_t timeout)
+{
+       u16 iv, w;
+       int stat = 0;
+       uint64_t start;
+
+       start = get_time_ns();
+       dbg_entry("dev=%x", (u32) dev);
+       /* we dont have anything better to do..
+        * So poll the status reg
+        */
+       while (!stat) {
+               if (is_timeout(start, timeout)) {
+                       dev_err("waitevent Timeout!");
+                       stat = -ETIMEDOUT;
+                       continue;
+               }
+               iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
+               switch (iv) {
+               case 0x01:      /* Arbitration lost */
+                       dev_err("Arbitration lost\n");
+                       dev->cmd_err = OMAP_I2C_STAT_AL;
+                       return 0;
+                       break;
+               case 0x02:      /* No acknowledgement */
+                       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
+                                          OMAP_I2C_CON_STP);
+                       dev->cmd_err = OMAP_I2C_STAT_NACK;
+                       return 0;
+                       break;
+               case 0x03:      /* Register access ready */
+                       dev->cmd_err = 0;
+                       return 0;
+               case 0x04:      /* Receive data ready */
+                       if (dev->buf_len) {
+                               w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
+                               *dev->buf++ = w;
+                               dev->buf_len--;
+                               if (dev->buf_len) {
+                                       *dev->buf++ = w >> 8;
+                                       dev->buf_len--;
+                               }
+                       } else {
+                               dev_err("RRDY IRQ while no data requested\n");
+                               stat = -2;
+                       }
+                       break;
+               case 0x05:      /* Transmit data ready */
+                       if (dev->buf_len) {
+                               w = *dev->buf++;
+                               dev->buf_len--;
+                               if (dev->buf_len) {
+                                       w |= *dev->buf++ << 8;
+                                       dev->buf_len--;
+                               }
+                               omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+                       } else {
+                               dev_err("XRDY IRQ while no data to send\n");
+                               stat = -1;
+                       }
+               case 0x00:      /* None */
+                       /* default.. continue to wait */
+                       break;
+               }
+       }
+
+       return stat;
+}
+
+static int omap_i2c_wait_event(struct omap_i2c_dev *dev, uint64_t timeout)
+{
+       u16 bits;
+       u16 stat, w;
+       int err;
+       uint64_t start;
+       dev_dbg("dev=%x timeout=%x", (u32) dev, timeout);
+
+       bits = OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ARDY |
+           OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
+           OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR;
+
+       start = get_time_ns();
+       /* We will exit out of this loop eventually.
+        * Trusting the hardware?
+        */
+       while (1) {
+               stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG)) & bits;
+
+               /* No Stat update? re-read */
+               if (!stat) {
+                       if (is_timeout(start, timeout)) {
+                               dev_err("waitevent Timeout!\n");
+                               return -ETIMEDOUT;
+                       }
+                       continue;
+               }
+
+               /* Ack other signals, but NOT RDY signals -> we need to do
+                * that after transfer of data
+                */
+               omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat &
+                               ~(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
+                                 OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
+
+               err = 0;
+               if (stat & OMAP_I2C_STAT_NACK) {
+                       dev_dbg("Nacked!\n", stat);
+                       err |= OMAP_I2C_STAT_NACK;
+               }
+               if (stat & OMAP_I2C_STAT_AL) {
+                       dev_err("Arbitration lost\n");
+                       err |= OMAP_I2C_STAT_AL;
+               }
+               if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
+                           OMAP_I2C_STAT_AL)) {
+                       dev->cmd_err = err;
+                       return 0;
+               }
+
+               if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
+                       u8 num_bytes = 1;
+                       if (dev->fifo_size) {
+                               num_bytes =
+                                   (stat & OMAP_I2C_STAT_RRDY) ? dev->
+                                   fifo_size : omap_i2c_read_reg(dev,
+                                                 OMAP_I2C_BUFSTAT_REG);
+                       }
+                       while (num_bytes) {
+                               num_bytes--;
+                               w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
+                               if (dev->buf_len) {
+                                       *dev->buf++ = w;
+                                       dev->buf_len--;
+                                       /* Data reg from 2430 is 8 bit wide */
+                                       if (!cpu_is_omap2430() &&
+                                           !cpu_is_omap34xx()) {
+                                               if (dev->buf_len) {
+                                                       *dev->buf++ = w >> 8;
+                                                       dev->buf_len--;
+                                               }
+                                       }
+                               } else {
+                                       if (stat & OMAP_I2C_STAT_RRDY)
+                                               dev_err
+                                                   ("RRDY IRQ while no data "
+                                                    "requested\n");
+                                       if (stat & OMAP_I2C_STAT_RDR)
+                                               dev_err("RDR IRQ while no data "
+                                                       "requested\n");
+                                       return -2;
+                               }
+                       }
+                       omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat &
+                               (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR));
+               }
+               if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
+                       u8 num_bytes = 1;
+                       if (dev->fifo_size) {
+                               num_bytes =
+                                   (stat & OMAP_I2C_STAT_XRDY) ? dev->
+                                   fifo_size : omap_i2c_read_reg(dev,
+                                                 OMAP_I2C_BUFSTAT_REG);
+                       }
+                       while (num_bytes) {
+                               num_bytes--;
+                               w = 0;
+                               if (dev->buf_len) {
+                                       w = *dev->buf++;
+                                       dev->buf_len--;
+                                       /* Data reg from  2430 is 8 bit wide */
+                                       if (!cpu_is_omap2430() &&
+                                           !cpu_is_omap34xx()) {
+                                               if (dev->buf_len) {
+                                                       w |= *dev->buf++ << 8;
+                                                       dev->buf_len--;
+                                               }
+                                       }
+                               } else {
+                                       if (stat & OMAP_I2C_STAT_XRDY)
+                                               dev_err("XRDY IRQ while no "
+                                                       "data to send\n");
+                                       if (stat & OMAP_I2C_STAT_XDR)
+                                               dev_err("XDR IRQ while no "
+                                                       "data to send\n");
+                                       return -2;
+                               }
+                               omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+                       }
+                       omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat &
+                               (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
+               }
+               if (stat & OMAP_I2C_STAT_ROVR) {
+                       dev_err("Receive overrun\n");
+                       dev->cmd_err |= OMAP_I2C_STAT_ROVR;
+               }
+               if (stat & OMAP_I2C_STAT_XUDF) {
+                       dev_err("Transmit overflow\n");
+                       dev->cmd_err |= OMAP_I2C_STAT_XUDF;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Low level master read/write transaction.
+ */
+static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
+                            struct i2c_msg *msg, int stop)
+{
+       struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
+#ifdef OMAP_HACK
+       u8 zero_byte = 0;
+#endif
+       int r;
+       u16 w;
+
+       dbg_entry("adap=%x msg=%s stop=%x", (u32) adap, (u32) msg, stop);
+       dev_dbg("addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
+               msg->addr, msg->len, msg->flags, stop);
+
+#ifndef OMAP_HACK
+       if (msg->len == 0)
+               return -EINVAL;
+
+       omap_i2c_write_reg(dev, OMAP_I2C_SA_REG, msg->addr);
+
+       /* REVISIT: Could the STB bit of I2C_CON be used with probing? */
+       dev->buf = msg->buf;
+       dev->buf_len = msg->len;
+
+#else
+
+       omap_i2c_write_reg(dev, OMAP_I2C_SA_REG, msg->addr);
+       /* REVISIT: Remove this hack when we can get I2C chips from board-*.c
+        *          files
+        * Sigh, seems we can't do zero length transactions. Thus, we
+        * can't probe for devices w/o actually sending/receiving at least
+        * a single byte. So we'll set count to 1 for the zero length
+        * transaction case and hope we don't cause grief for some
+        * arbitrary device due to random byte write/read during
+        * probes.
+        */
+       if (msg->len == 0) {
+               dev->buf = &zero_byte;
+               dev->buf_len = 1;
+       } else {
+               dev->buf = msg->buf;
+               dev->buf_len = msg->len;
+       }
+#endif
+
+       omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
+
+       /* Clear the FIFO Buffers */
+       w = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG);
+       w |= OMAP_I2C_BUF_RXFIF_CLR | OMAP_I2C_BUF_TXFIF_CLR;
+       omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, w);
+
+       dev->cmd_err = 0;
+
+       w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
+
+       /* High speed configuration */
+       if (dev->speed > 400)
+               w |= OMAP_I2C_CON_OPMODE_HS;
+
+       if (msg->flags & I2C_M_TEN)
+               w |= OMAP_I2C_CON_XA;
+       if (!(msg->flags & I2C_M_RD))
+               w |= OMAP_I2C_CON_TRX;
+
+       if (!dev->b_hw && stop)
+               w |= OMAP_I2C_CON_STP;
+
+       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+
+       if (dev->b_hw && stop) {
+               /* H/w behavior: dont write stt and stp together.. */
+               while (omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) &
+                      OMAP_I2C_CON_STT) {
+                       /* Dont do anything - this will come in a
+                        * couple of loops at max */
+               }
+               w |= OMAP_I2C_CON_STP;
+               w &= ~OMAP_I2C_CON_STT;
+               omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+       }
+       /* We dont get data in one millisec.. some thing is definitely
+        * and badly wrong!! */
+       if ((cpu_is_omap15xx()) && dev->rev1)
+               r = omap_i2c_rev1_wait_event(dev, MSECOND);
+       else
+               r = omap_i2c_wait_event(dev, MSECOND);
+       dev->buf_len = 0;
+       if (r < 0) {
+               dev_err("controller error %d\n", r);
+               omap_i2c_init(dev);
+               return r;
+       }
+
+       if (!dev->cmd_err)
+               return 0;
+
+       /* We have an error */
+       if (dev->cmd_err & (OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR |
+                           OMAP_I2C_STAT_XUDF)) {
+               /* Reprogram the controller ->NOTE 2 as in flow chart of TRM */
+               omap_i2c_init(dev);
+               return -EIO;
+       }
+
+       if (dev->cmd_err & OMAP_I2C_STAT_NACK) {
+               /* Reprogram the controller ->NOTE 2 as in flow chart of TRM */
+               omap_i2c_init(dev);
+               if (msg->flags & I2C_M_IGNORE_NAK)
+                       return 0;
+               return -EREMOTEIO;
+       }
+       return -EIO;
+}
+
+/*
+ * Prepare controller for a transaction and call omap_i2c_xfer_msg
+ * to do the work during transfer processing
+ */
+static int
+omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+       struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
+       int i;
+       int r;
+
+       dbg_entry("adap=%x msgs=%x num=%x", (u32) adap, (u32) msgs, num);
+       r = omap_i2c_wait_for_bb(dev);
+       if (r < 0) {
+               dev_err("timedout waiting for bus to free\n");
+               goto out;
+       }
+
+       for (i = 0; i < num; i++) {
+               r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
+               if (r != 0)
+                       break;
+       }
+
+       if (r == 0)
+               r = num;
+out:
+       return r;
+}
+
+static u32 omap_i2c_func(struct i2c_adapter *adap)
+{
+       dbg_entry("adap=%x", (u32) adap);
+       return I2C_FUNC_I2C;
+}
+
+static const struct i2c_algorithm omap_i2c_algo = {
+       .master_xfer = omap_i2c_xfer,
+       .functionality = omap_i2c_func,
+};
+
+static int omap_register_i2c_bus(int bus_id, unsigned long base,
+                         u32 clkrate, u32 func_clk)
+{
+       struct omap_i2c_dev *dev;
+       struct i2c_adapter *adap;
+       int r = 0;
+       dbg_entry("bus_id=%x base=%x clkrate=%x func_clk=%x info=%x len=%x",
+                 bus_id, base, clkrate, func_clk, (u32) info, len);
+       dev = calloc(sizeof(struct omap_i2c_dev), 1);
+       if (!dev) {
+               dev_err("malloc failed for omap_i2c_dev");
+               return -ENOMEM;
+       }
+
+       if (!clkrate)
+               clkrate = 100;
+
+       dev->speed = clkrate;
+       dev->fclk = func_clk;
+       dev->base = base;
+
+       if (cpu_is_omap15xx())
+               dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20;
+
+       if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+               /* Set up the fifo size - Get total size */
+               dev->fifo_size = 0x8 <<
+                   ((omap_i2c_read_reg(dev, OMAP_I2C_BUFSTAT_REG) >> 14) &
+                    0x3);
+               /*
+                * Set up notification threshold as half the total available
+                * size. This is to ensure that we can handle the status on
+                * int call back latencies
+                */
+               dev->fifo_size = (dev->fifo_size / 2);
+               dev->b_hw = 1;  /* Enable hardware fixes */
+       }
+
+       /* reset ASAP, clearing any IRQs */
+       omap_i2c_init(dev);
+
+       r = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
+       dev_dbg("bus %d rev%d.%d at %d kHz\n",
+               bus_id, r >> 4, r & 0xf, dev->speed);
+
+       adap = &dev->adapter;
+       i2c_set_adapdata(adap, dev);
+       strncpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
+       adap->algo = &omap_i2c_algo;
+       adap->dev.parent = NULL;
+
+       /* i2c device drivers may be active on return from add_adapter() */
+       adap->nr = bus_id;
+       r = i2c_add_numbered_adapter(adap);
+       if (r) {
+               dev_err("failure adding adapter %d\n", r);
+               free(dev);
+       }
+       return r;
+}
+
+static int omap_i2c_probe(struct device_d *dev)
+{
+        struct i2c_omap_platform_data *i2cp =
+                (struct i2c_omap_platform_data *) (dev->platform_data);
+        if (i2cp == NULL) {
+                dev_err("I2c_OMAP: need platform data\n");
+                return -EINVAL;
+        }
+       return omap_register_i2c_bus(i2cp->bus_id,
+                                    dev->map_base,
+                                    i2cp->i2c_clock_speed,
+                                    i2cp->func_clk);
+}
+
+static struct driver_d omapi2c_drv = {
+       .name = OMAP_I2C_ADAPTER_NAME,
+       .probe = omap_i2c_probe,
+       .type = DEVICE_TYPE_I2C,
+};
+
+static int omap_i2cdrv_init(void)
+{
+       int ret;
+       ret = register_driver(&omapi2c_drv);
+       return ret;
+}
+device_initcall(omap_i2cdrv_init);
drivers/i2c/busses/Kconfig 2008-06-19 08:51:23.000000000 -0500 renamed from drivers/i2c/busses/Kconfig 2008-06-19 08:42:46.000000000 -0500 +7 -0
Index: u-boot-v2.git/drivers/i2c/busses/Kconfig
===================================================================
@@ -4,4 +4,11 @@
 
 menu "I2C Hardware Bus support"
 
+config I2C_OMAP
+       bool "OMAP I2C adapter"
+       depends on ARCH_OMAP
+       help
+         If you say yes to this option, support will be included for the
+         I2C interface on the Texas Instruments OMAP family of processors.
+         For details see http://www.ti.com/omap.
 endmenu
include/asm-arm/arch-omap/i2c.h 2008-06-19 08:51:23.000000000 -0500 renamed from dev/null 1970-01-01 00:00:00.000000000 +0000 +154 -0

154 lines not on this page · raw message

#41 lore raw

PATCH 9/9 U-boot-V2:Boards:SDP3430 I2C bus1

In reply to Robert Schwebel

Registers i2c adapters used when CONFIG_I2C_OMAP
is enabled in config.

This patch additionally fixes a minor sparse
warning sdram_dev

---
 board/omap/board-sdp343x.c |   24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)
board/omap/board-sdp343x.c 2008-06-19 08:51:37.000000000 -0500 renamed from board/omap/board-sdp343x.c 2008-06-19 08:39:57.000000000 -0500 +23 -1
Index: u-boot-v2.git/board/omap/board-sdp343x.c
===================================================================
@@ -54,6 +54,7 @@
 #include <asm/arch/syslib.h>
 #include <asm/arch/control.h>
 #include <asm/arch/omap3-mux.h>
+#include <asm/arch/i2c.h>
 #include "board-sdp343x.h"
 
 /******************** Board Boot Time *******************/
@@ -642,7 +643,7 @@
 console_initcall(sdp3430_console_init);
 #endif                         /* CONFIG_DRIVER_SERIAL_NS16550 */
 
-struct device_d sdram_dev = {
+static struct device_d sdram_dev = {
        .name = "ram",
        .id = "ram0",
 
@@ -665,6 +666,21 @@
 };
 #endif
 
+#ifdef CONFIG_I2C_OMAP
+static struct i2c_omap_platform_data sdp343_i2c1 = {
+       .bus_id = 0,
+       .i2c_clock_speed = OMAP_I2C_CLK_2P6M,
+       .func_clk = OMAP_I2C_FCLK_96MHZ,
+};
+static struct device_d sdp3430_i2c1 = {
+       .name = OMAP_I2C_ADAPTER_NAME,
+       .id = "omap-i2c0",
+       .map_base = OMAP_I2C1_BASE,
+       .platform_data = (void *)&sdp343_i2c1,
+       .type = DEVICE_TYPE_I2C,
+};
+#endif
+
 static int sdp3430_devices_init(void)
 {
        int ret;
@@ -676,6 +692,12 @@
        if (ret)
                goto failed;
 #endif
+#ifdef CONFIG_I2C_OMAP
+       ret = register_device(&sdp3430_i2c1);
+       if (ret)
+               goto failed;
+#endif
+
 failed:
        return ret;
 }
#42 lore raw

cover U-boot-V2: Introduce I2C support for SDP3430

In reply to Timur Tabi
Quoted 6 lines · Timur Tabi
Quoted 3 lines

It does not have i2c support. And IMHO, using kernel like i2c addition in U-Boot v2 is appropriate. Why this is not a bloat U-Boot v2?

If it isn't, then it means that U-Boot V2 will be pretty bloated in general.

Please have a look at the code base first and post *then* instead of speculating.

Quoted 3 lines

Sounds to me like U-Boot V2 is just a repacked Linux kernel. We could probably save ourselves a lot of trouble if we just took the DDR and CPU register initialization code in U-Boot and moved it to the kernel.

It might be a good opportunity to check the code now ... :-)

rsc

Signature · 5 lines
 Dipl.-Ing. Robert Schwebel | http://www.pengutronix.de
 Pengutronix - Linux Solutions for Science and Industry
   Handelsregister:  Amtsgericht Hildesheim, HRA 2686
     Hannoversche Str. 2, 31134 Hildesheim, Germany
   Phone: +49-5121-206917-0 |  Fax: +49-5121-206917-9