1/* $NetBSD: mvsoc_intr.c,v 1.2 2010/12/20 00:25:28 matt Exp $ */ 2/* 3 * Copyright (c) 2010 KIYOHARA Takashi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> 29__KERNEL_RCSID(0, "$NetBSD: mvsoc_intr.c,v 1.2 2010/12/20 00:25:28 matt Exp $"); 30 31#define _INTR_PRIVATE 32 33#include <sys/param.h> 34#include <sys/proc.h> 35 36#include <machine/intr.h> 37 38#include <arm/cpu.h> 39#include <arm/pic/picvar.h> 40#include <arm/marvell/mvsocreg.h> 41#include <arm/marvell/mvsocvar.h> 42 43 44static void mvsoc_bridge_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t); 45static void mvsoc_bridge_pic_block_irqs(struct pic_softc *, size_t, uint32_t); 46static int mvsoc_bridge_pic_find_pending_irqs(struct pic_softc *); 47static void mvsoc_bridge_pic_establish_irq(struct pic_softc *, 48 struct intrsource *); 49static void mvsoc_bridge_pic_source_name(struct pic_softc *, int, char *, 50 size_t); 51 52static const char * const sources[] = { 53 "CPUSelfInt", "CPUTimer0IntReq", "CPUTimer1IntReq", "CPUWDTimerIntReq", 54 "AccessErr", "Bit64Err", 55}; 56 57static struct pic_ops mvsoc_bridge_picops = { 58 .pic_unblock_irqs = mvsoc_bridge_pic_unblock_irqs, 59 .pic_block_irqs = mvsoc_bridge_pic_block_irqs, 60 .pic_find_pending_irqs = mvsoc_bridge_pic_find_pending_irqs, 61 .pic_establish_irq = mvsoc_bridge_pic_establish_irq, 62 .pic_source_name = mvsoc_bridge_pic_source_name, 63}; 64 65struct pic_softc mvsoc_bridge_pic = { 66 .pic_ops = &mvsoc_bridge_picops, 67 .pic_maxsources = MVSOC_MLMB_MLMBI_NIRQ, 68 .pic_name = "mvsoc_bridge", 69}; 70 71 72void 73mvsoc_irq_handler(void *frame) 74{ 75 struct cpu_info * const ci = curcpu(); 76 const int oldipl = ci->ci_cpl; 77 const uint32_t oldipl_mask = __BIT(oldipl); 78 int ipl_mask = 0; 79 80 ci->ci_data.cpu_nintr++; 81 82 ipl_mask = find_pending_irqs(); 83 84 /* 85 * Record the pending_ipls and deliver them if we can. 86 */ 87 if ((ipl_mask & ~oldipl_mask) > oldipl_mask) 88 pic_do_pending_ints(I32_bit, oldipl, frame); 89} 90 91/* 92 * Mbus-L to Mbus bridge 93 */ 94 95void * 96mvsoc_bridge_intr_establish(int ih, int ipl, int (*ih_func)(void *), void *arg) 97{ 98 99 return intr_establish(mvsoc_bridge_pic.pic_irqbase + ih, ipl, 0, 100 ih_func, arg); 101} 102 103/* ARGSUSED */ 104static void 105mvsoc_bridge_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase, 106 uint32_t irq_mask) 107{ 108 109 write_mlmbreg(MVSOC_MLMB_MLMBICR, 110 read_mlmbreg(MVSOC_MLMB_MLMBICR) & ~irq_mask); 111 write_mlmbreg(MVSOC_MLMB_MLMBIMR, 112 read_mlmbreg(MVSOC_MLMB_MLMBIMR) | irq_mask); 113} 114 115/* ARGSUSED */ 116static void 117mvsoc_bridge_pic_block_irqs(struct pic_softc *pic, size_t irqbase, 118 uint32_t irq_mask) 119{ 120 121 write_mlmbreg(MVSOC_MLMB_MLMBIMR, 122 read_mlmbreg(MVSOC_MLMB_MLMBIMR) & ~irq_mask); 123} 124 125static int 126mvsoc_bridge_pic_find_pending_irqs(struct pic_softc *pic) 127{ 128 uint32_t pending; 129 130 pending = 131 read_mlmbreg(MVSOC_MLMB_MLMBICR) & read_mlmbreg(MVSOC_MLMB_MLMBIMR); 132 133 if (pending == 0) 134 return 0; 135 136 return pic_mark_pending_sources(pic, 0, pending); 137} 138 139/* ARGSUSED */ 140static void 141mvsoc_bridge_pic_establish_irq(struct pic_softc *pic, struct intrsource *is) 142{ 143 /* Nothing */ 144} 145 146static void 147mvsoc_bridge_pic_source_name(struct pic_softc *pic, int irq, char *buf, 148 size_t len) 149{ 150 151 strlcpy(buf, sources[irq], len); 152} 153