diff mbox series

[3/5] i2c: designware: add MSCC Ocelot support

Message ID 20180717114837.21839-4-alexandre.belloni@bootlin.com
State Changes Requested, archived
Headers show
Series Add support for MSCC Ocelot i2c | expand

Commit Message

Alexandre Belloni July 17, 2018, 11:48 a.m. UTC
The Microsemi Ocelot I2C controller is a designware IP. It also has a
second set of registers to allow tweaking SDA hold time and spike
filtering.

Cc: Rob Herring <robh+dt@kernel.org>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
 .../bindings/i2c/i2c-designware.txt           |  5 ++++-
 drivers/i2c/busses/i2c-designware-core.h      |  1 +
 drivers/i2c/busses/i2c-designware-platdrv.c   | 20 +++++++++++++++++++
 3 files changed, 25 insertions(+), 1 deletion(-)

Comments

Andy Shevchenko July 17, 2018, 12:19 p.m. UTC | #1
On Tue, 2018-07-17 at 13:48 +0200, Alexandre Belloni wrote:
> The Microsemi Ocelot I2C controller is a designware IP. It also has a
> second set of registers to allow tweaking SDA hold time and spike
> filtering.

Can you elaborate a bit?

Are they platform specific? Are they shadow registers? Are they
something else? Datasheet link / excerpt would be also good to read.
 
>  Optional properties :
> + - reg : for "mscc,ocelot-i2c", a second register set to configure
> the SDA hold
> +   time, named ICPU_CFG:TWI_DELAY in the datasheet.
> +

Hmm... Is this registers unique to the SoC in question? Is address of
them fixed or may be configured on RTL level?

If former is right, why do we need a separate property?

>  
> +#define MSCC_ICPU_CFG_TWI_DELAY		0x0
> +#define MSCC_ICPU_CFG_TWI_DELAY_ENABLE	BIT(0)
> +#define MSCC_ICPU_CFG_TWI_SPIKE_FILTER	0x4
> +
> +static int mscc_twi_set_sda_hold_time(struct dw_i2c_dev *dev)
> +{
> +	writel((dev->sda_hold_time << 1) |
> MSCC_ICPU_CFG_TWI_DELAY_ENABLE,
> +	       dev->base_ext + MSCC_ICPU_CFG_TWI_DELAY);
> +
> +	return 0;
> +}

Hmm... And does how this make native DesignWare IP's registers obsolete?


