[PATCH net] net: stmmac: dma channel control register need to be init first

2019-05-20 Thread Weifeng Voon
stmmac_init_chan() needs to be called before stmmac_init_rx_chan() and
stmmac_init_tx_chan(). This is because if PBLx8 is to be used,
"DMA_CH(#i)_Control.PBLx8" needs to be set before programming
"DMA_CH(#i)_TX_Control.TxPBL" and "DMA_CH(#i)_RX_Control.RxPBL".

Fixes: 47f2a9ce527a ("net: stmmac: dma channel init prepared for multiple 
queues")
Reviewed-by: Zhang, Baoli 
Signed-off-by: Ong Boon Leong 
Signed-off-by: Weifeng Voon 

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 5678b869cbff..2a1052704885 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2208,6 +2208,10 @@ static int stmmac_init_dma_engine(struct stmmac_priv 
*priv)
if (priv->plat->axi)
stmmac_axi(priv, priv->ioaddr, priv->plat->axi);
 
+   /* DMA CSR Channel configuration */
+   for (chan = 0; chan < dma_csr_ch; chan++)
+   stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
+
/* DMA RX Channel Configuration */
for (chan = 0; chan < rx_channels_count; chan++) {
rx_q = &priv->rx_queue[chan];
@@ -2233,10 +2237,6 @@ static int stmmac_init_dma_engine(struct stmmac_priv 
*priv)
   tx_q->tx_tail_addr, chan);
}
 
-   /* DMA CSR Channel configuration */
-   for (chan = 0; chan < dma_csr_ch; chan++)
-   stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
-
return ret;
 }
 
-- 
1.9.1



[PATCH net] net: stmmac: fix ethtool flow control not able to get/set

2019-05-20 Thread Weifeng Voon
From: "Tan, Tee Min" 

Currently ethtool was not able to get/set the flow control due to a
missing "!". It will always return -EOPNOTSUPP even the device is
flow control supported.

This patch fixes the condition check for ethtool flow control get/set
function for ETHTOOL_LINK_MODE_Asym_Pause_BIT.

Fixes: 3c1bcc8614db (“net: ethernet: Convert phydev advertize and supported 
from u32 to link mode”)
Signed-off-by: Tan, Tee Min 
Reviewed-by: Ong Boon Leong 
Signed-off-by: Voon, Weifeng 

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 3c749c3..e09522c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -460,7 +460,7 @@ static void stmmac_ethtool_gregs(struct net_device *dev,
} else {
if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
   netdev->phydev->supported) ||
-   linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
+   !linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
  netdev->phydev->supported))
return;
}
@@ -491,7 +491,7 @@ static void stmmac_ethtool_gregs(struct net_device *dev,
} else {
if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
   phy->supported) ||
-   linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
+   !linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
  phy->supported))
return -EOPNOTSUPP;
}
-- 
1.9.1



[PATCH 5/7] net: stmmac: add xpcs function hooks into main driver and ethtool

2019-04-24 Thread Weifeng Voon
From: Ong Boon Leong 

With xPCS functions now ready, we add them into the main driver and
ethtool logics. To differentiate from EQoS MAC PCS and DWC Ethernet
xPCS, we introduce 'has_xpcs' in platform data as a mean to indicate
whether GBE controller includes xPCS or not.

To support platform-specific C37 AN PCS mode selection for MII MMD,
we introduce 'pcs_mode' in platform data.

The basic framework for xPCS interrupt handling is implemented too.

Reviewed-by: Chuah Kim Tatt 
Reviewed-by: Voon Weifeng 
Reviewed-by: Kweh Hock Leong 
Reviewed-by: Baoli Zhang 
Signed-off-by: Ong Boon Leong 
---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h   |  2 +
 .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c   | 14 ++
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  | 50 ++
 include/linux/stmmac.h |  2 +
 4 files changed, 68 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h 
b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index dd95d95..0b8460a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -36,6 +36,7 @@ struct stmmac_resources {
const char *mac;
int wol_irq;
int lpi_irq;
+   int xpcs_irq;
int irq;
 };
 
