2013/5/22 Gabor Juhos <juh...@openwrt.org>: > 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 <juh...@openwrt.org> > Cc: Daniel Schwierzeck <daniel.schwierz...@googlemail.com>
ELDK-5.3 shows some warnings: pci_indirect.c: In function 'indirect_read_config_byte': pci_indirect.c:101:1: warning: implicit declaration of function 'out_le32' [-Wimplicit-function-declaration] pci_indirect.c:101:1: warning: implicit declaration of function 'in_8' [-Wimplicit-function-declaration] pci_indirect.c: In function 'indirect_read_config_word': pci_indirect.c:102:1: warning: implicit declaration of function 'in_le16' [-Wimplicit-function-declaration] pci_indirect.c: In function 'indirect_read_config_dword': pci_indirect.c:103:1: warning: implicit declaration of function 'in_le32' [-Wimplicit-function-declaration] pci_indirect.c: In function 'indirect_write_config_byte': pci_indirect.c:109:1: warning: implicit declaration of function 'out_8' [-Wimplicit-function-declaration] pci_indirect.c: In function 'indirect_write_config_word': pci_indirect.c:110:1: warning: implicit declaration of function 'out_le16' [-Wimplicit-function-declaration] pci_gt64120.c: In function 'gt64120_pci_init': pci_gt64120.c:178:1: warning: control reaches end of non-void function [-Wreturn-type] > --- > Changes since v2: > - move the PCI driver to drivers/pci > - fix checkpatch warnings > - rebased against the master branch of git.denx.de/u-boot.git > > 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 > > Screenshot: > > U-Boot 2013.04-00242-g8960ff8 (May 22 2013 - 13:25:13) > > Board: MIPS Malta CoreLV (Qemu) > DRAM: 256 MiB > pflash_write: Unimplemented flash cmd sequence (offset 0000000000000000, > wcycle 0x0 cmd 0x0 value 0xf0) > Flash: 4 MiB > Using default environment > > In: serial > Out: serial > Err: serial > qemu-malta # pci > Scanning PCI devices on bus 0 > BusDevFun VendorId DeviceId Device Class Sub-Class > _____________________________________________________________ > 00.00.00 0x11ab 0x4620 Bridge device 0x00 > 00.0a.00 0x8086 0x7110 Bridge device 0x01 > 00.0a.01 0x8086 0x7111 Mass storage controller 0x01 > 00.0a.02 0x8086 0x7112 Serial bus controller 0x03 > 00.0a.03 0x8086 0x7113 Bridge device 0x80 > 00.0b.00 0x1022 0x2000 Network controller 0x00 > qemu-malta # > --- > board/qemu-malta/qemu-malta.c | 12 +++ > drivers/pci/Makefile | 1 + > drivers/pci/pci_gt64120.c | 178 > +++++++++++++++++++++++++++++++++++++++++ > include/configs/qemu-malta.h | 6 ++ > include/pci_gt64120.h | 19 +++++ > 5 files changed, 216 insertions(+) > create mode 100644 drivers/pci/pci_gt64120.c > create mode 100644 include/pci_gt64120.h > > diff --git a/board/qemu-malta/qemu-malta.c b/board/qemu-malta/qemu-malta.c > index 449da9c..e3a733f 100644 > --- a/board/qemu-malta/qemu-malta.c > +++ b/board/qemu-malta/qemu-malta.c > @@ -8,8 +8,10 @@ > > #include <common.h> > > +#include <asm/addrspace.h> > #include <asm/io.h> > #include <asm/malta.h> > +#include <pci_gt64120.h> > > phys_size_t initdram(int board_type) > { > @@ -29,3 +31,13 @@ void _machine_restart(void) > reset_base = (void __iomem *)CKSEG1ADDR(MALTA_RESET_BASE); > __raw_writel(GORESET, reset_base); > } > + > +void pci_init_board(void) > +{ > + set_io_port_base(CKSEG1ADDR(MALTA_IO_PORT_BASE)); > + > + gt64120_pci_init((void *)CKSEG1ADDR(MALTA_GT_BASE), > + 0x00000000, 0x00000000, CONFIG_SYS_MEM_SIZE, > + 0x10000000, 0x10000000, 128 * 1024 * 1024, > + 0x00000000, 0x00000000, 0x20000); > +} > diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile > index 1ae35d3..02d2309 100644 > --- a/drivers/pci/Makefile > +++ b/drivers/pci/Makefile > @@ -27,6 +27,7 @@ LIB := $(obj)libpci.o > > COBJS-$(CONFIG_FSL_PCI_INIT) += fsl_pci_init.o > COBJS-$(CONFIG_PCI) += pci.o pci_auto.o pci_indirect.o > +COBJS-$(CONFIG_PCI_GT64120) += pci_gt64120.o > COBJS-$(CONFIG_FTPCI100) += pci_ftpci100.o > COBJS-$(CONFIG_IXP_PCI) += pci_ixp.o > COBJS-$(CONFIG_SH4_PCI) += pci_sh4.o > diff --git a/drivers/pci/pci_gt64120.c b/drivers/pci/pci_gt64120.c > new file mode 100644 > index 0000000..c2f2049 > --- /dev/null > +++ b/drivers/pci/pci_gt64120.c > @@ -0,0 +1,178 @@ > +/* > + * Copyright (C) 2013 Gabor Juhos <juh...@openwrt.org> > + * > + * Based on the Linux implementation. > + * Copyright (C) 1999, 2000, 2004 MIPS Technologies, Inc. > + * Authors: Carsten Langgaard <carst...@mips.com> > + * Maciej W. Rozycki <ma...@mips.com> > + * > + * 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 <common.h> > +#include <gt64120.h> > +#include <pci.h> > +#include <pci_gt64120.h> > + > +#include <asm/io.h> > + > +#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; > +}; > + > +struct gt64120_pci_controller { > + struct pci_controller hose; > + struct gt64120_regs *regs; > +}; > + > +static inline struct gt64120_pci_controller * > +hose_to_gt64120(struct pci_controller *hose) > +{ > + return container_of(hose, struct gt64120_pci_controller, hose); > +} > + > +#define GT_INTRCAUSE_ABORT_BITS \ > + (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT) > + > +static int gt_config_access(struct gt64120_pci_controller *gt, > + 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 */ > + 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 */ > + 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); > + } braces not needed (checkpatch.pl does not catch this) > + > + writel(val, >->regs->pci0_cfgdata); > + } else { > + val = 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 = readl(>->regs->intrcause); > + if (intr & GT_INTRCAUSE_ABORT_BITS) { > + /* Error occurred, clear abort bits */ > + 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) > +{ > + struct gt64120_pci_controller *gt = hose_to_gt64120(hose); > + > + *value = 0xffffffff; > + return gt_config_access(gt, PCI_ACCESS_READ, dev, where, value); > +} > + > +static int gt_write_config_dword(struct pci_controller *hose, pci_dev_t dev, > + int where, u32 value) > +{ > + struct gt64120_pci_controller *gt = hose_to_gt64120(hose); > + u32 data = value; > + > + return gt_config_access(gt, PCI_ACCESS_WRITE, dev, where, &data); > +} > + > +int gt64120_pci_init(void *regs, unsigned long sys_bus, unsigned long > sys_phys, > + unsigned long sys_size, unsigned long mem_bus, > + unsigned long mem_phys, unsigned long mem_size, > + unsigned long io_bus, unsigned long io_phys, > + unsigned long io_size) > +{ > + static struct gt64120_pci_controller global_gt; > + struct gt64120_pci_controller *gt; > + struct pci_controller *hose; > + > + gt = &global_gt; > + gt->regs = regs; > + > + hose = >->hose; > + > + hose->first_busno = 0; > + hose->last_busno = 0; > + > + /* System memory space */ > + pci_set_region(&hose->regions[0], sys_bus, sys_phys, sys_size, > + PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); > + > + /* PCI memory space */ > + pci_set_region(&hose->regions[1], mem_bus, mem_phys, mem_size, > + PCI_REGION_MEM); > + > + /* PCI I/O space */ > + pci_set_region(&hose->regions[2], io_bus, io_phys, io_size, > + 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); missing return keyword > +} > diff --git a/include/configs/qemu-malta.h b/include/configs/qemu-malta.h > index 436bb49..ef44d3d 100644 > --- a/include/configs/qemu-malta.h > +++ b/include/configs/qemu-malta.h > @@ -17,6 +17,10 @@ > */ > #define CONFIG_QEMU_MALTA > > +#define CONFIG_PCI > +#define CONFIG_PCI_GT64120 > +#define CONFIG_PCI_PNP > + > /* > * CPU Configuration > */ > @@ -104,6 +108,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 */ > diff --git a/include/pci_gt64120.h b/include/pci_gt64120.h > new file mode 100644 > index 0000000..aae6b33 > --- /dev/null > +++ b/include/pci_gt64120.h > @@ -0,0 +1,19 @@ > +/* > + * Copyright (C) 2013 Gabor Juhos <juh...@openwrt.org> > + * > + * 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. > + */ > + > +#ifndef _PCI_GT64120_H > +#define _PCI_GT64120_H > + > +int gt64120_pci_init(void *regs, unsigned long sys_bus, unsigned long > sys_phys, > + unsigned long sys_size, unsigned long mem_bus, > + unsigned long mem_phys, unsigned long mem_size, > + unsigned long io_bus, unsigned long io_phys, > + unsigned long io_size); > + > + > +#endif /* _PCI_GT64120_H */ > -- > 1.7.10 > -- Best regards, Daniel _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot