* i2c driver doubts [not found] ` <fdaba91e0907180554x69f0023dk5359f26b2ebf758d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2009-07-18 12:57 ` Stefano Tebaldi [not found] ` <fdaba91e0907180557n32663ecdy7ce5c6818f4694ab-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 4+ messages in thread From: Stefano Tebaldi @ 2009-07-18 12:57 UTC (permalink / raw) To: linux-i2c-u79uwXL29TY76Z2rM5mHXA Hi all, I am quite newbie about Linux Kernel development and in particular i2c driver. I am trying to write a i2c driver for a chip and I have the following doubts (I am using a Kernel 2.6 with the new style model instead of deprecated old legacy model): 1) I find quite confusing how the Linux system knows about i2c device and how I can indicate in my i2c driver the device I want to control and to communicate. I have seen that in the probe function, the i2c_client struct is passed as argument and I have understood that this struct is filled automatically by the Kernel. This struct contains some important information on my device such as address, irq, etc and it has to be used in the driver to communicate with the device. But my question is: where the Kernel know this device's details and where in my driver I have to indicate the device I want to control ? Is it the name in the i2c_driver struct driver field or id_table field ? If so, how can I know the right string to use for identifing my device ? 2) since at the moment I have no the board with the chip for what I am writing this driver, I would like to perform anyway some test on it using i2c_stub module. Do you think it makes sense ? At this point I have again the doubt at the 1) point: How can I indicate in my driver that it is for i2c_stub virtual chip ? 3) Is it possible to address two chip in a single driver (module) ? Because i2c_client struct has only one addr field. Have I to write two different drivers or for example can I obtain that calling in the module init two time i2c_add_driver() using two different i2c_driver struct, etc ? I read something about udev that probably can help to do that issue. What do you think about ? in addition, I am using sysfs for exporting device information to userspace like many drivers of this type do 4) For reading register values I have seen to use generally for example the i2c_smbus_read_byte_data() passing to it the i2c_client struct (for the device address) as first argument and the register address as second. In some cases, for reading the value of 6 contiguous registers, I have seen to use the i2c_transfer() sending first a i2c message of this type: struct i2c_msg msg1[] = { { client->addr, 0, 1, &type }, }; and then this one struct i2c_msg msg2[] = { { client->addr, I2C_M_RD, 6, d }, }; the last message is clear for me (d is u8 d[6]), but the first absolutely not. Can anyone explain to me ? How can I indicate the register address ? Is msg1 needed for this purpose ? Can I obtain the same result using i2c_smbus_read_block_data() ? sorry for the mail length and my poor english thank you very much. Any advice is welcome Stefano ^ permalink raw reply [flat|nested] 4+ messages in thread
[parent not found: <fdaba91e0907180557n32663ecdy7ce5c6818f4694ab-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: i2c driver doubts [not found] ` <fdaba91e0907180557n32663ecdy7ce5c6818f4694ab-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2009-07-24 8:37 ` Jean Delvare [not found] ` <20090724103738.1eac9a3b-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org> 0 siblings, 1 reply; 4+ messages in thread From: Jean Delvare @ 2009-07-24 8:37 UTC (permalink / raw) To: Stefano Tebaldi; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA Hi Stefano, On Sat, 18 Jul 2009 14:57:17 +0200, Stefano Tebaldi wrote: > I am quite newbie about Linux Kernel development and in particular i2c driver. > I am trying to write a i2c driver for a chip and I have the following > doubts (I am using a Kernel 2.6 > with the new style model instead of deprecated old legacy model): > > 1) I find quite confusing how the Linux system knows about i2c device > and how I can indicate in my i2c driver the device I want to control > and to communicate. > I have seen that in the probe function, the i2c_client struct is > passed as argument and I have understood that this struct is filled > automatically by the Kernel. This struct contains some important There is nothing automatic about it. All these values have to be provided explicitly, the kernel usually can't guess them. In most cases they come from platform data (on embedded systems) or from bridge drivers (for TV adapters.) > information on my device such as address, irq, etc and it has to be > used in the driver to communicate with the device. But my question is: > where the Kernel know this device's details and where in my driver I > have to indicate the device > I want to control ? Is it the name in the i2c_driver struct driver > field or id_table field ? If so, how can I know the right string to > use for identifing my device ? Assuming your kernel is recent enough (>= 2.6.25), the strings used to match an i2c driver with an i2c device are the ones listed in the type field in the struct i2c_device_id array attached to your driver. For example, the lm83 driver looks like this: static const struct i2c_device_id lm83_id[] = { { "lm83", lm83 }, { "lm82", lm82 }, { } }; MODULE_DEVICE_TABLE(i2c, lm83_id); static struct i2c_driver lm83_driver = { (...) .id_table = lm83_id, (...) }; This means that I2C devices named either "lm82" or "lm83" will be bound to the lm83 driver. These name strings are arbitrary. It is strongly recommended to use the name of the I2C chip with lowercase letters. The key point is that the strings must be unique, and using the chip name is a good way to achieve this. > 2) since at the moment I have no the board with the chip for what I am > writing this driver, I would like to perform anyway some test on it > using i2c_stub module. Do you think it makes sense ? Yes it does, the i2c-sub driver was written exactly for this. > At this point I have again the doubt at the 1) point: How can I > indicate in my driver that it is for i2c_stub virtual chip ? If your device can be detected somehow, you can implement the .detect() callback in your driver. This will let i2c-core instantiate the device for you. If not, you need kernel >= 2.6.31-rc1, which has a sysfs interface to instantiate (and delete) i2c devices from user-space. With older kernels you can make use of the I2C_CLIENT_INSMOD* macros, which will let you create devices at driver load time, but beware this is deprecated and will be removed in the future. If you haven't yet, I strongly suggest reading Documentation/i2c/instantiating-devices > 3) Is it possible to address two chip in a single driver (module) ? Not sure if you mean two different chip instances, or two different chip types, but the answer to both questions is yes. > Because i2c_client struct has only one addr field. Have I to write two > different drivers or for example can I obtain that calling in the > module init > two time i2c_add_driver() using two different i2c_driver struct, etc ? You're quite confused I'm afraid. A driver is a driver, a device is a device. Don't mix the concepts. Just because you have two devices thankfully doesn't mean you need two drivers. The same driver can handle as many devices as you want. So you'll only have one struct i2c_driver, and only call i2c_add_driver() once. > I read something about udev that probably can help to do that issue. > What do you think about ? in addition, I am using sysfs for exporting > device information to userspace like many drivers of this type do udev has nothing to do with this, it's a user-space thing. > 4) For reading register values I have seen to use generally for > example the i2c_smbus_read_byte_data() passing to it the i2c_client > struct (for the device address) as first argument and the register > address as second. i2c_client isn't passed only for the address, otherwise we'd just pass the address. It also has a pointer to the underlying I2C segment (for physical access) as well as a number of (rarely used) flags defining the transaction details. > In some cases, for reading the value of 6 contiguous registers, I have > seen to use the i2c_transfer() sending first a i2c message of this > type: > > struct i2c_msg msg1[] = { > { client->addr, 0, 1, &type }, > }; > > and then this one > > struct i2c_msg msg2[] = { > { client->addr, I2C_M_RD, 6, d }, > }; > > the last message is clear for me (d is u8 d[6]), but the first > absolutely not. Can anyone explain to me ? > How can I indicate the > register address ? Is msg1 needed for this purpose ? "type" in the first message is equivalent to the register address you pass as the second parameter to i2c_smbus_read_byte_data(). In most cases this is the address of the first register to read, and then the chip auto-increments the address for each byte you read (second message). > Can I obtain the same result using i2c_smbus_read_block_data() ? No, use i2c_smbus_read_i2c_block_data(). i2c_smbus_read_block_data() is the SMBus variant, where you receive a block size first and only then the data. SMBus devices do this but I2C devices don't. Hope that helps, -- Jean Delvare http://khali.linux-fr.org/wishlist.html ^ permalink raw reply [flat|nested] 4+ messages in thread
[parent not found: <20090724103738.1eac9a3b-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>]
* Re: i2c driver doubts [not found] ` <20090724103738.1eac9a3b-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org> @ 2009-07-24 15:49 ` Stefano Tebaldi [not found] ` <fdaba91e0907240849h6b3f1116je71acd059145a142-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 4+ messages in thread From: Stefano Tebaldi @ 2009-07-24 15:49 UTC (permalink / raw) To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA Hi Jean, thank you very much for your answers some other questions below 2009/7/24 Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>: >> At this point I have again the doubt at the 1) point: How can I >> indicate in my driver that it is for i2c_stub virtual chip ? > > If your device can be detected somehow, you can implement the .detect() > callback in your driver. This will let i2c-core instantiate the device > for you. > > If not, you need kernel >= 2.6.31-rc1, which has a sysfs interface to > instantiate (and delete) i2c devices from user-space. With older > kernels you can make use of the I2C_CLIENT_INSMOD* macros, which will > let you create devices at driver load time, but beware this is > deprecated and will be removed in the future. > > If you haven't yet, I strongly suggest reading > Documentation/i2c/instantiating-devices reading this document and asking for that issue, I have understood that I have to add i2c device configuration in i2c_board_info struct and call the i2c_register_board_info() in a specific architecture file describing platform I am using (for example, for arm architecture, this file can be linux/arch/arm/mach-pxa/mioa701.c or pcm990-baseboard.c) Currently I am using a standard PC and so for x86 architecture I was not able to find the right place where insert this registration. Then I tried to insert it directly in my driver, but I had an i2c_register_board_info() implementation missing error during linkage of my module and then finally I used i2c_new_device() instead of i2c_register_board_info() (as described in method 2 of instantiating-devices) and now things work using i2c-stub. I am using a 2.6.30 kernel. I can also try I2C_CLIENT_INSMOD* macros or better update to kernel >= 2.6.31-rc1 and try sysfs interface to instantiate i2c devices as you have suggested >> In some cases, for reading the value of 6 contiguous registers, I have >> seen to use the i2c_transfer() sending first a i2c message of this >> type: >> >> struct i2c_msg msg1[] = { >> { client->addr, 0, 1, &type }, >> }; >> >> and then this one >> >> struct i2c_msg msg2[] = { >> { client->addr, I2C_M_RD, 6, d }, >> }; >> >> the last message is clear for me (d is u8 d[6]), but the first >> absolutely not. Can anyone explain to me ? >> How can I indicate the >> register address ? Is msg1 needed for this purpose ? > > "type" in the first message is equivalent to the register address you > pass as the second parameter to i2c_smbus_read_byte_data(). In most > cases this is the address of the first register to read, and then the > chip auto-increments the address for each byte you read (second > message). > >> Can I obtain the same result using i2c_smbus_read_block_data() ? > > No, use i2c_smbus_read_i2c_block_data(). i2c_smbus_read_block_data() is > the SMBus variant, where you receive a block size first and only then > the data. SMBus devices do this but I2C devices don't. another question related to SMBus API: if I have two contigous registers each one containing 1 byte data and I use i2c_smbus_read_word_data() passing the address of the first register, can I obtain back the value of the two registers ? moreover, I read in Documentation/i2c/writing-clients the following: "If you can choose between plain I2C communication and SMBus level communication, please use the latter. All adapters understand SMBus level commands, but only some of them understand plain I2C!" Does it mean that if possibile is better to use SMBus API ? But I anderstood that some SMBus functionalities could not be supported by some devices and i2c_check_functionality() is used for this purpose. Is it correct ? ^ permalink raw reply [flat|nested] 4+ messages in thread
[parent not found: <fdaba91e0907240849h6b3f1116je71acd059145a142-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: i2c driver doubts [not found] ` <fdaba91e0907240849h6b3f1116je71acd059145a142-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2009-07-24 17:05 ` Jean Delvare 0 siblings, 0 replies; 4+ messages in thread From: Jean Delvare @ 2009-07-24 17:05 UTC (permalink / raw) To: Stefano Tebaldi; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA Hi Stefano, On Fri, 24 Jul 2009 17:49:32 +0200, Stefano Tebaldi wrote: > 2009/7/24 Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>: > > If your device can be detected somehow, you can implement the .detect() > > callback in your driver. This will let i2c-core instantiate the device > > for you. > > > > If not, you need kernel >= 2.6.31-rc1, which has a sysfs interface to > > instantiate (and delete) i2c devices from user-space. With older > > kernels you can make use of the I2C_CLIENT_INSMOD* macros, which will > > let you create devices at driver load time, but beware this is > > deprecated and will be removed in the future. > > > > If you haven't yet, I strongly suggest reading > > Documentation/i2c/instantiating-devices > > reading this document and asking for that issue, I have understood > that I have to add i2c device configuration in i2c_board_info struct > and > call the i2c_register_board_info() in a specific architecture file > describing platform I am using (for example, for arm architecture, > this file can be > linux/arch/arm/mach-pxa/mioa701.c or pcm990-baseboard.c) > Currently I am using a standard PC and so for x86 architecture I was > not able to find the right place where insert this registration. Then > I tried to insert it directly in my driver, but > I had an i2c_register_board_info() implementation missing error during i2c_register_board_info() requires fixed i2c adapter numbers, which x86 doesn't implement. So you indeed can't use i2c_register_board_info(). > linkage of my module and then finally I used i2c_new_device() instead > of i2c_register_board_info() (as described in method 2 of > instantiating-devices) and now things work using i2c-stub. > I am using a 2.6.30 kernel. I can also try I2C_CLIENT_INSMOD* macros > or better update to kernel >= 2.6.31-rc1 and try sysfs interface to > instantiate i2c devices as you have suggested i2c_new_device() indeed works if you don't mind patching i2c-stub locally. If this is only for temporary testing I guess this is acceptable. > > (...) > > No, use i2c_smbus_read_i2c_block_data(). i2c_smbus_read_block_data() is > > the SMBus variant, where you receive a block size first and only then > > the data. SMBus devices do this but I2C devices don't. > > another question related to SMBus API: if I have two contigous > registers each one containing 1 byte data and I use > i2c_smbus_read_word_data() passing the address of the first register, > can I obtain back the value of the two registers ? Depends on the hardware implementation on the I2C chip side. Some chips do support it, some do not. Just try... or look at the datasheet of your chip. > moreover, I read in Documentation/i2c/writing-clients the following: > > "If you can choose between plain I2C communication and SMBus level > communication, please use the latter. All adapters understand SMBus level > commands, but only some of them understand plain I2C!" > > Does it mean that if possibile is better to use SMBus API ? Yes. > But I anderstood that some SMBus functionalities could not be > supported by some devices and i2c_check_functionality() is used for > this purpose. Is it correct ? This is correct. But controllers that can do I2C, can do all of SMBus by definition. OTOH SMBus controllers can't do I2C, so if you use i2c_transfer() (I2C) your code will not work on SMBus controllers. Almost all x86 systems implement SMBus rather than full I2C, so you really want to use i2c_smbus_*() functions and not i2c_transfer(). Now you're right that SMBus controllers don't have to implement all of SMBus. Usually you have to find the correct balance between portability and speed. If you only use byte transactions, your code will run on all SMBus controllers, but may be slow if your chip has a large number of (used) registers. If you start using word or block transactions, some controllers might not support them and your driver will not work there. As a rule of thumb, word transactions are widely supported, while block transactions are not. The right balance really depends on the speed improvement you get from using block transactions for your specific chip, and on how many different systems your driver must work. There are some cases where portability doesn't matter at all. And if you really need both speed and portability, you're free to implement two (or more) register access functions in your driver, and select the best one at run-time using i2c_check_functionality(). -- Jean Delvare http://khali.linux-fr.org/wishlist.html ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2009-07-24 17:05 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <fdaba91e0907180554x69f0023dk5359f26b2ebf758d@mail.gmail.com>
[not found] ` <fdaba91e0907180554x69f0023dk5359f26b2ebf758d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-07-18 12:57 ` i2c driver doubts Stefano Tebaldi
[not found] ` <fdaba91e0907180557n32663ecdy7ce5c6818f4694ab-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-07-24 8:37 ` Jean Delvare
[not found] ` <20090724103738.1eac9a3b-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2009-07-24 15:49 ` Stefano Tebaldi
[not found] ` <fdaba91e0907240849h6b3f1116je71acd059145a142-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-07-24 17:05 ` Jean Delvare
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).