]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
Merge branch 'i2c/for-5.0' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 6 Jan 2019 02:13:35 +0000 (18:13 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 6 Jan 2019 02:13:35 +0000 (18:13 -0800)
Pull i2c updates from Wolfram Sang:
 "I2C has only driver updates for you this time.

  Mostly new IDs/DT compatibles, also SPDX conversions, small cleanups.
  STM32F7 got FastMode+ and PM support, Axxia some reliabilty
  improvements"

* 'i2c/for-5.0' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (26 commits)
  i2c: Add Actions Semiconductor Owl family S700 I2C support
  dt-bindings: i2c: Add S700 support for Actions Semi Soc's
  i2c: ismt: Add support for Intel Cedar Fork
  i2c: tegra: Switch to SPDX identifier
  i2c: tegra: Add missing kerneldoc for some fields
  i2c: tegra: Cleanup kerneldoc comments
  i2c: axxia: support sequence command mode
  dt-bindings: i2c: rcar: Add r8a774c0 support
  dt-bindings: i2c: sh_mobile: Add r8a774c0 support
  i2c: sh_mobile: Add support for r8a774c0 (RZ/G2E)
  i2c: i2c-cros-ec-tunnel: Switch to SPDX identifier.
  i2c: powermac: Use of_node_name_eq for node name comparisons
  i2c-axxia: check for error conditions first
  i2c-axxia: dedicated function to set client addr
  dt-bindings: i2c: Use correct vendor prefix for Atmel
  i2c: tegra: replace spin_lock_irqsave with spin_lock in ISR
  eeprom: at24: add support for 24c2048
  dt-bindings: eeprom: at24: add "atmel,24c2048" compatible string
  i2c: i2c-stm32f7: add PM Runtime support
  i2c: sh_mobile: add support for r8a77990 (R-Car E3)
  ...

22 files changed:
Documentation/devicetree/bindings/eeprom/at24.txt
Documentation/devicetree/bindings/i2c/i2c-at91.txt
Documentation/devicetree/bindings/i2c/i2c-mux-ltc4306.txt
Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt
Documentation/devicetree/bindings/i2c/i2c-owl.txt
Documentation/devicetree/bindings/i2c/i2c-rcar.txt
Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt
Documentation/devicetree/bindings/i2c/i2c-stm32.txt
Documentation/devicetree/bindings/i2c/nxp,pca9541.txt
drivers/i2c/busses/i2c-axxia.c
drivers/i2c/busses/i2c-bcm2835.c
drivers/i2c/busses/i2c-cros-ec-tunnel.c
drivers/i2c/busses/i2c-ibm_iic.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-ismt.c
drivers/i2c/busses/i2c-owl.c
drivers/i2c/busses/i2c-powermac.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/i2c/busses/i2c-stm32f7.c
drivers/i2c/busses/i2c-tegra.c
drivers/misc/eeprom/Kconfig
drivers/misc/eeprom/at24.c

index aededdbc262b241304a0651be8d418c061f89e05..f9a7c984274ce739c392a3af08c0775199d6e32e 100644 (file)
@@ -27,6 +27,7 @@ Required properties:
                 "atmel,24c256",
                 "atmel,24c512",
                 "atmel,24c1024",
+                "atmel,24c2048",
 
                 If <manufacturer> is not "atmel", then a fallback must be used
                 with the same <model> and "atmel" as manufacturer.
index ef973a0343c7b48a95cd18c3cc44b48b0ae08e62..b7cec17c3daf2b91fbb8afcbc303f60482fa8503 100644 (file)
@@ -33,7 +33,7 @@ i2c0: i2c@fff84000 {
        clock-frequency = <400000>;
 
        24c512@50 {
-               compatible = "24c512";
+               compatible = "atmel,24c512";
                reg = <0x50>;
                pagesize = <128>;
        }
index 1e98c6b3a721bfe6b92386678027a38641865ab8..8b1e49cdce3f9b2a3f2df640489314710e51e618 100644 (file)
@@ -43,7 +43,7 @@ Example:
                        reg = <0>;
 
                        eeprom@50 {
-                               compatible = "at,24c02";
+                               compatible = "atmel,24c02";
                                reg = <0x50>;
                        };
                };
@@ -54,7 +54,7 @@ Example:
                        reg = <1>;
 
                        eeprom@50 {
-                               compatible = "at,24c02";
+                               compatible = "atmel,24c02";
                                reg = <0x50>;
                        };
                };
index ccf6c86ed076dd843e7cac6f7459b2e520f73054..30ac6a60f041952719310cac6097870478ce0c3b 100644 (file)
@@ -54,7 +54,7 @@ Example:
                        reg = <2>;
 
                        eeprom@54 {
-                               compatible = "at,24c08";
+                               compatible = "atmel,24c08";
                                reg = <0x54>;
                        };
                };
index b743fe444e9f6096e2f16ca74bdb5386c8e0e1ec..54c05dbdb2e47d31ce3a0de1263519592131d5cc 100644 (file)
@@ -2,7 +2,9 @@ Actions Semiconductor Owl I2C controller
 
 Required properties:
 
-- compatible        : Should be "actions,s900-i2c".
+- compatible        : Should be one of the following:
+                     - "actions,s700-i2c" for S700 SoC
+                     - "actions,s900-i2c" for S900 SoC
 - reg               : Offset and length of the register set for the device.
 - #address-cells    : Should be 1.
 - #size-cells       : Should be 0.
index 30c0485b167b4d9db9a240423d04ab004005ab91..3ee5e8f6ee013987bf95640964da7a11fea060fe 100644 (file)
@@ -7,6 +7,7 @@ Required properties:
        "renesas,i2c-r8a7745" if the device is a part of a R8A7745 SoC.
        "renesas,i2c-r8a77470" if the device is a part of a R8A77470 SoC.
        "renesas,i2c-r8a774a1" if the device is a part of a R8A774A1 SoC.
