On 01/17, Bjorn Andersson wrote:
> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
> new file mode 100644
> index 0000000..2e0020e
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-qup.c
> @@ -0,0 +1,894 @@
> +/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/i2c.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +
> +/* QUP Registers */
> +#define QUP_CONFIG           0x000
> +#define QUP_STATE            0x004
> +#define QUP_IO_MODE          0x008
> +#define QUP_SW_RESET         0x00c
> +#define QUP_OPERATIONAL              0x018
> +#define QUP_ERROR_FLAGS              0x01c
> +#define QUP_ERROR_FLAGS_EN   0x020
> +#define QUP_HW_VERSION               0x030
> +#define QUP_MX_OUTPUT_CNT    0x100
> +#define QUP_OUT_FIFO_BASE    0x110
> +#define QUP_MX_WRITE_CNT     0x150
> +#define QUP_MX_INPUT_CNT     0x200
> +#define QUP_MX_READ_CNT              0x208
> +#define QUP_IN_FIFO_BASE     0x218
> +#define QUP_I2C_CLK_CTL              0x400
> +#define QUP_I2C_STATUS               0x404
> +
> +/* QUP States and reset values */
> +#define QUP_RESET_STATE              0
> +#define QUP_RUN_STATE                1
> +#define QUP_PAUSE_STATE              3
> +#define QUP_STATE_MASK               3
> +
> +#define QUP_STATE_VALID              BIT(2)
> +#define QUP_I2C_MAST_GEN     BIT(4)
> +
> +#define QUP_OPERATIONAL_RESET        0x000ff0
> +#define QUP_I2C_STATUS_RESET 0xfffffc
> +
> +/* QUP OPERATIONAL FLAGS */
> +#define QUP_OUT_SVC_FLAG     BIT(8)
> +#define QUP_IN_SVC_FLAG              BIT(9)
> +#define QUP_MX_INPUT_DONE    BIT(11)
> +
> +/* I2C mini core related values */
> +#define I2C_MINI_CORE                (2 << 8)
> +#define I2C_N_VAL            15
> +/* Most significant word offset in FIFO port */
> +#define QUP_MSW_SHIFT                (I2C_N_VAL + 1)
> +#define QUP_CLOCK_AUTO_GATE  BIT(13)
> +
> +/* Packing/Unpacking words in FIFOs, and IO modes */
> +#define QUP_UNPACK_EN                BIT(14)
> +#define QUP_PACK_EN          BIT(15)
> +#define QUP_OUTPUT_BLK_MODE  BIT(10)
> +#define QUP_INPUT_BLK_MODE   BIT(12)
> +
> +#define QUP_REPACK_EN                (QUP_UNPACK_EN | QUP_PACK_EN)
> +
> +#define QUP_OUTPUT_BLOCK_SIZE(x)(((x) & (0x03 << 0)) >> 0)
> +#define QUP_OUTPUT_FIFO_SIZE(x)      (((x) & (0x07 << 2)) >> 2)
> +#define QUP_INPUT_BLOCK_SIZE(x)      (((x) & (0x03 << 5)) >> 5)
> +#define QUP_INPUT_FIFO_SIZE(x)       (((x) & (0x07 << 7)) >> 7)
> +
> +/* QUP tags */
> +#define QUP_OUT_NOP          (0 << 8)
> +#define QUP_OUT_START                (1 << 8)
> +#define QUP_OUT_DATA         (2 << 8)
> +#define QUP_OUT_STOP         (3 << 8)
> +#define QUP_OUT_REC          (4 << 8)
> +#define QUP_IN_DATA          (5 << 8)
> +#define QUP_IN_STOP          (6 << 8)
> +#define QUP_IN_NACK          (7 << 8)
> +
> +/* Status, Error flags */
> +#define I2C_STATUS_WR_BUFFER_FULL    BIT(0)
> +#define I2C_STATUS_BUS_ACTIVE                BIT(8)
> +#define I2C_STATUS_BUS_MASTER                BIT(9)
> +#define I2C_STATUS_ERROR_MASK                0x38000fc
> +#define QUP_I2C_NACK_FLAG            BIT(3)
> +#define QUP_IN_NOT_EMPTY             BIT(5)
> +#define QUP_STATUS_ERROR_FLAGS               0x7c
> +
> +/* Master bus_err clock states */
> +#define I2C_CLK_RESET_BUSIDLE_STATE  0
> +#define I2C_CLK_FORCED_LOW_STATE     5
> +
> +#define QUP_MAX_CLK_STATE_RETRIES    300
> +#define QUP_MAX_QUP_STATE_RETRIES    100
> +#define I2C_STATUS_CLK_STATE         13
> +#define QUP_OUT_FIFO_NOT_EMPTY               0x10
> +#define QUP_READ_LIMIT                       256
> +
> +struct qup_i2c_dev {
> +     struct device           *dev;
> +     void __iomem            *base;
> +     int                     irq;
> +     struct clk              *clk;
> +     struct clk              *pclk;
> +     struct i2c_adapter      adap;
> +
> +     int                     clk_ctl;
> +     int                     one_bit_t;
> +     int                     out_fifo_sz;
> +     int                     in_fifo_sz;
> +     int                     out_blk_sz;
> +     int                     in_blk_sz;
> +     unsigned long           xfer_time;
> +     unsigned long           wait_idle;
> +
> +     struct i2c_msg          *msg;
> +     /* Current posion in user message buffer */

s/posion/position/

> +     int                     pos;
> +     /* Keep number of bytes left to be transmitted */
> +     int                     cnt;
> +     /* I2C protocol errors */
> +     u32                     bus_err;
> +     /* QUP core errors */
> +     u32                     qup_err;
> +     /*
> +      * Maximum bytes that could be send (per iteration). Could be
> +      * equal of fifo size or block size (in block mode)
> +      */
> +     int                     chunk_sz;
> +     struct completion       xfer;
> +};
[...]
> +
> +static int
> +qup_i2c_poll_state(struct qup_i2c_dev *qup, u32 req_state, bool only_valid)
> +{
> +     int retries = 0;
> +     u32 state;
> +
> +     do {
> +             state = readl(qup->base + QUP_STATE);
> +
> +             /*
> +              * If only valid bit needs to be checked, requested state is
> +              * 'don't care'
> +              */
> +             if (state & QUP_STATE_VALID) {
> +                     if (only_valid)
> +                             return 0;
> +                     if ((req_state & QUP_I2C_MAST_GEN)
> +                         && (state & QUP_I2C_MAST_GEN))
> +                             return 0;
> +                     if ((state & QUP_STATE_MASK) == req_state)
> +                             return 0;
> +             }
> +
> +             udelay(1);
> +     } while (retries++ != QUP_MAX_QUP_STATE_RETRIES);
> +
> +     return -ETIMEDOUT;
> +}
> +

