add idl4k kernel firmware version 1.13.0.105

This commit is contained in:
Jaroslav Kysela
2015-03-26 17:22:37 +01:00
parent 5194d2792e
commit e9070cdc77
31064 changed files with 12769984 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
#
# Makefile for the PMC-Sierra Titan
#
obj-y += irq.o prom.o py-console.o setup.o
obj-$(CONFIG_SMP) += smp.o
EXTRA_CFLAGS += -Werror

View File

@@ -0,0 +1,169 @@
/*
* Copyright (C) 2003 PMC-Sierra Inc.
* Author: Manish Lachwani (lachwani@pmc-sierra.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Description:
*
* This code reads the ATMEL 24CXX EEPROM. The PMC-Sierra Yosemite board uses the ATMEL
* 24C32/24C64 which uses two byte addressing as compared to 24C16. Note that this program
* uses the serial port like /dev/ttyS0, to communicate with the EEPROM. Hence, you are
* expected to have a connectivity from the EEPROM to the serial port. This program does
* __not__ communicate using the I2C protocol
*/
#include "atmel_read_eeprom.h"
static void delay(int delay)
{
while (delay--);
}
static void send_bit(unsigned char bit)
{
scl_lo;
delay(TXX);
if (bit)
sda_hi;
else
sda_lo;
delay(TXX);
scl_hi;
delay(TXX);
}
static void send_ack(void)
{
send_bit(0);
}
static void send_byte(unsigned char byte)
{
int i = 0;
for (i = 7; i >= 0; i--)
send_bit((byte >> i) & 0x01);
}
static void send_start(void)
{
sda_hi;
delay(TXX);
scl_hi;
delay(TXX);
sda_lo;
delay(TXX);
}
static void send_stop(void)
{
sda_lo;
delay(TXX);
scl_hi;
delay(TXX);
sda_hi;
delay(TXX);
}
static void do_idle(void)
{
sda_hi;
scl_hi;
vcc_off;
}
static int recv_bit(void)
{
int status;
scl_lo;
delay(TXX);
sda_hi;
delay(TXX);
scl_hi;
delay(TXX);
return 1;
}
static unsigned char recv_byte(void) {
int i;
unsigned char byte=0;
for (i=7;i>=0;i--)
byte |= (recv_bit() << i);
return byte;
}
static int recv_ack(void)
{
unsigned int ack;
ack = (unsigned int)recv_bit();
scl_lo;
if (ack) {
do_idle();
printk(KERN_ERR "Error reading the Atmel 24C32/24C64 EEPROM \n");
return -1;
}
return ack;
}
/*
* This function does the actual read of the EEPROM. It needs the buffer into which the
* read data is copied, the size of the EEPROM being read and the buffer size
*/
int read_eeprom(char *buffer, int eeprom_size, int size)
{
int i = 0, err;
send_start();
send_byte(W_HEADER);
recv_ack();
/* EEPROM with size of more than 2K need two byte addressing */
if (eeprom_size > 2048) {
send_byte(0x00);
recv_ack();
}
send_start();
send_byte(R_HEADER);
err = recv_ack();
if (err == -1)
return err;
for (i = 0; i < size; i++) {
*buffer++ = recv_byte();
send_ack();
}
/* Note : We should do some check if the buffer contains correct information */
send_stop();
}

View File

