Contributed by marco on from the more-sensors-coming-your-way dept.
At home I have two boxes that I do most of my code on, a Dell PowerEdge 2500 (an i386) and a Sun Netra T1 105 (a sparc64). I like working on both of them cos the architectures are so different from each other. i386 is a 32bit little-endian arch without strict alignment requirements and its cache coherent. sparc64 on the other hand is 64bit, big endian, needs strict alignment and isn't cache coherent. If I can get code working on both these boxes it is likely to work everywhere else as well.
However, they do have some hardware specific features. One thing I really love about the sparc is the lights out management on it. Turning the machine on and off via a serial cable is cool. I can't do that on the poweredge. Another thing that is different between them is the way they do hardware monitoring. The poweredge has esm, the sparc has an i2c controller. Jordan wrote code for esm and the end of last year and I ported it into the kernel, so my poweredge was happily telling me how hot it was. Unfortunately, no driver existed for the i2c bits on my netra. Until now...
I had spent some time looking around on google for hints as to what the controller was, and whether there was doco on it but never found anything. I think I just suck at searching for stuff on the internet.
Anyway, it wasn't until someone showed me how to navigate the device tree in openfirmware that i discovered that the i2c controllers node had a property called "compatible" with the value of "i2cpcf,8584". The pcf 8584 part turns out to be the name of the chip used, which is a Phillips PCF8584. Google quickly found me a pdf and the pcfiic(4) driver for this i2c controller was on its way.
Somehow Damien Miller (djm@) found out that I was making progress on sensor support for the netra and got involved. He got working on a driver for the temp sensor and we soon had some working code for the controller and for the temp sensor. Unfortunately we came up against two problems: the generic scan didnt find the device, and the temp sensor is incredibly dumb. All you can do is read values off it, but to make any sense of those values you need configuration information. Fortunately the devices location and its configuration info is available, but in openfirmware. djm's first code hardcoded this info into his driver, but that just isn't the Right Way(tm) to do things. We needed to get openfirmware more involved.
The i2c stack in openbsd is organised similairly to the scsi stack: there are drivers for controllers, a midlayer and then drivers for the i2c devices. The i2c controller is responsible for providing access to the bus, the midlayer scans the bus and brokers access to it, and the device drivers are consumers on the bus. Thanks to this layering there is am almost total separation between the i2c controller and its devices.
The generic i2c scan routine that tries to discover which devices are on the bus uses a series of heuristics, but that didn't work for us since the pcf device was unknown and outside the address ranges we scan. This problem has cropped up before in i2c land though, and the solution is to provide a custom scan routine for the midlayer to use. This was already done on sparc64 for the alipm(4) controller, but it wouldn't work with pcfiic. The alipm device presents multiple devices to openfirmware, one of which is the i2c bus. So to scan devices on alipm you have to look for its i2c bus, and then scan that bus for the devices. pcfiic just has i2c listed against it.
Our solution to this problem was to split the scan routine up into two parts, one that found the i2c bus on a pci device, and one that scans the i2c bus. alipm uses the pci one, which in turn uses the i2c one. pcfiic just uses the i2c one directly.
The other problem of getting openfirmware info down to the i2c device driver was a bit more interesting. There was no way for us to pass any info from the controller down to the devices. The reason we want to do this is so we can get an ofw node (which the i2c controllers scan routine knows about) down to the device. This is needed with the temp sensor on the netra cos the values off the device are useless without the information in openfirmware.
We ended up adding a generic cookie member to the i2c attach args that are passed from the midlayer down to the device. Because we were providing a custom scan routine from the controller to the midlayer, we were able to get it to fill in this cooke with a pointer to the ofw node.
Using both of these changes we are now able to fully probe the i2c devices and configure them according to ofw. The good thing about these changes is that theyre agnostic about the information you pass between the controller and the device, so the same mechanism can be used on macppc to pass ofw to its i2c devices. I believe that ACPI can hold information about smbus/i2c devices, so that too could be passed along.
Anyway, apart from these changes in the i2c midlayer the code for the netras i2c bits is very straightforward. If you have a Netra T1 105 or similair you should be able to see something like the following in your sysctl hw.sensors output:
hw.sensors.0=pcfadc0, temp,cpu, temp, 31.00 degC / 87.80 degF
Pretty cool isn't it?
The pcfiic driver should also work on e450s and ultra 250s. If anyone has one of these machines and is willing to work with us we can try and get some sensor action happening on those hosts as well. Contact me and we'll figure it out.
(Comments are closed)