@@ -168,6 +169,7 @@ struct stmmac_priv {
int clk_csr;
struct timer_list eee_ctrl_timer;
int lpi_irq;
+   int xpcs_irq;
int eee_enabled;
int eee_active;
int tx_lpi_timer;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 3c749c3..0c146b3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -392,6 +392,10 @@ static int stmmac_ethtool_get_link_ksettings(struct 
net_device *dev,
 
mutex_lock(&priv->lock);
stmmac_pcs_ctrl_ane(priv, priv->ioaddr, 1, priv->hw->ps, 0);
+
+   if (priv->plat->has_xpcs)
+   stmmac_xpcs_ctrl_ane(priv, dev, 1, 0);
+
mutex_unlock(&priv->lock);
 
return 0;
@@ -457,6 +461,11 @@ static void stmmac_ethtool_gregs(struct net_device *dev,
pause->autoneg = 1;
if (!adv_lp.pause)
return;
+   } else if (priv->plat->has_xpcs &&
+  !stmmac_xpcs_get_adv_lp(priv, netdev, &adv_lp)) {
+   pause->autoneg = 1;
+   if (!adv_lp.pause)
+   return;
} else {
if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
   netdev->phydev->supported) ||
@@ -488,6 +497,11 @@ static void stmmac_ethtool_gregs(struct net_device *dev,
pause->autoneg = 1;
if (!adv_lp.pause)
return -EOPNOTSUPP;
+   } else if (priv->plat->has_xpcs &&
+  !stmmac_xpcs_get_adv_lp(priv, netdev, &adv_lp)) {
+   pause->autoneg = 1;
+   if (!adv_lp.pause)
+   return -EOPNOTSUPP;
} else {
if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
   phy->supported) ||
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ec031e3..d6e315f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -112,6 +112,7 @@
 MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode");
 
 static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
+static irqreturn_t xpcs_interrupt(int irq, void *dev_id);
 
 #ifdef CONFIG_DEBUG_FS
 static int stmmac_init_fs(struct net_device *dev);
@@ -2538,6 +2539,10 @@ static int stmmac_hw_setup(struct net_device *dev, bool 
init_ptp)
/* Initialize MTL*/
stmmac_mtl_configuration(priv);
 
+   /* Initialize the xPCS PHY */
+   if (priv->plat->has_xpcs)
+   stmmac_xpcs_init(priv, dev, priv->plat->pcs_mode);
+
/* Initialize Safety Features */
stmmac_safety_feat_configuration(priv);
 
@@ -2579,6 +2584,9 @@ static int stmmac_hw_setup(struct net_device *dev, bool 
init_ptp)
if (priv->hw->pcs)
stmmac_pcs_ctrl_ane(priv, priv->hw, 1, priv->hw->ps, 0);
 
+   if (priv->plat->has_xpcs)
+   stmmac_xpcs_ctrl_ane(priv, dev, 1, 0);
+
/* set TX and RX rings length */
stmmac_set_rings_length(priv);
 
@@ -2696,11 +2704,27 @@ static int stmmac_open(struct net_device *dev)
}
}
 
+   /* xPCS IRQ line */
+   if (priv->xpcs_irq > 0) {
+   ret = request_irq(priv->xpcs_irq, xpcs_interrupt, IRQF_SHARED,
+ dev->name, dev);
+   if (unlikely(ret < 0)) {
+   netdev_err(priv->dev,
+   

[PATCH 3/7] net: stmmac: dma channel control register need to be init first

2019-04-24 Thread Weifeng Voon
stmmac_init_chan() needs to be called before stmmac_init_rx_chan() and
stmmac_init_tx_chan(). This is because if PBLx8 is to be used,
"DMA_CH(#i)_Control.PBLx8" needs to be set before programming
"DMA_CH(#i)_TX_Control.TxPBL" and "DMA_CH(#i)_RX_Control.RxPBL".

Reviewed-by: Zhang, Baoli 
Signed-off-by: Weifeng Voon 
Signed-off-by: Ong Boon Leong 
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index a26e36d..ec031e3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2208,6 +2208,10 @@ static int stmmac_init_dma_engine(struct stmmac_priv 
*priv)
if (priv->plat->axi)
stmmac_axi(priv, priv->ioaddr, priv->plat->axi);
 
+   /* DMA CSR Channel configuration */
+   for (chan = 0; chan < dma_csr_ch; chan++)
+   stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
+
/* DMA RX Channel Configuration */
for (chan = 0; chan < rx_channels_count; chan++) {
rx_q = &priv->rx_queue[chan];
@@ -2233,10 +2237,6 @@ static int stmmac_init_dma_engine(struct stmmac_priv 
*priv)
   tx_q->tx_tail_addr, chan);
}
 
-   /* DMA CSR Channel configuration */
-   for (chan = 0; chan < dma_csr_ch; chan++)
-   stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
-
return ret;
 }
 
-- 
1.9.1



[PATCH v3] i2c: designware: Use transfer timeout from ioctl I2C_TIMEOUT

2016-06-16 Thread Weifeng Voon
This allows applications to set the transfer timeout in 10ms increments via
ioctl I2C_TIMEOUT.

Signed-off-by: Weifeng Voon 
---
 changelog v2:
 * No code change, just change to a more suitable title

 changelog v3:
 * Move changelog out of commit log

 drivers/i2c/busses/i2c-designware-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
index 99b54be..c6922b8 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -663,7 +663,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg 
msgs[], int num)
i2c_dw_xfer_init(dev);
 
