aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c46
-rw-r--r--arch/powerpc/sysdev/mpic.c16
-rw-r--r--arch/powerpc/sysdev/xilinx_intc.c117
3 files changed, 116 insertions, 63 deletions
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index afe8dbc964aa..5c64ccd402e2 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -208,52 +208,6 @@ static int __init of_add_fixed_phys(void)
208arch_initcall(of_add_fixed_phys); 208arch_initcall(of_add_fixed_phys);
209#endif /* CONFIG_FIXED_PHY */ 209#endif /* CONFIG_FIXED_PHY */
210 210
211#ifdef CONFIG_PPC_83xx
212static int __init mpc83xx_wdt_init(void)
213{
214 struct resource r;
215 struct device_node *np;
216 struct platform_device *dev;
217 u32 freq = fsl_get_sys_freq();
218 int ret;
219
220 np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt");
221
222 if (!np) {
223 ret = -ENODEV;
224 goto nodev;
225 }
226
227 memset(&r, 0, sizeof(r));
228
229 ret = of_address_to_resource(np, 0, &r);
230 if (ret)
231 goto err;
232
233 dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1);
234 if (IS_ERR(dev)) {
235 ret = PTR_ERR(dev);
236 goto err;
237 }
238
239 ret = platform_device_add_data(dev, &freq, sizeof(freq));
240 if (ret)
241 goto unreg;
242
243 of_node_put(np);
244 return 0;
245
246unreg:
247 platform_device_unregister(dev);
248err:
249 of_node_put(np);
250nodev:
251 return ret;
252}
253
254arch_initcall(mpc83xx_wdt_init);
255#endif
256
257static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type) 211static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
258{ 212{
259 if (!phy_type) 213 if (!phy_type)
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 21b956701596..0efc12d1a3d7 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1057,13 +1057,6 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1057 memset(mpic, 0, sizeof(struct mpic)); 1057 memset(mpic, 0, sizeof(struct mpic));
1058 mpic->name = name; 1058 mpic->name = name;
1059 1059
1060 mpic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
1061 isu_size, &mpic_host_ops,
1062 flags & MPIC_LARGE_VECTORS ? 2048 : 256);
1063 if (mpic->irqhost == NULL)
1064 return NULL;
1065
1066 mpic->irqhost->host_data = mpic;
1067 mpic->hc_irq = mpic_irq_chip; 1060 mpic->hc_irq = mpic_irq_chip;
1068 mpic->hc_irq.typename = name; 1061 mpic->hc_irq.typename = name;
1069 if (flags & MPIC_PRIMARY) 1062 if (flags & MPIC_PRIMARY)
@@ -1213,6 +1206,15 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1213 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); 1206 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
1214 mpic->isu_mask = (1 << mpic->isu_shift) - 1; 1207 mpic->isu_mask = (1 << mpic->isu_shift) - 1;
1215 1208
1209 mpic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
1210 isu_size ? isu_size : mpic->num_sources,
1211 &mpic_host_ops,
1212 flags & MPIC_LARGE_VECTORS ? 2048 : 256);
1213 if (mpic->irqhost == NULL)
1214 return NULL;
1215
1216 mpic->irqhost->host_data = mpic;
1217
1216 /* Display version */ 1218 /* Display version */
1217 switch (greg_feature & MPIC_GREG_FEATURE_VERSION_MASK) { 1219 switch (greg_feature & MPIC_GREG_FEATURE_VERSION_MASK) {
1218 case 1: 1220 case 1:
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
index a22e1a2df1af..c658b413c9b4 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -41,8 +41,32 @@
41 41
42static struct irq_host *master_irqhost; 42static struct irq_host *master_irqhost;
43 43
44#define XILINX_INTC_MAXIRQS (32)
45
46/* The following table allows the interrupt type, edge or level,
47 * to be cached after being read from the device tree until the interrupt
48 * is mapped
49 */
50static int xilinx_intc_typetable[XILINX_INTC_MAXIRQS];
51
52/* Map the interrupt type from the device tree to the interrupt types
53 * used by the interrupt subsystem
54 */
55static unsigned char xilinx_intc_map_senses[] = {
56 IRQ_TYPE_EDGE_RISING,
57 IRQ_TYPE_EDGE_FALLING,
58 IRQ_TYPE_LEVEL_HIGH,
59 IRQ_TYPE_LEVEL_LOW,
60};
61
44/* 62/*
45 * IRQ Chip operations 63 * The interrupt controller is setup such that it doesn't work well with
64 * the level interrupt handler in the kernel because the handler acks the
65 * interrupt before calling the application interrupt handler. To deal with
66 * that, we use 2 different irq chips so that different functions can be
67 * used for level and edge type interrupts.
68 *
69 * IRQ Chip common (across level and edge) operations
46 */ 70 */
47static void xilinx_intc_mask(unsigned int virq) 71static void xilinx_intc_mask(unsigned int virq)
48{ 72{
@@ -52,15 +76,54 @@ static void xilinx_intc_mask(unsigned int virq)
52 out_be32(regs + XINTC_CIE, 1 << irq); 76 out_be32(regs + XINTC_CIE, 1 << irq);
53} 77}
54 78
55static void xilinx_intc_unmask(unsigned int virq) 79static int xilinx_intc_set_type(unsigned int virq, unsigned int flow_type)
80{
81 struct irq_desc *desc = get_irq_desc(virq);
82
83 desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
84 desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
85 if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
86 desc->status |= IRQ_LEVEL;
87 return 0;
88}
89
90/*
91 * IRQ Chip level operations
92 */
93static void xilinx_intc_level_unmask(unsigned int virq)
56{ 94{
57 int irq = virq_to_hw(virq); 95 int irq = virq_to_hw(virq);
58 void * regs = get_irq_chip_data(virq); 96 void * regs = get_irq_chip_data(virq);
59 pr_debug("unmask: %d\n", irq); 97 pr_debug("unmask: %d\n", irq);
60 out_be32(regs + XINTC_SIE, 1 << irq); 98 out_be32(regs + XINTC_SIE, 1 << irq);
99
100 /* ack level irqs because they can't be acked during
101 * ack function since the handle_level_irq function
102 * acks the irq before calling the inerrupt handler
103 */
104 out_be32(regs + XINTC_IAR, 1 << irq);
61} 105}
62 106
63static void xilinx_intc_ack(unsigned int virq) 107static struct irq_chip xilinx_intc_level_irqchip = {
108 .typename = "Xilinx Level INTC",
109 .mask = xilinx_intc_mask,
110 .mask_ack = xilinx_intc_mask,
111 .unmask = xilinx_intc_level_unmask,
112 .set_type = xilinx_intc_set_type,
113};
114
115/*
116 * IRQ Chip edge operations
117 */
118static void xilinx_intc_edge_unmask(unsigned int virq)
119{
120 int irq = virq_to_hw(virq);
121 void *regs = get_irq_chip_data(virq);
122 pr_debug("unmask: %d\n", irq);
123 out_be32(regs + XINTC_SIE, 1 << irq);
124}
125
126static void xilinx_intc_edge_ack(unsigned int virq)
64{ 127{
65 int irq = virq_to_hw(virq); 128 int irq = virq_to_hw(virq);
66 void * regs = get_irq_chip_data(virq); 129 void * regs = get_irq_chip_data(virq);
@@ -68,27 +131,60 @@ static void xilinx_intc_ack(unsigned int virq)
68 out_be32(regs + XINTC_IAR, 1 << irq); 131 out_be32(regs + XINTC_IAR, 1 << irq);
69} 132}
70 133
71static struct irq_chip xilinx_intc_irqchip = { 134static struct irq_chip xilinx_intc_edge_irqchip = {
72 .typename = "Xilinx INTC", 135 .typename = "Xilinx Edge INTC",
73 .mask = xilinx_intc_mask, 136 .mask = xilinx_intc_mask,
74 .unmask = xilinx_intc_unmask, 137 .unmask = xilinx_intc_edge_unmask,
75 .ack = xilinx_intc_ack, 138 .ack = xilinx_intc_edge_ack,
139 .set_type = xilinx_intc_set_type,
76}; 140};
77 141
78/* 142/*
79 * IRQ Host operations 143 * IRQ Host operations
80 */ 144 */
145
146/**
147 * xilinx_intc_xlate - translate virq# from device tree interrupts property
148 */
149static int xilinx_intc_xlate(struct irq_host *h, struct device_node *ct,
150 u32 *intspec, unsigned int intsize,
151 irq_hw_number_t *out_hwirq,
152 unsigned int *out_flags)
153{
154 if ((intsize < 2) || (intspec[0] >= XILINX_INTC_MAXIRQS))
155 return -EINVAL;
156
157 /* keep a copy of the interrupt type til the interrupt is mapped
158 */
159 xilinx_intc_typetable[intspec[0]] = xilinx_intc_map_senses[intspec[1]];
160
161 /* Xilinx uses 2 interrupt entries, the 1st being the h/w
162 * interrupt number, the 2nd being the interrupt type, edge or level
163 */
164 *out_hwirq = intspec[0];
165 *out_flags = xilinx_intc_map_senses[intspec[1]];
166
167 return 0;
168}
81static int xilinx_intc_map(struct irq_host *h, unsigned int virq, 169static int xilinx_intc_map(struct irq_host *h, unsigned int virq,
82 irq_hw_number_t irq) 170 irq_hw_number_t irq)
83{ 171{
84 set_irq_chip_data(virq, h->host_data); 172 set_irq_chip_data(virq, h->host_data);
85 set_irq_chip_and_handler(virq, &xilinx_intc_irqchip, handle_level_irq); 173
86 set_irq_type(virq, IRQ_TYPE_NONE); 174 if (xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_HIGH ||
175 xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_LOW) {
176 set_irq_chip_and_handler(virq, &xilinx_intc_level_irqchip,
177 handle_level_irq);
178 } else {
179 set_irq_chip_and_handler(virq, &xilinx_intc_edge_irqchip,
180 handle_edge_irq);
181 }
87 return 0; 182 return 0;
88} 183}
89 184
90static struct irq_host_ops xilinx_intc_ops = { 185static struct irq_host_ops xilinx_intc_ops = {
91 .map = xilinx_intc_map, 186 .map = xilinx_intc_map,
187 .xlate = xilinx_intc_xlate,
92}; 188};
93 189
94struct irq_host * __init 190struct irq_host * __init
@@ -116,7 +212,8 @@ xilinx_intc_init(struct device_node *np)
116 out_be32(regs + XINTC_MER, 0x3UL); /* Turn on the Master Enable. */ 212 out_be32(regs + XINTC_MER, 0x3UL); /* Turn on the Master Enable. */
117 213
118 /* Allocate and initialize an irq_host structure. */ 214 /* Allocate and initialize an irq_host structure. */
119 irq = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, 32, &xilinx_intc_ops, -1); 215 irq = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, XILINX_INTC_MAXIRQS,
216 &xilinx_intc_ops, -1);
120 if (!irq) 217 if (!irq)
121 panic(__FILE__ ": Cannot allocate IRQ host\n"); 218 panic(__FILE__ ": Cannot allocate IRQ host\n");
122 irq->host_data = regs; 219 irq->host_data = regs;