]>
Commit | Line | Data |
---|---|---|
5283ecb5 | 1 | /* |
62c7ae87 | 2 | * Low-Level PCI Support for the SH7780 |
5283ecb5 | 3 | * |
62c7ae87 | 4 | * Copyright (C) 2005 - 2009 Paul Mundt |
5283ecb5 | 5 | * |
62c7ae87 PM |
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 | |
8 | * for more details. | |
5283ecb5 | 9 | */ |
5283ecb5 PM |
10 | #include <linux/types.h> |
11 | #include <linux/kernel.h> | |
12 | #include <linux/init.h> | |
13 | #include <linux/pci.h> | |
5283ecb5 | 14 | #include <linux/errno.h> |
5283ecb5 | 15 | #include <linux/delay.h> |
959f85f8 | 16 | #include "pci-sh4.h" |
5283ecb5 | 17 | |
ab1363a8 | 18 | static int __init sh7780_pci_init(struct pci_channel *chan) |
5283ecb5 | 19 | { |
959f85f8 | 20 | unsigned int id; |
4e7b7fdb PM |
21 | const char *type = NULL; |
22 | int ret; | |
5283ecb5 | 23 | |
4e7b7fdb | 24 | printk(KERN_NOTICE "PCI: Starting intialization.\n"); |
5283ecb5 | 25 | |
e4c6a360 | 26 | chan->reg_base = 0xfe040000; |
ef53fdeb | 27 | chan->io_base = 0xfe200000; |
e4c6a360 | 28 | |
4e7b7fdb PM |
29 | /* Enable CPU access to the PCIC registers. */ |
30 | __raw_writel(PCIECR_ENBL, PCIECR); | |
5283ecb5 | 31 | |
4e7b7fdb PM |
32 | id = __raw_readw(chan->reg_base + SH7780_PCIVID); |
33 | if (id != SH7780_VENDOR_ID) { | |
34 | printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id); | |
35 | return -ENODEV; | |
32351a28 PM |
36 | } |
37 | ||
4e7b7fdb PM |
38 | id = __raw_readw(chan->reg_base + SH7780_PCIDID); |
39 | type = (id == SH7763_DEVICE_ID) ? "SH7763" : | |
40 | (id == SH7780_DEVICE_ID) ? "SH7780" : | |
41 | (id == SH7781_DEVICE_ID) ? "SH7781" : | |
42 | (id == SH7785_DEVICE_ID) ? "SH7785" : | |
43 | NULL; | |
44 | if (unlikely(!type)) { | |
45 | printk(KERN_ERR "PCI: Found an unsupported Renesas host " | |
46 | "controller, device id 0x%04x.\n", id); | |
47 | return -EINVAL; | |
5283ecb5 PM |
48 | } |
49 | ||
4e7b7fdb PM |
50 | printk(KERN_NOTICE "PCI: Found a Renesas %s host " |
51 | "controller, revision %d.\n", type, | |
52 | __raw_readb(chan->reg_base + SH7780_PCIRID)); | |
53 | ||
d0e3db40 | 54 | if ((ret = sh4_pci_check_direct(chan)) != 0) |
5283ecb5 PM |
55 | return ret; |
56 | ||
c66c1d79 PM |
57 | /* |
58 | * Platform specific initialization (BSC registers, and memory space | |
59 | * mapping) will be called via the platform defined function | |
60 | * pcibios_init_platform(). | |
61 | */ | |
5283ecb5 PM |
62 | return pcibios_init_platform(); |
63 | } | |
5283ecb5 | 64 | |
c66c1d79 PM |
65 | extern u8 pci_cache_line_size; |
66 | ||
ab1363a8 PM |
67 | static struct resource sh7785_io_resource = { |
68 | .name = "SH7785_IO", | |
69 | .start = SH7780_PCI_IO_BASE, | |
70 | .end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1, | |
71 | .flags = IORESOURCE_IO | |
72 | }; | |
73 | ||
74 | static struct resource sh7785_mem_resource = { | |
75 | .name = "SH7785_mem", | |
76 | .start = SH7780_PCI_MEMORY_BASE, | |
77 | .end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1, | |
78 | .flags = IORESOURCE_MEM | |
79 | }; | |
80 | ||
81 | struct pci_channel board_pci_channels[] = { | |
82 | { sh7780_pci_init, &sh4_pci_ops, &sh7785_io_resource, &sh7785_mem_resource, 0, 0xff }, | |
83 | { NULL, NULL, NULL, 0, 0 }, | |
84 | }; | |
85 | ||
4c7a47de PM |
86 | static struct sh4_pci_address_map sh7780_pci_map = { |
87 | .window0 = { | |
88 | #if defined(CONFIG_32BIT) | |
89 | .base = SH7780_32BIT_DDR_BASE_ADDR, | |
90 | .size = 0x40000000, | |
91 | #else | |
92 | .base = SH7780_CS0_BASE_ADDR, | |
93 | .size = 0x20000000, | |
94 | #endif | |
95 | }, | |
96 | }; | |
97 | ||
98 | int __init pcibios_init_platform(void) | |
5283ecb5 | 99 | { |
ab1363a8 | 100 | struct pci_channel *chan = &board_pci_channels[0]; |
5283ecb5 PM |
101 | u32 word; |
102 | ||
c66c1d79 PM |
103 | /* |
104 | * Set the class and sub-class codes. | |
105 | */ | |
ab78cbcf PM |
106 | __raw_writeb(PCI_CLASS_BRIDGE_HOST >> 8, |
107 | chan->reg_base + SH7780_PCIBCC); | |
108 | __raw_writeb(PCI_CLASS_BRIDGE_HOST & 0xff, | |
109 | chan->reg_base + SH7780_PCISUB); | |
0bbc9bc3 | 110 | |
c66c1d79 PM |
111 | pci_cache_line_size = pci_read_reg(chan, SH7780_PCICLS) / 4; |
112 | ||
62c7ae87 PM |
113 | /* |
114 | * Set IO and Mem windows to local address | |
5283ecb5 | 115 | * Make PCI and local address the same for easy 1 to 1 mapping |
5283ecb5 | 116 | */ |
4c7a47de | 117 | pci_write_reg(chan, sh7780_pci_map.window0.size - 0xfffff, SH4_PCILSR0); |
5283ecb5 | 118 | /* Set the values on window 0 PCI config registers */ |
4c7a47de PM |
119 | pci_write_reg(chan, sh7780_pci_map.window0.base, SH4_PCILAR0); |
120 | pci_write_reg(chan, sh7780_pci_map.window0.base, SH7780_PCIMBAR0); | |
5283ecb5 | 121 | |
62c7ae87 PM |
122 | pci_write_reg(chan, 0x0000380f, SH4_PCIAINTM); |
123 | ||
124 | /* Set up standard PCI config registers */ | |
125 | __raw_writew(0xFB00, chan->reg_base + SH7780_PCISTATUS); | |
126 | __raw_writew(0x0047, chan->reg_base + SH7780_PCICMD); | |
127 | __raw_writew(0x1912, chan->reg_base + SH7780_PCISVID); | |
128 | __raw_writew(0x0001, chan->reg_base + SH7780_PCISID); | |
129 | ||
130 | __raw_writeb(0x00, chan->reg_base + SH7780_PCIPIF); | |
131 | ||
b7576230 | 132 | /* Apply any last-minute PCIC fixups */ |
b8b47bfb | 133 | pci_fixup_pcic(chan); |
5283ecb5 | 134 | |
62c7ae87 PM |
135 | pci_write_reg(chan, 0xfd000000, SH7780_PCIMBR0); |
136 | pci_write_reg(chan, 0x00fc0000, SH7780_PCIMBMR0); | |
137 | ||
138 | #ifdef CONFIG_32BIT | |
139 | pci_write_reg(chan, 0xc0000000, SH7780_PCIMBR2); | |
140 | pci_write_reg(chan, 0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2); | |
141 | #endif | |
142 | ||
143 | /* Set IOBR for windows containing area specified in pci.h */ | |
144 | pci_write_reg(chan, chan->io_resource->start & ~(SH7780_PCI_IO_SIZE-1), | |
145 | SH7780_PCIIOBR); | |
146 | pci_write_reg(chan, ((SH7780_PCI_IO_SIZE-1) & (7<<18)), | |
147 | SH7780_PCIIOBMR); | |
148 | ||
5283ecb5 PM |
149 | /* SH7780 init done, set central function init complete */ |
150 | /* use round robin mode to stop a device starving/overruning */ | |
959f85f8 | 151 | word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO; |
b8b47bfb | 152 | pci_write_reg(chan, word, SH4_PCICR); |
5283ecb5 | 153 | |
f1dcab75 PM |
154 | __set_io_port_base(SH7780_PCI_IO_BASE); |
155 | ||
d0e3db40 | 156 | return 0; |
5283ecb5 | 157 | } |