@@ -0,0 +1,68 @@
/*
* arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
*
* Copyright (C) 2003 PMC-Sierra Inc.
* Author: Manish Lachwani (lachwani@pmc-sierra.com)
* Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Header file for atmel_read_eeprom.c
*/
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <asm/pci.h>
#include <asm/io.h>
#include <linux/init.h>
#include <asm/termios.h>
#include <asm/ioctls.h>
#include <linux/ioctl.h>
#include <linux/fcntl.h>
#define DEFAULT_PORT "/dev/ttyS0" /* Port to open */
#define TXX 0 /* Dummy loop for spinning */
#define BLOCK_SEL 0x00
#define SLAVE_ADDR 0xa0
#define READ_BIT 0x01
#define WRITE_BIT 0x00
#define R_HEADER SLAVE_ADDR + BLOCK_SEL + READ_BIT
#define W_HEADER SLAVE_ADDR + BLOCK_SEL + WRITE_BIT
/*
* Clock, Voltages and Data
*/
#define vcc_off (ioctl(fd, TIOCSBRK, 0))
#define vcc_on (ioctl(fd, TIOCCBRK, 0))
#define sda_hi (ioctl(fd, TIOCMBIS, &dtr))
#define sda_lo (ioctl(fd, TIOCMBIC, &dtr))
#define scl_lo (ioctl(fd, TIOCMBIC, &rts))
#define scl_hi (ioctl(fd, TIOCMBIS, &rts))
const char rts = TIOCM_RTS;
const char dtr = TIOCM_DTR;
int fd;

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2003 PMC-Sierra
* Author: Manish Lachwani (lachwani@pmc-sierra.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/pci.h>
/*
* HT Bus fixup for the Titan
* XXX IRQ values need to change based on the board layout
*/
void __init titan_ht_pcibios_fixup_bus(struct pci_bus *bus)
{
struct pci_bus *current_bus = bus;
struct pci_dev *devices;
struct list_head *devices_link;
list_for_each(devices_link, &(current_bus->devices)) {
devices = pci_dev_b(devices_link);
if (devices == NULL)
continue;
}
/*
* PLX and SPKT related changes go here
*/
}

View File

@@ -0,0 +1,416 @@
/*
* Copyright 2003 PMC-Sierra
* Author: Manish Lachwani (lachwani@pmc-sierra.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <asm/pci.h>
#include <asm/io.h>
#include <linux/init.h>
#include <asm/titan_dep.h>
#ifdef CONFIG_HYPERTRANSPORT
/*
* This function check if the Hypertransport Link Initialization completed. If
* it did, then proceed further with scanning bus #2
*/
static __inline__ int check_titan_htlink(void)
{
u32 val;
val = *(volatile uint32_t *)(RM9000x2_HTLINK_REG);
if (val & 0x00000020)
/* HT Link Initialization completed */
return 1;
else
return 0;
}
static int titan_ht_config_read_dword(struct pci_dev *device,
int offset, u32* val)
{
int dev, bus, func;
uint32_t address_reg, data_reg;
uint32_t address;
bus = device->bus->number;
dev = PCI_SLOT(device->devfn);
func = PCI_FUNC(device->devfn);
/* XXX Need to change the Bus # */
if (bus > 2)
address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
0x80000000 | 0x1;
else
address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
address_reg = RM9000x2_OCD_HTCFGA;
data_reg = RM9000x2_OCD_HTCFGD;
RM9K_WRITE(address_reg, address);
RM9K_READ(data_reg, val);
return PCIBIOS_SUCCESSFUL;
}
static int titan_ht_config_read_word(struct pci_dev *device,
int offset, u16* val)
{
int dev, bus, func;
uint32_t address_reg, data_reg;
uint32_t address;
bus = device->bus->number;
dev = PCI_SLOT(device->devfn);
func = PCI_FUNC(device->devfn);
/* XXX Need to change the Bus # */
if (bus > 2)
address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
0x80000000 | 0x1;
else
address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
address_reg = RM9000x2_OCD_HTCFGA;
data_reg = RM9000x2_OCD_HTCFGD;
if ((offset & 0x3) == 0)
offset = 0x2;
else
offset = 0x0;
RM9K_WRITE(address_reg, address);
RM9K_READ_16(data_reg + offset, val);
return PCIBIOS_SUCCESSFUL;
}
u32 longswap(unsigned long l)
{
unsigned char b1, b2, b3, b4;
b1 = l&255;
b2 = (l>>8)&255;
b3 = (l>>16)&255;
b4 = (l>>24)&255;
return ((b1<<24) + (b2<<16) + (b3<<8) + b4);
}
static int titan_ht_config_read_byte(struct pci_dev *device,
int offset, u8* val)
{
int dev, bus, func;
uint32_t address_reg, data_reg;
uint32_t address;
int offset1;
bus = device->bus->number;
dev = PCI_SLOT(device->devfn);
func = PCI_FUNC(device->devfn);
/* XXX Need to change the Bus # */
if (bus > 2)
address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
0x80000000 | 0x1;
else
address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
address_reg = RM9000x2_OCD_HTCFGA;
data_reg = RM9000x2_OCD_HTCFGD;
RM9K_WRITE(address_reg, address);
if ((offset & 0x3) == 0) {
offset1 = 0x3;
}
if ((offset & 0x3) == 1) {
offset1 = 0x2;
}
if ((offset & 0x3) == 2) {
offset1 = 0x1;
}
if ((offset & 0x3) == 3) {
offset1 = 0x0;
}
RM9K_READ_8(data_reg + offset1, val);
return PCIBIOS_SUCCESSFUL;
}
static int titan_ht_config_write_dword(struct pci_dev *device,
int offset, u8 val)
{
int dev, bus, func;
uint32_t address_reg, data_reg;
uint32_t address;
bus = device->bus->number;
dev = PCI_SLOT(device->devfn);
func = PCI_FUNC(device->devfn);
/* XXX Need to change the Bus # */
if (bus > 2)
address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
0x80000000 | 0x1;
else
address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
address_reg = RM9000x2_OCD_HTCFGA;
data_reg = RM9000x2_OCD_HTCFGD;
RM9K_WRITE(address_reg, address);
RM9K_WRITE(data_reg, val);
return PCIBIOS_SUCCESSFUL;
}
static int titan_ht_config_write_word(struct pci_dev *device,
int offset, u8 val)
{
int dev, bus, func;
uint32_t address_reg, data_reg;
uint32_t address;
bus = device->bus->number;
dev = PCI_SLOT(device->devfn);
func = PCI_FUNC(device->devfn);
/* XXX Need to change the Bus # */
if (bus > 2)
address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
0x80000000 | 0x1;
else
address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
address_reg = RM9000x2_OCD_HTCFGA;
data_reg = RM9000x2_OCD_HTCFGD;
if ((offset & 0x3) == 0)
offset = 0x2;
else
offset = 0x0;
RM9K_WRITE(address_reg, address);
RM9K_WRITE_16(data_reg + offset, val);
return PCIBIOS_SUCCESSFUL;
}
static int titan_ht_config_write_byte(struct pci_dev *device,
int offset, u8 val)
{
int dev, bus, func;
uint32_t address_reg, data_reg;
uint32_t address;
int offset1;
bus = device->bus->number;
dev = PCI_SLOT(device->devfn);
func = PCI_FUNC(device->devfn);
/* XXX Need to change the Bus # */
if (bus > 2)
address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
0x80000000 | 0x1;
else
address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
address_reg = RM9000x2_OCD_HTCFGA;
data_reg = RM9000x2_OCD_HTCFGD;
RM9K_WRITE(address_reg, address);
if ((offset & 0x3) == 0) {
offset1 = 0x3;
}
if ((offset & 0x3) == 1) {
offset1 = 0x2;
}
if ((offset & 0x3) == 2) {
offset1 = 0x1;
}
if ((offset & 0x3) == 3) {
offset1 = 0x0;
}
RM9K_WRITE_8(data_reg + offset1, val);
return PCIBIOS_SUCCESSFUL;
}
static void titan_pcibios_set_master(struct pci_dev *dev)
{
u16 cmd;
int bus = dev->bus->number;
if (check_titan_htlink())
titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_MASTER;
if (check_titan_htlink())
titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
}
int pcibios_enable_resources(struct pci_dev *dev)
{
u16 cmd, old_cmd;
u8 tmp1;
int idx;
struct resource *r;
int bus = dev->bus->number;
if (check_titan_htlink())
titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
for (idx = 0; idx < 6; idx++) {
r = &dev->resource[idx];
if (!r->start && r->end) {
printk(KERN_ERR
"PCI: Device %s not available because of "
"resource collisions\n", pci_name(dev));
return -EINVAL;
}
if (r->flags & IORESOURCE_IO)
cmd |= PCI_COMMAND_IO;
if (r->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
if (cmd != old_cmd) {
if (check_titan_htlink())
titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
}
if (check_titan_htlink())
titan_ht_config_read_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1);
if (tmp1 != 8) {
printk(KERN_WARNING "PCI setting cache line size to 8 from "
"%d\n", tmp1);
}
if (check_titan_htlink())
titan_ht_config_write_byte(dev, PCI_CACHE_LINE_SIZE, 8);
if (check_titan_htlink())
titan_ht_config_read_byte(dev, PCI_LATENCY_TIMER, &tmp1);
if (tmp1 < 32 || tmp1 == 0xff) {
printk(KERN_WARNING "PCI setting latency timer to 32 from %d\n",
tmp1);
}
if (check_titan_htlink())
titan_ht_config_write_byte(dev, PCI_LATENCY_TIMER, 32);
return 0;
}
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
return pcibios_enable_resources(dev);
}
void pcibios_align_resource(void *data, struct resource *res,
resource_size_t size, resource_size_t align)
{
struct pci_dev *dev = data;
if (res->flags & IORESOURCE_IO) {
resource_size_t start = res->start;
/* We need to avoid collisions with `mirrored' VGA ports
and other strange ISA hardware, so we always want the
addresses kilobyte aligned. */
if (size > 0x100) {
printk(KERN_ERR "PCI: I/O Region %s/%d too large"
" (%ld bytes)\n", pci_name(dev),
dev->resource - res, size);
}
start = (start + 1024 - 1) & ~(1024 - 1);
res->start = start;
}
}
struct pci_ops titan_pci_ops = {
titan_ht_config_read_byte,
titan_ht_config_read_word,
titan_ht_config_read_dword,
titan_ht_config_write_byte,
titan_ht_config_write_word,
titan_ht_config_write_dword
};
void __init pcibios_fixup_bus(struct pci_bus *c)
{
titan_ht_pcibios_fixup_bus(c);
}
void __init pcibios_init(void)
{
/* Reset PCI I/O and PCI MEM values */
/* XXX Need to add the proper values here */
ioport_resource.start = 0xe0000000;
ioport_resource.end = 0xe0000000 + 0x20000000 - 1;
iomem_resource.start = 0xc0000000;
iomem_resource.end = 0xc0000000 + 0x20000000 - 1;
/* XXX Need to add bus values */
pci_scan_bus(2, &titan_pci_ops, NULL);
pci_scan_bus(3, &titan_pci_ops, NULL);
}
/*
* for parsing "pci=" kernel boot arguments.
*/
char *pcibios_setup(char *str)
{
printk(KERN_INFO "rr: pcibios_setup\n");
/* Nothing to do for now. */
return str;
}
unsigned __init int pcibios_assign_all_busses(void)
{
/* We want to use the PCI bus detection done by PMON */
return 0;
}
#endif /* CONFIG_HYPERTRANSPORT */

View File

@@ -0,0 +1,158 @@
/*
* Copyright (C) 2003 PMC-Sierra Inc.
* Author: Manish Lachwani (lachwani@pmc-sierra.com)
*
* Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Second level Interrupt handlers for the PMC-Sierra Titan/Yosemite board
*/
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/timex.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/bitops.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
#include <asm/system.h>
#include <asm/titan_dep.h>
/* Hypertransport specific */
#define IRQ_ACK_BITS 0x00000000 /* Ack bits */
#define HYPERTRANSPORT_INTA 0x78 /* INTA# */
#define HYPERTRANSPORT_INTB 0x79 /* INTB# */
#define HYPERTRANSPORT_INTC 0x7a /* INTC# */
#define HYPERTRANSPORT_INTD 0x7b /* INTD# */
extern void titan_mailbox_irq(void);
#ifdef CONFIG_HYPERTRANSPORT
/*
* Handle hypertransport & SMP interrupts. The interrupt lines are scarce.
* For interprocessor interrupts, the best thing to do is to use the INTMSG
* register. We use the same external interrupt line, i.e. INTB3 and monitor
* another status bit
*/
static void ll_ht_smp_irq_handler(int irq)
{
u32 status = OCD_READ(RM9000x2_OCD_INTP0STATUS4);
/* Ack all the bits that correspond to the interrupt sources */
if (status != 0)
OCD_WRITE(RM9000x2_OCD_INTP0STATUS4, IRQ_ACK_BITS);
status = OCD_READ(RM9000x2_OCD_INTP1STATUS4);
if (status != 0)
OCD_WRITE(RM9000x2_OCD_INTP1STATUS4, IRQ_ACK_BITS);
#ifdef CONFIG_HT_LEVEL_TRIGGER
/*
* Level Trigger Mode only. Send the HT EOI message back to the source.
*/
switch (status) {
case 0x1000000:
OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTA);
break;
case 0x2000000:
OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTB);
break;
case 0x4000000:
OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTC);
break;
case 0x8000000:
OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTD);
break;
case 0x0000001:
/* PLX */
OCD_WRITE(RM9000x2_OCD_HTEOI, 0x20);
OCD_WRITE(IRQ_CLEAR_REG, IRQ_ACK_BITS);
break;
case 0xf000000:
OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTA);
OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTB);
OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTC);
OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTD);
break;
}
#endif /* CONFIG_HT_LEVEL_TRIGGER */
do_IRQ(irq);
}
#endif
asmlinkage void plat_irq_dispatch(void)
{
unsigned int cause = read_c0_cause();
unsigned int status = read_c0_status();
unsigned int pending = cause & status;
if (pending & STATUSF_IP7) {
do_IRQ(7);
} else if (pending & STATUSF_IP2) {
#ifdef CONFIG_HYPERTRANSPORT
ll_ht_smp_irq_handler(2);
#else
do_IRQ(2);
#endif
} else if (pending & STATUSF_IP3) {
do_IRQ(3);
} else if (pending & STATUSF_IP4) {
do_IRQ(4);
} else if (pending & STATUSF_IP5) {
#ifdef CONFIG_SMP
titan_mailbox_irq();
#else
do_IRQ(5);
#endif
} else if (pending & STATUSF_IP6) {
do_IRQ(4);
}
}
/*
* Initialize the next level interrupt handler
*/
void __init arch_init_irq(void)
{
clear_c0_status(ST0_IM);
mips_cpu_irq_init();
rm7k_cpu_irq_init();
rm9k_cpu_irq_init();
#ifdef CONFIG_GDB_CONSOLE
register_gdb_console();
#endif
}

