i2c: slave support framework for Linux devices

From: Kachalov Anton
Date: Wed Jul 20 2016 - 17:51:32 EST


Hello.

I'm working on multi-master i2c support in Aspeed SoC (AST2150, AST2300 and so on) and succeed with event passing to the slave software backend. Besides AST has two operation modes: byte transfer and buffer transfer. While i2c slave framework operates over bytes. In current scheme I would able to receive an interrupt on buffer fill then call N-times event function with one byte. It is a little overhead there.

Second one thing that I want to point is a slave support in I2C MUX/switch drivers. For instance I use PCA9548 switch and want to have N (N <= 8) slaves (one per channel). The generic switching algo tries to deselect channel each time transmission has ended. Sametime, pca954x allows to leave channel selected. It is very useful for slave operation mode (e.g. IPMB listener). There is no evidence from i2c-mux point of view if the channel is really deselected or not. If I want to code a generic slave support to re-register slaves on parent adapter (program i2c IP reg with proper slave address) each time I switch between channels, I need to leave channel "open" until I explicitly wants to deselect the channel to make slave driver operable. Like a "lock" channel function. E.g. check for lock flag before doing deselect in i2c_mux_smbus_xfer. There are four duplicate select/deselect code in each *mux*xfer routine that might be wrapped with channel lock check for the described approach. For generic i2c-mux slave switching it is needed a slave_switch function to be implemented in slave driver (mux/pca954x and bus/aspeed for instance).

In current implementation I did several hacks: dummy i2c slave driver for i2c-mux-pca954x registered on parent adapter's bus, proxy callback that passes data to the mux'es appropriate slave, manual call algo->reg_slave/unreg_slave to avoid deadlocks in select/deselect handlers.
One of the most tricky part here is calculating starting i2c bus number for array's offset (adap_off field) in slave_register/unregister driver's routines. Better to have something like a i2c_mux_channel(...) routine to access private "chan_id" field of mux. The second trick is a hotfix of algo array (came from i2c-mux as const value) to fill it with additional slaves function pointers.

Here is a patch:
https://github.com/ya-mouse/openbmc-target/blob/master/aspeed/patches-4.4/0065-i2c-slave-mux-pca954x.patch

What should be improved in i2c-mux and i2c slave framework to rewrite such code to have robust code without a number of hacks, tricks and workarounds? Any suggestions and comments are welcome.