diff options
Diffstat (limited to 'arch/sh/drivers/pci/pci-sh7780.c')
-rw-r--r-- | arch/sh/drivers/pci/pci-sh7780.c | 149 |
1 files changed, 83 insertions, 66 deletions
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c index 323b92d565fe..019e1afcd0a3 100644 --- a/arch/sh/drivers/pci/pci-sh7780.c +++ b/arch/sh/drivers/pci/pci-sh7780.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Low-Level PCI Support for the SH7780 | 2 | * Low-Level PCI Support for the SH7780 |
3 | * | 3 | * |
4 | * Copyright (C) 2005 - 2009 Paul Mundt | 4 | * Copyright (C) 2005 - 2010 Paul Mundt |
5 | * | 5 | * |
6 | * This file is subject to the terms and conditions of the GNU General Public | 6 | * This file is subject to the terms and conditions of the GNU General Public |
7 | * License. See the file "COPYING" in the main directory of this archive | 7 | * License. See the file "COPYING" in the main directory of this archive |
@@ -14,11 +14,13 @@ | |||
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include "pci-sh4.h" | 16 | #include "pci-sh4.h" |
17 | #include <asm/mmu.h> | ||
18 | #include <asm/sizes.h> | ||
17 | 19 | ||
18 | static struct resource sh7785_io_resource = { | 20 | static struct resource sh7785_io_resource = { |
19 | .name = "SH7785_IO", | 21 | .name = "SH7785_IO", |
20 | .start = SH7780_PCI_IO_BASE, | 22 | .start = 0x1000, |
21 | .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1, | 23 | .end = SH7780_PCI_IO_SIZE - 1, |
22 | .flags = IORESOURCE_IO | 24 | .flags = IORESOURCE_IO |
23 | }; | 25 | }; |
24 | 26 | ||
@@ -38,25 +40,14 @@ static struct pci_channel sh7780_pci_controller = { | |||
38 | .io_map_base = SH7780_PCI_IO_BASE, | 40 | .io_map_base = SH7780_PCI_IO_BASE, |
39 | }; | 41 | }; |
40 | 42 | ||
41 | static struct sh4_pci_address_map sh7780_pci_map = { | ||
42 | .window0 = { | ||
43 | #if defined(CONFIG_32BIT) | ||
44 | .base = SH7780_32BIT_DDR_BASE_ADDR, | ||
45 | .size = 0x40000000, | ||
46 | #else | ||
47 | .base = SH7780_CS0_BASE_ADDR, | ||
48 | .size = 0x20000000, | ||
49 | #endif | ||
50 | }, | ||
51 | }; | ||
52 | |||
53 | static int __init sh7780_pci_init(void) | 43 | static int __init sh7780_pci_init(void) |
54 | { | 44 | { |
55 | struct pci_channel *chan = &sh7780_pci_controller; | 45 | struct pci_channel *chan = &sh7780_pci_controller; |
46 | phys_addr_t memphys; | ||
47 | size_t memsize; | ||
56 | unsigned int id; | 48 | unsigned int id; |
57 | const char *type = NULL; | 49 | const char *type; |
58 | int ret; | 50 | int ret; |
59 | u32 word; | ||
60 | 51 | ||
61 | printk(KERN_NOTICE "PCI: Starting intialization.\n"); | 52 | printk(KERN_NOTICE "PCI: Starting intialization.\n"); |
62 | 53 | ||
@@ -65,17 +56,24 @@ static int __init sh7780_pci_init(void) | |||
65 | /* Enable CPU access to the PCIC registers. */ | 56 | /* Enable CPU access to the PCIC registers. */ |
66 | __raw_writel(PCIECR_ENBL, PCIECR); | 57 | __raw_writel(PCIECR_ENBL, PCIECR); |
67 | 58 | ||
68 | id = __raw_readw(chan->reg_base + SH7780_PCIVID); | 59 | /* Reset */ |
69 | if (id != SH7780_VENDOR_ID) { | 60 | __raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_PRST, |
61 | chan->reg_base + SH4_PCICR); | ||
62 | |||
63 | /* Wait for it to come back up.. */ | ||
64 | mdelay(100); | ||
65 | |||
66 | id = __raw_readw(chan->reg_base + PCI_VENDOR_ID); | ||
67 | if (id != PCI_VENDOR_ID_RENESAS) { | ||
70 | printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id); | 68 | printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id); |
71 | return -ENODEV; | 69 | return -ENODEV; |
72 | } | 70 | } |
73 | 71 | ||
74 | id = __raw_readw(chan->reg_base + SH7780_PCIDID); | 72 | id = __raw_readw(chan->reg_base + PCI_DEVICE_ID); |
75 | type = (id == SH7763_DEVICE_ID) ? "SH7763" : | 73 | type = (id == PCI_DEVICE_ID_RENESAS_SH7763) ? "SH7763" : |
76 | (id == SH7780_DEVICE_ID) ? "SH7780" : | 74 | (id == PCI_DEVICE_ID_RENESAS_SH7780) ? "SH7780" : |
77 | (id == SH7781_DEVICE_ID) ? "SH7781" : | 75 | (id == PCI_DEVICE_ID_RENESAS_SH7781) ? "SH7781" : |
78 | (id == SH7785_DEVICE_ID) ? "SH7785" : | 76 | (id == PCI_DEVICE_ID_RENESAS_SH7785) ? "SH7785" : |
79 | NULL; | 77 | NULL; |
80 | if (unlikely(!type)) { | 78 | if (unlikely(!type)) { |
81 | printk(KERN_ERR "PCI: Found an unsupported Renesas host " | 79 | printk(KERN_ERR "PCI: Found an unsupported Renesas host " |
@@ -85,59 +83,78 @@ static int __init sh7780_pci_init(void) | |||
85 | 83 | ||
86 | printk(KERN_NOTICE "PCI: Found a Renesas %s host " | 84 | printk(KERN_NOTICE "PCI: Found a Renesas %s host " |
87 | "controller, revision %d.\n", type, | 85 | "controller, revision %d.\n", type, |
88 | __raw_readb(chan->reg_base + SH7780_PCIRID)); | 86 | __raw_readb(chan->reg_base + PCI_REVISION_ID)); |
89 | 87 | ||
90 | if ((ret = sh4_pci_check_direct(chan)) != 0) | 88 | if ((ret = sh4_pci_check_direct(chan)) != 0) |
91 | return ret; | 89 | return ret; |
92 | 90 | ||
93 | /* | 91 | /* |
94 | * Set the class and sub-class codes. | 92 | * Now throw it in to register initialization mode and |
93 | * start the real work. | ||
95 | */ | 94 | */ |
96 | __raw_writeb(PCI_CLASS_BRIDGE_HOST >> 8, | 95 | __raw_writel(SH4_PCICR_PREFIX, chan->reg_base + SH4_PCICR); |
97 | chan->reg_base + SH7780_PCIBCC); | 96 | |
98 | __raw_writeb(PCI_CLASS_BRIDGE_HOST & 0xff, | 97 | memphys = __pa(memory_start); |
99 | chan->reg_base + SH7780_PCISUB); | 98 | memsize = memory_end - memory_start; |
100 | 99 | ||
101 | /* | 100 | /* |
102 | * Set IO and Mem windows to local address | 101 | * Set IO and Mem windows to local address |
103 | * Make PCI and local address the same for easy 1 to 1 mapping | 102 | * Make PCI and local address the same for easy 1 to 1 mapping |
104 | */ | 103 | */ |
105 | pci_write_reg(chan, sh7780_pci_map.window0.size - 0xfffff, SH4_PCILSR0); | 104 | __raw_writel(0, chan->reg_base + PCI_BASE_ADDRESS_0); |
106 | /* Set the values on window 0 PCI config registers */ | 105 | |
107 | pci_write_reg(chan, sh7780_pci_map.window0.base, SH4_PCILAR0); | 106 | __raw_writel(memphys, chan->reg_base + SH4_PCILAR0); |
108 | pci_write_reg(chan, sh7780_pci_map.window0.base, SH7780_PCIMBAR0); | 107 | __raw_writel((memsize - 1) << 9 | 1, |
109 | 108 | chan->reg_base + SH4_PCILSR0); | |
110 | pci_write_reg(chan, 0x0000380f, SH4_PCIAINTM); | 109 | |
111 | 110 | /* Clear out PCI arbiter IRQs */ | |
112 | /* Set up standard PCI config registers */ | 111 | __raw_writel(0, chan->reg_base + SH4_PCIAINT); |
113 | __raw_writew(0xFB00, chan->reg_base + SH7780_PCISTATUS); | 112 | |
114 | __raw_writew(0x0047, chan->reg_base + SH7780_PCICMD); | 113 | /* Unmask all of the arbiter IRQs. */ |
115 | __raw_writew(0x1912, chan->reg_base + SH7780_PCISVID); | 114 | __raw_writel(SH4_PCIAINT_MBKN | SH4_PCIAINT_TBTO | SH4_PCIAINT_MBTO | \ |
116 | __raw_writew(0x0001, chan->reg_base + SH7780_PCISID); | 115 | SH4_PCIAINT_TABT | SH4_PCIAINT_MABT | SH4_PCIAINT_RDPE | \ |
117 | 116 | SH4_PCIAINT_WDPE, chan->reg_base + SH4_PCIAINTM); | |
118 | __raw_writeb(0x00, chan->reg_base + SH7780_PCIPIF); | 117 | |
119 | 118 | /* Clear all error conditions */ | |
120 | /* Apply any last-minute PCIC fixups */ | 119 | __raw_writew(PCI_STATUS_DETECTED_PARITY | \ |
121 | pci_fixup_pcic(chan); | 120 | PCI_STATUS_SIG_SYSTEM_ERROR | \ |
122 | 121 | PCI_STATUS_REC_MASTER_ABORT | \ | |
123 | pci_write_reg(chan, 0xfd000000, SH7780_PCIMBR0); | 122 | PCI_STATUS_REC_TARGET_ABORT | \ |
124 | pci_write_reg(chan, 0x00fc0000, SH7780_PCIMBMR0); | 123 | PCI_STATUS_SIG_TARGET_ABORT | \ |
125 | 124 | PCI_STATUS_PARITY, chan->reg_base + PCI_STATUS); | |
126 | #ifdef CONFIG_32BIT | 125 | |
127 | pci_write_reg(chan, 0xc0000000, SH7780_PCIMBR2); | 126 | __raw_writew(PCI_COMMAND_SERR | PCI_COMMAND_WAIT | \ |
128 | pci_write_reg(chan, 0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2); | 127 | PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | \ |
129 | #endif | 128 | PCI_COMMAND_MEMORY, chan->reg_base + PCI_COMMAND); |
130 | 129 | ||
131 | /* Set IOBR for windows containing area specified in pci.h */ | 130 | /* Unmask all of the PCI IRQs */ |
132 | pci_write_reg(chan, chan->io_resource->start & ~(SH7780_PCI_IO_SIZE-1), | 131 | __raw_writel(SH4_PCIINTM_TTADIM | SH4_PCIINTM_TMTOIM | \ |
133 | SH7780_PCIIOBR); | 132 | SH4_PCIINTM_MDEIM | SH4_PCIINTM_APEDIM | \ |
134 | pci_write_reg(chan, ((SH7780_PCI_IO_SIZE-1) & (7<<18)), | 133 | SH4_PCIINTM_SDIM | SH4_PCIINTM_DPEITWM | \ |
135 | SH7780_PCIIOBMR); | 134 | SH4_PCIINTM_PEDITRM | SH4_PCIINTM_TADIMM | \ |
136 | 135 | SH4_PCIINTM_MADIMM | SH4_PCIINTM_MWPDIM | \ | |
137 | /* SH7780 init done, set central function init complete */ | 136 | SH4_PCIINTM_MRDPEIM, chan->reg_base + SH4_PCIINTM); |
138 | /* use round robin mode to stop a device starving/overruning */ | 137 | |
139 | word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO; | 138 | /* |
140 | pci_write_reg(chan, word, SH4_PCICR); | 139 | * Disable the cache snoop controller for non-coherent DMA. |
140 | */ | ||
141 | __raw_writel(0, chan->reg_base + SH7780_PCICSCR0); | ||
142 | __raw_writel(0, chan->reg_base + SH7780_PCICSAR0); | ||
143 | __raw_writel(0, chan->reg_base + SH7780_PCICSCR1); | ||
144 | __raw_writel(0, chan->reg_base + SH7780_PCICSAR1); | ||
145 | |||
146 | __raw_writel(0xfd000000, chan->reg_base + SH7780_PCIMBR0); | ||
147 | __raw_writel(0x00fc0000, chan->reg_base + SH7780_PCIMBMR0); | ||
148 | |||
149 | __raw_writel(0, chan->reg_base + SH7780_PCIIOBR); | ||
150 | __raw_writel(0, chan->reg_base + SH7780_PCIIOBMR); | ||
151 | |||
152 | /* | ||
153 | * Initialization mode complete, release the control register and | ||
154 | * enable round robin mode to stop device overruns/starvation. | ||
155 | */ | ||
156 | __raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO, | ||
157 | chan->reg_base + SH4_PCICR); | ||
141 | 158 | ||
142 | register_pci_controller(chan); | 159 | register_pci_controller(chan); |
143 | 160 | ||