+       "renesas,i2c-r8a774c0" if the device is a part of a R8A774C0 SoC.
        "renesas,i2c-r8a7778" if the device is a part of a R8A7778 SoC.
        "renesas,i2c-r8a7779" if the device is a part of a R8A7779 SoC.
        "renesas,i2c-r8a7790" if the device is a part of a R8A7790 SoC.
index d81b626436550e48129bb964bda0c141be99e1ee..202602e6e837ffc12660064c57b4417cc4a13931 100644 (file)
@@ -8,6 +8,7 @@ Required properties:
                        - "renesas,iic-r8a7744" (RZ/G1N)
                        - "renesas,iic-r8a7745" (RZ/G1E)
                        - "renesas,iic-r8a774a1" (RZ/G2M)
+                       - "renesas,iic-r8a774c0" (RZ/G2E)
                        - "renesas,iic-r8a7790" (R-Car H2)
                        - "renesas,iic-r8a7791" (R-Car M2-W)
                        - "renesas,iic-r8a7792" (R-Car V2H)
@@ -16,6 +17,7 @@ Required properties:
                        - "renesas,iic-r8a7795" (R-Car H3)
                        - "renesas,iic-r8a7796" (R-Car M3-W)
                        - "renesas,iic-r8a77965" (R-Car M3-N)
+                       - "renesas,iic-r8a77990" (R-Car E3)
                        - "renesas,iic-sh73a0" (SH-Mobile AG5)
                        - "renesas,rcar-gen2-iic" (generic R-Car Gen2 or RZ/G1
                                                        compatible device)
@@ -28,7 +30,13 @@ Required properties:
                        the platform first followed by the generic R-Car
                        version.
 
-                       renesas,rmobile-iic must always follow.
+                       When compatible with "renesas,rmobile-iic" it should
+                       be the last compatibility string listed.
+
+                       The r8a77990 (R-Car E3) and r8a774c0 (RZ/G2E)
+                       controllers are not considered compatible with
+                       "renesas,rcar-gen3-iic" or "renesas,rmobile-iic"
+                       due to the absence of automatic transmission registers.
 
 - reg             : address start and address range size of device
 - interrupts      : interrupt of device
index 3b54899666342b8e5a114bc0842e193871139d5e..69240e189b01e61d44e2d588aab0e8fe3db579fa 100644 (file)
@@ -26,6 +26,11 @@ Optional properties :
 - i2c-scl-falling-time-ns : Only for STM32F7, I2C SCL Falling time for the board
   (default: 10)
   I2C Timings are derived from these 2 values
+- st,syscfg-fmp:  Only for STM32F7, use to set Fast Mode Plus bit within SYSCFG
+  whether Fast Mode Plus speed is selected by slave.
+       1st cell : phandle to syscfg
+       2nd cell : register offset within SYSCFG
+       3rd cell : register bitmask for FMP bit
 
 Example :
 
@@ -53,4 +58,5 @@ Example :
                clocks = <&rcc 1 CLK_I2C1>;
                pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>;
                pinctrl-names = "default";
+               st,syscfg-fmp = <&syscfg 0x4 0x1>;
        };
index 0fbbc6970ec524fcacd68ab29b77473e7183ec54..42bfc09c8918dfcf5800fba7d03bc2360257fd72 100644 (file)
@@ -22,7 +22,7 @@ Example:
                        #size-cells = <0>;
 
                        eeprom@54 {
-                               compatible = "at,24c08";
+                               compatible = "atmel,24c08";
                                reg = <0x54>;
                        };
                };
index 51d34959709bade4c9baed0f14770ec4cb9719ea..bf564391091f3014bc7fb582cf96eeb666453252 100644 (file)
@@ -12,6 +12,7 @@
  */
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
@@ -25,6 +26,7 @@
 #define I2C_XFER_TIMEOUT    (msecs_to_jiffies(250))
 #define I2C_STOP_TIMEOUT    (msecs_to_jiffies(100))
 #define FIFO_SIZE           8
+#define SEQ_LEN             2
 
 #define GLOBAL_CONTROL         0x00
 #define   GLOBAL_MST_EN         BIT(0)
@@ -51,6 +53,7 @@
 #define   CMD_BUSY             (1<<3)
 #define   CMD_MANUAL           (0x00 | CMD_BUSY)
 #define   CMD_AUTO             (0x01 | CMD_BUSY)
+#define   CMD_SEQUENCE         (0x02 | CMD_BUSY)
 #define MST_RX_XFER            0x2c
 #define MST_TX_XFER            0x30
 #define MST_ADDR_1             0x34
@@ -87,7 +90,9 @@
  * axxia_i2c_dev - I2C device context
  * @base: pointer to register struct
  * @msg: pointer to current message