View File

@@ -0,0 +1,143 @@
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* Copyright (C) 2003, 2004 PMC-Sierra Inc.
* Author: Manish Lachwani (lachwani@pmc-sierra.com)
* Copyright (C) 2004 Ralf Baechle
*/
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/smp.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/reboot.h>
#include <asm/smp-ops.h>
#include <asm/system.h>
#include <asm/bootinfo.h>
#include <asm/pmon.h>
#ifdef CONFIG_SMP
extern void prom_grab_secondary(void);
#else
#define prom_grab_secondary() do { } while (0)
#endif
#include "setup.h"
struct callvectors *debug_vectors;
extern unsigned long yosemite_base;
extern unsigned long cpu_clock_freq;
const char *get_system_type(void)
{
return "PMC-Sierra Yosemite";
}
static void prom_cpu0_exit(void *arg)
{
void *nvram = (void *) YOSEMITE_RTC_BASE;
/* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
writeb(0x84, nvram + 0xff7);
/* wait for the watchdog to go off */
mdelay(100 + (1000 / 16));
/* if the watchdog fails for some reason, let people know */
printk(KERN_NOTICE "Watchdog reset failed\n");
}
/*
* Reset the NVRAM over the local bus
*/
static void prom_exit(void)
{
#ifdef CONFIG_SMP
if (smp_processor_id())
/* CPU 1 */
smp_call_function(prom_cpu0_exit, NULL, 1);
#endif
prom_cpu0_exit(NULL);
}
/*
* Halt the system
*/
static void prom_halt(void)
{
printk(KERN_NOTICE "\n** You can safely turn off the power\n");
while (1)
__asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0");
}
extern struct plat_smp_ops yos_smp_ops;
/*
* Init routine which accepts the variables from PMON
*/
void __init prom_init(void)
{
int argc = fw_arg0;
char **arg = (char **) fw_arg1;
char **env = (char **) fw_arg2;
struct callvectors *cv = (struct callvectors *) fw_arg3;
int i = 0;
/* Callbacks for halt, restart */
_machine_restart = (void (*)(char *)) prom_exit;
_machine_halt = prom_halt;
pm_power_off = prom_halt;
debug_vectors = cv;
arcs_cmdline[0] = '\0';
/* Get the boot parameters */
for (i = 1; i < argc; i++) {
if (strlen(arcs_cmdline) + strlen(arg[i] + 1) >=
sizeof(arcs_cmdline))
break;
strcat(arcs_cmdline, arg[i]);
strcat(arcs_cmdline, " ");
}
#ifdef CONFIG_SERIAL_8250_CONSOLE
if ((strstr(arcs_cmdline, "console=ttyS")) == NULL)
strcat(arcs_cmdline, "console=ttyS0,115200");
#endif
while (*env) {
if (strncmp("ocd_base", *env, strlen("ocd_base")) == 0)
yosemite_base =
simple_strtol(*env + strlen("ocd_base="), NULL,
16);
if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0)
cpu_clock_freq =
simple_strtol(*env + strlen("cpuclock="), NULL,
10);
env++;
}
prom_grab_secondary();
register_smp_ops(&yos_smp_ops);
}
void __init prom_free_prom_memory(void)
{
}
void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
{
}

