aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/pmc-sierra/yosemite
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/mips/pmc-sierra/yosemite
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/mips/pmc-sierra/yosemite')
-rw-r--r--arch/mips/pmc-sierra/yosemite/Makefile8
-rw-r--r--arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c171
-rw-r--r--arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h69
-rw-r--r--arch/mips/pmc-sierra/yosemite/dbg_io.c180
-rw-r--r--arch/mips/pmc-sierra/yosemite/ht-irq.c53
-rw-r--r--arch/mips/pmc-sierra/yosemite/ht.c454
-rw-r--r--arch/mips/pmc-sierra/yosemite/i2c-yosemite.c188
-rw-r--r--arch/mips/pmc-sierra/yosemite/i2c-yosemite.h96
-rw-r--r--arch/mips/pmc-sierra/yosemite/irq-handler.S93
-rw-r--r--arch/mips/pmc-sierra/yosemite/irq.c167
-rw-r--r--arch/mips/pmc-sierra/yosemite/prom.c141
-rw-r--r--arch/mips/pmc-sierra/yosemite/py-console.c114
-rw-r--r--arch/mips/pmc-sierra/yosemite/setup.c235
-rw-r--r--arch/mips/pmc-sierra/yosemite/setup.h32
-rw-r--r--arch/mips/pmc-sierra/yosemite/smp.c172
15 files changed, 2173 insertions, 0 deletions
diff --git a/arch/mips/pmc-sierra/yosemite/Makefile b/arch/mips/pmc-sierra/yosemite/Makefile
new file mode 100644
index 000000000000..ae96a71a3089
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for the PMC-Sierra Titan
3#
4
5obj-y += irq-handler.o irq.o i2c-yosemite.o prom.o py-console.o setup.o
6
7obj-$(CONFIG_KGDB) += dbg_io.o
8obj-$(CONFIG_SMP) += smp.o
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 000000000000..b067988614c3
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
@@ -0,0 +1,171 @@
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 *
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
28/*
29 * Description:
30 *
31 * This code reads the ATMEL 24CXX EEPROM. The PMC-Sierra Yosemite board uses the ATMEL
32 * 24C32/24C64 which uses two byte addressing as compared to 24C16. Note that this program
33 * uses the serial port like /dev/ttyS0, to communicate with the EEPROM. Hence, you are
34 * expected to have a connectivity from the EEPROM to the serial port. This program does
35 * __not__ communicate using the I2C protocol
36 */
37
38#include "atmel_read_eeprom.h"
39
40static void delay(int delay)
41{
42 while (delay--);
43}
44
45static void send_bit(unsigned char bit)
46{
47 scl_lo;
48 delay(TXX);
49 if (bit)
50 sda_hi;
51 else
52 sda_lo;
53
54 delay(TXX);
55 scl_hi;
56 delay(TXX);
57}
58
59static void send_ack(void)
60{
61 send_bit(0);
62}
63
64static void send_byte(unsigned char byte)
65{
66 int i = 0;
67
68 for (i = 7; i >= 0; i--)
69 send_bit((byte >> i) & 0x01);
70}
71
72static void send_start(void)
73{
74 sda_hi;
75 delay(TXX);
76 scl_hi;
77 delay(TXX);
78 sda_lo;
79 delay(TXX);
80}
81
82static void send_stop(void)
83{
84 sda_lo;
85 delay(TXX);
86 scl_hi;
87 delay(TXX);
88 sda_hi;
89 delay(TXX);
90}
91
92static void do_idle(void)
93{
94 sda_hi;
95 scl_hi;
96 vcc_off;
97}
98
99static int recv_bit(void)
100{
101 int status;
102
103 scl_lo;
104 delay(TXX);
105 sda_hi;
106 delay(TXX);
107 scl_hi;
108 delay(TXX);
109
110 return 1;
111}
112
113static unsigned char recv_byte(void) {
114 int i;
115 unsigned char byte=0;
116
117 for (i=7;i>=0;i--)
118 byte |= (recv_bit() << i);
119
120 return byte;
121}
122
123static int recv_ack(void)
124{
125 unsigned int ack;
126
127 ack = (unsigned int)recv_bit();
128 scl_lo;
129
130 if (ack) {
131 do_idle();
132 printk(KERN_ERR "Error reading the Atmel 24C32/24C64 EEPROM \n");
133 return -1;
134 }
135
136 return ack;
137}
138
139/*
140 * This function does the actual read of the EEPROM. It needs the buffer into which the
141 * read data is copied, the size of the EEPROM being read and the buffer size
142 */
143int read_eeprom(char *buffer, int eeprom_size, int size)
144{
145 int i = 0, err;
146
147 send_start();
148 send_byte(W_HEADER);
149 recv_ack();
150
151 /* EEPROM with size of more then 2K need two byte addressing */
152 if (eeprom_size > 2048) {
153 send_byte(0x00);
154 recv_ack();
155 }
156
157 send_start();
158 send_byte(R_HEADER);
159 err = recv_ack();
160 if (err == -1)
161 return err;
162
163 for (i = 0; i < size; i++) {
164 *buffer++ = recv_byte();
165 send_ack();
166 }
167
168 /* Note : We should do some check if the buffer contains correct information */
169
170 send_stop();
171}
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 000000000000..d27566d99ffc
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h
@@ -0,0 +1,69 @@
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 <linux/version.h>
38#include <asm/pci.h>
39#include <asm/io.h>
40#include <linux/init.h>
41#include <asm/termios.h>
42#include <asm/ioctls.h>
43#include <linux/ioctl.h>
44#include <linux/fcntl.h>
45
46#define DEFAULT_PORT "/dev/ttyS0" /* Port to open */
47#define TXX 0 /* Dummy loop for spinning */
48
49#define BLOCK_SEL 0x00
50#define SLAVE_ADDR 0xa0
51#define READ_BIT 0x01
52#define WRITE_BIT 0x00
53#define R_HEADER SLAVE_ADDR + BLOCK_SEL + READ_BIT
54#define W_HEADER SLAVE_ADDR + BLOCK_SEL + WRITE_BIT
55
56/*
57 * Clock, Voltages and Data
58 */
59#define vcc_off (ioctl(fd, TIOCSBRK, 0))
60#define vcc_on (ioctl(fd, TIOCCBRK, 0))
61#define sda_hi (ioctl(fd, TIOCMBIS, &dtr))
62#define sda_lo (ioctl(fd, TIOCMBIC, &dtr))
63#define scl_lo (ioctl(fd, TIOCMBIC, &rts))
64#define scl_hi (ioctl(fd, TIOCMBIS, &rts))
65
66const char rts = TIOCM_RTS;
67const char dtr = TIOCM_DTR;
68int fd;
69
diff --git a/arch/mips/pmc-sierra/yosemite/dbg_io.c b/arch/mips/pmc-sierra/yosemite/dbg_io.c
new file mode 100644
index 000000000000..0f659c9106ac
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/dbg_io.c
@@ -0,0 +1,180 @@
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/*
27 * Support for KGDB for the Yosemite board. We make use of single serial
28 * port to be used for KGDB as well as console. The second serial port
29 * seems to be having a problem. Single IRQ is allocated for both the
30 * ports. Hence, the interrupt routing code needs to figure out whether
31 * the interrupt came from channel A or B.
32 */
33
34#include <asm/serial.h>
35
36/*
37 * Baud rate, Parity, Data and Stop bit settings for the
38 * serial port on the Yosemite. Note that the Early printk
39 * patch has been added. So, we should be all set to go
40 */
41#define YOSEMITE_BAUD_2400 2400
42#define YOSEMITE_BAUD_4800 4800
43#define YOSEMITE_BAUD_9600 9600
44#define YOSEMITE_BAUD_19200 19200
45#define YOSEMITE_BAUD_38400 38400
46#define YOSEMITE_BAUD_57600 57600
47#define YOSEMITE_BAUD_115200 115200
48
49#define YOSEMITE_PARITY_NONE 0
50#define YOSEMITE_PARITY_ODD 0x08
51#define YOSEMITE_PARITY_EVEN 0x18
52#define YOSEMITE_PARITY_MARK 0x28
53#define YOSEMITE_PARITY_SPACE 0x38
54
55#define YOSEMITE_DATA_5BIT 0x0
56#define YOSEMITE_DATA_6BIT 0x1
57#define YOSEMITE_DATA_7BIT 0x2
58#define YOSEMITE_DATA_8BIT 0x3
59
60#define YOSEMITE_STOP_1BIT 0x0
61#define YOSEMITE_STOP_2BIT 0x4
62
63/* This is crucial */
64#define SERIAL_REG_OFS 0x1
65
66#define SERIAL_RCV_BUFFER 0x0
67#define SERIAL_TRANS_HOLD 0x0
68#define SERIAL_SEND_BUFFER 0x0
69#define SERIAL_INTR_ENABLE (1 * SERIAL_REG_OFS)
70#define SERIAL_INTR_ID (2 * SERIAL_REG_OFS)
71#define SERIAL_DATA_FORMAT (3 * SERIAL_REG_OFS)
72#define SERIAL_LINE_CONTROL (3 * SERIAL_REG_OFS)
73#define SERIAL_MODEM_CONTROL (4 * SERIAL_REG_OFS)
74#define SERIAL_RS232_OUTPUT (4 * SERIAL_REG_OFS)
75#define SERIAL_LINE_STATUS (5 * SERIAL_REG_OFS)
76#define SERIAL_MODEM_STATUS (6 * SERIAL_REG_OFS)
77#define SERIAL_RS232_INPUT (6 * SERIAL_REG_OFS)
78#define SERIAL_SCRATCH_PAD (7 * SERIAL_REG_OFS)
79
80#define SERIAL_DIVISOR_LSB (0 * SERIAL_REG_OFS)
81#define SERIAL_DIVISOR_MSB (1 * SERIAL_REG_OFS)
82
83/*
84 * Functions to READ and WRITE to serial port 0
85 */
86#define SERIAL_READ(ofs) (*((volatile unsigned char*) \
87 (TITAN_SERIAL_BASE + ofs)))
88
89#define SERIAL_WRITE(ofs, val) ((*((volatile unsigned char*) \
90 (TITAN_SERIAL_BASE + ofs))) = val)
91
92/*
93 * Functions to READ and WRITE to serial port 1
94 */
95#define SERIAL_READ_1(ofs) (*((volatile unsigned char*) \
96 (TITAN_SERIAL_BASE_1 + ofs)
97
98#define SERIAL_WRITE_1(ofs, val) ((*((volatile unsigned char*) \
99 (TITAN_SERIAL_BASE_1 + ofs))) = val)
100
101/*
102 * Second serial port initialization
103 */
104void init_second_port(void)
105{
106 /* Disable Interrupts */
107 SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0);
108 SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0x0);
109
110 {
111 unsigned int divisor;
112
113 SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x80);
114 divisor = TITAN_SERIAL_BASE_BAUD / YOSEMITE_BAUD_115200;
115 SERIAL_WRITE_1(SERIAL_DIVISOR_LSB, divisor & 0xff);
116
117 SERIAL_WRITE_1(SERIAL_DIVISOR_MSB,
118 (divisor & 0xff00) >> 8);
119 SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0);
120 }
121
122 SERIAL_WRITE_1(SERIAL_DATA_FORMAT, YOSEMITE_DATA_8BIT |
123 YOSEMITE_PARITY_NONE | YOSEMITE_STOP_1BIT);
124
125 /* Enable Interrupts */
126 SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0xf);
127}
128
129/* Initialize the serial port for KGDB debugging */
130void debugInit(unsigned int baud, unsigned char data, unsigned char parity,
131 unsigned char stop)
132{
133 /* Disable Interrupts */
134 SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0);
135 SERIAL_WRITE(SERIAL_INTR_ENABLE, 0x0);
136
137 {
138 unsigned int divisor;
139
140 SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x80);
141
142 divisor = TITAN_SERIAL_BASE_BAUD / baud;
143 SERIAL_WRITE(SERIAL_DIVISOR_LSB, divisor & 0xff);
144
145 SERIAL_WRITE(SERIAL_DIVISOR_MSB, (divisor & 0xff00) >> 8);
146 SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0);
147 }
148
149 SERIAL_WRITE(SERIAL_DATA_FORMAT, data | parity | stop);
150}
151
152static int remoteDebugInitialized = 0;
153
154unsigned char getDebugChar(void)
155{
156 if (!remoteDebugInitialized) {
157 remoteDebugInitialized = 1;
158 debugInit(YOSEMITE_BAUD_115200,
159 YOSEMITE_DATA_8BIT,
160 YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT);
161 }
162
163 while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x1) == 0);
164 return SERIAL_READ(SERIAL_RCV_BUFFER);
165}
166
167int putDebugChar(unsigned char byte)
168{
169 if (!remoteDebugInitialized) {
170 remoteDebugInitialized = 1;
171 debugInit(YOSEMITE_BAUD_115200,
172 YOSEMITE_DATA_8BIT,
173 YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT);
174 }
175
176 while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x20) == 0);
177 SERIAL_WRITE(SERIAL_SEND_BUFFER, byte);
178
179 return 1;
180}
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 000000000000..d22c9ffe4914
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/ht-irq.c
@@ -0,0 +1,53 @@
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/version.h>
30#include <linux/init.h>
31#include <asm/pci.h>
32
33/*
34 * HT Bus fixup for the Titan
35 * XXX IRQ values need to change based on the board layout
36 */
37void __init titan_ht_pcibios_fixup_bus(struct pci_bus *bus)
38{
39 struct pci_bus *current_bus = bus;
40 struct pci_dev *devices;
41 struct list_head *devices_link;
42
43 list_for_each(devices_link, &(current_bus->devices)) {
44 devices = pci_dev_b(devices_link);
45 if (devices == NULL)
46 continue;
47 }
48
49 /*
50 * PLX and SPKT related changes go here
51 */
52
53}
diff --git a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c
new file mode 100644
index 000000000000..dad228d3a220
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/ht.c
@@ -0,0 +1,454 @@
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/config.h>
27#include <linux/types.h>
28#include <linux/pci.h>
29#include <linux/kernel.h>
30#include <linux/slab.h>
31#include <linux/version.h>
32#include <asm/pci.h>
33#include <asm/io.h>
34
35#include <linux/init.h>
36#include <asm/titan_dep.h>
37
38#ifdef CONFIG_HYPERTRANSPORT
39
40
41/*
42 * This function check if the Hypertransport Link Initialization completed. If
43 * it did, then proceed further with scanning bus #2
44 */
45static __inline__ int check_titan_htlink(void)
46{
47 u32 val;
48
49 val = *(volatile uint32_t *)(RM9000x2_HTLINK_REG);
50 if (val & 0x00000020)
51 /* HT Link Initialization completed */
52 return 1;
53 else
54 return 0;
55}
56
57static int titan_ht_config_read_dword(struct pci_dev *device,
58 int offset, u32* val)
59{
60 int dev, bus, func;
61 uint32_t address_reg, data_reg;
62 uint32_t address;
63
64 bus = device->bus->number;
65 dev = PCI_SLOT(device->devfn);
66 func = PCI_FUNC(device->devfn);
67
68 /* XXX Need to change the Bus # */
69 if (bus > 2)
70 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
71 0x80000000 | 0x1;
72 else
73 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
74
75 address_reg = RM9000x2_OCD_HTCFGA;
76 data_reg = RM9000x2_OCD_HTCFGD;
77
78 RM9K_WRITE(address_reg, address);
79 RM9K_READ(data_reg, val);
80
81 return PCIBIOS_SUCCESSFUL;
82}
83
84
85static int titan_ht_config_read_word(struct pci_dev *device,
86 int offset, u16* val)
87{
88 int dev, bus, func;
89 uint32_t address_reg, data_reg;
90 uint32_t address;
91
92 bus = device->bus->number;
93 dev = PCI_SLOT(device->devfn);
94 func = PCI_FUNC(device->devfn);
95
96 /* XXX Need to change the Bus # */
97 if (bus > 2)
98 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
99 0x80000000 | 0x1;
100 else
101 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
102
103 address_reg = RM9000x2_OCD_HTCFGA;
104 data_reg = RM9000x2_OCD_HTCFGD;
105
106 if ((offset & 0x3) == 0)
107 offset = 0x2;
108 else
109 offset = 0x0;
110
111 RM9K_WRITE(address_reg, address);
112 RM9K_READ_16(data_reg + offset, val);
113
114 return PCIBIOS_SUCCESSFUL;
115}
116
117
118u32 longswap(unsigned long l)
119{
120 unsigned char b1,b2,b3,b4;
121
122 b1 = l&255;
123 b2 = (l>>8)&255;
124 b3 = (l>>16)&255;
125 b4 = (l>>24)&255;
126
127 return ((b1<<24) + (b2<<16) + (b3<<8) + b4);
128}
129
130
131static int titan_ht_config_read_byte(struct pci_dev *device,
132 int offset, u8* val)
133{
134 int dev, bus, func;
135 uint32_t address_reg, data_reg;
136 uint32_t address;
137 int offset1;
138
139 bus = device->bus->number;
140 dev = PCI_SLOT(device->devfn);
141 func = PCI_FUNC(device->devfn);
142
143 /* XXX Need to change the Bus # */
144 if (bus > 2)
145 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
146 0x80000000 | 0x1;
147 else
148 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
149
150 address_reg = RM9000x2_OCD_HTCFGA;
151 data_reg = RM9000x2_OCD_HTCFGD;
152
153 RM9K_WRITE(address_reg, address);
154
155 if ((offset & 0x3) == 0) {
156 offset1 = 0x3;
157 }
158 if ((offset & 0x3) == 1) {
159 offset1 = 0x2;
160 }
161 if ((offset & 0x3) == 2) {
162 offset1 = 0x1;
163 }
164 if ((offset & 0x3) == 3) {
165 offset1 = 0x0;
166 }
167 RM9K_READ_8(data_reg + offset1, val);
168
169 return PCIBIOS_SUCCESSFUL;
170}
171
172
173static int titan_ht_config_write_dword(struct pci_dev *device,
174 int offset, u8 val)
175{
176 int dev, bus, func;
177 uint32_t address_reg, data_reg;
178 uint32_t address;
179
180 bus = device->bus->number;
181 dev = PCI_SLOT(device->devfn);
182 func = PCI_FUNC(device->devfn);
183
184 /* XXX Need to change the Bus # */
185 if (bus > 2)
186 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
187 0x80000000 | 0x1;
188 else
189 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
190
191 address_reg = RM9000x2_OCD_HTCFGA;
192 data_reg = RM9000x2_OCD_HTCFGD;
193
194 RM9K_WRITE(address_reg, address);
195 RM9K_WRITE(data_reg, val);
196
197 return PCIBIOS_SUCCESSFUL;
198}
199
200static int titan_ht_config_write_word(struct pci_dev *device,
201 int offset, u8 val)
202{
203 int dev, bus, func;
204 uint32_t address_reg, data_reg;
205 uint32_t address;
206
207 bus = device->bus->number;
208 dev = PCI_SLOT(device->devfn);
209 func = PCI_FUNC(device->devfn);
210
211 /* XXX Need to change the Bus # */
212 if (bus > 2)
213 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
214 0x80000000 | 0x1;
215 else
216 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
217
218 address_reg = RM9000x2_OCD_HTCFGA;
219 data_reg = RM9000x2_OCD_HTCFGD;
220
221 if ((offset & 0x3) == 0)
222 offset = 0x2;
223 else
224 offset = 0x0;
225
226 RM9K_WRITE(address_reg, address);
227 RM9K_WRITE_16(data_reg + offset, val);
228
229 return PCIBIOS_SUCCESSFUL;
230}
231
232static int titan_ht_config_write_byte(struct pci_dev *device,
233 int offset, u8 val)
234{
235 int dev, bus, func;
236 uint32_t address_reg, data_reg;
237 uint32_t address;
238 int offset1;
239
240 bus = device->bus->number;
241 dev = PCI_SLOT(device->devfn);
242 func = PCI_FUNC(device->devfn);
243
244 /* XXX Need to change the Bus # */
245 if (bus > 2)
246 address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
247 0x80000000 | 0x1;
248 else
249 address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
250
251 address_reg = RM9000x2_OCD_HTCFGA;
252 data_reg = RM9000x2_OCD_HTCFGD;
253
254 RM9K_WRITE(address_reg, address);
255
256 if ((offset & 0x3) == 0) {
257 offset1 = 0x3;
258 }
259 if ((offset & 0x3) == 1) {
260 offset1 = 0x2;
261 }
262 if ((offset & 0x3) == 2) {
263 offset1 = 0x1;
264 }
265 if ((offset & 0x3) == 3) {
266 offset1 = 0x0;
267 }
268
269 RM9K_WRITE_8(data_reg + offset1, val);
270 return PCIBIOS_SUCCESSFUL;
271}
272
273
274static void titan_pcibios_set_master(struct pci_dev *dev)
275{
276 u16 cmd;
277 int bus = dev->bus->number;
278
279 if (check_titan_htlink())
280 titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
281
282 cmd |= PCI_COMMAND_MASTER;
283
284 if (check_titan_htlink())
285 titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
286}
287
288
289int pcibios_enable_resources(struct pci_dev *dev)
290{
291 u16 cmd, old_cmd;
292 u8 tmp1;
293 int idx;
294 struct resource *r;
295 int bus = dev->bus->number;
296
297 if (check_titan_htlink())
298 titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
299
300 old_cmd = cmd;
301 for (idx = 0; idx < 6; idx++) {
302 r = &dev->resource[idx];
303 if (!r->start && r->end) {
304 printk(KERN_ERR
305 "PCI: Device %s not available because of "
306 "resource collisions\n", pci_name(dev));
307 return -EINVAL;
308 }
309 if (r->flags & IORESOURCE_IO)
310 cmd |= PCI_COMMAND_IO;
311 if (r->flags & IORESOURCE_MEM)
312 cmd |= PCI_COMMAND_MEMORY;
313 }
314 if (cmd != old_cmd) {
315 if (check_titan_htlink())
316 titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
317 }
318
319 if (check_titan_htlink())
320 titan_ht_config_read_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1);
321
322 if (tmp1 != 8) {
323 printk(KERN_WARNING "PCI setting cache line size to 8 from "
324 "%d\n", tmp1);
325 }
326
327 if (check_titan_htlink())
328 titan_ht_config_write_byte(dev, PCI_CACHE_LINE_SIZE, 8);
329
330 if (check_titan_htlink())
331 titan_ht_config_read_byte(dev, PCI_LATENCY_TIMER, &tmp1);
332
333 if (tmp1 < 32 || tmp1 == 0xff) {
334 printk(KERN_WARNING "PCI setting latency timer to 32 from %d\n",
335 tmp1);
336 }
337
338 if (check_titan_htlink())
339 titan_ht_config_write_byte(dev, PCI_LATENCY_TIMER, 32);
340
341 return 0;
342}
343
344
345int pcibios_enable_device(struct pci_dev *dev, int mask)
346{
347 return pcibios_enable_resources(dev);
348}
349
350
351
352void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
353 struct resource *res, int resource)
354{
355 u32 new, check;
356 int reg;
357
358 return;
359
360 new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
361 if (resource < 6) {
362 reg = PCI_BASE_ADDRESS_0 + 4 * resource;
363 } else if (resource == PCI_ROM_RESOURCE) {
364 res->flags |= IORESOURCE_ROM_ENABLE;
365 reg = dev->rom_base_reg;
366 } else {
367 /*
368 * Somebody might have asked allocation of a non-standard
369 * resource
370 */
371 return;
372 }
373
374 pci_write_config_dword(dev, reg, new);
375 pci_read_config_dword(dev, reg, &check);
376 if ((new ^ check) &
377 ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
378 PCI_BASE_ADDRESS_MEM_MASK)) {
379 printk(KERN_ERR "PCI: Error while updating region "
380 "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
381 new, check);
382 }
383}
384
385
386void pcibios_align_resource(void *data, struct resource *res,
387 unsigned long size, unsigned long align)
388{
389 struct pci_dev *dev = data;
390
391 if (res->flags & IORESOURCE_IO) {
392 unsigned long start = res->start;
393
394 /* We need to avoid collisions with `mirrored' VGA ports
395 and other strange ISA hardware, so we always want the
396 addresses kilobyte aligned. */
397 if (size > 0x100) {
398 printk(KERN_ERR "PCI: I/O Region %s/%d too large"
399 " (%ld bytes)\n", pci_name(dev),
400 dev->resource - res, size);
401 }
402
403 start = (start + 1024 - 1) & ~(1024 - 1);
404 res->start = start;
405 }
406}
407
408struct pci_ops titan_pci_ops = {
409 titan_ht_config_read_byte,
410 titan_ht_config_read_word,
411 titan_ht_config_read_dword,
412 titan_ht_config_write_byte,
413 titan_ht_config_write_word,
414 titan_ht_config_write_dword
415};
416
417void __init pcibios_fixup_bus(struct pci_bus *c)
418{
419 titan_ht_pcibios_fixup_bus(c);
420}
421
422void __init pcibios_init(void)
423{
424
425 /* Reset PCI I/O and PCI MEM values */
426 /* XXX Need to add the proper values here */
427 ioport_resource.start = 0xe0000000;
428 ioport_resource.end = 0xe0000000 + 0x20000000 - 1;
429 iomem_resource.start = 0xc0000000;
430 iomem_resource.end = 0xc0000000 + 0x20000000 - 1;
431
432 /* XXX Need to add bus values */
433 pci_scan_bus(2, &titan_pci_ops, NULL);
434 pci_scan_bus(3, &titan_pci_ops, NULL);
435}
436
437/*
438 * for parsing "pci=" kernel boot arguments.
439 */
440char *pcibios_setup(char *str)
441{
442 printk(KERN_INFO "rr: pcibios_setup\n");
443 /* Nothing to do for now. */
444
445 return str;
446}
447
448unsigned __init int pcibios_assign_all_busses(void)
449{
450 /* We want to use the PCI bus detection done by PMON */
451 return 0;
452}
453
454#endif /* CONFIG_HYPERTRANSPORT */
diff --git a/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c
new file mode 100644
index 000000000000..416da22b3bf4
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c
@@ -0,0 +1,188 @@
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 * Detailed Description:
28 *
29 * This block implements the I2C interface to the slave devices like the
30 * Atmel 24C32 EEPROM and the MAX 1619 Sensors device. The I2C Master interface
31 * can be controlled by the SCMB block. And the SCMB block kicks in only when
32 * using the Ethernet Mode of operation and __not__ the SysAD mode
33 *
34 * The SCMB controls the two modes: MDIO and the I2C. The MDIO mode is used to
35 * communicate with the Quad-PHY from Marvel. The I2C is used to communicate
36 * with the I2C slave devices. It seems that the driver does not explicitly
37 * deal with the control of SDA and SCL serial lines. So, the driver will set
38 * the slave address, drive the command and then the data. The SCMB will then
39 * control the two serial lines as required.
40 *
41 * It seems the documents are very unclear abt this. Hence, I took some time
42 * out to write the desciption to have an idea of how the I2C can actually
43 * work. Currently, this Linux driver wont be integrated into the generic Linux
44 * I2C framework. And finally, the I2C interface is also known as the 2BI
45 * interface. 2BI means 2-bit interface referring to SDA and SCL serial lines
46 * respectively.
47 *
48 * - Manish Lachwani (12/09/2003)
49 */
50
51#include "i2c-yosemite.h"
52
53/*
54 * Poll the I2C interface for the BUSY bit.
55 */
56static int titan_i2c_poll(void)
57{
58 int i = 0;
59 unsigned long val = 0;
60
61 for (i = 0; i < TITAN_I2C_MAX_POLL; i++) {
62 val = TITAN_I2C_READ(TITAN_I2C_COMMAND);
63
64 if (!(val & 0x8000))
65 return 0;
66 }
67
68 return TITAN_I2C_ERR_TIMEOUT;
69}
70
71/*
72 * Execute the I2C command
73 */
74int titan_i2c_xfer(unsigned int slave_addr, titan_i2c_command * cmd,
75 int size, unsigned int *addr)
76{
77 int loop = 0, bytes, i;
78 unsigned int *write_data, data, *read_data;
79 unsigned long reg_val, val;
80
81 write_data = cmd->data;
82 read_data = addr;
83
84 TITAN_I2C_WRITE(TITAN_I2C_SLAVE_ADDRESS, slave_addr);
85
86 if (cmd->type == TITAN_I2C_CMD_WRITE)
87 loop = cmd->write_size;
88 else
89 loop = size;
90
91 while (loop > 0) {
92 if ((cmd->type == TITAN_I2C_CMD_WRITE) ||
93 (cmd->type == TITAN_I2C_CMD_READ_WRITE)) {
94
95 reg_val = TITAN_I2C_DATA;
96 for (i = 0; i < TITAN_I2C_MAX_WORDS_PER_RW;
97 ++i, write_data += 2, reg_val += 4) {
98 if (bytes < cmd->write_size) {
99 data = write_data[0];
100 ++data;
101 }
102
103 if (bytes < cmd->write_size) {
104 data = write_data[1];
105 ++data;
106 }
107
108 TITAN_I2C_WRITE(reg_val, data);
109 }
110 }
111
112 TITAN_I2C_WRITE(TITAN_I2C_COMMAND,
113 (unsigned int) (cmd->type << 13));
114 if (titan_i2c_poll() != TITAN_I2C_ERR_OK)
115 return TITAN_I2C_ERR_TIMEOUT;
116
117 if ((cmd->type == TITAN_I2C_CMD_READ) ||
118 (cmd->type == TITAN_I2C_CMD_READ_WRITE)) {
119
120 reg_val = TITAN_I2C_DATA;
121 for (i = 0; i < TITAN_I2C_MAX_WORDS_PER_RW;
122 ++i, read_data += 2, reg_val += 4) {
123 data = TITAN_I2C_READ(reg_val);
124
125 if (bytes < size) {
126 read_data[0] = data & 0xff;
127 ++bytes;
128 }
129
130 if (bytes < size) {
131 read_data[1] =
132 ((data >> 8) & 0xff);
133 ++bytes;
134 }
135 }
136 }
137
138 loop -= (TITAN_I2C_MAX_WORDS_PER_RW * 2);
139 }
140
141 /*
142 * Read the Interrupt status and then return the appropriate error code
143 */
144
145 val = TITAN_I2C_READ(TITAN_I2C_INTERRUPTS);
146 if (val & 0x0020)
147 return TITAN_I2C_ERR_ARB_LOST;
148
149 if (val & 0x0040)
150 return TITAN_I2C_ERR_NO_RESP;
151
152 if (val & 0x0080)
153 return TITAN_I2C_ERR_DATA_COLLISION;
154
155 return TITAN_I2C_ERR_OK;
156}
157
158/*
159 * Init the I2C subsystem of the PMC-Sierra Yosemite board
160 */
161int titan_i2c_init(titan_i2c_config * config)
162{
163 unsigned int val;
164
165 /*
166 * Reset the SCMB and program into the I2C mode
167 */
168 TITAN_I2C_WRITE(TITAN_I2C_SCMB_CONTROL, 0xA000);
169 TITAN_I2C_WRITE(TITAN_I2C_SCMB_CONTROL, 0x2000);
170
171 /*
172 * Configure the filtera and clka values
173 */
174 val = TITAN_I2C_READ(TITAN_I2C_SCMB_CLOCK_A);
175 val |= ((val & ~(0xF000)) | ((config->filtera << 12) & 0xF000));
176 val |= ((val & ~(0x03FF)) | (config->clka & 0x03FF));
177 TITAN_I2C_WRITE(TITAN_I2C_SCMB_CLOCK_A, val);
178
179 /*
180 * Configure the filterb and clkb values
181 */
182 val = TITAN_I2C_READ(TITAN_I2C_SCMB_CLOCK_B);
183 val |= ((val & ~(0xF000)) | ((config->filterb << 12) & 0xF000));
184 val |= ((val & ~(0x03FF)) | (config->clkb & 0x03FF));
185 TITAN_I2C_WRITE(TITAN_I2C_SCMB_CLOCK_B, val);
186
187 return TITAN_I2C_ERR_OK;
188}
diff --git a/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h
new file mode 100644
index 000000000000..31c5523276fa
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h
@@ -0,0 +1,96 @@
1/*
2 * arch/mips/pmc-sierra/yosemite/i2c-yosemite.h
3 *
4 * Copyright (C) 2003 PMC-Sierra Inc.
5 * Author: Manish Lachwani (lachwani@pmc-sierra.com)
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
28#ifndef __I2C_YOSEMITE_H
29#define __I2C_YOSEMITE_H
30
31/* Read and Write operations to the chip */
32
33#define TITAN_I2C_BASE 0xbb000000 /* XXX Needs to change */
34
35#define TITAN_I2C_WRITE(offset, data) \
36 *(volatile unsigned long *)(TITAN_I2C_BASE + offset) = data
37
38#define TITAN_I2C_READ(offset) *(volatile unsigned long *)(TITAN_I2C_BASE + offset)
39
40
41/* Local constansts*/
42#define TITAN_I2C_MAX_FILTER 15
43#define TITAN_I2C_MAX_CLK 1023
44#define TITAN_I2C_MAX_ARBF 15
45#define TITAN_I2C_MAX_NAK 15
46#define TITAN_I2C_MAX_MASTERCODE 7
47#define TITAN_I2C_MAX_WORDS_PER_RW 4
48#define TITAN_I2C_MAX_POLL 100
49
50/* Registers used for I2C work */
51#define TITAN_I2C_SCMB_CONTROL 0x0180 /* SCMB Control */
52#define TITAN_I2C_SCMB_CLOCK_A 0x0184 /* SCMB Clock A */
53#define TITAN_I2C_SCMB_CLOCK_B 0x0188 /* SCMB Clock B */
54#define TITAN_I2C_CONFIG 0x01A0 /* I2C Config */
55#define TITAN_I2C_COMMAND 0x01A4 /* I2C Command */
56#define TITAN_I2C_SLAVE_ADDRESS 0x01A8 /* I2C Slave Address */
57#define TITAN_I2C_DATA 0x01AC /* I2C Data [15:0] */
58#define TITAN_I2C_INTERRUPTS 0x01BC /* I2C Interrupts */
59
60/* Error */
61#define TITAN_I2C_ERR_ARB_LOST (-9220)
62#define TITAN_I2C_ERR_NO_RESP (-9221)
63#define TITAN_I2C_ERR_DATA_COLLISION (-9222)
64#define TITAN_I2C_ERR_TIMEOUT (-9223)
65#define TITAN_I2C_ERR_OK 0
66
67/* I2C Command Type */
68typedef enum {
69 TITAN_I2C_CMD_WRITE = 0,
70 TITAN_I2C_CMD_READ = 1,
71 TITAN_I2C_CMD_READ_WRITE = 2
72} titan_i2c_cmd_type;
73
74/* I2C structures */
75typedef struct {
76 int filtera; /* Register 0x0184, bits 15 - 12 */
77 int clka; /* Register 0x0184, bits 9 - 0 */
78 int filterb; /* Register 0x0188, bits 15 - 12 */
79 int clkb; /* Register 0x0188, bits 9 - 0 */
80} titan_i2c_config;
81
82/* I2C command type */
83typedef struct {
84 titan_i2c_cmd_type type; /* Type of command */
85 int num_arb; /* Register 0x01a0, bits 15 - 12 */
86 int num_nak; /* Register 0x01a0, bits 11 - 8 */
87 int addr_size; /* Register 0x01a0, bit 7 */
88 int mst_code; /* Register 0x01a0, bits 6 - 4 */
89 int arb_en; /* Register 0x01a0, bit 1 */
90 int speed; /* Register 0x01a0, bit 0 */
91 int slave_addr; /* Register 0x01a8 */
92 int write_size; /* Register 0x01a4, bits 10 - 8 */
93 unsigned int *data; /* Register 0x01ac */
94} titan_i2c_command;
95
96#endif /* __I2C_YOSEMITE_H */
diff --git a/arch/mips/pmc-sierra/yosemite/irq-handler.S b/arch/mips/pmc-sierra/yosemite/irq-handler.S
new file mode 100644
index 000000000000..33b9c40d4f5c
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/irq-handler.S
@@ -0,0 +1,93 @@
1/*
2 * Copyright 2003, 04 PMC-Sierra Inc.
3 * Author: Manish Lachwani (lachwani@pmc-sierra.com
4 * Copyright 2004 Ralf Baechle (ralf@linux-mips.org)
5 *
6 * First-level interrupt router for the PMC-Sierra Titan board
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 * Titan supports Hypertransport or PCI but not both. Hence, one interrupt
14 * line is shared between the PCI slot A and Hypertransport. This is the
15 * Processor INTB #0.
16 */
17
18#include <linux/config.h>
19#include <asm/asm.h>
20#include <asm/mipsregs.h>
21#include <asm/addrspace.h>
22#include <asm/regdef.h>
23#include <asm/stackframe.h>
24
25 .align 5
26 NESTED(titan_handle_int, PT_SIZE, sp)
27 SAVE_ALL
28 CLI
29 .set at
30 .set noreorder
31 la ra, ret_from_irq
32 mfc0 t0, CP0_CAUSE
33 mfc0 t2, CP0_STATUS
34
35 and t0, t2
36
37 andi t2, t0, STATUSF_IP7 /* INTB5 hardware line */
38 bnez t2, ll_timer_irq /* Timer */
39 andi t1, t0, STATUSF_IP2 /* INTB0 hardware line */
40 bnez t1, ll_pcia_irq /* 64-bit PCI */
41 andi t2, t0, STATUSF_IP3 /* INTB1 hardware line */
42 bnez t2, ll_pcib_irq /* second 64-bit PCI slot */
43 andi t1, t0, STATUSF_IP4 /* INTB2 hardware line */
44 bnez t1, ll_duart_irq /* UART */
45 andi t2, t0, STATUSF_IP5 /* SMP inter-core interrupts */
46 bnez t2, ll_smp_irq
47 andi t1, t0, STATUSF_IP6
48 bnez t1, ll_ht_irq /* Hypertransport */
49
50 move a0, sp
51 j do_extended_irq
52 END(titan_handle_int)
53
54 .set reorder
55 .align 5
56
57ll_pcia_irq:
58 li a0, 2
59 move a1, sp
60#ifdef CONFIG_HYPERTRANSPORT
61 j ll_ht_smp_irq_handler
62#else
63 j do_IRQ
64#endif
65
66ll_pcib_irq:
67 li a0, 3
68 move a1, sp
69 j do_IRQ
70
71ll_duart_irq:
72 li a0, 4
73 move a1, sp
74 j do_IRQ
75
76ll_smp_irq:
77 li a0, 5
78 move a1, sp
79#ifdef CONFIG_SMP
80 j titan_mailbox_irq
81#else
82 j do_IRQ
83#endif
84
85ll_ht_irq:
86 li a0, 6
87 move a1, sp
88 j ll_ht_smp_irq_handler
89
90ll_timer_irq:
91 li a0, 7
92 move a1, sp
93 j do_IRQ
diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c
new file mode 100644
index 000000000000..f4e2897d9bf7
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/irq.c
@@ -0,0 +1,167 @@
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 * Second level Interrupt handlers for the PMC-Sierra Titan/Yosemite board
26 */
27#include <linux/config.h>
28#include <linux/errno.h>
29#include <linux/init.h>
30#include <linux/kernel_stat.h>
31#include <linux/module.h>
32#include <linux/signal.h>
33#include <linux/sched.h>
34#include <linux/types.h>
35#include <linux/interrupt.h>
36#include <linux/ioport.h>
37#include <linux/irq.h>
38#include <linux/timex.h>
39#include <linux/slab.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 asmlinkage void titan_handle_int(void);
59extern void jaguar_mailbox_irq(struct pt_regs *);
60
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 */
67asmlinkage void ll_ht_smp_irq_handler(int irq, struct pt_regs *regs)
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, regs);
111}
112
113asmlinkage void do_extended_irq(struct pt_regs *regs)
114{
115 unsigned int intcontrol = read_c0_intcontrol();
116 unsigned int cause = read_c0_cause();
117 unsigned int status = read_c0_status();
118 unsigned int pending_sr, pending_ic;
119
120 pending_sr = status & cause & 0xff00;
121 pending_ic = (cause >> 8) & intcontrol & 0xff00;
122
123 if (pending_ic & (1 << 13))
124 do_IRQ(13, regs);
125
126}
127
128#ifdef CONFIG_KGDB
129extern void init_second_port(void);
130#endif
131
132/*
133 * Initialize the next level interrupt handler
134 */
135void __init arch_init_irq(void)
136{
137 clear_c0_status(ST0_IM);
138
139 set_except_vector(0, titan_handle_int);
140 mips_cpu_irq_init(0);
141 rm7k_cpu_irq_init(8);
142 rm9k_cpu_irq_init(12);
143
144#ifdef CONFIG_KGDB
145 /* At this point, initialize the second serial port */
146 init_second_port();
147#endif
148
149#ifdef CONFIG_GDB_CONSOLE
150 register_gdb_console();
151#endif
152}
153
154#ifdef CONFIG_KGDB
155/*
156 * The 16550 DUART has two ports, but is allocated one IRQ
157 * for the serial console. Hence, a generic framework for
158 * serial IRQ routing in place. Currently, just calls the
159 * do_IRQ fuction. But, going in the future, need to check
160 * DUART registers for channel A and B, then decide the
161 * appropriate action
162 */
163asmlinkage void yosemite_kgdb_irq(int irq, struct pt_regs *regs)
164{
165 do_IRQ(irq, regs);
166}
167#endif
diff --git a/arch/mips/pmc-sierra/yosemite/prom.c b/arch/mips/pmc-sierra/yosemite/prom.c
new file mode 100644
index 000000000000..1fb3e697948d
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/prom.c
@@ -0,0 +1,141 @@
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/config.h>
12#include <linux/init.h>
13#include <linux/sched.h>
14#include <linux/mm.h>
15#include <linux/delay.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/system.h>
23#include <asm/bootinfo.h>
24#include <asm/pmon.h>
25
26#ifdef CONFIG_SMP
27extern void prom_grab_secondary(void);
28#else
29#define prom_grab_secondary() do { } while (0)
30#endif
31
32#include "setup.h"
33
34struct callvectors *debug_vectors;
35
36extern unsigned long yosemite_base;
37extern unsigned long cpu_clock;
38
39const char *get_system_type(void)
40{
41 return "PMC-Sierra Yosemite";
42}
43
44static void prom_cpu0_exit(void *arg)
45{
46 void *nvram = (void *) YOSEMITE_RTC_BASE;
47
48 /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
49 writeb(0x84, nvram + 0xff7);
50
51 /* wait for the watchdog to go off */
52 mdelay(100 + (1000 / 16));
53
54 /* if the watchdog fails for some reason, let people know */
55 printk(KERN_NOTICE "Watchdog reset failed\n");
56}
57
58/*
59 * Reset the NVRAM over the local bus
60 */
61static void prom_exit(void)
62{
63#ifdef CONFIG_SMP
64 if (smp_processor_id())
65 /* CPU 1 */
66 smp_call_function(prom_cpu0_exit, NULL, 1, 1);
67#endif
68 prom_cpu0_exit(NULL);
69}
70
71/*
72 * Halt the system
73 */
74static void prom_halt(void)
75{
76 printk(KERN_NOTICE "\n** You can safely turn off the power\n");
77 while (1)
78 __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0");
79}
80
81/*
82 * Init routine which accepts the variables from PMON
83 */
84void __init prom_init(void)
85{
86 int argc = fw_arg0;
87 char **arg = (char **) fw_arg1;
88 char **env = (char **) fw_arg2;
89 struct callvectors *cv = (struct callvectors *) fw_arg3;
90 int i = 0;
91
92 /* Callbacks for halt, restart */
93 _machine_restart = (void (*)(char *)) prom_exit;
94 _machine_halt = prom_halt;
95 _machine_power_off = prom_halt;
96
97 debug_vectors = cv;
98 arcs_cmdline[0] = '\0';
99
100 /* Get the boot parameters */
101 for (i = 1; i < argc; i++) {
102 if (strlen(arcs_cmdline) + strlen(arg[i] + 1) >=
103 sizeof(arcs_cmdline))
104 break;
105
106 strcat(arcs_cmdline, arg[i]);
107 strcat(arcs_cmdline, " ");
108 }
109
110#ifdef CONFIG_SERIAL_8250_CONSOLE
111 if ((strstr(arcs_cmdline, "console=ttyS")) == NULL)
112 strcat(arcs_cmdline, "console=ttyS0,115200");
113#endif
114
115 while (*env) {
116 if (strncmp("ocd_base", *env, strlen("ocd_base")) == 0)
117 yosemite_base =
118 simple_strtol(*env + strlen("ocd_base="), NULL,
119 16);
120
121 if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0)
122 cpu_clock =
123 simple_strtol(*env + strlen("cpuclock="), NULL,
124 10);
125
126 env++;
127 }
128
129 mips_machgroup = MACH_GROUP_TITAN;
130 mips_machtype = MACH_TITAN_YOSEMITE;
131
132 prom_grab_secondary();
133}
134
135void __init prom_free_prom_memory(void)
136{
137}
138
139void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
140{
141}
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 000000000000..757e605693ff
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/py-console.c
@@ -0,0 +1,114 @@
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 " ld %0, %1 \n"
69 " lbu %0, (%0) \n"
70 " .set mips0 \n"
71 : "=r" (res)
72 : "m" (vaddr));
73
74 write_c0_status(sr);
75 ssnop_4();
76
77 return res;
78}
79
80static void writeb_outer_space(unsigned long long phys, unsigned char c)
81{
82 unsigned long long vaddr = IO_BASE_64 | phys;
83 unsigned long tmp;
84 unsigned int sr;
85
86 sr = read_c0_status();
87 write_c0_status((sr | ST0_KX) & ~ ST0_IE);
88 ssnop_4();
89
90 __asm__ __volatile__ (
91 " .set mips3 \n"
92 " ld %0, %1 \n"
93 " sb %2, (%0) \n"
94 " .set mips0 \n"
95 : "=&r" (tmp)
96 : "m" (vaddr), "r" (c));
97
98 write_c0_status(sr);
99 ssnop_4();
100}
101
102void prom_putchar(char c)
103{
104 unsigned long lsr = 0xfd000008ULL + offsetof(struct yo_uartregs, iu_lsr);
105 unsigned long thr = 0xfd000008ULL + offsetof(struct yo_uartregs, iu_thr);
106
107 while ((readb_outer_space(lsr) & 0x20) == 0);
108 writeb_outer_space(thr, c);
109}
110
111char __init prom_getchar(void)
112{
113 return 0;
114}
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
new file mode 100644
index 000000000000..7225bbf20ce4
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -0,0 +1,235 @@
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
43#include <asm/time.h>
44#include <asm/bootinfo.h>
45#include <asm/page.h>
46#include <asm/io.h>
47#include <asm/irq.h>
48#include <asm/processor.h>
49#include <asm/ptrace.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;
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
73unsigned long m48t37y_get_time(void)
74{
75 unsigned int year, month, day, hour, min, sec;
76
77 /* Stop the update to the time */
78 m48t37_base->control = 0x40;
79
80 year = BCD2BIN(m48t37_base->year);
81 year += BCD2BIN(m48t37_base->century) * 100;
82
83 month = BCD2BIN(m48t37_base->month);
84 day = BCD2BIN(m48t37_base->date);
85 hour = BCD2BIN(m48t37_base->hour);
86 min = BCD2BIN(m48t37_base->min);
87 sec = BCD2BIN(m48t37_base->sec);
88
89 /* Start the update to the time again */
90 m48t37_base->control = 0x00;
91
92 return mktime(year, month, day, hour, min, sec);
93}
94
95int m48t37y_set_time(unsigned long sec)
96{
97 struct rtc_time tm;
98
99 /* convert to a more useful format -- note months count from 0 */
100 to_tm(sec, &tm);
101 tm.tm_mon += 1;
102
103 /* enable writing */
104 m48t37_base->control = 0x80;
105
106 /* year */
107 m48t37_base->year = BIN2BCD(tm.tm_year % 100);
108 m48t37_base->century = BIN2BCD(tm.tm_year / 100);
109
110 /* month */
111 m48t37_base->month = BIN2BCD(tm.tm_mon);
112
113 /* day */
114 m48t37_base->date = BIN2BCD(tm.tm_mday);
115
116 /* hour/min/sec */
117 m48t37_base->hour = BIN2BCD(tm.tm_hour);
118 m48t37_base->min = BIN2BCD(tm.tm_min);
119 m48t37_base->sec = BIN2BCD(tm.tm_sec);
120
121 /* day of week -- not really used, but let's keep it up-to-date */
122 m48t37_base->day = BIN2BCD(tm.tm_wday + 1);
123
124 /* disable writing */
125 m48t37_base->control = 0x00;
126
127 return 0;
128}
129
130void yosemite_timer_setup(struct irqaction *irq)
131{
132 setup_irq(7, irq);
133}
134
135void yosemite_time_init(void)
136{
137 board_timer_setup = yosemite_timer_setup;
138 mips_hpt_frequency = cpu_clock / 2;
139mips_hpt_frequency = 33000000 * 3 * 5;
140}
141
142/* No other usable initialization hook than this ... */
143extern void (*late_time_init)(void);
144
145unsigned long ocd_base;
146
147EXPORT_SYMBOL(ocd_base);
148
149/*
150 * Common setup before any secondaries are started
151 */
152
153#define TITAN_UART_CLK 3686400
154#define TITAN_SERIAL_BASE_BAUD (TITAN_UART_CLK / 16)
155#define TITAN_SERIAL_IRQ 4
156#define TITAN_SERIAL_BASE 0xfd000008UL
157
158static void __init py_map_ocd(void)
159{
160 ocd_base = (unsigned long) ioremap(OCD_BASE, OCD_SIZE);
161 if (!ocd_base)
162 panic("Mapping OCD failed - game over. Your score is 0.");
163
164 /* Kludge for PMON bug ... */
165 OCD_WRITE(0x0710, 0x0ffff029);
166}
167
168static void __init py_uart_setup(void)
169{
170 struct uart_port up;
171
172 /*
173 * Register to interrupt zero because we share the interrupt with
174 * the serial driver which we don't properly support yet.
175 */
176 memset(&up, 0, sizeof(up));
177 up.membase = (unsigned char *) ioremap(TITAN_SERIAL_BASE, 8);
178 up.irq = TITAN_SERIAL_IRQ;
179 up.uartclk = TITAN_UART_CLK;
180 up.regshift = 0;
181 up.iotype = UPIO_MEM;
182 up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
183 up.line = 0;
184
185 if (early_serial_setup(&up))
186 printk(KERN_ERR "Early serial init of port 0 failed\n");
187}
188
189static void __init py_rtc_setup(void)
190{
191 m48t37_base = ioremap(YOSEMITE_RTC_BASE, YOSEMITE_RTC_SIZE);
192 if (!m48t37_base)
193 printk(KERN_ERR "Mapping the RTC failed\n");
194
195 rtc_get_time = m48t37y_get_time;
196 rtc_set_time = m48t37y_set_time;
197
198 write_seqlock(&xtime_lock);
199 xtime.tv_sec = m48t37y_get_time();
200 xtime.tv_nsec = 0;
201
202 set_normalized_timespec(&wall_to_monotonic,
203 -xtime.tv_sec, -xtime.tv_nsec);
204 write_sequnlock(&xtime_lock);
205}
206
207/* Not only time init but that's what the hook it's called through is named */
208static void __init py_late_time_init(void)
209{
210 py_map_ocd();
211 py_uart_setup();
212 py_rtc_setup();
213}
214
215static int __init pmc_yosemite_setup(void)
216{
217 board_time_init = yosemite_time_init;
218 late_time_init = py_late_time_init;
219
220 /* Add memory regions */
221 add_memory_region(0x00000000, 0x10000000, BOOT_MEM_RAM);
222
223#if 0 /* XXX Crash ... */
224 OCD_WRITE(RM9000x2_OCD_HTSC,
225 OCD_READ(RM9000x2_OCD_HTSC) | HYPERTRANSPORT_ENABLE);
226
227 /* Set the BAR. Shifted mode */
228 OCD_WRITE(RM9000x2_OCD_HTBAR0, HYPERTRANSPORT_BAR0_ADDR);
229 OCD_WRITE(RM9000x2_OCD_HTMASK0, HYPERTRANSPORT_SIZE0);
230#endif
231
232 return 0;
233}
234
235early_initcall(pmc_yosemite_setup);
diff --git a/arch/mips/pmc-sierra/yosemite/setup.h b/arch/mips/pmc-sierra/yosemite/setup.h
new file mode 100644
index 000000000000..1a01abfc7d33
--- /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 000000000000..1d3b0734c78c
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -0,0 +1,172 @@
1#include <linux/linkage.h>
2#include <linux/sched.h>
3
4#include <asm/pmon.h>
5#include <asm/titan_dep.h>
6
7extern unsigned int (*mips_hpt_read)(void);
8extern void (*mips_hpt_init)(unsigned int);
9
10#define LAUNCHSTACK_SIZE 256
11
12static spinlock_t launch_lock __initdata;
13
14static unsigned long secondary_sp __initdata;
15static unsigned long secondary_gp __initdata;
16
17static unsigned char launchstack[LAUNCHSTACK_SIZE] __initdata
18 __attribute__((aligned(2 * sizeof(long))));
19
20static void __init prom_smp_bootstrap(void)
21{
22 local_irq_disable();
23
24 while (spin_is_locked(&launch_lock));
25
26 __asm__ __volatile__(
27 " move $sp, %0 \n"
28 " move $gp, %1 \n"
29 " j smp_bootstrap \n"
30 :
31 : "r" (secondary_sp), "r" (secondary_gp));
32}
33
34/*
35 * PMON is a fragile beast. It'll blow up once the mappings it's littering
36 * right into the middle of KSEG3 are blown away so we have to grab the slave
37 * core early and keep it in a waiting loop.
38 */
39void __init prom_grab_secondary(void)
40{
41 spin_lock(&launch_lock);
42
43 pmon_cpustart(1, &prom_smp_bootstrap,
44 launchstack + LAUNCHSTACK_SIZE, 0);
45}
46
47/*
48 * Detect available CPUs, populate phys_cpu_present_map before smp_init
49 *
50 * We don't want to start the secondary CPU yet nor do we have a nice probing
51 * feature in PMON so we just assume presence of the secondary core.
52 */
53static char maxcpus_string[] __initdata =
54 KERN_WARNING "max_cpus set to 0; using 1 instead\n";
55
56void __init prom_prepare_cpus(unsigned int max_cpus)
57{
58 int enabled = 0, i;
59
60 if (max_cpus == 0) {
61 printk(maxcpus_string);
62 max_cpus = 1;
63 }
64
65 cpus_clear(phys_cpu_present_map);
66
67 for (i = 0; i < 2; i++) {
68 if (i == max_cpus)
69 break;
70
71 /*
72 * The boot CPU
73 */
74 cpu_set(i, phys_cpu_present_map);
75 __cpu_number_map[i] = i;
76 __cpu_logical_map[i] = i;
77 enabled++;
78 }
79
80 /*
81 * Be paranoid. Enable the IPI only if we're really about to go SMP.
82 */
83 if (enabled > 1)
84 set_c0_status(STATUSF_IP5);
85}
86
87/*
88 * Firmware CPU startup hook
89 * Complicated by PMON's weird interface which tries to minimic the UNIX fork.
90 * It launches the next * available CPU and copies some information on the
91 * stack so the first thing we do is throw away that stuff and load useful
92 * values into the registers ...
93 */
94void prom_boot_secondary(int cpu, struct task_struct *idle)
95{
96 unsigned long gp = (unsigned long) idle->thread_info;
97 unsigned long sp = gp + THREAD_SIZE - 32;
98
99 secondary_sp = sp;
100 secondary_gp = gp;
101
102 spin_unlock(&launch_lock);
103}
104
105/* Hook for after all CPUs are online */
106void prom_cpus_done(void)
107{
108}
109
110/*
111 * After we've done initial boot, this function is called to allow the
112 * board code to clean up state, if needed
113 */
114void prom_init_secondary(void)
115{
116 mips_hpt_init(mips_hpt_read());
117
118 set_c0_status(ST0_CO | ST0_IE | ST0_IM);
119}
120
121void prom_smp_finish(void)
122{
123}
124
125asmlinkage void titan_mailbox_irq(struct pt_regs *regs)
126{
127 int cpu = smp_processor_id();
128 unsigned long status;
129
130 if (cpu == 0) {
131 status = OCD_READ(RM9000x2_OCD_INTP0STATUS3);
132 OCD_WRITE(RM9000x2_OCD_INTP0CLEAR3, status);
133 }
134
135 if (cpu == 1) {
136 status = OCD_READ(RM9000x2_OCD_INTP1STATUS3);
137 OCD_WRITE(RM9000x2_OCD_INTP1CLEAR3, status);
138 }
139
140 if (status & 0x2)
141 smp_call_function_interrupt();
142}
143
144/*
145 * Send inter-processor interrupt
146 */
147void core_send_ipi(int cpu, unsigned int action)
148{
149 /*
150 * Generate an INTMSG so that it can be sent over to the
151 * destination CPU. The INTMSG will put the STATUS bits
152 * based on the action desired. An alternative strategy
153 * is to write to the Interrupt Set register, read the
154 * Interrupt Status register and clear the Interrupt
155 * Clear register. The latter is preffered.
156 */
157 switch (action) {
158 case SMP_RESCHEDULE_YOURSELF:
159 if (cpu == 1)
160 OCD_WRITE(RM9000x2_OCD_INTP1SET3, 4);
161 else
162 OCD_WRITE(RM9000x2_OCD_INTP0SET3, 4);
163 break;
164
165 case SMP_CALL_FUNCTION:
166 if (cpu == 1)
167 OCD_WRITE(RM9000x2_OCD_INTP1SET3, 2);
168 else
169 OCD_WRITE(RM9000x2_OCD_INTP0SET3, 2);
170 break;
171 }
172}