From patchwork Wed Sep 23 06:35:03 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Filippov X-Patchwork-Id: 521593 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 60574140187 for ; Wed, 23 Sep 2015 16:35:33 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=f5RnDvbb; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751985AbbIWGfb (ORCPT ); Wed, 23 Sep 2015 02:35:31 -0400 Received: from mail-la0-f47.google.com ([209.85.215.47]:34389 "EHLO mail-la0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751823AbbIWGfa (ORCPT ); Wed, 23 Sep 2015 02:35:30 -0400 Received: by lahg1 with SMTP id g1so38809647lah.1; Tue, 22 Sep 2015 23:35:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=XlB2BLVANrhXT8kkL5PvqFcCSjSJaJ+yqt/vxpt/PJQ=; b=f5RnDvbbucMxz/xE8mI84P5QGGpvR7P+rLQ0ZomnGlqYwxfkDYqIKW8GxlZqItqC/Q 1m+G4i6iUufoWUxUKIq2K79A6XmUMlXB4J5a8mGgpMlJMRnMbA+HCcfnFOdAh92QawFn X80sLof5hMfMZ4TxV/CDbuf/0/P7bFwo3SAE/Ret9kSAvlaFBmYh/lmKDyYjeI05UdWb 9EqAN152fvqiBWHpWpUHjs+BSriqMnVdWcB9DYH5Al9x3zStI2gTphzbJ7Kqr3jbwJ/6 sd3ub9v9N7xxW9INvURtBGtC4/wdYFqDArSfct5Bg4mxbhzK1dcdSsxabpB1HToWkpny Bplg== X-Received: by 10.25.38.132 with SMTP id m126mr3472983lfm.20.1442990128309; Tue, 22 Sep 2015 23:35:28 -0700 (PDT) Received: from octofox.metropolis ([5.19.183.212]) by smtp.gmail.com with ESMTPSA id z204sm428820lfd.1.2015.09.22.23.35.27 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 22 Sep 2015 23:35:27 -0700 (PDT) From: Max Filippov To: linux-i2c@vger.kernel.org Cc: Peter Korsgaard , Wolfram Sang , linux-kernel@vger.kernel.org, Max Filippov Subject: [PATCH v2] i2c-ocores: support big-endian register layout Date: Wed, 23 Sep 2015 09:35:03 +0300 Message-Id: <1442990103-13456-1-git-send-email-jcmvbkbc@gmail.com> X-Mailer: git-send-email 1.8.1.4 Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org This allows using OpenCores I2C controller attached to its host in native-endian mode with bi-endian CPUs. Example of such system is Xtensa XTFPGA platform. Signed-off-by: Max Filippov Acked-by: Peter Korsgaard --- Changes v1->v2: - expand changelog with motivation for the change. drivers/i2c/busses/i2c-ocores.c | 31 +++++++++++++++++++++++++++---- include/linux/i2c-ocores.h | 1 + 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index abf5db7..11b7b87 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -92,6 +92,16 @@ static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value) iowrite32(value, i2c->base + (reg << i2c->reg_shift)); } +static void oc_setreg_16be(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite16be(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_32be(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite32be(value, i2c->base + (reg << i2c->reg_shift)); +} + static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg) { return ioread8(i2c->base + (reg << i2c->reg_shift)); @@ -107,6 +117,16 @@ static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg) return ioread32(i2c->base + (reg << i2c->reg_shift)); } +static inline u8 oc_getreg_16be(struct ocores_i2c *i2c, int reg) +{ + return ioread16be(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_32be(struct ocores_i2c *i2c, int reg) +{ + return ioread32be(i2c->base + (reg << i2c->reg_shift)); +} + static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) { i2c->setreg(i2c, reg, value); @@ -428,6 +448,9 @@ static int ocores_i2c_probe(struct platform_device *pdev) i2c->reg_io_width = 1; /* Set to default value */ if (!i2c->setreg || !i2c->getreg) { + bool be = pdata ? pdata->big_endian : + of_device_is_big_endian(pdev->dev.of_node); + switch (i2c->reg_io_width) { case 1: i2c->setreg = oc_setreg_8; @@ -435,13 +458,13 @@ static int ocores_i2c_probe(struct platform_device *pdev) break; case 2: - i2c->setreg = oc_setreg_16; - i2c->getreg = oc_getreg_16; + i2c->setreg = be ? oc_setreg_16be : oc_setreg_16; + i2c->getreg = be ? oc_getreg_16be : oc_getreg_16; break; case 4: - i2c->setreg = oc_setreg_32; - i2c->getreg = oc_getreg_32; + i2c->setreg = be ? oc_setreg_32be : oc_setreg_32; + i2c->getreg = be ? oc_getreg_32be : oc_getreg_32; break; default: diff --git a/include/linux/i2c-ocores.h b/include/linux/i2c-ocores.h index 1c06b5c..01edd96 100644 --- a/include/linux/i2c-ocores.h +++ b/include/linux/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 */ + 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 */ };