<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://www.linux-mips.org/mediawiki/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://www.linux-mips.org/wiki?title=Linux_Interrupts&amp;feed=atom&amp;action=history</id>
		<title>Linux Interrupts - Revision history</title>
		<link rel="self" type="application/atom+xml" href="http://www.linux-mips.org/wiki?title=Linux_Interrupts&amp;feed=atom&amp;action=history"/>
		<link rel="alternate" type="text/html" href="http://www.linux-mips.org/wiki?title=Linux_Interrupts&amp;action=history"/>
		<updated>2013-05-22T11:19:44Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.20.2</generator>

	<entry>
		<id>//www.linux-mips.org/wiki?title=Linux_Interrupts&amp;diff=6243&amp;oldid=prev</id>
		<title>Slaz: /* CPU as an IRQ controller */</title>
		<link rel="alternate" type="text/html" href="http://www.linux-mips.org/wiki?title=Linux_Interrupts&amp;diff=6243&amp;oldid=prev"/>
				<updated>2006-03-23T05:24:01Z</updated>
		
		<summary type="html">&lt;p&gt;‎&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;CPU as an IRQ controller&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table class='diff diff-contentalign-left'&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
			&lt;tr style='vertical-align: top;'&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;← Older revision&lt;/td&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 05:24, 23 March 2006&lt;/td&gt;
			&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 22:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 22:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;== CPU as an IRQ controller ==&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;== CPU as an IRQ controller ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;MIPS processors include a simple interrupt controller.&amp;#160; In it's simplest case as implemented in the [[R2000]] it implements two ''software interrupts''.&amp;#160; &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;This &lt;/del&gt;are interrupts that can only be raised&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;MIPS processors include a simple interrupt controller.&amp;#160; In it's simplest case as implemented in the [[R2000]] it implements two ''software interrupts''.&amp;#160; &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;These &lt;/ins&gt;are interrupts that can only be raised by software setting the bit in the cause register and needs to be cleared by the interrupt handler.&amp;#160; Otherwise they will behave just like hardware interrupts.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;by software setting the bit in the cause register and needs to be cleared &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;by the interrupt handler&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;by the interrupt handler.&amp;#160; Otherwise they will behave just like hardware interrupts.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;In case of the [[R4000]] and most newer processors newer than the R4000 the IP7 bit in the cp0 status and cause registers doubles to serve the timer interrupt also.&amp;#160; That is the IP7 interrupt will be raised whenever the cop0 count and compare registers have the same value.&amp;#160; The exact mode of operation of the count register and the timer interrupt are often configurable by the CPU's mode bits.&amp;#160; Using IP7 as the timer interrupt typically also means this interrupt cannot sensibly used for any other purpose.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;In case of the [[R4000]] and most newer processors newer than the R4000 the IP7 bit in the cp0 status and cause registers doubles to serve the timer interrupt also.&amp;#160; That is the IP7 interrupt will be raised whenever the cop0 count and compare registers have the same value.&amp;#160; The exact mode of operation of the count register and the timer interrupt are often configurable by the CPU's mode bits.&amp;#160; Using IP7 as the timer interrupt typically also means this interrupt cannot sensibly used for any other purpose.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Slaz</name></author>	</entry>

	<entry>
		<id>//www.linux-mips.org/wiki?title=Linux_Interrupts&amp;diff=5511&amp;oldid=prev</id>
		<title>Ralf: Remove another Osprey reference</title>
		<link rel="alternate" type="text/html" href="http://www.linux-mips.org/wiki?title=Linux_Interrupts&amp;diff=5511&amp;oldid=prev"/>
				<updated>2005-06-02T12:13:10Z</updated>
		
		<summary type="html">&lt;p&gt;Remove another Osprey reference&lt;/p&gt;
