Date: Wed, 07 Jun 2006 20:24:01 +0300 From: Andriy Gapon <avg@icyb.net.ua> To: freebsd-hackers@freebsd.org Subject: using smbus from within kernel-land Message-ID: <44870BB1.6000309@icyb.net.ua>
next in thread | raw e-mail | index | archive | help
I am writing a driver for a piece of hardware that can be communicated with only through SMBus. My SMBus controller is already supported by FreeBSD and I can do some testing from userland via ioctls of /dev/smb#. I would like to learn how to do properly the following things in kernel-land: 1. declare that my module/driver uses smbus, and make smbus and a driver for my particular smb controller be loaded when my module is loaded 2. discover smbus of interest and slave address of interest provided that I know how my hardware responds to particular commands 3. register/allocate smbus of interest and/or slave address of interest ("smbus resource") to my driver 3a. make sure that smbus will no go away (get unloaded) while my module/driver is loaded and active 3b. make sure that there will be no issues with concurrent access of "my" smbus, that is, that no activity on /dev/smb# or other activity on "my" smbus interferes my driver's smbus usage 3c. likewise to the above, make sure that nothing tries to "own" "my" slave address I see that in Linux they have some framework for using smbus and its resources from kernel-land: http://www.charmed.com/txt/writing-clients.txt I could not find anything similar in FreeBSD. I see that we use smbus in kernel-land only in two places: device smb and bktr driver. Both seem to be rather special, if I interpret things correctly. device smb seems to be a glue between smbus and user-land, so it does not claim any specific resources and translates commands from userland in one-shot fashion, without any long term resource acquirement. bktr driver seems to be both smb controller and smb client at once. So, probably, it is not worried too much about concurrency and resource ownership issues. This is what I have written so far for smbus/HW detection: sc->smbus_dev = NULL; smbus_class = devclass_find("smbus"); if (smbus_class == NULL) goto end; for (i = 0; i < 128; i++) { int j, err; uint8_t val; smbus_dev = devclass_get_device(smbus_class, i); if (smbus_dev == NULL) /* past last unit ??? */ break; for (j = 0; j < sizeof(identity)/sizeof(identity[0]); j++) { if ((err = smbus_readb(smbus_dev, SLAVE_ADDR, identity[j].reg, &val)) != 0) break; if (val != identity[j].val) break; } if (j == sizeof(identity)/sizeof(identity[0])) { /* all checks passed */ sc->smbus_dev = smbus_dev; break; } } Basically, outer loop tries to loop over all smbus devices/units I could imagine (0-127), inner loop checks identity registers/commands against expected values. Currently I check only one slave address, but I plan to add an intermediate loop that will loop over all possible 127 slave addresses. -- Andriy Gapon
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?44870BB1.6000309>