]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - arch/sh/drivers/pci/pci-sh7780.c
sh: pci: Rework fixed region checks in ioremap().
[mirror_ubuntu-jammy-kernel.git] / arch / sh / drivers / pci / pci-sh7780.c
CommitLineData
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 18static 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
65extern u8 pci_cache_line_size;
66
ab1363a8
PM
67static 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
74static 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
81struct 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
86static 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
98int __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}