- * @msg_xfrd: number of bytes transferred in msg
+ * @msg_r: pointer to current read message (sequence transfer)
+ * @msg_xfrd: number of bytes transferred in tx_fifo
+ * @msg_xfrd_r: number of bytes transferred in rx_fifo
  * @msg_err: error code for completed message
  * @msg_complete: xfer completion object
  * @dev: device reference
 struct axxia_i2c_dev {
        void __iomem *base;
        struct i2c_msg *msg;
+       struct i2c_msg *msg_r;
        size_t msg_xfrd;
+       size_t msg_xfrd_r;
        int msg_err;
        struct completion msg_complete;
        struct device *dev;
@@ -227,14 +234,14 @@ static int i2c_m_recv_len(const struct i2c_msg *msg)
  */
 static int axxia_i2c_empty_rx_fifo(struct axxia_i2c_dev *idev)
 {
-       struct i2c_msg *msg = idev->msg;
+       struct i2c_msg *msg = idev->msg_r;
        size_t rx_fifo_avail = readl(idev->base + MST_RX_FIFO);
-       int bytes_to_transfer = min(rx_fifo_avail, msg->len - idev->msg_xfrd);
+       int bytes_to_transfer = min(rx_fifo_avail, msg->len - idev->msg_xfrd_r);
 
        while (bytes_to_transfer-- > 0) {
                int c = readl(idev->base + MST_DATA);
 
-               if (idev->msg_xfrd == 0 && i2c_m_recv_len(msg)) {
+               if (idev->msg_xfrd_r == 0 && i2c_m_recv_len(msg)) {
                        /*
                         * Check length byte for SMBus block read
                         */
@@ -247,7 +254,7 @@ static int axxia_i2c_empty_rx_fifo(struct axxia_i2c_dev *idev)
                        msg->len = 1 + c;
                        writel(msg->len, idev->base + MST_RX_XFER);
                }
-               msg->buf[idev->msg_xfrd++] = c;
+               msg->buf[idev->msg_xfrd_r++] = c;
        }
 
        return 0;
@@ -287,7 +294,7 @@ static irqreturn_t axxia_i2c_isr(int irq, void *_dev)
        }
 
        /* RX FIFO needs service? */
-       if (i2c_m_rd(idev->msg) && (status & MST_STATUS_RFL))
+       if (i2c_m_rd(idev->msg_r) && (status & MST_STATUS_RFL))
                axxia_i2c_empty_rx_fifo(idev);
 
        /* TX FIFO needs service? */
@@ -296,22 +303,7 @@ static irqreturn_t axxia_i2c_isr(int irq, void *_dev)
                        i2c_int_disable(idev, MST_STATUS_TFL);
        }
 
-       if (status & MST_STATUS_SCC) {
-               /* Stop completed */
-               i2c_int_disable(idev, ~MST_STATUS_TSS);
-               complete(&idev->msg_complete);
-       } else if (status & MST_STATUS_SNS) {
-               /* Transfer done */
-               i2c_int_disable(idev, ~MST_STATUS_TSS);
-               if (i2c_m_rd(idev->msg) && idev->msg_xfrd < idev->msg->len)
-                       axxia_i2c_empty_rx_fifo(idev);
-               complete(&idev->msg_complete);
-       } else if (status & MST_STATUS_TSS) {
-               /* Transfer timeout */
-               idev->msg_err = -ETIMEDOUT;
-               i2c_int_disable(idev, ~MST_STATUS_TSS);
-               complete(&idev->msg_complete);
-       } else if (unlikely(status & MST_STATUS_ERR)) {
+       if (unlikely(status & MST_STATUS_ERR)) {
                /* Transfer error */
                i2c_int_disable(idev, ~0);
                if (status & MST_STATUS_AL)
@@ -328,6 +320,24 @@ static irqreturn_t axxia_i2c_isr(int irq, void *_dev)
                        readl(idev->base + MST_TX_BYTES_XFRD),
                        readl(idev->base + MST_TX_XFER));
                complete(&idev->msg_complete);
+       } else if (status & MST_STATUS_SCC) {
+               /* Stop completed */
+               i2c_int_disable(idev, ~MST_STATUS_TSS);
+               complete(&idev->msg_complete);
+       } else if (status & MST_STATUS_SNS) {
+               /* Transfer done */
+               i2c_int_disable(idev, ~MST_STATUS_TSS);
+               if (i2c_m_rd(idev->msg_r) && idev->msg_xfrd_r < idev->msg_r->len)
+                       axxia_i2c_empty_rx_fifo(idev);
+               complete(&idev->msg_complete);
+       } else if (status & MST_STATUS_SS) {
+               /* Auto/Sequence transfer done */
+               complete(&idev->msg_complete);
+       } else if (status & MST_STATUS_TSS) {
+               /* Transfer timeout */
+               idev->msg_err = -ETIMEDOUT;
+               i2c_int_disable(idev, ~MST_STATUS_TSS);
+               complete(&idev->msg_complete);
        }
 
 out:
@@ -337,17 +347,9 @@ out:
        return IRQ_HANDLED;
 }
 