> +	if (of_device_is_compatible(pdev->dev.of_node, "mscc,ocelot-
> i2c"))

Can't you just ask for this unconditionally? Why not?
(It seems I might have known why not, but can we use named resource
instead in case this is not so SoC specific)
Alexandre Belloni July 17, 2018, 12:40 p.m. UTC | #2
On 17/07/2018 15:19:08+0300, Andy Shevchenko wrote:
> On Tue, 2018-07-17 at 13:48 +0200, Alexandre Belloni wrote:
> > The Microsemi Ocelot I2C controller is a designware IP. It also has a
> > second set of registers to allow tweaking SDA hold time and spike
> > filtering.
> 
> Can you elaborate a bit?
> 
> Are they platform specific? Are they shadow registers? Are they
> something else? Datasheet link / excerpt would be also good to read.
>  
> >  Optional properties :
> > + - reg : for "mscc,ocelot-i2c", a second register set to configure
> > the SDA hold
> > +   time, named ICPU_CFG:TWI_DELAY in the datasheet.
> > +
> 
> Hmm... Is this registers unique to the SoC in question? Is address of
> them fixed or may be configured on RTL level?
> 
> If former is right, why do we need a separate property?
> 

Those are registers from the SoC, their position varies depending on
the SoC.

Even if the position was fixed, I'm pretty sure another register set is
needed. It is not a new property.

> >  
> > +#define MSCC_ICPU_CFG_TWI_DELAY		0x0
> > +#define MSCC_ICPU_CFG_TWI_DELAY_ENABLE	BIT(0)
> > +#define MSCC_ICPU_CFG_TWI_SPIKE_FILTER	0x4
> > +
> > +static int mscc_twi_set_sda_hold_time(struct dw_i2c_dev *dev)
> > +{
> > +	writel((dev->sda_hold_time << 1) |
> > MSCC_ICPU_CFG_TWI_DELAY_ENABLE,
> > +	       dev->base_ext + MSCC_ICPU_CFG_TWI_DELAY);
> > +
> > +	return 0;
> > +}
> 
> Hmm... And does how this make native DesignWare IP's registers obsolete?
> 

DW_IC_SDA_HOLD doesn't exist in this version of the IP. It is replaced
by this SoC specific register.

> 
> > +	if (of_device_is_compatible(pdev->dev.of_node, "mscc,ocelot-
> > i2c"))
> 
> Can't you just ask for this unconditionally? Why not?
> (It seems I might have known why not, but can we use named resource
> instead in case this is not so SoC specific)
> 

It is SoC specific.
Andy Shevchenko July 17, 2018, 3:26 p.m. UTC | #3
On Tue, 2018-07-17 at 18:16 +0300, Andy Shevchenko wrote:
> On Tue, 2018-07-17 at 13:48 +0200, Alexandre Belloni wrote:
> > The Microsemi Ocelot I2C controller is a designware IP. It also has
> > a
> > second set of registers to allow tweaking SDA hold time and spike
> > filtering.

> What do you think?

You can also split it to 2-3 patches, like:
- move to device_get_match_data()
- move OF device table above in the code (no func changes)
- add support for MSCC
Rob Herring July 20, 2018, 5:56 p.m. UTC | #4
On Tue, Jul 17, 2018 at 01:48:35PM +0200, Alexandre Belloni wrote:
> The Microsemi Ocelot I2C controller is a designware IP. It also has a
> second set of registers to allow tweaking SDA hold time and spike
> filtering.
> 
> Cc: Rob Herring <robh+dt@kernel.org>
> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
> ---
>  .../bindings/i2c/i2c-designware.txt           |  5 ++++-
>  drivers/i2c/busses/i2c-designware-core.h      |  1 +
>  drivers/i2c/busses/i2c-designware-platdrv.c   | 20 +++++++++++++++++++
>  3 files changed, 25 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-designware.txt b/Documentation/devicetree/bindings/i2c/i2c-designware.txt
> index fbb0a6d8b964..7af4176da4af 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-designware.txt
> +++ b/Documentation/devicetree/bindings/i2c/i2c-designware.txt
> @@ -2,7 +2,7 @@
>  
>  Required properties :
>  
> - - compatible : should be "snps,designware-i2c"
> + - compatible : should be "snps,designware-i2c" or "mscc,ocelot-i2c"

Sounds like the registers are optional (or could be initialized by 
firmware), so shouldn't 'snps,designware-i2c' be a fallback compatible?

>   - reg : Offset and length of the register set for the device
>   - interrupts : <IRQ> where IRQ is the interrupt number.
>  
> @@ -11,6 +11,9 @@ Recommended properties :
>   - clock-frequency : desired I2C bus clock frequency in Hz.
>  
>  Optional properties :
> + - reg : for "mscc,ocelot-i2c", a second register set to configure the SDA hold
> +   time, named ICPU_CFG:TWI_DELAY in the datasheet.
> +
>   - i2c-sda-hold-time-ns : should contain the SDA hold time in nanoseconds.
>     This option is only supported in hardware blocks version 1.11a or newer.

Perhaps this needs an update too? It sounds like Microsemi fixed this 
problem on their own before version 1.11a of the IP block.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox series

Patch

diff --git a/Documentation/devicetree/bindings/i2c/i2c-designware.txt b/Documentation/devicetree/bindings/i2c/i2c-designware.txt
index fbb0a6d8b964..7af4176da4af 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-designware.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-designware.txt
@@ -2,7 +2,7 @@ 
 
 Required properties :
 
- - compatible : should be "snps,designware-i2c"
+ - compatible : should be "snps,designware-i2c" or "mscc,ocelot-i2c"
  - reg : Offset and length of the register set for the device
  - interrupts : <IRQ> where IRQ is the interrupt number.
 
@@ -11,6 +11,9 @@  Recommended properties :
  - clock-frequency : desired I2C bus clock frequency in Hz.
 
 Optional properties :
+ - reg : for "mscc,ocelot-i2c", a second register set to configure the SDA hold
+   time, named ICPU_CFG:TWI_DELAY in the datasheet.
+
  - i2c-sda-hold-time-ns : should contain the SDA hold time in nanoseconds.
    This option is only supported in hardware blocks version 1.11a or newer.
 
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index b2778b6d8aca..37f63d084c1d 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -237,6 +237,7 @@ 
 struct dw_i2c_dev {
 	struct device		*dev;
 	void __iomem		*base;
+	void __iomem		*base_ext;
 	struct completion	cmd_complete;
 	struct clk		*clk;
 	struct reset_control	*rst;
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 5660daf6c92e..1a476a6e3551 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -204,6 +204,18 @@  static void i2c_dw_configure_slave(struct dw_i2c_dev *dev)
 	dev->mode = DW_IC_SLAVE;
 }
 
+#define MSCC_ICPU_CFG_TWI_DELAY		0x0
+#define MSCC_ICPU_CFG_TWI_DELAY_ENABLE	BIT(0)
+#define MSCC_ICPU_CFG_TWI_SPIKE_FILTER	0x4
+
+static int mscc_twi_set_sda_hold_time(struct dw_i2c_dev *dev)
+{
+	writel((dev->sda_hold_time << 1) | MSCC_ICPU_CFG_TWI_DELAY_ENABLE,
+	       dev->base_ext + MSCC_ICPU_CFG_TWI_DELAY);
+
+	return 0;
+}
+
 static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev, int id)
 {
 	u32 param, tx_fifo_depth, rx_fifo_depth;
@@ -342,6 +354,13 @@  static int dw_i2c_plat_probe(struct platform_device *pdev)
 				1000000);
 	}
 
+	if (of_device_is_compatible(pdev->dev.of_node, "mscc,ocelot-i2c")) {
+		mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		dev->base_ext = devm_ioremap_resource(&pdev->dev, mem);
+		if (!IS_ERR(dev->base_ext))
+			dev->set_sda_hold_time = mscc_twi_set_sda_hold_time;
+	}
+
 	dw_i2c_set_fifo_size(dev, pdev->id);
 
 	adap = &dev->adapter;
@@ -410,6 +429,7 @@  static int dw_i2c_plat_remove(struct platform_device *pdev)
 #ifdef CONFIG_OF
 static const struct of_device_id dw_i2c_of_match[] = {
 	{ .compatible = "snps,designware-i2c", },
+	{ .compatible = "mscc,ocelot-i2c", },
 	{},
 };
 MODULE_DEVICE_TABLE(of, dw_i2c_of_match);