All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stefan Roese <sr@denx.de>
To: u-boot@lists.denx.de
Subject: [PATCH v1] i2c: octeon_i2c: Add I2C controller driver for Octeon
Date: Tue, 26 May 2020 12:55:21 +0200	[thread overview]
Message-ID: <4139b0a8-a5c0-77e5-4539-6f7799beef18@denx.de> (raw)
In-Reply-To: <CAPnjgZ34=g8poS=BOR6UAgO4yDQU6usmz7pM2y0PP74JtP9a1A@mail.gmail.com>

Hi Simon,

On 19.05.20 14:32, Simon Glass wrote:
> Hi,
> 
> On Thu, 14 May 2020 at 01:23, Stefan Roese <sr@denx.de> wrote:
>>
>> From: Suneel Garapati <sgarapati@marvell.com>
>>
>> Add support for I2C controllers found on Octeon II/III and Octeon TX
>> TX2 SoC platforms.
>>
>> Signed-off-by: Aaron Williams <awilliams@marvell.com>
>> Signed-off-by: Suneel Garapati <sgarapati@marvell.com>
>> Signed-off-by: Stefan Roese <sr@denx.de>
>> Cc: Heiko Schocher <hs@denx.de>
>> Cc: Simon Glass <sjg@chromium.org>
>> Cc: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
>> Cc: Aaron Williams <awilliams@marvell.com>
>> Cc: Chandrakala Chavva <cchavva@marvell.com>
>> ---
>> RFC -> v1 (Stefan):
>> - Separated this patch from the OcteonTX/TX2 RFC patch series into a
>>    single patch. This is useful, as the upcoming MIPS Octeon support will
>>    use this I2C driver.
>> - Added MIPS Octeon II/III support (big endian). Rename driver and its
>>    function names from "octeontx" to "octeon" to better match all Octeon
>>    platforms.
>> - Moved from union to defines / bitmasks as suggested by Simon. This makes
>>    the driver usage on little- and big-endian platforms much easier.
>> - Enhanced Kconfig text
>> - Removed all clock macros (use values from DT)
>> - Removed long driver debug strings. This is only available when a debug
>>    version of this driver is built. The user / developer can lookup the
>>    descriptive error messages in the driver in this case anyway.
>> - Removed static "last_id"
>> - Dropped misc blank lines. Misc reformatting.
>> - Dropped "!= 0"
>> - Added missing function comments
>> - Added missing strut comments
>> - Changed comment style
>> - Renames "result" to "ret"
>> - Hex numbers uppercase
>> - Minor other changes
>> - Reword commit text and subject
>>
>>   drivers/i2c/Kconfig      |  10 +
>>   drivers/i2c/Makefile     |   1 +
>>   drivers/i2c/octeon_i2c.c | 803 +++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 814 insertions(+)
>>   create mode 100644 drivers/i2c/octeon_i2c.c
>>
>> diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
>> index e42b6516bf..1330b36698 100644
>> --- a/drivers/i2c/Kconfig
>> +++ b/drivers/i2c/Kconfig
>> @@ -374,6 +374,16 @@ config SYS_I2C_SANDBOX
>>            bus. Devices can be attached to the bus using the device tree
>>            which specifies the driver to use.  See sandbox.dts as an example.
>>
>> +config SYS_I2C_OCTEON
>> +       bool "Octeon II/III/TX/TX2 I2C driver"
>> +       depends on (ARCH_OCTEON || ARCH_OCTEONTX || ARCH_OCTEONTX2) && DM_I2C
>> +       default y
>> +       help
>> +         Add support for the Marvell Octeon I2C driver. This is used with
>> +         various Octeon parts such as Octeon II/III and OcteonTX/TX2. All
>> +         chips have several I2C ports and all are provided, controlled by
>> +         the device tree.
>> +
>>   config SYS_I2C_S3C24X0
>>          bool "Samsung I2C driver"
>>          depends on ARCH_EXYNOS4 && DM_I2C
>> diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
>> index 62935b7ebc..2b58aae892 100644
>> --- a/drivers/i2c/Makefile
>> +++ b/drivers/i2c/Makefile
>> @@ -27,6 +27,7 @@ obj-$(CONFIG_SYS_I2C_LPC32XX) += lpc32xx_i2c.o
>>   obj-$(CONFIG_SYS_I2C_MESON) += meson_i2c.o
>>   obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o
>>   obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o
>> +obj-$(CONFIG_SYS_I2C_OCTEON) += octeon_i2c.o
>>   obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o
>>   obj-$(CONFIG_SYS_I2C_RCAR_I2C) += rcar_i2c.o
>>   obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o
>> diff --git a/drivers/i2c/octeon_i2c.c b/drivers/i2c/octeon_i2c.c
>> new file mode 100644
>> index 0000000000..210f98655e
>> --- /dev/null
>> +++ b/drivers/i2c/octeon_i2c.c
>> @@ -0,0 +1,803 @@
>> +// SPDX-License-Identifier:    GPL-2.0
>> +/*
>> + * Copyright (C) 2018 Marvell International Ltd.
>> + */
>> +
>> +#include <common.h>
>> +#include <i2c.h>
>> +#include <dm.h>
>> +#include <pci_ids.h>
>> +#include <asm/io.h>
>> +#include <asm/arch/clock.h>
>> +#include <linux/bitfield.h>
>> +
>> +/*
>> + * Octeon II/III (MIPS) have different register offsets than the ARM based
>> + * Octeon TX/TX2 SoCs
>> + */
>> +#if defined(CONFIG_ARCH_OCTEON)
>> +#define REG_OFFS               0x0000
>> +#else
>> +#define REG_OFFS               0x1000
>> +#endif
>> +
>> +#define TWSI_SW_TWSI           (REG_OFFS + 0x00)
>> +#define TWSI_TWSI_SW           (REG_OFFS + 0x08)
>> +#define TWSI_INT               (REG_OFFS + 0x10)
>> +#define TWSI_SW_TWSI_EXT       (REG_OFFS + 0x18)
>> +
>> +#define TWSI_SW_DATA_MASK      GENMASK_ULL(31, 0)
>> +#define TWSI_SW_EOP_IA_MASK    GENMASK_ULL(34, 32)
>> +#define TWSI_SW_IA_MASK                GENMASK_ULL(39, 35)
>> +#define TWSI_SW_ADDR_MASK      GENMASK_ULL(49, 40)
>> +#define TWSI_SW_SCR_MASK       GENMASK_ULL(51, 50)
>> +#define TWSI_SW_SIZE_MASK      GENMASK_ULL(54, 52)
>> +#define TWSI_SW_SOVR           BIT_ULL(55)
>> +#define TWSI_SW_R              BIT_ULL(56)
>> +#define TWSI_SW_OP_MASK                GENMASK_ULL(60, 57)
>> +#define TWSI_SW_EIA            GENMASK_ULL(61)
>> +#define TWSI_SW_SLONLY         BIT_ULL(62)
>> +#define TWSI_SW_V              BIT_ULL(63)
>> +
>> +#define TWSI_INT_SDA_OVR       BIT_ULL(8)
>> +#define TWSI_INT_SCL_OVR       BIT_ULL(9)
>> +#define TWSI_INT_SDA           BIT_ULL(10)
>> +#define TWSI_INT_SCL           BIT_ULL(11)
>> +
>> +enum {
>> +       TWSI_OP_WRITE   = 0,
>> +       TWSI_OP_READ    = 1,
>> +};
>> +
>> +enum {
>> +       TWSI_EOP_SLAVE_ADDR = 0,
>> +       TWSI_EOP_CLK_CTL = 3,
>> +       TWSI_SW_EOP_IA   = 6,
>> +};
>> +
>> +enum {
>> +       TWSI_SLAVEADD     = 0,
>> +       TWSI_DATA         = 1,
>> +       TWSI_CTL          = 2,
>> +       TWSI_CLKCTL       = 3,
>> +       TWSI_STAT         = 3,
>> +       TWSI_SLAVEADD_EXT = 4,
>> +       TWSI_RST          = 7,
>> +};
>> +
>> +enum {
>> +       TWSI_CTL_AAK    = BIT(2),
>> +       TWSI_CTL_IFLG   = BIT(3),
>> +       TWSI_CTL_STP    = BIT(4),
>> +       TWSI_CTL_STA    = BIT(5),
>> +       TWSI_CTL_ENAB   = BIT(6),
>> +       TWSI_CTL_CE     = BIT(7),
>> +};
>> +
>> +/*
>> + * Internal errors. When debugging is enabled, the driver will report the
>> + * error number and the user / developer can check the table below for the
>> + * detailed error description.
>> + */
>> +enum {
>> +       /** Bus error */
>> +       TWSI_STAT_BUS_ERROR             = 0x00,
>> +       /** Start condition transmitted */
>> +       TWSI_STAT_START                 = 0x08,
>> +       /** Repeat start condition transmitted */
>> +       TWSI_STAT_RSTART                = 0x10,
>> +       /** Address + write bit transmitted, ACK received */
>> +       TWSI_STAT_TXADDR_ACK            = 0x18,
>> +       /** Address + write bit transmitted, /ACK received */
>> +       TWSI_STAT_TXADDR_NAK            = 0x20,
>> +       /** Data byte transmitted in master mode, ACK received */
>> +       TWSI_STAT_TXDATA_ACK            = 0x28,
>> +       /** Data byte transmitted in master mode, ACK received */
>> +       TWSI_STAT_TXDATA_NAK            = 0x30,
>> +       /** Arbitration lost in address or data byte */
>> +       TWSI_STAT_TX_ARB_LOST           = 0x38,
>> +       /** Address + read bit transmitted, ACK received */
>> +       TWSI_STAT_RXADDR_ACK            = 0x40,
>> +       /** Address + read bit transmitted, /ACK received */
>> +       TWSI_STAT_RXADDR_NAK            = 0x48,
>> +       /** Data byte received in master mode, ACK transmitted */
>> +       TWSI_STAT_RXDATA_ACK_SENT       = 0x50,
>> +       /** Data byte received, NACK transmitted */
>> +       TWSI_STAT_RXDATA_NAK_SENT       = 0x58,
>> +       /** Slave address received, sent ACK */
>> +       TWSI_STAT_SLAVE_RXADDR_ACK      = 0x60,
>> +       /**
>> +        * Arbitration lost in address as master, slave address + write bit
>> +        * received, ACK transmitted
>> +        */
>> +       TWSI_STAT_TX_ACK_ARB_LOST       = 0x68,
>> +       /** General call address received, ACK transmitted */
>> +       TWSI_STAT_RX_GEN_ADDR_ACK       = 0x70,
>> +       /**
>> +        * Arbitration lost in address as master, general call address
>> +        * received, ACK transmitted
>> +        */
>> +       TWSI_STAT_RX_GEN_ADDR_ARB_LOST  = 0x78,
>> +       /** Data byte received after slave address received, ACK transmitted */
>> +       TWSI_STAT_SLAVE_RXDATA_ACK      = 0x80,
>> +       /** Data byte received after slave address received, /ACK transmitted */
>> +       TWSI_STAT_SLAVE_RXDATA_NAK      = 0x88,
>> +       /**
>> +        * Data byte received after general call address received, ACK
>> +        * transmitted
>> +        */
>> +       TWSI_STAT_GEN_RXADDR_ACK        = 0x90,
>> +       /**
>> +        * Data byte received after general call address received, /ACK
>> +        * transmitted
>> +        */
>> +       TWSI_STAT_GEN_RXADDR_NAK        = 0x98,
>> +       /** STOP or repeated START condition received in slave mode */
>> +       TWSI_STAT_STOP_MULTI_START      = 0xa0,
>> +       /** Slave address + read bit received, ACK transmitted */
>> +       TWSI_STAT_SLAVE_RXADDR2_ACK     = 0xa8,
>> +       /**
>> +        * Arbitration lost in address as master, slave address + read bit
>> +        * received, ACK transmitted
>> +        */
>> +       TWSI_STAT_RXDATA_ACK_ARB_LOST   = 0xb0,
>> +       /** Data byte transmitted in slave mode, ACK received */
>> +       TWSI_STAT_SLAVE_TXDATA_ACK      = 0xb8,
>> +       /** Data byte transmitted in slave mode, /ACK received */
>> +       TWSI_STAT_SLAVE_TXDATA_NAK      = 0xc0,
>> +       /** Last byte transmitted in slave mode, ACK received */
>> +       TWSI_STAT_SLAVE_TXDATA_END_ACK  = 0xc8,
>> +       /** Second address byte + write bit transmitted, ACK received */
>> +       TWSI_STAT_TXADDR2DATA_ACK       = 0xd0,
>> +       /** Second address byte + write bit transmitted, /ACK received */
>> +       TWSI_STAT_TXADDR2DATA_NAK       = 0xd8,
>> +       /** No relevant status information */
>> +       TWSI_STAT_IDLE                  = 0xf8
>> +};
>> +
>> +#ifndef CONFIG_SYS_I2C_OCTEON_SLAVE_ADDR
>> +# define CONFIG_SYS_I2C_OCTEON_SLAVE_ADDR      0x77
> 
> This should be a device-tree property.

