Received: by 2002:a05:6358:d09b:b0:dc:cd0c:909e with SMTP id jc27csp1204569rwb; Wed, 16 Nov 2022 13:50:13 -0800 (PST) X-Google-Smtp-Source: AA0mqf55eg4xB313w9/ededjuGJWTv+OOKZxSalMnjDwnnOqGlLaV17CNd0FThxssyOAK2wqEfjI X-Received: by 2002:a17:902:db09:b0:187:feb:a787 with SMTP id m9-20020a170902db0900b001870feba787mr10523789plx.39.1668635412942; Wed, 16 Nov 2022 13:50:12 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668635412; cv=none; d=google.com; s=arc-20160816; b=Up/KoIH6afKLcnVb6IS4veVrOqRgphU5KBrg0GmZtuyermDYZ+YICEI3VM6DqnbZUD A+DqxtM//GzjRIlOFW2+9cZ98aN5971Pq6M4t0VSkTY2KQlSMpbZPj+vf8jRuNbf6mV6 Rr3OYleTmlDn4rSjsMnuvRZgKbrrHWvVkpHb2PL5AwTFgyxsGf/TKDsoRNeTbpELDjE8 Xgb/b75Xs+rl1NE7b6MNCbx0Vy/iz8RnkzLoeHNXSiSS2PS28NEN5q24ffGmFKSDI+3W BLwM5ijY3A4nMRvv2nC+UfGza1SA3Lfc5rRsIGFal895w3iqK5WkAVNWq0P7NTgWgw4/ g3Ig== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:user-agent:references:message-id :in-reply-to:subject:cc:to:from:date; bh=+/UNtP9k8Mya/QUJPvSSMHEOfEqJ/aYlKp4rFZyYZuU=; b=KY/be49RSsb8oJpheMP5OOIAPJ/7B7E7vvF8kmlKQuqDnCmZKAzSN0rJas1SPQDudY qSK9URyUEVBxSEbIKSPzM97Ra+1m037M8jdMFUH47Unv8xLCLcZojFw8hrJrBQ046b8Y Q40jytJxPQba0dlFB6p6mR+wHCCZPZhyqKcLupriL+O6vSA4FmE6oEyzGn26UPxdvkMN XiKfFGLUXL6JH27a1nsco9HXL0SqRf7MXs46D9t/gdQrIE1FvsAd/TFfbUF1r9yJDk7m HyVMzcvIOKFhBuoioQOPxhtxPYAwnQ8MbMD2MAbm56CTzmBx/ag3juzeQIBU0dJ9n3Ot FRcg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id a129-20020a636687000000b0046e96b98a68si15437718pgc.614.2022.11.16.13.50.00; Wed, 16 Nov 2022 13:50:12 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234310AbiKPVgL (ORCPT + 91 others); Wed, 16 Nov 2022 16:36:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41664 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234174AbiKPVgE (ORCPT ); Wed, 16 Nov 2022 16:36:04 -0500 Received: from angie.orcam.me.uk (angie.orcam.me.uk [IPv6:2001:4190:8020::34]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 65845FAF0 for ; Wed, 16 Nov 2022 13:36:02 -0800 (PST) Received: by angie.orcam.me.uk (Postfix, from userid 500) id C1D3F92009D; Wed, 16 Nov 2022 22:36:01 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id BBC7D92009C; Wed, 16 Nov 2022 21:36:01 +0000 (GMT) Date: Wed, 16 Nov 2022 21:36:01 +0000 (GMT) From: "Maciej W. Rozycki" To: Sudip Mukherjee cc: linux-kernel@vger.kernel.org Subject: [PATCH 3/6] parport_pc: Let chipset drivers mask ECR bits on writes In-Reply-To: Message-ID: References: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Provide an `ecr_writable' parameter to `__parport_pc_probe_port' so that callers can specify a mask of bits to modify on ECR writes. To avoid the need for separate bit set and bit clear masks always set bit 0 whenever a non-zero mask has been set, as all the currently known cases where a mask is required, that is Oxford Semiconductor devices, do require this bit to be set. If further cases are discovered where the bit is required to be clear, we can update code accordingly, but chances are very low as the bit is supposed to be read-only[1]. Skip ECR probing, which can be problematic as the Oxford Semiconductor OX12PCI840 part has been reported to lock up on setting bit 2, whenever a non-zero mask has been requested by a port subdriver, assuming that the ECR must be there if the subdriver has requested a specific way to access it. References: [1] "Extended Capabilities Port Protocol and ISA Interface Standard", Microsoft Corporation, Revision: 1.14, July 14, 1993, Table 14 "Extended Control Register" Signed-off-by: Maciej W. Rozycki --- drivers/parport/parport_pc.c | 46 +++++++++++++++++++++++++++---------------- include/linux/parport_pc.h | 3 ++ 2 files changed, 32 insertions(+), 17 deletions(-) linux-parport-pc-ecr-write.diff Index: linux-macro/drivers/parport/parport_pc.c =================================================================== --- linux-macro.orig/drivers/parport/parport_pc.c +++ linux-macro/drivers/parport/parport_pc.c @@ -106,15 +106,22 @@ static int pnp_registered_parport; static void frob_econtrol(struct parport *pb, unsigned char m, unsigned char v) { + const struct parport_pc_private *priv = pb->physport->private_data; + unsigned char ecr_writable = priv->ecr_writable; unsigned char ectr = 0; + unsigned char new; if (m != 0xff) ectr = inb(ECONTROL(pb)); - pr_debug("frob_econtrol(%02x,%02x): %02x -> %02x\n", - m, v, ectr, (ectr & ~m) ^ v); + new = (ectr & ~m) ^ v; + if (ecr_writable) + /* All known users of the ECR mask require bit 0 to be set. */ + new = (new & ecr_writable) | 1; - outb((ectr & ~m) ^ v, ECONTROL(pb)); + pr_debug("frob_econtrol(%02x,%02x): %02x -> %02x\n", m, v, ectr, new); + + outb(new, ECONTROL(pb)); } static inline void frob_set_mode(struct parport *p, int mode) @@ -1479,21 +1486,24 @@ static int parport_ECR_present(struct pa struct parport_pc_private *priv = pb->private_data; unsigned char r = 0xc; - outb(r, CONTROL(pb)); - if ((inb(ECONTROL(pb)) & 0x3) == (r & 0x3)) { - outb(r ^ 0x2, CONTROL(pb)); /* Toggle bit 1 */ + if (!priv->ecr_writable) { + outb(r, CONTROL(pb)); + if ((inb(ECONTROL(pb)) & 0x3) == (r & 0x3)) { + outb(r ^ 0x2, CONTROL(pb)); /* Toggle bit 1 */ - r = inb(CONTROL(pb)); - if ((inb(ECONTROL(pb)) & 0x2) == (r & 0x2)) - goto no_reg; /* Sure that no ECR register exists */ - } + r = inb(CONTROL(pb)); + if ((inb(ECONTROL(pb)) & 0x2) == (r & 0x2)) + /* Sure that no ECR register exists */ + goto no_reg; + } - if ((inb(ECONTROL(pb)) & 0x3) != 0x1) - goto no_reg; + if ((inb(ECONTROL(pb)) & 0x3) != 0x1) + goto no_reg; - ECR_WRITE(pb, 0x34); - if (inb(ECONTROL(pb)) != 0x35) - goto no_reg; + ECR_WRITE(pb, 0x34); + if (inb(ECONTROL(pb)) != 0x35) + goto no_reg; + } priv->ecr = 1; outb(0xc, CONTROL(pb)); @@ -2005,7 +2015,8 @@ static struct parport *__parport_pc_prob int irq, int dma, struct device *dev, int irqflags, - unsigned int mode_mask) + unsigned int mode_mask, + unsigned char ecr_writable) { struct parport_pc_private *priv; struct parport_operations *ops; @@ -2054,6 +2065,7 @@ static struct parport *__parport_pc_prob priv->ctr = 0xc; priv->ctr_writable = ~0x10; priv->ecr = 0; + priv->ecr_writable = ecr_writable; priv->fifo_depth = 0; priv->dma_buf = NULL; priv->dma_handle = 0; @@ -2256,7 +2268,7 @@ struct parport *parport_pc_probe_port(un int irqflags) { return __parport_pc_probe_port(base, base_hi, irq, dma, - dev, irqflags, 0); + dev, irqflags, 0, 0); } EXPORT_SYMBOL(parport_pc_probe_port); Index: linux-macro/include/linux/parport_pc.h =================================================================== --- linux-macro.orig/include/linux/parport_pc.h +++ linux-macro/include/linux/parport_pc.h @@ -26,6 +26,9 @@ struct parport_pc_private { /* Whether or not there's an ECR. */ int ecr; + /* Bitmask of writable ECR bits. */ + unsigned char ecr_writable; + /* Number of PWords that FIFO will hold. */ int fifo_depth;