How to pass board specific info to I2C driver module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: Piepho Trent-B16872 
> Sent: Thursday, November 06, 2008 7:15 AM
> To: Jean Delvare
> Cc: Hu Mingkai-B21284; lm-sensors at lm-sensors.org
> Subject: Re:  How to pass board specific info to 
> I2C driver module
> 
> On Wed, 5 Nov 2008, Jean Delvare wrote:
> > On Mon, 27 Oct 2008 16:52:06 +0800, Hu Mingkai-B21284 wrote:
> > One thing that makes sense to pass to the driver is the chip's work 
> > voltage, if measurements depend on it. This isn't something 
> libsensors 
> > handles (nor do I think it should).
> 
> This chip basically returns voltage in units of Vdd/1024, 
> where Vdd is the work voltage.  Can't libsensors scale 
> voltages?  I still think platform data is the way to go, but 
> it should be possible to do it with libsensors, shouldn't it?
> 
> >> Here is the way I can think of:
> >> 1. to use dts file to pass the info to the module.
> >>     This way make the driver is bound to OF implement.
> >
> > I don't think that would make your driver OF-dependent. 
> Every device 
> > can have platform data associated with it. So you could 
> convert the OF 
> > data to driver-specific platform data and the driver 
> doesn't even have 
> > to know that it has been instantiated through OF.
> 
> This is a problem that's been brought up before.  What you 
> need is small driver-specific block of code that turns an OF 
> device node's properties into a filled in platform data 
> structure.  It's not entirely clear where it should go, 
> somewhere in drivers/of or somewhere in drivers/hwmon, like 
> in drivers/hwmon/mcp3021.c?  But that's a small detail.
> 
> A bigger problem is that there are a lot of i2c clients, so 
> while writing one OF binding function isn't a big deal, 
> writing bindings for everything ends up being a rather large 
> amount of code and a lot of bindings to define.
> 
> The problem that doesn't have a clear solution is that i2c 
> clients can have function pointers in their platform data, 
> like pca953x for example.  You can't put functions in an OF 
> property.  So what do you do here?
> 
> One thing I thought of would be a function that's like 
> i2c_register_board_info(), but instead:
> 
> of_i2c_register_platform_data(const char *node_path, void 
> *platform_data);
> 
> The other stuff in struct i2c_board_info (driver_name, type, 
> flags, addr, irq) isn't needed because it already comes from 
> the OF device tree.  It's only the platform_data that's a 
> problem.  Instead of binding the data to a device using the 
> adapter number and device address like 
> i2c_register_board_info() does, the OF path of the device is used.
> 
> Code like this:
> 
> static struct pca953x_platform_data pdata = { ... }; static 
> struct i2c_board_info __initdata gpiochips[] = {
>  	{ I2C_BOARD_INFO("pca953x", 0x18), .type = "pca9557", 
> .platform_data = &pdata }, }; static int __init add_gpio_chips(void) {
>  	i2c_register_board_info(1, gpiochips, ARRAY_SIZE(gpiochips));
>  	/* How do we know the adapter number will be 1?  We 
> don't!  Ugly hack */ }
> 
> Becomes this:
> 
> static struct pca953x_platform_data pdata = { ... }; static 
> int __init add_gpio_chips(void) {
>  	
> of_i2c_register_platform_data("/soc8572 at e0000000/i2c at 3100/gpio
> ", &pdata); }
> 
> The advantage here is that we can provide platform data for 
> any i2c device, without needing to add device specific OF 
> binding code for each and every device we might want.  The 
> other advantage is that we can have function pointers in the 
> platform data, which isn't possible otherwise.
> 
> The disadvantage is that the platform data is compiled into 
> the kernel, rather than in the OF device tree.  But, this is 
> the way platform data has always worked since it was created. 
>  It's the way it works now.  It's the way non-OF arches will 
> continue to work.  So maybe it's not ideal, but it's clearly 
> not the end of the world.
> 

First, thanks for your detailed description. 
If add the aboveing code in the driver code, we can't differentiate the
platform_data
for different chips. So I think the better way to get the platform_data
is from i2c 
subnode property in the dts file in the functon of_register_i2c_devices,
then fill it in the platform_data of the i2c_board_info, and then create
a i2c_client. 

but how do I name the property of the node? platform_data or vdd? I read
the ePAPR and
no results. If there are many property to pass into, it'll end up being
a rather large 
amount of code, as you found out.

> >> 2. to use the module parameter.
> >>     For different chips, the work voltage and the ratio may be
> >>     different, but the chip uses the same driver.
> >
> > That's not really practical as you found out yourself. If 
> the platform 
> > code knows the work voltage and other parameters for the 
> given system 
> > then filling platform data inside the kernel and passing it to the 
> > driver is the way to go.
> 
> The Vdd parameter can be made an array, one element for each 
> chip.  This is the standard to pass device data to a driver 
> for something like a PCI card. 
> Just run "modinfo bttv" or a hundred other drivers that work 
> this way. 
> Problems come up when you want to compile drivers into the 
> kernel, figuring out which position in the array corresponds 
> to which device, adding or removing a device changing said 
> positions, and passing function pointers.
> 
> Another solution, though I know you're not a fan of it Jean, 
> but I think it's a great idea when possible, is to make the 
> parameter a settable attribute in sysfs.  E.g, the mcp3021 
> driver would have a "vdd" attribute that one could set to 
> "3300" via sysfs.
> 
> That solves a lot of the problems.  Want it in the device 
> tree?  Put it somewhere and then have a userspace script that 
> grabs "/proc/device-tree/.../vdd" and puts it into 
> "/sys/class/hwmon/.../device/vdd".  No kernel code needed.  
> The mcp3021 driver doesn't need to know or care about the OF 
> device tree.  On non-OF arches, the value could come from DMI 
> or anything.
> 
> And sometimes it's not so simple as vdd = 3300.  Maybe vdd is 
> specific to each board and gets measured during production 
> and stored into an eeprom or on flash?  "cat /mnt/flash/vdd > 
> /sys/.../vdd" is a lot easier to do from a userspace script 
> than from the kernel!
> 
> Or maybe you have a chip with absolute voltage, like an lm87, 
> and a relative voltage chip like an mcp3021?  Suppose the Vdd 
> to the mcp3021 is one of the voltages being measured by the 
> lm87?  You could do this, no kernel code
> needed:
> 
> cat /sys/class/hwmon/hwmon0/device/in0_input > 
> /sys/class/hwmon/hwmon1/device/vdd
> 
> And many of these settings don't have obviously correct 
> values.  If you're the one who has to figure them out, being 
> able to change them while the system is running is incredibly 
> useful.  Do you remember what it was like to develop device 
> drivers before Linux had loadable modules?  You had to reboot 
> your computer for every single compile you wanted to test.  I 
> remember, and I don't want to go back to that.
> 

Yes, maybe this is the simplest way to handle this issue, as we thought
of firstly.
How do you think if it, Jean?

Thanks,
Vincent




[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux