Nvec dt
Links
[1] [[RFC binding for nvec mfd device]] [2] Device Tree Usage [3] ePAPR specification [4] arch/arm/boot/dts/tegra20.dtsi [5] http://lists.denx.de/pipermail/u-boot/2014-April/178449.html
Intro
Here is my step-by-step vision of dt for nvec. There is few requirements: 1) DT must describe hardware, but not software. 2) DT must be enough for SW implementation.
Configurations
I. i2c_controller_master { i2c_device_master, i2c_device_master, i2c_device_slave, i2c_device_slave } II. i2c_controller_master { i2c_device_slave, i2c_device_slave } III. i2c_controller_slave { i2c_device_master, i2c_device_master, i2c_device_slave, i2c_device_slave } IV. i2c_controller_slave { i2c_device_slave, i2c_device_slave } - impossible
Addressing
a) #address-cells / #size-cells, master/slave by first value (child)
I2C controller node has #address-cells 1 or 2 (1 means master mode only, 2 mean master/slave mode possible) There are now two ways to set address in the I2C child nodes:
a) reg = <slave address> ordinary child operating in slave mode, address-cells of parent is 1
b) reg = <0 slave address> alternative form of above if address-cells is 2 (master and slave mode of controller possible)
c) reg = <1 master address> child operates in master mode, address-cells must be 2
initially, the i2c controller runs its old setup code (does not enable slave mode). If the child (in master mode operation) gets instantiated, it tells the i2c controller via some api that it should setup slave mode.
I. i2c_controller - master
devices - masters and slaves i2c_controller { reg = <0x7000c500 0x100> #address-cells = <2> i2c_device_master { reg = <0x01 0x87> } i2c_device_slave { reg = <0x00 0x87> } } |
II. i2c_controller - master
devices - all slaves i2c_controller { reg = <0x7000c500 0x100> #address-cells = <1> i2c_device_slave { reg = <0x87> } } |
III. i2c_controller - slave
devices - masters and slaves i2c_controller { reg = <0x7000c500 0x100> #address-cells = <2> i2c_device_master { reg = <0x01 0x87> } i2c_device_slave { reg = <0x00 0x87> } } |
b) extend "reg" property
I. i2c_controller - master
devices - masters and slaves i2c_controller { reg = <0x7000c500 0x100> i2c_device_master { ??? } i2c_device_slave { ??? } } |
II. i2c_controller - master
devices - all slaves i2c_controller { reg = <0x7000c500 0x100> i2c_device_slave { reg = <0x87> } } |
III. i2c_controller - slave
devices - masters and slaves i2c_controller { reg = <0x7000c500 0x100 0x87 0> i2c_device_master { reg = <0x00> } i2c_device_slave { reg = <0x87> }} |
c) use "alternate-reg" property (see PCI Bus Binding to IEEE Std 1275-1994 Standard for Boot)
I. i2c_controller - master
devices - masters and slaves i2c_controller { reg = <0x7000c500 0x100> i2c_device_master { reg = <0x89> } i2c_device_slave { reg = <0x87> } } |
II. i2c_controller - master
devices - all slaves i2c_controller { reg = <0x7000c500 0x100> i2c_device_slave { reg = <0x87> } } |
III. i2c_controller - slave
devices - masters and slaves i2c_controller { reg = <0x7000c500 0x100> alternate-reg = <0x87> i2c_device_master { reg = <0x00> } i2c_device_slave { reg = <0x87> } } |
d) use tricky bits ???
e) tricky bits on childs (TODO: make a clear description)
I. i2c_controller - master
devices - masters and slaves i2c_controller { reg = <0x7000c500 0x100> ??? i2c_device_master { reg = <0x0187> } i2c_device_slave { reg = <0x0087> } } |
II. i2c_controller - master
devices - all slaves i2c_controller { reg = <0x7000c500 0x100> i2c_device_slave { reg = <0x0087> } } |
III. i2c_controller - slave
devices - masters and slaves i2c_controller { reg = <0x7000c500 0x100> i2c_device_master { reg = <0x0187> } i2c_device_slave { reg = <0x0087> } } |
OLD
General
Root node is SOC. <name>[@<unit-address>]. : name - device type, unit-address - address, that is used to access device
a) SOC can have multiple i2c controllers. b) Some of controllers can be master and/or slave at the same time. c) Some of controllers can be connected to same i2c bus. d) In some cases slave may want attention from master.
a) SOC can have multiple i2c controllers. OK, it's current implementation
b) ??? Some of controllers can be master and/or slave at the same time. Q: Need a way for SW to select mode. How it should be done ?
i2c-slave@7000c500 { compatible = "nvidia,tegra20-i2c"; ??? }
Possible values: master, slave, master and slave, sw decides In current implementation i2c controller is master, i2c device is slave.
c) Some of controllers can be connected to same i2c bus. Q: Do we need information, that both controllers are on the same bus.
i2c-slave@7000c500 { compatible = "nvidia,tegra20-i2c"; ??? } i2c-slave@7000cf00 { compatible = "nvidia,tegra20-i2c"; ??? }
A: Useless case. Forget.
d) In some cases slave may want attention from master. Q: Who should contain information about "gpio" ? Master or slave ?
i2c-slave@7000c500 { compatible = "vendor,device"; mode = "slave"; master@87 { compatible = "nvidia,nvec"; mode = "master"; reg = <0x87>; }; }
If i2c controller don't know about gpios, then there is no reason to add this field to it's node. Only nvec knows about gpios. This is a reason why we should add gpio to nvec node.
Nvec
Root node is tegra20. This means that parent i2c node should be tegra's i2c controller.
i2c-slave@7000c500 { compatible = "nvidia,tegra20-i2c-slave"; }
Nvec is child node.
i2c-slave@7000c500 { compatible = "nvidia,tegra20-i2c-slave"; reg = <0x7000c500 0x100>; nvec@87 { compatible = "nvidia,nvec"; reg = <0x87>; }; }
Software interaction
Common: [ master ] --i2c-- [ slave ] | [ i2c-master ] ---- [ i2c-slave ] Nvec: [ Nvec ] --i2c-- [ Tegra20 ] | [ tegra20-i2c ] ---- [ nvec ] Left side - hardware components, right side - software drivers.
TODO: describe communication process
Discussion
i2c-slave@7000c500 { compatible = "nvidia,tegra20-i2c-slave", "simple-bus"; reg = <0x7000c500 0x100>; interrupts = <0 92 0x04>; #address-cells = <1>; #size-cells = <0>; clock-frequency = <80000>; clocks = <&tegra_car 67>, <&tegra_car 124>; clock-names = "div-clk", "fast-clk"; nvec@87 { compatible = "nvidia,nvec", "simple-bus"; reg = <0x87>; request-gpios = <&gpio TEGRA_GPIO(V, 2) 0>; keyboard { compatible = "nvidia,nvec-keyboard"; ... <insert key mappings here> ... }; ps2 { compatible = "nvidia,nvec-ps2"; packet-size = 6; /* for the ac100 tp */ }; events { compatible = "nvidia,nvec-events"; ... <add some system events here, e.g. lid switch, power button> ... }; charger: ac { compatible = "nvidia,nvec-ac"; }; battery { compatible = "nvidia,nvec-battery"; charger = <&charger>; }; oem { compatible = "compal,nvec-paz00"; /* ac100 specific extentions to the protocol */ }; }; };
- simple bus (smbus) - where to define
- GPIO is part of the NVEC (?)
- If you need to instantiate child nodes as Linux platform devices, this should be done in the driver for the bus. Relying on simple-bus to do this is a hack.