Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932636AbbFRQT7 (ORCPT ); Thu, 18 Jun 2015 12:19:59 -0400 Received: from mail-bn1on0094.outbound.protection.outlook.com ([157.56.110.94]:20630 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751719AbbFRQTt (ORCPT ); Thu, 18 Jun 2015 12:19:49 -0400 Authentication-Results: spf=pass (sender IP is 149.199.60.100) smtp.mailfrom=xilinx.com; vger.kernel.org; dkim=none (message not signed) header.d=none; From: Anurag Kumar Vulisha To: , , , , , , , CC: , , , , , , , , Anurag Kumar Vulisha Subject: [PATCH] i2c: removed work arounds in i2c driver for Zynq Ultrascale+ MPSoC Date: Thu, 18 Jun 2015 21:49:42 +0530 Message-ID: <1434644382-11905-1-git-send-email-anuragku@xilinx.com> X-Mailer: git-send-email 1.7.4 X-RCIS-Action: ALLOW X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.0.0.1202-21620.005 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BL2FFO11FD038;1:dMRk9wSeIj5NQzAJmLnoeNWTT5/SOoYD23yiJAXS+LuEaNI3Dbm8/lhbPssBmOYNE7v0dpcj6kLIU/jCmvo/+Gy4GxXceJJAqDacgdyzGpT+tGYcf1jCJZjAXYRQC85kNNoMrhenk3lr3rnxsDciJo1lYooq6Rt71g8p3wOspqS/caND+pKa9TPNpmLbyyXebBHSRb+V9MGiX3ubJqpTqVwWVRrDfvg0v24ntDqG4MBXxIF0jSCsI5d0kZNuOGTb0SYXpCRVzBJbF9nP7SBz2Kwk6VcoGvs9SwqRwXZ9WuM3XLxoNkpuCH5EhtT5fgOul/MAzywhomRJJcz/fSCAJQ== X-Forefront-Antispam-Report: CIP:149.199.60.100;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(2980300002)(438002)(189002)(199003)(6806004)(50226001)(19580405001)(46386002)(92566002)(45336002)(47776003)(107886002)(36386004)(189998001)(33646002)(5001960100002)(42186005)(50986999)(5001770100001)(52956003)(87936001)(103686003)(48376002)(63266004)(19580395003)(86362001)(50466002)(575784001)(2201001)(46102003)(106466001)(229853001)(36756003)(77156002)(62966003)(107986001)(4001450100001)(5001870100001)(90966001)(4001430100001);DIR:OUT;SFP:1101;SCL:1;SRVR:BL2FFO11HUB031;H:xsj-pvapsmtpgw02;FPR:;SPF:Pass;MLV:ovrnspm;MX:1;A:1;PTR:xapps1.xilinx.com,unknown-60-100.xilinx.com;LANG:en; MIME-Version: 1.0 Content-Type: text/plain X-Microsoft-Exchange-Diagnostics: 1;BL2FFO11HUB031;2:LRzSgQvWnjKXwOOHE00V4AuJq4Zsl0E69efYBW+Z6JPWigSDzpkkIhpy53PoKY3I;2:JRShbFtwmOhOeelwowdi3eYzeq0ewfiutSzxIDmuObmKWVTF4RXrh2TjlxWz6Aa60pXYLxAKhA+P/otvgNM7uv+Hk8EUCckegG6kH2Bnnuw4zrlTWfaLueKIC9YUgji1qIn+ZqUszl0TG+kNPMKOzec1P3VZ3c8dshHPnkqlMtT8heITo1Ai+BhQmqNyMnDJdZlTbrn3kIPwjyNVXLi9lTUrtMIVCSCox3txDZ6jqRDk0e/6eU99xgwjUw+I39Sv;6:slmNgLPUl8AFosIDyjfzQirZt2XE3SBDLG73p3p18Xc8W1n7R1isACUdb+gRqGH4bhG+3Z8NDTJgpdz9M8l5SphtbNK6rzo13oISYEAK3a3sADOvuDD5gwk6qwLtpi+kiYNGuPKzRR2nU9oDse39kFfUSO5WJXD1+K/vgufw38gDGQEeIfUgXZ+aUv2orNPxeyzgZGrRRcVgXvLNejpYMFkXgZFIVoZ3gZojIoPXRpFXqR6WHg32C0dwtPP2IIceC431sBanZRxg2R0lCjCrzHP/icfIA0H+/926zkqU8SEuJgkFnjqnLu3oWqRkLkuHUjXqK/LCuc5hv79eHI9HPI8ld8ESLIZ4kecOFBylAnb5DypuN7zZS4dMngMkomqcio19TM+d4MFmGhY3hCHU6y6H5mMG1EUvZEpjWQHW3fBlNrLqrmyaJtayJn8DbJb3h+8tDbbOQeWGPSRLRxaYFlbORyLZcSmpCusYAjlbhSnMbGh0WF/6iH8cNZ5haFdm X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BL2FFO11HUB031; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(520003)(5005006)(3002001);SRVR:BL2FFO11HUB031;BCL:0;PCL:0;RULEID:;SRVR:BL2FFO11HUB031; X-Microsoft-Exchange-Diagnostics: 1;BL2FFO11HUB031;3:86RhusQMDDz5mYllLqgOmctdwNg3FvV6rmwhtIxhGumPtqHvzA+xornKKC3/GPeWD7e/cA9DFF0mDaYJnbsCLj7anR3kMHZVOr1sSLobljZfT/E2FuuwzJLUTgJsaG0WSjo5k/moJ8i4D5PuweBTzU2GeIRFTUg9xUR9eb1UzbFJK6mES1tnl5IxZYgBeo7mAxqYwMBSsFfWQKrZj6zIS5UCQND2gt0nBF7judHx5SQfZihlWliyx2dj47PECeUGYXl4JPMaJ/aSQYHPYDhoIwMUJG1had9Q/1EB3uaJMAdSJvr0CR8UIIsoZDzVqksE X-Forefront-PRVS: 0611A21987 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BL2FFO11HUB031;9:o5jl1yGP1G8GZ2j8fmjW7eJGiBEkQoAR5xuvHvDB8?= =?us-ascii?Q?xcVMP2q/THBd32Ci4VKraoxwf53jGYt3AoLeJfSbdTYGSPh3/etrQNgq+8qZ?= =?us-ascii?Q?hRHte1iLE40S/5jcvraTBBg5eCmoRCkXAbISljOFy6ohtk/QcWPJmmGNz60Q?= =?us-ascii?Q?GWiSC8DWtmVLz2U+3rR4DVZwWI7H+wcIglu4tMP3ObB5WrSPQCh5vsmcAYBD?= =?us-ascii?Q?swD+bDLXAE+NEeKfdaE1YA/Va8xAfD2zg+YKLdhUIA1YWsoJ+zKJfQCRotR1?= =?us-ascii?Q?khrSOJSYG2vy0/qpmUyH6zBAMpsoXXcVg0FC9EZuxoC23bhEuqHMZHFdnQPe?= =?us-ascii?Q?y39MzzYSdaaRLYf1jiUyvOzgRxsbDEZI1gaLt5OWfdmkOXjM8PGbbKTk5Z0U?= =?us-ascii?Q?vylioTrKBpnzfk0zvvns7N15Jb8KJwAWnSH68BHH0sSB/qJkw0QBySsVNgr2?= =?us-ascii?Q?jpTvSWTtG7vAdrrn1p+K/LgaShVE0zYD+T195lnPf0JLXeB9KUMI1bu1gafQ?= =?us-ascii?Q?/M6YZXy3NMOyFSxwkb7RLrsaJ0kpqZDP7qNMqt+a9VM/Ab2axE4iAR0qEtgP?= =?us-ascii?Q?k3/FWt+1DET6SLGnJhMc2jVq/OeKVomSwwiFf/jXCi5OjF2w0PF4b9QlJi+m?= =?us-ascii?Q?VYv6WgYGwBrUJLpUw1zNcpT5+Bc85FE/f8yBKnXmPWyDJp+L3ncCH1vShmex?= =?us-ascii?Q?NP6Dz60ij5XLL8atV6zR+83rnv3la7ie94T/u1KRK883tUagsV0wh0nar4wR?= =?us-ascii?Q?B+vdpwy2IrjKIGqdXtq+cse0qgJ33DXXxAb/J9Ch4c0iGTNDS7F5OFBxdMbt?= =?us-ascii?Q?3YJN9aj5RfB+GbHIxaYjszfvfQqV1rG47xYNU29PHzSHIKobt3Dng0LXsqb1?= =?us-ascii?Q?nGjkFUuHM6XihFvcl5c8r2sFv/90fKS/WXCgZZ8M3u9n9m5cFvKfgybNUju+?= =?us-ascii?Q?cM9EatIyhusn11Zz2ruFM4L9rGYlnfQb+9m5GW+1WF0cEdejDPRJ/Fy8370e?= =?us-ascii?Q?B3dKllwP9zJV+3qKUfbhEJ8uW4z3dWfamUNYLrnPiZUK2UjGHeTaZcrdTN8x?= =?us-ascii?Q?Vl4ugWC4qjKn/zUwbowOCHqMbSb?= X-Microsoft-Exchange-Diagnostics: 1;BL2FFO11HUB031;3:LwsZE2EzAUeGPdsIvglnNHKVPMsssVmVS0CdViaWrXByNvwjXnbfdMcUsatG4FtjjqNqDOCJvPQrswg/qTLfjKSs7Q0Y6XrCGGnYgWAZu1vgx2OWW1XddghKHflOUzlNVSoUWlIjmGnfYYb0hAEuzQ==;10:C70lht/ug1STHkM4LDi7nQDNYgFnFZ4RnJLZS3akOhuTMSiK17jPIR2M6sKChQ339UFjbd5sL7XJC1tIGveLZYM3k8kGfBnS7FLNrEOPM9A= X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Jun 2015 16:19:47.1908 (UTC) X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c;Ip=[149.199.60.100];Helo=[xsj-pvapsmtpgw02] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL2FFO11HUB031 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7689 Lines: 218 Removed the workarounds present in the cadence i2c driver for Zynq Ultrascale+ MPSoC Signed-off-by: Anurag Kumar Vulisha --- .../devicetree/bindings/i2c/i2c-cadence.txt | 2 +- drivers/i2c/busses/i2c-cadence.c | 67 ++++++++++++++++--- 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-cadence.txt b/Documentation/devicetree/bindings/i2c/i2c-cadence.txt index 7cb0b56..11ef7f2 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-cadence.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-cadence.txt @@ -2,7 +2,7 @@ Binding for the Cadence I2C controller Required properties: - reg: Physical base address and size of the controller's register area. - - compatible: Compatibility string. Must be 'cdns,i2c-r1p10'. + - compatible: Compatibility string.Use 'cdns,i2c-r1p10' or 'cdns,i2c-r1p14' - clocks: Input clock specifier. Refer to common clock bindings. - interrupts: Interrupt specifier. Refer to interrupt bindings. - #address-cells: Should be 1. diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 2ee78e0..6ad1571 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -17,6 +17,7 @@ #include #include #include +#include /* Register offsets for the I2C device. */ #define CDNS_I2C_CR_OFFSET 0x00 /* Control Register, RW */ @@ -113,6 +114,8 @@ #define CDNS_I2C_TIMEOUT_MAX 0xFF +#define CDNS_I2C_BROKEN_HOLD_BIT 0x00000001 + #define cdns_i2c_readreg(offset) readl_relaxed(id->membase + offset) #define cdns_i2c_writereg(val, offset) writel_relaxed(val, id->membase + offset) @@ -135,6 +138,7 @@ * @bus_hold_flag: Flag used in repeated start for clearing HOLD bit * @clk: Pointer to struct clk * @clk_rate_change_nb: Notifier block for clock rate changes + * @quirks: flag for broken hold bit usage in r1p10 */ struct cdns_i2c { void __iomem *membase; @@ -154,6 +158,11 @@ struct cdns_i2c { unsigned int bus_hold_flag; struct clk *clk; struct notifier_block clk_rate_change_nb; + u32 quirks; +}; + +struct cdns_platform_data { + u32 quirks; }; #define to_cdns_i2c(_nb) container_of(_nb, struct cdns_i2c, \ @@ -172,6 +181,12 @@ static void cdns_i2c_clear_bus_hold(struct cdns_i2c *id) cdns_i2c_writereg(reg & ~CDNS_I2C_CR_HOLD, CDNS_I2C_CR_OFFSET); } +static inline bool cdns_is_holdquirk(struct cdns_i2c *id, bool hold_wrkaround) +{ + return (hold_wrkaround && + (id->curr_recv_count == CDNS_I2C_FIFO_DEPTH + 1)); +} + /** * cdns_i2c_isr - Interrupt handler for the I2C device * @irq: irq number for the I2C device @@ -186,6 +201,7 @@ static irqreturn_t cdns_i2c_isr(int irq, void *ptr) { unsigned int isr_status, avail_bytes, updatetx; unsigned int bytes_to_send; + bool hold_quirk; struct cdns_i2c *id = ptr; /* Signal completion only after everything is updated */ int done_flag = 0; @@ -208,6 +224,8 @@ static irqreturn_t cdns_i2c_isr(int irq, void *ptr) if (id->recv_count > id->curr_recv_count) updatetx = 1; + hold_quirk = (id->quirks & CDNS_I2C_BROKEN_HOLD_BIT) && updatetx; + /* When receiving, handle data interrupt and completion interrupt */ if (id->p_recv_buf && ((isr_status & CDNS_I2C_IXR_COMP) || @@ -229,8 +247,7 @@ static irqreturn_t cdns_i2c_isr(int irq, void *ptr) id->recv_count--; id->curr_recv_count--; - if (updatetx && - (id->curr_recv_count == CDNS_I2C_FIFO_DEPTH + 1)) + if (cdns_is_holdquirk(id, hold_quirk)) break; } @@ -241,8 +258,7 @@ static irqreturn_t cdns_i2c_isr(int irq, void *ptr) * maintain transfer size non-zero while performing a large * receive operation. */ - if (updatetx && - (id->curr_recv_count == CDNS_I2C_FIFO_DEPTH + 1)) { + if (cdns_is_holdquirk(id, hold_quirk)) { /* wait while fifo is full */ while (cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET) != (id->curr_recv_count - CDNS_I2C_FIFO_DEPTH)) @@ -264,6 +280,22 @@ static irqreturn_t cdns_i2c_isr(int irq, void *ptr) CDNS_I2C_XFER_SIZE_OFFSET); id->curr_recv_count = id->recv_count; } + } else if (id->recv_count && !hold_quirk && + !id->curr_recv_count) { + + /* Set the slave address in address register*/ + cdns_i2c_writereg(id->p_msg->addr & CDNS_I2C_ADDR_MASK, + CDNS_I2C_ADDR_OFFSET); + + if (id->recv_count > CDNS_I2C_TRANSFER_SIZE) { + cdns_i2c_writereg(CDNS_I2C_TRANSFER_SIZE, + CDNS_I2C_XFER_SIZE_OFFSET); + id->curr_recv_count = CDNS_I2C_TRANSFER_SIZE; + } else { + cdns_i2c_writereg(id->recv_count, + CDNS_I2C_XFER_SIZE_OFFSET); + id->curr_recv_count = id->recv_count; + } } /* Clear hold (if not repeated start) and signal completion */ @@ -535,11 +567,13 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int ret, count; u32 reg; struct cdns_i2c *id = adap->algo_data; + bool hold_quirk; /* Check if the bus is free */ if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA) return -EAGAIN; + hold_quirk = !!(id->quirks & CDNS_I2C_BROKEN_HOLD_BIT); /* * Set the flag to one when multiple messages are to be * processed with a repeated start. @@ -552,7 +586,7 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, * followed by any other message, an error is returned * indicating that this sequence is not supported. */ - for (count = 0; count < num - 1; count++) { + for (count = 0; (count < num - 1 && hold_quirk); count++) { if (msgs[count].flags & I2C_M_RD) { dev_warn(adap->dev.parent, "Can't do repeated start after a receive message\n"); @@ -815,6 +849,16 @@ static int __maybe_unused cdns_i2c_resume(struct device *_dev) static SIMPLE_DEV_PM_OPS(cdns_i2c_dev_pm_ops, cdns_i2c_suspend, cdns_i2c_resume); +static const struct cdns_platform_data r1p10_i2c_def = { + .quirks = CDNS_I2C_BROKEN_HOLD_BIT, }; + +static const struct of_device_id cdns_i2c_of_match[] = { + { .compatible = "cdns,i2c-r1p10", .data = &r1p10_i2c_def }, + { .compatible = "cdns,i2c-r1p14",}, + { /* end of table */ } +}; +MODULE_DEVICE_TABLE(of, cdns_i2c_of_match); + /** * cdns_i2c_probe - Platform registration call * @pdev: Handle to the platform device structure @@ -830,6 +874,7 @@ static int cdns_i2c_probe(struct platform_device *pdev) struct resource *r_mem; struct cdns_i2c *id; int ret; + const struct of_device_id *match; id = devm_kzalloc(&pdev->dev, sizeof(*id), GFP_KERNEL); if (!id) @@ -837,6 +882,12 @@ static int cdns_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, id); + match = of_match_node(cdns_i2c_of_match, pdev->dev.of_node); + if (match && match->data) { + const struct cdns_platform_data *data = match->data; + id->quirks = data->quirks; + } + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); id->membase = devm_ioremap_resource(&pdev->dev, r_mem); if (IS_ERR(id->membase)) @@ -935,12 +986,6 @@ static int cdns_i2c_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id cdns_i2c_of_match[] = { - { .compatible = "cdns,i2c-r1p10", }, - { /* end of table */ } -}; -MODULE_DEVICE_TABLE(of, cdns_i2c_of_match); - static struct platform_driver cdns_i2c_drv = { .driver = { .name = DRIVER_NAME, -- 1.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/