From patchwork Sat Dec 5 17:51:31 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 7775981 X-Patchwork-Delegate: horms@verge.net.au Return-Path: X-Original-To: patchwork-linux-sh@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 52436BEEE5 for ; Sat, 5 Dec 2015 17:51:52 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 555482045B for ; Sat, 5 Dec 2015 17:51:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2A6432049E for ; Sat, 5 Dec 2015 17:51:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753331AbbLERvt (ORCPT ); Sat, 5 Dec 2015 12:51:49 -0500 Received: from mail-lf0-f65.google.com ([209.85.215.65]:34626 "EHLO mail-lf0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753264AbbLERvs (ORCPT ); Sat, 5 Dec 2015 12:51:48 -0500 Received: by lfu94 with SMTP id 94so12967972lfu.1 for ; Sat, 05 Dec 2015 09:51:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ragnatech-se.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=R+q6PYXIO6q+k0PfO7pITNIc1HuYAwSVX2L6FLqDzX0=; b=Fh1du/bRQHG7F87kEhdMM233iSMvF+70a+Fl96GgblQ35hpLExbWSK1ApYEGHFVOBA qFH96gyvkD3mShPit4zCcND6AUn6Cfe0ogWzvKeMOn6PMhqTvGSa/RzF+f0S4F4KbXe1 1Np72BXsadR4bB5QqlVvTrmSwzCXPVjzM4+KxfEdYMNylhpBN+78cvkckBCjEOI8G85Z sCaKH9thx9s2x+s6a9OR6B+acH+VpC8AC1WmTswBgDrCv+7DcMPyoilbJEIZ7Dlo/Rq5 hNOkVmoXBnr6oF1CyMCwQvchtgKFsj4RKhw7uWKtpy/EE2rWGAvXXMabMU5w7M60tQB7 ANzw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-type:content-transfer-encoding; bh=R+q6PYXIO6q+k0PfO7pITNIc1HuYAwSVX2L6FLqDzX0=; b=JLx2q5qHIQ0R2Ns3a1TD0EXH8CUNOkjCyrhjLEsT9IJPmOl98q6DG/awI1pcyXIkub 94BKPeyjBo0518p6w/VYPrmFaJy9q5xrnZc9vKdyXttT+cd1vwAn2uTPyjds3mTlu7Ee kCi9Prhps39oPwqYTV2ov0GxW0P+PmcA8xlnUMXjCXrEqYX9CR9Oo0kcXvheAZFQYnRy XTLOl93i5Mcon6rg0XT7s2+SFJxiPK+yTv4vI4msARFK/yHwRtWvBp5drE9Ut+hhR3j2 C86ZT2A0OkOWs6TkD4fpv/KxQTOuYvPqxtsEAazo0pc+lWH715JIY+dL4qdKYcNKxRCc 8MiA== X-Gm-Message-State: ALoCoQmopqTOSjgOoyWXGBimZXw1nM6FmyTrM8sRDxZ8cUKTl78gLUNE3/QnEV26/RPWtrZywyxp X-Received: by 10.25.21.80 with SMTP id l77mr8893089lfi.43.1449337906633; Sat, 05 Dec 2015 09:51:46 -0800 (PST) Received: from hydra.berto.se (dynamic.0.6.79d1f80.14cc20ac3a53.cust.bredband2.com. [89.233.230.99]) by smtp.gmail.com with ESMTPSA id a2sm3339242lbp.37.2015.12.05.09.51.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 05 Dec 2015 09:51:46 -0800 (PST) From: "=?UTF-8?q?Niklas=20S=C3=B6derlund?=" X-Google-Original-From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= To: wsa@the-dreams.de, linux-i2c@vger.kernel.org Cc: ian.molton@codethink.co.uk, laurent.pinchart@ideasonboard.com, magnus.damm@gmail.com, linux-sh@vger.kernel.org, =?UTF-8?q?Niklas=20S=C3=B6derlund?= Subject: [PATCH v2] i2c: emev2: add slave support Date: Sat, 5 Dec 2015 18:51:31 +0100 Message-Id: <1449337891-3880-2-git-send-email-niklas.soderlund+renesas@ragnatech.se> X-Mailer: git-send-email 2.6.3 In-Reply-To: <1449337891-3880-1-git-send-email-niklas.soderlund+renesas@ragnatech.se> References: <1449337891-3880-1-git-send-email-niklas.soderlund+renesas@ragnatech.se> MIME-Version: 1.0 Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID,T_RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add I2C slave provider using the generic slave interface. Signed-off-by: Niklas Söderlund --- drivers/i2c/busses/i2c-emev2.c | 112 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-emev2.c b/drivers/i2c/busses/i2c-emev2.c index 192ef6b..96bb4e7 100644 --- a/drivers/i2c/busses/i2c-emev2.c +++ b/drivers/i2c/busses/i2c-emev2.c @@ -71,6 +71,7 @@ struct em_i2c_device { struct i2c_adapter adap; struct completion msg_done; struct clk *sclk; + struct i2c_client *slave; }; static inline void em_clear_set_bit(struct em_i2c_device *priv, u8 clear, u8 set, u8 reg) @@ -226,22 +227,131 @@ static int em_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, return num; } +static bool em_i2c_slave_irq(struct em_i2c_device *priv) +{ + u8 status, value; + enum i2c_slave_event event; + int ret; + + if (!priv->slave) + return false; + + status = readb(priv->base + I2C_OFS_IICSE0); + + /* Extension code, do not participate */ + if (status & I2C_BIT_EXC0) { + em_clear_set_bit(priv, 0, I2C_BIT_LREL0, I2C_OFS_IICC0); + return true; + } + + /* Stop detected, we don't know if it's for slave or master */ + if (status & I2C_BIT_SPD0) { + /* Notify slave device */ + i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value); + /* Pretend we did not handle the interrupt */ + return false; + } + + /* Only handle interrupts addressed to us */ + if (!(status & I2C_BIT_COI0)) + return false; + + /* Enable stop interrupts */ + em_clear_set_bit(priv, 0, I2C_BIT_SPIE0, I2C_OFS_IICC0); + + /* Transmission or Reception */ + if (status & I2C_BIT_TRC0) { + if (status & I2C_BIT_ACKD0) { + /* 9 bit interrupt mode */ + em_clear_set_bit(priv, 0, I2C_BIT_WTIM0, I2C_OFS_IICC0); + + /* Send data */ + event = status & I2C_BIT_STD0 ? + I2C_SLAVE_READ_REQUESTED : + I2C_SLAVE_READ_PROCESSED; + i2c_slave_event(priv->slave, event, &value); + writeb(value, priv->base + I2C_OFS_IIC0); + } else { + /* NACK, stop transmitting */ + em_clear_set_bit(priv, 0, I2C_BIT_LREL0, I2C_OFS_IICC0); + } + } else { + /* 8 bit interrupt mode */ + em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_ACKE0, + I2C_OFS_IICC0); + em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_WREL0, + I2C_OFS_IICC0); + + if (status & I2C_BIT_STD0) { + i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_REQUESTED, + &value); + } else { + /* Recv data */ + value = readb(priv->base + I2C_OFS_IIC0); + ret = i2c_slave_event(priv->slave, + I2C_SLAVE_WRITE_RECEIVED, &value); + if (ret < 0) + em_clear_set_bit(priv, I2C_BIT_ACKE0, 0, + I2C_OFS_IICC0); + } + } + + return true; +} + static irqreturn_t em_i2c_irq_handler(int this_irq, void *dev_id) { struct em_i2c_device *priv = dev_id; + if (em_i2c_slave_irq(priv)) + return IRQ_HANDLED; + complete(&priv->msg_done); + return IRQ_HANDLED; } static u32 em_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SLAVE; +} + +static int em_i2c_reg_slave(struct i2c_client *slave) +{ + struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter); + + if (priv->slave) + return -EBUSY; + + if (slave->flags & I2C_CLIENT_TEN) + return -EAFNOSUPPORT; + + priv->slave = slave; + + /* Set slave address */ + writeb(slave->addr << 1, priv->base + I2C_OFS_SVA0); + + return 0; +} + +static int em_i2c_unreg_slave(struct i2c_client *slave) +{ + struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter); + + WARN_ON(!priv->slave); + + writeb(0, priv->base + I2C_OFS_SVA0); + + priv->slave = NULL; + + return 0; } static struct i2c_algorithm em_i2c_algo = { .master_xfer = em_i2c_xfer, .functionality = em_i2c_func, + .reg_slave = em_i2c_reg_slave, + .unreg_slave = em_i2c_unreg_slave, }; static int em_i2c_probe(struct platform_device *pdev)