RE: [PATCH v6 1/2] i2c: buses: add i2c bus driver for NVIDIA GPU

2018-09-06 Thread Ajay Gupta
Hi Peter,
> >> This seems to behave rather strange for len > 4, and I do not see
> >> anything preventing that from happening.
> > Actually the check is in ccg_read() of the client driver at
> > https://marc.info/?l=linux-usb&m=153618608301206&w=2
> >
> >> Am I missing something, or do you need to add a quirk for max_read_len?
> > I will add a check in this function as well.
> 
> No, you should add a pointer to a struct i2c_adapter_quirks, with
> max_read_len set I think. At least that's how e.g. i2c-qup.c does it.
Ok, will fix in next version.
 
> >>> + break;

> >>> + mutex_lock(&i2cd->mutex);
> >>> + for (i = 0; i < num; i++) {
> >>
> >> I don't get how this loop works. You do not seem to always start with a
> start.
> >> E.g., if the first message is I2C_M_RD, i2c_read() is called before
> >> i2c_start(). Is that correct?
> > That’s correct and it is because i2_read() itself does the START and STOP.
> 
> Well, in that case, you don't fully support combined I2C transactions.
> You cannot e.g. generate this from Documentation/i2c/i2c-protocol
> 
>   S Addr Rd [A] [Data] NA S Addr Wr [A] Data [A] P
> 
> By your description, all reads are terminated by a stop, and that is a quirk. 
> I
> think you need to add some of the I2C_AQ_COMB* flags to the above
> mentioned struct i2c_adapter_quirks.
Ok, will add those quirks flags. Also will modify to have implicit STOP after
last write message.
 
> >> Also, if a message has I2C_M_STOP but not I2C_M_RD, the call to
> >> i2c_stop() happens before the call the i2c_write(). What's up with that?
> > Client driver sends I2C_M_STOP along with every write message.
> 
> Why is it certain that the client driver in 2/2 is the only client of this 
> adapter?
> If that's really fundamentally the case, and it can't change for whatever
> reason, then I think these things should be mentioned somewhere.
There can be other client. I will update the driver with quirks and implicit
STOP after last write message.

Thanks
Ajay

--
nvpublic
--

> >> I would expect an i2c_start() before the loop or first in the loop,
> >> and a
> >> i2c_stop() after the loop.
> > I2c_read() function itself takes care of it.
> >
> >> As is, the stop after the loop is only called on error.
> > To be exact, whenever there is error in i2c_write().
> >
> >> In addition, I would expect messages that have I2C_M_STOP to trigger
> >> an
> >> i2c_stop() call *after* the message, even if the message is not last in the
> loop.
> > Yes, its like that for all write messages.
> >
> >> What am I missing?
> >>
> >>> + if (msgs[i].flags & I2C_M_RD) {
> >>> + status = i2c_read(i2cd, msgs[i].buf, msgs[i].len);
> >>> + if (status < 0) {
> >>> + dev_err(dev, "i2c_read error %x", status);
> >>> + goto unlock;
> >>> + }
> >>> + i2cd->do_start = true;
> >>> + } else if (msgs[i].flags & I2C_M_STOP) {
> >>> + status = i2c_stop(i2cd);
> >>> + if (status < 0) {
> >>> + dev_err(dev, "i2c_stop error %x", status);
> >>> + goto unlock;
> >>> + }
> >>> + i2cd->do_start = true;
> >>> + } else {
> >>> + if (i2cd->do_start) {
> >>> + status = i2c_start(i2cd, msgs[i].addr);
> >>> + if (status < 0) {
> >>> + dev_err(dev, "i2c_start error %x",
> >>> + status);
> >>> + goto unlock;
> >>> + }
> >>> + status = i2c_write(i2cd, msgs[i].addr << 1);
> >>> + if (status < 0) {
> >>> + dev_err(dev, "i2c_write error %x",
> >>> + status);
> >>> + goto stop;
> >>> + }
> >>> + i2cd->do_start = false;
> >>> + }
> >>> + for (j = 0; j < msgs[i].len; j++) {
> >>> + status = i2c_write(i2cd, *(msgs[i].buf + j));
> >>> + if (status < 0) {
> >>> + dev_err(dev, "i2c_write error %x",
> >>> + status);
> >>> + goto stop;
> >>> + }
> >>> + }
> >>> + }
> >>> + }
> >>> + status = i;
> >>> + goto unlock;
> > 
> >
> >>> +stop:
> >>> + status = i2c_stop(i2cd);
> >>> + if (status < 0)
> >>> + dev_err(dev, "i2c_stop error %x", status);
> >>
> >> Hmm, every time you call one of i2c_start, i2c_read, i2c_write or
> >> i2c_stop you check for error and issue a generic dev_err message. I
> >> think you should move these error messages into the functions instead
> >> or repeating them for every use.
> > Ok, w