Okay, will move to DT.

>> +#endif
>> +
>> +/**
>> + * struct octeon_twsi - Private data of this driver
>> + *
>> + * @base:      Base address of i2c registers
>> + */
>> +struct octeon_twsi {
>> +       void __iomem *base;
>> +};
>> +
>> +static void twsi_unblock(void *base);
>> +static int twsi_stop(void *base);
>> +
>> +#if defined(CONFIG_ARCH_OCTEON)
> 
> Needs a clock driver.

Right. I'll try to add clock driver support with the first Octeon base
port.

>> +static int get_io_clock(void)
>> +{
>> +       return octeon_get_io_clock();
>> +}
>> +#else
>> +static int get_io_clock(void)
>> +{
>> +       return octeontx_get_io_clock();
>> +}
>> +#endif
>> +
>> +static int twsi_thp(void)
>> +{
>> +       if (IS_ENABLED(CONFIG_ARCH_OCTEON) || IS_ENABLED(CONFIG_ARCH_OCTEONTX))
>> +               return 24;
>> +       else
>> +               return 3;
>> +}
>> +
> 
> [..]
> 
>> +/**
>> + * Calculate the divisor values
>> + *
>> + * @speed      Speed to set
>> + * @m_div      Pointer to M divisor
>> + * @n_div      Pointer to N divisor
>> + * @return     0 for success, otherwise error
>> + */
>> +static void twsi_calc_div(unsigned int speed, int *m_div, int *n_div)
>> +{
>> +       int io_clock_hz;
>> +       int tclk, fsamp;
>> +       int ndiv, mdiv;
>> +
>> +#if defined(CONFIG_ARCH_OCTEON) || defined(CONFIG_ARCH_OCTEONTX)
>> +       io_clock_hz = get_io_clock();
>> +       tclk = io_clock_hz / (2 * (twsi_thp() + 1));
>> +#elif defined(CONFIG_ARCH_OCTEONTX2)
>> +       /* Refclk src in mode register defaults to 100MHz clock */
>> +       io_clock_hz = 100000000; /* 100 Mhz */
>> +       tclk = io_clock_hz / (twsi_thp() + 2);
>> +#endif
> 
> Needs a clock driver. If different logic is needed it should use the
> compatible string / driver data rather than #ifdefs.

Yes, will update.

>> +       debug("%s( io_clock %u tclk %u)\n", __func__, io_clock_hz, tclk);
>> +
>> +       /*
>> +        * Compute the clocks M divider:
>> +        *
>> +        * TWSI freq = (core freq) / (10 x (M+1) x 2 * (thp+1) x 2^N)
>> +        * M = ((core freq) / (10 x (TWSI freq) x 2 * (thp+1) x 2^N)) - 1
>> +        *
>> +        * For OcteonTX2 -
>> +        * TWSI freq = (core freq) / (10 x (M+1) x (thp+2) x 2^N)
>> +        * M = ((core freq) / (10 x (TWSI freq) x (thp+2) x 2^N)) - 1
>> +        */
>> +       for (ndiv = 0; ndiv < 8; ndiv++) {
>> +               fsamp = tclk / (1 << ndiv);
>> +               mdiv = fsamp / speed / 10;
>> +               mdiv -= 1;
>> +               if (mdiv < 16)
>> +                       break;
>> +       }
>> +
>> +       *m_div = mdiv;
>> +       *n_div = ndiv;
>> +}
>> +
>> +/**
> 
> [..]
> 
>> +/**
>> + * Driver probe function
>> + *
>> + * @dev                I2C device to probe
>> + * @return     0 for success, otherwise error
>> + */
>> +static int octeon_pci_i2c_probe(struct udevice *dev)
>> +{
>> +       struct octeon_twsi *twsi = dev_get_priv(dev);
>> +#if !defined(CONFIG_ARCH_OCTEON)
> 
> Again should use dev_get_driver_data()

Yes, will update in v2.

Thanks,
Stefan

  reply	other threads:[~2020-05-26 10:55 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-14  7:23 [PATCH v1] i2c: octeon_i2c: Add I2C controller driver for Octeon Stefan Roese
2020-05-19  6:07 ` Heiko Schocher
2020-05-26  6:49   ` Stefan Roese
2020-05-19 12:32 ` Simon Glass
2020-05-26 10:55   ` Stefan Roese [this message]
2020-06-03  5:15 ` Rayagonda Kokatanur
2020-06-03  5:20   ` Stefan Roese
2020-06-03  5:37     ` Rayagonda Kokatanur
2020-06-03  5:39       ` Stefan Roese

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4139b0a8-a5c0-77e5-4539-6f7799beef18@denx.de \
    --to=sr@denx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.