&lt;table class='diff diff-contentalign-left'&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
			&lt;tr style='vertical-align: top;'&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;← Older revision&lt;/td&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 12:13, 2 June 2005&lt;/td&gt;
			&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 36:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 36:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;There are plenty of examples of how cascading interrupt works, such as the DDB5477. Here is a short summary:&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;There are plenty of examples of how cascading interrupt works, such as the DDB5477. Here is a short summary:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* Assign blocks of IRQ numbers to various interrupt controllers in the whole &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;&amp;#160;  &lt;/del&gt;system. For example, in the case of &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;the Osprey&lt;/del&gt;, CPU interrupts occupy IRQ 0 to 7. [[NEC_VR4100|Vr4181]] system interrupts occupy IRQ 8 to 39, and GPIO interrupts occupy 40 to 56. In most cases, the actual IRQ numbers do not matter, as long as the driver knows which IRQ number it should use. However, if you have an i8259 interrupt controller and an ISA bus, you should try to assign IRQ number 0 to 16 for the i8259 interrupts because it will make the legacy PC drivers happy. (Please note before ~12/08/2001 in version 2.4.16 of the Linux kernel, the 'i8259.c' file set the base vector to be 0x20. If you use the IRQ acknowledgement cycle to obtain the interrupt vector, you will get an IRQ number from 0x20 to 0x2f. You will then need to substract 0x20 from the return value to get the correct IRQ number.)&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* Assign blocks of IRQ numbers to various interrupt controllers in the whole system. For example, in the case of &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;Vr4181 systems&lt;/ins&gt;, CPU interrupts occupy IRQ 0 to 7. [[NEC_VR4100|Vr4181]] system interrupts occupy IRQ 8 to 39, and GPIO interrupts occupy 40 to 56. In most cases, the actual IRQ numbers do not matter, as long as the driver knows which IRQ number it should use. However, if you have an i8259 interrupt controller and an ISA bus, you should try to assign IRQ number 0 to 16 for the i8259 interrupts because it will make the legacy PC drivers happy. (Please note before ~12/08/2001 in version 2.4.16 of the Linux kernel, the 'i8259.c' file set the base vector to be 0x20. If you use the IRQ acknowledgement cycle to obtain the interrupt vector, you will get an IRQ number from 0x20 to 0x2f. You will then need to substract 0x20 from the return value to get the correct IRQ number.)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* Write the 'hw_irq_controller' member functinos for your specific controllers. Note that CPU and i8259 already have their code written. You just need to define appropriate CONFIG options for your board. See the next sub-section for more details about writing 'hw_irq_controller' member functions.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* Write the 'hw_irq_controller' member functinos for your specific controllers. Note that CPU and i8259 already have their code written. You just need to define appropriate CONFIG options for your board. See the next sub-section for more details about writing 'hw_irq_controller' member functions.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* In your IRQ setup routine, initialize all the controllers, usually by calling 'interrupt_controller_XXX_init()' functions.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* In your IRQ setup routine, initialize all the controllers, usually by calling 'interrupt_controller_XXX_init()' functions.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Ralf</name></author>	</entry>

	<entry>
		<id>//www.linux-mips.org/wiki?title=Linux_Interrupts&amp;diff=2462&amp;oldid=prev</id>
		<title>Ralf: Remove Osprey reference.</title>
		<link rel="alternate" type="text/html" href="http://www.linux-mips.org/wiki?title=Linux_Interrupts&amp;diff=2462&amp;oldid=prev"/>
				<updated>2005-06-02T12:11:11Z</updated>
		
		<summary type="html">&lt;p&gt;Remove Osprey reference.&lt;/p&gt;