Re: [PATCH v6 1/2] i2c: buses: add i2c bus driver for NVIDIA GPU

2018-09-06 Thread Peter Rosin
On 2018-09-06 19:39, Ajay Gupta wrote:
> Hi Peter,
> 
>>> Latest NVIDIA GPU card has USB Type-C interface. There is a Type-C
>>> controller which can be accessed over I2C.
>>>
>>> This driver adds I2C bus driver to communicate with Type-C controller.
>>> I2C client driver will be part of USB Type-C UCSI driver.
>>>
>>> Signed-off-by: Ajay Gupta 
> 
>>> +static void enable_i2c_bus(struct gpu_i2c_dev *i2cd)
>>
>> Please prefix all your functions with gpu_, or nvidia_gpu_ or something like
>> that (because gpu sounds like a something graphics, not that nvidia_gpu helps
>> with that problem though...)
> Ok, will prefix them.
>  
>>> +{
>>> +   u32 val;
>>> +
>>> +   /* enable I2C */
>>> +   val = readl(i2cd->regs + I2C_MST_HYBRID_PADCTL);
>>> +   val |= I2C_MST_HYBRID_PADCTL_MODE_I2C |
>>> +   I2C_MST_HYBRID_PADCTL_I2C_SCL_INPUT_RCV |
>>> +   I2C_MST_HYBRID_PADCTL_I2C_SDA_INPUT_RCV;
>>> +   writel(val, i2cd->regs + I2C_MST_HYBRID_PADCTL);
>>> +
>>> +   /* enable 100KHZ mode */
>>> +   val = I2C_MST_I2C0_TIMING_SCL_PERIOD_100KHZ;
>>> +   val |= (I2C_MST_I2C0_TIMING_TIMEOUT_CLK_CNT_MAX
>>> +   << I2C_MST_I2C0_TIMING_TIMEOUT_CLK_CNT);
>>> +   val |= I2C_MST_I2C0_TIMING_TIMEOUT_CHECK;
>>> +   writel(val, i2cd->regs + I2C_MST_I2C0_TIMING); }
>>> +
>>> +static int i2c_check_status(struct gpu_i2c_dev *i2cd) {
>>> +   unsigned long target = jiffies + msecs_to_jiffies(1000);
>>> +   u32 val;
>>> +
>>> +   do {
>>> +   val = readl(i2cd->regs + I2C_MST_CNTL);
>>> +   if (!(val & I2C_MST_CNTL_CYCLE_TRIGGER))
>>> +   break;
>>> +   if ((val & I2C_MST_CNTL_STATUS) !=
>>> +   I2C_MST_CNTL_STATUS_BUS_BUSY)
>>> +   break;
>>> +   usleep_range(1000, 2000);
>>> +   } while (time_is_after_jiffies(target));
>>> +   if (time_is_before_jiffies(target))
>>> +   return -EIO;
>>> +
>>> +   val = readl(i2cd->regs + I2C_MST_CNTL);
>>> +   switch (val & I2C_MST_CNTL_STATUS) {
>>> +   case I2C_MST_CNTL_STATUS_OKAY:
>>> +   return 0;
>>> +   case I2C_MST_CNTL_STATUS_NO_ACK:
>>> +   return -EIO;
>>> +   case I2C_MST_CNTL_STATUS_TIMEOUT:
>>> +   return -ETIME;
>>> +   case I2C_MST_CNTL_STATUS_BUS_BUSY:
>>> +   return -EBUSY;
>>> +   default:
>>> +   return 0;
>>> +   }
>>> +}
>>> +
>>> +static int i2c_read(struct gpu_i2c_dev *i2cd, u8 *data, u16 len) {
>>> +   int status;
>>> +   u32 val;
>>> +
>>> +   val = I2C_MST_CNTL_GEN_START | I2C_MST_CNTL_GEN_STOP |
>>> +   I2C_MST_CNTL_CMD_READ | (len <<
>> I2C_MST_CNTL_BURST_SIZE_SHIFT) |
>>> +   I2C_MST_CNTL_CYCLE_TRIGGER |
>> I2C_MST_CNTL_GEN_NACK;
>>> +   val &= ~I2C_MST_CNTL_GEN_RAB;
>>> +   writel(val, i2cd->regs + I2C_MST_CNTL);
>>> +
>>> +   status = i2c_check_status(i2cd);
>>> +   if (status < 0)
>>> +   return status;
>>> +
>>> +   val = readl(i2cd->regs + I2C_MST_DATA);
>>> +   switch (len) {
>>> +   case 1:
>>> +   data[0] = val;
>>> +   break;
>>> +   case 2:
>>> +   put_unaligned_be16(val, data);
>>> +   break;
>>> +   case 3:
>>> +   put_unaligned_be16(val >> 8, data);
>>> +   data[2] = val;
>>> +   break;
>>> +   case 4:
>>> +   put_unaligned_be32(val, data);
>>> +   break;
>>> +   default:
>>
>> This seems to behave rather strange for len > 4, and I do not see anything
>> preventing that from happening.
> Actually the check is in ccg_read() of the 
> client driver at https://marc.info/?l=linux-usb&m=153618608301206&w=2 
> 
>> Am I missing something, or do you need to add a quirk for max_read_len?
> I will add a check in this function as well.

No, you should add a pointer to a struct i2c_adapter_quirks, with
max_read_len set I think. At least that's how e.g. i2c-qup.c does it.

>>> +   break;
>>> +   }
>>> +   return status;
>>> +}
>>> +
>>> +static int i2c_start(struct gpu_i2c_dev *i2cd, u16 addr) {
>>> +   u32 val;
>>> +
>>> +   val = addr << I2C_MST_ADDR_DAB;
>>> +   writel(val, i2cd->regs + I2C_MST_ADDR);
>>> +
>>> +   val = I2C_MST_CNTL_GEN_START | I2C_MST_CNTL_CMD_NONE |
>>> +   I2C_MST_CNTL_GEN_NACK;
>>> +   val &= ~(I2C_MST_CNTL_GEN_STOP | I2C_MST_CNTL_GEN_RAB);
>>> +   writel(val, i2cd->regs + I2C_MST_CNTL);
>>> +
>>> +   return i2c_check_status(i2cd);
>>> +}
>>> +
>>> +static int i2c_stop(struct gpu_i2c_dev *i2cd) {
>>> +   u32 val;
>>> +
>>> +   val = I2C_MST_CNTL_GEN_STOP | I2C_MST_CNTL_CMD_NONE |
>>> +   I2C_MST_CNTL_GEN_NACK;
>>> +   val &= ~(I2C_MST_CNTL_GEN_START | I2C_MST_CNTL_GEN_RAB);
>>> +   writel(val, i2cd->regs + I2C_MST_CNTL);
>>> +
>>> +   return i2c_check_status(i2cd);
>>> +}
>>> +
>>> +static int i2c_write(struct gpu_i2c_dev *i2cd, u8 data) {
>>> +   u32 val;
>>> +
>>> +   writel(data, i2cd->regs + I2C_MST_DATA);
>>> +
>>> +   val = I2C_MST_CNTL_CMD_WRITE | (1 <<
>> I2C_MST_CNTL_BURST_SIZE_SHIFT) |
>>> +   I2C_MST_CNTL_GEN_NACK;
>>> +   val &= ~(I2C_MST_CNTL_GEN_START | I2C_MST_C

RE: [PATCH v6 1/2] i2c: buses: add i2c bus driver for NVIDIA GPU

2018-09-06 Thread Ajay Gupta
Hi Peter,

> > Latest NVIDIA GPU card has USB Type-C interface. There is a Type-C
> > controller which can be accessed over I2C.
> >
> > This driver adds I2C bus driver to communicate with Type-C controller.
> > I2C client driver will be part of USB Type-C UCSI driver.
> >
> > Signed-off-by: Ajay Gupta 

> > +static void enable_i2c_bus(struct gpu_i2c_dev *i2cd)
> 
> Please prefix all your functions with gpu_, or nvidia_gpu_ or something like
> that (because gpu sounds like a something graphics, not that nvidia_gpu helps
> with that problem though...)
Ok, will prefix them.
 
> > +{
> > +   u32 val;
> > +
> > +   /* enable I2C */
> > +   val = readl(i2cd->regs + I2C_MST_HYBRID_PADCTL);
> > +   val |= I2C_MST_HYBRID_PADCTL_MODE_I2C |
> > +   I2C_MST_HYBRID_PADCTL_I2C_SCL_INPUT_RCV |
> > +   I2C_MST_HYBRID_PADCTL_I2C_SDA_INPUT_RCV;
> > +   writel(val, i2cd->regs + I2C_MST_HYBRID_PADCTL);
> > +
> > +   /* enable 100KHZ mode */
> > +   val = I2C_MST_I2C0_TIMING_SCL_PERIOD_100KHZ;
> > +   val |= (I2C_MST_I2C0_TIMING_TIMEOUT_CLK_CNT_MAX
> > +   << I2C_MST_I2C0_TIMING_TIMEOUT_CLK_CNT);
> > +   val |= I2C_MST_I2C0_TIMING_TIMEOUT_CHECK;
> > +   writel(val, i2cd->regs + I2C_MST_I2C0_TIMING); }
> > +
> > +static int i2c_check_status(struct gpu_i2c_dev *i2cd) {
> > +   unsigned long target = jiffies + msecs_to_jiffies(1000);
> > +   u32 val;
> > +
> > +   do {
> > +   val = readl(i2cd->regs + I2C_MST_CNTL);
> > +   if (!(val & I2C_MST_CNTL_CYCLE_TRIGGER))
> > +   break;
> > +   if ((val & I2C_MST_CNTL_STATUS) !=
> > +   I2C_MST_CNTL_STATUS_BUS_BUSY)
> > +   break;
> > +   usleep_range(1000, 2000);
> > +   } while (time_is_after_jiffies(target));
> > +   if (time_is_before_jiffies(target))
> > +   return -EIO;
> > +
> > +   val = readl(i2cd->regs + I2C_MST_CNTL);
> > +   switch (val & I2C_MST_CNTL_STATUS) {
> > +   case I2C_MST_CNTL_STATUS_OKAY:
> > +   return 0;
> > +   case I2C_MST_CNTL_STATUS_NO_ACK:
> > +   return -EIO;
> > +   case I2C_MST_CNTL_STATUS_TIMEOUT:
> > +   return -ETIME;
> > +   case I2C_MST_CNTL_STATUS_BUS_BUSY:
> > +   return -EBUSY;
> > +   default:
> > +   return 0;
> > +   }
> > +}
> > +
> > +static int i2c_read(struct gpu_i2c_dev *i2cd, u8 *data, u16 len) {
> > +   int status;
> > +   u32 val;
> > +
> > +   val = I2C_MST_CNTL_GEN_START | I2C_MST_CNTL_GEN_STOP |
> > +   I2C_MST_CNTL_CMD_READ | (len <<
> I2C_MST_CNTL_BURST_SIZE_SHIFT) |
> > +   I2C_MST_CNTL_CYCLE_TRIGGER |
> I2C_MST_CNTL_GEN_NACK;
> > +   val &= ~I2C_MST_CNTL_GEN_RAB;
> > +   writel(val, i2cd->regs + I2C_MST_CNTL);
> > +
> > +   status = i2c_check_status(i2cd);
> > +   if (status < 0)
> > +   return status;
> > +
> > +   val = readl(i2cd->regs + I2C_MST_DATA);
> > +   switch (len) {
> > +   case 1:
> > +   data[0] = val;
> > +   break;
> > +   case 2:
> > +   put_unaligned_be16(val, data);
> > +   break;
> > +   case 3:
> > +   put_unaligned_be16(val >> 8, data);
> > +   data[2] = val;
> > +   break;
> > +   case 4:
> > +   put_unaligned_be32(val, data);
> > +   break;
> > +   default:
> 
> This seems to behave rather strange for len > 4, and I do not see anything
> preventing that from happening.
Actually the check is in ccg_read() of the 
client driver at https://marc.info/?l=linux-usb&m=153618608301206&w=2 

> Am I missing something, or do you need to add a quirk for max_read_len?
I will add a check in this function as well.

> > +   break;
> > +   }
> > +   return status;
> > +}
> > +
> > +static int i2c_start(struct gpu_i2c_dev *i2cd, u16 addr) {
> > +   u32 val;
> > +
> > +   val = addr << I2C_MST_ADDR_DAB;
> > +   writel(val, i2cd->regs + I2C_MST_ADDR);
> > +
> > +   val = I2C_MST_CNTL_GEN_START | I2C_MST_CNTL_CMD_NONE |
> > +   I2C_MST_CNTL_GEN_NACK;
> > +   val &= ~(I2C_MST_CNTL_GEN_STOP | I2C_MST_CNTL_GEN_RAB);
> > +   writel(val, i2cd->regs + I2C_MST_CNTL);
> > +
> > +   return i2c_check_status(i2cd);
> > +}
> > +
> > +static int i2c_stop(struct gpu_i2c_dev *i2cd) {
> > +   u32 val;
> > +
> > +   val = I2C_MST_CNTL_GEN_STOP | I2C_MST_CNTL_CMD_NONE |
> > +   I2C_MST_CNTL_GEN_NACK;
> > +   val &= ~(I2C_MST_CNTL_GEN_START | I2C_MST_CNTL_GEN_RAB);
> > +   writel(val, i2cd->regs + I2C_MST_CNTL);
> > +
> > +   return i2c_check_status(i2cd);
> > +}
> > +
> > +static int i2c_write(struct gpu_i2c_dev *i2cd, u8 data) {
> > +   u32 val;
> > +
> > +   writel(data, i2cd->regs + I2C_MST_DATA);
> > +
> > +   val = I2C_MST_CNTL_CMD_WRITE | (1 <<
> I2C_MST_CNTL_BURST_SIZE_SHIFT) |
> > +   I2C_MST_CNTL_GEN_NACK;
> > +   val &= ~(I2C_MST_CNTL_GEN_START | I2C_MST_CNTL_GEN_STOP |
> > +I2C_MST_CNTL_GEN_RAB);
> > +   writel(val, i2cd->regs + I2C_MST_CNTL);
> > +
> > +   return i2c_check_status(i2cd);
> > +}
> > +
> > +static int gpu_i2c_master_xfer(struct

Re: [PATCH v6 1/2] i2c: buses: add i2c bus driver for NVIDIA GPU

2018-09-06 Thread Peter Rosin
On 2018-09-06 00:20, Ajay Gupta wrote:
> Latest NVIDIA GPU card has USB Type-C interface. There is a
> Type-C controller which can be accessed over I2C.
> 
> This driver adds I2C bus driver to communicate with Type-C controller.
> I2C client driver will be part of USB Type-C UCSI driver.
> 
> Signed-off-by: Ajay Gupta 
> ---
> Changes from v1 -> v2
>   None
> Changes from v2 -> v3
>   Fixed review comments from Andy and Thierry
>   Rename i2c-gpu.c -> i2c-nvidia-gpu.c
> Changes from v3 -> v4
>   Fixed review comments from Andy
> Changes from v4 -> v5
>   Fixed review comments from Andy
> Changes from v5 -> v6
>   None 
> 
>  Documentation/i2c/busses/i2c-nvidia-gpu |  18 ++
>  MAINTAINERS |   7 +
>  drivers/i2c/busses/Kconfig  |   9 +
>  drivers/i2c/busses/Makefile |   1 +
>  drivers/i2c/busses/i2c-nvidia-gpu.c | 405 
> 
>  5 files changed, 440 insertions(+)
>  create mode 100644 Documentation/i2c/busses/i2c-nvidia-gpu
>  create mode 100644 drivers/i2c/busses/i2c-nvidia-gpu.c
> 
> diff --git a/Documentation/i2c/busses/i2c-nvidia-gpu 
> b/Documentation/i2c/busses/i2c-nvidia-gpu
> new file mode 100644
> index 000..31884d2
> --- /dev/null
> +++ b/Documentation/i2c/busses/i2c-nvidia-gpu
> @@ -0,0 +1,18 @@
> +Kernel driver i2c-nvidia-gpu
> +
> +Datasheet: not publicly available.
> +
> +Authors:
> + Ajay Gupta 
> +
> +Description
> +---
> +
> +i2c-nvidia-gpu is a driver for I2C controller included in NVIDIA Turing
> +and later GPUs and it is used to communicate with Type-C controller on GPUs.
> +
> +If your 'lspci -v' listing shows something like the following,
> +
> +01:00.3 Serial bus controller [0c80]: NVIDIA Corporation Device 1ad9 (rev a1)
> +
> +then this driver should support the I2C controller of your GPU.
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9ad052a..2d1c5a1 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6797,6 +6797,13 @@ L: linux-a...@vger.kernel.org
>  S:   Maintained
>  F:   drivers/i2c/i2c-core-acpi.c
>  
> +I2C CONTROLLER DRIVER FOR NVIDIA GPU
> +M:   Ajay Gupta 
> +L:   linux-...@vger.kernel.org
> +S:   Maintained
> +F:   Documentation/i2c/busses/i2c-nvidia-gpu
> +F:   drivers/i2c/busses/i2c-nvidia-gpu.c
> +
>  I2C MUXES
>  M:   Peter Rosin 
>  L:   linux-...@vger.kernel.org
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index 451d4ae..eed827b 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -224,6 +224,15 @@ config I2C_NFORCE2_S4985
> This driver can also be built as a module.  If so, the module
> will be called i2c-nforce2-s4985.
>  
> +config I2C_NVIDIA_GPU
> + tristate "NVIDIA GPU I2C controller"
> + depends on PCI
> + help
> +   If you say yes to this option, support will be included for the
> +   NVIDIA GPU I2C controller which is used to communicate with the GPU's
> +   Type-C controller. This driver can also be built as a module called
> +   i2c-nvidia-gpu.
> +
>  config I2C_SIS5595
>   tristate "SiS 5595"
>   depends on PCI
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index 18b26af..d499813 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -140,5 +140,6 @@ obj-$(CONFIG_I2C_SIBYTE)  += i2c-sibyte.o
>  obj-$(CONFIG_I2C_XGENE_SLIMPRO) += i2c-xgene-slimpro.o
>  obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
>  obj-$(CONFIG_I2C_FSI)+= i2c-fsi.o
> +obj-$(CONFIG_I2C_NVIDIA_GPU) += i2c-nvidia-gpu.o
>  
>  ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
> diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c 
> b/drivers/i2c/busses/i2c-nvidia-gpu.c
> new file mode 100644
> index 000..2ce6706
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-nvidia-gpu.c
> @@ -0,0 +1,405 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Nvidia GPU I2C controller Driver
> + *
> + * Copyright (C) 2018 NVIDIA Corporation. All rights reserved.
> + * Author: Ajay Gupta 
> + */
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +
> +/* I2C definitions */
> +#define I2C_MST_CNTL 0x00
> +#define I2C_MST_CNTL_GEN_START   BIT(0)
> +#define I2C_MST_CNTL_GEN_STOPBIT(1)
> +#define I2C_MST_CNTL_CMD_NONE(0 << 2)
> +#define I2C_MST_CNTL_CMD_READ(1 << 2)
> +#define I2C_MST_CNTL_CMD_WRITE   (2 << 2)
> +#define I2C_MST_CNTL_GEN_RAB BIT(4)
> +#define I2C_MST_CNTL_BURST_SIZE_SHIFT6
> +#define I2C_MST_CNTL_GEN_NACKBIT(28)
> +#define I2C_MST_CNTL_STATUS  GENMASK(30, 29)
> +#define I2C_MST_CNTL_STATUS_OKAY (0 << 29)
> +#define I2C_MST_CNTL_STATUS_NO_ACK   (1 << 29)
> +#define I2C_MST_CNTL_STATUS_TIMEOUT  (2 <

Re: [PATCH v6 1/2] i2c: buses: add i2c bus driver for NVIDIA GPU

2018-09-06 Thread Heikki Krogerus
On Wed, Sep 05, 2018 at 03:20:21PM -0700, Ajay Gupta wrote:
> Latest NVIDIA GPU card has USB Type-C interface. There is a
> Type-C controller which can be accessed over I2C.
> 
> This driver adds I2C bus driver to communicate with Type-C controller.
> I2C client driver will be part of USB Type-C UCSI driver.
> 
> Signed-off-by: Ajay Gupta 

FWIW:

Reviewed-by: Heikki Krogerus 

> ---
> Changes from v1 -> v2
>   None
> Changes from v2 -> v3
>   Fixed review comments from Andy and Thierry
>   Rename i2c-gpu.c -> i2c-nvidia-gpu.c
> Changes from v3 -> v4
>   Fixed review comments from Andy
> Changes from v4 -> v5
>   Fixed review comments from Andy
> Changes from v5 -> v6
>   None 
> 
>  Documentation/i2c/busses/i2c-nvidia-gpu |  18 ++
>  MAINTAINERS |   7 +
>  drivers/i2c/busses/Kconfig  |   9 +
>  drivers/i2c/busses/Makefile |   1 +
>  drivers/i2c/busses/i2c-nvidia-gpu.c | 405 
> 
>  5 files changed, 440 insertions(+)
>  create mode 100644 Documentation/i2c/busses/i2c-nvidia-gpu
>  create mode 100644 drivers/i2c/busses/i2c-nvidia-gpu.c
> 
> diff --git a/Documentation/i2c/busses/i2c-nvidia-gpu 
> b/Documentation/i2c/busses/i2c-nvidia-gpu
> new file mode 100644
> index 000..31884d2
> --- /dev/null
> +++ b/Documentation/i2c/busses/i2c-nvidia-gpu
> @@ -0,0 +1,18 @@
> +Kernel driver i2c-nvidia-gpu
> +
> +Datasheet: not publicly available.
> +
> +Authors:
> + Ajay Gupta 
> +
> +Description
> +---
> +
> +i2c-nvidia-gpu is a driver for I2C controller included in NVIDIA Turing
> +and later GPUs and it is used to communicate with Type-C controller on GPUs.
> +
> +If your 'lspci -v' listing shows something like the following,
> +
> +01:00.3 Serial bus controller [0c80]: NVIDIA Corporation Device 1ad9 (rev a1)
> +
> +then this driver should support the I2C controller of your GPU.
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9ad052a..2d1c5a1 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6797,6 +6797,13 @@ L: linux-a...@vger.kernel.org
>  S:   Maintained
>  F:   drivers/i2c/i2c-core-acpi.c
>  
> +I2C CONTROLLER DRIVER FOR NVIDIA GPU
> +M:   Ajay Gupta 
> +L:   linux-...@vger.kernel.org
> +S:   Maintained
> +F:   Documentation/i2c/busses/i2c-nvidia-gpu
> +F:   drivers/i2c/busses/i2c-nvidia-gpu.c
> +
>  I2C MUXES
>  M:   Peter Rosin 
>  L:   linux-...@vger.kernel.org
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index 451d4ae..eed827b 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -224,6 +224,15 @@ config I2C_NFORCE2_S4985
> This driver can also be built as a module.  If so, the module
> will be called i2c-nforce2-s4985.
>  
> +config I2C_NVIDIA_GPU
> + tristate "NVIDIA GPU I2C controller"
> + depends on PCI
> + help
> +   If you say yes to this option, support will be included for the
> +   NVIDIA GPU I2C controller which is used to communicate with the GPU's
> +   Type-C controller. This driver can also be built as a module called
> +   i2c-nvidia-gpu.
> +
>  config I2C_SIS5595
>   tristate "SiS 5595"
>   depends on PCI
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index 18b26af..d499813 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -140,5 +140,6 @@ obj-$(CONFIG_I2C_SIBYTE)  += i2c-sibyte.o
>  obj-$(CONFIG_I2C_XGENE_SLIMPRO) += i2c-xgene-slimpro.o
>  obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
>  obj-$(CONFIG_I2C_FSI)+= i2c-fsi.o
> +obj-$(CONFIG_I2C_NVIDIA_GPU) += i2c-nvidia-gpu.o
>  
>  ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
> diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c 
> b/drivers/i2c/busses/i2c-nvidia-gpu.c
> new file mode 100644
> index 000..2ce6706
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-nvidia-gpu.c
> @@ -0,0 +1,405 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Nvidia GPU I2C controller Driver
> + *
> + * Copyright (C) 2018 NVIDIA Corporation. All rights reserved.
> + * Author: Ajay Gupta 
> + */
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +
> +/* I2C definitions */
> +#define I2C_MST_CNTL 0x00
> +#define I2C_MST_CNTL_GEN_START   BIT(0)
> +#define I2C_MST_CNTL_GEN_STOPBIT(1)
> +#define I2C_MST_CNTL_CMD_NONE(0 << 2)
> +#define I2C_MST_CNTL_CMD_READ(1 << 2)
> +#define I2C_MST_CNTL_CMD_WRITE   (2 << 2)
> +#define I2C_MST_CNTL_GEN_RAB BIT(4)
> +#define I2C_MST_CNTL_BURST_SIZE_SHIFT6
> +#define I2C_MST_CNTL_GEN_NACKBIT(28)
> +#define I2C_MST_CNTL_STATUS  GENMASK(30, 29)
> +#define I2C_MST_CNTL_STATUS_OKAY (0 << 29)
> +#define I2C_MST_CNTL_STATUS_NO_ACK   (1

Re: [PATCH v6 1/2] i2c: buses: add i2c bus driver for NVIDIA GPU

2018-09-05 Thread Andy Shevchenko
On Thu, Sep 6, 2018 at 1:23 AM Ajay Gupta  wrote:
>
> Latest NVIDIA GPU card has USB Type-C interface. There is a
> Type-C controller which can be accessed over I2C.
>
> This driver adds I2C bus driver to communicate with Type-C controller.
> I2C client driver will be part of USB Type-C UCSI driver.
>

FWIW,
Reviewed-by: Andy Shevchenko 

> Signed-off-by: Ajay Gupta 
> ---
> Changes from v1 -> v2
> None
> Changes from v2 -> v3
> Fixed review comments from Andy and Thierry
> Rename i2c-gpu.c -> i2c-nvidia-gpu.c
> Changes from v3 -> v4
> Fixed review comments from Andy
> Changes from v4 -> v5
> Fixed review comments from Andy
> Changes from v5 -> v6
> None
>
>  Documentation/i2c/busses/i2c-nvidia-gpu |  18 ++
>  MAINTAINERS |   7 +
>  drivers/i2c/busses/Kconfig  |   9 +
>  drivers/i2c/busses/Makefile |   1 +
>  drivers/i2c/busses/i2c-nvidia-gpu.c | 405 
> 
>  5 files changed, 440 insertions(+)
>  create mode 100644 Documentation/i2c/busses/i2c-nvidia-gpu
>  create mode 100644 drivers/i2c/busses/i2c-nvidia-gpu.c
>
> diff --git a/Documentation/i2c/busses/i2c-nvidia-gpu 
> b/Documentation/i2c/busses/i2c-nvidia-gpu
> new file mode 100644
> index 000..31884d2
> --- /dev/null
> +++ b/Documentation/i2c/busses/i2c-nvidia-gpu
> @@ -0,0 +1,18 @@
> +Kernel driver i2c-nvidia-gpu
> +
> +Datasheet: not publicly available.
> +
> +Authors:
> +   Ajay Gupta 
> +
> +Description
> +---
> +
> +i2c-nvidia-gpu is a driver for I2C controller included in NVIDIA Turing
> +and later GPUs and it is used to communicate with Type-C controller on GPUs.
> +
> +If your 'lspci -v' listing shows something like the following,
> +
> +01:00.3 Serial bus controller [0c80]: NVIDIA Corporation Device 1ad9 (rev a1)
> +
> +then this driver should support the I2C controller of your GPU.
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9ad052a..2d1c5a1 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6797,6 +6797,13 @@ L:   linux-a...@vger.kernel.org
>  S: Maintained
>  F: drivers/i2c/i2c-core-acpi.c
>
> +I2C CONTROLLER DRIVER FOR NVIDIA GPU
> +M: Ajay Gupta 
> +L: linux-...@vger.kernel.org
> +S: Maintained
> +F: Documentation/i2c/busses/i2c-nvidia-gpu
> +F: drivers/i2c/busses/i2c-nvidia-gpu.c
> +
>  I2C MUXES
>  M: Peter Rosin 
>  L: linux-...@vger.kernel.org
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index 451d4ae..eed827b 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -224,6 +224,15 @@ config I2C_NFORCE2_S4985
>   This driver can also be built as a module.  If so, the module
>   will be called i2c-nforce2-s4985.
>
> +config I2C_NVIDIA_GPU
> +   tristate "NVIDIA GPU I2C controller"
> +   depends on PCI
> +   help
> + If you say yes to this option, support will be included for the
> + NVIDIA GPU I2C controller which is used to communicate with the 
> GPU's
> + Type-C controller. This driver can also be built as a module called
> + i2c-nvidia-gpu.
> +
>  config I2C_SIS5595
> tristate "SiS 5595"
> depends on PCI
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index 18b26af..d499813 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -140,5 +140,6 @@ obj-$(CONFIG_I2C_SIBYTE)+= i2c-sibyte.o
>  obj-$(CONFIG_I2C_XGENE_SLIMPRO) += i2c-xgene-slimpro.o
>  obj-$(CONFIG_SCx200_ACB)   += scx200_acb.o
>  obj-$(CONFIG_I2C_FSI)  += i2c-fsi.o
> +obj-$(CONFIG_I2C_NVIDIA_GPU)   += i2c-nvidia-gpu.o
>
>  ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
> diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c 
> b/drivers/i2c/busses/i2c-nvidia-gpu.c
> new file mode 100644
> index 000..2ce6706
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-nvidia-gpu.c
> @@ -0,0 +1,405 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Nvidia GPU I2C controller Driver
> + *
> + * Copyright (C) 2018 NVIDIA Corporation. All rights reserved.
> + * Author: Ajay Gupta 
> + */
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +
> +/* I2C definitions */
> +#define I2C_MST_CNTL   0x00
> +#define I2C_MST_CNTL_GEN_START BIT(0)
> +#define I2C_MST_CNTL_GEN_STOP  BIT(1)
> +#define I2C_MST_CNTL_CMD_NONE  (0 << 2)
> +#define I2C_MST_CNTL_CMD_READ  (1 << 2)
> +#define I2C_MST_CNTL_CMD_WRITE (2 << 2)
> +#define I2C_MST_CNTL_GEN_RAB   BIT(4)
> +#define I2C_MST_CNTL_BURST_SIZE_SHIFT  6
> +#define I2C_MST_CNTL_GEN_NACK  BIT(28)
> +#define I2C_MST_CNTL_STATUSGENMASK(30, 29)
> +#define I2C_MST_CNTL_STATUS_OKAY   (0 << 29)
> +#define I2C_MST_CNTL_STATUS_NO_ACK