sh: Reworked SH7780 PCI initialization.
[linux-2.6.git] / arch / sh / drivers / pci / pci-sh7780.c
1 /*
2  * Low-Level PCI Support for the SH7780
3  *
4  *  Copyright (C) 2005 - 2010  Paul Mundt
5  *
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.
9  */
10 #include <linux/types.h>
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/pci.h>
14 #include <linux/errno.h>
15 #include <linux/delay.h>
16 #include "pci-sh4.h"
17 #include <asm/mmu.h>
18 #include <asm/sizes.h>
19
20 static struct resource sh7785_io_resource = {
21         .name   = "SH7785_IO",
22         .start  = 0x1000,
23         .end    = SH7780_PCI_IO_SIZE - 1,
24         .flags  = IORESOURCE_IO
25 };
26
27 static struct resource sh7785_mem_resource = {
28         .name   = "SH7785_mem",
29         .start  = SH7780_PCI_MEMORY_BASE,
30         .end    = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
31         .flags  = IORESOURCE_MEM
32 };
33
34 static struct pci_channel sh7780_pci_controller = {
35         .pci_ops        = &sh4_pci_ops,
36         .mem_resource   = &sh7785_mem_resource,
37         .mem_offset     = 0x00000000,
38         .io_resource    = &sh7785_io_resource,
39         .io_offset      = 0x00000000,
40         .io_map_base    = SH7780_PCI_IO_BASE,
41 };
42
43 static int __init sh7780_pci_init(void)
44 {
45         struct pci_channel *chan = &sh7780_pci_controller;
46         phys_addr_t memphys;
47         size_t memsize;
48         unsigned int id;
49         const char *type;
50         int ret;
51
52         printk(KERN_NOTICE "PCI: Starting intialization.\n");
53
54         chan->reg_base = 0xfe040000;
55
56         /* Enable CPU access to the PCIC registers. */
57         __raw_writel(PCIECR_ENBL, PCIECR);
58
59         /* Reset */
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) {
68                 printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id);
69                 return -ENODEV;
70         }
71
72         id = __raw_readw(chan->reg_base + PCI_DEVICE_ID);
73         type = (id == PCI_DEVICE_ID_RENESAS_SH7763) ? "SH7763" :
74                (id == PCI_DEVICE_ID_RENESAS_SH7780) ? "SH7780" :
75                (id == PCI_DEVICE_ID_RENESAS_SH7781) ? "SH7781" :
76                (id == PCI_DEVICE_ID_RENESAS_SH7785) ? "SH7785" :
77                                           NULL;
78         if (unlikely(!type)) {
79                 printk(KERN_ERR "PCI: Found an unsupported Renesas host "
80                        "controller, device id 0x%04x.\n", id);
81                 return -EINVAL;
82         }
83
84         printk(KERN_NOTICE "PCI: Found a Renesas %s host "
85                "controller, revision %d.\n", type,
86                __raw_readb(chan->reg_base + PCI_REVISION_ID));
87
88         if ((ret = sh4_pci_check_direct(chan)) != 0)
89                 return ret;
90
91         /*
92          * Now throw it in to register initialization mode and
93          * start the real work.
94          */
95         __raw_writel(SH4_PCICR_PREFIX, chan->reg_base + SH4_PCICR);
96
97         memphys = __pa(memory_start);
98         memsize = memory_end - memory_start;
99
100         /*
101          * Set IO and Mem windows to local address
102          * Make PCI and local address the same for easy 1 to 1 mapping
103          */
104         __raw_writel(0, chan->reg_base + PCI_BASE_ADDRESS_0);
105
106         __raw_writel(memphys, chan->reg_base + SH4_PCILAR0);
107         __raw_writel((memsize - 1) << 9 | 1,
108                      chan->reg_base + SH4_PCILSR0);
109
110         /* Clear out PCI arbiter IRQs */
111         __raw_writel(0, chan->reg_base + SH4_PCIAINT);
112
113         /* Unmask all of the arbiter IRQs. */
114         __raw_writel(SH4_PCIAINT_MBKN | SH4_PCIAINT_TBTO | SH4_PCIAINT_MBTO | \
115                      SH4_PCIAINT_TABT | SH4_PCIAINT_MABT | SH4_PCIAINT_RDPE | \
116                      SH4_PCIAINT_WDPE, chan->reg_base + SH4_PCIAINTM);
117
118         /* Clear all error conditions */
119         __raw_writew(PCI_STATUS_DETECTED_PARITY  | \
120                      PCI_STATUS_SIG_SYSTEM_ERROR | \
121                      PCI_STATUS_REC_MASTER_ABORT | \
122                      PCI_STATUS_REC_TARGET_ABORT | \
123                      PCI_STATUS_SIG_TARGET_ABORT | \
124                      PCI_STATUS_PARITY, chan->reg_base + PCI_STATUS);
125
126         __raw_writew(PCI_COMMAND_SERR | PCI_COMMAND_WAIT | \
127                      PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | \
128                      PCI_COMMAND_MEMORY, chan->reg_base + PCI_COMMAND);
129
130         /* Unmask all of the PCI IRQs */
131         __raw_writel(SH4_PCIINTM_TTADIM  | SH4_PCIINTM_TMTOIM  | \
132                      SH4_PCIINTM_MDEIM   | SH4_PCIINTM_APEDIM  | \
133                      SH4_PCIINTM_SDIM    | SH4_PCIINTM_DPEITWM | \
134                      SH4_PCIINTM_PEDITRM | SH4_PCIINTM_TADIMM  | \
135                      SH4_PCIINTM_MADIMM  | SH4_PCIINTM_MWPDIM  | \
136                      SH4_PCIINTM_MRDPEIM, chan->reg_base + SH4_PCIINTM);
137
138         /*
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);
158
159         register_pci_controller(chan);
160
161         return 0;
162 }
163 arch_initcall(sh7780_pci_init);