Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932520AbbGJOzO (ORCPT ); Fri, 10 Jul 2015 10:55:14 -0400 Received: from mail-bn1on0084.outbound.protection.outlook.com ([157.56.110.84]:33696 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932177AbbGJOzI (ORCPT ); Fri, 10 Jul 2015 10:55:08 -0400 Authentication-Results: spf=pass (sender IP is 149.199.60.83) smtp.mailfrom=xilinx.com; vger.kernel.org; dkim=none (message not signed) header.d=none; From: Anurag Kumar Vulisha To: wsa@the-dreams.de, robh+dt@kernel.org, pawel.moll@arm.com, mark.rutland@arm.com, ijc+devicetree@hellion.org.uk, galak@codeaurora.org, michal.simek@xilinx.com, soren.brinkmann@xilinx.com CC: linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, harinik@xilinx.com, punnaia@xilinx.com, svemula@xilinx.com, anirudh@xilinx.com, Anurag Kumar Vulisha Subject: [PATCH v2] i2c: removed work arounds in i2c driver for Zynq Ultrascale+ MPSoC Date: Fri, 10 Jul 2015 20:10:14 +0530 Message-ID: <1436539214-21536-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-21668.005 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BN1BFFO11FD007;1:vAwlka695t51eFPViPz4P6kc3uEhDzFDvVxnSA4HtKg1j0dnYYfR35/9vuDDN3ngb+aPkd3O95W0F7QTDgWDwwxg8X6B/JPj9fep3WLkgN7BTj7Fe4/Dnn2bb0GetgMCppzfcKoCdUhxzIKa0rqNW0zRl9giORe5biNkon4bVCmpE9A5goZUYXZdI2WVM/GQPg7X7MZvt8s5cN50lCg8D2e+BBcrxgRRVHvyfpuyqUoBnvUwKDlR4FTFfDcYwiY41XajhRgHMahHZWfKXqvrZcptBHkZepQ9VEJ+4Iw4S+wpoTEN9hdpvlxIaw54+h3FSnma/OUgChnGzK4W48Mi+XID9bD5O4tVIYYw2RxHh/zZBLJQpLZevfCOFnpXSks5fg66GDZfYaLHApZnD2eHe5dX7P4V8dBBYIZbIcnntBQ= X-Forefront-Antispam-Report: CIP:149.199.60.83;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(2980300002)(438002)(199003)(189002)(36386004)(47776003)(50986999)(50466002)(575784001)(52956003)(86362001)(106466001)(62966003)(77156002)(46102003)(5001960100002)(110136002)(36756003)(92566002)(50226001)(5003940100001)(107886002)(103686003)(45336002)(42186005)(229853001)(63266004)(6806004)(19580405001)(19580395003)(46386002)(33646002)(48376002)(189998001)(87936001)(107986001)(4001450100001)(4001430100001)(90966001);DIR:OUT;SFP:1101;SCL:1;SRVR:BN1BFFO11HUB050;H:xsj-pvapsmtpgw01;FPR:;SPF:Pass;MLV:sfv;A:1;MX:1;LANG:en; MIME-Version: 1.0 Content-Type: text/plain X-Microsoft-Exchange-Diagnostics: 1;BN1BFFO11HUB050;2:QSQzKKUWrQfgFHjJiV+QD2vGIjFS/kSE6CKgrs52nfEUY11BpsYiCvNXFxtVAyTk;3:mrh0AsmNs0wzB3V/iKy783WgYZ7S6S1jlJSApUG0TH5R2EEJHRcoA+3K6HxMWAXbZN4f1eHjQmithhD0gIHnhamxgiCHk/bq0OgUbO+e/+1HfP0pu5OU6VQsJceoRovWQ2rnGQO03XW7cGF4Sn0TyRbAth03vvIHcDKLPQxPbjMHVyxjcPOAfsD9C53lutjrrmczZvOuNKMIkZKQCeVRfOYN7+Hdr+kUoGT7nF23zRE=;20:/gLzjuTR9FcrXgHy6MWCDugvAcH/NcnvQFLsG4u37GPxWt+OUAW5dQzoG4ZEnLbFqy6HjMI4Mrbtlzzqn4vtL3wju5+zm0NTkwyjcCbszXBWw8BfsPMjgTceBjFtkSwzbkk4eNyBEk5wl0aNPU5GjzpNCtCKeOof+BVjm8zqmU9j21w99ZCbptfkbO50dpzj2UKxt9Y0aGuqf81WlsXwhHAQonx23CYOWcgvsH6St475dzIbquDXoki1qGAwYyCgoiSvj+fLR+Pkt0UkATEqpYAYQx5Sgm1Xqpmeam7YYoZx5+5PuFRM4+jlTNhQJHCEqVPJwemWITFQxTv7CLF2FJ6F7+m+e9TUScOyJw+TaTZpjbVV0L25bM4GLhHaICL2nkBJHwh17aNBusvkGaOaSUOnNAenbipyzAJ04AvobWTNjDXVyHuCdhEDXmVUF4R+rTOhRGS8rXYdGfYqMKeISZXd95P7ZKW4gPwSdqgx4gQQdKEry31Evzqvz9khEgY1 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN1BFFO11HUB050; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(5005006)(3002001);SRVR:BN1BFFO11HUB050;BCL:0;PCL:0;RULEID:;SRVR:BN1BFFO11HUB050; X-Microsoft-Exchange-Diagnostics: 1;BN1BFFO11HUB050;4:vFb5XSTCgCiiTi7Koi1o4pmfsyIHiwQ9NQqOf6MXLAZAGCels57Pc/xoEcBulScvQiXJkPOVaPuxIjh185jdOb4u9sTYKcrSbGghX+3eNO/l9P1q8lwQzvfpoCpXGznMo5flurMxZvmKdj1WLxTT5rnKml7SwwOeW+BbXC+QbHIhHHMSzCYzFNMwg/rrRYBM0pqcTh9p+yLUAfoSnT6VjV/2JiMt6BXUyfN9d4tXo/E0tEu/B7dnK2DD6yLx9R5h74y+8COfkE47yvpMrXU7YoOspOd5t9gTTlbTXErR3VI= X-Forefront-PRVS: 06339BAE63 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BN1BFFO11HUB050;23:aYuLDBVI//UE/Y+I8Mblui9PF6fEhFtHEz9gJdK?= =?us-ascii?Q?l870rbdbEphW/ma6DT0yaqy4MJPbkwg11aG0iUMRhSfxMBHVhlbVN7mJLyYR?= =?us-ascii?Q?d9YJiRVyvrsEiZx98mV4ldmnocZik6YO8eaeGrkTlByAEysDGtTl7P3PNrso?= =?us-ascii?Q?m6hd4ZwZ64jDJff3FUIiC4Bcb5v5g8fwbSwjiwfBXX9rouvloYXk6hDNeAqK?= =?us-ascii?Q?ZftnNt42rkHEa3VcY0ZNOahKlnJoU4L4OYjl3fuSGqbTRxOhar3SwPOokfJ7?= =?us-ascii?Q?AQasPTJnMuvm32dF3R35gkt7HwPyNYKwiRmgYqbJV14J1e8YL2ioQyKPGNsp?= =?us-ascii?Q?z5nXvg2RcaD1+WHW6tiMIhy7k0tOqSA0RodQeGdWpYIrmXxs8YP9Z/+9osav?= =?us-ascii?Q?kHl4MefC8beL+xljld9qgzRPVZh4OX6qplYuPTizMpfW+dLDvvp7FlguzgWv?= =?us-ascii?Q?MO8FajkaSzXz9SUAdcrHxwl9bEm9RZZBjjk14MQS/YMsjIiM0+Jd4dnueGqx?= =?us-ascii?Q?9jTzTbzHBI8YUI7Xf0UIjs4rOz2yoKhGosMV6Yldr/8/I7f6e8rA9AXjklV2?= =?us-ascii?Q?/mSg2nJAPhCAqakYDWFlco9vR4H8lqYdNy/4MWSps9ujhh88Dl2xDIH57dFC?= =?us-ascii?Q?gyOgjchGt3f37QCM2HTaNiC2uR8sWsjlrrwFBiVNsEceZOaPMtTIMKsT1v15?= =?us-ascii?Q?IZczARU3yEbTgz7LSbWunjCm57LVYFtn9vOErnpEbra58u/hBV2i03bG2BXs?= =?us-ascii?Q?lEP3/QGGRDzABPbu+CgOy3TUO8mUdNLbQ0tp11p60waYjqxwqwm4+N7+BL5N?= =?us-ascii?Q?WX25Ug0O4AxNcs/lHmwd2G2eMwoKUNzrnPm34on3Ao0bb6ATjZ9/U7/vA2FZ?= =?us-ascii?Q?xKj92IrgLUamKwjw/DzJeqKzz71U0mXbGI3+nIN7gk9/3IC6kmzApRDfl3GS?= =?us-ascii?Q?1KQVZIvjQJQqE3UnXKV6AcSumyt49QhvV6SAldUi01l+1Lxn8C7DB3Plv9ii?= =?us-ascii?Q?qk4QWETzB3oTXl6wB2jxOr/sIuf3KuCbrDImlmGrl9B2GEt3CeSCxPsTKexk?= =?us-ascii?Q?luMZXqOs=3D?= X-Microsoft-Exchange-Diagnostics: 1;BN1BFFO11HUB050;5:L9PNqGOKpf93Nmqkmle5Q0uCzEEg9E3NXuTd48z2WUIDN6+o04E5rbtHmKJ/RD8y/oxEy4kfLoDAYYhcwDvZbJ30a9pifgRuyVJzr9TnOzYqPLcakjTdLBUYEZlKAf6iUWtdKWjP3JXzSqUxuY12gQ==;24:iTEWVtCDHkRfeul0BZJwU6AfvNrnUR88lI6DhtOCP3ZznkGtQKeg0gAcBIaQZpuo7IrBX1nDBwn+lpQe3tnhROC+FpzZBOy7+DdhjaW5P78= X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 Jul 2015 14:40:29.9437 (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.83];Helo=[xsj-pvapsmtpgw01] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN1BFFO11HUB050 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 8120 Lines: 228 Cadence 1.0 version has bugs which have been fixed in the cadence 1.4 version. This patch removes the quirks present in the driver for cadence 1.4 version. Signed-off-by: Anurag Kumar Vulisha --- Changes in v2: 1.Changed the commit message. 2.Changed the compatible string description in devicetree binding Documentation. 3.Used BIT(0) in macro and moved "};" to next line in r1p10_i2c_def platform data. --- .../devicetree/bindings/i2c/i2c-cadence.txt | 6 ++- drivers/i2c/busses/i2c-cadence.c | 68 ++++++++++++++++--- 2 files changed, 62 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-cadence.txt b/Documentation/devicetree/bindings/i2c/i2c-cadence.txt index 7cb0b56..ebaa90c 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-cadence.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-cadence.txt @@ -2,7 +2,11 @@ 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: Should contain one of: + * "cdns,i2c-r1p10" + Note: Use this when cadence i2c controller version 1.0 is used. + * "cdns,i2c-r1p14" + Note: Use this when cadence i2c controller version 1.4 is used. - 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..5df288b 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 BIT(0) + #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,17 @@ 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 +875,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 +883,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 +987,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/