arm: tegra: implement NVEC driver using tegra i2c.
Subsystems (6)
v2 cover arm: tegra: implement NVEC driver using tegra i2c.
NVEC driver contains code to manage tegra i2c controller in slave mode. I2C slave support was implemented in linux kernel. The goal of this patch serie is to implement I2C slave mode in tegra drived and rework NVEC driver to use it.
Patches are based on i2c for-next.
Changes for v2:
- rebased on top of new i2c slave framework.
- old code is removed in separate patch
- documentation patch is integrated to main nvec patch
Thanks in advance
Andrey Danin (4):
i2c: tegra: implement slave mode staging/nvec: reimplement on top of tegra i2c driver staging/nvec: remove old code
dt: paz00: define nvec as child of i2c bus
.../devicetree/bindings/nvec/nvidia,nvec.txt | 21 +- arch/arm/boot/dts/tegra20-paz00.dts | 22 +- drivers/i2c/busses/Kconfig | 1 + drivers/i2c/busses/i2c-tegra.c | 119 ++++++ drivers/staging/nvec/nvec.c | 411 +++++++-------------- drivers/staging/nvec/nvec.h | 10 - 6 files changed, 269 insertions(+), 315 deletions(-)
Signature · 1 line
1.9.1
PATCH v2 1/4 i2c: tegra: implement slave mode
Initialization code is based on NVEC driver.
There is a HW bug in AP20 that was also mentioned in kernel sources for Toshiba AC100.
---
Changes for v2:
- remove hack from tegra_i2c_clock_disable
- replace slave status helper functions with local variables
- add constant for default delay count value
- add 10-bit address support
- remove read_slave_start_delay init as zero
- don't reset controller during slave registration
- slave isr returns int instead of bool
- make status related variables in slave u32 instead of unsigned int
- enable i2c slave in Kconfig
- rebase on top of new i2c slave framework
- delay workaround was added from nvec
--- drivers/i2c/busses/Kconfig | 1 + drivers/i2c/busses/i2c-tegra.c | 119 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+)
drivers/i2c/busses/Kconfig +1 -0
@@ -852,6 +852,7 @@ config I2C_SUN6I_P2WI config I2C_TEGRA tristate "NVIDIA Tegra internal I2C controller" depends on ARCH_TEGRA + select I2C_SLAVE help If you say yes to this option, support will be included for the I2C controller embedded in NVIDIA Tegra SOCs
drivers/i2c/busses/i2c-tegra.c +119 -0
172 lines not on this page · raw message
Signature · 1 line
1.9.1
Re: [PATCH v2 1/4] i2c: tegra: implement slave mode
drivers/i2c/busses/i2c-tegra.c static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) · line 486
Quoted 10 lines
drivers/i2c/busses/i2c-tegra.c +10
-0+static void tegra_i2c_slave_write (struct tegra_i2c_dev *i2c_dev,u32 val) +{ +i2c_writel (i2c_dev, val,I2C_SL_RCVD ); + +/* +* TODO: A correct fix needs to be found for this. +* +* We experience less incomplete messages with this delay than without +* it, but we don't know why. Help is appreciated. +*/
Uh oh. So I assume this is another reason for staging?
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (!i2c_dev->slave || !i2c_dev->slave->slave_cb) + return -EINVAL;
The core checks for slave_cb being valid.
drivers/i2c/busses/i2c-tegra.c static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) · line 512
Quoted 1 line
drivers/i2c/busses/i2c-tegra.c +1
-0+i2c_slave_event (i2c_dev->slave,I2C_SLAVE_STOP , &dummy);
You could use value here, too, or?
drivers/i2c/busses/i2c-tegra.c static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) · line 547
Quoted 2 lines
drivers/i2c/busses/i2c-tegra.c +2
-0+if (!tegra_i2c_slave_isr (irq, i2c_dev)) +return IRQ_HANDLED ;
Minor nit: I'd prefer == 0 here, since it reads "if not slave_isr return handled".
drivers/i2c/busses/i2c-tegra.c static u32 tegra_i2c_func(struct i2c_adapter *adap) · line 762
Quoted 2 lines
drivers/i2c/busses/i2c-tegra.c +2
-0+if (slave->addr >0x7F ) + addr2 = (slave->addr >>7 ) |I2C_SL_ADDR2_TEN_BIT_MODE ;
Nope. There are 10 bit encodings of addresses 0x000-0x07f, too. So, you need to check for the flag (slave->flags & I2C_CLIENT_TEN).
Re: [PATCH v2 1/4] i2c: tegra: implement slave mode
Quoted 4 lines · Wolfram Sang
Quoted 4 lines
drivers/i2c/busses/i2c-tegra.c +4
-0+static void tegra_i2c_slave_write (struct tegra_i2c_dev *i2c_dev,u32 val) +{ +i2c_writel (i2c_dev, val,I2C_SL_RCVD ); +
Quoted 8 lines
drivers/i2c/busses/i2c-tegra.c static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) · line 486
Quoted 6 lines
drivers/i2c/busses/i2c-tegra.c +6
-0+/* +* TODO: A correct fix needs to be found for this. +* +* We experience less incomplete messages with this delay than without +* it, but we don't know why. Help is appreciated. +*/ Uh oh. So I assume this is another reason for staging?
I think we can live with this upstream, no need for staging.
Quoted 15 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (!i2c_dev->slave || !i2c_dev->slave->slave_cb) + return -EINVAL;The core checks for
slave_cbbeing valid.drivers/i2c/busses/i2c-tegra.c static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) · line 512
Quoted 1 line
drivers/i2c/busses/i2c-tegra.c +1
-0+i2c_slave_event (i2c_dev->slave,I2C_SLAVE_STOP , &dummy);You could use value here, too, or?
drivers/i2c/busses/i2c-tegra.c static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) · line 547
Quoted 2 lines
drivers/i2c/busses/i2c-tegra.c +2
-0+if (!tegra_i2c_slave_isr (irq, i2c_dev)) +return IRQ_HANDLED ;Minor nit: I'd prefer == 0 here, since it reads "if not
slave_isrreturn handled".
Quoted 5 lines
drivers/i2c/busses/i2c-tegra.c static u32 tegra_i2c_func(struct i2c_adapter *adap) · line 762
Quoted 2 lines
drivers/i2c/busses/i2c-tegra.c +2
-0+if (slave->addr >0x7F ) + addr2 = (slave->addr >>7 ) |I2C_SL_ADDR2_TEN_BIT_MODE ;Nope. There are 10 bit encodings of addresses 0x000-0x07f, too. So, you need to check for the flag (
slave->flags&I2C_CLIENT_TEN).
If you'd fix up these and resend, I'll happily include this patch for 4.3 already.
Thanks,
Wolfram
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150720/ca98dfad/attachment.sig>
PATCH v2 2/4 staging/nvec: reimplement on top of tegra i2c driver
In reply to Andrey DaninRemove i2c controller related code and use tegra i2c driver in slave mode. Update nvec documentation.
---
Changes for v2:
- remove extra new line
- keep old functions to simplify review
- move nvec_state enum to nvec.c
- use nvec-slave instead of nvec in dts to keep ABI compatibility
- rebased on top of new i2c slave framework
- delay workaround moved to tegra-i2c
- documentation patch is integrated in this commit
- reverted a log message to minimize changes
--- .../devicetree/bindings/nvec/nvidia,nvec.txt | 21 +- drivers/staging/nvec/nvec.c | 258 +++++++++++++-------- drivers/staging/nvec/nvec.h | 10 - 3 files changed, 169 insertions(+), 120 deletions(-)
Documentation/devicetree/bindings/nvec/nvidia,nvec.txt +3 -18
@@ -1,21 +1,6 @@ NVIDIA compliant embedded controller Required properties: -- compatible : should be "nvidia,nvec". -- reg : the iomem of the i2c slave controller -- interrupts : the interrupt line of the i2c slave controller -- clock-frequency : the frequency of the i2c bus -- gpios : the gpio used for ec request -- slave-addr: the i2c address of the slave controller -- clocks : Must contain an entry for each entry in clock-names. - See ../clocks/clock-bindings.txt for details. -- clock-names : Must include the following entries: - Tegra20/Tegra30: - - div-clk - - fast-clk - Tegra114: - - div-clk -- resets : Must contain an entry for each entry in reset-names. - See ../reset/reset.txt for details. -- reset-names : Must include the following entries: - - i2c +- compatible : should be "nvidia,nvec-slave". +- reg: the i2c address of the slave controller +- request-gpios : the gpio used for ec request
drivers/staging/nvec/nvec.c +166 -92
389 lines not on this page · raw message
drivers/staging/nvec/nvec.h +0 -10
@@ -107,11 +107,6 @@ struct nvec_msg {* struct nvec_chip - A single connection to an NVIDIA Embedded controller * @dev: The device * @gpio: The same as for &struct nvec_platform_data -* @irq: The IRQ of the I2C device -* @i2c_addr: The address of the I2C slave -* @base: The base of the memory mapped region of the I2C device -* @i2c_clk: The clock of the I2C device -* @rst: The reset of the I2C device * @notifier_list: Notifiers to be called on received messages, see * nvec_register_notifier() * @rx_data: Received messages that have to be processed
@@ -137,11 +132,6 @@ struct nvec_msg {struct nvec_chip {struct device *dev;int gpio; -int irq; -int i2c_addr; -void __iomem *base; -struct clk *i2c_clk; -struct reset_control *rst;struct atomic_notifier_head notifier_list;struct list_head rx_data, tx_data;struct notifier_block nvec_status_notifier;
Signature · 1 line
1.9.1
Re: [PATCH v2 2/4] staging/nvec: reimplement on top of tegra i2c driver
Quoted 15 lines
drivers/staging/nvec/nvec.c +15
-0+/** +* nvec_slave_cb - I2C slave callback +* +* This callback fills our RX buffers and empties our TX +* buffers. This uses a finite state machine. +*/ +static int nvec_slave_cb (struct i2c_client *client, +enum i2c_slave_event event,u8 *val) +{ +struct nvec_chip *nvec =i2c_get_clientdata (client); + +switch (event) { +case I2C_SLAVE_WRITE_REQUESTED : +/* Alloc new msg only if prev transaction finished */ +if (nvec->state ==ST_NONE )
drivers/staging/nvec/nvec.c static void nvec_disable_i2c_slave(struct nvec_chip *nvec) · line 783
Quoted 10 lines
drivers/staging/nvec/nvec.c +10
-0+ nvec->rx =nvec_msg_alloc (nvec,NVEC_MSG_RX ); + +/* Should not happen in a normal world */ +if (unlikely (nvec->rx ==NULL )) { + nvec->state =ST_NONE ; +return -1 ; + } + nvec->rx->pos =0 ; + +if (client->addr != ((*val) >>1 )) {
Uh, I2C_SLAVE_WRITE_REQUESTED should not use val.
Quoted 8 lines
drivers/staging/nvec/nvec.c +8
-0+dev_err (&client->dev, +"received address 0x%02x, expected 0x%02x\n" , + ((*val) >>1 ), client->addr); +return -1 ; + } + nvec->state =ST_TRANS_START ; +break ; +
...
Quoted 11 lines
drivers/staging/nvec/nvec.c +11
-0+case I2C_SLAVE_READ_PROCESSED : +if (nvec->state !=ST_RX && + nvec->state !=ST_TX ) { +dev_err (&client->dev, +"unexpected read: state %d\n" , + nvec->state); +return -1 ; + } + +if (!nvec->tx || nvec->tx->pos >= nvec->tx->size) { + dev_err(nvec->dev,
drivers/staging/nvec/nvec.c static void nvec_disable_i2c_slave(struct nvec_chip *nvec) · line 848
Quoted 10 lines
drivers/staging/nvec/nvec.c +10
-0+"tx buffer underflow on %p (%u > %u)\n" , + nvec->tx, + (uint) (nvec->tx ? nvec->tx->pos :0 ), + (uint) (nvec->tx ? nvec->tx->size : 0)); + nvec->state =ST_NONE ; +break ; + } + + nvec->state =ST_TX ; + *val = nvec->tx->data[nvec->tx->pos++];
Are you sure you want to increase the pointer here? Remember that this byte is requested but might not be sent out if the remote master stops the transfer after the previous byte using NACK instead of ACK.
Quoted 2 lines
(quoted diff) +2
-0+ break; +
PATCH v2 3/4 staging/nvec: remove old code
In reply to Andrey Danin---
Changes for v2:
- it is initial verion
--- drivers/staging/nvec/nvec.c | 211 -------------------------------------------- 1 file changed, 211 deletions(-)
drivers/staging/nvec/nvec.c +0 -211
@@ -516,23 +516,6 @@ static void nvec_rx_completed(struct nvec_chip *nvec)schedule_work (&nvec->rx_work); } -#if 0 -/** -* nvec_invalid_flags - Send an error message about invalid flags and jump -* @nvec: The nvec device -* @status: The status flags -* @reset: Whether we shall jump to state 0. -*/ -static void nvec_invalid_flags (struct nvec_chip *nvec,unsigned int status, -bool reset) -{ -dev_err (nvec->dev,"unexpected status flags 0x%02x during state %i\n" , - status, nvec->state); -if (reset) - nvec->state =0 ; -} -#endif /* FIXME: remove old code */ -/** * nvec_tx_set - Set the message to transfer (nvec->tx) * @nvec: A &struct nvec_chip
@@ -562,200 +545,6 @@ static void nvec_tx_set(struct nvec_chip *nvec) (uint)nvec->tx->size, nvec->tx->data[1]); } - -#if 0 -/** -* nvec_interrupt - Interrupt handler -* @irq: The IRQ -* @dev: The nvec device -* -* Interrupt handler that fills our RX buffers and empties our TX -* buffers. This uses a finite state machine with ridiculous amounts -* of error checking, in order to be fairly reliable. -*/ -static irqreturn_t nvec_interrupt (int irq,void *dev) -{ -unsigned long status; -unsigned int received =0 ; -unsigned char to_send =0xff ; -const unsigned long irq_mask =I2C_SL_IRQ |END_TRANS |RCVD |RNW ; -struct nvec_chip *nvec = dev; -unsigned int state = nvec->state; - - status =readl (nvec->base +I2C_SL_STATUS ); - -/* Filter out some errors */ -if ((status & irq_mask) ==0 && (status & ~irq_mask) !=0 ) { -dev_err (nvec->dev,"unexpected irq mask %lx\n" , status); -return IRQ_HANDLED ; - } -if ((status &I2C_SL_IRQ ) ==0 ) { -dev_err (nvec->dev,"Spurious IRQ\n" ); -return IRQ_HANDLED ; - } - -/* The EC did not request a read, so it send us something, read it */ -if ((status &RNW ) ==0 ) { - received =readl (nvec->base +I2C_SL_RCVD ); -if (status &RCVD ) -writel (0 , nvec->base +I2C_SL_RCVD ); - } - -if (status == (I2C_SL_IRQ |RCVD )) - nvec->state =0 ; - -switch (nvec->state) { -case 0 :/* Verify that its a transfer start, the rest later */ -if (status != (I2C_SL_IRQ |RCVD )) -nvec_invalid_flags (nvec, status, false); -break ; -case 1 :/* command byte */ -if (status !=I2C_SL_IRQ ) { -nvec_invalid_flags (nvec, status, true); - }else { - nvec->rx =nvec_msg_alloc (nvec,NVEC_MSG_RX ); -/* Should not happen in a normal world */ -if (unlikely (nvec->rx ==NULL )) { - nvec->state =0 ; -break ; - } - nvec->rx->data[0 ] = received; - nvec->rx->pos =1 ; - nvec->state =2 ; - } -break ; -case 2 :/* first byte after command */ -if (status == (I2C_SL_IRQ |RNW |RCVD )) { -udelay (33 ); -if (nvec->rx->data[0 ] !=0x01 ) { -dev_err (nvec->dev, -"Read without prior read command\n" ); - nvec->state =0 ; -break ; - } -nvec_msg_free (nvec, nvec->rx); - nvec->state =3 ; -nvec_tx_set (nvec); -BUG_ON (nvec->tx->size <1 ); - to_send = nvec->tx->data[0 ]; - nvec->tx->pos =1 ; - }else if (status == (I2C_SL_IRQ )) { -BUG_ON (nvec->rx ==NULL ); - nvec->rx->data[1 ] = received; - nvec->rx->pos =2 ; - nvec->state =4 ; - }else { -nvec_invalid_flags (nvec, status, true); - } -break ; -case 3 :/* EC does a block read, we transmit data */ -if (status &END_TRANS ) { -nvec_tx_completed (nvec); - }else if ((status &RNW ) ==0 || (status &RCVD )) { -nvec_invalid_flags (nvec, status, true); - }else if (nvec->tx && nvec->tx->pos < nvec->tx->size) { - to_send = nvec->tx->data[nvec->tx->pos++]; - }else { -dev_err (nvec->dev,"tx buffer underflow on %p (%u > %u)\n" , - nvec->tx, - (uint) (nvec->tx ? nvec->tx->pos :0 ), - (uint) (nvec->tx ? nvec->tx->size :0 )); - nvec->state =0 ; - } -break ; -case 4 :/* EC does some write, we read the data */ -if ((status & (END_TRANS |RNW )) ==END_TRANS ) -nvec_rx_completed (nvec); -else if (status & (RNW |RCVD )) -nvec_invalid_flags (nvec, status, true); -else if (nvec->rx && nvec->rx->pos <NVEC_MSG_SIZE ) - nvec->rx->data[nvec->rx->pos++] = received; -else -dev_err (nvec->dev, -"RX buffer overflow on %p: Trying to write byte %u of %u\n" , - nvec->rx, nvec->rx ? nvec->rx->pos :0 , -NVEC_MSG_SIZE ); -break ; -default : - nvec->state =0 ; - } - -/* If we are told that a new transfer starts, verify it */ -if ((status & (RCVD |RNW )) ==RCVD ) { -if (received != nvec->i2c_addr) -dev_err (nvec->dev, -"received address 0x%02x, expected 0x%02x\n" , - received, nvec->i2c_addr); - nvec->state =1 ; - } - -/* Send data if requested, but not on end of transmission */ -if ((status & (RNW |END_TRANS )) ==RNW ) -writel (to_send, nvec->base +I2C_SL_RCVD ); - -/* If we have send the first byte */ -if (status == (I2C_SL_IRQ |RNW |RCVD )) -nvec_gpio_set_value (nvec,1 ); - -dev_dbg (nvec->dev, -"Handled: %s 0x%02x, %s 0x%02x in state %u [%s%s%s]\n" , - (status &RNW ) ==0 ?"received" :"R=" , - received, - (status & (RNW |END_TRANS )) ?"sent" :"S=" , - to_send, - state, - status &END_TRANS ?" END_TRANS" :"" , - status &RCVD ?" RCVD" :"" , - status &RNW ?" RNW" :"" ); - - -/* -* TODO: A correct fix needs to be found for this. -* -* We experience less incomplete messages with this delay than without -* it, but we don't know why. Help is appreciated. -*/ -udelay (100 ); - -return IRQ_HANDLED ; -} - -static void tegra_init_i2c_slave (struct nvec_chip *nvec) -{ -u32 val; - -clk_prepare_enable (nvec->i2c_clk); - -reset_control_assert (nvec->rst); -udelay (2 ); -reset_control_deassert (nvec->rst); - - val =I2C_CNFG_NEW_MASTER_SFM |I2C_CNFG_PACKET_MODE_EN | - (0x2 <<I2C_CNFG_DEBOUNCE_CNT_SHIFT ); -writel (val, nvec->base +I2C_CNFG ); - -clk_set_rate (nvec->i2c_clk,8 *80000 ); - -writel (I2C_SL_NEWSL , nvec->base +I2C_SL_CNFG ); -writel (0x1E , nvec->base +I2C_SL_DELAY_COUNT ); - -writel (nvec->i2c_addr>>1 , nvec->base +I2C_SL_ADDR1 ); -writel (0 , nvec->base +I2C_SL_ADDR2 ); - -enable_irq (nvec->irq); -} - -#ifdef CONFIG_PM_SLEEP -static void nvec_disable_i2c_slave (struct nvec_chip *nvec) -{ -disable_irq (nvec->irq); -writel (I2C_SL_NEWSL |I2C_SL_NACK , nvec->base +I2C_SL_CNFG ); -clk_disable_unprepare (nvec->i2c_clk); -} -#endif -#endif /* FIXME: remove old code. */ - -/** * nvec_slave_cb - I2C slave callback *
Signature · 1 line
1.9.1
PATCH v2 4/4 dt: paz00: define nvec as child of i2c bus
In reply to Andrey DaninNVEC driver was reimplemented to use tegra i2c. Use common i2c bindings for NVEC node.
---
Changes for v2:
- swap reg and request-gpios properties
- use nvec-slave instead of nvec to keep ABI compatibility
- place doc in separate patch
--- arch/arm/boot/dts/tegra20-paz00.dts | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-)
arch/arm/boot/dts/tegra20-paz00.dts +9 -13
@@ -288,20 +288,16 @@ clock-frequency = <100000>; }; - nvec at 7000c500 { - compatible = "nvidia,nvec"; - reg = <0x7000c500 0x100>; - interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; + i2c at 7000c500 { + status = "okay"; clock-frequency = <80000>; - request-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>; - slave-addr = <138>; - clocks = <&tegra_car TEGRA20_CLK_I2C3>, - <&tegra_car TEGRA20_CLK_PLL_P_OUT3>; - clock-names = "div-clk", "fast-clk"; - resets = <&tegra_car 67>; - reset-names = "i2c"; + + nvec: nvec at 45 { + compatible = "nvidia,nvec-slave"; + reg = <0x45>; + request-gpios = <&gpio TEGRA_GPIO(V, 2) + GPIO_ACTIVE_HIGH>; + }; }; i2c at 7000d000 {
Signature · 1 line
1.9.1
Quoted 4 lines · Andrey Danin
NVEC driver contains code to manage tegra i2c controller in slave mode. I2C slave support was implemented in linux kernel. The goal of this patch serie is to implement I2C slave mode in tegra drived and rework NVEC driver to use it.
Thanks. Looks pretty good already. If being I2C slave was the reason for this driver being in staging, we soon need to think of a proper place outside staging.
Marc Dietrich
maintainerv2 cover arm: tegra: implement NVEC driver using tegrai2c.
Hi Wolfram,
Am Freitag, 3. April 2015, 21:46:35 schrieb Wolfram Sang:
Quoted 9 lines · Andrey Danin
Quoted 4 lines
NVEC driver contains code to manage tegra i2c controller in slave mode. I2C slave support was implemented in linux kernel. The goal of this patch serie is to implement I2C slave mode in tegra drived and rework NVEC driver to use it.
Thanks. Looks pretty good already. If being I2C slave was the reason for this driver being in staging, we soon need to think of a proper place outside staging.
yes, moving the low level i2c functions out to the bus driver was our major concern. But there are still some minor things left before before we can move out of staging.
One thing where we need your help as a I2C maintainer is how to represent an i2c slave device using device-tree. You may remember our discussion in the past from here [1] where you suggested to just make a slave client by its compatible name. Stephen Warren from NVIDIA raised some concerns about this solution because it may not be appropriate in all possible future cases (which is what a proper device-tree representation should take care off). He instead suggested to mark a slave client by adding some flag to the reg property, to be able to handle a situation where both master client and slave client have the same i2c bus address forming a loopback (e.g. for testing purpose) on the same bus. More details here [2].
I hope with this post I can join the different discussions somehow so we are able to find a common sense which is acceptable for all.
Marc
[1] http://lkml.iu.edu/hypermail/linux/kernel/1409.1/03446.html
[2] https://lists.launchpad.net/ac100/msg01361.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150407/330e1c96/attachment.sig>
v2 cover arm: tegra: implement NVEC driver using tegrai2c.
Quoted 12 lines
One thing where we need your help as a I2C maintainer is how to represent an i2c slave device using device-tree. You may remember our discussion in the past from here [1] where you suggested to just make a slave client by its compatible name. Stephen Warren from NVIDIA raised some concerns about this solution because it may not be appropriate in all possible future cases (which is what a proper device-tree representation should take care off). He instead suggested to mark a slave client by adding some flag to the reg property, to be able to handle a situation where both master client and slave client have the same i2c bus address forming a loopback (e.g. for testing purpose) on the same bus. More details here [2].
Quoted 2 lines
I hope with this post I can join the different discussions somehow so we are able to find a common sense which is acceptable for all.
I'll have a look again for 4.2.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150410/577d2d97/attachment.sig>
How to encode being an I2C slave in DT?
In reply to Marc DietrichI'm back in town. Sorry for the delay...
Quoted 10 lines
One thing where we need your help as a I2C maintainer is how to represent an i2c slave device using device-tree. You may remember our discussion in the past from here [1] where you suggested to just make a slave client by its compatible name. Stephen Warren from NVIDIA raised some concerns about this solution because it may not be appropriate in all possible future cases (which is what a proper device-tree representation should take care off). He instead suggested to mark a slave client by adding some flag to the reg property, to be able to handle a situation where both master client and slave client have the same i2c bus address forming a loopback (e.g. for testing purpose) on the same bus. More details here [2].
Well... I can agree that we shouldn't prevent a loopback from a DT point of view. (Despite the fact that it is really for development and I wonder how many I2C IP cores can do this flawlessly)
However, I am still against putting that information into the reg property. I see devices coming which have multiple addresses, so people somewhen want to encode this in DT as well. I'd like to have that a simple array of addresses. Adding flags, rarely used, will create a mess IMO.
So what about adding a new property "i2c-slave-reg"? This does not only prevent the confusion above, but also makes it very clear that this node is an I2C slave without the need to encode that somehow in the compatible property (although it probably should be described there as well, still).
Quoted 2 lines
I hope with this post I can join the different discussions somehow so we are able to find a common sense which is acceptable for all.
Thanks for doing this! I changed the subject to maybe raise interest a bit more.
How to encode being an I2C slave in DT?
Quoted 18 lines · Wolfram Sang
I'm back in town. Sorry for the delay...
Quoted 10 lines
One thing where we need your help as a I2C maintainer is how to represent an i2c slave device using device-tree. You may remember our discussion in the past from here [1] where you suggested to just make a slave client by its compatible name. Stephen Warren from NVIDIA raised some concerns about this solution because it may not be appropriate in all possible future cases (which is what a proper device-tree representation should take care off). He instead suggested to mark a slave client by adding some flag to the reg property, to be able to handle a situation where both master client and slave client have the same i2c bus address forming a loopback (e.g. for testing purpose) on the same bus. More details here [2].
Well... I can agree that we shouldn't prevent a loopback from a DT point of view. (Despite the fact that it is really for development and I wonder how many I2C IP cores can do this flawlessly)
Quoted 5 lines
However, I am still against putting that information into the reg property. I see devices coming which have multiple addresses, so people somewhen want to encode this in DT as well. I'd like to have that a simple array of addresses. Adding flags, rarely used, will create a mess IMO.
The container node has a #address-cells property for this very reason. It's perfectly well-defined how to split up a property containing a large number of cells into separate values, by using the value of #address-cells. Plus, the canonical formatting (albeit not enforced by the DT compiler) for a property that contains an array of entries, each 2 cells in size, would be:
reg = <0 0x1a>, <0 0x40>, <0 0x48>;
rather than:
reg = <0 0x1a 0 0x40 0 0x48>;
... so it's quite simple to make it very human-readable too.
Quoted 5 lines
So what about adding a new property "i2c-slave-reg"? This does not only prevent the confusion above, but also makes it very clear that this node is an I2C slave without the need to encode that somehow in the compatible property (although it probably should be described there as well, still).
That doesn't sound like a good idea. reg is the DT-defined way of identifying/numbering child nodes. We shouldn't invent other properties that mean essentially the same thing, but simply encode flags.
It might be reasonable to split an I2C controller node up so that it has n child nodes:
i2c-controller at 1234 {
compatible = "foo";
reg = <0x1234 0x100>;
#address-cells = <1>;
#size-cells = <0>;
master {
eeprom at 1a {
compatible = ...;
reg = <0x1a>;
};
...
};
slave {
nvec at NN {
compatible = ...;
reg = <0xNN>;
};
...
};
};However, that seems a lot more complex and invasive than just adding an extra address cell to reg, and putting everything into a single node.
Quoted 5 lines
Quoted 2 lines
I hope with this post I can join the different discussions somehow so we are able to find a common sense which is acceptable for all.
Thanks for doing this! I changed the subject to maybe raise interest a bit more.
How to encode being an I2C slave in DT?
Quoted 7 lines
The container node has a #address-cells property for this very reason. It's perfectly well-defined how to split up a property containing a large number of cells into separate values, by using the value of #address-cells. Plus, the canonical formatting (albeit not enforced by the DT compiler) for a property that contains an array of entries, each 2 cells in size, would be:
Quoted 7 lines
reg = <0
0x1a>, <00x40>, <00x48>;rather than:
reg = <0
0x1a00x4000x48>;... so it's quite simple to make it very human-readable too.
I give in to the flag idea. I also noticed that we'd need another flag anyhow to mark 10 bit addresses. I am still thinking between using two address-cells in that case (clean seperation between address and flags) or to encode the flags as MSB in the current address (all busses will have same address-cells and child description, less code paths and no overhead in dtbs).
That being said, for the loopback testcase, the I2C slave framework will need updates as well. I think I can cook up something. Will be interesting to see if my hardware can do this. Has the loopback already been tested on Tegra?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150506/faec8eb4/attachment-0001.sig>
How to encode being an I2C slave in DT?
Quoted 22 lines · Wolfram Sang
Quoted 7 lines
The container node has a #address-cells property for this very reason. It's perfectly well-defined how to split up a property containing a large number of cells into separate values, by using the value of #address-cells. Plus, the canonical formatting (albeit not enforced by the DT compiler) for a property that contains an array of entries, each 2 cells in size, would be:
Quoted 7 lines
reg = <0
0x1a>, <00x40>, <00x48>;rather than:
reg = <0
0x1a00x4000x48>;... so it's quite simple to make it very human-readable too.
I give in to the flag idea. I also noticed that we'd need another flag anyhow to mark 10 bit addresses. I am still thinking between using two address-cells in that case (clean seperation between address and flags) or to encode the flags as MSB in the current address (all busses will have same address-cells and child description, less code paths and no overhead in dtbs).
Quoted 4 lines
That being said, for the loopback testcase, the I2C slave framework will need updates as well. I think I can cook up something. Will be interesting to see if my hardware can do this. Has the loopback already been tested on Tegra?
I don't believe that loopback has been tested on Tegra, at least with upstream SW. I have no idea whether our downstream SW or Silicon validation team has tested it.
How to encode being an I2C slave in DT?
In reply to Wolfram SangQuoted 13 lines · Wolfram Sang
Quoted 13 lines
The container node has a #address-cells property for this very reason. It's perfectly well-defined how to split up a property containing a large number of cells into separate values, by using the value of #address-cells. Plus, the canonical formatting (albeit not enforced by the DT compiler) for a property that contains an array of entries, each 2 cells in size, would be:
reg = <0
0x1a>, <00x40>, <00x48>;rather than:
reg = <0
0x1a00x4000x48>;
Quoted 8 lines
Quoted 1 line
... so it's quite simple to make it very human-readable too.
I give in to the flag idea. I also noticed that we'd need another flag anyhow to mark 10 bit addresses. I am still thinking between using two address-cells in that case (clean seperation between address and flags) or to encode the flags as MSB in the current address (all busses will have same address-cells and child description, less code paths and no overhead in dtbs).
Reading thru the thread, this seems good to me. I would go with adding flags in the MSB of the reg cell rather than adding a cell.
Rob
How to encode being an I2C slave in DT?
Quoted 10 lines
Quoted 7 lines
I give in to the flag idea. I also noticed that we'd need another flag anyhow to mark 10 bit addresses. I am still thinking between using two address-cells in that case (clean seperation between address and flags) or to encode the flags as MSB in the current address (all busses will have same address-cells and child description, less code paths and no overhead in dtbs).
Reading thru the thread, this seems good to me. I would go with adding flags in the MSB of the reg cell rather than adding a cell.
Thanks. I was leaning to the MSB idea, too, and am currently checking how the code would look like. Feels much better to do knowing that it is basically upstream compatible ;)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150519/d60fd9fe/attachment.sig>
How to encode being an I2C slave in DT?
Hello Wolfram,
Quoted 8 lines · Wolfram Sang
Quoted 8 lines
Quoted 7 lines
I give in to the flag idea. I also noticed that we'd need another flag anyhow to mark 10 bit addresses. I am still thinking between using two address-cells in that case (clean seperation between address and flags) or to encode the flags as MSB in the current address (all busses will have same address-cells and child description, less code paths and no overhead in dtbs).
Quoted 7 lines
Quoted 2 lines
Reading thru the thread, this seems good to me. I would go with adding flags in the MSB of the reg cell rather than adding a cell.
Thanks. I was leaning to the MSB idea, too, and am currently checking how the code would look like. Feels much better to do knowing that it is basically upstream compatible ;)
Did you have enough time to check this ? (sorry for the noise, if I missed patch(es) in the ml)
Thanks.
How to encode being an I2C slave in DT?
Quoted 3 lines
Did you have enough time to check this ? (sorry for the noise, if I missed patch(es) in the ml)
Nice coincidence, scheduled for tomorrow...
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150716/ef4382ec/attachment.sig>
How to encode being an I2C slave in DT?
In reply to Wolfram SangHello,
Quoted 5 lines · Wolfram Sang
So what about adding a new property "i2c-slave-reg"? This does not only prevent the confusion above, but also makes it very clear that this node is an I2C slave without the need to encode that somehow in the compatible property (although it probably should be described there as well, still).
I admit I didn't follow the discussions referenced in the footnotes, but I wonder if the slave part should be added to the device tree at all. AFAICT it could (and so should) be completely userspace-defined which slave driver is used on which address. I imagine that for most controllers the bus addresses to use can be chosen more or less freely. So what am I missing?
Quoted 5 lines
Quoted 2 lines
I hope with this post I can join the different discussions somehow so we are able to find a common sense which is acceptable for all.
Thanks for doing this! I changed the subject to maybe raise interest a bit more.
that worked fine :-)
Best regards
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-K?nig | Industrial Linux Solutions | http://www.pengutronix.de/ |
Marc Dietrich
maintainerHow to encode being an I2C slave in DT?
Am Mittwoch, 6. Mai 2015, 08:59:28 schrieb Uwe Kleine-K?nig:
Quoted 9 lines
Hello,
Quoted 5 lines · Wolfram Sang
So what about adding a new property "i2c-slave-reg"? This does not only prevent the confusion above, but also makes it very clear that this node is an I2C slave without the need to encode that somehow in the compatible property (although it probably should be described there as well, still).
Quoted 6 lines
I admit I didn't follow the discussions referenced in the footnotes, but I wonder if the slave part should be added to the device tree at all. AFAICT it could (and so should) be completely userspace-defined which slave driver is used on which address. I imagine that for most controllers the bus addresses to use can be chosen more or less freely. So what am I missing?
if you had read the footnotes you would know :-) Our usecase is connect an embeedded controller via i2c to the host soc, similar to cros-ec, but here the ec is the i2c master. The ec connects keyboard, mouse, pwrmngt, and other stuff, for which the drivers are best implemented in kernel code AFAIK.
Marc
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150506/afbd62ae/attachment-0001.sig>
How to encode being an I2C slave in DT?
Hello Marc,
Quoted 15 lines · Marc Dietrich
Am Mittwoch, 6. Mai 2015, 08:59:28 schrieb Uwe Kleine-K?nig:
Quoted 7 lines · Wolfram Sang
Quoted 5 lines
So what about adding a new property "i2c-slave-reg"? This does not only prevent the confusion above, but also makes it very clear that this node is an I2C slave without the need to encode that somehow in the compatible property (although it probably should be described there as well, still).
Quoted 6 lines
I admit I didn't follow the discussions referenced in the footnotes, but I wonder if the slave part should be added to the device tree at all. AFAICT it could (and so should) be completely userspace-defined which slave driver is used on which address. I imagine that for most controllers the bus addresses to use can be chosen more or less freely. So what am I missing?
Quoted 4 lines
if you had read the footnotes you would know :-) Our usecase is connect an embeedded controller via i2c to the host soc, similar to cros-ec, but here the ec is the i2c master. The ec connects keyboard, mouse, pwrmngt, and other stuff, for which the drivers are best implemented in kernel code AFAIK.
Right, the driver might sensibly be implemented in kernel space. But I'd vote that you still need to do the binding of these drivers to your slave controller from userspace. Then there is no need to specify anything in your dtb.
Best regards
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-K?nig | Industrial Linux Solutions | http://www.pengutronix.de/ |
How to encode being an I2C slave in DT?
Quoted 23 lines · Uwe Kleine-K?nig
Hello Marc,
Quoted 15 lines · Marc Dietrich
Am Mittwoch, 6. Mai 2015, 08:59:28 schrieb Uwe Kleine-K?nig:
Quoted 7 lines · Wolfram Sang
Quoted 5 lines
So what about adding a new property "i2c-slave-reg"? This does not only prevent the confusion above, but also makes it very clear that this node is an I2C slave without the need to encode that somehow in the compatible property (although it probably should be described there as well, still).
Quoted 6 lines
I admit I didn't follow the discussions referenced in the footnotes, but I wonder if the slave part should be added to the device tree at all. AFAICT it could (and so should) be completely userspace-defined which slave driver is used on which address. I imagine that for most controllers the bus addresses to use can be chosen more or less freely. So what am I missing?
Quoted 4 lines
if you had read the footnotes you would know :-) Our usecase is connect an embeedded controller via i2c to the host soc, similar to cros-ec, but here the ec is the i2c master. The ec connects keyboard, mouse, pwrmngt, and other stuff, for which the drivers are best implemented in kernel code AFAIK.
Quoted 4 lines
Right, the driver might sensibly be implemented in kernel space. But I'd vote that you still need to do the binding of these drivers to your slave controller from userspace. Then there is no need to specify anything in your dtb.
I think the set of I2C slave devices that are implemented by the Linux system can reasonably be considered part of the HW definition. Most DT content to date has been a definition of the HW that's available to SW, but at least in this case, this I2C slave device is something that must be implemented (admittedly in conjunction with SW) using the I2C slave HW on the main SoC, in order for the overall HW to work as intended.
BTW, I believe devicetree-spec at vger.kernel.org was created to address subsystem-level DT schema questions like this. It's much lower volume, so perhaps the thread would get noticed by the DT maintainers if posted there (or perhaps just CC them)?
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: How to encode being an I2C slave in DT?
Hello Stephen,
Quoted 27 lines · Stephen Warren
Quoted 21 lines · Uwe Kleine-König
Quoted 15 lines · Marc Dietrich
Am Mittwoch, 6. Mai 2015, 08:59:28 schrieb Uwe Kleine-König:
Quoted 7 lines · Wolfram Sang
Quoted 5 lines
So what about adding a new property "i2c-slave-reg"? This does not only prevent the confusion above, but also makes it very clear that this node is an I2C slave without the need to encode that somehow in the compatible property (although it probably should be described there as well, still).
Quoted 6 lines
I admit I didn't follow the discussions referenced in the footnotes, but I wonder if the slave part should be added to the device tree at all. AFAICT it could (and so should) be completely userspace-defined which slave driver is used on which address. I imagine that for most controllers the bus addresses to use can be chosen more or less freely. So what am I missing?
Quoted 4 lines
if you had read the footnotes you would know :-) Our usecase is connect an embeedded controller via i2c to the host soc, similar to cros-ec, but here the ec is the i2c master. The ec connects keyboard, mouse, pwrmngt, and other stuff, for which the drivers are best implemented in kernel code AFAIK.
Quoted 4 lines
Right, the driver might sensibly be implemented in kernel space. But I'd vote that you still need to do the binding of these drivers to your slave controller from userspace. Then there is no need to specify anything in your dtb.
Quoted 7 lines
I think the set of I2C slave devices that are implemented by the Linux system can reasonably be considered part of the HW definition. Most DT content to date has been a definition of the HW that's available to SW, but at least in this case, this I2C slave device is something that must be implemented (admittedly in conjunction with SW) using the I2C slave HW on the main SoC, in order for the overall HW to work as intended.
I'm not convinced. Why must it be implemented? And is it too late if the setup is done by userspace?
The devicetree description of a flash chip doesn't include the rootfs content either, although a working rootfs is critical for most operating systems. The devicetree description of an ethernet adapter doesn't include its network setup although an ethernet adapter hardly makes any sense without an IP.
Quoted 4 lines
BTW, I believe [email protected] was created to address subsystem-level DT schema questions like this. It's much
lower volume, so perhaps the thread would get noticed by the DT maintainers if posted there (or perhaps just CC them)?
I added them to Cc.
Best regards
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | http://www.pengutronix.de/ |
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: How to encode being an I2C slave in DT?
Quoted 38 lines · Uwe Kleine-König
Hello Stephen,
Quoted 27 lines · Stephen Warren
Quoted 21 lines · Uwe Kleine-König
Quoted 15 lines · Marc Dietrich
Am Mittwoch, 6. Mai 2015, 08:59:28 schrieb Uwe Kleine-König:
Quoted 7 lines · Wolfram Sang
Quoted 5 lines
So what about adding a new property "i2c-slave-reg"? This does not only prevent the confusion above, but also makes it very clear that this node is an I2C slave without the need to encode that somehow in the compatible property (although it probably should be described there as well, still).
Quoted 6 lines
I admit I didn't follow the discussions referenced in the footnotes, but I wonder if the slave part should be added to the device tree at all. AFAICT it could (and so should) be completely userspace-defined which slave driver is used on which address. I imagine that for most controllers the bus addresses to use can be chosen more or less freely. So what am I missing?
Quoted 4 lines
if you had read the footnotes you would know :-) Our usecase is connect an embeedded controller via i2c to the host soc, similar to cros-ec, but here the ec is the i2c master. The ec connects keyboard, mouse, pwrmngt, and other stuff, for which the drivers are best implemented in kernel code AFAIK.
Quoted 4 lines
Right, the driver might sensibly be implemented in kernel space. But I'd vote that you still need to do the binding of these drivers to your slave controller from userspace. Then there is no need to specify anything in your dtb.
Quoted 7 lines
I think the set of I2C slave devices that are implemented by the Linux system can reasonably be considered part of the HW definition. Most DT content to date has been a definition of the HW that's available to SW, but at least in this case, this I2C slave device is something that must be implemented (admittedly in conjunction with SW) using the I2C slave HW on the main SoC, in order for the overall HW to work as intended.
Quoted 1 line
I'm not convinced. Why must it be implemented?
The other HW in the system expects the I2C slave device to exist. I believe that makes it a HW level description, and hence suitable to represent in DT.
Representing this in DT saves user-space from requiring board-specific knowledge. The kernel should be abstracting HW as best it can, so that user-space can be entirely generic, supporting classes of devices, not enumeration/instantiation of devices. Assuming a system didn't store its root filesystem on a particular SD card or USB controller, we could instantiate those controllers from user-space too (or an initrd even if the root fs was there). However, we choose not to do that...
In the specific case of nvec (the I2C slave device that triggered this thread) and I dare say other devices too, there is more to the device than just the I2C slave device. There's also a GPIO that serves to provide synchronization between the SoC and external device.
Quoted 1 line
And is it too late if the setup is done by userspace?
The primary purpose of nvec is to provide keyboard and mouse (touchpad) input, so enabling this once user space was booted would probably work. However, the device should likely be enabled by the initrd not the root filesystem (if such a split exists in a given distro) so that the user can actually interact with any initrd shell if the boot fails. That would bloat the initrd. System power management (power off at least) goes through the same device, so deferring that might not be great, but I suppose there likely wouldn't be a "turn power off" event requested until user-space was booted.
Quoted 12 lines
The devicetree description of a flash chip doesn't include the rootfs content either, although a working rootfs is critical for most operating systems. The devicetree description of an ethernet adapter doesn't include its network setup although an ethernet adapter hardly makes any sense without an IP.
Quoted 4 lines
BTW, I believe [email protected] was created to address subsystem-level DT schema questions like this. It's much
lower volume, so perhaps the thread would get noticed by the DT maintainers if posted there (or perhaps just CC them)?I added them to Cc.