View File

@@ -0,0 +1,109 @@
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2001, 2002, 2004 Ralf Baechle
*/
#include <linux/init.h>
#include <linux/console.h>
#include <linux/kdev_t.h>
#include <linux/major.h>
#include <linux/termios.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <asm/serial.h>
#include <asm/io.h>
/* SUPERIO uart register map */
struct yo_uartregs {
union {
volatile u8 rbr; /* read only, DLAB == 0 */
volatile u8 thr; /* write only, DLAB == 0 */
volatile u8 dll; /* DLAB == 1 */
} u1;
union {
volatile u8 ier; /* DLAB == 0 */
volatile u8 dlm; /* DLAB == 1 */
} u2;
union {
volatile u8 iir; /* read only */
volatile u8 fcr; /* write only */
} u3;
volatile u8 iu_lcr;
volatile u8 iu_mcr;
volatile u8 iu_lsr;
volatile u8 iu_msr;
volatile u8 iu_scr;
} yo_uregs_t;
#define iu_rbr u1.rbr
#define iu_thr u1.thr
#define iu_dll u1.dll
#define iu_ier u2.ier
#define iu_dlm u2.dlm
#define iu_iir u3.iir
#define iu_fcr u3.fcr
#define ssnop() __asm__ __volatile__("sll $0, $0, 1\n");
#define ssnop_4() do { ssnop(); ssnop(); ssnop(); ssnop(); } while (0)
#define IO_BASE_64 0x9000000000000000ULL
static unsigned char readb_outer_space(unsigned long long phys)
{
unsigned long long vaddr = IO_BASE_64 | phys;
unsigned char res;
unsigned int sr;
sr = read_c0_status();
write_c0_status((sr | ST0_KX) & ~ ST0_IE);
ssnop_4();
__asm__ __volatile__ (
" .set mips3 \n"
" ld %0, %1 \n"
" lbu %0, (%0) \n"
" .set mips0 \n"
: "=r" (res)
: "m" (vaddr));
write_c0_status(sr);
ssnop_4();
return res;
}
static void writeb_outer_space(unsigned long long phys, unsigned char c)
{
unsigned long long vaddr = IO_BASE_64 | phys;
unsigned long tmp;
unsigned int sr;
sr = read_c0_status();
write_c0_status((sr | ST0_KX) & ~ ST0_IE);
ssnop_4();
__asm__ __volatile__ (
" .set mips3 \n"
" ld %0, %1 \n"
" sb %2, (%0) \n"
" .set mips0 \n"
: "=&r" (tmp)
: "m" (vaddr), "r" (c));
write_c0_status(sr);
ssnop_4();
}
void prom_putchar(char c)
{
unsigned long lsr = 0xfd000008ULL + offsetof(struct yo_uartregs, iu_lsr);
unsigned long thr = 0xfd000008ULL + offsetof(struct yo_uartregs, iu_thr);
while ((readb_outer_space(lsr) & 0x20) == 0);
writeb_outer_space(thr, c);
}

