-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> create mode 100644 arch/mips/pci/pci-tx4939.c create mode 100644 arch/mips/txx9/generic/irq_tx4939.c create mode 100644 arch/mips/txx9/generic/setup_tx4939.c create mode 100644 include/asm-mips/txx9/tx4939.h
- Loading branch information
Atsushi Nemoto
authored and
Ralf Baechle
committed
Oct 11, 2008
1 parent
ae027ea
commit 0dcdbe6
Showing
7 changed files
with
1,337 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
* linux/arch/mips/pci/pci-tx4939.c | ||
* | ||
* Based on linux/arch/mips/txx9/rbtx4939/setup.c, | ||
* and RBTX49xx patch from CELF patch archive. | ||
* | ||
* Copyright 2001, 2003-2005 MontaVista Software Inc. | ||
* Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) | ||
* (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 | ||
* | ||
* 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. | ||
*/ | ||
#include <linux/init.h> | ||
#include <linux/pci.h> | ||
#include <linux/kernel.h> | ||
#include <linux/interrupt.h> | ||
#include <asm/txx9/generic.h> | ||
#include <asm/txx9/tx4939.h> | ||
|
||
int __init tx4939_report_pciclk(void) | ||
{ | ||
int pciclk = 0; | ||
|
||
pr_info("PCIC --%s PCICLK:", | ||
(__raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_PCI66) ? | ||
" PCI66" : ""); | ||
if (__raw_readq(&tx4939_ccfgptr->pcfg) & TX4939_PCFG_PCICLKEN_ALL) { | ||
pciclk = txx9_master_clock * 20 / 6; | ||
if (!(__raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_PCI66)) | ||
pciclk /= 2; | ||
printk(KERN_CONT "Internal(%u.%uMHz)", | ||
(pciclk + 50000) / 1000000, | ||
((pciclk + 50000) / 100000) % 10); | ||
} else { | ||
printk(KERN_CONT "External"); | ||
pciclk = -1; | ||
} | ||
printk(KERN_CONT "\n"); | ||
return pciclk; | ||
} | ||
|
||
void __init tx4939_report_pci1clk(void) | ||
{ | ||
unsigned int pciclk = txx9_master_clock * 20 / 6; | ||
|
||
pr_info("PCIC1 -- PCICLK:%u.%uMHz\n", | ||
(pciclk + 50000) / 1000000, | ||
((pciclk + 50000) / 100000) % 10); | ||
} | ||
|
||
int __init tx4939_pcic1_map_irq(const struct pci_dev *dev, u8 slot) | ||
{ | ||
if (get_tx4927_pcicptr(dev->bus->sysdata) == tx4939_pcic1ptr) { | ||
switch (slot) { | ||
case TX4927_PCIC_IDSEL_AD_TO_SLOT(31): | ||
if (__raw_readq(&tx4939_ccfgptr->pcfg) & | ||
TX4939_PCFG_ET0MODE) | ||
return TXX9_IRQ_BASE + TX4939_IR_ETH(0); | ||
break; | ||
case TX4927_PCIC_IDSEL_AD_TO_SLOT(30): | ||
if (__raw_readq(&tx4939_ccfgptr->pcfg) & | ||
TX4939_PCFG_ET1MODE) | ||
return TXX9_IRQ_BASE + TX4939_IR_ETH(1); | ||
break; | ||
} | ||
return 0; | ||
} | ||
return -1; | ||
} | ||
|
||
int __init tx4939_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||
{ | ||
int irq = tx4939_pcic1_map_irq(dev, slot); | ||
|
||
if (irq >= 0) | ||
return irq; | ||
irq = pin; | ||
/* IRQ rotation */ | ||
irq--; /* 0-3 */ | ||
irq = (irq + 33 - slot) % 4; | ||
irq++; /* 1-4 */ | ||
|
||
switch (irq) { | ||
case 1: | ||
irq = TXX9_IRQ_BASE + TX4939_IR_INTA; | ||
break; | ||
case 2: | ||
irq = TXX9_IRQ_BASE + TX4939_IR_INTB; | ||
break; | ||
case 3: | ||
irq = TXX9_IRQ_BASE + TX4939_IR_INTC; | ||
break; | ||
case 4: | ||
irq = TXX9_IRQ_BASE + TX4939_IR_INTD; | ||
break; | ||
} | ||
return irq; | ||
} | ||
|
||
void __init tx4939_setup_pcierr_irq(void) | ||
{ | ||
if (request_irq(TXX9_IRQ_BASE + TX4939_IR_PCIERR, | ||
tx4927_pcierr_interrupt, | ||
IRQF_DISABLED, "PCI error", | ||
(void *)TX4939_PCIC_REG)) | ||
pr_warning("Failed to request irq for PCIERR\n"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
/* | ||
* TX4939 irq routines | ||
* Based on linux/arch/mips/kernel/irq_txx9.c, | ||
* and RBTX49xx patch from CELF patch archive. | ||
* | ||
* Copyright 2001, 2003-2005 MontaVista Software Inc. | ||
* Author: MontaVista Software, Inc. | ||
* ahennessy@mvista.com | ||
* source@mvista.com | ||
* Copyright (C) 2000-2001,2005-2007 Toshiba Corporation | ||
* | ||
* 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. | ||
*/ | ||
/* | ||
* TX4939 defines 64 IRQs. | ||
* Similer to irq_txx9.c but different register layouts. | ||
*/ | ||
#include <linux/init.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/types.h> | ||
#include <asm/irq_cpu.h> | ||
#include <asm/txx9irq.h> | ||
#include <asm/txx9/tx4939.h> | ||
|
||
/* IRCER : Int. Control Enable */ | ||
#define TXx9_IRCER_ICE 0x00000001 | ||
|
||
/* IRCR : Int. Control */ | ||
#define TXx9_IRCR_LOW 0x00000000 | ||
#define TXx9_IRCR_HIGH 0x00000001 | ||
#define TXx9_IRCR_DOWN 0x00000002 | ||
#define TXx9_IRCR_UP 0x00000003 | ||
#define TXx9_IRCR_EDGE(cr) ((cr) & 0x00000002) | ||
|
||
/* IRSCR : Int. Status Control */ | ||
#define TXx9_IRSCR_EIClrE 0x00000100 | ||
#define TXx9_IRSCR_EIClr_MASK 0x0000000f | ||
|
||
/* IRCSR : Int. Current Status */ | ||
#define TXx9_IRCSR_IF 0x00010000 | ||
|
||
#define irc_dlevel 0 | ||
#define irc_elevel 1 | ||
|
||
static struct { | ||
unsigned char level; | ||
unsigned char mode; | ||
} tx4939irq[TX4939_NUM_IR] __read_mostly; | ||
|
||
static void tx4939_irq_unmask(unsigned int irq) | ||
{ | ||
unsigned int irq_nr = irq - TXX9_IRQ_BASE; | ||
u32 __iomem *lvlp; | ||
int ofs; | ||
if (irq_nr < 32) { | ||
irq_nr--; | ||
lvlp = &tx4939_ircptr->lvl[(irq_nr % 16) / 2].r; | ||
} else { | ||
irq_nr -= 32; | ||
lvlp = &tx4939_ircptr->lvl[8 + (irq_nr % 16) / 2].r; | ||
} | ||
ofs = (irq_nr & 16) + (irq_nr & 1) * 8; | ||
__raw_writel((__raw_readl(lvlp) & ~(0xff << ofs)) | ||
| (tx4939irq[irq_nr].level << ofs), | ||
lvlp); | ||
} | ||
|
||
static inline void tx4939_irq_mask(unsigned int irq) | ||
{ | ||
unsigned int irq_nr = irq - TXX9_IRQ_BASE; | ||
u32 __iomem *lvlp; | ||
int ofs; | ||
if (irq_nr < 32) { | ||
irq_nr--; | ||
lvlp = &tx4939_ircptr->lvl[(irq_nr % 16) / 2].r; | ||
} else { | ||
irq_nr -= 32; | ||
lvlp = &tx4939_ircptr->lvl[8 + (irq_nr % 16) / 2].r; | ||
} | ||
ofs = (irq_nr & 16) + (irq_nr & 1) * 8; | ||
__raw_writel((__raw_readl(lvlp) & ~(0xff << ofs)) | ||
| (irc_dlevel << ofs), | ||
lvlp); | ||
mmiowb(); | ||
} | ||
|
||
static void tx4939_irq_mask_ack(unsigned int irq) | ||
{ | ||
unsigned int irq_nr = irq - TXX9_IRQ_BASE; | ||
|
||
tx4939_irq_mask(irq); | ||
if (TXx9_IRCR_EDGE(tx4939irq[irq_nr].mode)) { | ||
irq_nr--; | ||
/* clear edge detection */ | ||
__raw_writel((TXx9_IRSCR_EIClrE | (irq_nr & 0xf)) | ||
<< (irq_nr & 0x10), | ||
&tx4939_ircptr->edc.r); | ||
} | ||
} | ||
|
||
static int tx4939_irq_set_type(unsigned int irq, unsigned int flow_type) | ||
{ | ||
unsigned int irq_nr = irq - TXX9_IRQ_BASE; | ||
u32 cr; | ||
u32 __iomem *crp; | ||
int ofs; | ||
int mode; | ||
|
||
if (flow_type & IRQF_TRIGGER_PROBE) | ||
return 0; | ||
switch (flow_type & IRQF_TRIGGER_MASK) { | ||
case IRQF_TRIGGER_RISING: | ||
mode = TXx9_IRCR_UP; | ||
break; | ||
case IRQF_TRIGGER_FALLING: | ||
mode = TXx9_IRCR_DOWN; | ||
break; | ||
case IRQF_TRIGGER_HIGH: | ||
mode = TXx9_IRCR_HIGH; | ||
break; | ||
case IRQF_TRIGGER_LOW: | ||
mode = TXx9_IRCR_LOW; | ||
break; | ||
default: | ||
return -EINVAL; | ||
} | ||
if (irq_nr < 32) { | ||
irq_nr--; | ||
crp = &tx4939_ircptr->dm[(irq_nr & 8) >> 3].r; | ||
} else { | ||
irq_nr -= 32; | ||
crp = &tx4939_ircptr->dm2[((irq_nr & 8) >> 3)].r; | ||
} | ||
ofs = (((irq_nr & 16) >> 1) | (irq_nr & (8 - 1))) * 2; | ||
cr = __raw_readl(crp); | ||
cr &= ~(0x3 << ofs); | ||
cr |= (mode & 0x3) << ofs; | ||
__raw_writel(cr, crp); | ||
tx4939irq[irq_nr].mode = mode; | ||
return 0; | ||
} | ||
|
||
static struct irq_chip tx4939_irq_chip = { | ||
.name = "TX4939", | ||
.ack = tx4939_irq_mask_ack, | ||
.mask = tx4939_irq_mask, | ||
.mask_ack = tx4939_irq_mask_ack, | ||
.unmask = tx4939_irq_unmask, | ||
.set_type = tx4939_irq_set_type, | ||
}; | ||
|
||
static int tx4939_irq_set_pri(int irc_irq, int new_pri) | ||
{ | ||
int old_pri; | ||
|
||
if ((unsigned int)irc_irq >= TX4939_NUM_IR) | ||
return 0; | ||
old_pri = tx4939irq[irc_irq].level; | ||
tx4939irq[irc_irq].level = new_pri; | ||
return old_pri; | ||
} | ||
|
||
void __init tx4939_irq_init(void) | ||
{ | ||
int i; | ||
|
||
mips_cpu_irq_init(); | ||
/* disable interrupt control */ | ||
__raw_writel(0, &tx4939_ircptr->den.r); | ||
__raw_writel(0, &tx4939_ircptr->maskint.r); | ||
__raw_writel(0, &tx4939_ircptr->maskext.r); | ||
/* irq_base + 0 is not used */ | ||
for (i = 1; i < TX4939_NUM_IR; i++) { | ||
tx4939irq[i].level = 4; /* middle level */ | ||
tx4939irq[i].mode = TXx9_IRCR_LOW; | ||
set_irq_chip_and_handler(TXX9_IRQ_BASE + i, | ||
&tx4939_irq_chip, handle_level_irq); | ||
} | ||
|
||
/* mask all IRC interrupts */ | ||
__raw_writel(0, &tx4939_ircptr->msk.r); | ||
for (i = 0; i < 16; i++) | ||
__raw_writel(0, &tx4939_ircptr->lvl[i].r); | ||
/* setup IRC interrupt mode (Low Active) */ | ||
for (i = 0; i < 2; i++) | ||
__raw_writel(0, &tx4939_ircptr->dm[i].r); | ||
for (i = 0; i < 2; i++) | ||
__raw_writel(0, &tx4939_ircptr->dm2[i].r); | ||
/* enable interrupt control */ | ||
__raw_writel(TXx9_IRCER_ICE, &tx4939_ircptr->den.r); | ||
__raw_writel(irc_elevel, &tx4939_ircptr->msk.r); | ||
|
||
set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4939_IRC_INT, | ||
handle_simple_irq); | ||
|
||
/* raise priority for errors, timers, sio */ | ||
tx4939_irq_set_pri(TX4939_IR_WTOERR, 7); | ||
tx4939_irq_set_pri(TX4939_IR_PCIERR, 7); | ||
tx4939_irq_set_pri(TX4939_IR_PCIPME, 7); | ||
for (i = 0; i < TX4939_NUM_IR_TMR; i++) | ||
tx4939_irq_set_pri(TX4939_IR_TMR(i), 6); | ||
for (i = 0; i < TX4939_NUM_IR_SIO; i++) | ||
tx4939_irq_set_pri(TX4939_IR_SIO(i), 5); | ||
} | ||
|
||
int tx4939_irq(void) | ||
{ | ||
u32 csr = __raw_readl(&tx4939_ircptr->cs.r); | ||
|
||
if (likely(!(csr & TXx9_IRCSR_IF))) | ||
return TXX9_IRQ_BASE + (csr & (TX4939_NUM_IR - 1)); | ||
return -1; | ||
} |
Oops, something went wrong.