Path: blob/master/arch/blackfin/mach-common/ints-priority.c
10817 views
/*1* Set up the interrupt priorities2*3* Copyright 2004-2009 Analog Devices Inc.4* 2003 Bas Vermeulen <[email protected]>5* 2002 Arcturus Networks Inc. MaTed <[email protected]>6* 2000-2001 Lineo, Inc. D. Jefff Dionne <[email protected]>7* 1999 D. Jeff Dionne <[email protected]>8* 1996 Roman Zippel9*10* Licensed under the GPL-211*/1213#include <linux/module.h>14#include <linux/kernel_stat.h>15#include <linux/seq_file.h>16#include <linux/irq.h>17#include <linux/sched.h>18#ifdef CONFIG_IPIPE19#include <linux/ipipe.h>20#endif21#include <asm/traps.h>22#include <asm/blackfin.h>23#include <asm/gpio.h>24#include <asm/irq_handler.h>25#include <asm/dpmc.h>2627#define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1))2829/*30* NOTES:31* - we have separated the physical Hardware interrupt from the32* levels that the LINUX kernel sees (see the description in irq.h)33* -34*/3536#ifndef CONFIG_SMP37/* Initialize this to an actual value to force it into the .data38* section so that we know it is properly initialized at entry into39* the kernel but before bss is initialized to zero (which is where40* it would live otherwise). The 0x1f magic represents the IRQs we41* cannot actually mask out in hardware.42*/43unsigned long bfin_irq_flags = 0x1f;44EXPORT_SYMBOL(bfin_irq_flags);45#endif4647#ifdef CONFIG_PM48unsigned long bfin_sic_iwr[3]; /* Up to 3 SIC_IWRx registers */49unsigned vr_wakeup;50#endif5152static struct ivgx {53/* irq number for request_irq, available in mach-bf5xx/irq.h */54unsigned int irqno;55/* corresponding bit in the SIC_ISR register */56unsigned int isrflag;57} ivg_table[NR_PERI_INTS];5859static struct ivg_slice {60/* position of first irq in ivg_table for given ivg */61struct ivgx *ifirst;62struct ivgx *istop;63} ivg7_13[IVG13 - IVG7 + 1];646566/*67* Search SIC_IAR and fill tables with the irqvalues68* and their positions in the SIC_ISR register.69*/70static void __init search_IAR(void)71{72unsigned ivg, irq_pos = 0;73for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) {74int irqN;7576ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos];7778for (irqN = 0; irqN < NR_PERI_INTS; irqN += 4) {79int irqn;80u32 iar = bfin_read32((unsigned long *)SIC_IAR0 +81#if defined(CONFIG_BF51x) || defined(CONFIG_BF52x) || \82defined(CONFIG_BF538) || defined(CONFIG_BF539)83((irqN % 32) >> 3) + ((irqN / 32) * ((SIC_IAR4 - SIC_IAR0) / 4))84#else85(irqN >> 3)86#endif87);8889for (irqn = irqN; irqn < irqN + 4; ++irqn) {90int iar_shift = (irqn & 7) * 4;91if (ivg == (0xf & (iar >> iar_shift))) {92ivg_table[irq_pos].irqno = IVG7 + irqn;93ivg_table[irq_pos].isrflag = 1 << (irqn % 32);94ivg7_13[ivg].istop++;95irq_pos++;96}97}98}99}100}101102/*103* This is for core internal IRQs104*/105106void bfin_ack_noop(struct irq_data *d)107{108/* Dummy function. */109}110111static void bfin_core_mask_irq(struct irq_data *d)112{113bfin_irq_flags &= ~(1 << d->irq);114if (!hard_irqs_disabled())115hard_local_irq_enable();116}117118static void bfin_core_unmask_irq(struct irq_data *d)119{120bfin_irq_flags |= 1 << d->irq;121/*122* If interrupts are enabled, IMASK must contain the same value123* as bfin_irq_flags. Make sure that invariant holds. If interrupts124* are currently disabled we need not do anything; one of the125* callers will take care of setting IMASK to the proper value126* when reenabling interrupts.127* local_irq_enable just does "STI bfin_irq_flags", so it's exactly128* what we need.129*/130if (!hard_irqs_disabled())131hard_local_irq_enable();132return;133}134135void bfin_internal_mask_irq(unsigned int irq)136{137unsigned long flags = hard_local_irq_save();138139#ifdef SIC_IMASK0140unsigned mask_bank = SIC_SYSIRQ(irq) / 32;141unsigned mask_bit = SIC_SYSIRQ(irq) % 32;142bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) &143~(1 << mask_bit));144# ifdef CONFIG_SMP145bfin_write_SICB_IMASK(mask_bank, bfin_read_SICB_IMASK(mask_bank) &146~(1 << mask_bit));147# endif148#else149bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &150~(1 << SIC_SYSIRQ(irq)));151#endif152153hard_local_irq_restore(flags);154}155156static void bfin_internal_mask_irq_chip(struct irq_data *d)157{158bfin_internal_mask_irq(d->irq);159}160161#ifdef CONFIG_SMP162static void bfin_internal_unmask_irq_affinity(unsigned int irq,163const struct cpumask *affinity)164#else165void bfin_internal_unmask_irq(unsigned int irq)166#endif167{168unsigned long flags = hard_local_irq_save();169170#ifdef SIC_IMASK0171unsigned mask_bank = SIC_SYSIRQ(irq) / 32;172unsigned mask_bit = SIC_SYSIRQ(irq) % 32;173# ifdef CONFIG_SMP174if (cpumask_test_cpu(0, affinity))175# endif176bfin_write_SIC_IMASK(mask_bank,177bfin_read_SIC_IMASK(mask_bank) |178(1 << mask_bit));179# ifdef CONFIG_SMP180if (cpumask_test_cpu(1, affinity))181bfin_write_SICB_IMASK(mask_bank,182bfin_read_SICB_IMASK(mask_bank) |183(1 << mask_bit));184# endif185#else186bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() |187(1 << SIC_SYSIRQ(irq)));188#endif189190hard_local_irq_restore(flags);191}192193#ifdef CONFIG_SMP194static void bfin_internal_unmask_irq_chip(struct irq_data *d)195{196bfin_internal_unmask_irq_affinity(d->irq, d->affinity);197}198199static int bfin_internal_set_affinity(struct irq_data *d,200const struct cpumask *mask, bool force)201{202bfin_internal_mask_irq(d->irq);203bfin_internal_unmask_irq_affinity(d->irq, mask);204205return 0;206}207#else208static void bfin_internal_unmask_irq_chip(struct irq_data *d)209{210bfin_internal_unmask_irq(d->irq);211}212#endif213214#ifdef CONFIG_PM215int bfin_internal_set_wake(unsigned int irq, unsigned int state)216{217u32 bank, bit, wakeup = 0;218unsigned long flags;219bank = SIC_SYSIRQ(irq) / 32;220bit = SIC_SYSIRQ(irq) % 32;221222switch (irq) {223#ifdef IRQ_RTC224case IRQ_RTC:225wakeup |= WAKE;226break;227#endif228#ifdef IRQ_CAN0_RX229case IRQ_CAN0_RX:230wakeup |= CANWE;231break;232#endif233#ifdef IRQ_CAN1_RX234case IRQ_CAN1_RX:235wakeup |= CANWE;236break;237#endif238#ifdef IRQ_USB_INT0239case IRQ_USB_INT0:240wakeup |= USBWE;241break;242#endif243#ifdef CONFIG_BF54x244case IRQ_CNT:245wakeup |= ROTWE;246break;247#endif248default:249break;250}251252flags = hard_local_irq_save();253254if (state) {255bfin_sic_iwr[bank] |= (1 << bit);256vr_wakeup |= wakeup;257258} else {259bfin_sic_iwr[bank] &= ~(1 << bit);260vr_wakeup &= ~wakeup;261}262263hard_local_irq_restore(flags);264265return 0;266}267268static int bfin_internal_set_wake_chip(struct irq_data *d, unsigned int state)269{270return bfin_internal_set_wake(d->irq, state);271}272#else273# define bfin_internal_set_wake_chip NULL274#endif275276static struct irq_chip bfin_core_irqchip = {277.name = "CORE",278.irq_ack = bfin_ack_noop,279.irq_mask = bfin_core_mask_irq,280.irq_unmask = bfin_core_unmask_irq,281};282283static struct irq_chip bfin_internal_irqchip = {284.name = "INTN",285.irq_ack = bfin_ack_noop,286.irq_mask = bfin_internal_mask_irq_chip,287.irq_unmask = bfin_internal_unmask_irq_chip,288.irq_mask_ack = bfin_internal_mask_irq_chip,289.irq_disable = bfin_internal_mask_irq_chip,290.irq_enable = bfin_internal_unmask_irq_chip,291#ifdef CONFIG_SMP292.irq_set_affinity = bfin_internal_set_affinity,293#endif294.irq_set_wake = bfin_internal_set_wake_chip,295};296297void bfin_handle_irq(unsigned irq)298{299#ifdef CONFIG_IPIPE300struct pt_regs regs; /* Contents not used. */301ipipe_trace_irq_entry(irq);302__ipipe_handle_irq(irq, ®s);303ipipe_trace_irq_exit(irq);304#else /* !CONFIG_IPIPE */305generic_handle_irq(irq);306#endif /* !CONFIG_IPIPE */307}308309#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)310static int mac_stat_int_mask;311312static void bfin_mac_status_ack_irq(unsigned int irq)313{314switch (irq) {315case IRQ_MAC_MMCINT:316bfin_write_EMAC_MMC_TIRQS(317bfin_read_EMAC_MMC_TIRQE() &318bfin_read_EMAC_MMC_TIRQS());319bfin_write_EMAC_MMC_RIRQS(320bfin_read_EMAC_MMC_RIRQE() &321bfin_read_EMAC_MMC_RIRQS());322break;323case IRQ_MAC_RXFSINT:324bfin_write_EMAC_RX_STKY(325bfin_read_EMAC_RX_IRQE() &326bfin_read_EMAC_RX_STKY());327break;328case IRQ_MAC_TXFSINT:329bfin_write_EMAC_TX_STKY(330bfin_read_EMAC_TX_IRQE() &331bfin_read_EMAC_TX_STKY());332break;333case IRQ_MAC_WAKEDET:334bfin_write_EMAC_WKUP_CTL(335bfin_read_EMAC_WKUP_CTL() | MPKS | RWKS);336break;337default:338/* These bits are W1C */339bfin_write_EMAC_SYSTAT(1L << (irq - IRQ_MAC_PHYINT));340break;341}342}343344static void bfin_mac_status_mask_irq(struct irq_data *d)345{346unsigned int irq = d->irq;347348mac_stat_int_mask &= ~(1L << (irq - IRQ_MAC_PHYINT));349#ifdef BF537_FAMILY350switch (irq) {351case IRQ_MAC_PHYINT:352bfin_write_EMAC_SYSCTL(bfin_read_EMAC_SYSCTL() & ~PHYIE);353break;354default:355break;356}357#else358if (!mac_stat_int_mask)359bfin_internal_mask_irq(IRQ_MAC_ERROR);360#endif361bfin_mac_status_ack_irq(irq);362}363364static void bfin_mac_status_unmask_irq(struct irq_data *d)365{366unsigned int irq = d->irq;367368#ifdef BF537_FAMILY369switch (irq) {370case IRQ_MAC_PHYINT:371bfin_write_EMAC_SYSCTL(bfin_read_EMAC_SYSCTL() | PHYIE);372break;373default:374break;375}376#else377if (!mac_stat_int_mask)378bfin_internal_unmask_irq(IRQ_MAC_ERROR);379#endif380mac_stat_int_mask |= 1L << (irq - IRQ_MAC_PHYINT);381}382383#ifdef CONFIG_PM384int bfin_mac_status_set_wake(struct irq_data *d, unsigned int state)385{386#ifdef BF537_FAMILY387return bfin_internal_set_wake(IRQ_GENERIC_ERROR, state);388#else389return bfin_internal_set_wake(IRQ_MAC_ERROR, state);390#endif391}392#else393# define bfin_mac_status_set_wake NULL394#endif395396static struct irq_chip bfin_mac_status_irqchip = {397.name = "MACST",398.irq_ack = bfin_ack_noop,399.irq_mask_ack = bfin_mac_status_mask_irq,400.irq_mask = bfin_mac_status_mask_irq,401.irq_unmask = bfin_mac_status_unmask_irq,402.irq_set_wake = bfin_mac_status_set_wake,403};404405void bfin_demux_mac_status_irq(unsigned int int_err_irq,406struct irq_desc *inta_desc)407{408int i, irq = 0;409u32 status = bfin_read_EMAC_SYSTAT();410411for (i = 0; i <= (IRQ_MAC_STMDONE - IRQ_MAC_PHYINT); i++)412if (status & (1L << i)) {413irq = IRQ_MAC_PHYINT + i;414break;415}416417if (irq) {418if (mac_stat_int_mask & (1L << (irq - IRQ_MAC_PHYINT))) {419bfin_handle_irq(irq);420} else {421bfin_mac_status_ack_irq(irq);422pr_debug("IRQ %d:"423" MASKED MAC ERROR INTERRUPT ASSERTED\n",424irq);425}426} else427printk(KERN_ERR428"%s : %s : LINE %d :\nIRQ ?: MAC ERROR"429" INTERRUPT ASSERTED BUT NO SOURCE FOUND"430"(EMAC_SYSTAT=0x%X)\n",431__func__, __FILE__, __LINE__, status);432}433#endif434435static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)436{437#ifdef CONFIG_IPIPE438handle = handle_level_irq;439#endif440__irq_set_handler_locked(irq, handle);441}442443static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);444extern void bfin_gpio_irq_prepare(unsigned gpio);445446#if !defined(CONFIG_BF54x)447448static void bfin_gpio_ack_irq(struct irq_data *d)449{450/* AFAIK ack_irq in case mask_ack is provided451* get's only called for edge sense irqs452*/453set_gpio_data(irq_to_gpio(d->irq), 0);454}455456static void bfin_gpio_mask_ack_irq(struct irq_data *d)457{458unsigned int irq = d->irq;459u32 gpionr = irq_to_gpio(irq);460461if (!irqd_is_level_type(d))462set_gpio_data(gpionr, 0);463464set_gpio_maska(gpionr, 0);465}466467static void bfin_gpio_mask_irq(struct irq_data *d)468{469set_gpio_maska(irq_to_gpio(d->irq), 0);470}471472static void bfin_gpio_unmask_irq(struct irq_data *d)473{474set_gpio_maska(irq_to_gpio(d->irq), 1);475}476477static unsigned int bfin_gpio_irq_startup(struct irq_data *d)478{479u32 gpionr = irq_to_gpio(d->irq);480481if (__test_and_set_bit(gpionr, gpio_enabled))482bfin_gpio_irq_prepare(gpionr);483484bfin_gpio_unmask_irq(d);485486return 0;487}488489static void bfin_gpio_irq_shutdown(struct irq_data *d)490{491u32 gpionr = irq_to_gpio(d->irq);492493bfin_gpio_mask_irq(d);494__clear_bit(gpionr, gpio_enabled);495bfin_gpio_irq_free(gpionr);496}497498static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)499{500unsigned int irq = d->irq;501int ret;502char buf[16];503u32 gpionr = irq_to_gpio(irq);504505if (type == IRQ_TYPE_PROBE) {506/* only probe unenabled GPIO interrupt lines */507if (test_bit(gpionr, gpio_enabled))508return 0;509type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;510}511512if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |513IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {514515snprintf(buf, 16, "gpio-irq%d", irq);516ret = bfin_gpio_irq_request(gpionr, buf);517if (ret)518return ret;519520if (__test_and_set_bit(gpionr, gpio_enabled))521bfin_gpio_irq_prepare(gpionr);522523} else {524__clear_bit(gpionr, gpio_enabled);525return 0;526}527528set_gpio_inen(gpionr, 0);529set_gpio_dir(gpionr, 0);530531if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))532== (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))533set_gpio_both(gpionr, 1);534else535set_gpio_both(gpionr, 0);536537if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))538set_gpio_polar(gpionr, 1); /* low or falling edge denoted by one */539else540set_gpio_polar(gpionr, 0); /* high or rising edge denoted by zero */541542if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {543set_gpio_edge(gpionr, 1);544set_gpio_inen(gpionr, 1);545set_gpio_data(gpionr, 0);546547} else {548set_gpio_edge(gpionr, 0);549set_gpio_inen(gpionr, 1);550}551552if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))553bfin_set_irq_handler(irq, handle_edge_irq);554else555bfin_set_irq_handler(irq, handle_level_irq);556557return 0;558}559560#ifdef CONFIG_PM561static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)562{563return gpio_pm_wakeup_ctrl(irq_to_gpio(d->irq), state);564}565#else566# define bfin_gpio_set_wake NULL567#endif568569static void bfin_demux_gpio_block(unsigned int irq)570{571unsigned int gpio, mask;572573gpio = irq_to_gpio(irq);574mask = get_gpiop_data(gpio) & get_gpiop_maska(gpio);575576while (mask) {577if (mask & 1)578bfin_handle_irq(irq);579irq++;580mask >>= 1;581}582}583584void bfin_demux_gpio_irq(unsigned int inta_irq,585struct irq_desc *desc)586{587unsigned int irq;588589switch (inta_irq) {590#if defined(BF537_FAMILY)591case IRQ_PF_INTA_PG_INTA:592bfin_demux_gpio_block(IRQ_PF0);593irq = IRQ_PG0;594break;595case IRQ_PH_INTA_MAC_RX:596irq = IRQ_PH0;597break;598#elif defined(BF533_FAMILY)599case IRQ_PROG_INTA:600irq = IRQ_PF0;601break;602#elif defined(BF538_FAMILY)603case IRQ_PORTF_INTA:604irq = IRQ_PF0;605break;606#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)607case IRQ_PORTF_INTA:608irq = IRQ_PF0;609break;610case IRQ_PORTG_INTA:611irq = IRQ_PG0;612break;613case IRQ_PORTH_INTA:614irq = IRQ_PH0;615break;616#elif defined(CONFIG_BF561)617case IRQ_PROG0_INTA:618irq = IRQ_PF0;619break;620case IRQ_PROG1_INTA:621irq = IRQ_PF16;622break;623case IRQ_PROG2_INTA:624irq = IRQ_PF32;625break;626#endif627default:628BUG();629return;630}631632bfin_demux_gpio_block(irq);633}634635#else /* CONFIG_BF54x */636637#define NR_PINT_SYS_IRQS 4638#define NR_PINT_BITS 32639#define NR_PINTS 160640#define IRQ_NOT_AVAIL 0xFF641642#define PINT_2_BANK(x) ((x) >> 5)643#define PINT_2_BIT(x) ((x) & 0x1F)644#define PINT_BIT(x) (1 << (PINT_2_BIT(x)))645646static unsigned char irq2pint_lut[NR_PINTS];647static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS];648649struct pin_int_t {650unsigned int mask_set;651unsigned int mask_clear;652unsigned int request;653unsigned int assign;654unsigned int edge_set;655unsigned int edge_clear;656unsigned int invert_set;657unsigned int invert_clear;658unsigned int pinstate;659unsigned int latch;660};661662static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = {663(struct pin_int_t *)PINT0_MASK_SET,664(struct pin_int_t *)PINT1_MASK_SET,665(struct pin_int_t *)PINT2_MASK_SET,666(struct pin_int_t *)PINT3_MASK_SET,667};668669inline unsigned int get_irq_base(u32 bank, u8 bmap)670{671unsigned int irq_base;672673if (bank < 2) { /*PA-PB */674irq_base = IRQ_PA0 + bmap * 16;675} else { /*PC-PJ */676irq_base = IRQ_PC0 + bmap * 16;677}678679return irq_base;680}681682/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */683void init_pint_lut(void)684{685u16 bank, bit, irq_base, bit_pos;686u32 pint_assign;687u8 bmap;688689memset(irq2pint_lut, IRQ_NOT_AVAIL, sizeof(irq2pint_lut));690691for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) {692693pint_assign = pint[bank]->assign;694695for (bit = 0; bit < NR_PINT_BITS; bit++) {696697bmap = (pint_assign >> ((bit / 8) * 8)) & 0xFF;698699irq_base = get_irq_base(bank, bmap);700701irq_base += (bit % 8) + ((bit / 8) & 1 ? 8 : 0);702bit_pos = bit + bank * NR_PINT_BITS;703704pint2irq_lut[bit_pos] = irq_base - SYS_IRQS;705irq2pint_lut[irq_base - SYS_IRQS] = bit_pos;706}707}708}709710static void bfin_gpio_ack_irq(struct irq_data *d)711{712u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];713u32 pintbit = PINT_BIT(pint_val);714u32 bank = PINT_2_BANK(pint_val);715716if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {717if (pint[bank]->invert_set & pintbit)718pint[bank]->invert_clear = pintbit;719else720pint[bank]->invert_set = pintbit;721}722pint[bank]->request = pintbit;723724}725726static void bfin_gpio_mask_ack_irq(struct irq_data *d)727{728u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];729u32 pintbit = PINT_BIT(pint_val);730u32 bank = PINT_2_BANK(pint_val);731732if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {733if (pint[bank]->invert_set & pintbit)734pint[bank]->invert_clear = pintbit;735else736pint[bank]->invert_set = pintbit;737}738739pint[bank]->request = pintbit;740pint[bank]->mask_clear = pintbit;741}742743static void bfin_gpio_mask_irq(struct irq_data *d)744{745u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];746747pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val);748}749750static void bfin_gpio_unmask_irq(struct irq_data *d)751{752u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];753u32 pintbit = PINT_BIT(pint_val);754u32 bank = PINT_2_BANK(pint_val);755756pint[bank]->mask_set = pintbit;757}758759static unsigned int bfin_gpio_irq_startup(struct irq_data *d)760{761unsigned int irq = d->irq;762u32 gpionr = irq_to_gpio(irq);763u32 pint_val = irq2pint_lut[irq - SYS_IRQS];764765if (pint_val == IRQ_NOT_AVAIL) {766printk(KERN_ERR767"GPIO IRQ %d :Not in PINT Assign table "768"Reconfigure Interrupt to Port Assignemt\n", irq);769return -ENODEV;770}771772if (__test_and_set_bit(gpionr, gpio_enabled))773bfin_gpio_irq_prepare(gpionr);774775bfin_gpio_unmask_irq(d);776777return 0;778}779780static void bfin_gpio_irq_shutdown(struct irq_data *d)781{782u32 gpionr = irq_to_gpio(d->irq);783784bfin_gpio_mask_irq(d);785__clear_bit(gpionr, gpio_enabled);786bfin_gpio_irq_free(gpionr);787}788789static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)790{791unsigned int irq = d->irq;792int ret;793char buf[16];794u32 gpionr = irq_to_gpio(irq);795u32 pint_val = irq2pint_lut[irq - SYS_IRQS];796u32 pintbit = PINT_BIT(pint_val);797u32 bank = PINT_2_BANK(pint_val);798799if (pint_val == IRQ_NOT_AVAIL)800return -ENODEV;801802if (type == IRQ_TYPE_PROBE) {803/* only probe unenabled GPIO interrupt lines */804if (test_bit(gpionr, gpio_enabled))805return 0;806type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;807}808809if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |810IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {811812snprintf(buf, 16, "gpio-irq%d", irq);813ret = bfin_gpio_irq_request(gpionr, buf);814if (ret)815return ret;816817if (__test_and_set_bit(gpionr, gpio_enabled))818bfin_gpio_irq_prepare(gpionr);819820} else {821__clear_bit(gpionr, gpio_enabled);822return 0;823}824825if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))826pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */827else828pint[bank]->invert_clear = pintbit; /* high or rising edge denoted by zero */829830if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))831== (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {832if (gpio_get_value(gpionr))833pint[bank]->invert_set = pintbit;834else835pint[bank]->invert_clear = pintbit;836}837838if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {839pint[bank]->edge_set = pintbit;840bfin_set_irq_handler(irq, handle_edge_irq);841} else {842pint[bank]->edge_clear = pintbit;843bfin_set_irq_handler(irq, handle_level_irq);844}845846return 0;847}848849#ifdef CONFIG_PM850static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)851{852u32 pint_irq;853u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];854u32 bank = PINT_2_BANK(pint_val);855856switch (bank) {857case 0:858pint_irq = IRQ_PINT0;859break;860case 2:861pint_irq = IRQ_PINT2;862break;863case 3:864pint_irq = IRQ_PINT3;865break;866case 1:867pint_irq = IRQ_PINT1;868break;869default:870return -EINVAL;871}872873bfin_internal_set_wake(pint_irq, state);874875return 0;876}877#else878# define bfin_gpio_set_wake NULL879#endif880881void bfin_demux_gpio_irq(unsigned int inta_irq,882struct irq_desc *desc)883{884u32 bank, pint_val;885u32 request, irq;886887switch (inta_irq) {888case IRQ_PINT0:889bank = 0;890break;891case IRQ_PINT2:892bank = 2;893break;894case IRQ_PINT3:895bank = 3;896break;897case IRQ_PINT1:898bank = 1;899break;900default:901return;902}903904pint_val = bank * NR_PINT_BITS;905906request = pint[bank]->request;907908while (request) {909if (request & 1) {910irq = pint2irq_lut[pint_val] + SYS_IRQS;911bfin_handle_irq(irq);912}913pint_val++;914request >>= 1;915}916917}918#endif919920static struct irq_chip bfin_gpio_irqchip = {921.name = "GPIO",922.irq_ack = bfin_gpio_ack_irq,923.irq_mask = bfin_gpio_mask_irq,924.irq_mask_ack = bfin_gpio_mask_ack_irq,925.irq_unmask = bfin_gpio_unmask_irq,926.irq_disable = bfin_gpio_mask_irq,927.irq_enable = bfin_gpio_unmask_irq,928.irq_set_type = bfin_gpio_irq_type,929.irq_startup = bfin_gpio_irq_startup,930.irq_shutdown = bfin_gpio_irq_shutdown,931.irq_set_wake = bfin_gpio_set_wake,932};933934void __cpuinit init_exception_vectors(void)935{936/* cannot program in software:937* evt0 - emulation (jtag)938* evt1 - reset939*/940bfin_write_EVT2(evt_nmi);941bfin_write_EVT3(trap);942bfin_write_EVT5(evt_ivhw);943bfin_write_EVT6(evt_timer);944bfin_write_EVT7(evt_evt7);945bfin_write_EVT8(evt_evt8);946bfin_write_EVT9(evt_evt9);947bfin_write_EVT10(evt_evt10);948bfin_write_EVT11(evt_evt11);949bfin_write_EVT12(evt_evt12);950bfin_write_EVT13(evt_evt13);951bfin_write_EVT14(evt_evt14);952bfin_write_EVT15(evt_system_call);953CSYNC();954}955956/*957* This function should be called during kernel startup to initialize958* the BFin IRQ handling routines.959*/960961int __init init_arch_irq(void)962{963int irq;964unsigned long ilat = 0;965966/* Disable all the peripheral intrs - page 4-29 HW Ref manual */967#ifdef SIC_IMASK0968bfin_write_SIC_IMASK0(SIC_UNMASK_ALL);969bfin_write_SIC_IMASK1(SIC_UNMASK_ALL);970# ifdef SIC_IMASK2971bfin_write_SIC_IMASK2(SIC_UNMASK_ALL);972# endif973# ifdef CONFIG_SMP974bfin_write_SICB_IMASK0(SIC_UNMASK_ALL);975bfin_write_SICB_IMASK1(SIC_UNMASK_ALL);976# endif977#else978bfin_write_SIC_IMASK(SIC_UNMASK_ALL);979#endif980981local_irq_disable();982983#ifdef CONFIG_BF54x984# ifdef CONFIG_PINTx_REASSIGN985pint[0]->assign = CONFIG_PINT0_ASSIGN;986pint[1]->assign = CONFIG_PINT1_ASSIGN;987pint[2]->assign = CONFIG_PINT2_ASSIGN;988pint[3]->assign = CONFIG_PINT3_ASSIGN;989# endif990/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */991init_pint_lut();992#endif993994for (irq = 0; irq <= SYS_IRQS; irq++) {995if (irq <= IRQ_CORETMR)996irq_set_chip(irq, &bfin_core_irqchip);997else998irq_set_chip(irq, &bfin_internal_irqchip);9991000switch (irq) {1001#if defined(BF537_FAMILY)1002case IRQ_PH_INTA_MAC_RX:1003case IRQ_PF_INTA_PG_INTA:1004#elif defined(BF533_FAMILY)1005case IRQ_PROG_INTA:1006#elif defined(CONFIG_BF54x)1007case IRQ_PINT0:1008case IRQ_PINT1:1009case IRQ_PINT2:1010case IRQ_PINT3:1011#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)1012case IRQ_PORTF_INTA:1013case IRQ_PORTG_INTA:1014case IRQ_PORTH_INTA:1015#elif defined(CONFIG_BF561)1016case IRQ_PROG0_INTA:1017case IRQ_PROG1_INTA:1018case IRQ_PROG2_INTA:1019#elif defined(BF538_FAMILY)1020case IRQ_PORTF_INTA:1021#endif1022irq_set_chained_handler(irq, bfin_demux_gpio_irq);1023break;1024#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)1025case IRQ_MAC_ERROR:1026irq_set_chained_handler(irq,1027bfin_demux_mac_status_irq);1028break;1029#endif1030#ifdef CONFIG_SMP1031case IRQ_SUPPLE_0:1032case IRQ_SUPPLE_1:1033irq_set_handler(irq, handle_percpu_irq);1034break;1035#endif10361037#ifdef CONFIG_TICKSOURCE_CORETMR1038case IRQ_CORETMR:1039# ifdef CONFIG_SMP1040irq_set_handler(irq, handle_percpu_irq);1041# else1042irq_set_handler(irq, handle_simple_irq);1043# endif1044break;1045#endif10461047#ifdef CONFIG_TICKSOURCE_GPTMR01048case IRQ_TIMER0:1049irq_set_handler(irq, handle_simple_irq);1050break;1051#endif10521053default:1054#ifdef CONFIG_IPIPE1055irq_set_handler(irq, handle_level_irq);1056#else1057irq_set_handler(irq, handle_simple_irq);1058#endif1059break;1060}1061}10621063init_mach_irq();10641065#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)1066for (irq = IRQ_MAC_PHYINT; irq <= IRQ_MAC_STMDONE; irq++)1067irq_set_chip_and_handler(irq, &bfin_mac_status_irqchip,1068handle_level_irq);1069#endif1070/* if configured as edge, then will be changed to do_edge_IRQ */1071for (irq = GPIO_IRQ_BASE;1072irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++)1073irq_set_chip_and_handler(irq, &bfin_gpio_irqchip,1074handle_level_irq);10751076bfin_write_IMASK(0);1077CSYNC();1078ilat = bfin_read_ILAT();1079CSYNC();1080bfin_write_ILAT(ilat);1081CSYNC();10821083printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n");1084/* IMASK=xxx is equivalent to STI xx or bfin_irq_flags=xx,1085* local_irq_enable()1086*/1087program_IAR();1088/* Therefore it's better to setup IARs before interrupts enabled */1089search_IAR();10901091/* Enable interrupts IVG7-15 */1092bfin_irq_flags |= IMASK_IVG15 |1093IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |1094IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;10951096/* This implicitly covers ANOMALY_050001711097* Boot-ROM code modifies SICA_IWRx wakeup registers1098*/1099#ifdef SIC_IWR01100bfin_write_SIC_IWR0(IWR_DISABLE_ALL);1101# ifdef SIC_IWR11102/* BF52x/BF51x system reset does not properly reset SIC_IWR1 which1103* will screw up the bootrom as it relies on MDMA0/1 waking it1104* up from IDLE instructions. See this report for more info:1105* http://blackfin.uclinux.org/gf/tracker/43231106*/1107if (ANOMALY_05000435)1108bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11));1109else1110bfin_write_SIC_IWR1(IWR_DISABLE_ALL);1111# endif1112# ifdef SIC_IWR21113bfin_write_SIC_IWR2(IWR_DISABLE_ALL);1114# endif1115#else1116bfin_write_SIC_IWR(IWR_DISABLE_ALL);1117#endif11181119return 0;1120}11211122#ifdef CONFIG_DO_IRQ_L11123__attribute__((l1_text))1124#endif1125static int vec_to_irq(int vec)1126{1127struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;1128struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;1129unsigned long sic_status[3];11301131if (likely(vec == EVT_IVTMR_P))1132return IRQ_CORETMR;11331134#ifdef SIC_ISR1135sic_status[0] = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR();1136#else1137if (smp_processor_id()) {1138# ifdef SICB_ISR01139/* This will be optimized out in UP mode. */1140sic_status[0] = bfin_read_SICB_ISR0() & bfin_read_SICB_IMASK0();1141sic_status[1] = bfin_read_SICB_ISR1() & bfin_read_SICB_IMASK1();1142# endif1143} else {1144sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0();1145sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1();1146}1147#endif1148#ifdef SIC_ISR21149sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2();1150#endif11511152for (;; ivg++) {1153if (ivg >= ivg_stop)1154return -1;1155#ifdef SIC_ISR1156if (sic_status[0] & ivg->isrflag)1157#else1158if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag)1159#endif1160return ivg->irqno;1161}1162}11631164#ifdef CONFIG_DO_IRQ_L11165__attribute__((l1_text))1166#endif1167void do_irq(int vec, struct pt_regs *fp)1168{1169int irq = vec_to_irq(vec);1170if (irq == -1)1171return;1172asm_do_IRQ(irq, fp);1173}11741175#ifdef CONFIG_IPIPE11761177int __ipipe_get_irq_priority(unsigned irq)1178{1179int ient, prio;11801181if (irq <= IRQ_CORETMR)1182return irq;11831184for (ient = 0; ient < NR_PERI_INTS; ient++) {1185struct ivgx *ivg = ivg_table + ient;1186if (ivg->irqno == irq) {1187for (prio = 0; prio <= IVG13-IVG7; prio++) {1188if (ivg7_13[prio].ifirst <= ivg &&1189ivg7_13[prio].istop > ivg)1190return IVG7 + prio;1191}1192}1193}11941195return IVG15;1196}11971198/* Hw interrupts are disabled on entry (check SAVE_CONTEXT). */1199#ifdef CONFIG_DO_IRQ_L11200__attribute__((l1_text))1201#endif1202asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)1203{1204struct ipipe_percpu_domain_data *p = ipipe_root_cpudom_ptr();1205struct ipipe_domain *this_domain = __ipipe_current_domain;1206struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop;1207struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst;1208int irq, s = 0;12091210irq = vec_to_irq(vec);1211if (irq == -1)1212return 0;12131214if (irq == IRQ_SYSTMR) {1215#if !defined(CONFIG_GENERIC_CLOCKEVENTS) || defined(CONFIG_TICKSOURCE_GPTMR0)1216bfin_write_TIMER_STATUS(1); /* Latch TIMIL0 */1217#endif1218/* This is basically what we need from the register frame. */1219__raw_get_cpu_var(__ipipe_tick_regs).ipend = regs->ipend;1220__raw_get_cpu_var(__ipipe_tick_regs).pc = regs->pc;1221if (this_domain != ipipe_root_domain)1222__raw_get_cpu_var(__ipipe_tick_regs).ipend &= ~0x10;1223else1224__raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10;1225}12261227/*1228* We don't want Linux interrupt handlers to run at the1229* current core priority level (i.e. < EVT15), since this1230* might delay other interrupts handled by a high priority1231* domain. Here is what we do instead:1232*1233* - we raise the SYNCDEFER bit to prevent1234* __ipipe_handle_irq() to sync the pipeline for the root1235* stage for the incoming interrupt. Upon return, that IRQ is1236* pending in the interrupt log.1237*1238* - we raise the TIF_IRQ_SYNC bit for the current thread, so1239* that _schedule_and_signal_from_int will eventually sync the1240* pipeline from EVT15.1241*/1242if (this_domain == ipipe_root_domain) {1243s = __test_and_set_bit(IPIPE_SYNCDEFER_FLAG, &p->status);1244barrier();1245}12461247ipipe_trace_irq_entry(irq);1248__ipipe_handle_irq(irq, regs);1249ipipe_trace_irq_exit(irq);12501251if (user_mode(regs) &&1252!ipipe_test_foreign_stack() &&1253(current->ipipe_flags & PF_EVTRET) != 0) {1254/*1255* Testing for user_regs() does NOT fully eliminate1256* foreign stack contexts, because of the forged1257* interrupt returns we do through1258* __ipipe_call_irqtail. In that case, we might have1259* preempted a foreign stack context in a high1260* priority domain, with a single interrupt level now1261* pending after the irqtail unwinding is done. In1262* which case user_mode() is now true, and the event1263* gets dispatched spuriously.1264*/1265current->ipipe_flags &= ~PF_EVTRET;1266__ipipe_dispatch_event(IPIPE_EVENT_RETURN, regs);1267}12681269if (this_domain == ipipe_root_domain) {1270set_thread_flag(TIF_IRQ_SYNC);1271if (!s) {1272__clear_bit(IPIPE_SYNCDEFER_FLAG, &p->status);1273return !test_bit(IPIPE_STALL_FLAG, &p->status);1274}1275}12761277return 0;1278}12791280#endif /* CONFIG_IPIPE */128112821283