aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/pmc-sierra
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /arch/mips/pmc-sierra
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'arch/mips/pmc-sierra')
-rw-r--r--arch/mips/pmc-sierra/yosemite/Makefile9
-rw-r--r--arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c169
-rw-r--r--arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h67
-rw-r--r--arch/mips/pmc-sierra/yosemite/ht-irq.c51
-rw-r--r--arch/mips/pmc-sierra/yosemite/ht.c415
-rw-r--r--arch/mips/pmc-sierra/yosemite/irq.c153
-rw-r--r--arch/mips/pmc-sierra/yosemite/prom.c143
-rw-r--r--arch/mips/pmc-sierra/yosemite/py-console.c117
-rw-r--r--arch/mips/pmc-sierra/yosemite/setup.c223
-rw-r--r--arch/mips/pmc-sierra/yosemite/setup.h32
-rw-r--r--arch/mips/pmc-sierra/yosemite/smp.c185
11 files changed, 1564 insertions, 0 deletions
diff --git a/arch/mips/pmc-sierra/yosemite/Makefile b/arch/mips/pmc-sierra/yosemite/Makefile
new file mode 100644
index 00000000000..02f5fb94ea2
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for the PMC-Sierra Titan
3#
4
5obj-y += irq.o prom.o py-console.o setup.o
6
7obj-$(CONFIG_SMP) += smp.o
8
9ccflags-y := -Werror
diff --git a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
new file mode 100644
index 00000000000..d6f8bdff8cb
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
@@ -0,0 +1,169 @@
1/*
2 * Copyright (C) 2003 PMC-Sierra Inc.
3 * Author: Manish Lachwani (lachwani@pmc-sierra.com)
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
11 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
13 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
14 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
15 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
16 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
17 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
18 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
19 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26/*
27 * Description:
28 *
29 * This code reads the ATMEL 24CXX EEPROM. The PMC-Sierra Yosemite board uses the ATMEL
30 * 24C32/24C64 which uses two byte addressing as compared to 24C16. Note that this program
31 * uses the serial port like /dev/ttyS0, to communicate with the EEPROM. Hence, you are
32 * expected to have a connectivity from the EEPROM to the serial port. This program does
33 * __not__ communicate using the I2C protocol
34 */
35
36#include "atmel_read_eeprom.h"
37
38static void delay(int delay)
39{
40 while (delay--);
41}
42
43static void send_bit(unsigned char bit)
44{
45 scl_lo;
46 delay(TXX);
47 if (bit)
48 sda_hi;
49 else
50 sda_lo;
51
52 delay(TXX);
53 scl_hi;
54 delay(TXX);
55}
56
57static void send_ack(void)
58{
59 send_bit(0);
60}
61
62static void send_byte(unsigned char byte)
63{
64 int i = 0;
65
66 for (i = 7; i >= 0; i--)
67 send_bit((byte >> i) & 0x01);
68}
69
70static void send_start(void)
71{
72 sda_hi;
73 delay(TXX);
74 scl_hi;
75 delay(TXX);
76 sda_lo;
77 delay(TXX);
78}
79
80static void send_stop(void)
81{
82 sda_lo;
83 delay(TXX);
84 scl_hi;
85 delay(TXX);
86 sda_hi;
87 delay(TXX);
88}
89
90static void do_idle(void)
91{
92 sda_hi;
93 scl_hi;
94 vcc_off;
95}
96
97static int recv_bit(void)
98{
99 int status;
100
101 scl_lo;
102 delay(TXX);
103 sda_hi;
104 delay(TXX);
105 scl_hi;
106 delay(TXX);
107
108 return 1;
109}
110
111static unsigned char recv_byte(void) {
112 int i;
113 unsigned char byte=0;
114
115 for (i=7;i>=0;i--)
116 byte |= (recv_bit() << i);
117
118 return byte;
119}
120
121static int recv_ack(void)
122{
123 unsigned int ack;
124
125 ack = (unsigned int)recv_bit();
126 scl_lo;
127
128 if (ack) {
129 do_idle();
130 printk(KERN_ERR "Error reading the Atmel 24C32/24C64 EEPROM\n");
131 return -1;
132 }
133
134 return ack;
135}
136
137/*
138 * This function does the actual read of the EEPROM. It needs the buffer into which the
139 * read data is copied, the size of the EEPROM being read and the buffer size
140 */
141int read_eeprom(char *buffer, int eeprom_size, int size)
142{
143 int i = 0, err;
144
145 send_start();
146 send_byte(W_HEADER);
147 recv_ack();
148
149 /* EEPROM with size of more than 2K need two byte addressing */
150 if (eeprom_size > 2048) {
151 send_byte(0x00);
152 recv_ack();
153 }
154
155 send_start();
156 send_byte(R_HEADER);
157 err = recv_ack();
158 if (err == -1)
159 return err;
160
161 for (i = 0; i < size; i++) {
162 *buffer++ = recv_byte();
163 send_ack();
164 }
165
166 /* Note : We should do some check if the buffer contains correct information */
167
168 send_stop();
169}
diff --git a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h
new file mode 100644
index 00000000000..d6c7ec469fa
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h
@@ -0,0 +1,67 @@
1/*
2 * arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
3 *
4 * Copyright (C) 2003 PMC-Sierra Inc.
5 * Author: Manish Lachwani (lachwani@pmc-sierra.com)
6 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29/*
30 * Header file for atmel_read_eeprom.c
31 */
32
33#include <linux/types.h>
34#include <linux/pci.h>
35#include <linux/kernel.h>
36#include <linux/slab.h>
37#include <asm/pci.h>
38#include <asm/io.h>
39#include <linux/init.h>
40#include <asm/termios.h>
41#include <asm/ioctls.h>
42#include <linux/ioctl.h>
43#include <linux/fcntl.h>
44
45#define DEFAULT_PORT "/dev/ttyS0" /* Port to open */
46#define TXX 0 /* Dummy loop for spinning */
47
48#define BLOCK_SEL 0x00
49#define SLAVE_ADDR 0xa0
50#define READ_BIT 0x01
51#define WRITE_BIT 0x00
52#define R_HEADER SLAVE_ADDR + BLOCK_SEL + READ_BIT
53#define W_HEADER SLAVE_ADDR + BLOCK_SEL + WRITE_BIT
54
55/*
56 * Clock, Voltages and Data
57 */
58#define vcc_off (ioctl(fd, TIOCSBRK, 0))
59#define vcc_on (ioctl(fd, TIOCCBRK, 0))
60#define sda_hi (ioctl(fd, TIOCMBIS, &dtr))
61#define sda_lo (ioctl(fd, TIOCMBIC, &dtr))
62#define scl_lo (ioctl(fd, TIOCMBIC, &rts))
63#define scl_hi (ioctl(fd, TIOCMBIS, &rts))
64
65const char rts = TIOCM_RTS;
66const char dtr = TIOCM_DTR;
67int fd;
diff --git a/arch/mips/pmc-sierra/yosemite/ht-irq.c b/arch/mips/pmc-sierra/yosemite/ht-irq.c
new file mode 100644
index 00000000000..86b98e98fb4
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/ht-irq.c
@@ -0,0 +1,51 @@
1/*
2 * Copyright 2003 PMC-Sierra
3 * Author: Manish Lachwani (lachwani@pmc-sierra.com)
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
11 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
13 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
14 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
15 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
16 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
17 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
18 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
19 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26#include <linux/types.h>
27#include <linux/pci.h>
28#include <linux/kernel.h>
29#include <linux/init.h>
30#include <asm/pci.h>
31
32/*
33 * HT Bus fixup for the Titan
34 * XXX IRQ values need to change based on the board layout
35 */
36void __init titan_ht_pcibios_fixup_bus(struct pci_bus *bus)
37{
38 struct pci_bus *current_bus = bus;
39 struct pci_dev *devices;
40 struct list_head *devices_link;
41
42 list_for_each(devices_link, &(current_bus->devices)) {
43 devices = pci_dev_b(devices_link);
44 if (devices == NULL)
45 continue;
46 }
47
48 /*
49 * PLX and SPKT related changes go here
50 */
51}
diff --git a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c
new file mode 100644
index 00000000000..63be40e470d
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/ht.c
@@ -0,0 +1,415 @@
1/*
2 * Copyright 2003 PMC-Sierra
3 * Author: Manish Lachwani (lachwani@pmc-sierra.com)
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
11 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
13 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
14 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
15 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
16 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
17 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
18 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
19 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26#include <linux/types.h>
27#include <linux/pci.h>
28#include <linux/kernel.h>
29#include <asm/pci.h>
30#include <asm/io.h>
31
32#include <linux/init.h>
33#include <asm/titan_dep.h>
34
35#ifdef CONFIG_HYPERTRANSPORT
36
37
38/*
39 * This function check if the Hypertransport Link Initialization completed. If
40 * it did, then proceed further with scanning bus #2
41 */
42static __inline__ int check_titan_htlink(void)
43{
44 u32 val;
45
46 val = *(volatile uint32_t *)(RM9000x2_HTLINK_REG);
47 if (val & 0x00000020)
48 /* HT Link Initialization completed */
49 return 1;
50 else
51 return 0;
52}
53
54static int titan_ht_config_read_dword(struct pci_dev *device,
55 int offset, u32* val)
56{
57 int dev, bus, func;
58 uint32_t address_reg, data_reg;
59 uint32_t address;
60
61 bus = device->bus->number;
62 dev = PCI_SLOT(device->devfn);
63 func = PCI_FUNC(device->devfn);
64
65 /* XXX Need to change the Bus # */
66 if (bus > 2)
67 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
68 0x80000000 | 0x1;
69 else
70 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
71
72 address_reg = RM9000x2_OCD_HTCFGA;
73 data_reg = RM9000x2_OCD_HTCFGD;
74
75 RM9K_WRITE(address_reg, address);
76 RM9K_READ(data_reg, val);
77
78 return PCIBIOS_SUCCESSFUL;
79}
80
81
82static int titan_ht_config_read_word(struct pci_dev *device,
83 int offset, u16* val)
84{
85 int dev, bus, func;
86 uint32_t address_reg, data_reg;
87 uint32_t address;
88
89 bus = device->bus->number;
90 dev = PCI_SLOT(device->devfn);
91 func = PCI_FUNC(device->devfn);
92
93 /* XXX Need to change the Bus # */
94 if (bus > 2)
95 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
96 0x80000000 | 0x1;
97 else
98 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
99
100 address_reg = RM9000x2_OCD_HTCFGA;
101 data_reg = RM9000x2_OCD_HTCFGD;
102
103 if ((offset & 0x3) == 0)
104 offset = 0x2;
105 else
106 offset = 0x0;
107
108 RM9K_WRITE(address_reg, address);
109 RM9K_READ_16(data_reg + offset, val);
110
111 return PCIBIOS_SUCCESSFUL;
112}
113
114
115u32 longswap(unsigned long l)
116{
117 unsigned char b1, b2, b3, b4;
118
119 b1 = l&255;
120 b2 = (l>>8)&255;
121 b3 = (l>>16)&255;
122 b4 = (l>>24)&255;
123
124 return ((b1<<24) + (b2<<16) + (b3<<8) + b4);
125}
126
127
128static int titan_ht_config_read_byte(struct pci_dev *device,
129 int offset, u8* val)
130{
131 int dev, bus, func;
132 uint32_t address_reg, data_reg;
133 uint32_t address;
134 int offset1;
135
136 bus = device->bus->number;
137 dev = PCI_SLOT(device->devfn);
138 func = PCI_FUNC(device->devfn);
139
140 /* XXX Need to change the Bus # */
141 if (bus > 2)
142 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
143 0x80000000 | 0x1;
144 else
145 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
146
147 address_reg = RM9000x2_OCD_HTCFGA;
148 data_reg = RM9000x2_OCD_HTCFGD;
149
150 RM9K_WRITE(address_reg, address);
151
152 if ((offset & 0x3) == 0) {
153 offset1 = 0x3;
154 }
155 if ((offset & 0x3) == 1) {
156 offset1 = 0x2;
157 }
158 if ((offset & 0x3) == 2) {
159 offset1 = 0x1;
160 }
161 if ((offset & 0x3) == 3) {
162 offset1 = 0x0;
163 }
164 RM9K_READ_8(data_reg + offset1, val);
165
166 return PCIBIOS_SUCCESSFUL;
167}
168
169
170static int titan_ht_config_write_dword(struct pci_dev *device,
171 int offset, u8 val)
172{
173 int dev, bus, func;
174 uint32_t address_reg, data_reg;
175 uint32_t address;
176
177 bus = device->bus->number;
178 dev = PCI_SLOT(device->devfn);
179 func = PCI_FUNC(device->devfn);
180
181 /* XXX Need to change the Bus # */
182 if (bus > 2)
183 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
184 0x80000000 | 0x1;
185 else
186 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
187
188 address_reg = RM9000x2_OCD_HTCFGA;
189 data_reg = RM9000x2_OCD_HTCFGD;
190
191 RM9K_WRITE(address_reg, address);
192 RM9K_WRITE(data_reg, val);
193
194 return PCIBIOS_SUCCESSFUL;
195}
196
197static int titan_ht_config_write_word(struct pci_dev *device,
198 int offset, u8 val)
199{
200 int dev, bus, func;
201 uint32_t address_reg, data_reg;
202 uint32_t address;
203
204 bus = device->bus->number;
205 dev = PCI_SLOT(device->devfn);
206 func = PCI_FUNC(device->devfn);
207
208 /* XXX Need to change the Bus # */
209 if (bus > 2)
210 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
211 0x80000000 | 0x1;
212 else
213 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
214
215 address_reg = RM9000x2_OCD_HTCFGA;
216 data_reg = RM9000x2_OCD_HTCFGD;
217
218 if ((offset & 0x3) == 0)
219 offset = 0x2;
220 else
221 offset = 0x0;
222
223 RM9K_WRITE(address_reg, address);
224 RM9K_WRITE_16(data_reg + offset, val);
225
226 return PCIBIOS_SUCCESSFUL;
227}
228
229static int titan_ht_config_write_byte(struct pci_dev *device,
230 int offset, u8 val)
231{
232 int dev, bus, func;
233 uint32_t address_reg, data_reg;
234 uint32_t address;
235 int offset1;
236
237 bus = device->bus->number;
238 dev = PCI_SLOT(device->devfn);
239 func = PCI_FUNC(device->devfn);
240
241 /* XXX Need to change the Bus # */
242 if (bus > 2)
243 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
244 0x80000000 | 0x1;
245 else
246 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
247
248 address_reg = RM9000x2_OCD_HTCFGA;
249 data_reg = RM9000x2_OCD_HTCFGD;
250
251 RM9K_WRITE(address_reg, address);
252
253 if ((offset & 0x3) == 0) {
254 offset1 = 0x3;
255 }
256 if ((offset & 0x3) == 1) {
257 offset1 = 0x2;
258 }
259 if ((offset & 0x3) == 2) {
260 offset1 = 0x1;
261 }
262 if ((offset & 0x3) == 3) {
263 offset1 = 0x0;
264 }
265
266 RM9K_WRITE_8(data_reg + offset1, val);
267 return PCIBIOS_SUCCESSFUL;
268}
269
270
271static void titan_pcibios_set_master(struct pci_dev *dev)
272{
273 u16 cmd;
274 int bus = dev->bus->number;
275
276 if (check_titan_htlink())
277 titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
278
279 cmd |= PCI_COMMAND_MASTER;
280
281 if (check_titan_htlink())
282 titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
283}
284
285
286int pcibios_enable_resources(struct pci_dev *dev)
287{
288 u16 cmd, old_cmd;
289 u8 tmp1;
290 int idx;
291 struct resource *r;
292 int bus = dev->bus->number;
293
294 if (check_titan_htlink())
295 titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
296
297 old_cmd = cmd;
298 for (idx = 0; idx < 6; idx++) {
299 r = &dev->resource[idx];
300 if (!r->start && r->end) {
301 printk(KERN_ERR
302 "PCI: Device %s not available because of "
303 "resource collisions\n", pci_name(dev));
304 return -EINVAL;
305 }
306 if (r->flags & IORESOURCE_IO)
307 cmd |= PCI_COMMAND_IO;
308 if (r->flags & IORESOURCE_MEM)
309 cmd |= PCI_COMMAND_MEMORY;
310 }
311 if (cmd != old_cmd) {
312 if (check_titan_htlink())
313 titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
314 }
315
316 if (check_titan_htlink())
317 titan_ht_config_read_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1);
318
319 if (tmp1 != 8) {
320 printk(KERN_WARNING "PCI setting cache line size to 8 from "
321 "%d\n", tmp1);
322 }
323
324 if (check_titan_htlink())
325 titan_ht_config_write_byte(dev, PCI_CACHE_LINE_SIZE, 8);
326
327 if (check_titan_htlink())
328 titan_ht_config_read_byte(dev, PCI_LATENCY_TIMER, &tmp1);
329
330 if (tmp1 < 32 || tmp1 == 0xff) {
331 printk(KERN_WARNING "PCI setting latency timer to 32 from %d\n",
332 tmp1);
333 }
334
335 if (check_titan_htlink())
336 titan_ht_config_write_byte(dev, PCI_LATENCY_TIMER, 32);
337
338 return 0;
339}
340
341
342int pcibios_enable_device(struct pci_dev *dev, int mask)
343{
344 return pcibios_enable_resources(dev);
345}
346
347resource_size_t pcibios_align_resource(void *data, const struct resource *res,
348 resource_size_t size, resource_size_t align)
349{
350 struct pci_dev *dev = data;
351 resource_size_t start = res->start;
352
353 if (res->flags & IORESOURCE_IO) {
354 /* We need to avoid collisions with `mirrored' VGA ports
355 and other strange ISA hardware, so we always want the
356 addresses kilobyte aligned. */
357 if (size > 0x100) {
358 printk(KERN_ERR "PCI: I/O Region %s/%d too large"
359 " (%ld bytes)\n", pci_name(dev),
360 dev->resource - res, size);
361 }
362
363 start = (start + 1024 - 1) & ~(1024 - 1);
364 }
365
366 return start;
367}
368
369struct pci_ops titan_pci_ops = {
370 titan_ht_config_read_byte,
371 titan_ht_config_read_word,
372 titan_ht_config_read_dword,
373 titan_ht_config_write_byte,
374 titan_ht_config_write_word,
375 titan_ht_config_write_dword
376};
377
378void __init pcibios_fixup_bus(struct pci_bus *c)
379{
380 titan_ht_pcibios_fixup_bus(c);
381}
382
383void __init pcibios_init(void)
384{
385
386 /* Reset PCI I/O and PCI MEM values */
387 /* XXX Need to add the proper values here */
388 ioport_resource.start = 0xe0000000;
389 ioport_resource.end = 0xe0000000 + 0x20000000 - 1;
390 iomem_resource.start = 0xc0000000;
391 iomem_resource.end = 0xc0000000 + 0x20000000 - 1;
392
393 /* XXX Need to add bus values */
394 pci_scan_bus(2, &titan_pci_ops, NULL);
395 pci_scan_bus(3, &titan_pci_ops, NULL);
396}
397
398/*
399 * for parsing "pci=" kernel boot arguments.
400 */
401char *pcibios_setup(char *str)
402{
403 printk(KERN_INFO "rr: pcibios_setup\n");
404 /* Nothing to do for now. */
405
406 return str;
407}
408
409unsigned __init int pcibios_assign_all_busses(void)
410{
411 /* We want to use the PCI bus detection done by PMON */
412 return 0;
413}
414
415#endif /* CONFIG_HYPERTRANSPORT */
diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c
new file mode 100644
index 00000000000..25bbbf428be
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/irq.c
@@ -0,0 +1,153 @@
1/*
2 * Copyright (C) 2003 PMC-Sierra Inc.
3 * Author: Manish Lachwani (lachwani@pmc-sierra.com)
4 *
5 * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
13 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
15 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
16 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
18 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 *
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 675 Mass Ave, Cambridge, MA 02139, USA.
26 *
27 * Second level Interrupt handlers for the PMC-Sierra Titan/Yosemite board
28 */
29#include <linux/errno.h>
30#include <linux/init.h>
31#include <linux/kernel_stat.h>
32#include <linux/module.h>
33#include <linux/signal.h>
34#include <linux/sched.h>
35#include <linux/types.h>
36#include <linux/interrupt.h>
37#include <linux/ioport.h>
38#include <linux/irq.h>
39#include <linux/timex.h>
40#include <linux/random.h>
41#include <linux/bitops.h>
42#include <asm/bootinfo.h>
43#include <asm/io.h>
44#include <asm/irq.h>
45#include <asm/irq_cpu.h>
46#include <asm/mipsregs.h>
47#include <asm/system.h>
48#include <asm/titan_dep.h>
49
50/* Hypertransport specific */
51#define IRQ_ACK_BITS 0x00000000 /* Ack bits */
52
53#define HYPERTRANSPORT_INTA 0x78 /* INTA# */
54#define HYPERTRANSPORT_INTB 0x79 /* INTB# */
55#define HYPERTRANSPORT_INTC 0x7a /* INTC# */
56#define HYPERTRANSPORT_INTD 0x7b /* INTD# */
57
58extern void titan_mailbox_irq(void);
59
60#ifdef CONFIG_HYPERTRANSPORT
61/*
62 * Handle hypertransport & SMP interrupts. The interrupt lines are scarce.
63 * For interprocessor interrupts, the best thing to do is to use the INTMSG
64 * register. We use the same external interrupt line, i.e. INTB3 and monitor
65 * another status bit
66 */
67static void ll_ht_smp_irq_handler(int irq)
68{
69 u32 status = OCD_READ(RM9000x2_OCD_INTP0STATUS4);
70
71 /* Ack all the bits that correspond to the interrupt sources */
72 if (status != 0)
73 OCD_WRITE(RM9000x2_OCD_INTP0STATUS4, IRQ_ACK_BITS);
74
75 status = OCD_READ(RM9000x2_OCD_INTP1STATUS4);
76 if (status != 0)
77 OCD_WRITE(RM9000x2_OCD_INTP1STATUS4, IRQ_ACK_BITS);
78
79#ifdef CONFIG_HT_LEVEL_TRIGGER
80 /*
81 * Level Trigger Mode only. Send the HT EOI message back to the source.
82 */
83 switch (status) {
84 case 0x1000000:
85 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTA);
86 break;
87 case 0x2000000:
88 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTB);
89 break;
90 case 0x4000000:
91 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTC);
92 break;
93 case 0x8000000:
94 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTD);
95 break;
96 case 0x0000001:
97 /* PLX */
98 OCD_WRITE(RM9000x2_OCD_HTEOI, 0x20);
99 OCD_WRITE(IRQ_CLEAR_REG, IRQ_ACK_BITS);
100 break;
101 case 0xf000000:
102 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTA);
103 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTB);
104 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTC);
105 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTD);
106 break;
107 }
108#endif /* CONFIG_HT_LEVEL_TRIGGER */
109
110 do_IRQ(irq);
111}
112#endif
113
114asmlinkage void plat_irq_dispatch(void)
115{
116 unsigned int cause = read_c0_cause();
117 unsigned int status = read_c0_status();
118 unsigned int pending = cause & status;
119
120 if (pending & STATUSF_IP7) {
121 do_IRQ(7);
122 } else if (pending & STATUSF_IP2) {
123#ifdef CONFIG_HYPERTRANSPORT
124 ll_ht_smp_irq_handler(2);
125#else
126 do_IRQ(2);
127#endif
128 } else if (pending & STATUSF_IP3) {
129 do_IRQ(3);
130 } else if (pending & STATUSF_IP4) {
131 do_IRQ(4);
132 } else if (pending & STATUSF_IP5) {
133#ifdef CONFIG_SMP
134 titan_mailbox_irq();
135#else
136 do_IRQ(5);
137#endif
138 } else if (pending & STATUSF_IP6) {
139 do_IRQ(4);
140 }
141}
142
143/*
144 * Initialize the next level interrupt handler
145 */
146void __init arch_init_irq(void)
147{
148 clear_c0_status(ST0_IM);
149
150 mips_cpu_irq_init();
151 rm7k_cpu_irq_init();
152 rm9k_cpu_irq_init();
153}
diff --git a/arch/mips/pmc-sierra/yosemite/prom.c b/arch/mips/pmc-sierra/yosemite/prom.c
new file mode 100644
index 00000000000..cf4c868715a
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/prom.c
@@ -0,0 +1,143 @@
1/*
2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation; either version 2 of the License, or (at your
5 * option) any later version.
6 *
7 * Copyright (C) 2003, 2004 PMC-Sierra Inc.
8 * Author: Manish Lachwani (lachwani@pmc-sierra.com)
9 * Copyright (C) 2004 Ralf Baechle
10 */
11#include <linux/init.h>
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <linux/delay.h>
15#include <linux/pm.h>
16#include <linux/smp.h>
17
18#include <asm/io.h>
19#include <asm/pgtable.h>
20#include <asm/processor.h>
21#include <asm/reboot.h>
22#include <asm/smp-ops.h>
23#include <asm/system.h>
24#include <asm/bootinfo.h>
25#include <asm/pmon.h>
26
27#ifdef CONFIG_SMP
28extern void prom_grab_secondary(void);
29#else
30#define prom_grab_secondary() do { } while (0)
31#endif
32
33#include "setup.h"
34
35struct callvectors *debug_vectors;
36
37extern unsigned long yosemite_base;
38extern unsigned long cpu_clock_freq;
39
40const char *get_system_type(void)
41{
42 return "PMC-Sierra Yosemite";
43}
44
45static void prom_cpu0_exit(void *arg)
46{
47 void *nvram = (void *) YOSEMITE_RTC_BASE;
48
49 /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
50 writeb(0x84, nvram + 0xff7);
51
52 /* wait for the watchdog to go off */
53 mdelay(100 + (1000 / 16));
54
55 /* if the watchdog fails for some reason, let people know */
56 printk(KERN_NOTICE "Watchdog reset failed\n");
57}
58
59/*
60 * Reset the NVRAM over the local bus
61 */
62static void prom_exit(void)
63{
64#ifdef CONFIG_SMP
65 if (smp_processor_id())
66 /* CPU 1 */
67 smp_call_function(prom_cpu0_exit, NULL, 1);
68#endif
69 prom_cpu0_exit(NULL);
70}
71
72/*
73 * Halt the system
74 */
75static void prom_halt(void)
76{
77 printk(KERN_NOTICE "\n** You can safely turn off the power\n");
78 while (1)
79 __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0");
80}
81
82extern struct plat_smp_ops yos_smp_ops;
83
84/*
85 * Init routine which accepts the variables from PMON
86 */
87void __init prom_init(void)
88{
89 int argc = fw_arg0;
90 char **arg = (char **) fw_arg1;
91 char **env = (char **) fw_arg2;
92 struct callvectors *cv = (struct callvectors *) fw_arg3;
93 int i = 0;
94
95 /* Callbacks for halt, restart */
96 _machine_restart = (void (*)(char *)) prom_exit;
97 _machine_halt = prom_halt;
98 pm_power_off = prom_halt;
99
100 debug_vectors = cv;
101 arcs_cmdline[0] = '\0';
102
103 /* Get the boot parameters */
104 for (i = 1; i < argc; i++) {
105 if (strlen(arcs_cmdline) + strlen(arg[i] + 1) >=
106 sizeof(arcs_cmdline))
107 break;
108
109 strcat(arcs_cmdline, arg[i]);
110 strcat(arcs_cmdline, " ");
111 }
112
113#ifdef CONFIG_SERIAL_8250_CONSOLE
114 if ((strstr(arcs_cmdline, "console=ttyS")) == NULL)
115 strcat(arcs_cmdline, "console=ttyS0,115200");
116#endif
117
118 while (*env) {
119 if (strncmp("ocd_base", *env, strlen("ocd_base")) == 0)
120 yosemite_base =
121 simple_strtol(*env + strlen("ocd_base="), NULL,
122 16);
123
124 if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0)
125 cpu_clock_freq =
126 simple_strtol(*env + strlen("cpuclock="), NULL,
127 10);
128
129 env++;
130 }
131
132 prom_grab_secondary();
133
134 register_smp_ops(&yos_smp_ops);
135}
136
137void __init prom_free_prom_memory(void)
138{
139}
140
141void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
142{
143}
diff --git a/arch/mips/pmc-sierra/yosemite/py-console.c b/arch/mips/pmc-sierra/yosemite/py-console.c
new file mode 100644
index 00000000000..434d7b1a8c6
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/py-console.c
@@ -0,0 +1,117 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2001, 2002, 2004 Ralf Baechle
7 */
8#include <linux/init.h>
9#include <linux/console.h>
10#include <linux/kdev_t.h>
11#include <linux/major.h>
12#include <linux/termios.h>
13#include <linux/sched.h>
14#include <linux/tty.h>
15
16#include <linux/serial.h>
17#include <linux/serial_core.h>
18#include <asm/serial.h>
19#include <asm/io.h>
20
21/* SUPERIO uart register map */
22struct yo_uartregs {
23 union {
24 volatile u8 rbr; /* read only, DLAB == 0 */
25 volatile u8 thr; /* write only, DLAB == 0 */
26 volatile u8 dll; /* DLAB == 1 */
27 } u1;
28 union {
29 volatile u8 ier; /* DLAB == 0 */
30 volatile u8 dlm; /* DLAB == 1 */
31 } u2;
32 union {
33 volatile u8 iir; /* read only */
34 volatile u8 fcr; /* write only */
35 } u3;
36 volatile u8 iu_lcr;
37 volatile u8 iu_mcr;
38 volatile u8 iu_lsr;
39 volatile u8 iu_msr;
40 volatile u8 iu_scr;
41} yo_uregs_t;
42
43#define iu_rbr u1.rbr
44#define iu_thr u1.thr
45#define iu_dll u1.dll
46#define iu_ier u2.ier
47#define iu_dlm u2.dlm
48#define iu_iir u3.iir
49#define iu_fcr u3.fcr
50
51#define ssnop() __asm__ __volatile__("sll $0, $0, 1\n");
52#define ssnop_4() do { ssnop(); ssnop(); ssnop(); ssnop(); } while (0)
53
54#define IO_BASE_64 0x9000000000000000ULL
55
56static unsigned char readb_outer_space(unsigned long long phys)
57{
58 unsigned long long vaddr = IO_BASE_64 | phys;
59 unsigned char res;
60 unsigned int sr;
61
62 sr = read_c0_status();
63 write_c0_status((sr | ST0_KX) & ~ ST0_IE);
64 ssnop_4();
65
66 __asm__ __volatile__ (
67 " .set mips3 \n"
68 " .set push \n"
69 " .set noreorder \n"
70 " .set nomacro \n"
71 " ld %0, %1 \n"
72 " .set pop \n"
73 " lbu %0, (%0) \n"
74 " .set mips0 \n"
75 : "=r" (res)
76 : "R" (vaddr));
77
78 write_c0_status(sr);
79 ssnop_4();
80
81 return res;
82}
83
84static void writeb_outer_space(unsigned long long phys, unsigned char c)
85{
86 unsigned long long vaddr = IO_BASE_64 | phys;
87 unsigned long tmp;
88 unsigned int sr;
89
90 sr = read_c0_status();
91 write_c0_status((sr | ST0_KX) & ~ ST0_IE);
92 ssnop_4();
93
94 __asm__ __volatile__ (
95 " .set mips3 \n"
96 " .set push \n"
97 " .set noreorder \n"
98 " .set nomacro \n"
99 " ld %0, %1 \n"
100 " .set pop \n"
101 " sb %2, (%0) \n"
102 " .set mips0 \n"
103 : "=&r" (tmp)
104 : "R" (vaddr), "r" (c));
105
106 write_c0_status(sr);
107 ssnop_4();
108}
109
110void prom_putchar(char c)
111{
112 unsigned long lsr = 0xfd000008ULL + offsetof(struct yo_uartregs, iu_lsr);
113 unsigned long thr = 0xfd000008ULL + offsetof(struct yo_uartregs, iu_thr);
114
115 while ((readb_outer_space(lsr) & 0x20) == 0);
116 writeb_outer_space(thr, c);
117}
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
new file mode 100644
index 00000000000..3498ac9c35a
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -0,0 +1,223 @@
1/*
2 * Copyright (C) 2003 PMC-Sierra Inc.
3 * Author: Manish Lachwani (lachwani@pmc-sierra.com)
4 *
5 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
13 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
15 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
16 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
18 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 *
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27#include <linux/bcd.h>
28#include <linux/init.h>
29#include <linux/kernel.h>
30#include <linux/types.h>
31#include <linux/mm.h>
32#include <linux/bootmem.h>
33#include <linux/swap.h>
34#include <linux/ioport.h>
35#include <linux/sched.h>
36#include <linux/interrupt.h>
37#include <linux/timex.h>
38#include <linux/termios.h>
39#include <linux/tty.h>
40#include <linux/serial.h>
41#include <linux/serial_core.h>
42#include <linux/serial_8250.h>
43
44#include <asm/time.h>
45#include <asm/bootinfo.h>
46#include <asm/page.h>
47#include <asm/io.h>
48#include <asm/irq.h>
49#include <asm/processor.h>
50#include <asm/reboot.h>
51#include <asm/serial.h>
52#include <asm/titan_dep.h>
53#include <asm/m48t37.h>
54
55#include "setup.h"
56
57unsigned char titan_ge_mac_addr_base[6] = {
58 // 0x00, 0x03, 0xcc, 0x1d, 0x22, 0x00
59 0x00, 0xe0, 0x04, 0x00, 0x00, 0x21
60};
61
62unsigned long cpu_clock_freq;
63unsigned long yosemite_base;
64
65static struct m48t37_rtc *m48t37_base;
66
67void __init bus_error_init(void)
68{
69 /* Do nothing */
70}
71
72
73void read_persistent_clock(struct timespec *ts)
74{
75 unsigned int year, month, day, hour, min, sec;
76 unsigned long flags;
77
78 spin_lock_irqsave(&rtc_lock, flags);
79 /* Stop the update to the time */
80 m48t37_base->control = 0x40;
81
82 year = bcd2bin(m48t37_base->year);
83 year += bcd2bin(m48t37_base->century) * 100;
84
85 month = bcd2bin(m48t37_base->month);
86 day = bcd2bin(m48t37_base->date);
87 hour = bcd2bin(m48t37_base->hour);
88 min = bcd2bin(m48t37_base->min);
89 sec = bcd2bin(m48t37_base->sec);
90
91 /* Start the update to the time again */
92 m48t37_base->control = 0x00;
93 spin_unlock_irqrestore(&rtc_lock, flags);
94
95 ts->tv_sec = mktime(year, month, day, hour, min, sec);
96 ts->tv_nsec = 0;
97}
98
99int rtc_mips_set_time(unsigned long tim)
100{
101 struct rtc_time tm;
102 unsigned long flags;
103
104 /*
105 * Convert to a more useful format -- note months count from 0
106 * and years from 1900
107 */
108 rtc_time_to_tm(tim, &tm);
109 tm.tm_year += 1900;
110 tm.tm_mon += 1;
111
112 spin_lock_irqsave(&rtc_lock, flags);
113 /* enable writing */
114 m48t37_base->control = 0x80;
115
116 /* year */
117 m48t37_base->year = bin2bcd(tm.tm_year % 100);
118 m48t37_base->century = bin2bcd(tm.tm_year / 100);
119
120 /* month */
121 m48t37_base->month = bin2bcd(tm.tm_mon);
122
123 /* day */
124 m48t37_base->date = bin2bcd(tm.tm_mday);
125
126 /* hour/min/sec */
127 m48t37_base->hour = bin2bcd(tm.tm_hour);
128 m48t37_base->min = bin2bcd(tm.tm_min);
129 m48t37_base->sec = bin2bcd(tm.tm_sec);
130
131 /* day of week -- not really used, but let's keep it up-to-date */
132 m48t37_base->day = bin2bcd(tm.tm_wday + 1);
133
134 /* disable writing */
135 m48t37_base->control = 0x00;
136 spin_unlock_irqrestore(&rtc_lock, flags);
137
138 return 0;
139}
140
141void __init plat_time_init(void)
142{
143 mips_hpt_frequency = cpu_clock_freq / 2;
144mips_hpt_frequency = 33000000 * 3 * 5;
145}
146
147unsigned long ocd_base;
148
149EXPORT_SYMBOL(ocd_base);
150
151/*
152 * Common setup before any secondaries are started
153 */
154
155#define TITAN_UART_CLK 3686400
156#define TITAN_SERIAL_BASE_BAUD (TITAN_UART_CLK / 16)
157#define TITAN_SERIAL_IRQ 4
158#define TITAN_SERIAL_BASE 0xfd000008UL
159
160static void __init py_map_ocd(void)
161{
162 ocd_base = (unsigned long) ioremap(OCD_BASE, OCD_SIZE);
163 if (!ocd_base)
164 panic("Mapping OCD failed - game over. Your score is 0.");
165
166 /* Kludge for PMON bug ... */
167 OCD_WRITE(0x0710, 0x0ffff029);
168}
169
170static void __init py_uart_setup(void)
171{
172#ifdef CONFIG_SERIAL_8250
173 struct uart_port up;
174
175 /*
176 * Register to interrupt zero because we share the interrupt with
177 * the serial driver which we don't properly support yet.
178 */
179 memset(&up, 0, sizeof(up));
180 up.membase = (unsigned char *) ioremap(TITAN_SERIAL_BASE, 8);
181 up.irq = TITAN_SERIAL_IRQ;
182 up.uartclk = TITAN_UART_CLK;
183 up.regshift = 0;
184 up.iotype = UPIO_MEM;
185 up.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
186 up.line = 0;
187
188 if (early_serial_setup(&up))
189 printk(KERN_ERR "Early serial init of port 0 failed\n");
190#endif /* CONFIG_SERIAL_8250 */
191}
192
193static void __init py_rtc_setup(void)
194{
195 m48t37_base = ioremap(YOSEMITE_RTC_BASE, YOSEMITE_RTC_SIZE);
196 if (!m48t37_base)
197 printk(KERN_ERR "Mapping the RTC failed\n");
198}
199
200/* Not only time init but that's what the hook it's called through is named */
201static void __init py_late_time_init(void)
202{
203 py_map_ocd();
204 py_uart_setup();
205 py_rtc_setup();
206}
207
208void __init plat_mem_setup(void)
209{
210 late_time_init = py_late_time_init;
211
212 /* Add memory regions */
213 add_memory_region(0x00000000, 0x10000000, BOOT_MEM_RAM);
214
215#if 0 /* XXX Crash ... */
216 OCD_WRITE(RM9000x2_OCD_HTSC,
217 OCD_READ(RM9000x2_OCD_HTSC) | HYPERTRANSPORT_ENABLE);
218
219 /* Set the BAR. Shifted mode */
220 OCD_WRITE(RM9000x2_OCD_HTBAR0, HYPERTRANSPORT_BAR0_ADDR);
221 OCD_WRITE(RM9000x2_OCD_HTMASK0, HYPERTRANSPORT_SIZE0);
222#endif
223}
diff --git a/arch/mips/pmc-sierra/yosemite/setup.h b/arch/mips/pmc-sierra/yosemite/setup.h
new file mode 100644
index 00000000000..1a01abfc7d3
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/setup.h
@@ -0,0 +1,32 @@
1/*
2 * Copyright 2003, 04 PMC-Sierra
3 * Author: Manish Lachwani (lachwani@pmc-sierra.com)
4 * Copyright 2004 Ralf Baechle <ralf@linux-mips.org>
5 *
6 * Board specific definititions for the PMC-Sierra Yosemite
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13#ifndef __SETUP_H__
14#define __SETUP_H__
15
16/* M48T37 RTC + NVRAM */
17#define YOSEMITE_RTC_BASE 0xfc800000
18#define YOSEMITE_RTC_SIZE 0x00800000
19
20#define HYPERTRANSPORT_BAR0_ADDR 0x00000006
21#define HYPERTRANSPORT_SIZE0 0x0fffffff
22#define HYPERTRANSPORT_BAR0_ATTR 0x00002000
23
24#define HYPERTRANSPORT_ENABLE 0x6
25
26/*
27 * EEPROM Size
28 */
29#define TITAN_ATMEL_24C32_SIZE 32768
30#define TITAN_ATMEL_24C64_SIZE 65536
31
32#endif /* __SETUP_H__ */
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
new file mode 100644
index 00000000000..2608752898c
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -0,0 +1,185 @@
1#include <linux/linkage.h>
2#include <linux/sched.h>
3#include <linux/smp.h>
4
5#include <asm/pmon.h>
6#include <asm/titan_dep.h>
7#include <asm/time.h>
8
9#define LAUNCHSTACK_SIZE 256
10
11static __cpuinitdata arch_spinlock_t launch_lock = __ARCH_SPIN_LOCK_UNLOCKED;
12
13static unsigned long secondary_sp __cpuinitdata;
14static unsigned long secondary_gp __cpuinitdata;
15
16static unsigned char launchstack[LAUNCHSTACK_SIZE] __initdata
17 __attribute__((aligned(2 * sizeof(long))));
18
19static void __init prom_smp_bootstrap(void)
20{
21 local_irq_disable();
22
23 while (arch_spin_is_locked(&launch_lock));
24
25 __asm__ __volatile__(
26 " move $sp, %0 \n"
27 " move $gp, %1 \n"
28 " j smp_bootstrap \n"
29 :
30 : "r" (secondary_sp), "r" (secondary_gp));
31}
32
33/*
34 * PMON is a fragile beast. It'll blow up once the mappings it's littering
35 * right into the middle of KSEG3 are blown away so we have to grab the slave
36 * core early and keep it in a waiting loop.
37 */
38void __init prom_grab_secondary(void)
39{
40 arch_spin_lock(&launch_lock);
41
42 pmon_cpustart(1, &prom_smp_bootstrap,
43 launchstack + LAUNCHSTACK_SIZE, 0);
44}
45
46void titan_mailbox_irq(void)
47{
48 int cpu = smp_processor_id();
49 unsigned long status;
50
51 switch (cpu) {
52 case 0:
53 status = OCD_READ(RM9000x2_OCD_INTP0STATUS3);
54 OCD_WRITE(RM9000x2_OCD_INTP0CLEAR3, status);
55
56 if (status & 0x2)
57 smp_call_function_interrupt();
58 if (status & 0x4)
59 scheduler_ipi();
60 break;
61
62 case 1:
63 status = OCD_READ(RM9000x2_OCD_INTP1STATUS3);
64 OCD_WRITE(RM9000x2_OCD_INTP1CLEAR3, status);
65
66 if (status & 0x2)
67 smp_call_function_interrupt();
68 if (status & 0x4)
69 scheduler_ipi();
70 break;
71 }
72}
73
74/*
75 * Send inter-processor interrupt
76 */
77static void yos_send_ipi_single(int cpu, unsigned int action)
78{
79 /*
80 * Generate an INTMSG so that it can be sent over to the
81 * destination CPU. The INTMSG will put the STATUS bits
82 * based on the action desired. An alternative strategy
83 * is to write to the Interrupt Set register, read the
84 * Interrupt Status register and clear the Interrupt
85 * Clear register. The latter is preffered.
86 */
87 switch (action) {
88 case SMP_RESCHEDULE_YOURSELF:
89 if (cpu == 1)
90 OCD_WRITE(RM9000x2_OCD_INTP1SET3, 4);
91 else
92 OCD_WRITE(RM9000x2_OCD_INTP0SET3, 4);
93 break;
94
95 case SMP_CALL_FUNCTION:
96 if (cpu == 1)
97 OCD_WRITE(RM9000x2_OCD_INTP1SET3, 2);
98 else
99 OCD_WRITE(RM9000x2_OCD_INTP0SET3, 2);
100 break;
101 }
102}
103
104static void yos_send_ipi_mask(const struct cpumask *mask, unsigned int action)
105{
106 unsigned int i;
107
108 for_each_cpu(i, mask)
109 yos_send_ipi_single(i, action);
110}
111
112/*
113 * After we've done initial boot, this function is called to allow the
114 * board code to clean up state, if needed
115 */
116static void __cpuinit yos_init_secondary(void)
117{
118 set_c0_status(ST0_CO | ST0_IE | ST0_IM);
119}
120
121static void __cpuinit yos_smp_finish(void)
122{
123}
124
125/* Hook for after all CPUs are online */
126static void yos_cpus_done(void)
127{
128}
129
130/*
131 * Firmware CPU startup hook
132 * Complicated by PMON's weird interface which tries to minimic the UNIX fork.
133 * It launches the next * available CPU and copies some information on the
134 * stack so the first thing we do is throw away that stuff and load useful
135 * values into the registers ...
136 */
137static void __cpuinit yos_boot_secondary(int cpu, struct task_struct *idle)
138{
139 unsigned long gp = (unsigned long) task_thread_info(idle);
140 unsigned long sp = __KSTK_TOS(idle);
141
142 secondary_sp = sp;
143 secondary_gp = gp;
144
145 arch_spin_unlock(&launch_lock);
146}
147
148/*
149 * Detect available CPUs, populate cpu_possible_map before smp_init
150 *
151 * We don't want to start the secondary CPU yet nor do we have a nice probing
152 * feature in PMON so we just assume presence of the secondary core.
153 */
154static void __init yos_smp_setup(void)
155{
156 int i;
157
158 cpus_clear(cpu_possible_map);
159
160 for (i = 0; i < 2; i++) {
161 cpu_set(i, cpu_possible_map);
162 __cpu_number_map[i] = i;
163 __cpu_logical_map[i] = i;
164 }
165}
166
167static void __init yos_prepare_cpus(unsigned int max_cpus)
168{
169 /*
170 * Be paranoid. Enable the IPI only if we're really about to go SMP.
171 */
172 if (cpus_weight(cpu_possible_map))
173 set_c0_status(STATUSF_IP5);
174}
175
176struct plat_smp_ops yos_smp_ops = {
177 .send_ipi_single = yos_send_ipi_single,
178 .send_ipi_mask = yos_send_ipi_mask,
179 .init_secondary = yos_init_secondary,
180 .smp_finish = yos_smp_finish,
181 .cpus_done = yos_cpus_done,
182 .boot_secondary = yos_boot_secondary,
183 .smp_setup = yos_smp_setup,
184 .prepare_cpus = yos_prepare_cpus,
185};