-static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
+static void axxia_i2c_set_addr(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
 {
-       u32 int_mask = MST_STATUS_ERR | MST_STATUS_SNS;
-       u32 rx_xfer, tx_xfer;
        u32 addr_1, addr_2;
-       unsigned long time_left;
-       unsigned int wt_value;
-
-       idev->msg = msg;
-       idev->msg_xfrd = 0;
-       reinit_completion(&idev->msg_complete);
 
        if (i2c_m_ten(msg)) {
                /* 10-bit address
@@ -367,6 +369,90 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
                addr_2 = 0;
        }
 
+       writel(addr_1, idev->base + MST_ADDR_1);
+       writel(addr_2, idev->base + MST_ADDR_2);
+}
+
+/* The NAK interrupt will be sent _before_ issuing STOP command
+ * so the controller might still be busy processing it. No
+ * interrupt will be sent at the end so we have to poll for it
+ */
+static int axxia_i2c_handle_seq_nak(struct axxia_i2c_dev *idev)
+{
+       unsigned long timeout = jiffies + I2C_XFER_TIMEOUT;
+
+       do {
+               if ((readl(idev->base + MST_COMMAND) & CMD_BUSY) == 0)
+                       return 0;
+               usleep_range(1, 100);
+       } while (time_before(jiffies, timeout));
+
+       return -ETIMEDOUT;
+}
+
+static int axxia_i2c_xfer_seq(struct axxia_i2c_dev *idev, struct i2c_msg msgs[])
+{
+       u32 int_mask = MST_STATUS_ERR | MST_STATUS_SS | MST_STATUS_RFL;
+       u32 rlen = i2c_m_recv_len(&msgs[1]) ? I2C_SMBUS_BLOCK_MAX : msgs[1].len;
+       unsigned long time_left;
+
+       axxia_i2c_set_addr(idev, &msgs[0]);
+
+       writel(msgs[0].len, idev->base + MST_TX_XFER);
+       writel(rlen, idev->base + MST_RX_XFER);
+
+       idev->msg = &msgs[0];
+       idev->msg_r = &msgs[1];
+       idev->msg_xfrd = 0;
+       idev->msg_xfrd_r = 0;
+       axxia_i2c_fill_tx_fifo(idev);
+
+       writel(CMD_SEQUENCE, idev->base + MST_COMMAND);
+
+       reinit_completion(&idev->msg_complete);
+       i2c_int_enable(idev, int_mask);
+
+       time_left = wait_for_completion_timeout(&idev->msg_complete,
+                                               I2C_XFER_TIMEOUT);
+
+       i2c_int_disable(idev, int_mask);
+
+       axxia_i2c_empty_rx_fifo(idev);
+
+       if (idev->msg_err == -ENXIO) {
+               if (axxia_i2c_handle_seq_nak(idev))
+                       axxia_i2c_init(idev);
+       } else if (readl(idev->base + MST_COMMAND) & CMD_BUSY) {
+               dev_warn(idev->dev, "busy after xfer\n");
+       }
+
+       if (time_left == 0) {
+               idev->msg_err = -ETIMEDOUT;
+               i2c_recover_bus(&idev->adapter);
+               axxia_i2c_init(idev);
+       }
+
+       if (unlikely(idev->msg_err) && idev->msg_err != -ENXIO)
+               axxia_i2c_init(idev);
+
+       return idev->msg_err;
+}
+
+static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
+{
+       u32 int_mask = MST_STATUS_ERR | MST_STATUS_SNS;
+       u32 rx_xfer, tx_xfer;
+       unsigned long time_left;
+       unsigned int wt_value;
+
+       idev->msg = msg;
+       idev->msg_r = msg;
+       idev->msg_xfrd = 0;
+       idev->msg_xfrd_r = 0;
+       reinit_completion(&idev->msg_complete);
+
+       axxia_i2c_set_addr(idev, msg);
+
        if (i2c_m_rd(msg)) {
                /* I2C read transfer */
                rx_xfer = i2c_m_recv_len(msg) ? I2C_SMBUS_BLOCK_MAX : msg->len;
@@ -379,8 +465,6 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
 
        writel(rx_xfer, idev->base + MST_RX_XFER);
        writel(tx_xfer, idev->base + MST_TX_XFER);
-       writel(addr_1, idev->base + MST_ADDR_1);
-       writel(addr_2, idev->base + MST_ADDR_2);
 
        if (i2c_m_rd(msg))
                int_mask |= MST_STATUS_RFL;
@@ -445,6 +529,18 @@ static int axxia_i2c_stop(struct axxia_i2c_dev *idev)
        return 0;
 }
 
+/* This function checks if the msgs[] array contains messages compatible with
+ * Sequence mode of operation. This mode assumes there will be exactly one
+ * write of non-zero length followed by exactly one read of non-zero length,
+ * both targeted at the same client device.
+ */
+static bool axxia_i2c_sequence_ok(struct i2c_msg msgs[], int num)
+{
+       return num == SEQ_LEN && !i2c_m_rd(&msgs[0]) && i2c_m_rd(&msgs[1]) &&
+              msgs[0].len > 0 && msgs[0].len <= FIFO_SIZE &&
+              msgs[1].len > 0 && msgs[0].addr == msgs[1].addr;
+}
+
 static int
 axxia_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 {
@@ -453,6 +549,12 @@ axxia_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        int ret = 0;
 
        idev->msg_err = 0;
+
+       if (axxia_i2c_sequence_ok(msgs, num)) {
+               ret = axxia_i2c_xfer_seq(idev, msgs);
+               return ret ? : SEQ_LEN;
+       }
+
        i2c_int_enable(idev, MST_STATUS_TSS);
 
        for (i = 0; ret == 0 && i < num; ++i)
index 44deae78913e5fa259927d1b5e8b6bf9aee60138..ec6e69aa3a8e5ac455c0ede516d96b75fc7a87a8 100644 (file)
@@ -1,14 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * BCM2835 master mode driver
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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>
index eb76b76f4754edfed8ba4641d854de97c593969e..82bcd9a78759198befef1d588235def83cdf7f9f 100644 (file)
@@ -1,13 +1,7 @@
-/*
- *  Copyright (C) 2013 Google, Inc
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- * Expose an I2C passthrough to the ChromeOS EC.
- */
+// SPDX-License-Identifier: GPL-2.0+
+// Expose an I2C passthrough to the ChromeOS EC.
+//
+// Copyright (C) 2013 Google, Inc.
 
 #include <linux/module.h>
 #include <linux/i2c.h>
index 6f6e1dfe7ccee3982d4e824215b53ef2e48772ff..d78023d42a350b6195b653aebd9d97fe85aed203 100644 (file)
@@ -437,7 +437,7 @@ static int iic_wait_for_tc(struct ibm_iic_private* dev){
                                break;
                        }
 
-                       if (unlikely(signal_pending(current))){
+                       if (signal_pending(current)){
                                DBG("%d: poll interrupted\n", dev->idx);
                                ret = -ERESTARTSYS;
                                break;
index c406700789e1f9c5a3af5c3fa62f045180702bb1..fa9ad53845d9a36bef9927bd9f53c783b397bfd9 100644 (file)
@@ -1090,7 +1090,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
        /* Get I2C clock */
        i2c_imx->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(i2c_imx->clk)) {
-               dev_err(&pdev->dev, "can't get I2C clock\n");
+               if (PTR_ERR(i2c_imx->clk) != -EPROBE_DEFER)
+                       dev_err(&pdev->dev, "can't get I2C clock\n");
                return PTR_ERR(i2c_imx->clk);
        }
 
index 0d1c3ec8cb40734f96529dffadffc28d686c22ac..02d23edb2fb10abae55075bd121df69c6893eb66 100644 (file)
@@ -75,6 +75,7 @@
 /* PCI DIDs for the Intel SMBus Message Transport (SMT) Devices */
 #define PCI_DEVICE_ID_INTEL_S1200_SMT0 0x0c59
 #define PCI_DEVICE_ID_INTEL_S1200_SMT1 0x0c5a
+#define PCI_DEVICE_ID_INTEL_CDF_SMT    0x18ac
 #define PCI_DEVICE_ID_INTEL_DNV_SMT    0x19ac
 #define PCI_DEVICE_ID_INTEL_AVOTON_SMT 0x1f15
 
@@ -181,6 +182,7 @@ struct ismt_priv {
 static const struct pci_device_id ismt_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT0) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT1) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CDF_SMT) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DNV_SMT) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMT) },
        { 0, }
index 96b4572e6d9cc4465decf7993616595caa492da3..b6b5a495118b6dc8e13ff7582ab815a684778152 100644 (file)
@@ -475,6 +475,7 @@ disable_clk:
 }
 
 static const struct of_device_id owl_i2c_of_match[] = {
+       { .compatible = "actions,s700-i2c" },
        { .compatible = "actions,s900-i2c" },
        { /* sentinel */ }
 };