&lt;table class='diff diff-contentalign-left'&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
			&lt;tr style='vertical-align: top;'&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;← Older revision&lt;/td&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 12:11, 2 June 2005&lt;/td&gt;
			&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 34:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 34:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;More than likely you will have more interrupt sources than those that can directly connect to the CPU interrupt pins. A second or even third-level interrupt controller may connect to one or more of those CPU pins. In that case, you have cascading interrupts.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;More than likely you will have more interrupt sources than those that can directly connect to the CPU interrupt pins. A second or even third-level interrupt controller may connect to one or more of those CPU pins. In that case, you have cascading interrupts.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;There are plenty of examples of how cascading interrupt works, such as the DDB5477 &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;and the Osprey&lt;/del&gt;. Here is a short summary:&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;There are plenty of examples of how cascading interrupt works, such as the DDB5477. Here is a short summary:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* Assign blocks of IRQ numbers to various interrupt controllers in the whole&amp;#160; &amp;#160; system. For example, in the case of the Osprey, CPU interrupts occupy IRQ 0 to 7. [[NEC_VR4100|Vr4181]] system interrupts occupy IRQ 8 to 39, and GPIO interrupts occupy 40 to 56. In most cases, the actual IRQ numbers do not matter, as long as the driver knows which IRQ number it should use. However, if you have an i8259 interrupt controller and an ISA bus, you should try to assign IRQ number 0 to 16 for the i8259 interrupts because it will make the legacy PC drivers happy. (Please note before ~12/08/2001 in version 2.4.16 of the Linux kernel, the 'i8259.c' file set the base vector to be 0x20. If you use the IRQ acknowledgement cycle to obtain the interrupt vector, you will get an IRQ number from 0x20 to 0x2f. You will then need to substract 0x20 from the return value to get the correct IRQ number.)&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* Assign blocks of IRQ numbers to various interrupt controllers in the whole&amp;#160; &amp;#160; system. For example, in the case of the Osprey, CPU interrupts occupy IRQ 0 to 7. [[NEC_VR4100|Vr4181]] system interrupts occupy IRQ 8 to 39, and GPIO interrupts occupy 40 to 56. In most cases, the actual IRQ numbers do not matter, as long as the driver knows which IRQ number it should use. However, if you have an i8259 interrupt controller and an ISA bus, you should try to assign IRQ number 0 to 16 for the i8259 interrupts because it will make the legacy PC drivers happy. (Please note before ~12/08/2001 in version 2.4.16 of the Linux kernel, the 'i8259.c' file set the base vector to be 0x20. If you use the IRQ acknowledgement cycle to obtain the interrupt vector, you will get an IRQ number from 0x20 to 0x2f. You will then need to substract 0x20 from the return value to get the correct IRQ number.)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Ralf</name></author>	</entry>

	<entry>
		<id>//www.linux-mips.org/wiki?title=Linux_Interrupts&amp;diff=2461&amp;oldid=prev</id>
		<title>Ralf: /* CPU as an IRQ controller */</title>
		<link rel="alternate" type="text/html" href="http://www.linux-mips.org/wiki?title=Linux_Interrupts&amp;diff=2461&amp;oldid=prev"/>
				<updated>2005-05-10T13:59:49Z</updated>
		
		<summary type="html">&lt;p&gt;‎&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;CPU as an IRQ controller&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table class='diff diff-contentalign-left'&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
			&lt;tr style='vertical-align: top;'&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;← Older revision&lt;/td&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 13:59, 10 May 2005&lt;/td&gt;
			&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 22:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 22:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;== CPU as an IRQ controller ==&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;== CPU as an IRQ controller ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;Most R4K-compatible &lt;/del&gt;MIPS &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;CPUs have the ability to support eight &lt;/del&gt;interrupt &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;sources&lt;/del&gt;. &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;The first &lt;/del&gt;two &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;are &lt;/del&gt;software interrupts&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;, and the last one is typically used for CPU counter interrupt&lt;/del&gt;. &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;Therefore you &lt;/del&gt;can &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;have up &lt;/del&gt;to &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;five external &lt;/del&gt;interrupt &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;sources&lt;/del&gt;.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;MIPS &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;processors include a simple &lt;/ins&gt;interrupt &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;controller&lt;/ins&gt;. &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt; In it's simplest case as implemented in the [[R2000]] it implements &lt;/ins&gt;two &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;''&lt;/ins&gt;software interrupts&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;''&lt;/ins&gt;. &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt; This are interrupts that &lt;/ins&gt;can &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;only be raised&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;#160;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;by software setting the bit in the cause register and needs &lt;/ins&gt;to &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;be cleared by the &lt;/ins&gt;interrupt &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;handler&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;#160;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;by the interrupt handler.&amp;#160; Otherwise they will behave just like hardware interrupts&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;Luckily if &lt;/del&gt;the &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;CPU is &lt;/del&gt;the &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;only IRQ controller in &lt;/del&gt;the &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;system, you are done! The hw_irq_handler code is written &lt;/del&gt;in &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;arch/mips/kernel/irq_cpu.c file. All you have &lt;/del&gt;to &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;do is to define &amp;quot;CONFIG_IRQ_CPU&amp;quot; for your machine&lt;/del&gt;. &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;And in your irq setup routine make sure you call mips_cpu_irq_init(0). This call will initialize &lt;/del&gt;the interrupt &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;descriptor &lt;/del&gt;and &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;set up &lt;/del&gt;the &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;IRQ numbers to range from 0 to 7&lt;/del&gt;.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;In case of &lt;/ins&gt;the &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;[[R4000]] and most newer processors newer than &lt;/ins&gt;the &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;R4000 &lt;/ins&gt;the &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;IP7 bit &lt;/ins&gt;in &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;the cp0 status and cause registers doubles &lt;/ins&gt;to &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;serve the timer interrupt also&lt;/ins&gt;. &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt; That is &lt;/ins&gt;the &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;IP7 &lt;/ins&gt;interrupt &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;will be raised whenever the cop0 count &lt;/ins&gt;and &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;compare registers have &lt;/ins&gt;the &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;same value.&amp;#160; The exact mode of operation of the count register and the timer interrupt are often configurable by the CPU's mode bits.&amp;#160; Using IP7 as the timer interrupt typically also means this interrupt cannot sensibly used for any other purpose&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;You can also find a matching &lt;/del&gt;interrupt &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;dispatching &lt;/del&gt;code in &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;this file&lt;/del&gt;.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;So here's how to initialize the timer &lt;/ins&gt;interrupt &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;in a typical system.&amp;#160; First define &amp;quot;CONFIG_IRQ_CPU&amp;quot; for your machine to enable compile the support &lt;/ins&gt;code &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;into the kernel.&amp;#160; Then &lt;/ins&gt;in &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;your &amp;lt;code&amp;gt;arch_init_irq()&amp;lt;/code&amp;gt; just call &amp;lt;code&amp;gt;mips_cpu_irq_init(x)&amp;lt;/code&amp;gt; where for &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; you put the first of the 8 interrupt numbers you're going to assign to the CPU's interrupt controller&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Set up cascading interrupts&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Set up cascading interrupts&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Ralf</name></author>	</entry>

	<entry>
		<id>//www.linux-mips.org/wiki?title=Linux_Interrupts&amp;diff=2381&amp;oldid=prev</id>
		<title>67.176.99.141 at 00:14, 6 May 2005</title>
		<link rel="alternate" type="text/html" href="http://www.linux-mips.org/wiki?title=Linux_Interrupts&amp;diff=2381&amp;oldid=prev"/>
				<updated>2005-05-06T00:14:25Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class='diff diff-contentalign-left'&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
			&lt;tr style='vertical-align: top;'&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;← Older revision&lt;/td&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 00:14, 6 May 2005&lt;/td&gt;
			&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;It &lt;/del&gt;you followed the previous steps, most likely you will see kernel hanging at the BogusMIPS calibration step. The reason is simple: The interrupt code is not there and jiffies are never updated. Therefore the calibration can never be done.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;If &lt;/ins&gt;you followed the previous steps, most likely you will see kernel hanging at the BogusMIPS calibration step. The reason is simple: The interrupt code is not there and jiffies are never updated. Therefore the calibration can never be done.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Before you start writing interrupt code, it really pays to study the hardware first. Pay particular attention to identify all interrupt sources, their corresponding controllers and how they are routed.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Before you start writing interrupt code, it really pays to study the hardware first. Pay particular attention to identify all interrupt sources, their corresponding controllers and how they are routed.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>67.176.99.141</name></author>	</entry>

	<entry>
		<id>//www.linux-mips.org/wiki?title=Linux_Interrupts&amp;diff=2371&amp;oldid=prev</id>
		<title>Alec v at 21:18, 30 January 2005</title>
		<link rel="alternate" type="text/html" href="http://www.linux-mips.org/wiki?title=Linux_Interrupts&amp;diff=2371&amp;oldid=prev"/>
				<updated>2005-01-30T21:18:33Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class='diff diff-contentalign-left'&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
			&lt;tr style='vertical-align: top;'&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;← Older revision&lt;/td&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Revision as of 21:18, 30 January 2005&lt;/td&gt;
			&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 34:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 34:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;There are plenty of examples of how cascading interrupt works, such as the DDB5477 and the Osprey. Here is a short summary:&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;There are plenty of examples of how cascading interrupt works, such as the DDB5477 and the Osprey. Here is a short summary:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* Assign blocks of IRQ numbers to various interrupt controllers in the whole&amp;#160; &amp;#160; system. For example, in the case of the Osprey, CPU interrupts occupy IRQ 0 to 7. Vr4181 system interrupts occupy IRQ 8 to 39, and GPIO interrupts occupy 40 to 56. In most cases, the actual IRQ numbers do not matter, as long as the driver knows which IRQ number it should use. However, if you have an i8259 interrupt controller and an ISA bus, you should try to assign IRQ number 0 to 16 for the i8259 interrupts because it will make the legacy PC drivers happy. (Please note before ~12/08/2001 in version 2.4.16 of the Linux kernel, the 'i8259.c' file set the base vector to be 0x20. If you use the IRQ acknowledgement cycle to obtain the interrupt vector, you will get an IRQ number from 0x20 to 0x2f. You will then need to substract 0x20 from the return value to get the correct IRQ number.)&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* Assign blocks of IRQ numbers to various interrupt controllers in the whole&amp;#160; &amp;#160; system. For example, in the case of the Osprey, CPU interrupts occupy IRQ 0 to 7. &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;[[NEC_VR4100|&lt;/ins&gt;Vr4181&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;]] &lt;/ins&gt;system interrupts occupy IRQ 8 to 39, and GPIO interrupts occupy 40 to 56. In most cases, the actual IRQ numbers do not matter, as long as the driver knows which IRQ number it should use. However, if you have an i8259 interrupt controller and an ISA bus, you should try to assign IRQ number 0 to 16 for the i8259 interrupts because it will make the legacy PC drivers happy. (Please note before ~12/08/2001 in version 2.4.16 of the Linux kernel, the 'i8259.c' file set the base vector to be 0x20. If you use the IRQ acknowledgement cycle to obtain the interrupt vector, you will get an IRQ number from 0x20 to 0x2f. You will then need to substract 0x20 from the return value to get the correct IRQ number.)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* Write the 'hw_irq_controller' member functinos for your specific controllers. Note that CPU and i8259 already have their code written. You just need to define appropriate CONFIG options for your board. See the next sub-section for more details about writing 'hw_irq_controller' member functions.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* Write the 'hw_irq_controller' member functinos for your specific controllers. Note that CPU and i8259 already have their code written. You just need to define appropriate CONFIG options for your board. See the next sub-section for more details about writing 'hw_irq_controller' member functions.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* In your IRQ setup routine, initialize all the controllers, usually by calling 'interrupt_controller_XXX_init()' functions.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* In your IRQ setup routine, initialize all the controllers, usually by calling 'interrupt_controller_XXX_init()' functions.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Alec v</name></author>	</entry>

	<entry>
		<id>//www.linux-mips.org/wiki?title=Linux_Interrupts&amp;diff=1423&amp;oldid=prev</id>
		<title>Ralf at 23:06, 8 November 2004</title>
		<link rel="alternate" type="text/html" href="http://www.linux-mips.org/wiki?title=Linux_Interrupts&amp;diff=1423&amp;oldid=prev"/>
				<updated>2004-11-08T23:06:45Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;It you followed the previous steps, most likely you will see kernel hanging at the BogusMIPS calibration step. The reason is simple: The interrupt code is not there and jiffies are never updated. Therefore the calibration can never be done.&lt;br /&gt;