This is what I was suggesting. Don't know if it's any clearer,
but it saves us a whopping 3 lines!

---8<----
 drivers/i2c/busses/i2c-qup.c | 43 ++++++++++++++++++++-----------------------
 1 file changed, 20 insertions(+), 23 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 2e0020e829ae..431de13f6281 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -47,7 +47,7 @@
 #define QUP_STATE_MASK         3
 
 #define QUP_STATE_VALID                BIT(2)
-#define QUP_I2C_MAST_GEN       BIT(4)
+#define QUP_I2C_MAST_GEN       (QUP_STATE_VALID | BIT(4))
 
 #define QUP_OPERATIONAL_RESET  0x000ff0
 #define QUP_I2C_STATUS_RESET   0xfffffc
@@ -190,43 +190,40 @@ done:
        return IRQ_HANDLED;
 }
 
-static int
-qup_i2c_poll_state(struct qup_i2c_dev *qup, u32 req_state, bool only_valid)
+static int __qup_i2c_poll_state(struct qup_i2c_dev *qup, u32 mask, u32 value)
 {
        int retries = 0;
        u32 state;
 
        do {
                state = readl(qup->base + QUP_STATE);
-
-               /*
-                * If only valid bit needs to be checked, requested state is
-                * 'don't care'
-                */
-               if (state & QUP_STATE_VALID) {
-                       if (only_valid)
-                               return 0;
-                       if ((req_state & QUP_I2C_MAST_GEN)
-                           && (state & QUP_I2C_MAST_GEN))
-                               return 0;
-                       if ((state & QUP_STATE_MASK) == req_state)
-                               return 0;
-               }
-
+               if ((state & mask) == value)
+                       return 0;
                udelay(1);
        } while (retries++ != QUP_MAX_QUP_STATE_RETRIES);
 
        return -ETIMEDOUT;
 }
 
+static int qup_i2c_poll_state_bit(struct qup_i2c_dev *qup, u32 mask)
+{
+       return __qup_i2c_poll_state(qup, mask, mask);
+}
+
+static int qup_i2c_poll_state(struct qup_i2c_dev *qup, u32 state)
+{
+       return __qup_i2c_poll_state(qup, QUP_STATE_VALID | QUP_STATE_MASK,
+                                        QUP_STATE_VALID | state);
+}
+
 static int qup_i2c_change_state(struct qup_i2c_dev *qup, u32 state)
 {
-       if (qup_i2c_poll_state(qup, 0, true) != 0)
+       if (qup_i2c_poll_state_bit(qup, QUP_STATE_VALID) != 0)
                return -EIO;
 
        writel(state, qup->base + QUP_STATE);
 
-       if (qup_i2c_poll_state(qup, state, false) != 0)
+       if (qup_i2c_poll_state(qup, state) != 0)
                return -EIO;
        return 0;
 }
@@ -616,7 +613,7 @@ qup_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg 
msgs[], int num)
                goto out;
 
        writel(1, qup->base + QUP_SW_RESET);
-       ret = qup_i2c_poll_state(qup, QUP_RESET_STATE, false);
+       ret = qup_i2c_poll_state(qup, QUP_RESET_STATE);
        if (ret) {
                dev_err(qup->dev, "cannot goto reset state\n");
                goto out;
@@ -633,7 +630,7 @@ qup_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg 
msgs[], int num)
                writel(0, qup->base + QUP_I2C_CLK_CTL);
                writel(QUP_I2C_STATUS_RESET, qup->base + QUP_I2C_STATUS);
 
-               if (qup_i2c_poll_state(qup, QUP_I2C_MAST_GEN, false) != 0) {
+               if (qup_i2c_poll_state_bit(qup, QUP_I2C_MAST_GEN) != 0) {
                        ret = -EIO;
                        goto out;
                }
@@ -730,7 +727,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
         * so we reset the core before registering for interrupts.
         */
        writel(1, qup->base + QUP_SW_RESET);
-       ret = qup_i2c_poll_state(qup, 0, true);
+       ret = qup_i2c_poll_state(qup, QUP_STATE_VALID);
        if (ret)
                goto fail;
 

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to