From afd5e44a32c561a8e5f7d13b2108fb7266ead1a6 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 18 Oct 2004 09:00:22 -0700 Subject: [PATCH] [PATCH] sh: PCI updates This updates some of the PCI drivers. SH7751, the sh03 board-specific PCI code, and some ST40 PCI updates are grouped in this. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/boards/se/7751/io.c | 2 +- arch/sh/boards/se/7751/pci.c | 2 +- arch/sh/drivers/pci/Makefile | 2 +- arch/sh/drivers/pci/fixups-rts7751r2d.c | 21 +- arch/sh/drivers/pci/fixups-sh03.c | 61 ++++++ arch/sh/drivers/pci/ops-rts7751r2d.c | 7 +- arch/sh/drivers/pci/ops-sh03.c | 45 ++++ arch/sh/drivers/pci/pci-auto.c | 2 + arch/sh/drivers/pci/pci-sh7751.c | 7 +- arch/sh/drivers/pci/pci-st40.c | 276 ++++++++++++++++-------- arch/sh/drivers/pci/pci-st40.h | 70 ++++++ arch/sh/drivers/pci/pci.c | 2 + 12 files changed, 393 insertions(+), 104 deletions(-) create mode 100644 arch/sh/drivers/pci/fixups-sh03.c create mode 100644 arch/sh/drivers/pci/ops-sh03.c diff --git a/arch/sh/boards/se/7751/io.c b/arch/sh/boards/se/7751/io.c index 224a5e37d7d36..99041b2692612 100644 --- a/arch/sh/boards/se/7751/io.c +++ b/arch/sh/boards/se/7751/io.c @@ -18,7 +18,7 @@ #include #include -#include +#include "../../../drivers/pci/pci-sh7751.h" #if 0 /****************************************************************** diff --git a/arch/sh/boards/se/7751/pci.c b/arch/sh/boards/se/7751/pci.c index 2f8682ebc1e94..1f273efd2cf51 100644 --- a/arch/sh/boards/se/7751/pci.c +++ b/arch/sh/boards/se/7751/pci.c @@ -19,7 +19,7 @@ #include #include -#include +#include "../../../drivers/pci/pci-sh7751.h" #define PCIMCR_MRSET_OFF 0xBFFFFFFF #define PCIMCR_RFSH_OFF 0xFFFFFFFB diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile index 4923bbf5e8a9f..365bc16a4a83b 100644 --- a/arch/sh/drivers/pci/Makefile +++ b/arch/sh/drivers/pci/Makefile @@ -13,4 +13,4 @@ obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \ obj-$(CONFIG_SH_SECUREEDGE5410) += ops-snapgear.o obj-$(CONFIG_SH_BIGSUR) += ops-bigsur.o obj-$(CONFIG_SH_RTS7751R2D) += ops-rts7751r2d.o fixups-rts7751r2d.o - +obj-$(CONFIG_SH_SH03) += ops-sh03.o fixups-sh03.o diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c index 7b5dbe157867d..0c590fc7a0812 100644 --- a/arch/sh/drivers/pci/fixups-rts7751r2d.c +++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c @@ -18,15 +18,26 @@ int pci_fixup_pcic(void) { - unsigned long mcr; + unsigned long bcr1, mcr; - outl(0xfb900047, SH7751_PCICONF1); - outl(0xab000001, SH7751_PCICONF4); + bcr1 = inl(SH7751_BCR1); + bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */ + outl(bcr1, PCI_REG(SH7751_PCIBCR1)); + + /* Enable all interrupts, so we known what to fix */ + outl(0x0000c3ff, PCI_REG(SH7751_PCIINTM)); + outl(0x0000380f, PCI_REG(SH7751_PCIAINTM)); + + outl(0xfb900047, PCI_REG(SH7751_PCICONF1)); + outl(0xab000001, PCI_REG(SH7751_PCICONF4)); mcr = inl(SH7751_MCR); mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF; - outl(mcr, SH7751_PCIMCR); + outl(mcr, PCI_REG(SH7751_PCIMCR)); + outl(0x0c000000, PCI_REG(SH7751_PCICONF5)); + outl(0xd0000000, PCI_REG(SH7751_PCICONF6)); + outl(0x0c000000, PCI_REG(SH7751_PCILAR0)); + outl(0x00000000, PCI_REG(SH7751_PCILAR1)); return 0; } - diff --git a/arch/sh/drivers/pci/fixups-sh03.c b/arch/sh/drivers/pci/fixups-sh03.c new file mode 100644 index 0000000000000..5db5cb91c5698 --- /dev/null +++ b/arch/sh/drivers/pci/fixups-sh03.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include + +/* + * IRQ functions + */ + +int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev) +{ + int irq; + + if (dev->bus->number == 0) { + switch (slot) { + case 4: return 5; /* eth0 */ + case 8: return 5; /* eth1 */ + case 6: return 2; /* PCI bridge */ + default: + printk("PCI: Bad IRQ mapping request for slot %d\n", slot); + return 2; + } + } else { + switch (pin) { + case 0: irq = 2; break; + case 1: irq = 2; break; + case 2: irq = 2; break; + case 3: irq = 2; break; + case 4: irq = 2; break; + default: irq = -1; break; + } + } + return irq; +} + +static u8 __init sh03_no_swizzle(struct pci_dev *dev, u8 *pin) +{ + /* no swizzling */ + return PCI_SLOT(dev->devfn); +} + +static int sh03_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + int irq = -1; + + /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */ + irq = pcibios_map_platform_irq(slot, pin, dev); + if( irq < 0 ) { + pr_debug("PCI: Error mapping IRQ on device %s\n", dev->slot_name); + return irq; + } + + pr_debug("Setting IRQ for slot %s to %d\n", dev->slot_name, irq); + + return irq; +} + +void __init pcibios_fixup_irqs(void) +{ + pci_fixup_irqs(sh03_no_swizzle, sh03_pci_lookup_irq); +} diff --git a/arch/sh/drivers/pci/ops-rts7751r2d.c b/arch/sh/drivers/pci/ops-rts7751r2d.c index 2bceb43c9a33a..beafa11f4d0c6 100644 --- a/arch/sh/drivers/pci/ops-rts7751r2d.c +++ b/arch/sh/drivers/pci/ops-rts7751r2d.c @@ -61,7 +61,12 @@ EXPORT_SYMBOL(board_pci_channels); static struct sh7751_pci_address_map sh7751_pci_map = { .window0 = { .base = SH7751_CS3_BASE_ADDR, - .size = 0x03f00000, + .size = 0x04000000, + }, + + .window1 = { + .base = 0x00000000, /* Unused */ + .size = 0x00000000, /* Unused */ }, .flags = SH7751_PCIC_NO_RESET, diff --git a/arch/sh/drivers/pci/ops-sh03.c b/arch/sh/drivers/pci/ops-sh03.c new file mode 100644 index 0000000000000..df2199732348e --- /dev/null +++ b/arch/sh/drivers/pci/ops-sh03.c @@ -0,0 +1,45 @@ +/* + * linux/arch/sh/drivers/pci/ops-sh03.c + * + * PCI initialization for the Interface CTP/PCI-SH03 board + */ + +#include +#include +#include +#include +#include +#include +#include +#include "pci-sh7751.h" + +/* + * Description: This function sets up and initializes the pcic, sets + * up the BARS, maps the DRAM into the address space etc, etc. + */ +int __init pcibios_init_platform(void) +{ + return 1; +} + +static struct resource sh7751_io_resource = { + .name = "SH03 IO", + .start = SH7751_PCI_IO_BASE, + .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1, + .flags = IORESOURCE_IO +}; + +static struct resource sh7751_mem_resource = { + .name = "SH03 mem", + .start = SH7751_PCI_MEMORY_BASE, + .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM +}; + +extern struct pci_ops sh7751_pci_ops; + +struct pci_channel board_pci_channels[] = { + { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff }, + { NULL, NULL, NULL, 0, 0 }, +}; + diff --git a/arch/sh/drivers/pci/pci-auto.c b/arch/sh/drivers/pci/pci-auto.c index 2ad70d499114e..4cef4d1d8c841 100644 --- a/arch/sh/drivers/pci/pci-auto.c +++ b/arch/sh/drivers/pci/pci-auto.c @@ -524,8 +524,10 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus) PCI_COMMAND, cmdstat | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); +#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D) early_write_config_byte(hose, top_bus, current_bus, pci_devfn, PCI_LATENCY_TIMER, 0x80); +#endif /* Allocate PCI I/O and/or memory space */ pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_5); diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c index 1a5a883ad01c5..6d4c9f2b31e42 100644 --- a/arch/sh/drivers/pci/pci-sh7751.c +++ b/arch/sh/drivers/pci/pci-sh7751.c @@ -33,6 +33,8 @@ static unsigned int pci_probe = PCI_PROBE_CONF1; extern int pci_fixup_pcic(void); +void pcibios_fixup_irqs(void) __attribute__ ((weak)); + /* * Direct access to PCI hardware... */ @@ -158,7 +160,6 @@ static int __init pci_check_direct(void) * Handle bus scanning and fixups .... */ -#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D) static void __init pci_fixup_ide_bases(struct pci_dev *d) { int i; @@ -256,7 +257,7 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map) outl(0, PCI_REG(SH7751_PCICLKR)); /* Clear Powerdown IRQ's (not done in reset) */ word = SH7751_PCIPINT_D3 | SH7751_PCIPINT_D0; - outl(word, PCI_REG(SH7751_PCICLKR)); + outl(word, PCI_REG(SH7751_PCIPINT)); /* * This code is unused for some boards as it is done in the @@ -361,7 +362,7 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map) * TODO: add support for the internal error interrupts and * DMA interrupts... */ - + #ifdef CONFIG_SH_RTS7751R2D pci_fixup_pcic(); #endif diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c index 4be02f6275589..2688f4159764a 100644 --- a/arch/sh/drivers/pci/pci-st40.c +++ b/arch/sh/drivers/pci/pci-st40.c @@ -18,6 +18,7 @@ #include #include #include +#include /* irqreturn_t */ #include "pci-st40.h" @@ -28,24 +29,22 @@ #define ST40PCI_REG_ADDRESS (ST40PCI_BASE_ADDRESS+0x07000000) #define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x)) +#define ST40PCI_REG_INDEXED(reg, index) \ + (ST40PCI_REG(reg##0) + \ + ((ST40PCI_REG(reg##1) - ST40PCI_REG(reg##0))*index)) #define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg)) #define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg)) #define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg)) +#define ST40PCI_WRITE_INDEXED(reg, index, val) \ + writel((val), ST40PCI_REG_INDEXED(reg, index)); #define ST40PCI_READ(reg) readl(ST40PCI_REG(reg)) #define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg)) #define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg)) -#define ST40PCI_SERR_IRQ 64 -#define ST40PCI_SERR_INT_GROUP 0 -#define ST40PCI_SERR_INT_POS 0 -#define ST40PCI_SERR_INT_PRI 15 - -#define ST40PCI_ERR_IRQ 65 -#define ST40PCI_ERR_INT_GROUP 1 -#define ST40PCI_ERR_INT_POS 1 -#define ST40PCI_ERR_INT_PRI 14 +#define ST40PCI_SERR_IRQ 64 +#define ST40PCI_ERR_IRQ 65 /* Macros to extract PLL params */ @@ -69,47 +68,143 @@ #define PLL_25MHZ 0x793c8512 #define PLL_33MHZ PLL_SET(18,88,3,295) +static void pci_set_rbar_region(unsigned int region, unsigned long localAddr, + unsigned long pciOffset, unsigned long regionSize); + +/* + * The pcibios_map_platform_irq function is defined in the appropriate + * board specific code and referenced here + */ +extern int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin); static __init void SetPCIPLL(void) { - /* Stop the PLL */ - writel(0, PLLPCICR); + { + /* Lets play with the PLL values */ + unsigned long pll1cr1; + unsigned long mdiv, ndiv, pdiv; + unsigned long muxcr; + unsigned int muxcr_ratios[4] = { 8, 16, 21, 1 }; + unsigned int freq; + +#define CLKGENA 0xbb040000 +#define CLKGENA_PLL2_MUXCR CLKGENA + 0x48 + pll1cr1 = ctrl_inl(PLLPCICR); + printk("PLL1CR1 %08lx\n", pll1cr1); + mdiv = PLL_MDIV(pll1cr1); + ndiv = PLL_NDIV(pll1cr1); + pdiv = PLL_PDIV(pll1cr1); + printk("mdiv %02lx ndiv %02lx pdiv %02lx\n", mdiv, ndiv, pdiv); + freq = ((2*27*ndiv)/mdiv) / (1 << pdiv); + printk("PLL freq %dMHz\n", freq); + muxcr = ctrl_inl(CLKGENA_PLL2_MUXCR); + printk("PCI freq %dMhz\n", freq / muxcr_ratios[muxcr & 3]); + } +} - /* Always run at 33Mhz. The PCI clock is totally async - * to the rest of the system - */ - writel(PLL_33MHZ | PLLPCICR_POWERON, PLLPCICR); - printk("ST40PCI: Waiting for PCI PLL to lock\n"); - while ((readl(PLLPCICR) & PLLPCICR_LOCK) == 0); - writel(readl(PLLPCICR) | PLLPCICR_OUT_EN, PLLPCICR); +struct pci_err { + unsigned mask; + const char *error_string; +}; + +static struct pci_err int_error[]={ + { INT_MNLTDIM,"MNLTDIM: Master non-lock transfer"}, + { INT_TTADI, "TTADI: Illegal byte enable in I/O transfer"}, + { INT_TMTO, "TMTO: Target memory read/write timeout"}, + { INT_MDEI, "MDEI: Master function disable error"}, + { INT_APEDI, "APEDI: Address parity error"}, + { INT_SDI, "SDI: SERR detected"}, + { INT_DPEITW, "DPEITW: Data parity error target write"}, + { INT_PEDITR, "PEDITR: PERR detected"}, + { INT_TADIM, "TADIM: Target abort detected"}, + { INT_MADIM, "MADIM: Master abort detected"}, + { INT_MWPDI, "MWPDI: PERR from target at data write"}, + { INT_MRDPEI, "MRDPEI: Master read data parity error"} +}; +#define NUM_PCI_INT_ERRS (sizeof(int_error)/sizeof(struct pci_err)) + +static struct pci_err aint_error[]={ + { AINT_MBI, "MBI: Master broken"}, + { AINT_TBTOI, "TBTOI: Target bus timeout"}, + { AINT_MBTOI, "MBTOI: Master bus timeout"}, + { AINT_TAI, "TAI: Target abort"}, + { AINT_MAI, "MAI: Master abort"}, + { AINT_RDPEI, "RDPEI: Read data parity"}, + { AINT_WDPE, "WDPE: Write data parity"} +}; + +#define NUM_PCI_AINT_ERRS (sizeof(aint_error)/sizeof(struct pci_err)) + +static void print_pci_errors(unsigned reg,struct pci_err *error,int num_errors) +{ + int i; + + for(i=0;i1) return IRQ_HANDLED; + + printk("** PCI ERROR **\n"); - pci_int = ST40PCI_READ(INT); - pci_cir = ST40PCI_READ(CIR); - pci_air = ST40PCI_READ(AIR); + if(pci_int) { + printk("** INT register status\n"); + print_pci_errors(pci_int,int_error,NUM_PCI_INT_ERRS); + } - if (pci_int) { - printk("PCI INTERRUPT!\n"); - printk("PCI INT -> 0x%x\n", pci_int & 0xffff); - printk("PCI AIR -> 0x%x\n", pci_air); - printk("PCI CIR -> 0x%x\n", pci_cir); - ST40PCI_WRITE(INT, ~0); + if(pci_aint) { + printk("** AINT register status\n"); + print_pci_errors(pci_aint,aint_error,NUM_PCI_AINT_ERRS); } - pci_aint = ST40PCI_READ(AINT); - if (pci_aint) { - printk("PCI ARB INTERRUPT!\n"); - printk("PCI AINT -> 0x%x\n", pci_aint); - printk("PCI AIR -> 0x%x\n", pci_air); - printk("PCI CIR -> 0x%x\n", pci_cir); - ST40PCI_WRITE(AINT, ~0); + printk("** Address and command info\n"); + + printk("** Command %s : Address 0x%x\n", + pci_commands[pci_cir&0xf],pci_air); + + if(pci_cir&CIR_PIOTEM) { + printk("CIR_PIOTEM:PIO transfer error for master\n"); + } + if(pci_cir&CIR_RWTET) { + printk("CIR_RWTET:Read/Write transfer error for target\n"); } return IRQ_HANDLED; @@ -119,7 +214,7 @@ static irqreturn_t st40_pci_irq(int irq, void *dev_instance, struct pt_regs *reg /* Rounds a number UP to the nearest power of two. Used for * sizing the PCI window. */ -static u32 __init r2p2(u32 num) +static u32 r2p2(u32 num) { int i = 31; u32 tmp = num; @@ -179,12 +274,16 @@ int __init st40pci_init(unsigned memStart, unsigned memSize) /* Loop while core resets */ while (ST40PCI_READ(CR) & CR_SOFT_RESET); + /* Switch off interrupts */ + ST40PCI_WRITE(INTM, 0); + ST40PCI_WRITE(AINT, 0); + /* Now, lets reset all the cards on the bus with extreme prejudice */ ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL); udelay(250); /* Set bus active, take it out of reset */ - ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_CFINT | CR_PFCS | CR_PFE); + ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_BMAM | CR_CFINT | CR_PFCS | CR_PFE); /* The PCI spec says that no access must be made to the bus until 1 second * after reset. This seem ludicrously long, but some delay is needed here @@ -219,37 +318,20 @@ int __init st40pci_init(unsigned memStart, unsigned memSize) /* Set up the 64K window */ ST40PCI_WRITE(IOBMR, 0x0); - /* Now we set up the mbars so the PCI bus can see the memory of the machine */ + /* Now we set up the mbars so the PCI bus can see the local memory */ + /* Expose a 256M window starting at PCI address 0... */ + ST40PCI_WRITE(CSR_MBAR0, 0); + ST40PCI_WRITE(LSR0, 0x0fff0001); - if (memSize < (64 * 1024)) { - printk("Ridiculous memory size of 0x%x?\n",memSize); - return 0; - } - - lsr0 = - (memSize > - (512 * 1024 * 1024)) ? 0x1fff0001 : ((r2p2(memSize) - - 0x10000) | 0x1); - - ST40PCI_WRITE(LSR0, lsr0); - - ST40PCI_WRITE(CSR_MBAR0, memStart); - ST40PCI_WRITE(LAR0, memStart); + /* ... and set up the initial incomming window to expose all of RAM */ + pci_set_rbar_region(7, memStart, memStart, memSize); /* Maximise timeout values */ ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff); ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff); ST40PCI_WRITE_BYTE(CSR_MIT, 0xff); - - /* Install the pci interrupt handlers */ - make_intc2_irq(ST40PCI_SERR_IRQ, INTC2_BASE0, - ST40PCI_SERR_INT_GROUP, ST40PCI_SERR_INT_POS, - ST40PCI_SERR_INT_PRI); - - make_intc2_irq(ST40PCI_ERR_IRQ, INTC2_BASE0, ST40PCI_ERR_INT_GROUP, - ST40PCI_ERR_INT_POS, ST40PCI_ERR_INT_PRI); - + ST40PCI_WRITE_BYTE(PERF,PERF_MASTER_WRITE_POSTING); return 1; } @@ -332,7 +414,7 @@ static int st40pci_write(struct pci_bus *bus, unsigned int devfn, int where, int return PCIBIOS_SUCCESSFUL; } -static struct pci_ops pci_config_ops = { +struct pci_ops st40pci_config_ops = { .read = st40pci_read, .write = st40pci_write, }; @@ -348,36 +430,12 @@ static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) } -/* This needs to be shunted out of here into the board specific bit */ -#define HARP_PCI_IRQ 1 -#define HARP_BRIDGE_IRQ 2 -#define OVERDRIVE_SLOT0_IRQ 0 - -static int __init map_harp_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - switch (slot) { -#ifdef CONFIG_SH_STB1_HARP - case 2: /*This is the PCI slot on the */ - return HARP_PCI_IRQ; - case 1: /* this is the bridge */ - return HARP_BRIDGE_IRQ; -#elif defined(CONFIG_SH_STB1_OVERDRIVE) - case 1: - case 2: - case 3: - return slot - 1; -#else -#error Unknown board -#endif - default: - return -1; - } -} - -void __init pcibios_init(void) +static int __init pcibios_init(void) { extern unsigned long memory_start, memory_end; + printk(KERN_ALERT "pci-st40.c: pcibios_init\n"); + if (sh_mv.mv_init_pci != NULL) { sh_mv.mv_init_pci(); } @@ -392,7 +450,7 @@ void __init pcibios_init(void) if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq, SA_INTERRUPT, "st40pci", NULL)) { printk(KERN_ERR "st40pci: Cannot hook interrupt\n"); - return; + return -EIO; } /* Enable the PCI interrupts on the device */ @@ -406,12 +464,46 @@ void __init pcibios_init(void) #endif /* ok, do the scan man */ - pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL); + pci_root_bus = pci_scan_bus(0, &st40pci_config_ops, NULL); pci_assign_unassigned_resources(); - pci_fixup_irqs(no_swizzle, map_harp_irq); + pci_fixup_irqs(no_swizzle, pcibios_map_platform_irq); + return 0; } +subsys_initcall(pcibios_init); + void __init pcibios_fixup_bus(struct pci_bus *bus) { } + +/* + * Publish a region of local address space over the PCI bus + * to other devices. + */ +static void pci_set_rbar_region(unsigned int region, unsigned long localAddr, + unsigned long pciOffset, unsigned long regionSize) +{ + unsigned long mask; + + if (region > 7) + return; + + if (regionSize > (512 * 1024 * 1024)) + return; + + mask = r2p2(regionSize) - 0x10000; + + /* Diable the region (in case currently in use, should never happen) */ + ST40PCI_WRITE_INDEXED(RSR, region, 0); + + /* Start of local address space to publish */ + ST40PCI_WRITE_INDEXED(RLAR, region, PHYSADDR(localAddr) ); + + /* Start of region in PCI address space as an offset from MBAR0 */ + ST40PCI_WRITE_INDEXED(RBAR, region, pciOffset); + + /* Size of region */ + ST40PCI_WRITE_INDEXED(RSR, region, mask | 1); +} + diff --git a/arch/sh/drivers/pci/pci-st40.h b/arch/sh/drivers/pci/pci-st40.h index 2e3451a97c7fd..d729e0c2d5fee 100644 --- a/arch/sh/drivers/pci/pci-st40.h +++ b/arch/sh/drivers/pci/pci-st40.h @@ -33,13 +33,36 @@ #define ST40PCI_LAR0 0x1c #define ST40PCI_INT 0x24 +#define INT_MNLTDIM (1<<15) +#define INT_TTADI (1<<14) +#define INT_TMTO (1<<9) +#define INT_MDEI (1<<8) +#define INT_APEDI (1<<7) +#define INT_SDI (1<<6) +#define INT_DPEITW (1<<5) +#define INT_PEDITR (1<<4) +#define INT_TADIM (1<<3) #define INT_MADIM (1<<2) +#define INT_MWPDI (1<<1) +#define INT_MRDPEI (1<<0) #define ST40PCI_INTM 0x28 #define ST40PCI_AIR 0x2c + #define ST40PCI_CIR 0x30 +#define CIR_PIOTEM (1<<31) +#define CIR_RWTET (1<<26) + #define ST40PCI_AINT 0x40 +#define AINT_MBI (1<<13) +#define AINT_TBTOI (1<<12) +#define AINT_MBTOI (1<<11) +#define AINT_TAI (1<<3) +#define AINT_MAI (1<<2) +#define AINT_RDPEI (1<<1) +#define AINT_WDPE (1<<0) + #define ST40PCI_AINTM 0x44 #define ST40PCI_BMIR 0x48 #define ST40PCI_PAR 0x4c @@ -51,6 +74,53 @@ #define ST40PCI_IOBMR 0x74 #define ST40PCI_PDR 0x78 +/* H8 specific registers start here */ +#define ST40PCI_WCBAR 0x7c +#define ST40PCI_LOCCFG_UNLOCK 0x34 + +#define ST40PCI_RBAR0 0x100 +#define ST40PCI_RSR0 0x104 +#define ST40PCI_RLAR0 0x108 + +#define ST40PCI_RBAR1 0x110 +#define ST40PCI_RSR1 0x114 +#define ST40PCI_RLAR1 0x118 + + +#define ST40PCI_RBAR2 0x120 +#define ST40PCI_RSR2 0x124 +#define ST40PCI_RLAR2 0x128 + +#define ST40PCI_RBAR3 0x130 +#define ST40PCI_RSR3 0x134 +#define ST40PCI_RLAR3 0x138 + +#define ST40PCI_RBAR4 0x140 +#define ST40PCI_RSR4 0x144 +#define ST40PCI_RLAR4 0x148 + +#define ST40PCI_RBAR5 0x150 +#define ST40PCI_RSR5 0x154 +#define ST40PCI_RLAR5 0x158 + +#define ST40PCI_RBAR6 0x160 +#define ST40PCI_RSR6 0x164 +#define ST40PCI_RLAR6 0x168 + +#define ST40PCI_RBAR7 0x170 +#define ST40PCI_RSR7 0x174 +#define ST40PCI_RLAR7 0x178 + + +#define ST40PCI_RBAR(n) (0x100+(0x10*(n))) +#define ST40PCI_RSR(n) (0x104+(0x10*(n))) +#define ST40PCI_RLAR(n) (0x108+(0x10*(n))) + +#define ST40PCI_PERF 0x80 +#define PERF_MASTER_WRITE_POSTING (1<<4) +/* H8 specific registers end here */ + + /* These are configs space registers */ #define ST40PCI_CSR_VID 0x10000 #define ST40PCI_CSR_DID 0x10002 diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 4bf35336d8249..363bc839b2840 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -106,6 +106,8 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) pci_read_config_word(dev, PCI_COMMAND, &cmd); old_cmd = cmd; for(idx=0; idx<6; idx++) { + if (!(mask & (1 << idx))) + continue; r = &dev->resource[idx]; if (!r->start && r->end) { printk(KERN_ERR "PCI: Device %s not available because " -- 2.53.0