index f6f4ed8afc9386ac34fe7be9ee40e575ac6e00ee..281113c28314efb32d889c21e3344e8f408e87a0 100644 (file)
@@ -229,9 +229,9 @@ static u32 i2c_powermac_get_addr(struct i2c_adapter *adap,
                return (be32_to_cpup(prop) & 0xff) >> 1;
 
        /* Now handle some devices with missing "reg" properties */
-       if (!strcmp(node->name, "cereal"))
+       if (of_node_name_eq(node, "cereal"))
                return 0x60;
-       else if (!strcmp(node->name, "deq"))
+       else if (of_node_name_eq(node, "deq"))
                return 0x34;
 
        dev_warn(&adap->dev, "No i2c address for %pOF\n", node);
@@ -304,7 +304,7 @@ static bool i2c_powermac_get_type(struct i2c_adapter *adap,
        }
 
        /* Now look for known workarounds */
-       if (!strcmp(node->name, "deq")) {
+       if (of_node_name_eq(node, "deq")) {
                /* Apple uses address 0x34 for TAS3001 and 0x35 for TAS3004 */
                if (addr == 0x34) {
                        snprintf(type, type_size, "MAC,tas3001");
@@ -331,7 +331,7 @@ static void i2c_powermac_register_devices(struct i2c_adapter *adap,
         * case we skip this function completely as the device-tree will
         * not contain anything useful.
         */
-       if (!strcmp(adap->dev.of_node->name, "via-pmu"))
+       if (of_node_name_eq(adap->dev.of_node, "via-pmu"))
                return;
 
        for_each_child_of_node(adap->dev.of_node, node) {
index a7a7a9c3bc7c499b59f4672399adf7ec3691f667..a64f2ff3cb49ce47b41dda39d00bf92e532cab75 100644 (file)
@@ -800,6 +800,7 @@ static const struct sh_mobile_dt_config r8a7740_dt_config = {
 static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
        { .compatible = "renesas,iic-r8a73a4", .data = &fast_clock_dt_config },
        { .compatible = "renesas,iic-r8a7740", .data = &r8a7740_dt_config },
+       { .compatible = "renesas,iic-r8a774c0", .data = &fast_clock_dt_config },
        { .compatible = "renesas,iic-r8a7790", .data = &v2_freq_calc_dt_config },
        { .compatible = "renesas,iic-r8a7791", .data = &fast_clock_dt_config },
        { .compatible = "renesas,iic-r8a7792", .data = &fast_clock_dt_config },
@@ -808,6 +809,7 @@ static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
        { .compatible = "renesas,rcar-gen2-iic", .data = &fast_clock_dt_config },
        { .compatible = "renesas,iic-r8a7795", .data = &fast_clock_dt_config },
        { .compatible = "renesas,rcar-gen3-iic", .data = &fast_clock_dt_config },
+       { .compatible = "renesas,iic-r8a77990", .data = &fast_clock_dt_config },
        { .compatible = "renesas,iic-sh73a0", .data = &fast_clock_dt_config },
        { .compatible = "renesas,rmobile-iic", .data = &default_dt_config },
        {},
index 62d023e737d9c2f60a26ea4174e78154dc10e877..13e1213561d4b40335b44ff28d832d7840a4b4d2 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
 
 #define STM32F7_SCLH_MAX                       BIT(8)
 #define STM32F7_SCLL_MAX                       BIT(8)
 
+#define STM32F7_AUTOSUSPEND_DELAY              (HZ / 100)
+
 /**
  * struct stm32f7_i2c_spec - private i2c specification timing
  * @rate: I2C bus speed (Hz)
@@ -276,6 +282,7 @@ struct stm32f7_i2c_msg {
  * slave)
  * @dma: dma data
  * @use_dma: boolean to know if dma is used in the current transfer
+ * @regmap: holds SYSCFG phandle for Fast Mode Plus bits
  */
 struct stm32f7_i2c_dev {
        struct i2c_adapter adap;
@@ -296,6 +303,7 @@ struct stm32f7_i2c_dev {
        bool master_mode;
        struct stm32_i2c_dma *dma;
        bool use_dma;
+       struct regmap *regmap;
 };
 
 /**
@@ -1545,15 +1553,13 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
        i2c_dev->msg_id = 0;
        f7_msg->smbus = false;
 
-       ret = clk_enable(i2c_dev->clk);
-       if (ret) {
-               dev_err(i2c_dev->dev, "Failed to enable clock\n");
+       ret = pm_runtime_get_sync(i2c_dev->dev);
+       if (ret < 0)
                return ret;
-       }
 
        ret = stm32f7_i2c_wait_free_bus(i2c_dev);
        if (ret)
-               goto clk_free;
+               goto pm_free;
 
        stm32f7_i2c_xfer_msg(i2c_dev, msgs);
 
@@ -1569,8 +1575,9 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
                ret = -ETIMEDOUT;
        }
 
-clk_free:
-       clk_disable(i2c_dev->clk);
+pm_free:
+       pm_runtime_mark_last_busy(i2c_dev->dev);
+       pm_runtime_put_autosuspend(i2c_dev->dev);
 
        return (ret < 0) ? ret : num;
 }
@@ -1592,39 +1599,37 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
        f7_msg->read_write = read_write;
        f7_msg->smbus = true;
 
-       ret = clk_enable(i2c_dev->clk);
-       if (ret) {
-               dev_err(i2c_dev->dev, "Failed to enable clock\n");
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0)
                return ret;
-       }
 
        ret = stm32f7_i2c_wait_free_bus(i2c_dev);
        if (ret)
-               goto clk_free;
+               goto pm_free;
 
        ret = stm32f7_i2c_smbus_xfer_msg(i2c_dev, flags, command, data);
        if (ret)
-               goto clk_free;
+               goto pm_free;
 
        timeout = wait_for_completion_timeout(&i2c_dev->complete,
                                              i2c_dev->adap.timeout);
        ret = f7_msg->result;
        if (ret)
-               goto clk_free;
+               goto pm_free;
 
        if (!timeout) {
                dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr);
                if (i2c_dev->use_dma)
                        dmaengine_terminate_all(dma->chan_using);
                ret = -ETIMEDOUT;
-               goto clk_free;
+               goto pm_free;
        }
 
        /* Check PEC */
        if ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && read_write) {
                ret = stm32f7_i2c_smbus_check_pec(i2c_dev);
                if (ret)
-                       goto clk_free;
+                       goto pm_free;
        }
 
        if (read_write && size != I2C_SMBUS_QUICK) {
@@ -1649,8 +1654,9 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
                }
        }
 
-clk_free:
-       clk_disable(i2c_dev->clk);
+pm_free:
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
        return ret;
 }
 
@@ -1676,13 +1682,9 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
        if (ret)
                return ret;
 
-       if (!(stm32f7_i2c_is_slave_registered(i2c_dev))) {
-               ret = clk_enable(i2c_dev->clk);
-               if (ret) {
-                       dev_err(dev, "Failed to enable clock\n");
-                       return ret;
-               }
-       }
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0)
+               return ret;
 
        if (id == 0) {
                /* Configure Own Address 1 */
@@ -1703,7 +1705,7 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
                oar2 &= ~STM32F7_I2C_OAR2_MASK;
                if (slave->flags & I2C_CLIENT_TEN) {
                        ret = -EOPNOTSUPP;
-                       goto exit;
+                       goto pm_free;
                }
 
                oar2 |= STM32F7_I2C_OAR2_OA2_7(slave->addr);
@@ -1712,7 +1714,7 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
                writel_relaxed(oar2, i2c_dev->base + STM32F7_I2C_OAR2);
        } else {
                ret = -ENODEV;
-               goto exit;
+               goto pm_free;
        }
 
        /* Enable ACK */
@@ -1723,11 +1725,10 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
                STM32F7_I2C_CR1_PE;
        stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
 
-       return 0;
-
-exit:
-       if (!(stm32f7_i2c_is_slave_registered(i2c_dev)))
-               clk_disable(i2c_dev->clk);
+       ret = 0;
+pm_free:
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
 
        return ret;
 }
@@ -1745,6 +1746,10 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
 
        WARN_ON(!i2c_dev->slave[id]);
 
+       ret = pm_runtime_get_sync(i2c_dev->dev);
+       if (ret < 0)
+               return ret;
+
        if (id == 0) {
                mask = STM32F7_I2C_OAR1_OA1EN;
                stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR1, mask);
@@ -1755,14 +1760,39 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
 
        i2c_dev->slave[id] = NULL;
 
-       if (!(stm32f7_i2c_is_slave_registered(i2c_dev))) {
+       if (!(stm32f7_i2c_is_slave_registered(i2c_dev)))
                stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_ALL_IRQ_MASK);
-               clk_disable(i2c_dev->clk);
-       }
+
+       pm_runtime_mark_last_busy(i2c_dev->dev);
+       pm_runtime_put_autosuspend(i2c_dev->dev);
 
        return 0;
 }
 
+static int stm32f7_i2c_setup_fm_plus_bits(struct platform_device *pdev,
+                                         struct stm32f7_i2c_dev *i2c_dev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       int ret;
+       u32 reg, mask;
+
+       i2c_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg-fmp");
+       if (IS_ERR(i2c_dev->regmap)) {
+               /* Optional */
+               return 0;
+       }
+
+       ret = of_property_read_u32_index(np, "st,syscfg-fmp", 1, &reg);
+       if (ret)
+               return ret;
+
+       ret = of_property_read_u32_index(np, "st,syscfg-fmp", 2, &mask);
+       if (ret)
+               return ret;
+
+       return regmap_update_bits(i2c_dev->regmap, reg, mask, mask);
+}
+
 static u32 stm32f7_i2c_func(struct i2c_adapter *adap)
 {
        return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SLAVE |
@@ -1819,6 +1849,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "Error: Missing controller clock\n");
                return PTR_ERR(i2c_dev->clk);
        }
