microblaze: Enable PCI, missing files
There are two parts of changes. The first is just enable PCI in Makefiles and in Kconfig. The second is the rest of missing files. I didn't want to add it with previous patch because that patch is too big. Current Microblaze toolchain has problem with weak symbols that's why is necessary to apply this changes to be possible to compile pci support. Xilinx knows about this problem. Signed-off-by: Michal Simek <monstr@monstr.eu>
This commit is contained in:
Родитель
d3afa58c20
Коммит
a6475c1322
|
@ -256,6 +256,21 @@ source "fs/Kconfig.binfmt"
|
|||
|
||||
endmenu
|
||||
|
||||
menu "Bus Options"
|
||||
|
||||
config PCI
|
||||
bool "PCI support"
|
||||
|
||||
config PCI_DOMAINS
|
||||
def_bool PCI
|
||||
|
||||
config PCI_SYSCALL
|
||||
def_bool PCI
|
||||
|
||||
source "drivers/pci/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
source "net/Kconfig"
|
||||
|
||||
source "drivers/Kconfig"
|
||||
|
|
|
@ -50,6 +50,7 @@ libs-y += $(LIBGCC)
|
|||
core-y += arch/microblaze/kernel/
|
||||
core-y += arch/microblaze/mm/
|
||||
core-y += arch/microblaze/platform/
|
||||
core-$(CONFIG_PCI) += arch/microblaze/pci/
|
||||
|
||||
drivers-$(CONFIG_OPROFILE) += arch/microblaze/oprofile/
|
||||
|
||||
|
|
|
@ -17,7 +17,21 @@
|
|||
#include <linux/mm.h> /* Get struct page {...} */
|
||||
#include <asm-generic/iomap.h>
|
||||
|
||||
#define PCI_DRAM_OFFSET 0
|
||||
#ifndef CONFIG_PCI
|
||||
#define _IO_BASE 0
|
||||
#define _ISA_MEM_BASE 0
|
||||
#define PCI_DRAM_OFFSET 0
|
||||
#else
|
||||
#define _IO_BASE isa_io_base
|
||||
#define _ISA_MEM_BASE isa_mem_base
|
||||
#define PCI_DRAM_OFFSET pci_dram_offset
|
||||
#endif
|
||||
|
||||
extern unsigned long isa_io_base;
|
||||
extern unsigned long pci_io_base;
|
||||
extern unsigned long pci_dram_offset;
|
||||
|
||||
extern resource_size_t isa_mem_base;
|
||||
|
||||
#define IO_SPACE_LIMIT (0xFFFFFFFF)
|
||||
|
||||
|
|
|
@ -89,6 +89,21 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
|
|||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/*
|
||||
* Macro to mark a page protection value as "uncacheable".
|
||||
*/
|
||||
|
||||
#define _PAGE_CACHE_CTL (_PAGE_GUARDED | _PAGE_NO_CACHE | \
|
||||
_PAGE_WRITETHRU)
|
||||
|
||||
#define pgprot_noncached(prot) \
|
||||
(__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \
|
||||
_PAGE_NO_CACHE | _PAGE_GUARDED))
|
||||
|
||||
#define pgprot_noncached_wc(prot) \
|
||||
(__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \
|
||||
_PAGE_NO_CACHE))
|
||||
|
||||
/*
|
||||
* The MicroBlaze MMU is identical to the PPC-40x MMU, and uses a hash
|
||||
* table containing PTEs, together with a set of 16 segment registers, to
|
||||
|
|
|
@ -31,6 +31,21 @@
|
|||
/* Other Prototypes */
|
||||
extern int early_uartlite_console(void);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
/*
|
||||
* PCI <-> OF matching functions
|
||||
* (XXX should these be here?)
|
||||
*/
|
||||
struct pci_bus;
|
||||
struct pci_dev;
|
||||
extern int pci_device_from_OF_node(struct device_node *node,
|
||||
u8 *bus, u8 *devfn);
|
||||
extern struct device_node *pci_busdev_to_OF_node(struct pci_bus *bus,
|
||||
int devfn);
|
||||
extern struct device_node *pci_device_to_OF_node(struct pci_dev *dev);
|
||||
extern void pci_create_OF_bus_map(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* OF address retreival & translation
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Makefile
|
||||
#
|
||||
|
||||
obj-$(CONFIG_PCI) += pci_32.o pci-common.o indirect_pci.o iomap.o
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Support for indirect PCI bridges.
|
||||
*
|
||||
* Copyright (C) 1998 Gabriel Paubert.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
|
||||
static int
|
||||
indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
|
||||
int len, u32 *val)
|
||||
{
|
||||
struct pci_controller *hose = pci_bus_to_host(bus);
|
||||
volatile void __iomem *cfg_data;
|
||||
u8 cfg_type = 0;
|
||||
u32 bus_no, reg;
|
||||
|
||||
if (hose->indirect_type & INDIRECT_TYPE_NO_PCIE_LINK) {
|
||||
if (bus->number != hose->first_busno)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
if (devfn != 0)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (hose->indirect_type & INDIRECT_TYPE_SET_CFG_TYPE)
|
||||
if (bus->number != hose->first_busno)
|
||||
cfg_type = 1;
|
||||
|
||||
bus_no = (bus->number == hose->first_busno) ?
|
||||
hose->self_busno : bus->number;
|
||||
|
||||
if (hose->indirect_type & INDIRECT_TYPE_EXT_REG)
|
||||
reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
|
||||
else
|
||||
reg = offset & 0xfc; /* Only 3 bits for function */
|
||||
|
||||
if (hose->indirect_type & INDIRECT_TYPE_BIG_ENDIAN)
|
||||
out_be32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
|
||||
(devfn << 8) | reg | cfg_type));
|
||||
else
|
||||
out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
|
||||
(devfn << 8) | reg | cfg_type));
|
||||
|
||||
/*
|
||||
* Note: the caller has already checked that offset is
|
||||
* suitably aligned and that len is 1, 2 or 4.
|
||||
*/
|
||||
cfg_data = hose->cfg_data + (offset & 3); /* Only 3 bits for function */
|
||||
switch (len) {
|
||||
case 1:
|
||||
*val = in_8(cfg_data);
|
||||
break;
|
||||
case 2:
|
||||
*val = in_le16(cfg_data);
|
||||
break;
|
||||
default:
|
||||
*val = in_le32(cfg_data);
|
||||
break;
|
||||
}
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
|
||||
int len, u32 val)
|
||||
{
|
||||
struct pci_controller *hose = pci_bus_to_host(bus);
|
||||
volatile void __iomem *cfg_data;
|
||||
u8 cfg_type = 0;
|
||||
u32 bus_no, reg;
|
||||
|
||||
if (hose->indirect_type & INDIRECT_TYPE_NO_PCIE_LINK) {
|
||||
if (bus->number != hose->first_busno)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
if (devfn != 0)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (hose->indirect_type & INDIRECT_TYPE_SET_CFG_TYPE)
|
||||
if (bus->number != hose->first_busno)
|
||||
cfg_type = 1;
|
||||
|
||||
bus_no = (bus->number == hose->first_busno) ?
|
||||
hose->self_busno : bus->number;
|
||||
|
||||
if (hose->indirect_type & INDIRECT_TYPE_EXT_REG)
|
||||
reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
|
||||
else
|
||||
reg = offset & 0xfc;
|
||||
|
||||
if (hose->indirect_type & INDIRECT_TYPE_BIG_ENDIAN)
|
||||
out_be32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
|
||||
(devfn << 8) | reg | cfg_type));
|
||||
else
|
||||
out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
|
||||
(devfn << 8) | reg | cfg_type));
|
||||
|
||||
/* surpress setting of PCI_PRIMARY_BUS */
|
||||
if (hose->indirect_type & INDIRECT_TYPE_SURPRESS_PRIMARY_BUS)
|
||||
if ((offset == PCI_PRIMARY_BUS) &&
|
||||
(bus->number == hose->first_busno))
|
||||
val &= 0xffffff00;
|
||||
|
||||
/* Workaround for PCI_28 Errata in 440EPx/GRx */
|
||||
if ((hose->indirect_type & INDIRECT_TYPE_BROKEN_MRM) &&
|
||||
offset == PCI_CACHE_LINE_SIZE) {
|
||||
val = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: the caller has already checked that offset is
|
||||
* suitably aligned and that len is 1, 2 or 4.
|
||||
*/
|
||||
cfg_data = hose->cfg_data + (offset & 3);
|
||||
switch (len) {
|
||||
case 1:
|
||||
out_8(cfg_data, val);
|
||||
break;
|
||||
case 2:
|
||||
out_le16(cfg_data, val);
|
||||
break;
|
||||
default:
|
||||
out_le32(cfg_data, val);
|
||||
break;
|
||||
}
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static struct pci_ops indirect_pci_ops = {
|
||||
.read = indirect_read_config,
|
||||
.write = indirect_write_config,
|
||||
};
|
||||
|
||||
void __init
|
||||
setup_indirect_pci(struct pci_controller *hose,
|
||||
resource_size_t cfg_addr,
|
||||
resource_size_t cfg_data, u32 flags)
|
||||
{
|
||||
resource_size_t base = cfg_addr & PAGE_MASK;
|
||||
void __iomem *mbase;
|
||||
|
||||
mbase = ioremap(base, PAGE_SIZE);
|
||||
hose->cfg_addr = mbase + (cfg_addr & ~PAGE_MASK);
|
||||
if ((cfg_data & PAGE_MASK) != base)
|
||||
mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
|
||||
hose->cfg_data = mbase + (cfg_data & ~PAGE_MASK);
|
||||
hose->ops = &indirect_pci_ops;
|
||||
hose->indirect_type = flags;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* ppc64 "iomap" interface implementation.
|
||||
*
|
||||
* (C) Copyright 2004 Linus Torvalds
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
|
||||
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
|
||||
{
|
||||
resource_size_t start = pci_resource_start(dev, bar);
|
||||
resource_size_t len = pci_resource_len(dev, bar);
|
||||
unsigned long flags = pci_resource_flags(dev, bar);
|
||||
|
||||
if (!len)
|
||||
return NULL;
|
||||
if (max && len > max)
|
||||
len = max;
|
||||
if (flags & IORESOURCE_IO)
|
||||
return ioport_map(start, len);
|
||||
if (flags & IORESOURCE_MEM)
|
||||
return ioremap(start, len);
|
||||
/* What? */
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_iomap);
|
||||
|
||||
void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
|
||||
{
|
||||
if (isa_vaddr_is_ioport(addr))
|
||||
return;
|
||||
if (pcibios_vaddr_is_ioport(addr))
|
||||
return;
|
||||
iounmap(addr);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_iounmap);
|
|
@ -48,6 +48,7 @@ obj-$(CONFIG_PPC) += setup-bus.o
|
|||
obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
|
||||
obj-$(CONFIG_X86_VISWS) += setup-irq.o
|
||||
obj-$(CONFIG_MN10300) += setup-bus.o
|
||||
obj-$(CONFIG_MICROBLAZE) += setup-bus.o
|
||||
|
||||
#
|
||||
# ACPI Related PCI FW Functions
|
||||
|
|
Загрузка…
Ссылка в новой задаче