From patchwork Tue Apr 3 19:11:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 132781 Delivered-To: patch@linaro.org Received: by 10.46.84.29 with SMTP id i29csp4175453ljb; Tue, 3 Apr 2018 12:12:03 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+NSKq90FPVcj2qvPa7gflf3iWUftDfV3VoECZpznKhJU7D362BTIkJLIEw7yNO26oY1vKS X-Received: by 10.98.73.214 with SMTP id r83mr11609074pfi.76.1522782723592; Tue, 03 Apr 2018 12:12:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1522782723; cv=none; d=google.com; s=arc-20160816; b=UqhZt0o2dHWEdr5olObGY4zw5oOJayprp78G6X6xZrQWDtdHD+9jyw/nov5cEZxF6R ZiHeYuouWdNIkm6KKtMq0q9ZdY8dn4AfUCrbDb+IcSbv4DdIxr53vfF+cIxNrVcRApc2 EGtj+GfMAkNHzw3mGGoCPgUfJkoj9m2x+V3d2160Dl0E8UQAD4KTXZP9fN0YNbz4wsNN XmcmjdHFmNd1wCWv/IAfCsZJkr3s66Vfx/qGVT94JFXsdsGm1y0lsgRhwD/+d3cnEWEu xI938rplOIWHfbeCDFLHCvOgCFO5732vsA8oEggMQOcy7b50Kkv65qzuh11ozVOlSJVS Yj9A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=5H7RRsVaATT8cCxp+bxpCPwKnlHRMmcG30hhwJ0kUVc=; b=bF40ovrfEVrfD+lfD5zs+t5/eX+/vlsfkoEw4gSCX0BlTkdlQJ54jz1XkawXTyMc9c iiKw9x6wOZcMBvXD+6YlU7OQ3s7BGYbkx1d80fj/gq+xzAHkT5Lv8AUmRZVfENYOyd0W VraHuWmuiqOV8Zwyl6LbEbecu0XxaNuTaaed/Bz9Cu8JtXXMsrgLJcg2PPVbHr87/gu7 Y8vQpv9Kvwb+VBA7zY9gZTlZd1D22htrVGpwUCU7NGcrxYkbXQqMziLBYDqzyd7xHGBJ cfK9ZMS/69kR1OL/OqDW39x4tlsHDutAlUKjT/e89ozCXYuEszlgJQLGUih6hE3s/Vmy gdjQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=UmOB9+5t; spf=pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-i2c-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s78si2646947pfa.374.2018.04.03.12.12.03; Tue, 03 Apr 2018 12:12:03 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=UmOB9+5t; spf=pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-i2c-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752929AbeDCTMC (ORCPT + 3 others); Tue, 3 Apr 2018 15:12:02 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:39728 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752914AbeDCTMB (ORCPT ); Tue, 3 Apr 2018 15:12:01 -0400 Received: by mail-wm0-f66.google.com with SMTP id f125so37197684wme.4 for ; Tue, 03 Apr 2018 12:12:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=5H7RRsVaATT8cCxp+bxpCPwKnlHRMmcG30hhwJ0kUVc=; b=UmOB9+5thRrLL1WyCZ+aisgh5cdJfhEGxl9HPrAJhHM0LXWPQTtiN5QrLGumOnk8he CjNyPJ+MeehkVkZELxVC9QKCnxVrVZ+W/750/b1ZRiWudlP4BDcX1OVo6U3Cj0uE07Lr 19JvjY/h+M/kt1ixyS/DUE7fUMk9TUp7mqYJE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=5H7RRsVaATT8cCxp+bxpCPwKnlHRMmcG30hhwJ0kUVc=; b=RMyv3YM5ObLSrQQAG7Wjvw365sKMBrbpNjx6dEcUgWS+Zhe78bm6InJyjPKHK0AR3K dUzIubByRgfgvYEpYaadvbaQbrMp3+Gc1DcO7/SNWBoP3haaWHjG5l3OOickS0ItBat5 kGhpInCcRE9Feljdee6aGZnJSGMa7G0ZLee5a/0BgujuLD2A8MLBHvmhqe0GXBKDBk0S TKpTi99goUygV4OhjiTclOBacL46lpDbRQNx/OxkHsB7mLGZ13Yqqu2QCSKWviVlutrW 0NaoYhRKbQTlPxmIhFjObBVaokAjTeoZk7ODsop9Qyv+CMrbAJn3otp+moAjEDKHDWdJ /koA== X-Gm-Message-State: AElRT7Gvpip+Gr11osPTTCM+V5CtHcVwMN60B0hsKJJol1LZFy1TfIf0 H7CByebiAdTlGig738CbiHQycg== X-Received: by 10.28.141.138 with SMTP id p132mr5528768wmd.51.1522782720473; Tue, 03 Apr 2018 12:12:00 -0700 (PDT) Received: from localhost.localdomain ([2a01:e35:3995:5470:200:1aff:fe1b:b328]) by smtp.gmail.com with ESMTPSA id y100sm25120682wmh.2.2018.04.03.12.11.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 03 Apr 2018 12:11:59 -0700 (PDT) From: Ard Biesheuvel To: wsa@the-dreams.de Cc: linux-i2c@vger.kernel.org, linux-arm-kernel@lists.infradead.org, jassisinghbrar@gmail.com, andy.shevchenko@gmail.com, Ard Biesheuvel Subject: [PATCH v7 1/4] dt-bindings: i2c: add binding for Socionext SynQuacer I2C Date: Tue, 3 Apr 2018 21:11:48 +0200 Message-Id: <20180403191151.14924-2-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180403191151.14924-1-ard.biesheuvel@linaro.org> References: <20180403191151.14924-1-ard.biesheuvel@linaro.org> Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org Add a binding for the I2C controller that can be found in the Socionext SynQuacer SoC. Signed-off-by: Ard Biesheuvel Reviewed-by: Rob Herring --- Documentation/devicetree/bindings/i2c/i2c-synquacer.txt | 29 ++++++++++++++++++++ 1 file changed, 29 insertions(+) -- 2.15.1 diff --git a/Documentation/devicetree/bindings/i2c/i2c-synquacer.txt b/Documentation/devicetree/bindings/i2c/i2c-synquacer.txt new file mode 100644 index 000000000000..72f4a2f0fedc --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-synquacer.txt @@ -0,0 +1,29 @@ +Socionext SynQuacer I2C + +Required properties: +- compatible : Must be "socionext,synquacer-i2c" +- reg : Offset and length of the register set for the device +- interrupts : A single interrupt specifier +- #address-cells : Must be <1>; +- #size-cells : Must be <0>; +- clock-names : Must contain "pclk". +- clocks : Must contain an entry for each name in clock-names. + (See the common clock bindings.) + +Optional properties: +- clock-frequency : Desired I2C bus clock frequency in Hz. As only Normal and + Fast modes are supported, possible values are 100000 and + 400000. + +Example : + + i2c@51210000 { + compatible = "socionext,synquacer-i2c"; + reg = <0x51210000 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "pclk"; + clocks = <&clk_i2c>; + clock-frequency = <400000>; + }; From patchwork Tue Apr 3 19:11:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 132782 Delivered-To: patch@linaro.org Received: by 10.46.84.29 with SMTP id i29csp4175522ljb; Tue, 3 Apr 2018 12:12:07 -0700 (PDT) X-Google-Smtp-Source: AIpwx49dkelcMIQp5Mphrk6d5Rg/otdH93YkED/GWwhUDLMQK7ttNr6HB6XU+HNpCtq4XYGrYTgK X-Received: by 2002:a17:902:4222:: with SMTP id g31-v6mr15756311pld.335.1522782727475; Tue, 03 Apr 2018 12:12:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1522782727; cv=none; d=google.com; s=arc-20160816; b=fZwalDMCrfYw14OW3PqjDeWVCVs/pweF4EqRpAEAEyS6UaiS1mrsgp4Ks7jPTtt/sa 8E8h/SIlr2j7QtpSsv8kMLfyK30ajRuBLhwVDs5N5fOV89Rz4PN62BOqOWgZMYEm+kos VsYf+ML6iA9l0ccFv5om0rghm5UzdGIcYWN290rRKDle7ysABuYV4MHTXMSPIIHOkbQG pkrIFcjQPDVQlbxawvXkqV0WRZyaQmQ5VJ2qJ2w2cCnOU1tHX1/97v6Y7PLXv5Zq46vU JjpA9vftSpWJKqdol92Ud8H0hmocecP0TFChe9Ty3t1JAotC/DDgi4M4Ek4/124MDrnm Yg7A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=2O8jB1oc/DYXtJrakS/5AkAX5frsjWpmFP2RyzUA7zI=; b=wawnQ2JKEuNk8DA/rfIo5iW5SV+261i7pgJWDubJU2Li/gAI8QJklINPAQyig/gUO5 tFhNolIVxlHjQNGAkSiZHM9tX20rwrSJMB1zwvMfHt5S5naV5lMZOrA4aVIpj8eVwnaU zHcCJlVrcW12VW8We7lKu6Wl5FpyvyKdaD1dU6+P+4nVUP0wo1rI7aq6sey1DgSZ5S5i BtzgrDY6wg7aRrviyxhP5jieSCSajrVzJlAS9L01DEvc7TEJ6fb3Pxuhujiw2UI/f7kq lXjj5albXh32BLKeqw4zFd/cY0Vw3WMZt/ZDUiCEVRqj06rcjFJ7+mgdD7uo+pWJRUKb smUA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=gCYkIOxK; spf=pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-i2c-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s78si2646947pfa.374.2018.04.03.12.12.07; Tue, 03 Apr 2018 12:12:07 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=gCYkIOxK; spf=pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-i2c-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753177AbeDCTMG (ORCPT + 3 others); Tue, 3 Apr 2018 15:12:06 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:37621 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753005AbeDCTMF (ORCPT ); Tue, 3 Apr 2018 15:12:05 -0400 Received: by mail-wm0-f67.google.com with SMTP id r131so37198159wmb.2 for ; Tue, 03 Apr 2018 12:12:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=2O8jB1oc/DYXtJrakS/5AkAX5frsjWpmFP2RyzUA7zI=; b=gCYkIOxKKN+R++X0DnqRgneVOLj8UjmgBLA9MJXvRIbzJkN6fdJ7X/Wc4iNiZnkC0/ uuoIjim3xWQnm9Bs8ngGwAWAWZlqGTO8hNDBGjP79ObNhNuBn9BdYw9z0Dxq5YPyh65L yI0mX3cx6kHJSU8pEx8V9AFndP1YJx/eMUgfA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=2O8jB1oc/DYXtJrakS/5AkAX5frsjWpmFP2RyzUA7zI=; b=hiwBvtg2w2G84fR4/uFbfOC5Yqn/D6QFSHtl8UD6g/Vjl1Tp9MHxn7TILHGnSjxbRA Lg9bqfi3+b+c9NtT0SxyRSFkAKefc7vVtgI9mu5DeEzaSKpl+WUiz5nP9zRq0wsbZYMc rLPhIUCufmo9qEyvcVm2+txRLd7T9BoHLeoVHQM4FN3jfM5YeXC5MuA8eymji8w6WkPn 6P48XjcF8dni1spa65+rxFrQnQk6jnrbA8O9Bi28ikxpMIKu47Aa2Pj2muQkgJOoGism MfzIZNCNtnCQ9GxnzOaWufM8kqBjlJBJPn2/BvMlc9/QSWXHRsZz3oy3rq/eo2EmWthy yvzw== X-Gm-Message-State: AElRT7Hr/s5oWDwOXNZM8ZI/tiIQo/Zz8koRW/fxXHsyz9HgwOzBADBa kr+uGLCrt3mFpHpURdx8Ed9vxg== X-Received: by 10.28.156.4 with SMTP id f4mr5435960wme.79.1522782723523; Tue, 03 Apr 2018 12:12:03 -0700 (PDT) Received: from localhost.localdomain ([2a01:e35:3995:5470:200:1aff:fe1b:b328]) by smtp.gmail.com with ESMTPSA id y100sm25120682wmh.2.2018.04.03.12.12.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 03 Apr 2018 12:12:02 -0700 (PDT) From: Ard Biesheuvel To: wsa@the-dreams.de Cc: linux-i2c@vger.kernel.org, linux-arm-kernel@lists.infradead.org, jassisinghbrar@gmail.com, andy.shevchenko@gmail.com, Ard Biesheuvel Subject: [PATCH v7 2/4] i2c: add support for Socionext SynQuacer I2C controller Date: Tue, 3 Apr 2018 21:11:49 +0200 Message-Id: <20180403191151.14924-3-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180403191151.14924-1-ard.biesheuvel@linaro.org> References: <20180403191151.14924-1-ard.biesheuvel@linaro.org> Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org This is a cleaned up version of the I2C controller driver for the Fujitsu F_I2C IP, which was never supported upstream, and has now been incorporated into the Socionext SynQuacer SoC. Signed-off-by: Ard Biesheuvel Reviewed-by: Andy Shevchenko --- drivers/i2c/busses/Kconfig | 10 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-synquacer.c | 669 ++++++++++++++++++++ 3 files changed, 680 insertions(+) -- 2.15.1 diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index e2954fb86d65..56903952d364 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -997,6 +997,16 @@ config I2C_SUN6I_P2WI This interface is used to connect to specific PMIC devices (like the AXP221). +config I2C_SYNQUACER + tristate "Socionext SynQuacer I2C controller" + depends on ARCH_SYNQUACER || COMPILE_TEST + help + Say Y here to include support for the I2C controller used in some + Fujitsu and Socionext SoCs. + + This driver can also be built as a module. If so, the module + will be called i2c-synquacer. + config I2C_TEGRA tristate "NVIDIA Tegra internal I2C controller" depends on ARCH_TEGRA diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 2ce8576540a2..40ab7bfc3458 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -98,6 +98,7 @@ obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7.o obj-$(CONFIG_I2C_STU300) += i2c-stu300.o obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o +obj-$(CONFIG_I2C_SYNQUACER) += i2c-synquacer.o obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o obj-$(CONFIG_I2C_TEGRA_BPMP) += i2c-tegra-bpmp.o obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c new file mode 100644 index 000000000000..2d9d7efd8e2d --- /dev/null +++ b/drivers/i2c/busses/i2c-synquacer.c @@ -0,0 +1,669 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012 FUJITSU SEMICONDUCTOR LIMITED + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WAIT_PCLK(n, rate) \ + ndelay(DIV_ROUND_UP(DIV_ROUND_UP(1000000000, rate), n) + 10) + +/* I2C register address definitions */ +#define SYNQUACER_I2C_REG_BSR (0x00 << 2) // Bus Status +#define SYNQUACER_I2C_REG_BCR (0x01 << 2) // Bus Control +#define SYNQUACER_I2C_REG_CCR (0x02 << 2) // Clock Control +#define SYNQUACER_I2C_REG_ADR (0x03 << 2) // Address +#define SYNQUACER_I2C_REG_DAR (0x04 << 2) // Data +#define SYNQUACER_I2C_REG_CSR (0x05 << 2) // Expansion CS +#define SYNQUACER_I2C_REG_FSR (0x06 << 2) // Bus Clock Freq +#define SYNQUACER_I2C_REG_BC2R (0x07 << 2) // Bus Control 2 + +/* I2C register bit definitions */ +#define SYNQUACER_I2C_BSR_FBT BIT(0) // First Byte Transfer +#define SYNQUACER_I2C_BSR_GCA BIT(1) // General Call Address +#define SYNQUACER_I2C_BSR_AAS BIT(2) // Address as Slave +#define SYNQUACER_I2C_BSR_TRX BIT(3) // Transfer/Receive +#define SYNQUACER_I2C_BSR_LRB BIT(4) // Last Received Bit +#define SYNQUACER_I2C_BSR_AL BIT(5) // Arbitration Lost +#define SYNQUACER_I2C_BSR_RSC BIT(6) // Repeated Start Cond. +#define SYNQUACER_I2C_BSR_BB BIT(7) // Bus Busy + +#define SYNQUACER_I2C_BCR_INT BIT(0) // Interrupt +#define SYNQUACER_I2C_BCR_INTE BIT(1) // Interrupt Enable +#define SYNQUACER_I2C_BCR_GCAA BIT(2) // Gen. Call Access Ack. +#define SYNQUACER_I2C_BCR_ACK BIT(3) // Acknowledge +#define SYNQUACER_I2C_BCR_MSS BIT(4) // Master Slave Select +#define SYNQUACER_I2C_BCR_SCC BIT(5) // Start Condition Cont. +#define SYNQUACER_I2C_BCR_BEIE BIT(6) // Bus Error Int Enable +#define SYNQUACER_I2C_BCR_BER BIT(7) // Bus Error + +#define SYNQUACER_I2C_CCR_CS_MASK (0x1f) // CCR Clock Period Sel. +#define SYNQUACER_I2C_CCR_EN BIT(5) // Enable +#define SYNQUACER_I2C_CCR_FM BIT(6) // Speed Mode Select + +#define SYNQUACER_I2C_CSR_CS_MASK (0x3f) // CSR Clock Period Sel. + +#define SYNQUACER_I2C_BC2R_SCLL BIT(0) // SCL Low Drive +#define SYNQUACER_I2C_BC2R_SDAL BIT(1) // SDA Low Drive +#define SYNQUACER_I2C_BC2R_SCLS BIT(4) // SCL Status +#define SYNQUACER_I2C_BC2R_SDAS BIT(5) // SDA Status + +/* PCLK frequency */ +#define SYNQUACER_I2C_BUS_CLK_FR(rate) (((rate) / 20000000) + 1) + +/* STANDARD MODE frequency */ +#define SYNQUACER_I2C_CLK_MASTER_STD(rate) \ + DIV_ROUND_UP(DIV_ROUND_UP((rate), 100000) - 2, 2) +/* FAST MODE frequency */ +#define SYNQUACER_I2C_CLK_MASTER_FAST(rate) \ + DIV_ROUND_UP((DIV_ROUND_UP((rate), 400000) - 2) * 2, 3) + +/* (clkrate <= 18000000) */ +/* calculate the value of CS bits in CCR register on standard mode */ +#define SYNQUACER_I2C_CCR_CS_STD_MAX_18M(rate) \ + ((SYNQUACER_I2C_CLK_MASTER_STD(rate) - 65) \ + & SYNQUACER_I2C_CCR_CS_MASK) + +/* calculate the value of CS bits in CSR register on standard mode */ +#define SYNQUACER_I2C_CSR_CS_STD_MAX_18M(rate) 0x00 + +/* calculate the value of CS bits in CCR register on fast mode */ +#define SYNQUACER_I2C_CCR_CS_FAST_MAX_18M(rate) \ + ((SYNQUACER_I2C_CLK_MASTER_FAST(rate) - 1) \ + & SYNQUACER_I2C_CCR_CS_MASK) + +/* calculate the value of CS bits in CSR register on fast mode */ +#define SYNQUACER_I2C_CSR_CS_FAST_MAX_18M(rate) 0x00 + +/* (clkrate > 18000000) */ +/* calculate the value of CS bits in CCR register on standard mode */ +#define SYNQUACER_I2C_CCR_CS_STD_MIN_18M(rate) \ + ((SYNQUACER_I2C_CLK_MASTER_STD(rate) - 1) \ + & SYNQUACER_I2C_CCR_CS_MASK) + +/* calculate the value of CS bits in CSR register on standard mode */ +#define SYNQUACER_I2C_CSR_CS_STD_MIN_18M(rate) \ + (((SYNQUACER_I2C_CLK_MASTER_STD(rate) - 1) >> 5) \ + & SYNQUACER_I2C_CSR_CS_MASK) + +/* calculate the value of CS bits in CCR register on fast mode */ +#define SYNQUACER_I2C_CCR_CS_FAST_MIN_18M(rate) \ + ((SYNQUACER_I2C_CLK_MASTER_FAST(rate) - 1) \ + & SYNQUACER_I2C_CCR_CS_MASK) + +/* calculate the value of CS bits in CSR register on fast mode */ +#define SYNQUACER_I2C_CSR_CS_FAST_MIN_18M(rate) \ + (((SYNQUACER_I2C_CLK_MASTER_FAST(rate) - 1) >> 5) \ + & SYNQUACER_I2C_CSR_CS_MASK) + +/* min I2C clock frequency 14M */ +#define SYNQUACER_I2C_MIN_CLK_RATE (14 * 1000000) +/* max I2C clock frequency 200M */ +#define SYNQUACER_I2C_MAX_CLK_RATE (200 * 1000000) +/* I2C clock frequency 18M */ +#define SYNQUACER_I2C_CLK_RATE_18M (18 * 1000000) + +#define SYNQUACER_I2C_SPEED_FM 400 // Fast Mode +#define SYNQUACER_I2C_SPEED_SM 100 // Standard Mode + +enum i2c_state { + STATE_IDLE, + STATE_START, + STATE_READ, + STATE_WRITE +}; + +struct synquacer_i2c { + struct completion completion; + + struct i2c_msg *msg; + u32 msg_num; + u32 msg_idx; + u32 msg_ptr; + + int irq; + struct device *dev; + void __iomem *base; + struct clk *pclk; + u32 pclkrate; + u32 speed_khz; + u32 timeout_ms; + enum i2c_state state; + struct i2c_adapter adapter; + + bool is_suspended; +}; + +static inline int is_lastmsg(struct synquacer_i2c *i2c) +{ + return i2c->msg_idx >= (i2c->msg_num - 1); +} + +static inline int is_msglast(struct synquacer_i2c *i2c) +{ + return i2c->msg_ptr == (i2c->msg->len - 1); +} + +static inline int is_msgend(struct synquacer_i2c *i2c) +{ + return i2c->msg_ptr >= i2c->msg->len; +} + +static inline unsigned long calc_timeout_ms(struct synquacer_i2c *i2c, + struct i2c_msg *msgs, + int num) +{ + unsigned long bit_count = 0; + int i; + + for (i = 0; i < num; i++, msgs++) + bit_count += msgs->len; + + return DIV_ROUND_UP((bit_count * 9 + num * 10) * 3, 200) + 10; +} + +static void synquacer_i2c_stop(struct synquacer_i2c *i2c, int ret) +{ + /* + * clear IRQ (INT=0, BER=0) + * set Stop Condition (MSS=0) + * Interrupt Disable + */ + writeb(0, i2c->base + SYNQUACER_I2C_REG_BCR); + + i2c->state = STATE_IDLE; + + i2c->msg_ptr = 0; + i2c->msg = NULL; + i2c->msg_idx++; + i2c->msg_num = 0; + if (ret) + i2c->msg_idx = ret; + + complete(&i2c->completion); +} + +static void synquacer_i2c_hw_init(struct synquacer_i2c *i2c) +{ + unsigned char ccr_cs, csr_cs; + u32 rt = i2c->pclkrate; + + /* Set own Address */ + writeb(0, i2c->base + SYNQUACER_I2C_REG_ADR); + + /* Set PCLK frequency */ + writeb(SYNQUACER_I2C_BUS_CLK_FR(i2c->pclkrate), + i2c->base + SYNQUACER_I2C_REG_FSR); + + switch (i2c->speed_khz) { + case SYNQUACER_I2C_SPEED_FM: + if (i2c->pclkrate <= SYNQUACER_I2C_CLK_RATE_18M) { + ccr_cs = SYNQUACER_I2C_CCR_CS_FAST_MAX_18M(rt); + csr_cs = SYNQUACER_I2C_CSR_CS_FAST_MAX_18M(rt); + } else { + ccr_cs = SYNQUACER_I2C_CCR_CS_FAST_MIN_18M(rt); + csr_cs = SYNQUACER_I2C_CSR_CS_FAST_MIN_18M(rt); + } + + /* Set Clock and enable, Set fast mode */ + writeb(ccr_cs | SYNQUACER_I2C_CCR_FM | + SYNQUACER_I2C_CCR_EN, + i2c->base + SYNQUACER_I2C_REG_CCR); + writeb(csr_cs, i2c->base + SYNQUACER_I2C_REG_CSR); + break; + case SYNQUACER_I2C_SPEED_SM: + if (i2c->pclkrate <= SYNQUACER_I2C_CLK_RATE_18M) { + ccr_cs = SYNQUACER_I2C_CCR_CS_STD_MAX_18M(rt); + csr_cs = SYNQUACER_I2C_CSR_CS_STD_MAX_18M(rt); + } else { + ccr_cs = SYNQUACER_I2C_CCR_CS_STD_MIN_18M(rt); + csr_cs = SYNQUACER_I2C_CSR_CS_STD_MIN_18M(rt); + } + + /* Set Clock and enable, Set standard mode */ + writeb(ccr_cs | SYNQUACER_I2C_CCR_EN, + i2c->base + SYNQUACER_I2C_REG_CCR); + writeb(csr_cs, i2c->base + SYNQUACER_I2C_REG_CSR); + break; + default: + WARN_ON(1); + } + + /* clear IRQ (INT=0, BER=0), Interrupt Disable */ + writeb(0, i2c->base + SYNQUACER_I2C_REG_BCR); + writeb(0, i2c->base + SYNQUACER_I2C_REG_BC2R); +} + +static void synquacer_i2c_hw_reset(struct synquacer_i2c *i2c) +{ + /* Disable clock */ + writeb(0, i2c->base + SYNQUACER_I2C_REG_CCR); + writeb(0, i2c->base + SYNQUACER_I2C_REG_CSR); + + WAIT_PCLK(100, i2c->pclkrate); +} + +static int synquacer_i2c_master_start(struct synquacer_i2c *i2c, + struct i2c_msg *pmsg) +{ + unsigned char bsr, bcr; + + writeb(i2c_8bit_addr_from_msg(pmsg), i2c->base + SYNQUACER_I2C_REG_DAR); + + dev_dbg(i2c->dev, "slave:0x%02x\n", pmsg->addr); + + /* Generate Start Condition */ + bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR); + bcr = readb(i2c->base + SYNQUACER_I2C_REG_BCR); + dev_dbg(i2c->dev, "bsr:0x%02x, bcr:0x%02x\n", bsr, bcr); + + if ((bsr & SYNQUACER_I2C_BSR_BB) && + !(bcr & SYNQUACER_I2C_BCR_MSS)) { + dev_dbg(i2c->dev, "bus is busy"); + return -EBUSY; + } + + if (bsr & SYNQUACER_I2C_BSR_BB) { /* Bus is busy */ + dev_dbg(i2c->dev, "Continuous Start"); + writeb(bcr | SYNQUACER_I2C_BCR_SCC, + i2c->base + SYNQUACER_I2C_REG_BCR); + } else { + if (bcr & SYNQUACER_I2C_BCR_MSS) { + dev_dbg(i2c->dev, "not in master mode"); + return -EAGAIN; + } + dev_dbg(i2c->dev, "Start Condition"); + /* Start Condition + Enable Interrupts */ + writeb(bcr | SYNQUACER_I2C_BCR_MSS | + SYNQUACER_I2C_BCR_INTE | SYNQUACER_I2C_BCR_BEIE, + i2c->base + SYNQUACER_I2C_REG_BCR); + } + + WAIT_PCLK(10, i2c->pclkrate); + + /* get BSR & BCR registers */ + bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR); + bcr = readb(i2c->base + SYNQUACER_I2C_REG_BCR); + dev_dbg(i2c->dev, "bsr:0x%02x, bcr:0x%02x\n", bsr, bcr); + + if ((bsr & SYNQUACER_I2C_BSR_AL) || + !(bcr & SYNQUACER_I2C_BCR_MSS)) { + dev_dbg(i2c->dev, "arbitration lost\n"); + return -EAGAIN; + } + + return 0; +} + +static int synquacer_i2c_doxfer(struct synquacer_i2c *i2c, + struct i2c_msg *msgs, int num) +{ + unsigned char bsr; + unsigned long timeout; + int ret; + + if (i2c->is_suspended) + return -EBUSY; + + synquacer_i2c_hw_init(i2c); + bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR); + if (bsr & SYNQUACER_I2C_BSR_BB) { + dev_err(i2c->dev, "cannot get bus (bus busy)\n"); + return -EBUSY; + } + + reinit_completion(&i2c->completion); + + i2c->msg = msgs; + i2c->msg_num = num; + i2c->msg_ptr = 0; + i2c->msg_idx = 0; + i2c->state = STATE_START; + + ret = synquacer_i2c_master_start(i2c, i2c->msg); + if (ret < 0) { + dev_dbg(i2c->dev, "Address failed: (%d)\n", ret); + return ret; + } + + timeout = wait_for_completion_timeout(&i2c->completion, + msecs_to_jiffies(i2c->timeout_ms)); + if (timeout == 0) { + dev_dbg(i2c->dev, "timeout\n"); + return -EAGAIN; + } + + ret = i2c->msg_idx; + if (ret != num) { + dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); + return -EAGAIN; + } + + /* wait 2 clock periods to ensure the stop has been through the bus */ + udelay(DIV_ROUND_UP(2 * 1000, i2c->speed_khz)); + + return 0; +} + +static irqreturn_t synquacer_i2c_isr(int irq, void *dev_id) +{ + struct synquacer_i2c *i2c = dev_id; + + unsigned char byte; + unsigned char bsr, bcr; + int ret; + + bcr = readb(i2c->base + SYNQUACER_I2C_REG_BCR); + bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR); + dev_dbg(i2c->dev, "bsr:0x%02x, bcr:0x%02x\n", bsr, bcr); + + if (bcr & SYNQUACER_I2C_BCR_BER) { + dev_err(i2c->dev, "bus error\n"); + synquacer_i2c_stop(i2c, -EAGAIN); + goto out; + } + if ((bsr & SYNQUACER_I2C_BSR_AL) || + !(bcr & SYNQUACER_I2C_BCR_MSS)) { + dev_dbg(i2c->dev, "arbitration lost\n"); + synquacer_i2c_stop(i2c, -EAGAIN); + goto out; + } + + switch (i2c->state) { + + case STATE_START: + if (bsr & SYNQUACER_I2C_BSR_LRB) { + dev_dbg(i2c->dev, "ack was not received\n"); + synquacer_i2c_stop(i2c, -EAGAIN); + goto out; + } + + if (i2c->msg->flags & I2C_M_RD) + i2c->state = STATE_READ; + else + i2c->state = STATE_WRITE; + + if (is_lastmsg(i2c) && i2c->msg->len == 0) { + synquacer_i2c_stop(i2c, 0); + goto out; + } + + if (i2c->state == STATE_READ) + goto prepare_read; + + /* fallthru */ + + case STATE_WRITE: + if (bsr & SYNQUACER_I2C_BSR_LRB) { + dev_dbg(i2c->dev, "WRITE: No Ack\n"); + synquacer_i2c_stop(i2c, -EAGAIN); + goto out; + } + + if (!is_msgend(i2c)) { + writeb(i2c->msg->buf[i2c->msg_ptr++], + i2c->base + SYNQUACER_I2C_REG_DAR); + + /* clear IRQ, and continue */ + writeb(SYNQUACER_I2C_BCR_BEIE | + SYNQUACER_I2C_BCR_MSS | + SYNQUACER_I2C_BCR_INTE, + i2c->base + SYNQUACER_I2C_REG_BCR); + break; + } + if (is_lastmsg(i2c)) { + synquacer_i2c_stop(i2c, 0); + break; + } + dev_dbg(i2c->dev, "WRITE: Next Message\n"); + + i2c->msg_ptr = 0; + i2c->msg_idx++; + i2c->msg++; + + /* send the new start */ + ret = synquacer_i2c_master_start(i2c, i2c->msg); + if (ret < 0) { + dev_dbg(i2c->dev, "restart error (%d)\n", ret); + synquacer_i2c_stop(i2c, -EAGAIN); + break; + } + i2c->state = STATE_START; + break; + + case STATE_READ: + byte = readb(i2c->base + SYNQUACER_I2C_REG_DAR); + if (!(bsr & SYNQUACER_I2C_BSR_FBT)) /* data */ + i2c->msg->buf[i2c->msg_ptr++] = byte; + else /* address */ + dev_dbg(i2c->dev, "address:0x%02x. ignore it.\n", byte); + +prepare_read: + if (is_msglast(i2c)) { + writeb(SYNQUACER_I2C_BCR_MSS | + SYNQUACER_I2C_BCR_BEIE | + SYNQUACER_I2C_BCR_INTE, + i2c->base + SYNQUACER_I2C_REG_BCR); + break; + } + if (!is_msgend(i2c)) { + writeb(SYNQUACER_I2C_BCR_MSS | + SYNQUACER_I2C_BCR_BEIE | + SYNQUACER_I2C_BCR_INTE | + SYNQUACER_I2C_BCR_ACK, + i2c->base + SYNQUACER_I2C_REG_BCR); + break; + } + if (is_lastmsg(i2c)) { + /* last message, send stop and complete */ + dev_dbg(i2c->dev, "READ: Send Stop\n"); + synquacer_i2c_stop(i2c, 0); + break; + } + dev_dbg(i2c->dev, "READ: Next Transfer\n"); + + i2c->msg_ptr = 0; + i2c->msg_idx++; + i2c->msg++; + + ret = synquacer_i2c_master_start(i2c, i2c->msg); + if (ret < 0) { + dev_dbg(i2c->dev, "restart error (%d)\n", ret); + synquacer_i2c_stop(i2c, -EAGAIN); + } else { + i2c->state = STATE_START; + } + break; + default: + dev_err(i2c->dev, "called in err STATE (%d)\n", i2c->state); + break; + } + +out: + WAIT_PCLK(10, i2c->pclkrate); + return IRQ_HANDLED; +} + +static int synquacer_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num) +{ + struct synquacer_i2c *i2c; + int retry; + int ret; + + i2c = i2c_get_adapdata(adap); + i2c->timeout_ms = calc_timeout_ms(i2c, msgs, num); + + dev_dbg(i2c->dev, "calculated timeout %d ms\n", i2c->timeout_ms); + + for (retry = 0; retry < adap->retries; retry++) { + + ret = synquacer_i2c_doxfer(i2c, msgs, num); + if (ret != -EAGAIN) + return ret; + + dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry); + + synquacer_i2c_hw_reset(i2c); + } + return -EIO; +} + +static u32 synquacer_i2c_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm synquacer_i2c_algo = { + .master_xfer = synquacer_i2c_xfer, + .functionality = synquacer_i2c_functionality, +}; + +static struct i2c_adapter synquacer_i2c_ops = { + .owner = THIS_MODULE, + .name = "synquacer_i2c-adapter", + .algo = &synquacer_i2c_algo, + .retries = 5, +}; + +static int synquacer_i2c_probe(struct platform_device *pdev) +{ + struct synquacer_i2c *i2c; + struct resource *r; + u32 bus_speed; + int ret; + + i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + bus_speed = i2c_acpi_find_bus_speed(&pdev->dev); + if (!bus_speed) + device_property_read_u32(&pdev->dev, "clock-frequency", + &bus_speed); + + device_property_read_u32(&pdev->dev, "socionext,pclk-rate", + &i2c->pclkrate); + + i2c->pclk = devm_clk_get(&pdev->dev, "pclk"); + if (IS_ERR(i2c->pclk) && PTR_ERR(i2c->pclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (!IS_ERR_OR_NULL(i2c->pclk)) { + dev_dbg(&pdev->dev, "clock source %p\n", i2c->pclk); + + ret = clk_prepare_enable(i2c->pclk); + if (ret) { + dev_err(&pdev->dev, "failed to enable clock (%d)\n", + ret); + return ret; + } + i2c->pclkrate = clk_get_rate(i2c->pclk); + } + + if (i2c->pclkrate < SYNQUACER_I2C_MIN_CLK_RATE || + i2c->pclkrate > SYNQUACER_I2C_MAX_CLK_RATE) { + dev_err(&pdev->dev, "PCLK missing or out of range (%d)\n", + i2c->pclkrate); + return -EINVAL; + } + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + i2c->base = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(i2c->base)) + return PTR_ERR(i2c->base); + + i2c->irq = platform_get_irq(pdev, 0); + if (i2c->irq < 0) { + dev_err(&pdev->dev, "no IRQ resource found\n"); + return -ENODEV; + } + + ret = devm_request_irq(&pdev->dev, i2c->irq, synquacer_i2c_isr, + 0, dev_name(&pdev->dev), i2c); + if (ret < 0) { + dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); + return ret; + } + + i2c->state = STATE_IDLE; + i2c->dev = &pdev->dev; + i2c->adapter = synquacer_i2c_ops; + i2c_set_adapdata(&i2c->adapter, i2c); + i2c->adapter.dev.parent = &pdev->dev; + i2c->adapter.nr = pdev->id; + init_completion(&i2c->completion); + + if (bus_speed < 400000) + i2c->speed_khz = SYNQUACER_I2C_SPEED_SM; + else + i2c->speed_khz = SYNQUACER_I2C_SPEED_FM; + + synquacer_i2c_hw_init(i2c); + + ret = i2c_add_numbered_adapter(&i2c->adapter); + if (ret) { + dev_err(&pdev->dev, "failed to add bus to i2c core\n"); + return ret; + } + + platform_set_drvdata(pdev, i2c); + + dev_info(&pdev->dev, "%s: synquacer_i2c adapter\n", + dev_name(&i2c->adapter.dev)); + + return 0; +} + +static int synquacer_i2c_remove(struct platform_device *pdev) +{ + struct synquacer_i2c *i2c = platform_get_drvdata(pdev); + + i2c_del_adapter(&i2c->adapter); + if (!IS_ERR(i2c->pclk)) + clk_disable_unprepare(i2c->pclk); + + return 0; +}; + +static const struct of_device_id synquacer_i2c_dt_ids[] = { + { .compatible = "socionext,synquacer-i2c" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, synquacer_i2c_dt_ids); + +#ifdef CONFIG_ACPI +static const struct acpi_device_id synquacer_i2c_acpi_ids[] = { + { "SCX0003" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(acpi, synquacer_i2c_acpi_ids); +#endif + +static struct platform_driver synquacer_i2c_driver = { + .probe = synquacer_i2c_probe, + .remove = synquacer_i2c_remove, + .driver = { + .name = "synquacer_i2c", + .of_match_table = of_match_ptr(synquacer_i2c_dt_ids), + .acpi_match_table = ACPI_PTR(synquacer_i2c_acpi_ids), + }, +}; +module_platform_driver(synquacer_i2c_driver); + +MODULE_AUTHOR("Fujitsu Semiconductor Ltd"); +MODULE_DESCRIPTION("Socionext SynQuacer I2C Driver"); +MODULE_LICENSE("GPL v2"); From patchwork Tue Apr 3 19:11:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 132783 Delivered-To: patch@linaro.org Received: by 10.46.84.29 with SMTP id i29csp4175547ljb; Tue, 3 Apr 2018 12:12:08 -0700 (PDT) X-Google-Smtp-Source: AIpwx48j9PRVAxsGNo6Uvl+PXeM61b0EjG2UKX4thU5XI/rEnjAXCzubucyEHgi1sFsXaBoi2AnU X-Received: by 10.98.60.4 with SMTP id j4mr11453411pfa.229.1522782728162; Tue, 03 Apr 2018 12:12:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1522782728; cv=none; d=google.com; s=arc-20160816; b=RIt0ay/xkVHr1xx/flUwYZrTlyS6zESArJ6PeP/tetridO8co5TG8WU8KnReDu+knv V0WQAoRCEwhNvoSgIW++EsoUktONTLseIvrGWz9VtzLEGZ/0lqDYdd25/BhDYLvdPxRA ljObl1jlJU3+ZE6fCf9FtWAp2UaJ4g+K+/gTHUNhAqn76DHf/fvcBvnFmfT/hGyvvO3A 5gkU1A1Opf4vOAOqR5ZN1KYNiuH98LkosvamL4Xd67aLjigb8UdixuIrjmhAF5V+m3Z4 vnBFcpOL30YT1RbpLttz9rs69b4yCj+q+6V3Pb4oGY8N3k3nCu24tHl8sX4qGPuj+WzP OZ7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=cIsfmCaG1eTi2Vegv49ijJbnU+PkN09SgF1pSIiomUA=; b=PuA9Sh0sAhn0cqmBNFuNfLqAqzHO1RWAaWKjaBwHwnmbL3GCZ8HHK8RLl2jqSYUgsA pcln0ZURljGUGq8wGEMwh7PVPY5HFpzmykAPFd4xxvNi4qPp3kK+1JJRXaYNIHWhLsCC 00IwXWVsg3liFiTIXo/FNNXoXgU+druR2GU2zatyghGCrqrgY8KUUzf3URWr92D3Jntr dxRYhHU99D35DBMzHm597IWqijDyBvvrDZ1wl4Nw3ciZmIxp9GTl13jphE+FOOBYRm2f EKRJ1PVkjZnPsR5GXR+0Nyxr58ZonXPGhM0r2o/wZglXBvab45LjdQgBl/RberWukcQl Lm4A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=OfFAlDim; spf=pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-i2c-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s78si2646947pfa.374.2018.04.03.12.12.07; Tue, 03 Apr 2018 12:12:08 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=OfFAlDim; spf=pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-i2c-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753005AbeDCTMH (ORCPT + 3 others); Tue, 3 Apr 2018 15:12:07 -0400 Received: from mail-wm0-f65.google.com ([74.125.82.65]:38156 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753156AbeDCTMG (ORCPT ); Tue, 3 Apr 2018 15:12:06 -0400 Received: by mail-wm0-f65.google.com with SMTP id i3so13446497wmf.3 for ; Tue, 03 Apr 2018 12:12:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=cIsfmCaG1eTi2Vegv49ijJbnU+PkN09SgF1pSIiomUA=; b=OfFAlDimscehezy0c2MZHiTvPGU4elQt5NgsNg8sEHKA/AtLaqcWlPMa+FwxwbeXdL ymHjyONBS1NFNUY041iF+TW4xU9c4LaRx0AkOHcRF3ETHhEWGTCTGcbrff5jDAEstLAC MDE5/r2zFhA6LSpZ3oFNszixp3gOtFy09w82A= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=cIsfmCaG1eTi2Vegv49ijJbnU+PkN09SgF1pSIiomUA=; b=jcByWwpbb/DjhqEOkE/fx0zaLi/diRPHQGJMbZm7TZp1cY4rPdSyQoXBx+tdbH+1KI vmc5sNV1gj30pVRHY5iuVMJc9j5G2b0Q49OuSxmc0dJQbrQ4jIVE+0v6lZGHSEj9g6+s Xqqup0ZiGbPJG23pngWkTi3x4IcYA8NZnSKB5STmuF/lSqQpah4zmpgZ0HwEEij2UZ+a m0S4WEWLlSu+xkGDjEpB5sNXB5Lramcb2LGa18t8TaEiozkbuLb4hg6lC28zbkDhPZy1 zMrztHHm/VDkq5+ZyKsbt6w6E9CqwyTv/7Lg5NGXlkERGDVDfvJTGi4gb7Pg/M98tLGh CbTA== X-Gm-Message-State: ALQs6tBjCgpXDczFpRcAQOh/hJx55DyfPE6F4uCINMz5QQ8VGlxmibbj I278fMabDfj/gDPdxwNvvmuPHA== X-Received: by 10.28.21.77 with SMTP id 74mr5431813wmv.76.1522782725466; Tue, 03 Apr 2018 12:12:05 -0700 (PDT) Received: from localhost.localdomain ([2a01:e35:3995:5470:200:1aff:fe1b:b328]) by smtp.gmail.com with ESMTPSA id y100sm25120682wmh.2.2018.04.03.12.12.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 03 Apr 2018 12:12:04 -0700 (PDT) From: Ard Biesheuvel To: wsa@the-dreams.de Cc: linux-i2c@vger.kernel.org, linux-arm-kernel@lists.infradead.org, jassisinghbrar@gmail.com, andy.shevchenko@gmail.com, Ard Biesheuvel Subject: [PATCH v7 3/4] i2c: add param sanity check to i2c_transfer() Date: Tue, 3 Apr 2018 21:11:50 +0200 Message-Id: <20180403191151.14924-4-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180403191151.14924-1-ard.biesheuvel@linaro.org> References: <20180403191151.14924-1-ard.biesheuvel@linaro.org> Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org The API docs describe i2c_transfer() as taking a pointer to an array of i2c_msg containing at least 1 entry, but leaves it to the individual drivers to sanity check the msgs and num parameters. Let's do this in core code instead. Signed-off-by: Ard Biesheuvel --- drivers/i2c/i2c-core-base.c | 3 +++ 1 file changed, 3 insertions(+) -- 2.15.1 diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index c8bfe008f208..e2ca5c331ecb 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -1845,6 +1845,9 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) unsigned long orig_jiffies; int ret, try; + if (WARN_ON(!msgs || num <= 0)) + return -EINVAL; + if (adap->quirks && i2c_check_for_quirks(adap, msgs, num)) return -EOPNOTSUPP; From patchwork Tue Apr 3 19:11:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 132784 Delivered-To: patch@linaro.org Received: by 10.46.84.29 with SMTP id i29csp4175580ljb; Tue, 3 Apr 2018 12:12:09 -0700 (PDT) X-Google-Smtp-Source: AIpwx4/ATiNFYOIEEuRlWa0DEpuOYzA7eoMH+PGjbtkyjuRzyYJnhhP6eNYEY+pQFEHMov5JVOEe X-Received: by 10.167.128.2 with SMTP id j2mr11560493pfi.179.1522782729410; Tue, 03 Apr 2018 12:12:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1522782729; cv=none; d=google.com; s=arc-20160816; b=af9q6Ysxwq7kf59B6xh+n16FeUFaOleVqP0OjLeGMaql4ENs0VatnXsAbND/jqUiAK oL7SHK9DjZ0hPYvonSrfrJi/Glg8K2/kPFP5Ovw0XXzqQF4A2kve3NjdcSgJvXzxemVf 8+ycIOsmKeSd5eojeOBCYKeq0PDou+Sqjv2vo1/iElmR3qkBACJhJUGlqhHjvxODfK/i pRKLmQQpUcrT2D3Qy2jecAHp53zrCuQ0/A8cUYP237ywL6TO5vlX9GrOdh7K2S1AOCJi B1QZVs+wUqk5sPTr/gzbe5xe0waoz+A0k40zoRUW1rV4lSOE/nnrwRm/fnsgkl6Pq1gB +kvA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=bSGU9Jj6xWyiDhyUIo/8oatGQXHlwFct2hTWSIrqNyU=; b=Lob0AN5r98ITwo/zYKunUC0+rj6qq9QEO1Z/3KZ9VFF3HTc2oRDPSQStCITTHfcSs4 Se0OKWhxURu1I71Z0hIN4UQDyPoMAdlSP6AhqYEU51WB4bXdfSQb2fEMoAVOS2hK5gv6 EFlwMWyu7KxRvPCYzNXjSgXbmSVmc2AEBCsP/YqK0lcJvt/0BiSz9M3JY4jlEJEYMhDn nqgH6OEcjYfjmDtgoct+QZzb3GNO5s07d2r0N3qI/jWt0JvDlZjtTiz6s2h6sJuGHx2w PrRRVY+rCl/599ZjtEJwSwmj6iLY2vmMN+vdGHgWwqjVuXH317PiBzOEHIDhjISVHm41 siZA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Ckaf40US; spf=pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-i2c-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s78si2646947pfa.374.2018.04.03.12.12.09; Tue, 03 Apr 2018 12:12:09 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Ckaf40US; spf=pass (google.com: best guess record for domain of linux-i2c-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-i2c-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753289AbeDCTMI (ORCPT + 3 others); Tue, 3 Apr 2018 15:12:08 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:54973 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753156AbeDCTMI (ORCPT ); Tue, 3 Apr 2018 15:12:08 -0400 Received: by mail-wm0-f66.google.com with SMTP id r191so5056297wmg.4 for ; Tue, 03 Apr 2018 12:12:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=bSGU9Jj6xWyiDhyUIo/8oatGQXHlwFct2hTWSIrqNyU=; b=Ckaf40USdkXCRxM5IwsHmhWGbErCZ8Jiilr3VfHcWLXyFEZsW4/bhlnGKemlBUbY/1 8Dd8cPq07ooThXK/T/PmeR9DmrKVX9OarNVLzydFpLEVy2C6n5zKBTYNtmZ+CCzAbq2H jCKG0KVY8x1rPv7qOcy+/Yy3Tse3QWNVBpwws= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=bSGU9Jj6xWyiDhyUIo/8oatGQXHlwFct2hTWSIrqNyU=; b=DIbPbJ8Wkr3gJgtzt2rkXYr5tLIWkfybWdKpUfeS35nlKu8Tdt8jSJe5iNLAY7D5DD tSgvCwN4exJLskzpNsKvl7doorlYqfQab/UYOrQL2uOMkoeJlm7euQS5Yhcwr1fGXyJg Nc+C7gkGVJv0PVhhsqGSnetbswsziSVF1Wb4t2Hx/CclJ8uNceC+yFy1+71srCsgHWEr d+w7N5W0WB1h644WOY6zmL4HimykxwWqps3FmPUpHP0LT2mJ82JaugGPuYWhrbNW4xnu E9vTkD8n8RWNtPKkgdVDAzJjD32eN/PQA1ILGhY/9S8CJg2e99RyGWAjq30k6Fb8pNYF w9tw== X-Gm-Message-State: ALQs6tAka7dB655NV2ifh7VMWmA6QuU8C/AmL24fqu/I7YRlkGONxZvp 5XOI6EbT3mQ8QsxFyAKZYS+3FQ== X-Received: by 10.28.220.193 with SMTP id t184mr5398279wmg.138.1522782726964; Tue, 03 Apr 2018 12:12:06 -0700 (PDT) Received: from localhost.localdomain ([2a01:e35:3995:5470:200:1aff:fe1b:b328]) by smtp.gmail.com with ESMTPSA id y100sm25120682wmh.2.2018.04.03.12.12.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 03 Apr 2018 12:12:06 -0700 (PDT) From: Ard Biesheuvel To: wsa@the-dreams.de Cc: linux-i2c@vger.kernel.org, linux-arm-kernel@lists.infradead.org, jassisinghbrar@gmail.com, andy.shevchenko@gmail.com, Ard Biesheuvel Subject: [PATCH v7 4/4] MAINTAINERS: add Ard as Socionext SynQuacer I2C driver maintainer Date: Tue, 3 Apr 2018 21:11:51 +0200 Message-Id: <20180403191151.14924-5-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180403191151.14924-1-ard.biesheuvel@linaro.org> References: <20180403191151.14924-1-ard.biesheuvel@linaro.org> Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org Add myself as maintainer for the newly added Socionext SynQuacer I2C driver. Signed-off-by: Ard Biesheuvel --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) -- 2.15.1 diff --git a/MAINTAINERS b/MAINTAINERS index 2d3f847cdc8d..6b3e60a6d282 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12816,6 +12816,12 @@ F: include/media/soc* F: drivers/media/i2c/soc_camera/ F: drivers/media/platform/soc_camera/ +SOCIONEXT SYNQUACER I2C DRIVER +M: Ard Biesheuvel +L: linux-i2c@vger.kernel.org +S: Maintained +F: drivers/i2c/busses/i2c-synquacer.c + SOCIONEXT UNIPHIER SOUND DRIVER M: Katsuhiro Suzuki L: alsa-devel@alsa-project.org (moderated for non-subscribers)