blob: 019e1afcd0a390c7c501b6d037389920d3f26afa [file] [log] [blame]
Paul Mundt5283ecb2006-09-27 15:59:17 +09001/*
Paul Mundt62c7ae82009-04-17 20:37:16 +09002 * Low-Level PCI Support for the SH7780
Paul Mundt5283ecb2006-09-27 15:59:17 +09003 *
Paul Mundta45635d2010-01-29 22:19:04 +09004 * Copyright (C) 2005 - 2010 Paul Mundt
Paul Mundt5283ecb2006-09-27 15:59:17 +09005 *
Paul Mundt62c7ae82009-04-17 20:37:16 +09006 * 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.
Paul Mundt5283ecb2006-09-27 15:59:17 +09009 */
Paul Mundt5283ecb2006-09-27 15:59:17 +090010#include <linux/types.h>
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/pci.h>
Paul Mundt5283ecb2006-09-27 15:59:17 +090014#include <linux/errno.h>
Paul Mundt5283ecb2006-09-27 15:59:17 +090015#include <linux/delay.h>
Paul Mundt959f85f2006-09-27 16:43:28 +090016#include "pci-sh4.h"
Paul Mundta45635d2010-01-29 22:19:04 +090017#include <asm/mmu.h>
18#include <asm/sizes.h>
Paul Mundt5283ecb2006-09-27 15:59:17 +090019
Paul Mundte79066a2009-04-20 18:29:22 +090020static struct resource sh7785_io_resource = {
21 .name = "SH7785_IO",
Paul Mundta45635d2010-01-29 22:19:04 +090022 .start = 0x1000,
23 .end = SH7780_PCI_IO_SIZE - 1,
Paul Mundte79066a2009-04-20 18:29:22 +090024 .flags = IORESOURCE_IO
25};
26
27static 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
34static struct pci_channel sh7780_pci_controller = {
35 .pci_ops = &sh4_pci_ops,
36 .mem_resource = &sh7785_mem_resource,
Paul Mundt09cfeb12009-04-20 18:42:00 +090037 .mem_offset = 0x00000000,
Paul Mundte79066a2009-04-20 18:29:22 +090038 .io_resource = &sh7785_io_resource,
Paul Mundt09cfeb12009-04-20 18:42:00 +090039 .io_offset = 0x00000000,
Paul Mundt5582b062009-05-27 00:12:58 +090040 .io_map_base = SH7780_PCI_IO_BASE,
Paul Mundte79066a2009-04-20 18:29:22 +090041};
42
Paul Mundte79066a2009-04-20 18:29:22 +090043static int __init sh7780_pci_init(void)
Paul Mundt5283ecb2006-09-27 15:59:17 +090044{
Paul Mundte79066a2009-04-20 18:29:22 +090045 struct pci_channel *chan = &sh7780_pci_controller;
Paul Mundta45635d2010-01-29 22:19:04 +090046 phys_addr_t memphys;
47 size_t memsize;
Paul Mundt959f85f2006-09-27 16:43:28 +090048 unsigned int id;
Paul Mundta45635d2010-01-29 22:19:04 +090049 const char *type;
Paul Mundt4e7b7fd2009-04-17 15:05:19 +090050 int ret;
Paul Mundt5283ecb2006-09-27 15:59:17 +090051
Paul Mundt4e7b7fd2009-04-17 15:05:19 +090052 printk(KERN_NOTICE "PCI: Starting intialization.\n");
Paul Mundt5283ecb2006-09-27 15:59:17 +090053
Magnus Damme4c6a362008-02-19 21:35:04 +090054 chan->reg_base = 0xfe040000;
55
Paul Mundt4e7b7fd2009-04-17 15:05:19 +090056 /* Enable CPU access to the PCIC registers. */
57 __raw_writel(PCIECR_ENBL, PCIECR);
Paul Mundt959f85f2006-09-27 16:43:28 +090058
Paul Mundta45635d2010-01-29 22:19:04 +090059 /* 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) {
Paul Mundt4e7b7fd2009-04-17 15:05:19 +090068 printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id);
Paul Mundt959f85f2006-09-27 16:43:28 +090069 return -ENODEV;
70 }
71
Paul Mundta45635d2010-01-29 22:19:04 +090072 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" :
Paul Mundt4e7b7fd2009-04-17 15:05:19 +090077 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,
Paul Mundta45635d2010-01-29 22:19:04 +090086 __raw_readb(chan->reg_base + PCI_REVISION_ID));
Paul Mundt4e7b7fd2009-04-17 15:05:19 +090087
Magnus Dammd0e3db42009-03-11 15:46:14 +090088 if ((ret = sh4_pci_check_direct(chan)) != 0)
Paul Mundt5283ecb2006-09-27 15:59:17 +090089 return ret;
90
Paul Mundtc66c1d72009-04-17 16:38:00 +090091 /*
Paul Mundta45635d2010-01-29 22:19:04 +090092 * Now throw it in to register initialization mode and
93 * start the real work.
Paul Mundtc66c1d72009-04-17 16:38:00 +090094 */
Paul Mundta45635d2010-01-29 22:19:04 +090095 __raw_writel(SH4_PCICR_PREFIX, chan->reg_base + SH4_PCICR);
96
97 memphys = __pa(memory_start);
98 memsize = memory_end - memory_start;
Paul Mundt0bbc9bc2009-04-17 14:09:09 +090099
Paul Mundt62c7ae82009-04-17 20:37:16 +0900100 /*
101 * Set IO and Mem windows to local address
Paul Mundt5283ecb2006-09-27 15:59:17 +0900102 * Make PCI and local address the same for easy 1 to 1 mapping
Paul Mundt5283ecb2006-09-27 15:59:17 +0900103 */
Paul Mundta45635d2010-01-29 22:19:04 +0900104 __raw_writel(0, chan->reg_base + PCI_BASE_ADDRESS_0);
Paul Mundt5283ecb2006-09-27 15:59:17 +0900105
Paul Mundta45635d2010-01-29 22:19:04 +0900106 __raw_writel(memphys, chan->reg_base + SH4_PCILAR0);
107 __raw_writel((memsize - 1) << 9 | 1,
108 chan->reg_base + SH4_PCILSR0);
Paul Mundt62c7ae82009-04-17 20:37:16 +0900109
Paul Mundta45635d2010-01-29 22:19:04 +0900110 /* Clear out PCI arbiter IRQs */
111 __raw_writel(0, chan->reg_base + SH4_PCIAINT);
Paul Mundt62c7ae82009-04-17 20:37:16 +0900112
Paul Mundta45635d2010-01-29 22:19:04 +0900113 /* 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);
Paul Mundt62c7ae82009-04-17 20:37:16 +0900117
Paul Mundta45635d2010-01-29 22:19:04 +0900118 /* 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);
Paul Mundt5283ecb2006-09-27 15:59:17 +0900125
Paul Mundta45635d2010-01-29 22:19:04 +0900126 __raw_writew(PCI_COMMAND_SERR | PCI_COMMAND_WAIT | \
127 PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | \
128 PCI_COMMAND_MEMORY, chan->reg_base + PCI_COMMAND);
Paul Mundt62c7ae82009-04-17 20:37:16 +0900129
Paul Mundta45635d2010-01-29 22:19:04 +0900130 /* 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);
Paul Mundt62c7ae82009-04-17 20:37:16 +0900137
Paul Mundta45635d2010-01-29 22:19:04 +0900138 /*
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);
Paul Mundt62c7ae82009-04-17 20:37:16 +0900145
Paul Mundta45635d2010-01-29 22:19:04 +0900146 __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);
Paul Mundt5283ecb2006-09-27 15:59:17 +0900158
Paul Mundte79066a2009-04-20 18:29:22 +0900159 register_pci_controller(chan);
160
Magnus Dammd0e3db42009-03-11 15:46:14 +0900161 return 0;
Paul Mundt5283ecb2006-09-27 15:59:17 +0900162}
Paul Mundte79066a2009-04-20 18:29:22 +0900163arch_initcall(sh7780_pci_init);