+
        ret = clk_prepare_enable(i2c_dev->clk);
        if (ret) {
                dev_err(&pdev->dev, "Failed to prepare_enable clock\n");
@@ -1828,12 +1859,16 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
        i2c_dev->speed = STM32_I2C_SPEED_STANDARD;
        ret = device_property_read_u32(&pdev->dev, "clock-frequency",
                                       &clk_rate);
-       if (!ret && clk_rate >= 1000000)
+       if (!ret && clk_rate >= 1000000) {
                i2c_dev->speed = STM32_I2C_SPEED_FAST_PLUS;
-       else if (!ret && clk_rate >= 400000)
+               ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev);
+               if (ret)
+                       goto clk_free;
+       } else if (!ret && clk_rate >= 400000) {
                i2c_dev->speed = STM32_I2C_SPEED_FAST;
-       else if (!ret && clk_rate >= 100000)
+       } else if (!ret && clk_rate >= 100000) {
                i2c_dev->speed = STM32_I2C_SPEED_STANDARD;
+       }
 
        rst = devm_reset_control_get(&pdev->dev, NULL);
        if (IS_ERR(rst)) {
@@ -1888,8 +1923,6 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
        if (ret)
                goto clk_free;
 
-       stm32f7_i2c_hw_config(i2c_dev);
-
        adap = &i2c_dev->adap;
        i2c_set_adapdata(adap, i2c_dev);
        snprintf(adap->name, sizeof(adap->name), "STM32F7 I2C(%pa)",
@@ -1908,18 +1941,35 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
                                             STM32F7_I2C_TXDR,
                                             STM32F7_I2C_RXDR);
 
-       ret = i2c_add_adapter(adap);
-       if (ret)
-               goto clk_free;
-
        platform_set_drvdata(pdev, i2c_dev);
 
-       clk_disable(i2c_dev->clk);
+       pm_runtime_set_autosuspend_delay(i2c_dev->dev,
+                                        STM32F7_AUTOSUSPEND_DELAY);
+       pm_runtime_use_autosuspend(i2c_dev->dev);
+       pm_runtime_set_active(i2c_dev->dev);
+       pm_runtime_enable(i2c_dev->dev);
+
+       pm_runtime_get_noresume(&pdev->dev);
+
+       stm32f7_i2c_hw_config(i2c_dev);
+
+       ret = i2c_add_adapter(adap);
+       if (ret)
+               goto pm_disable;
 
        dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr);
 
