From patchwork Sat Feb 2 16:06:02 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gabor Juhos X-Patchwork-Id: 217685 X-Patchwork-Delegate: daniel.schwierzeck@googlemail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 5BFC62C0087 for ; Sun, 3 Feb 2013 03:07:06 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id DA6994A158; Sat, 2 Feb 2013 17:06:53 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 13ilocu0tbUS; Sat, 2 Feb 2013 17:06:53 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id D5D944A130; Sat, 2 Feb 2013 17:06:23 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 73E3B4A116 for ; Sat, 2 Feb 2013 17:06:18 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 5ppMa-Plaoum for ; Sat, 2 Feb 2013 17:06:17 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from arrakis.dune.hu (arrakis.dune.hu [78.24.191.176]) by theia.denx.de (Postfix) with ESMTPS id DBEA14A0ED for ; Sat, 2 Feb 2013 17:06:16 +0100 (CET) Received: from arrakis.dune.hu ([127.0.0.1]) by localhost (arrakis.dune.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 0VNFz0OQlkxb; Sat, 2 Feb 2013 17:06:14 +0100 (CET) Received: from localhost.localdomain (catvpool-576570d8.szarvasnet.hu [87.101.112.216]) by arrakis.dune.hu (Postfix) with ESMTPSA id 7A591287219; Sat, 2 Feb 2013 17:06:13 +0100 (CET) From: Gabor Juhos To: u-boot@lists.denx.de Date: Sat, 2 Feb 2013 17:06:02 +0100 Message-Id: <1359821166-32352-7-git-send-email-juhosg@openwrt.org> X-Mailer: git-send-email 1.7.10 In-Reply-To: <1359821166-32352-1-git-send-email-juhosg@openwrt.org> References: <1359821166-32352-1-git-send-email-juhosg@openwrt.org> Subject: [U-Boot] [PATCH v2 06/10] MIPS: qemu-malta: add PCI support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Qemu emulates the Galileo GT64120 System Controller which provides a CPU bus to PCI bus bridge. The patch adds driver for this bridge and enables PCI support for the emulated Malta board. Signed-off-by: Gabor Juhos Cc: Daniel Schwierzeck --- Changes since v1: - rebased against mips/testing Changes since RFC: - use a C struct to define the register layout instead of using a base address plus offset notation - remove custom IO accessors --- board/qemu-malta/Makefile | 5 +- board/qemu-malta/pci.c | 168 ++++++++++++++++++++++++++++++++++++++++++ include/configs/qemu-malta.h | 6 ++ 3 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 board/qemu-malta/pci.c diff --git a/board/qemu-malta/Makefile b/board/qemu-malta/Makefile index 6251bb8..59c1b1d 100644 --- a/board/qemu-malta/Makefile +++ b/board/qemu-malta/Makefile @@ -25,7 +25,10 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).o -COBJS = $(BOARD).o +COBJS-y += $(BOARD).o +COBJS-$(CONFIG_PCI) += pci.o + +COBJS := $(COBJS-y) SOBJS = lowlevel_init.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/board/qemu-malta/pci.c b/board/qemu-malta/pci.c new file mode 100644 index 0000000..fd9193b --- /dev/null +++ b/board/qemu-malta/pci.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2013 Gabor Juhos + * + * Based on the Linux implementation. + * Copyright (C) 1999, 2000, 2004 MIPS Technologies, Inc. + * Authors: Carsten Langgaard + * Maciej W. Rozycki + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +struct gt64120_regs { + u8 unused_000[0xc18]; + u32 intrcause; + u8 unused_c1c[0x0dc]; + u32 pci0_cfgaddr; + u32 pci0_cfgdata; +}; + +DECLARE_GLOBAL_DATA_PTR; + +static struct gt64120_regs *gt_regs; + +/* + * PCI controller "hose" value + */ +static struct pci_controller hose; + +#define GT_INTRCAUSE_ABORT_BITS \ + (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT) + +static int gt_config_access(unsigned char access_type, pci_dev_t bdf, + int where, u32 *data) +{ + unsigned int bus = PCI_BUS(bdf); + unsigned int dev = PCI_DEV(bdf); + unsigned int devfn = PCI_DEV(bdf) << 3 | PCI_FUNC(bdf); + u32 intr; + u32 addr; + u32 val; + + if (bus == 0 && dev >= 31) { + /* Because of a bug in the galileo (for slot 31). */ + return -1; + } + + if (access_type == PCI_ACCESS_WRITE) + debug("PCI WR %02x:%02x.%x reg:%02d data:%08x\n", + PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), + where, *data); + + /* Clear cause register bits */ + __raw_writel(~GT_INTRCAUSE_ABORT_BITS, >_regs->intrcause); + + addr = GT_PCI0_CFGADDR_CONFIGEN_BIT; + addr |= bus << GT_PCI0_CFGADDR_BUSNUM_SHF; + addr |= devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF; + addr |= (where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF; + + /* Setup address */ + __raw_writel(addr, >_regs->pci0_cfgaddr); + + if (access_type == PCI_ACCESS_WRITE) { + if (bus == 0 && dev == 0) { + /* + * The Galileo system controller is acting + * differently than other devices. + */ + val = *data; + } else + val = cpu_to_le32(*data); + + __raw_writel(val, >_regs->pci0_cfgdata); + } else { + val = __raw_readl(>_regs->pci0_cfgdata); + + if (bus == 0 && dev == 0) { + /* + * The Galileo system controller is acting + * differently than other devices. + */ + *data = val; + } else + *data = le32_to_cpu(val); + } + + /* Check for master or target abort */ + intr = __raw_readl(>_regs->intrcause); + if (intr & GT_INTRCAUSE_ABORT_BITS) { + /* Error occurred, clear abort bits */ + __raw_writel(~GT_INTRCAUSE_ABORT_BITS, >_regs->intrcause); + return -1; + } + + if (access_type == PCI_ACCESS_READ) + debug("PCI RD %02x:%02x.%x reg:%02d data:%08x\n", + PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf), where, *data); + + return 0; +} + +static int gt_read_config_dword(struct pci_controller *hose, pci_dev_t dev, + int where, u32 *value) +{ + *value = 0xffffffff; + return gt_config_access(PCI_ACCESS_READ, dev, where, value); +} + +static int gt_write_config_dword(struct pci_controller *hose, pci_dev_t dev, + int where, u32 value) +{ + u32 data = value; + + return gt_config_access(PCI_ACCESS_WRITE, dev, where, &data); +} + +void pci_init_board(void) +{ + set_io_port_base(CKSEG1ADDR(MALTA_IO_PORT_BASE)); + + gt_regs = (struct gt64120_regs *) CKSEG1ADDR(MALTA_GT_BASE); + + hose.first_busno = 0; + hose.last_busno = 0xff; + + /* System memory space */ + pci_set_region(&hose.regions[0], + 0x00000000, 0x00000000, + CONFIG_SYS_MEM_SIZE, + PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); + + /* PCI memory space */ + pci_set_region(&hose.regions[1], + 0x10000000, 0x10000000, + 128 * 1024 * 1024, + PCI_REGION_MEM); + + /* PCI I/O space */ + pci_set_region(&hose.regions[2], + 0x0000000, 0x0000000, + 0x20000, + PCI_REGION_IO); + + hose.region_count = 3; + + pci_set_ops(&hose, + pci_hose_read_config_byte_via_dword, + pci_hose_read_config_word_via_dword, + gt_read_config_dword, + pci_hose_write_config_byte_via_dword, + pci_hose_write_config_word_via_dword, + gt_write_config_dword); + + pci_register_hose(&hose); + hose.last_busno = pci_hose_scan(&hose); +} diff --git a/include/configs/qemu-malta.h b/include/configs/qemu-malta.h index 881c15d..36b584a 100644 --- a/include/configs/qemu-malta.h +++ b/include/configs/qemu-malta.h @@ -17,6 +17,9 @@ */ #define CONFIG_QEMU_MALTA +#define CONFIG_PCI +#define CONFIG_PCI_PNP + /* * CPU Configuration */ @@ -30,6 +33,7 @@ #define CONFIG_SWAP_IO_SPACE + /* * Memory map */ @@ -108,6 +112,8 @@ #undef CONFIG_CMD_NET #undef CONFIG_CMD_NFS +#define CONFIG_CMD_PCI + #define CONFIG_SYS_LONGHELP /* verbose help, undef to save memory */ #endif /* _QEMU_MALTA_CONFIG_H */