Current-Users archive

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

Re: Upgrading from 5.1_STABLE to 5.99.46 on Sun Fire V100



On Mon, Feb 28, 2011 at 06:53:30PM +0000, Eduardo Horvath wrote:
> On Mon, 28 Feb 2011, Rafal Boni wrote:
> 
> > and the OF device tree looks like so:
> > 
> >     f0069d48: /pci
> >     [...]
> >     f007b6bc: /pci/pmu@3
> >     f007be84: /pci/pmu@3/i2c@0,0
> >     f007d31c: /pci/pmu@3/i2c@0,0/temperature@0,30 ("i2c-max1617")
> >     f007d48c: /pci/pmu@3/i2c@0,0/dimm@0,a8        ("i2c-at34c02")
> >     (more dimms)
> >     f007d6b4: /pci/pmu@3/i2c@0,0/i2c-nvram@0,a0   ("i2c-at24c64")
> >     f007e1cc: /pci/pmu@3/i2c@0,0/i2c-nvram@0,a0/idprom@1fd8
> >     f007e480: /pci/pmu@3/i2c@0,0/motherboard-fru@0,a2 ("i2c-at24c64")
> >     f007f018: /pci/pmu@3/ppm@0,b3                 ("SUNW,smbus-ppm")
> >     f007f28c: /pci/pmu@3/beep@0,b2                ("SUNW,smbus-beep")
> >     f007f3a4: /pci/pmu@3/fan-control@0,c8         ("SUNW,smbus-fan-control")
> >     [...]
> > 
> > Note that what the i2c controller sees as children on my machine are the
> > 'ppm', 'beep' and 'fan-control' instead of (what I would expect):
> >  "temparature", N instances of "dimm", "i2c-nvram", "motherboard-fru".
> > 
> > What I'm not 100% sure of is whether the peers of the i2c bus should be
> > passed as well or not -- it doesn't make sense to me from the OF tree,
> > but I'm also relatively clueless about OF, so maybe I am missing some-
> > thing.
> 
> I think what you're seeing here is that pmu@3 is the SMBUS controller and 
> /pci/pmu@3/i2c@0,0 is SMBUS to I2C bridge chip.  You should dump the 
> properties of /pci/pmu@3 and /pci/pmu@3/i2c@0,0 to be sure.

I think you're right... this is what /pci/pmu@3/i2c@0,0 has for props:

f007be84: /pci/pmu@3/i2c@0,0

#address-cells          00000002 ........ ........ ........     2
#size-cells             00000000 ........ ........ ........     0
compatible              6932632d 736d6275 7300.... ........   "i2c-smbus"
interrupts              00000001 ........ ........ ........   ....
name                    69326300 ........ ........ ........   "i2c"
reg                     00000000 00000000 00000100 00000001   ................
            0010:       00000000 00000100 ........ ........   ........

And here's /pci/pmu@3:

f007b6bc: /pci/pmu@3

#address-cells          00000002 ........ ........ ........     2
#size-cells             00000001 ........ ........ ........     1
class-code              00000000 ........ ........ ........   ....
compatible              70636931 3062392c 37313031 00......   "pci10b9,7101"
            000d:       70636963 6c617373 2c303030 30303000   "pciclass,000000"
device-id               00007101 ........ ........ ........   ..q.
devsel-speed            00000001 ........ ........ ........   ....
max-latency             00000000 ........ ........ ........   ....
min-grant               00000000 ........ ........ ........   ....
name                    706d7500 ........ ........ ........   "pmu"
ranges                  00000000 00000000 00001800 00000000   ................
            0010:       00000000 00000100 00000001 00000000   ................
            0020:       81001810 00000000 00004000 00000100   ..........@.....
            0030:       00000002 00000000 81001814 00000000   ................
            0040:       00000000 00000100 ........ ........   ........
reg                     00001800 00000000 00000000 00000000   ................
            0010:       00000000 81001810 00000000 00004000   ..............@.
            0020:       00000000 00000010 ........ ........   ........
revision-id             00000000 ........ ........ ........   ....
vendor-id               000010b9 ........ ........ ........   ....

But I'm still slightly clueless as far as whether that means I can treat
the smbus devices (fan-control, ppm, beep) as dumb i2c devices, or not.

Adding a loop in of_enter_i2c_devs() that checks for the 'i2c' child
device and enumerates its' children if found gets me the missing i2c
devices, but I'm not sure if I should skip all the smbus devices or
not (and if so, how best to detect the situation):

diff --git a/sys/dev/ofw/ofw_subr.c b/sys/dev/ofw/ofw_subr.c
index 0b074d0..2fa5044 100644
--- a/sys/dev/ofw/ofw_subr.c
+++ b/sys/dev/ofw/ofw_subr.c
@@ -335,7 +335,7 @@ of_get_mode_string(char *buffer, int len)
 void
 of_enter_i2c_devs(prop_dictionary_t props, int ofnode, size_t cell_size)
 {
-       int node, len;
+       int node, iicnode, len;
        char name[32];
        uint64_t reg64;
        uint32_t reg32;
@@ -345,9 +345,20 @@ of_enter_i2c_devs(prop_dictionary_t props, int ofnode, 
size_t cell_size)
 
        array = prop_array_create();
 
+       iicnode = 0;
        for (node = OF_child(ofnode); node; node = OF_peer(node)) {
                if (OF_getprop(node, "name", name, sizeof(name)) <= 0)
                        continue;
+
+               /* 
+                * Could be an SMBus with e.g. an SMBus-I2C bridge; handle the
+                * I2C bus below if we find one.
+                */
+               if (strcmp(name, "i2c") == 0) {
+                       iicnode = node;
+                       continue;
+               }
+
                len = OF_getproplen(node, "reg");
                addr = 0;
                if (cell_size == 8 && len >= sizeof(reg64)) {
@@ -375,6 +386,39 @@ of_enter_i2c_devs(prop_dictionary_t props, int ofnode, 
size_t cell_size)
                prop_object_release(dev);
        }
 
+       if (iicnode != 0) {
+               for (node = OF_child(iicnode); node; node = OF_peer(node)) {
+                       if (OF_getprop(node, "name", name, sizeof(name)) <= 0)
+                               continue;
+
+                       len = OF_getproplen(node, "reg");
+                       addr = 0;
+                       if (cell_size == 8 && len >= sizeof(reg64)) {
+                               if (OF_getprop(node, "reg", &reg64, 
+                                       sizeof(reg64)) < sizeof(reg64))
+                                       continue;
+                               addr = reg64;
+                       } else if (cell_size == 4 && len >= sizeof(reg32)) {
+                               if (OF_getprop(node, "reg", &reg32, 
+                                       sizeof(reg32)) < sizeof(reg32))
+                                       continue;
+                               addr = reg32;
+                       } else {
+                               continue;
+                       }
+                       addr >>= 1;
+                       if (addr == 0) continue;
+
+                       dev = prop_dictionary_create();
+                       prop_dictionary_set_cstring(dev, "name", name);
+                       prop_dictionary_set_uint32(dev, "addr", addr);
+                       prop_dictionary_set_uint64(dev, "cookie", node);
+                       of_to_dataprop(dev, node, "compatible", "compatible");
+                       prop_array_add(array, dev);
+                       prop_object_release(dev);
+               }
+       }
+
        prop_dictionary_set(props, "i2c-child-devices", array);
        prop_object_release(array);
 }

-- 
  Time is an illusion; lunchtime, doubly so.     |/\/\|           Rafal Boni
                   -- Ford Prefect               |\/\/|      
rafal%pobox.com@localhost


Home | Main Index | Thread Index | Old Index