Commit bdf21b18 authored by Pete Popov's avatar Pete Popov Committed by Ralf Baechle

Philips PNX8550 support: MIPS32-like core with 2 Trimedias on it.

Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent e01402b1
......@@ -489,6 +489,16 @@ config HYPERTRANSPORT
bool "Hypertransport Support for PMC-Sierra Yosemite"
depends on PMC_YOSEMITE
config PNX8550_V2PCI
bool "Support for Philips PNX8550 based Viper2-PCI board"
select PNX8550
select SYS_SUPPORTS_LITTLE_ENDIAN
config PNX8550_JBS
bool "Support for Philips PNX8550 based JBS board"
select PNX8550
select SYS_SUPPORTS_LITTLE_ENDIAN
config DDB5074
bool "Support for NEC DDB Vrc-5074 (EXPERIMENTAL)"
depends on EXPERIMENTAL
......@@ -827,6 +837,7 @@ config TOSHIBA_FPCIB0
source "arch/mips/sgi-ip27/Kconfig"
source "arch/mips/sibyte/Kconfig"
source "arch/mips/philips/pnx8550/common/Kconfig"
config RWSEM_GENERIC_SPINLOCK
bool
......@@ -954,6 +965,16 @@ config ITE_BOARD_GEN
depends on MIPS_IVR || MIPS_ITE8172
default y
config PNX8550
bool
select SOC_PNX8550
config SOC_PNX8550
bool
select SYS_SUPPORTS_32BIT_KERNEL
select DMA_NONCOHERENT
select HW_HAS_PCI
config SWAP_IO_SPACE
bool
......
......@@ -228,6 +228,7 @@ cflags-$(CONFIG_CPU_RM9000) += \
$(call set_gccflags,rm9000,mips4,r5000,mips4,mips2) \
-Wa,--trap
cflags-$(CONFIG_CPU_SB1) += \
$(call set_gccflags,sb1,mips64,r5000,mips4,mips2) \
-Wa,--trap
......@@ -560,6 +561,19 @@ load-$(CONFIG_CASIO_E55) += 0xffffffff80004000
#
load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000
#
# Common Philips PNX8550
#
core-$(CONFIG_SOC_PNX8550) += arch/mips/philips/pnx8550/common/
cflags-$(CONFIG_SOC_PNX8550) += -Iinclude/asm-mips/mach-pnx8550
#
# Philips PNX8550 JBS board
#
libs-$(CONFIG_PNX8550_JBS) += arch/mips/philips/pnx8550/jbs/
#cflags-$(CONFIG_PNX8550_JBS) += -Iinclude/asm-mips/mach-pnx8550
load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000
#
# SGI IP22 (Indy/Indigo2)
#
......
......@@ -121,6 +121,7 @@ static inline void check_wait(void)
case CPU_24K:
case CPU_25KF:
case CPU_34K:
case CPU_PR4450:
cpu_wait = r4k_wait;
printk(" available.\n");
break;
......@@ -624,6 +625,21 @@ static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c)
}
}
static inline void cpu_probe_philips(struct cpuinfo_mips *c)
{
decode_configs(c);
switch (c->processor_id & 0xff00) {
case PRID_IMP_PR4450:
c->cputype = CPU_PR4450;
c->isa_level = MIPS_CPU_ISA_M32;
break;
default:
panic("Unknown Philips Core!"); /* REVISIT: die? */
break;
}
}
__init void cpu_probe(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
......@@ -649,6 +665,9 @@ __init void cpu_probe(void)
case PRID_COMP_SANDCRAFT:
cpu_probe_sandcraft(c);
break;
case PRID_COMP_PHILIPS:
cpu_probe_philips(c);
break;
default:
c->cputype = CPU_UNKNOWN;
}
......
......@@ -80,7 +80,8 @@ static const char *cpu_name[] = {
[CPU_VR4133] = "NEC VR4133",
[CPU_VR4181] = "NEC VR4181",
[CPU_VR4181A] = "NEC VR4181A",
[CPU_SR71000] = "Sandcraft SR71000"
[CPU_SR71000] = "Sandcraft SR71000",
[CPU_PR4450] = "Philips PR4450",
};
......
......@@ -11,6 +11,7 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
......@@ -112,8 +113,10 @@ static void c0_timer_ack(void)
{
unsigned int count;
#ifndef CONFIG_SOC_PNX8550 /* pnx8550 resets to zero */
/* Ack this timer interrupt and set the next one. */
expirelo += cycles_per_jiffy;
#endif
write_c0_compare(expirelo);
/* Check to see if we have missed any timer interrupts. */
......
......@@ -844,6 +844,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
case CPU_AU1500:
case CPU_AU1550:
case CPU_AU1200:
case CPU_PR4450:
i_nop(p);
tlbw(p);
break;
......
......@@ -34,6 +34,7 @@ obj-$(CONFIG_MIPS_ITE8172) += fixup-ite8172g.o
obj-$(CONFIG_MIPS_IVR) += fixup-ivr.o
obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o
obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o
obj-$(CONFIG_SOC_PNX8550) += fixup-pnx8550.o ops-pnx8550.o
obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o
obj-$(CONFIG_MOMENCO_JAGUAR_ATX)+= fixup-jaguar.o
obj-$(CONFIG_MOMENCO_OCELOT) += fixup-ocelot.o pci-ocelot.o
......
/*
* Philips PNX8550 pci fixups.
*
* Copyright 2005 Embedded Alley Solutions, Inc
* source@embeddealley.com
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* 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.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/mach-pnx8550/pci.h>
#include <asm/mach-pnx8550/int.h>
#undef DEBUG
#ifdef DEBUG
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
extern char irq_tab_jbs[][5];
void __init pcibios_fixup_resources(struct pci_dev *dev)
{
/* no need to fixup IO resources */
}
void __init pcibios_fixup(void)
{
/* nothing to do here */
}
int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
return irq_tab_jbs[slot][pin];
}
/* Do platform specific device initialization at pci_enable_device() time */
int pcibios_plat_dev_init(struct pci_dev *dev)
{
return 0;
}
/*
*
* BRIEF MODULE DESCRIPTION
*
* 2.6 port, Embedded Alley Solutions, Inc
*
* Based on:
* Author: source@mvista.com
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* 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.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <asm/mach-pnx8550/pci.h>
#include <asm/mach-pnx8550/glb.h>
#include <asm/debug.h>
static inline void clear_status(void)
{
unsigned long pci_stat;
pci_stat = inl(PCI_BASE | PCI_GPPM_STATUS);
outl(pci_stat, PCI_BASE | PCI_GPPM_ICLR);
}
static inline unsigned int
calc_cfg_addr(struct pci_bus *bus, unsigned int devfn, int where)
{
unsigned int addr;
addr = ((bus->number > 0) ? (((bus->number & 0xff) << PCI_CFG_BUS_SHIFT) | 1) : 0);
addr |= ((devfn & 0xff) << PCI_CFG_FUNC_SHIFT) | (where & 0xfc);
return addr;
}
static int
config_access(unsigned int pci_cmd, struct pci_bus *bus, unsigned int devfn, int where, unsigned int pci_mode, unsigned int *val)
{
unsigned int flags;
unsigned long loops = 0;
unsigned long ioaddr = calc_cfg_addr(bus, devfn, where);
local_irq_save(flags);
/*Clear pending interrupt status */
if (inl(PCI_BASE | PCI_GPPM_STATUS)) {
clear_status();
while (!(inl(PCI_BASE | PCI_GPPM_STATUS) == 0)) ;
}
outl(ioaddr, PCI_BASE | PCI_GPPM_ADDR);
if ((pci_cmd == PCI_CMD_IOW) || (pci_cmd == PCI_CMD_CONFIG_WRITE))
outl(*val, PCI_BASE | PCI_GPPM_WDAT);
outl(INIT_PCI_CYCLE | pci_cmd | (pci_mode & PCI_BYTE_ENABLE_MASK),
PCI_BASE | PCI_GPPM_CTRL);
loops =
((loops_per_jiffy *
PCI_IO_JIFFIES_TIMEOUT) >> (PCI_IO_JIFFIES_SHIFT));
while (1) {
if (inl(PCI_BASE | PCI_GPPM_STATUS) & GPPM_DONE) {
if ((pci_cmd == PCI_CMD_IOR) ||
(pci_cmd == PCI_CMD_CONFIG_READ))
*val = inl(PCI_BASE | PCI_GPPM_RDAT);
clear_status();
local_irq_restore(flags);
return PCIBIOS_SUCCESSFUL;
} else if (inl(PCI_BASE | PCI_GPPM_STATUS) & GPPM_R_MABORT) {
break;
}
loops--;
if (loops == 0) {
printk("%s : Arbiter Locked.\n", __FUNCTION__);
}
}
clear_status();
if ((pci_cmd == PCI_CMD_IOR) || (pci_cmd == PCI_CMD_IOW)) {
printk("%s timeout (GPPM_CTRL=%X) ioaddr %lX pci_cmd %X\n",
__FUNCTION__, inl(PCI_BASE | PCI_GPPM_CTRL), ioaddr,
pci_cmd);
}
if ((pci_cmd == PCI_CMD_IOR) || (pci_cmd == PCI_CMD_CONFIG_READ))
*val = 0xffffffff;
local_irq_restore(flags);
return PCIBIOS_DEVICE_NOT_FOUND;
}
/*
* We can't address 8 and 16 bit words directly. Instead we have to
* read/write a 32bit word and mask/modify the data we actually want.
*/
static int
read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 * val)
{
unsigned int data = 0;
int err;
if (bus == 0)
return -1;
err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(1 << (where & 3)), &data);
switch (where & 0x03) {
case 0:
*val = (unsigned char)(data & 0x000000ff);
break;
case 1:
*val = (unsigned char)((data & 0x0000ff00) >> 8);
break;
case 2:
*val = (unsigned char)((data & 0x00ff0000) >> 16);
break;
case 3:
*val = (unsigned char)((data & 0xff000000) >> 24);
break;
}
return err;
}
static int
read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 * val)
{
unsigned int data = 0;
int err;
if (bus == 0)
return -1;
if (where & 0x01)
return PCIBIOS_BAD_REGISTER_NUMBER;
err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(3 << (where & 3)), &data);
switch (where & 0x02) {
case 0:
*val = (unsigned short)(data & 0x0000ffff);
break;
case 2:
*val = (unsigned short)((data & 0xffff0000) >> 16);
break;
}
return err;
}
static int
read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 * val)
{
int err;
if (bus == 0)
return -1;
if (where & 0x03)
return PCIBIOS_BAD_REGISTER_NUMBER;
err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, 0, val);
return err;
}
static int
write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val)
{
unsigned int data = (unsigned int)val;
int err;
if (bus == 0)
return -1;
switch (where & 0x03) {
case 1:
data = (data << 8);
break;
case 2:
data = (data << 16);
break;
case 3:
data = (data << 24);
break;
default:
break;
}
err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(1 << (where & 3)), &data);
return err;
}
static int
write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val)
{
unsigned int data = (unsigned int)val;
int err;
if (bus == 0)
return -1;
if (where & 0x01)
return PCIBIOS_BAD_REGISTER_NUMBER;
switch (where & 0x02) {
case 2:
data = (data << 16);
break;
default:
break;
}
err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, ~(3 << (where & 3)), &data);
return err;
}
static int
write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val)
{
int err;
if (bus == 0)
return -1;
if (where & 0x03)
return PCIBIOS_BAD_REGISTER_NUMBER;
err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, 0, &val);
return err;
}
static int config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val)
{
switch (size) {
case 1: {
u8 _val;
int rc = read_config_byte(bus, devfn, where, &_val);
*val = _val;
return rc;
}
case 2: {
u16 _val;
int rc = read_config_word(bus, devfn, where, &_val);
*val = _val;
return rc;
}
default:
return read_config_dword(bus, devfn, where, val);
}
}
static int config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
{
switch (size) {
case 1:
return write_config_byte(bus, devfn, where, (u8) val);
case 2:
return write_config_word(bus, devfn, where, (u16) val);
default:
return write_config_dword(bus, devfn, where, val);
}
}
struct pci_ops pnx8550_pci_ops = {
config_read,
config_write
};
#
# Per Hallsmark, per.hallsmark@mvista.com
#
# ########################################################################
#
# This program is free software; you can distribute it and/or modify it
# under the terms of the GNU General Public License (Version 2) as
# published by the Free Software Foundation.
#
# This program is distributed in the hope it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# 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.,
# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
#
# #######################################################################
#
# Makefile for the PNX8550 specific kernel interface routines
# under Linux.
#
obj-y := setup.o prom.o mipsIRQ.o int.o reset.o time.o proc.o platform.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_KGDB) += gdb_hook.o
/*
* Carsten Langgaard, carstenl@mips.com
* Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
*
* ########################################################################
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* 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.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* ########################################################################
*
* This is the interface to the remote debugger stub.
*
*/
#include <linux/types.h>
#include <linux/serial.h>
#include <linux/serialP.h>
#include <linux/serial_reg.h>
#include <linux/serial_ip3106.h>
#include <asm/serial.h>
#include <asm/io.h>
#include <uart.h>
static struct serial_state rs_table[IP3106_NR_PORTS] = {
};
static struct async_struct kdb_port_info = {0};
void rs_kgdb_hook(int tty_no)
{
struct serial_state *ser = &rs_table[tty_no];
kdb_port_info.state = ser;
kdb_port_info.magic = SERIAL_MAGIC;
kdb_port_info.port = tty_no;
kdb_port_info.flags = ser->flags;
/*
* Clear all interrupts
*/
/* Clear all the transmitter FIFO counters (pointer and status) */
ip3106_lcr(UART_BASE, tty_no) |= IP3106_UART_LCR_TX_RST;
/* Clear all the receiver FIFO counters (pointer and status) */
ip3106_lcr(UART_BASE, tty_no) |= IP3106_UART_LCR_RX_RST;
/* Clear all interrupts */
ip3106_iclr(UART_BASE, tty_no) = IP3106_UART_INT_ALLRX |
IP3106_UART_INT_ALLTX;
/*
* Now, initialize the UART
*/
ip3106_lcr(UART_BASE, tty_no) = IP3106_UART_LCR_8BIT;
ip3106_baud(UART_BASE, tty_no) = 5; // 38400 Baud
}
int putDebugChar(char c)
{
/* Wait until FIFO not full */
while (((ip3106_fifo(UART_BASE, kdb_port_info.port) & IP3106_UART_FIFO_TXFIFO) >> 16) >= 16)
;
/* Send one char */
ip3106_fifo(UART_BASE, kdb_port_info.port) = c;
return 1;
}
char getDebugChar(void)
{
char ch;
/* Wait until there is a char in the FIFO */
while (!((ip3106_fifo(UART_BASE, kdb_port_info.port) &
IP3106_UART_FIFO_RXFIFO) >> 8))