00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include <arch/arm.h>
00048 #include <dev/irqreg.h>
00049
00050 #ifndef NUT_IRQPRI_TC1
00051 #define NUT_IRQPRI_TC1 4
00052 #endif
00053
00054 static int TimerCounter1IrqCtl(int cmd, void *param);
00055
00056 IRQ_HANDLER sig_TC1 = {
00057 #ifdef NUT_PERFMON
00058 0,
00059 #endif
00060 NULL,
00061 NULL,
00062 TimerCounter1IrqCtl
00063 };
00064
00068 static u_int dummy;
00069 static void TimerCounter1IrqEntry(void) __attribute__ ((naked));
00070 void TimerCounter1IrqEntry(void)
00071 {
00072 IRQ_ENTRY();
00073 #ifdef NUT_PERFMON
00074 sig_TC1.ir_count++;
00075 #endif
00076 dummy = inr(TC1_SR);
00077 if (sig_TC1.ir_handler) {
00078 (sig_TC1.ir_handler) (sig_TC1.ir_arg);
00079 }
00080 IRQ_EXIT();
00081 }
00082
00100 static int TimerCounter1IrqCtl(int cmd, void *param)
00101 {
00102 int rc = 0;
00103 u_int *ival = (u_int *)param;
00104 int enabled = inr(AIC_IMR) & _BV(TC1_ID);
00105
00106
00107 if (enabled) {
00108 outr(AIC_IDCR, _BV(TC1_ID));
00109 }
00110 switch(cmd) {
00111 case NUT_IRQCTL_INIT:
00112
00113 outr(AIC_SVR(TC1_ID), (unsigned int)TimerCounter1IrqEntry);
00114
00115 outr(AIC_SMR(TC1_ID), AIC_SRCTYPE_INT_EDGE_TRIGGERED | NUT_IRQPRI_TC1);
00116
00117 outr(AIC_ICCR, _BV(TC1_ID));
00118
00119 enabled = 0;
00120 break;
00121 case NUT_IRQCTL_STATUS:
00122 if (enabled) {
00123 *ival |= 1;
00124 }
00125 else {
00126 *ival &= ~1;
00127 }
00128 break;
00129 case NUT_IRQCTL_ENABLE:
00130 enabled = 1;
00131 break;
00132 case NUT_IRQCTL_DISABLE:
00133 enabled = 0;
00134 break;
00135 case NUT_IRQCTL_GETMODE:
00136 {
00137 u_int val = inr(AIC_SMR(TC1_ID)) & AIC_SRCTYPE;
00138 if (val == AIC_SRCTYPE_INT_LEVEL_SENSITIVE || val == AIC_SRCTYPE_EXT_HIGH_LEVEL) {
00139 *ival = NUT_IRQMODE_LEVEL;
00140 } else {
00141 *ival = NUT_IRQMODE_EDGE;
00142 }
00143 }
00144 break;
00145 case NUT_IRQCTL_SETMODE:
00146 if (*ival == NUT_IRQMODE_LEVEL) {
00147 outr(AIC_SMR(TC1_ID), (inr(AIC_SMR(TC1_ID)) & ~AIC_SRCTYPE) | AIC_SRCTYPE_INT_LEVEL_SENSITIVE);
00148 } else if (*ival == NUT_IRQMODE_EDGE) {
00149 outr(AIC_SMR(TC1_ID), (inr(AIC_SMR(TC1_ID)) & ~AIC_SRCTYPE) | AIC_SRCTYPE_INT_EDGE_TRIGGERED);
00150 } else {
00151 rc = -1;
00152 }
00153 break;
00154 case NUT_IRQCTL_GETPRIO:
00155 *ival = inr(AIC_SMR(TC1_ID)) & AIC_PRIOR;
00156 break;
00157 case NUT_IRQCTL_SETPRIO:
00158 outr(AIC_SMR(TC1_ID), (inr(AIC_SMR(TC1_ID)) & ~AIC_PRIOR) | *ival);
00159 break;
00160 #ifdef NUT_PERFMON
00161 case NUT_IRQCTL_GETCOUNT:
00162 *ival = (u_int)sig_TC1.ir_count;
00163 sig_TC1.ir_count = 0;
00164 break;
00165 #endif
00166 default:
00167 rc = -1;
00168 break;
00169 }
00170
00171
00172 if (enabled) {
00173 outr(AIC_IECR, _BV(TC1_ID));
00174 }
00175 return rc;
00176 }