From patchwork Fri Jan 11 23:43:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Lunn X-Patchwork-Id: 1023811 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=lunn.ch Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=lunn.ch header.i=@lunn.ch header.b="3WYtGsr0"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43bzxT47NNz9sBQ for ; Sat, 12 Jan 2019 10:45:01 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726193AbfAKXpB (ORCPT ); Fri, 11 Jan 2019 18:45:01 -0500 Received: from vps0.lunn.ch ([185.16.172.187]:40858 "EHLO vps0.lunn.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725794AbfAKXpB (ORCPT ); Fri, 11 Jan 2019 18:45:01 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lunn.ch; s=20171124; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=YMUuqptdSr1Y5/f+XQKtXAwtD3hqE8ojQOl2a4y7KTg=; b=3WYtGsr0BabjGblrhwWgnbY9ScpPMevHZLnCib10b/mzELzk9ND/mWT6LBGXZz3n+Njp9MhgWywlWWyH+rGHoidJSRo0LeQK7B0x8bhyJeEnf/99Qu3UWyTAUPDmNVG3cl0SsBbeRVmI4T56R7F68qNfpeWaUYG9A6Z6/DuImi0=; Received: from andrew by vps0.lunn.ch with local (Exim 4.84_2) (envelope-from ) id 1gi6TD-0004Tl-NB; Sat, 12 Jan 2019 00:44:11 +0100 From: Andrew Lunn To: Peter Korsgaard Cc: Wolfram Sang , Lee Jones , linux-i2c@vger.kernel.org, Andrew Lunn Subject: [PATCH v2 resend 1/3] i2c: ocores: Add support for IO mapper registers. Date: Sat, 12 Jan 2019 00:43:56 +0100 Message-Id: <1547250238-17181-2-git-send-email-andrew@lunn.ch> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1547250238-17181-1-git-send-email-andrew@lunn.ch> References: <1547250238-17181-1-git-send-email-andrew@lunn.ch> Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org Some implementations of the OCORES i2c bus master use IO mapped registers. Add support for getting the IO registers from the platform data, and register accessor functions. Signed-off-by: Andrew Lunn --- drivers/i2c/busses/i2c-ocores.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 87f9caacba85..ddf089280847 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -28,6 +28,7 @@ struct ocores_i2c { void __iomem *base; + int iobase; u32 reg_shift; u32 reg_io_width; wait_queue_head_t wait; @@ -127,6 +128,16 @@ static inline u8 oc_getreg_32be(struct ocores_i2c *i2c, int reg) return ioread32be(i2c->base + (reg << i2c->reg_shift)); } +static void oc_setreg_io_8(struct ocores_i2c *i2c, int reg, u8 value) +{ + outb(value, i2c->iobase + reg); +} + +static inline u8 oc_getreg_io_8(struct ocores_i2c *i2c, int reg) +{ + return inb(i2c->iobase + reg); +} + static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) { i2c->setreg(i2c, reg, value); @@ -423,9 +434,24 @@ static int ocores_i2c_probe(struct platform_device *pdev) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(i2c->base)) - return PTR_ERR(i2c->base); + if (res) { + i2c->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(i2c->base)) + return PTR_ERR(i2c->base); + } else { + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!res) + return -EINVAL; + i2c->iobase = res->start; + if (!devm_request_region(&pdev->dev, res->start, + resource_size(res), + pdev->name)) { + dev_err(&pdev->dev, "Can't get I/O resource.\n"); + return -EBUSY; + } + i2c->setreg = oc_setreg_io_8; + i2c->getreg = oc_getreg_io_8; + } pdata = dev_get_platdata(&pdev->dev); if (pdata) { From patchwork Fri Jan 11 23:43:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Lunn X-Patchwork-Id: 1023809 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=lunn.ch Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=lunn.ch header.i=@lunn.ch header.b="MOlyo3YS"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43bzwv5Rnqz9sBQ for ; Sat, 12 Jan 2019 10:44:31 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725915AbfAKXo3 (ORCPT ); Fri, 11 Jan 2019 18:44:29 -0500 Received: from vps0.lunn.ch ([185.16.172.187]:40848 "EHLO vps0.lunn.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725794AbfAKXo3 (ORCPT ); Fri, 11 Jan 2019 18:44:29 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lunn.ch; s=20171124; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=wOO9Zcxi/bEhsGd3JxzzglGUiXHEbW2OH3XKIibFq4k=; b=MOlyo3YSnZAKyVcLXwjTRQApO2KCTrkDa6LVG5MilE6Js3NoerU8/2sk0QTe59ra29wCwUXDOrWZE4/hv3uT1ZJNtg3OQNnAZ4HQufMN7uP8sp8Dsluoqk18uFs+Amwl1s+Jd0Pz29NMdeeZz4pqNJtI0L+5Iq5qaRJSOlOi9r0=; Received: from andrew by vps0.lunn.ch with local (Exim 4.84_2) (envelope-from ) id 1gi6TD-0004Tq-Nq; Sat, 12 Jan 2019 00:44:11 +0100 From: Andrew Lunn To: Peter Korsgaard Cc: Wolfram Sang , Lee Jones , linux-i2c@vger.kernel.org, Andrew Lunn Subject: [PATCH v2 resend 2/3] i2c: ocores: Add support for bus clock via platform data Date: Sat, 12 Jan 2019 00:43:57 +0100 Message-Id: <1547250238-17181-3-git-send-email-andrew@lunn.ch> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1547250238-17181-1-git-send-email-andrew@lunn.ch> References: <1547250238-17181-1-git-send-email-andrew@lunn.ch> Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org Add the I2C bus clock speed to the platform data structure. If not set, default to 100KHz as before. Signed-off-by: Andrew Lunn --- drivers/i2c/busses/i2c-ocores.c | 5 ++++- include/linux/platform_data/i2c-ocores.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index ddf089280847..d2730efe6bec 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -458,7 +458,10 @@ static int ocores_i2c_probe(struct platform_device *pdev) i2c->reg_shift = pdata->reg_shift; i2c->reg_io_width = pdata->reg_io_width; i2c->ip_clock_khz = pdata->clock_khz; - i2c->bus_clock_khz = 100; + if (pdata->bus_khz) + i2c->bus_clock_khz = pdata->bus_khz; + else + i2c->bus_clock_khz = 100; } else { ret = ocores_i2c_of_probe(pdev, i2c); if (ret) diff --git a/include/linux/platform_data/i2c-ocores.h b/include/linux/platform_data/i2c-ocores.h index 113d6b12f650..f497ab8fe9f8 100644 --- a/include/linux/platform_data/i2c-ocores.h +++ b/include/linux/platform_data/i2c-ocores.h @@ -15,6 +15,7 @@ struct ocores_i2c_platform_data { u32 reg_shift; /* register offset shift value */ u32 reg_io_width; /* register io read/write width */ u32 clock_khz; /* input clock in kHz */ + u32 bus_khz; /* bus clock in kHz */ bool big_endian; /* registers are big endian */ u8 num_devices; /* number of devices in the devices list */ struct i2c_board_info const *devices; /* devices connected to the bus */ From patchwork Fri Jan 11 23:43:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Lunn X-Patchwork-Id: 1023812 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=lunn.ch Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=lunn.ch header.i=@lunn.ch header.b="dVIzbwdg"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43bzxn5FqPz9sBQ for ; Sat, 12 Jan 2019 10:45:17 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726224AbfAKXpR (ORCPT ); Fri, 11 Jan 2019 18:45:17 -0500 Received: from vps0.lunn.ch ([185.16.172.187]:40863 "EHLO vps0.lunn.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725794AbfAKXpR (ORCPT ); Fri, 11 Jan 2019 18:45:17 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lunn.ch; s=20171124; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=gscr8Zg26o4ajhfhMVvMpi7a9SCVSiyb7h1anTHs04I=; b=dVIzbwdgOcJRKApXw4Z3gjlCmAICZDr2eUhvErmV4RMzyn5xUgp7ylopP0uzkCX65hds9Tn5Z59ygHd2fs1HzCwW1xHM3kxdmInPX9IpDNHTsJINcSFeWLst76tYlpLbdSMzUQMVtc9sJllHGqdzUCRNH20cfMR8ahHMPfPVmoU=; Received: from andrew by vps0.lunn.ch with local (Exim 4.84_2) (envelope-from ) id 1gi6TD-0004Tv-OO; Sat, 12 Jan 2019 00:44:11 +0100 From: Andrew Lunn To: Peter Korsgaard Cc: Wolfram Sang , Lee Jones , linux-i2c@vger.kernel.org, Andrew Lunn Subject: [PATCH v2 resend 3/3] i2c: ocores: Add support for polling interrupt status Date: Sat, 12 Jan 2019 00:43:58 +0100 Message-Id: <1547250238-17181-4-git-send-email-andrew@lunn.ch> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1547250238-17181-1-git-send-email-andrew@lunn.ch> References: <1547250238-17181-1-git-send-email-andrew@lunn.ch> Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org Not all implementations of the OCORES i2c bus master support generating interrupts. Add support for polling the interrupt status bit when no interrupt is defined. Signed-off-by: Andrew Lunn --- drivers/i2c/busses/i2c-ocores.c | 64 ++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index d2730efe6bec..9576e842e557 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -40,10 +41,14 @@ struct ocores_i2c { struct clk *clk; int ip_clock_khz; int bus_clock_khz; + int flags; void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value); u8 (*getreg)(struct ocores_i2c *i2c, int reg); }; +/* flags */ +#define I2C_FLAG_NOIRQ BIT(0) + /* registers */ #define OCI2C_PRELOW 0 #define OCI2C_PREHIGH 1 @@ -224,6 +229,27 @@ static irqreturn_t ocores_isr(int irq, void *dev_id) return IRQ_HANDLED; } +static void ocores_poll_irq(struct ocores_i2c *i2c) +{ + int timeout = 500; + u8 stat; + + do { + /* delay 2-3 SCL (5-7usec for 400KHz) */ + usleep_range(5, 7); + stat = oc_getreg(i2c, OCI2C_STATUS); + } while ((stat & OCI2C_STAT_TIP) && timeout--); + + + if (!(stat & OCI2C_STAT_TIP)) { + ocores_process(i2c); + } else { + i2c->state = STATE_ERROR; + dev_dbg(&i2c->adap.dev, "Timeout while polling %02x\n", stat); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + } +} + static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { struct ocores_i2c *i2c = i2c_get_adapdata(adap); @@ -236,11 +262,18 @@ static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) oc_setreg(i2c, OCI2C_DATA, i2c_8bit_addr_from_msg(i2c->msg)); oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); - if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || - (i2c->state == STATE_DONE), HZ)) + if (i2c->flags & I2C_FLAG_NOIRQ) { + while (!((i2c->state == STATE_DONE) || + (i2c->state == STATE_ERROR))) + ocores_poll_irq(i2c); return (i2c->state == STATE_DONE) ? num : -EIO; - else - return -ETIMEDOUT; + } else { + if (wait_event_timeout(i2c->wait, + (i2c->state == STATE_ERROR) || + (i2c->state == STATE_DONE), HZ)) + return (i2c->state == STATE_DONE) ? num : -EIO; + } + return -ETIMEDOUT; } static int ocores_init(struct device *dev, struct ocores_i2c *i2c) @@ -425,14 +458,17 @@ static int ocores_i2c_probe(struct platform_device *pdev) int ret; int i; - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); if (!i2c) return -ENOMEM; + irq = platform_get_irq(pdev, 0); + if (irq == -ENXIO) + i2c->flags |= I2C_FLAG_NOIRQ; + else + if (irq < 0) + return irq; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res) { i2c->base = devm_ioremap_resource(&pdev->dev, res); @@ -504,11 +540,13 @@ static int ocores_i2c_probe(struct platform_device *pdev) goto err_clk; init_waitqueue_head(&i2c->wait); - ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0, - pdev->name, i2c); - if (ret) { - dev_err(&pdev->dev, "Cannot claim IRQ\n"); - goto err_clk; + if (!(i2c->flags & I2C_FLAG_NOIRQ)) { + ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0, + pdev->name, i2c); + if (ret) { + dev_err(&pdev->dev, "Cannot claim IRQ\n"); + goto err_clk; + } } /* hook up driver to tree */