&lt;br /&gt;
Before you start writing interrupt code, it really pays to study the hardware first. Pay particular attention to identify all interrupt sources, their corresponding controllers and how they are routed.&lt;br /&gt;
&lt;br /&gt;
Then you need to come up with a strategy, which typically includes:&lt;br /&gt;
* a static interrupt routing map&lt;br /&gt;
* a list of interrupt sources&lt;br /&gt;
* a list of their corresponding controllers&lt;br /&gt;
* how interrupt controllers cascade from each other&lt;br /&gt;
&lt;br /&gt;
== Interrupt code overview ==&lt;br /&gt;
&lt;br /&gt;
To completely service an interrupt, four different pieces of code work together:&lt;br /&gt;
&lt;br /&gt;
; IRQ detection/dispatching : This is typically assembly code in a file called 'int_handler.S'. Sometimes there is also secondary-level dispatching code written in C for complicated IRQ detection. The end result is that we identify and select a single IRQ source, represented by an integer, and then pass it to function 'do_IRQ()'.&lt;br /&gt;
; do_IRQ() : do_IRQ() is provided in the 'arch/mips/kernel/irq.c' file. It provides a common framework for IRQ handling. It invokes the individual IRQ controller code to enable/disable a particular interrupt. It calls the driver supplied interrupt handling routine that does the real processing.&lt;br /&gt;
; hw_irq_handler : It is a structure associated with each IRQ source. The structure is a collection of function pointers, which tells do_IRQ() how it should deal with this particular IRQ.&lt;br /&gt;
; driver interrupt handling code : The code that does the real job.&lt;br /&gt;
&lt;br /&gt;
Obviously for our porting purposes we need to write IRQ detection/disptaching code and the hw_irq_handler code for any new IRQ controller used in the system. In addition, there is also IRQ setup and initialization code.&lt;br /&gt;
 &lt;br /&gt;
