Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/sh/cchips/hd6446x/hd64461.c
15116 views
1
/*
2
* Copyright (C) 2000 YAEGASHI Takeshi
3
* Hitachi HD64461 companion chip support
4
*/
5
6
#include <linux/sched.h>
7
#include <linux/module.h>
8
#include <linux/kernel.h>
9
#include <linux/param.h>
10
#include <linux/interrupt.h>
11
#include <linux/init.h>
12
#include <linux/irq.h>
13
#include <linux/io.h>
14
#include <asm/irq.h>
15
#include <asm/hd64461.h>
16
17
/* This belongs in cpu specific */
18
#define INTC_ICR1 0xA4140010UL
19
20
static void hd64461_mask_irq(struct irq_data *data)
21
{
22
unsigned int irq = data->irq;
23
unsigned short nimr;
24
unsigned short mask = 1 << (irq - HD64461_IRQBASE);
25
26
nimr = __raw_readw(HD64461_NIMR);
27
nimr |= mask;
28
__raw_writew(nimr, HD64461_NIMR);
29
}
30
31
static void hd64461_unmask_irq(struct irq_data *data)
32
{
33
unsigned int irq = data->irq;
34
unsigned short nimr;
35
unsigned short mask = 1 << (irq - HD64461_IRQBASE);
36
37
nimr = __raw_readw(HD64461_NIMR);
38
nimr &= ~mask;
39
__raw_writew(nimr, HD64461_NIMR);
40
}
41
42
static void hd64461_mask_and_ack_irq(struct irq_data *data)
43
{
44
hd64461_mask_irq(data);
45
46
#ifdef CONFIG_HD64461_ENABLER
47
if (data->irq == HD64461_IRQBASE + 13)
48
__raw_writeb(0x00, HD64461_PCC1CSCR);
49
#endif
50
}
51
52
static struct irq_chip hd64461_irq_chip = {
53
.name = "HD64461-IRQ",
54
.irq_mask = hd64461_mask_irq,
55
.irq_mask_ack = hd64461_mask_and_ack_irq,
56
.irq_unmask = hd64461_unmask_irq,
57
};
58
59
static void hd64461_irq_demux(unsigned int irq, struct irq_desc *desc)
60
{
61
unsigned short intv = __raw_readw(HD64461_NIRR);
62
unsigned int ext_irq = HD64461_IRQBASE;
63
64
intv &= (1 << HD64461_IRQ_NUM) - 1;
65
66
for (; intv; intv >>= 1, ext_irq++) {
67
if (!(intv & 1))
68
continue;
69
70
generic_handle_irq(ext_irq);
71
}
72
}
73
74
int __init setup_hd64461(void)
75
{
76
int i, nid = cpu_to_node(boot_cpu_data);
77
78
if (!MACH_HD64461)
79
return 0;
80
81
printk(KERN_INFO
82
"HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n",
83
HD64461_IOBASE, CONFIG_HD64461_IRQ, HD64461_IRQBASE,
84
HD64461_IRQBASE + 15);
85
86
/* Should be at processor specific part.. */
87
#if defined(CONFIG_CPU_SUBTYPE_SH7709)
88
__raw_writew(0x2240, INTC_ICR1);
89
#endif
90
__raw_writew(0xffff, HD64461_NIMR);
91
92
/* IRQ 80 -> 95 belongs to HD64461 */
93
for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) {
94
unsigned int irq;
95
96
irq = create_irq_nr(i, nid);
97
if (unlikely(irq == 0)) {
98
pr_err("%s: failed hooking irq %d for HD64461\n",
99
__func__, i);
100
return -EBUSY;
101
}
102
103
if (unlikely(irq != i)) {
104
pr_err("%s: got irq %d but wanted %d, bailing.\n",
105
__func__, irq, i);
106
destroy_irq(irq);
107
return -EINVAL;
108
}
109
110
irq_set_chip_and_handler(i, &hd64461_irq_chip,
111
handle_level_irq);
112
}
113
114
irq_set_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux);
115
irq_set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW);
116
117
#ifdef CONFIG_HD64461_ENABLER
118
printk(KERN_INFO "HD64461: enabling PCMCIA devices\n");
119
__raw_writeb(0x4c, HD64461_PCC1CSCIER);
120
__raw_writeb(0x00, HD64461_PCC1CSCR);
121
#endif
122
123
return 0;
124
}
125
126
module_init(setup_hd64461);
127
128