/* wait for tx to complete */
-   if (!wait_for_completion_timeout(&dev->cmd_complete, HZ)) {
+   if (!wait_for_completion_timeout(&dev->cmd_complete, adap->timeout)) {
dev_err(dev->dev, "controller timed out\n");
/* i2c_dw_init implicitly disables the adapter */
i2c_dw_init(dev);
-- 
1.9.1



[PATCH v2] i2c: designware: Use transfer timeout from ioctl I2C_TIMEOUT

2016-06-15 Thread Weifeng Voon
This allows applications to set the transfer timeout in 10ms increments via
ioctl I2C_TIMEOUT.

changelog v2:
* No code change, just change to a more suitable title

Signed-off-by: Weifeng Voon 
---
 drivers/i2c/busses/i2c-designware-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
index 99b54be..c6922b8 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -663,7 +663,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg 
msgs[], int num)
i2c_dw_xfer_init(dev);
 
/* wait for tx to complete */
-   if (!wait_for_completion_timeout(&dev->cmd_complete, HZ)) {
+   if (!wait_for_completion_timeout(&dev->cmd_complete, adap->timeout)) {
dev_err(dev->dev, "controller timed out\n");
/* i2c_dw_init implicitly disables the adapter */
i2c_dw_init(dev);
-- 
1.9.1



[PATCH] i2c: designware: Enable ioctl I2C_TIMEOUT

2016-06-02 Thread Weifeng Voon
This allows applications to set the transfer timeout in 10ms increments via
ioctl I2C_TIMEOUT.

Signed-off-by: Weifeng Voon 
---
 drivers/i2c/busses/i2c-designware-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
index 99b54be..c6922b8 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -663,7 +663,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg 
msgs[], int num)
i2c_dw_xfer_init(dev);
 
/* wait for tx to complete */
-   if (!wait_for_completion_timeout(&dev->cmd_complete, HZ)) {
+   if (!wait_for_completion_timeout(&dev->cmd_complete, adap->timeout)) {
dev_err(dev->dev, "controller timed out\n");
/* i2c_dw_init implicitly disables the adapter */
i2c_dw_init(dev);
-- 
1.9.1



[PATCH 3/5] i2c: designware: Enable fast mode plus

2016-05-26 Thread Weifeng Voon
This patch enabled fast mode plus. The fast mode plus and fast speed
share the same HCNT and LCNT register. So, the fast mode plus will only
run when the HCNT and LCNT value is provided. Else, it will run at fast
speed as default.

Signed-off-by: Weifeng Voon 
---
 drivers/i2c/busses/i2c-designware-core.c| 7 +--
 drivers/i2c/busses/i2c-designware-platdrv.c | 9 ++---
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
index 99b54be..25c78d2 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -347,8 +347,11 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
 
-   /* Set SCL timing parameters for fast-mode */
-   if (dev->fs_hcnt && dev->fs_lcnt) {
+   /* Set SCL timing parameters for fast-mode or fast-mode plus */
+   if ((dev->clk_freq == 100) && dev->fp_hcnt && dev->fp_lcnt) {
+   hcnt = dev->fp_hcnt;
+   lcnt = dev->fp_lcnt;
+   } else if (dev->fs_hcnt && dev->fs_lcnt) {
hcnt = dev->fs_hcnt;
lcnt = dev->fs_lcnt;
} else {
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c 
b/drivers/i2c/busses/i2c-designware-platdrv.c
index cbe4fb3..ea92e9f 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -196,10 +196,13 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
dw_i2c_acpi_configure(pdev);
 
/*
-* Only standard mode at 100kHz and fast mode at 400kHz are supported.
+* Only standard mode at 100kHz, fast mode at 400kHz,
+* and fast mode plus at 1MHz are supported.
 */
-   if (dev->clk_freq != 10 && dev->clk_freq != 40) {
-   dev_err(&pdev->dev, "Only 100kHz and 400kHz supported");
+   if (dev->clk_freq != 10 && dev->clk_freq != 40
+   && dev->clk_freq != 100) {
+   dev_err(&pdev->dev,
+   "Only 100kHz, 400kHz and 1MHz are supported");
return -EINVAL;
}
 
-- 
1.9.1



[PATCH 1/5] i2c: designware: Move clk_freq into struct dw_i2c_dev

2016-05-26 Thread Weifeng Voon
I2c designware controller operate speed is configured in the register
IC_CON. Previously the operate speed is determined by a local variable
clk_freq. This patch will move the local variable clk_freq into struct
dw_i2c_dev. This change will ease the set and get of the clk_freq.

Signed-off-by: Weifeng Voon 
---
 drivers/i2c/busses/i2c-designware-core.h|  2 ++
 drivers/i2c/busses/i2c-designware-platdrv.c | 12 ++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.h 
b/drivers/i2c/busses/i2c-designware-core.h
index cd409e7..87d406e 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -56,6 +56,7 @@
  * @tx_fifo_depth: depth of the hardware tx fifo
  * @rx_fifo_depth: depth of the hardware rx fifo
  * @rx_outstanding: current master-rx elements in tx fifo
+ * @clk_freq: bus clock frequency
  * @ss_hcnt: standard speed HCNT value
  * @ss_lcnt: standard speed LCNT value
  * @fs_hcnt: fast speed HCNT value
@@ -95,6 +96,7 @@ struct dw_i2c_dev {
unsigned inttx_fifo_depth;
unsigned intrx_fifo_depth;
int rx_outstanding;
+   u32 clk_freq;
u32 sda_hold_time;
u32 sda_falling_time;
u32 scl_falling_time;
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c 
b/drivers/i2c/busses/i2c-designware-platdrv.c
index d656657..1608cf4 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -155,7 +155,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
struct i2c_adapter *adap;
struct resource *mem;
int irq, r;
-   u32 clk_freq, ht = 0;
+   u32 ht = 0;
 
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -175,10 +175,10 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev);
 
/* fast mode by default because of legacy reasons */
-   clk_freq = 40;
+   dev->clk_freq = 40;
 
if (pdata) {
-   clk_freq = pdata->i2c_scl_freq;
+   dev->clk_freq = pdata->i2c_scl_freq;
} else {
device_property_read_u32(&pdev->dev, "i2c-sda-hold-time-ns",
 &ht);
@@ -187,7 +187,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
device_property_read_u32(&pdev->dev, "i2c-scl-falling-time-ns",
 &dev->scl_falling_time);
device_property_read_u32(&pdev->dev, "clock-frequency",
-&clk_freq);
+&dev->clk_freq);
}
 
if (has_acpi_companion(&pdev->dev))
@@ -196,7 +196,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
/*
 * Only standard mode at 100kHz and fast mode at 400kHz are supported.
 */
-   if (clk_freq != 10 && clk_freq != 40) {
+   if (dev->clk_freq != 10 && dev->clk_freq != 40) {
dev_err(&pdev->dev, "Only 100kHz and 400kHz supported");
return -EINVAL;
}
@@ -212,7 +212,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_I2C_BLOCK;
-   if (clk_freq == 10)
+   if (dev->clk_freq == 10)
dev->master_cfg =  DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_STD;
else
-- 
1.9.1



[PATCH 4/5] i2c: designware: set the common config before the if else

2016-05-26 Thread Weifeng Voon
DW_IC_CON_MASTER, DW_IC_CON_SLAVE_DISABLE and DW_IC_CON_RESTART_EN are
common config that need to be set for i2c designware master. So, configure
it first without having to repeat inside the if else.

Signed-off-by: Weifeng Voon 
---
 drivers/i2c/busses/i2c-designware-platdrv.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c 
b/drivers/i2c/busses/i2c-designware-platdrv.c
index ea92e9f..d45481e 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -217,12 +217,14 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_I2C_BLOCK;
+
+   dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
+ DW_IC_CON_RESTART_EN;
+
if (dev->clk_freq == 10)
-   dev->master_cfg =  DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
-   DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_STD;
+   dev->master_cfg |= DW_IC_CON_SPEED_STD;
else
-   dev->master_cfg =  DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
-   DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
+   dev->master_cfg |= DW_IC_CON_SPEED_FAST;
 
dev->clk = devm_clk_get(&pdev->dev, NULL);
if (!i2c_dw_plat_prepare_clk(dev, true)) {
-- 
1.9.1



[PATCH 5/5] i2c: designware: Enable high speed mode

2016-05-26 Thread Weifeng Voon
This patch enabled high speed mode. High speed mode can be turn on by
setting the clk_freq to 340. High speed HCNT and LCNT are needed
as there is no default value provided.

Signed-off-by: Weifeng Voon 
---
 drivers/i2c/busses/i2c-designware-core.c| 26 +-
 drivers/i2c/busses/i2c-designware-core.h|  2 ++
 drivers/i2c/busses/i2c-designware-platdrv.c | 16 +++-
 3 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
index 25c78d2..5299b88 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -42,6 +42,8 @@
 #define DW_IC_SS_SCL_LCNT  0x18
 #define DW_IC_FS_SCL_HCNT  0x1c
 #define DW_IC_FS_SCL_LCNT  0x20
+#define DW_IC_HS_SCL_HCNT  0x24
+#define DW_IC_HS_SCL_LCNT  0x28
 #define DW_IC_INTR_STAT0x2c
 #define DW_IC_INTR_MASK0x30
 #define DW_IC_RAW_INTR_STAT0x34
@@ -95,6 +97,9 @@
 
 #define DW_IC_TAR_10BITADDR_MASTER BIT(12)
 
+#define DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH (BIT(2) | BIT(3))
+#define DW_IC_COMP_PARAM_1_SPEED_MODE_MASK GENMASK(3, 2)
+
 /*
  * status codes
  */
@@ -293,7 +298,7 @@ static unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
 int i2c_dw_init(struct dw_i2c_dev *dev)
 {
u32 hcnt, lcnt;
-   u32 reg;
+   u32 reg, comp_param1;
u32 sda_falling_time, scl_falling_time;
int ret;
 
@@ -320,6 +325,8 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
return -ENODEV;
}
 
+   comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
+
/* Disable the adapter */
__i2c_dw_enable(dev, false);
 
@@ -369,6 +376,23 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
 
+   if ((dev->master_cfg & DW_IC_CON_SPEED_MASK) ==
+   DW_IC_CON_SPEED_HIGH) {
+   if ((comp_param1 & DW_IC_COMP_PARAM_1_SPEED_MODE_MASK)
+   != DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH) {
+   dev_err(dev->dev, "High Speed not supported!\n");
+   dev->master_cfg &= ~DW_IC_CON_SPEED_MASK;
+   dev->master_cfg |= DW_IC_CON_SPEED_FAST;
+   } else if (dev->hs_hcnt && dev->hs_lcnt) {
+   hcnt = dev->hs_hcnt;
+   lcnt = dev->hs_lcnt;
+   dw_writel(dev, hcnt, DW_IC_HS_SCL_HCNT);
+   dw_writel(dev, lcnt, DW_IC_HS_SCL_LCNT);
+   dev_dbg(dev->dev, "HighSpeed-mode HCNT:LCNT = %d:%d\n",
+   hcnt, lcnt);
+   }
+   }
+
/* Configure SDA Hold Time if required */
if (dev->sda_hold_time) {
reg = dw_readl(dev, DW_IC_COMP_VERSION);
diff --git a/drivers/i2c/busses/i2c-designware-core.h 
b/drivers/i2c/busses/i2c-designware-core.h
index 1124240..d545011 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -26,6 +26,8 @@
 #define DW_IC_CON_MASTER   0x1
 #define DW_IC_CON_SPEED_STD0x2
 #define DW_IC_CON_SPEED_FAST   0x4
+#define DW_IC_CON_SPEED_HIGH   0x6
+#define DW_IC_CON_SPEED_MASK   GENMASK(2, 1)
 #define DW_IC_CON_10BITADDR_MASTER 0x10
 #define DW_IC_CON_RESTART_EN   0x20
 #define DW_IC_CON_SLAVE_DISABLE0x40
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c 
b/drivers/i2c/busses/i2c-designware-platdrv.c
index d45481e..cb846cb 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -197,12 +197,12 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
 
/*
 * Only standard mode at 100kHz, fast mode at 400kHz,
-* and fast mode plus at 1MHz are supported.
+* fast mode plus at 1MHz and high speed mode at 3.4MHz are supported.
 */
if (dev->clk_freq != 10 && dev->clk_freq != 40
-   && dev->clk_freq != 100) {
+   && dev->clk_freq != 100 && dev->clk_freq != 340) {
dev_err(&pdev->dev,
-   "Only 100kHz, 400kHz and 1MHz are supported");
+   "Only 100kHz, 400kHz, 1MHz and 3.4MHz supported");
return -EINVAL;
}
 
@@ -221,10 +221,16 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
  DW_IC_CON_RESTART_EN;
 
-   if (dev->clk_freq == 10)
+   switch (dev->clk_freq) {
+   case 10:
dev->master_cfg |= DW_IC

[PATCH 0/5] i2c: designware: Enable fast mode plus and high speed

2016-05-26 Thread Weifeng Voon
Enabled fast mode plus and high speed which supported by APL SoC.

Weifeng Voon (5):
  i2c: designware: Move clk_freq into struct dw_i2c_dev
  i2c: designware: get fast plus and high speed *CNT configuration
  i2c: designware: Enable fast mode plus
  i2c: designware: set the common config before the if else
  i2c: designware: Enable high speed mode

 drivers/i2c/busses/i2c-designware-core.c| 33 +---
 drivers/i2c/busses/i2c-designware-core.h| 12 +
 drivers/i2c/busses/i2c-designware-platdrv.c | 39 +++--
 3 files changed, 68 insertions(+), 16 deletions(-)

-- 
1.9.1



[PATCH 2/5] i2c: designware: get fast plus and high speed *CNT configuration

2016-05-26 Thread Weifeng Voon
I2C designware controller can run at fast mode plus and high speed. This
patch adds the capability to get the HCNT, LCNT configuration via
FPCN (fast plus) and HSCN (high speed) ACPI method.

Signed-off-by: Weifeng Voon 
---
 drivers/i2c/busses/i2c-designware-core.h| 8 
 drivers/i2c/busses/i2c-designware-platdrv.c | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/drivers/i2c/busses/i2c-designware-core.h 
b/drivers/i2c/busses/i2c-designware-core.h
index 87d406e..1124240 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -61,6 +61,10 @@
  * @ss_lcnt: standard speed LCNT value
  * @fs_hcnt: fast speed HCNT value
  * @fs_lcnt: fast speed LCNT value
+ * @fp_hcnt: fast plus HCNT value
+ * @fp_lcnt: fast plus LCNT value
+ * @hs_hcnt: high speed HCNT value
+ * @hs_lcnt: high speed LCNT value
  * @acquire_lock: function to acquire a hardware lock on the bus
  * @release_lock: function to release a hardware lock on the bus
  * @pm_runtime_disabled: true if pm runtime is disabled
@@ -104,6 +108,10 @@ struct dw_i2c_dev {
u16 ss_lcnt;
u16 fs_hcnt;
u16 fs_lcnt;
+   u16 fp_hcnt;
+   u16 fp_lcnt;
+   u16 hs_hcnt;
+   u16 hs_lcnt;
int (*acquire_lock)(struct dw_i2c_dev *dev);
void(*release_lock)(struct dw_i2c_dev *dev);
boolpm_runtime_disabled;
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c 
b/drivers/i2c/busses/i2c-designware-platdrv.c
index 1608cf4..cbe4fb3 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -107,6 +107,8 @@ static int dw_i2c_acpi_configure(struct platform_device 
*pdev)
dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, NULL);
dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
   &dev->sda_hold_time);
+   dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, NULL);
+   dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, NULL);
 
id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
if (id && id->driver_data)
-- 
1.9.1