== CPU as an IRQ controller ==&lt;br /&gt;
&lt;br /&gt;
Most R4K-compatible MIPS CPUs have the ability to support eight interrupt sources. The first two are software interrupts, and the last one is typically used for CPU counter interrupt. Therefore you can have up to five external interrupt sources.&lt;br /&gt;
&lt;br /&gt;
Luckily if the CPU is the only IRQ controller in the system, you are done! The hw_irq_handler code is written in arch/mips/kernel/irq_cpu.c file. All you have to do is to define &amp;quot;CONFIG_IRQ_CPU&amp;quot; for your machine. And in your irq setup routine make sure you call mips_cpu_irq_init(0). This call will initialize the interrupt descriptor and set up the IRQ numbers to range from 0 to 7.&lt;br /&gt;
&lt;br /&gt;
You can also find a matching interrupt dispatching code in this file.&lt;br /&gt;
&lt;br /&gt;
Set up cascading interrupts&lt;br /&gt;
&lt;br /&gt;
More than likely you will have more interrupt sources than those that can directly connect to the CPU interrupt pins. A second or even third-level interrupt controller may connect to one or more of those CPU pins. In that case, you have cascading interrupts.&lt;br /&gt;
&lt;br /&gt;
There are plenty of examples of how cascading interrupt works, such as the DDB5477 and the Osprey. Here is a short summary:&lt;br /&gt;
&lt;br /&gt;
* Assign blocks of IRQ numbers to various interrupt controllers in the whole    system. For example, in the case of the Osprey, CPU interrupts occupy IRQ 0 to 7. Vr4181 system interrupts occupy IRQ 8 to 39, and GPIO interrupts occupy 40 to 56. In most cases, the actual IRQ numbers do not matter, as long as the driver knows which IRQ number it should use. However, if you have an i8259 interrupt controller and an ISA bus, you should try to assign IRQ number 0 to 16 for the i8259 interrupts because it will make the legacy PC drivers happy. (Please note before ~12/08/2001 in version 2.4.16 of the Linux kernel, the 'i8259.c' file set the base vector to be 0x20. If you use the IRQ acknowledgement cycle to obtain the interrupt vector, you will get an IRQ number from 0x20 to 0x2f. You will then need to substract 0x20 from the return value to get the correct IRQ number.)&lt;br /&gt;
* Write the 'hw_irq_controller' member functinos for your specific controllers. Note that CPU and i8259 already have their code written. You just need to define appropriate CONFIG options for your board. See the next sub-section for more details about writing 'hw_irq_controller' member functions.&lt;br /&gt;
* In your IRQ setup routine, initialize all the controllers, usually by calling 'interrupt_controller_XXX_init()' functions.&lt;br /&gt;
* In your IRQ setup routine, setup the cascading IRQs. This setup will enable interrupts for the upper interrupt controller so that the lower-level interrupts can cascade through once they are enabled. A typical way of doing this is to have a dummy 'irqaction struct' and setup as follows:&lt;br /&gt;
 &lt;br /&gt;
        static struct irqaction cascade =&lt;br /&gt;
                { no_action, SA_INTERRUPT, 0, &amp;quot;cascade&amp;quot;, NULL, NULL };&lt;br /&gt;
 &lt;br /&gt;
        extern int setup_irq(unsigned int irq, struct irqaction *irqaction);&lt;br /&gt;
 &lt;br /&gt;
        void __init &amp;lt;my&amp;gt;_irq_init(void)&lt;br /&gt;
        {&lt;br /&gt;
                ....&lt;br /&gt;
                setup_irq(CPU_IP3, &amp;amp;cascade);&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
* You need to expand your interrupt dispatching code properly to identify the added interrupt sources. If the code is simple enough, you can do it in the same int_handler.S file. If it is more complicated, you may do it in a separate C function (such as in the DDB5476 board).&lt;br /&gt;
&lt;br /&gt;
== The hw_irq_controller struct ==&lt;br /&gt;
&lt;br /&gt;
The 'hw_irq_controller structure' is a defined in the 'include/linux/irq.h' file as an alias for the 'hw_interrupt_type' structure.&lt;br /&gt;
&lt;br /&gt;
    struct hw_interrupt_type {&lt;br /&gt;
            const char * typename;&lt;br /&gt;
            unsigned int (*startup)(unsigned int irq);&lt;br /&gt;
            void (*shutdown)(unsigned int irq);&lt;br /&gt;
            void (*enable)(unsigned int irq);&lt;br /&gt;
            void (*disable)(unsigned int irq);&lt;br /&gt;
            void (*ack)(unsigned int irq);&lt;br /&gt;
            void (*end)(unsigned int irq);&lt;br /&gt;
            void (*set_affinity)(unsigned int irq, unsigned long mask);&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
The 'arch/mips/kernel/irq_cpu.c' is a good sample code to write 'hw_irq_controller' member functions. Here are some more programming notes for each of these functions:&lt;br /&gt;
&lt;br /&gt;
    const char * typename;&lt;br /&gt;
        Controller name. Will be displayed under /proc/interrupts.&lt;br /&gt;
    unsigned int (*startup)(unsigned int irq);&lt;br /&gt;
        Invoked when request_irq() or setup_irq are called. You need to enable&lt;br /&gt;
        this interrupt here. Other than that you may also want to do some&lt;br /&gt;
        IRQ-specific initialization (such as turning on power for this&lt;br /&gt;
        interrupt, perhaps).&lt;br /&gt;
    void (*shutdown)(unsigned int irq);&lt;br /&gt;
        Invoked when free_irq() is called. You need to disable this interrupt&lt;br /&gt;
        and perhaps some other IRQ-specific cleanup.&lt;br /&gt;
    void (*enable)(unsigned int irq) and void (*disable)(unsigned int irq)&lt;br /&gt;
        They are used to implement enable_irq(), disable_irq() and&lt;br /&gt;
        disable_irq_nosync(), which in turn are used by driver code.&lt;br /&gt;
    void (*ack)(unsigned int irq)&lt;br /&gt;
        ack() is invoked at the beginning of do_IRQ() when we want to&lt;br /&gt;
        acknoledge an interrupt. I think you need also to disable this&lt;br /&gt;
        interrupt here so that you don't get recursive interrupts on the same&lt;br /&gt;
        interrupt source. [HELP: can someone confirm?]&lt;br /&gt;
    void (*end)(unsigned int irq)&lt;br /&gt;
        This is called by do_IRQ() after it has handled this interrupt. If you&lt;br /&gt;
        disabled interrupt in ack() function, you should enable it here. [HELP:&lt;br /&gt;
        generally what else we should do here?]&lt;br /&gt;
    void (*set_affinity)(unsigned int irq, unsigned long mask)&lt;br /&gt;
        This is used in SMP machines to set up interrupt handling affinity with&lt;br /&gt;
        certain CPUs. [TODO] [HELP]&lt;br /&gt;
&lt;br /&gt;
== The IRQ initialization code ==&lt;br /&gt;
&lt;br /&gt;
The IRQ initialization is done in 'init_IRQ()'. Currently it is supplied by each individual board. In the future, it will probably be a MIPS common routine, which will further invoke a board-specific function, board_irq_init(). board_irq_init will be a function pointer that &amp;lt;my_board&amp;gt;_setup() function needs to assign propoer value.&lt;br /&gt;
&lt;br /&gt;
In any case, the following is a skeleton code for a normal init_IRQ() routine.&lt;br /&gt;
&lt;br /&gt;
    extern asmlinkage void vr4181_handle_irq(void);&lt;br /&gt;
    extern void breakpoint(void);&lt;br /&gt;
    extern int setup_irq(unsigned int irq, struct irqaction *irqaction);&lt;br /&gt;
    extern void mips_cpu_irq_init(u32 irq_base);&lt;br /&gt;
    extern void init_generic_irq(void);&lt;br /&gt;
 &lt;br /&gt;
    static struct irqaction cascade =&lt;br /&gt;
            { no_action, SA_INTERRUPT, 0, &amp;quot;cascade&amp;quot;, NULL, NULL };&lt;br /&gt;
    static struct irqaction reserved =&lt;br /&gt;
            { no_action, SA_INTERRUPT, 0, &amp;quot;reserved&amp;quot;, NULL, NULL };&lt;br /&gt;
    static struct irqaction error_irq =&lt;br /&gt;
            { error_action, SA_INTERRUPT, 0, &amp;quot;error&amp;quot;, NULL, NULL };&lt;br /&gt;
 &lt;br /&gt;
    void __init init_IRQ(void)&lt;br /&gt;
    {&lt;br /&gt;
            int i;&lt;br /&gt;
            extern irq_desc_t irq_desc[];&lt;br /&gt;
 &lt;br /&gt;
            /* hardware initialization code */&lt;br /&gt;
            ....&lt;br /&gt;
 &lt;br /&gt;
            /* this is the routine defined in int_handler.S file */&lt;br /&gt;
            set_except_vector(0, my_irq_dispatcher);&lt;br /&gt;
 &lt;br /&gt;
            /* setup the default irq descriptor */&lt;br /&gt;
            init_generic_irq();&lt;br /&gt;
 &lt;br /&gt;
            /* init all interrupt controllers */&lt;br /&gt;
            mips_cpu_irq_init(CPU_IRQ_BASE);&lt;br /&gt;
            ....&lt;br /&gt;
 &lt;br /&gt;
            /* set up cascading IRQ */&lt;br /&gt;
            setup_irq(CPU_IRQ_IP3, &amp;amp;cascade);&lt;br /&gt;
 &lt;br /&gt;
            /* set up reserved IRQ so that others can not mistakingly request&lt;br /&gt;
             * it later.&lt;br /&gt;
             */&lt;br /&gt;
            setup_irq(CPU_IRQ_IP4, &amp;amp;reserved);&lt;br /&gt;
 &lt;br /&gt;
    #ifdef CONFIG_DEBUG&lt;br /&gt;
            /* setup debug IRQ so that if that interrupt happens, we can&lt;br /&gt;
             * capture it.&lt;br /&gt;
             */&lt;br /&gt;
            setup_irq(CPU_IRQ_IP4, &amp;amp;error_irq);&lt;br /&gt;
    #endif&lt;br /&gt;
 &lt;br /&gt;
    #ifdef CONFIG_REMOTE_DEBUG&lt;br /&gt;
            printk(&amp;quot;Setting debug traps - please connect the remote debugger.\n&amp;quot;);&lt;br /&gt;
            set_debug_traps();&lt;br /&gt;
            breakpoint();&lt;br /&gt;
    #endif&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
== Final notes ==&lt;br /&gt;
&lt;br /&gt;
What is described in this chapter is what is so-called new style interrupt handling. We used to have three different ways to handle interrupts: new style (CONFIG_NEW_IRQ), the old style (CONFIG_ROTTEN_IRQ) and board-private ad hoc routines. New style is now the only valid method since [[October]]-[[2002]].&lt;br /&gt;
&lt;br /&gt;
Next page: [[System Time and Timer]]&lt;/div&gt;</summary>
		<author><name>Ralf</name></author>	</entry>

	</feed>