From patchwork Mon Nov 9 17:31:21 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Krzysztof Halasa X-Patchwork-Id: 38014 X-Patchwork-Delegate: davem@davemloft.net 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.176.167]) by ozlabs.org (Postfix) with ESMTP id 09E2FB7B68 for ; Tue, 10 Nov 2009 10:53:22 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750954AbZKIRbT (ORCPT ); Mon, 9 Nov 2009 12:31:19 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1750912AbZKIRbT (ORCPT ); Mon, 9 Nov 2009 12:31:19 -0500 Received: from khc.piap.pl ([195.187.100.11]:36241 "EHLO khc.piap.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750749AbZKIRbR (ORCPT ); Mon, 9 Nov 2009 12:31:17 -0500 Received: from intrepid.localdomain (intrepid.localdomain [10.0.0.2]) by khc.piap.pl (Postfix) with ESMTP id AC3019320; Mon, 9 Nov 2009 18:31:21 +0100 (CET) From: Krzysztof Halasa To: linux-ide@vger.kernel.org, lkml Subject: SATA_SIL on IXP425 workaround Date: Mon, 09 Nov 2009 18:31:21 +0100 Message-ID: MIME-Version: 1.0 Sender: linux-ide-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ide@vger.kernel.org I'm trying to add a workaround for IXP4xx CPUs to SATA SIL driver. The problem is that IXP4xx CPUs (Intel's XScale (ARM) network-oriented processors) are unable to perform 8 and 16-bit read from PCI MMIO, they can only do a full 32-bit readl(); SIL chips respond to that with PCI abort. The workaround is to use 8 and 16-bit regular IO reads (inb/inw) instead (MMIO write is not a problem). For SIL3x12 the workaround is simple (attached) and it works on my 3512. I'm not sure about 3114 (the 4-port chip) - the PIO BARs have TF, CTL and BWDMA registers which are common to channels 0 and 2, and (the other set) to channels 1 and 3. Channel selection is done with bit 4 of device/head TF register, this is similar (same?) as PATA master/slave. Does that mean that I can simply treat channel 0 as PRI master, ch#2 as PRI slave, ch#1 as SEC master and ch#3 as SEC slave, and the SFF code will select the right device correctly? Does it need additional code? I don't have anything based on 3114. Note: the large PRD is not a problem here, the transfer can be started by MMIO write. Only reads are an issue. --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -757,7 +757,12 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) return rc; +#ifdef CONFIG_ARCH_IXP4XX + /* We need all 6 regions on IXP4xx */ + rc = pcim_iomap_regions(pdev, 0x3F, DRV_NAME); +#else rc = pcim_iomap_regions(pdev, 1 << SIL_MMIO_BAR, DRV_NAME); +#endif if (rc == -EBUSY) pcim_pin_device(pdev); if (rc) @@ -777,10 +782,18 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) struct ata_port *ap = host->ports[i]; struct ata_ioports *ioaddr = &ap->ioaddr; +#ifdef CONFIG_ARCH_IXP4XX + /* IXP4xx CPUs can't perform 8 and 16-bit MMIO reads, + use normal IO from/to regions 0-5 instead */ + ioaddr->cmd_addr = host->iomap[i * 2]; + ioaddr->altstatus_addr = host->iomap[1 + i * 2] + 2; + ioaddr->bmdma_addr = host->iomap[4] + sil_port[i].bmdma; +#else ioaddr->cmd_addr = mmio_base + sil_port[i].tf; - ioaddr->altstatus_addr = - ioaddr->ctl_addr = mmio_base + sil_port[i].ctl; + ioaddr->altstatus_addr = mmio_base + sil_port[i].ctl; ioaddr->bmdma_addr = mmio_base + sil_port[i].bmdma; +#endif + ioaddr->ctl_addr = mmio_base + sil_port[i].ctl; ioaddr->scr_addr = mmio_base + sil_port[i].scr; ata_sff_std_ports(ioaddr);