xref: /netbsd-src/sys/arch/rs6000/rs6000/pic_iocc.c (revision d206c3458b7848902ac12dfb5de8f3a16c6f4067)
1*d206c345Sthorpej /*	$NetBSD: pic_iocc.c,v 1.6 2020/11/21 15:52:32 thorpej Exp $	*/
268fe5b6fSgarbled 
368fe5b6fSgarbled /*-
468fe5b6fSgarbled  * Copyright (c) 2007 The NetBSD Foundation, Inc.
568fe5b6fSgarbled  * All rights reserved.
668fe5b6fSgarbled  *
768fe5b6fSgarbled  * This code is derived from software contributed to The NetBSD Foundation
868fe5b6fSgarbled  * by Tim Rightnour
968fe5b6fSgarbled  *
1068fe5b6fSgarbled  * Redistribution and use in source and binary forms, with or without
1168fe5b6fSgarbled  * modification, are permitted provided that the following conditions
1268fe5b6fSgarbled  * are met:
1368fe5b6fSgarbled  * 1. Redistributions of source code must retain the above copyright
1468fe5b6fSgarbled  *    notice, this list of conditions and the following disclaimer.
1568fe5b6fSgarbled  * 2. Redistributions in binary form must reproduce the above copyright
1668fe5b6fSgarbled  *    notice, this list of conditions and the following disclaimer in the
1768fe5b6fSgarbled  *    documentation and/or other materials provided with the distribution.
1868fe5b6fSgarbled  *
1968fe5b6fSgarbled  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2068fe5b6fSgarbled  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2168fe5b6fSgarbled  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2268fe5b6fSgarbled  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2368fe5b6fSgarbled  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2468fe5b6fSgarbled  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2568fe5b6fSgarbled  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2668fe5b6fSgarbled  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2768fe5b6fSgarbled  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2868fe5b6fSgarbled  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2968fe5b6fSgarbled  * POSSIBILITY OF SUCH DAMAGE.
3068fe5b6fSgarbled  */
3168fe5b6fSgarbled 
3268fe5b6fSgarbled #include <sys/cdefs.h>
33*d206c345Sthorpej __KERNEL_RCSID(0, "$NetBSD: pic_iocc.c,v 1.6 2020/11/21 15:52:32 thorpej Exp $");
3468fe5b6fSgarbled 
3568fe5b6fSgarbled #include <sys/param.h>
36*d206c345Sthorpej #include <sys/kmem.h>
3768fe5b6fSgarbled #include <sys/kernel.h>
38d6c3db71Sdyoung #include <sys/bus.h>
3968fe5b6fSgarbled 
4068fe5b6fSgarbled #include <uvm/uvm_extern.h>
4168fe5b6fSgarbled 
4268fe5b6fSgarbled #include <machine/pio.h>
4368fe5b6fSgarbled #include <machine/intr.h>
4468fe5b6fSgarbled #include <machine/iocc.h>
4568fe5b6fSgarbled 
4668fe5b6fSgarbled #include <arch/powerpc/pic/picvar.h>
4768fe5b6fSgarbled 
4868fe5b6fSgarbled struct pic_ops *setup_iocc(void);
4968fe5b6fSgarbled 
5068fe5b6fSgarbled static void iocc_set_priority(int, int, int);
5168fe5b6fSgarbled static int iocc_get_irq(struct pic_ops *, int);
5268fe5b6fSgarbled static void iocc_enable_irq(struct pic_ops *, int, int);
5368fe5b6fSgarbled static void iocc_ack_irq(struct pic_ops *, int);
5468fe5b6fSgarbled static void iocc_disable_irq(struct pic_ops *, int);
5568fe5b6fSgarbled 
5668fe5b6fSgarbled struct pic_ops *
setup_iocc(void)5768fe5b6fSgarbled setup_iocc(void)
5868fe5b6fSgarbled {
5968fe5b6fSgarbled 	struct pic_ops *pic;
6068fe5b6fSgarbled 	int i;
6168fe5b6fSgarbled 
62*d206c345Sthorpej 	pic = kmem_alloc(sizeof(struct pic_ops), KM_SLEEP);
6368fe5b6fSgarbled 	pic->pic_numintrs = 16;
6468fe5b6fSgarbled 	pic->pic_cookie = (void *)NULL;
6568fe5b6fSgarbled 	pic->pic_enable_irq = iocc_enable_irq;
6668fe5b6fSgarbled 	pic->pic_reenable_irq = iocc_enable_irq;
6768fe5b6fSgarbled 	pic->pic_disable_irq = iocc_disable_irq;
6868fe5b6fSgarbled 	pic->pic_get_irq = iocc_get_irq;
6968fe5b6fSgarbled 	pic->pic_ack_irq = iocc_ack_irq;
7068fe5b6fSgarbled 	pic->pic_establish_irq = dummy_pic_establish_intr;
7168fe5b6fSgarbled 	pic->pic_finish_setup = NULL;
7268fe5b6fSgarbled 	strcpy(pic->pic_name, "iocc");
7368fe5b6fSgarbled 	pic_add(pic);
7468fe5b6fSgarbled 
7568fe5b6fSgarbled 	/* set all priorities as high */
7668fe5b6fSgarbled 	for (i=0; i < pic->pic_numintrs; i++)
7768fe5b6fSgarbled 		iocc_set_priority(0, 0, i);
7868fe5b6fSgarbled 	return(pic);
7968fe5b6fSgarbled }
8068fe5b6fSgarbled 
8168fe5b6fSgarbled /*
8268fe5b6fSgarbled  * the IOCC IER is a bitmask of pending IRQs, where only 0-15 are valid
8368fe5b6fSgarbled  */
8468fe5b6fSgarbled static int
iocc_get_irq(struct pic_ops * pic,int mode)8568fe5b6fSgarbled iocc_get_irq(struct pic_ops *pic, int mode)
8668fe5b6fSgarbled {
8768fe5b6fSgarbled         int irq;
8868fe5b6fSgarbled         uint32_t rv = 0;
8968fe5b6fSgarbled 
9068fe5b6fSgarbled         rv = in32rb(RS6000_BUS_SPACE_IO + IOCC_IRR);
9168fe5b6fSgarbled         if (rv == 0)
9268fe5b6fSgarbled                 return 255;
9368fe5b6fSgarbled 
94930ad812Smatt         irq = 31 - __builtin_clz(rv);
9568fe5b6fSgarbled         if (irq >= 0 && irq < 16)
9668fe5b6fSgarbled                 return irq;
9768fe5b6fSgarbled         return 255;
9868fe5b6fSgarbled }
9968fe5b6fSgarbled 
10068fe5b6fSgarbled /* enable an IRQ on the IOCC */
10168fe5b6fSgarbled static void
iocc_enable_irq(struct pic_ops * pic,int irq,int type)10268fe5b6fSgarbled iocc_enable_irq(struct pic_ops *pic, int irq, int type)
10368fe5b6fSgarbled {
10468fe5b6fSgarbled         uint32_t mask;
10568fe5b6fSgarbled 
10668fe5b6fSgarbled         mask = in32rb(RS6000_BUS_SPACE_IO + IOCC_IEE);
10768fe5b6fSgarbled         mask |= 1 << irq;
10868fe5b6fSgarbled         out32rb(RS6000_BUS_SPACE_IO + IOCC_IEE, mask);
10968fe5b6fSgarbled }
11068fe5b6fSgarbled 
11168fe5b6fSgarbled /* disable an IRQ on the IOCC */
11268fe5b6fSgarbled static void
iocc_disable_irq(struct pic_ops * pic,int irq)11368fe5b6fSgarbled iocc_disable_irq(struct pic_ops *pic, int irq)
11468fe5b6fSgarbled {
11568fe5b6fSgarbled         uint32_t mask;
11668fe5b6fSgarbled 
11768fe5b6fSgarbled         mask = in32rb(RS6000_BUS_SPACE_IO + IOCC_IEE);
11868fe5b6fSgarbled         mask &= ~(1 << irq);
11968fe5b6fSgarbled         out32rb(RS6000_BUS_SPACE_IO + IOCC_IEE, mask);
12068fe5b6fSgarbled }
12168fe5b6fSgarbled 
12268fe5b6fSgarbled /* Issue an EOI to the IOCC */
12368fe5b6fSgarbled static void
iocc_ack_irq(struct pic_ops * pic,int irq)12468fe5b6fSgarbled iocc_ack_irq(struct pic_ops *pic, int irq)
12568fe5b6fSgarbled {
12668fe5b6fSgarbled         out32rb(RS6000_BUS_SPACE_IO + IOCC_EOI(irq), 0x1); /* val is ignored */
12768fe5b6fSgarbled }
12868fe5b6fSgarbled 
12968fe5b6fSgarbled /* set interrupt priority and destination */
13068fe5b6fSgarbled static void
iocc_set_priority(int cpu,int pri,int irq)13168fe5b6fSgarbled iocc_set_priority(int cpu, int pri, int irq)
13268fe5b6fSgarbled {
13368fe5b6fSgarbled         uint32_t x;
13468fe5b6fSgarbled 
13568fe5b6fSgarbled         x = pri;
13668fe5b6fSgarbled         x |= cpu<<8;
13768fe5b6fSgarbled         out32rb(RS6000_BUS_SPACE_IO + IOCC_XIVR(irq), x);
13868fe5b6fSgarbled }
139