+       pm_runtime_mark_last_busy(i2c_dev->dev);
+       pm_runtime_put_autosuspend(i2c_dev->dev);
+
        return 0;
 
+pm_disable:
+       pm_runtime_put_noidle(i2c_dev->dev);
+       pm_runtime_disable(i2c_dev->dev);
+       pm_runtime_set_suspended(i2c_dev->dev);
+       pm_runtime_dont_use_autosuspend(i2c_dev->dev);
+
 clk_free:
        clk_disable_unprepare(i2c_dev->clk);
 
@@ -1936,11 +1986,50 @@ static int stm32f7_i2c_remove(struct platform_device *pdev)
        }
 
        i2c_del_adapter(&i2c_dev->adap);
+       pm_runtime_get_sync(i2c_dev->dev);
 
-       clk_unprepare(i2c_dev->clk);
+       clk_disable_unprepare(i2c_dev->clk);
+
+       pm_runtime_put_noidle(i2c_dev->dev);
+       pm_runtime_disable(i2c_dev->dev);
+       pm_runtime_set_suspended(i2c_dev->dev);
+       pm_runtime_dont_use_autosuspend(i2c_dev->dev);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int stm32f7_i2c_runtime_suspend(struct device *dev)
+{
+       struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
+
+       if (!stm32f7_i2c_is_slave_registered(i2c_dev))
+               clk_disable_unprepare(i2c_dev->clk);
+
+       return 0;
+}
+
+static int stm32f7_i2c_runtime_resume(struct device *dev)
+{
+       struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
+       int ret;
+
+       if (!stm32f7_i2c_is_slave_registered(i2c_dev)) {
+               ret = clk_prepare_enable(i2c_dev->clk);
+               if (ret) {
+                       dev_err(dev, "failed to prepare_enable clock\n");
+                       return ret;
+               }
+       }
 
        return 0;
 }