View File

@@ -0,0 +1,223 @@
/*
* Copyright (C) 2003 PMC-Sierra Inc.
* Author: Manish Lachwani (lachwani@pmc-sierra.com)
*
* Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/bcd.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/bootmem.h>
#include <linux/swap.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/termios.h>
#include <linux/tty.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
#include <asm/time.h>
#include <asm/bootinfo.h>
#include <asm/page.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/processor.h>
#include <asm/reboot.h>
#include <asm/serial.h>
#include <asm/titan_dep.h>
#include <asm/m48t37.h>
#include "setup.h"
unsigned char titan_ge_mac_addr_base[6] = {
// 0x00, 0x03, 0xcc, 0x1d, 0x22, 0x00
0x00, 0xe0, 0x04, 0x00, 0x00, 0x21
};
unsigned long cpu_clock_freq;
unsigned long yosemite_base;
static struct m48t37_rtc *m48t37_base;
void __init bus_error_init(void)
{
/* Do nothing */
}
void read_persistent_clock(struct timespec *ts)
{
unsigned int year, month, day, hour, min, sec;
unsigned long flags;
spin_lock_irqsave(&rtc_lock, flags);
/* Stop the update to the time */
m48t37_base->control = 0x40;
year = bcd2bin(m48t37_base->year);
year += bcd2bin(m48t37_base->century) * 100;
month = bcd2bin(m48t37_base->month);
day = bcd2bin(m48t37_base->date);
hour = bcd2bin(m48t37_base->hour);
min = bcd2bin(m48t37_base->min);
sec = bcd2bin(m48t37_base->sec);
/* Start the update to the time again */
m48t37_base->control = 0x00;
spin_unlock_irqrestore(&rtc_lock, flags);
ts->tv_sec = mktime(year, month, day, hour, min, sec);
ts->tv_nsec = 0;
}
int rtc_mips_set_time(unsigned long tim)
{
struct rtc_time tm;
unsigned long flags;
/*
* Convert to a more useful format -- note months count from 0
* and years from 1900
*/
rtc_time_to_tm(tim, &tm);
tm.tm_year += 1900;
tm.tm_mon += 1;
spin_lock_irqsave(&rtc_lock, flags);
/* enable writing */
m48t37_base->control = 0x80;
/* year */
m48t37_base->year = bin2bcd(tm.tm_year % 100);
m48t37_base->century = bin2bcd(tm.tm_year / 100);
/* month */
m48t37_base->month = bin2bcd(tm.tm_mon);
/* day */
m48t37_base->date = bin2bcd(tm.tm_mday);
/* hour/min/sec */
m48t37_base->hour = bin2bcd(tm.tm_hour);
m48t37_base->min = bin2bcd(tm.tm_min);
m48t37_base->sec = bin2bcd(tm.tm_sec);
/* day of week -- not really used, but let's keep it up-to-date */
m48t37_base->day = bin2bcd(tm.tm_wday + 1);
/* disable writing */
m48t37_base->control = 0x00;
spin_unlock_irqrestore(&rtc_lock, flags);
return 0;
}
void __init plat_time_init(void)
{
mips_hpt_frequency = cpu_clock_freq / 2;
mips_hpt_frequency = 33000000 * 3 * 5;
}
unsigned long ocd_base;
EXPORT_SYMBOL(ocd_base);
/*
* Common setup before any secondaries are started
*/
#define TITAN_UART_CLK 3686400
#define TITAN_SERIAL_BASE_BAUD (TITAN_UART_CLK / 16)
#define TITAN_SERIAL_IRQ 4
#define TITAN_SERIAL_BASE 0xfd000008UL
static void __init py_map_ocd(void)
{
ocd_base = (unsigned long) ioremap(OCD_BASE, OCD_SIZE);
if (!ocd_base)
panic("Mapping OCD failed - game over. Your score is 0.");
/* Kludge for PMON bug ... */
OCD_WRITE(0x0710, 0x0ffff029);
}
static void __init py_uart_setup(void)
{
#ifdef CONFIG_SERIAL_8250
struct uart_port up;
/*
* Register to interrupt zero because we share the interrupt with
* the serial driver which we don't properly support yet.
*/
memset(&up, 0, sizeof(up));
up.membase = (unsigned char *) ioremap(TITAN_SERIAL_BASE, 8);
up.irq = TITAN_SERIAL_IRQ;
up.uartclk = TITAN_UART_CLK;
up.regshift = 0;
up.iotype = UPIO_MEM;
up.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
up.line = 0;
if (early_serial_setup(&up))
printk(KERN_ERR "Early serial init of port 0 failed\n");
#endif /* CONFIG_SERIAL_8250 */
}
static void __init py_rtc_setup(void)
{
m48t37_base = ioremap(YOSEMITE_RTC_BASE, YOSEMITE_RTC_SIZE);
if (!m48t37_base)
printk(KERN_ERR "Mapping the RTC failed\n");
}
/* Not only time init but that's what the hook it's called through is named */
static void __init py_late_time_init(void)
{
py_map_ocd();
py_uart_setup();
py_rtc_setup();
}
void __init plat_mem_setup(void)
{
late_time_init = py_late_time_init;
/* Add memory regions */
add_memory_region(0x00000000, 0x10000000, BOOT_MEM_RAM);
#if 0 /* XXX Crash ... */
OCD_WRITE(RM9000x2_OCD_HTSC,
OCD_READ(RM9000x2_OCD_HTSC) | HYPERTRANSPORT_ENABLE);
/* Set the BAR. Shifted mode */
OCD_WRITE(RM9000x2_OCD_HTBAR0, HYPERTRANSPORT_BAR0_ADDR);
OCD_WRITE(RM9000x2_OCD_HTMASK0, HYPERTRANSPORT_SIZE0);
#endif
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2003, 04 PMC-Sierra
* Author: Manish Lachwani (lachwani@pmc-sierra.com)
* Copyright 2004 Ralf Baechle <ralf@linux-mips.org>
*
* Board specific definititions for the PMC-Sierra Yosemite
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __SETUP_H__
#define __SETUP_H__
/* M48T37 RTC + NVRAM */
#define YOSEMITE_RTC_BASE 0xfc800000
#define YOSEMITE_RTC_SIZE 0x00800000
#define HYPERTRANSPORT_BAR0_ADDR 0x00000006
#define HYPERTRANSPORT_SIZE0 0x0fffffff
#define HYPERTRANSPORT_BAR0_ATTR 0x00002000
#define HYPERTRANSPORT_ENABLE 0x6
/*
* EEPROM Size
*/
#define TITAN_ATMEL_24C32_SIZE 32768
#define TITAN_ATMEL_24C64_SIZE 65536
#endif /* __SETUP_H__ */

View File

@@ -0,0 +1,181 @@
#include <linux/linkage.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <asm/pmon.h>
#include <asm/titan_dep.h>
#include <asm/time.h>
#define LAUNCHSTACK_SIZE 256
static __cpuinitdata DEFINE_SPINLOCK(launch_lock);
static unsigned long secondary_sp __cpuinitdata;
static unsigned long secondary_gp __cpuinitdata;
static unsigned char launchstack[LAUNCHSTACK_SIZE] __initdata
__attribute__((aligned(2 * sizeof(long))));
static void __init prom_smp_bootstrap(void)
{
local_irq_disable();
while (spin_is_locked(&launch_lock));
__asm__ __volatile__(
" move $sp, %0 \n"
" move $gp, %1 \n"
" j smp_bootstrap \n"
:
: "r" (secondary_sp), "r" (secondary_gp));
}
/*
* PMON is a fragile beast. It'll blow up once the mappings it's littering
* right into the middle of KSEG3 are blown away so we have to grab the slave
* core early and keep it in a waiting loop.
*/
void __init prom_grab_secondary(void)
{
spin_lock(&launch_lock);
pmon_cpustart(1, &prom_smp_bootstrap,
launchstack + LAUNCHSTACK_SIZE, 0);
}
void titan_mailbox_irq(void)
{
int cpu = smp_processor_id();
unsigned long status;
switch (cpu) {
case 0:
status = OCD_READ(RM9000x2_OCD_INTP0STATUS3);
OCD_WRITE(RM9000x2_OCD_INTP0CLEAR3, status);
if (status & 0x2)
smp_call_function_interrupt();
break;
case 1:
status = OCD_READ(RM9000x2_OCD_INTP1STATUS3);
OCD_WRITE(RM9000x2_OCD_INTP1CLEAR3, status);
if (status & 0x2)
smp_call_function_interrupt();
break;
}
}
/*
* Send inter-processor interrupt
*/
static void yos_send_ipi_single(int cpu, unsigned int action)
{
/*
* Generate an INTMSG so that it can be sent over to the
* destination CPU. The INTMSG will put the STATUS bits
* based on the action desired. An alternative strategy
* is to write to the Interrupt Set register, read the
* Interrupt Status register and clear the Interrupt
* Clear register. The latter is preffered.
*/
switch (action) {
case SMP_RESCHEDULE_YOURSELF:
if (cpu == 1)
OCD_WRITE(RM9000x2_OCD_INTP1SET3, 4);
else
OCD_WRITE(RM9000x2_OCD_INTP0SET3, 4);
break;
case SMP_CALL_FUNCTION:
if (cpu == 1)
OCD_WRITE(RM9000x2_OCD_INTP1SET3, 2);
else
OCD_WRITE(RM9000x2_OCD_INTP0SET3, 2);
break;
}
}
static void yos_send_ipi_mask(const struct cpumask *mask, unsigned int action)
{
unsigned int i;
for_each_cpu(i, mask)
yos_send_ipi_single(i, action);
}
/*
* After we've done initial boot, this function is called to allow the
* board code to clean up state, if needed
*/
static void __cpuinit yos_init_secondary(void)
{
set_c0_status(ST0_CO | ST0_IE | ST0_IM);
}
static void __cpuinit yos_smp_finish(void)
{
}
/* Hook for after all CPUs are online */
static void yos_cpus_done(void)
{
}
/*
* Firmware CPU startup hook
* Complicated by PMON's weird interface which tries to minimic the UNIX fork.
* It launches the next * available CPU and copies some information on the
* stack so the first thing we do is throw away that stuff and load useful
* values into the registers ...
*/
static void __cpuinit yos_boot_secondary(int cpu, struct task_struct *idle)
{
unsigned long gp = (unsigned long) task_thread_info(idle);
unsigned long sp = __KSTK_TOS(idle);
secondary_sp = sp;
secondary_gp = gp;
spin_unlock(&launch_lock);
}
/*
* Detect available CPUs, populate cpu_possible_map before smp_init
*
* We don't want to start the secondary CPU yet nor do we have a nice probing
* feature in PMON so we just assume presence of the secondary core.
*/
static void __init yos_smp_setup(void)
{
int i;
cpus_clear(cpu_possible_map);
for (i = 0; i < 2; i++) {
cpu_set(i, cpu_possible_map);
__cpu_number_map[i] = i;
__cpu_logical_map[i] = i;
}
}
static void __init yos_prepare_cpus(unsigned int max_cpus)
{
/*
* Be paranoid. Enable the IPI only if we're really about to go SMP.
*/
if (cpus_weight(cpu_possible_map))
set_c0_status(STATUSF_IP5);
}
struct plat_smp_ops yos_smp_ops = {
.send_ipi_single = yos_send_ipi_single,
.send_ipi_mask = yos_send_ipi_mask,
.init_secondary = yos_init_secondary,
.smp_finish = yos_smp_finish,
.cpus_done = yos_cpus_done,
.boot_secondary = yos_boot_secondary,
.smp_setup = yos_smp_setup,
.prepare_cpus = yos_prepare_cpus,
};