1*49de48baSmartin /* $NetBSD: mvsoc_intr.c,v 1.9 2014/02/22 16:14:38 martin Exp $ */
252d286fbSkiyohara /*
352d286fbSkiyohara * Copyright (c) 2010 KIYOHARA Takashi
452d286fbSkiyohara * All rights reserved.
552d286fbSkiyohara *
652d286fbSkiyohara * Redistribution and use in source and binary forms, with or without
752d286fbSkiyohara * modification, are permitted provided that the following conditions
852d286fbSkiyohara * are met:
952d286fbSkiyohara * 1. Redistributions of source code must retain the above copyright
1052d286fbSkiyohara * notice, this list of conditions and the following disclaimer.
1152d286fbSkiyohara * 2. Redistributions in binary form must reproduce the above copyright
1252d286fbSkiyohara * notice, this list of conditions and the following disclaimer in the
1352d286fbSkiyohara * documentation and/or other materials provided with the distribution.
1452d286fbSkiyohara *
1552d286fbSkiyohara * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1652d286fbSkiyohara * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1752d286fbSkiyohara * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1852d286fbSkiyohara * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
1952d286fbSkiyohara * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2052d286fbSkiyohara * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2152d286fbSkiyohara * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2252d286fbSkiyohara * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2352d286fbSkiyohara * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
2452d286fbSkiyohara * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2552d286fbSkiyohara * POSSIBILITY OF SUCH DAMAGE.
2652d286fbSkiyohara */
2752d286fbSkiyohara
2852d286fbSkiyohara #include <sys/cdefs.h>
29*49de48baSmartin __KERNEL_RCSID(0, "$NetBSD: mvsoc_intr.c,v 1.9 2014/02/22 16:14:38 martin Exp $");
301ec637abSkiyohara
311ec637abSkiyohara #include "opt_mvsoc.h"
3252d286fbSkiyohara
3352d286fbSkiyohara #define _INTR_PRIVATE
3452d286fbSkiyohara
3552d286fbSkiyohara #include <sys/param.h>
3652d286fbSkiyohara #include <sys/proc.h>
3752d286fbSkiyohara
3852d286fbSkiyohara #include <machine/intr.h>
3952d286fbSkiyohara
40*49de48baSmartin #include <arm/armreg.h>
4152d286fbSkiyohara #include <arm/cpu.h>
4252d286fbSkiyohara #include <arm/pic/picvar.h>
4352d286fbSkiyohara #include <arm/marvell/mvsocreg.h>
4452d286fbSkiyohara #include <arm/marvell/mvsocvar.h>
4552d286fbSkiyohara
46a9160f60Srkujawa
47a039bd91Smatt int (*find_pending_irqs)(void);
4852d286fbSkiyohara
4952d286fbSkiyohara static void mvsoc_bridge_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
5052d286fbSkiyohara static void mvsoc_bridge_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
5152d286fbSkiyohara static int mvsoc_bridge_pic_find_pending_irqs(struct pic_softc *);
5252d286fbSkiyohara static void mvsoc_bridge_pic_establish_irq(struct pic_softc *,
5352d286fbSkiyohara struct intrsource *);
5452d286fbSkiyohara static void mvsoc_bridge_pic_source_name(struct pic_softc *, int, char *,
5552d286fbSkiyohara size_t);
5652d286fbSkiyohara
5752d286fbSkiyohara static const char * const sources[] = {
5852d286fbSkiyohara "CPUSelfInt", "CPUTimer0IntReq", "CPUTimer1IntReq", "CPUWDTimerIntReq",
5952d286fbSkiyohara "AccessErr", "Bit64Err",
6052d286fbSkiyohara };
6152d286fbSkiyohara
6252d286fbSkiyohara static struct pic_ops mvsoc_bridge_picops = {
6352d286fbSkiyohara .pic_unblock_irqs = mvsoc_bridge_pic_unblock_irqs,
6452d286fbSkiyohara .pic_block_irqs = mvsoc_bridge_pic_block_irqs,
6552d286fbSkiyohara .pic_find_pending_irqs = mvsoc_bridge_pic_find_pending_irqs,
6652d286fbSkiyohara .pic_establish_irq = mvsoc_bridge_pic_establish_irq,
6752d286fbSkiyohara .pic_source_name = mvsoc_bridge_pic_source_name,
6852d286fbSkiyohara };
6952d286fbSkiyohara
7052d286fbSkiyohara struct pic_softc mvsoc_bridge_pic = {
7152d286fbSkiyohara .pic_ops = &mvsoc_bridge_picops,
7252d286fbSkiyohara .pic_maxsources = MVSOC_MLMB_MLMBI_NIRQ,
7352d286fbSkiyohara .pic_name = "mvsoc_bridge",
7452d286fbSkiyohara };
7552d286fbSkiyohara
7652d286fbSkiyohara
7752d286fbSkiyohara void
mvsoc_irq_handler(void * frame)7852d286fbSkiyohara mvsoc_irq_handler(void *frame)
7952d286fbSkiyohara {
8052d286fbSkiyohara struct cpu_info * const ci = curcpu();
8152d286fbSkiyohara const int oldipl = ci->ci_cpl;
8252d286fbSkiyohara const uint32_t oldipl_mask = __BIT(oldipl);
8352d286fbSkiyohara int ipl_mask = 0;
8452d286fbSkiyohara
856a66466fSmatt ci->ci_data.cpu_nintr++;
8652d286fbSkiyohara
8752d286fbSkiyohara ipl_mask = find_pending_irqs();
8852d286fbSkiyohara
8952d286fbSkiyohara /*
9052d286fbSkiyohara * Record the pending_ipls and deliver them if we can.
9152d286fbSkiyohara */
9252d286fbSkiyohara if ((ipl_mask & ~oldipl_mask) > oldipl_mask)
9352d286fbSkiyohara pic_do_pending_ints(I32_bit, oldipl, frame);
9452d286fbSkiyohara }
9552d286fbSkiyohara
9652d286fbSkiyohara /*
9752d286fbSkiyohara * Mbus-L to Mbus bridge
9852d286fbSkiyohara */
9952d286fbSkiyohara
10052d286fbSkiyohara void *
mvsoc_bridge_intr_establish(int ih,int ipl,int (* ih_func)(void *),void * arg)10152d286fbSkiyohara mvsoc_bridge_intr_establish(int ih, int ipl, int (*ih_func)(void *), void *arg)
10252d286fbSkiyohara {
10352d286fbSkiyohara
10421c11346Sjakllsch return intr_establish(mvsoc_bridge_pic.pic_irqbase + ih, ipl,
10521c11346Sjakllsch IST_LEVEL_HIGH, ih_func, arg);
10652d286fbSkiyohara }
10752d286fbSkiyohara
10852d286fbSkiyohara /* ARGSUSED */
10952d286fbSkiyohara static void
mvsoc_bridge_pic_unblock_irqs(struct pic_softc * pic,size_t irqbase,uint32_t irq_mask)11052d286fbSkiyohara mvsoc_bridge_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
11152d286fbSkiyohara uint32_t irq_mask)
11252d286fbSkiyohara {
11352d286fbSkiyohara
11452d286fbSkiyohara write_mlmbreg(MVSOC_MLMB_MLMBICR,
11552d286fbSkiyohara read_mlmbreg(MVSOC_MLMB_MLMBICR) & ~irq_mask);
11652d286fbSkiyohara write_mlmbreg(MVSOC_MLMB_MLMBIMR,
11752d286fbSkiyohara read_mlmbreg(MVSOC_MLMB_MLMBIMR) | irq_mask);
11852d286fbSkiyohara }
11952d286fbSkiyohara
12052d286fbSkiyohara /* ARGSUSED */
12152d286fbSkiyohara static void
mvsoc_bridge_pic_block_irqs(struct pic_softc * pic,size_t irqbase,uint32_t irq_mask)12252d286fbSkiyohara mvsoc_bridge_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
12352d286fbSkiyohara uint32_t irq_mask)
12452d286fbSkiyohara {
12552d286fbSkiyohara
12652d286fbSkiyohara write_mlmbreg(MVSOC_MLMB_MLMBIMR,
12752d286fbSkiyohara read_mlmbreg(MVSOC_MLMB_MLMBIMR) & ~irq_mask);
12852d286fbSkiyohara }
12952d286fbSkiyohara
13052d286fbSkiyohara static int
mvsoc_bridge_pic_find_pending_irqs(struct pic_softc * pic)13152d286fbSkiyohara mvsoc_bridge_pic_find_pending_irqs(struct pic_softc *pic)
13252d286fbSkiyohara {
13352d286fbSkiyohara uint32_t pending;
13452d286fbSkiyohara
13552d286fbSkiyohara pending =
13652d286fbSkiyohara read_mlmbreg(MVSOC_MLMB_MLMBICR) & read_mlmbreg(MVSOC_MLMB_MLMBIMR);
13794a0b335Sjakllsch
13852d286fbSkiyohara if (pending == 0)
13952d286fbSkiyohara return 0;
14094a0b335Sjakllsch
14194a0b335Sjakllsch return pic_mark_pending_sources(pic, 0, pending);
14252d286fbSkiyohara }
14352d286fbSkiyohara
14452d286fbSkiyohara /* ARGSUSED */
14552d286fbSkiyohara static void
mvsoc_bridge_pic_establish_irq(struct pic_softc * pic,struct intrsource * is)14652d286fbSkiyohara mvsoc_bridge_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
14752d286fbSkiyohara {
14852d286fbSkiyohara /* Nothing */
14952d286fbSkiyohara }
15052d286fbSkiyohara
15152d286fbSkiyohara static void
mvsoc_bridge_pic_source_name(struct pic_softc * pic,int irq,char * buf,size_t len)15252d286fbSkiyohara mvsoc_bridge_pic_source_name(struct pic_softc *pic, int irq, char *buf,
15352d286fbSkiyohara size_t len)
15452d286fbSkiyohara {
15552d286fbSkiyohara
15652d286fbSkiyohara strlcpy(buf, sources[irq], len);
15752d286fbSkiyohara }
158