Skip to content

Commit

Permalink
powerpc: Add PCI support for 8540 ADS to powerpc tree
Browse files Browse the repository at this point in the history
Add PCI support for setting PCI from flat device tree on 85xx specifically for
MPC8540 ADS.

Signed-off-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
  • Loading branch information
Andy Fleming authored and Kumar Gala committed Feb 22, 2006
1 parent 774fee5 commit 8080d54
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 25 deletions.
3 changes: 2 additions & 1 deletion arch/powerpc/platforms/85xx/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#
# Makefile for the PowerPC 85xx linux kernel.
#
obj-$(CONFIG_PPC_85xx) += misc.o mpc85xx_ads.o
obj-$(CONFIG_PPC_85xx) += misc.o pci.o
obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
24 changes: 0 additions & 24 deletions arch/powerpc/platforms/85xx/mpc8540_ads.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,30 +30,6 @@
#define PIRQC MPC85xx_IRQ_EXT3
#define PIRQD MPC85xx_IRQ_EXT4

#define MPC85XX_PCI1_LOWER_IO 0x00000000
#define MPC85XX_PCI1_UPPER_IO 0x00ffffff

#define MPC85XX_PCI1_LOWER_MEM 0x80000000
#define MPC85XX_PCI1_UPPER_MEM 0x9fffffff

#define MPC85XX_PCI1_IO_BASE 0xe2000000
#define MPC85XX_PCI1_MEM_OFFSET 0x00000000

#define MPC85XX_PCI1_IO_SIZE 0x01000000

/* PCI config */
#define PCI1_CFG_ADDR_OFFSET (0x8000)
#define PCI1_CFG_DATA_OFFSET (0x8004)

#define PCI2_CFG_ADDR_OFFSET (0x9000)
#define PCI2_CFG_DATA_OFFSET (0x9004)

/* Additional register for PCI-X configuration */
#define PCIX_NEXT_CAP 0x60
#define PCIX_CAP_ID 0x61
#define PCIX_COMMAND 0x62
#define PCIX_STATUS 0x64

/* Offset of CPM register space */
#define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET)

Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/platforms/85xx/mpc85xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@
*/

extern void mpc85xx_restart(char *);
extern int add_bridge(struct device_node *dev);
67 changes: 67 additions & 0 deletions arch/powerpc/platforms/85xx/mpc85xx_ads.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,62 @@ static u_char mpc85xx_ads_openpic_initsenses[] __initdata = {
0x0, /* External 11: */
};

#ifdef CONFIG_PCI
/*
* interrupt routing
*/

int
mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
{
static char pci_irq_table[][4] =
/*
* This is little evil, but works around the fact
* that revA boards have IDSEL starting at 18
* and others boards (older) start at 12
*
* PCI IDSEL/INTPIN->INTLINE
* A B C D
*/
{
{PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 2 */
{PIRQD, PIRQA, PIRQB, PIRQC},
{PIRQC, PIRQD, PIRQA, PIRQB},
{PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 5 */
{0, 0, 0, 0}, /* -- */
{0, 0, 0, 0}, /* -- */
{0, 0, 0, 0}, /* -- */
{0, 0, 0, 0}, /* -- */
{0, 0, 0, 0}, /* -- */
{0, 0, 0, 0}, /* -- */
{PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 12 */
{PIRQD, PIRQA, PIRQB, PIRQC},
{PIRQC, PIRQD, PIRQA, PIRQB},
{PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 15 */
{0, 0, 0, 0}, /* -- */
{0, 0, 0, 0}, /* -- */
{PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 18 */
{PIRQD, PIRQA, PIRQB, PIRQC},
{PIRQC, PIRQD, PIRQA, PIRQB},
{PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 21 */
};

const long min_idsel = 2, max_idsel = 21, irqs_per_slot = 4;
return PCI_IRQ_TABLE_LOOKUP;
}

int
mpc85xx_exclude_device(u_char bus, u_char devfn)
{
if (bus == 0 && PCI_SLOT(devfn) == 0)
return PCIBIOS_DEVICE_NOT_FOUND;
else
return PCIBIOS_SUCCESSFUL;
}

#endif /* CONFIG_PCI */


void __init mpc85xx_ads_pic_init(void)
{
struct mpic *mpic1;
Expand Down Expand Up @@ -110,6 +166,7 @@ void __init mpc85xx_ads_pic_init(void)
static void __init mpc85xx_ads_setup_arch(void)
{
struct device_node *cpu;
struct device_node *np;

if (ppc_md.progress)
ppc_md.progress("mpc85xx_ads_setup_arch()", 0);
Expand All @@ -125,6 +182,16 @@ static void __init mpc85xx_ads_setup_arch(void)
loops_per_jiffy = 50000000 / HZ;
of_node_put(cpu);
}

#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
add_bridge(np);

ppc_md.pci_swizzle = common_swizzle;
ppc_md.pci_map_irq = mpc85xx_map_irq;
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif

#ifdef CONFIG_ROOT_NFS
ROOT_DEV = Root_NFS;
#else
Expand Down
96 changes: 96 additions & 0 deletions arch/powerpc/platforms/85xx/pci.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* FSL SoC setup code
*
* Maintained by Kumar Gala (see MAINTAINERS for contact information)
*
* 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/config.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/module.h>

#include <asm/system.h>
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/pci-bridge.h>
#include <asm/prom.h>
#include <sysdev/fsl_soc.h>

#undef DEBUG

#ifdef DEBUG
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif

int mpc85xx_pci2_busno = 0;

#ifdef CONFIG_PCI
int __init add_bridge(struct device_node *dev)
{
int len;
struct pci_controller *hose;
struct resource rsrc;
int *bus_range;
int primary = 1, has_address = 0;
phys_addr_t immr = get_immrbase();

DBG("Adding PCI host bridge %s\n", dev->full_name);

/* Fetch host bridge registers address */
has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);

/* Get bus range if any */
bus_range = (int *) get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", dev->full_name);
}

hose = pcibios_alloc_controller();
if (!hose)
return -ENOMEM;
hose->arch_data = dev;
hose->set_cfg_type = 1;

hose->first_busno = bus_range ? bus_range[0] : 0;
hose->last_busno = bus_range ? bus_range[1] : 0xff;

/* PCI 1 */
if ((rsrc.start & 0xfffff) == 0x8000) {
setup_indirect_pci(hose, immr + 0x8000, immr + 0x8004);
}
/* PCI 2 */
if ((rsrc.start & 0xfffff) == 0x9000) {
setup_indirect_pci(hose, immr + 0x9000, immr + 0x9004);
primary = 0;
hose->bus_offset = hose->first_busno;
mpc85xx_pci2_busno = hose->first_busno;
}

printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%08lx. "
"Firmware bus number: %d->%d\n",
rsrc.start, hose->first_busno, hose->last_busno);

DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
hose, hose->cfg_addr, hose->cfg_data);

/* Interpret the "ranges" property */
/* This also maps the I/O region and sets isa_io/mem_base */
pci_process_bridge_OF_ranges(hose, dev, primary);

return 0;
}

#endif

0 comments on commit 8080d54

Please sign in to comment.