+#endif
+
+static const struct dev_pm_ops stm32f7_i2c_pm_ops = {
+       SET_RUNTIME_PM_OPS(stm32f7_i2c_runtime_suspend,
+                          stm32f7_i2c_runtime_resume, NULL)
+};
 
 static const struct of_device_id stm32f7_i2c_match[] = {
        { .compatible = "st,stm32f7-i2c", .data = &stm32f7_setup},
@@ -1952,6 +2041,7 @@ static struct platform_driver stm32f7_i2c_driver = {
        .driver = {
                .name = "stm32f7-i2c",
                .of_match_table = stm32f7_i2c_match,
+               .pm = &stm32f7_i2c_pm_ops,
        },
        .probe = stm32f7_i2c_probe,
        .remove = stm32f7_i2c_remove,
index 437294ea2f0ad9381035c19f00ffae82ada203c8..e417ebf7628c6aab5ed58f6395598be5e495a3f1 100644 (file)
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * drivers/i2c/busses/i2c-tegra.c
  *
  * Copyright (C) 2010 Google, Inc.
  * Author: Colin Cross <ccross@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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/kernel.h>
@@ -145,8 +136,8 @@ enum msg_end_type {
  * @has_continue_xfer_support: Continue transfer supports.
  * @has_per_pkt_xfer_complete_irq: Has enable/disable capability for transfer
  *             complete interrupt per packet basis.
- * @has_single_clk_source: The i2c controller has single clock source. Tegra30
- *             and earlier Socs has two clock sources i.e. div-clk and
+ * @has_single_clk_source: The I2C controller has single clock source. Tegra30
+ *             and earlier SoCs have two clock sources i.e. div-clk and
  *             fast-clk.
  * @has_config_load_reg: Has the config load register to load the new
  *             configuration.
@@ -154,8 +145,17 @@ enum msg_end_type {
  * @clk_divisor_std_fast_mode: Clock divisor in standard/fast mode. It is
  *             applicable if there is no fast clock source i.e. single clock
  *             source.
+ * @clk_divisor_fast_plus_mode: Clock divisor in fast mode plus. It is
+ *             applicable if there is no fast clock source (i.e. single
+ *             clock source).
+ * @has_multi_master_mode: The I2C controller supports running in single-master
+ *             or multi-master mode.
+ * @has_slcg_override_reg: The I2C controller supports a register that
+ *             overrides the second level clock gating.
+ * @has_mst_fifo: The I2C controller contains the new MST FIFO interface that
+ *             provides additional features and allows for longer messages to
+ *             be transferred in one go.
  */
-
 struct tegra_i2c_hw_feature {
        bool has_continue_xfer_support;
        bool has_per_pkt_xfer_complete_irq;
@@ -170,22 +170,27 @@ struct tegra_i2c_hw_feature {
 };
 
 /**
- * struct tegra_i2c_dev        - per device i2c context
+ * struct tegra_i2c_dev - per device I2C context
  * @dev: device reference for power management
- * @hw: Tegra i2c hw feature.
- * @adapter: core i2c layer adapter information
- * @div_clk: clock reference for div clock of i2c controller.
- * @fast_clk: clock reference for fast clock of i2c controller.
+ * @hw: Tegra I2C HW feature
+ * @adapter: core I2C layer adapter information
+ * @div_clk: clock reference for div clock of I2C controller
+ * @fast_clk: clock reference for fast clock of I2C controller
+ * @rst: reset control for the I2C controller
  * @base: ioremapped registers cookie
- * @cont_id: i2c controller id, used for for packet header
- * @irq: irq number of transfer complete interrupt
- * @is_dvc: identifies the DVC i2c controller, has a different register layout
+ * @cont_id: I2C controller ID, used for packet header
+ * @irq: IRQ number of transfer complete interrupt
+ * @irq_disabled: used to track whether or not the interrupt is enabled
+ * @is_dvc: identifies the DVC I2C controller, has a different register layout
  * @msg_complete: transfer completion notifier
  * @msg_err: error code for completed message
  * @msg_buf: pointer to current message data
  * @msg_buf_remaining: size of unsent data in the message buffer
  * @msg_read: identifies read transfers
- * @bus_clk_rate: current i2c bus clock rate
+ * @bus_clk_rate: current I2C bus clock rate
+ * @clk_divisor_non_hs_mode: clock divider for non-high-speed modes
+ * @is_multimaster_mode: track if I2C controller is in multi-master mode
+ * @xfer_lock: lock to serialize transfer submission and processing
  */
 struct tegra_i2c_dev {
        struct device *dev;
@@ -608,11 +613,10 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
        u32 status;
        const u32 status_err = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
        struct tegra_i2c_dev *i2c_dev = dev_id;
-       unsigned long flags;
 
        status = i2c_readl(i2c_dev, I2C_INT_STATUS);
 
-       spin_lock_irqsave(&i2c_dev->xfer_lock, flags);
+       spin_lock(&i2c_dev->xfer_lock);
        if (status == 0) {
                dev_warn(i2c_dev->dev, "irq status 0 %08x %08x %08x\n",
                         i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS),
@@ -670,7 +674,7 @@ err:
 
        complete(&i2c_dev->msg_complete);
 done:
-       spin_unlock_irqrestore(&i2c_dev->xfer_lock, flags);
+       spin_unlock(&i2c_dev->xfer_lock);
        return IRQ_HANDLED;
 }
 
index fe7a1d27a017b52574d91d22f270ab9b4ed34743..a846faefa210385a9e1fb9674e97199b73cf33a1 100644 (file)
@@ -13,7 +13,7 @@ config EEPROM_AT24
          ones like at24c64, 24lc02 or fm24c04:
 
             24c00, 24c01, 24c02, spd (readonly 24c02), 24c04, 24c08,
-            24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024
+            24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024, 24c2048
 
          Unless you like data loss puzzles, always be sure that any chip
          you configure as a 24c32 (32 kbit) or larger is NOT really a
index 636ed7149793b5c4eeac354a4415cb945a570c4a..ddfcf4ade7bf33b46fbc0f5256d32a10240c74c9 100644 (file)
@@ -156,6 +156,7 @@ AT24_CHIP_DATA(at24_data_24c128, 131072 / 8, AT24_FLAG_ADDR16);
 AT24_CHIP_DATA(at24_data_24c256, 262144 / 8, AT24_FLAG_ADDR16);
 AT24_CHIP_DATA(at24_data_24c512, 524288 / 8, AT24_FLAG_ADDR16);
 AT24_CHIP_DATA(at24_data_24c1024, 1048576 / 8, AT24_FLAG_ADDR16);
+AT24_CHIP_DATA(at24_data_24c2048, 2097152 / 8, AT24_FLAG_ADDR16);
 /* identical to 24c08 ? */
 AT24_CHIP_DATA(at24_data_INT3499, 8192 / 8, 0);
 
@@ -182,6 +183,7 @@ static const struct i2c_device_id at24_ids[] = {
        { "24c256",     (kernel_ulong_t)&at24_data_24c256 },
        { "24c512",     (kernel_ulong_t)&at24_data_24c512 },
        { "24c1024",    (kernel_ulong_t)&at24_data_24c1024 },
+       { "24c2048",    (kernel_ulong_t)&at24_data_24c2048 },
        { "at24",       0 },
        { /* END OF LIST */ }
 };
@@ -210,6 +212,7 @@ static const struct of_device_id at24_of_match[] = {
        { .compatible = "atmel,24c256",         .data = &at24_data_24c256 },
        { .compatible = "atmel,24c512",         .data = &at24_data_24c512 },
        { .compatible = "atmel,24c1024",        .data = &at24_data_24c1024 },
+       { .compatible = "atmel,24c2048",        .data = &at24_data_24c2048 },
        { /* END OF LIST */ },
 };
 MODULE_DEVICE_TABLE(of, at24_of_match);