Changeset 5ad38eac in rtems
- Timestamp:
- 10/12/14 19:10:00 (9 years ago)
- Branches:
- 4.11, 5, master
- Children:
- ff8922c
- Parents:
- 5fdb72a0
- git-author:
- Joel Sherrill <joel.sherrill@…> (10/12/14 19:10:00)
- git-committer:
- Joel Sherrill <joel.sherrill@…> (10/13/14 15:33:31)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
c/src/lib/libbsp/powerpc/shared/clock/clock.c
r5fdb72a0 r5ad38eac 43 43 volatile uint32_t Clock_driver_ticks = 0; 44 44 45 rtems_device_major_number rtems_clock_major = UINT32_MAX;46 47 rtems_device_minor_number rtems_clock_minor = UINT32_MAX;48 49 45 static uint32_t ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX; 50 46 … … 55 51 static void ppc_clock_no_tick(void) 56 52 { 57 53 /* Do nothing */ 58 54 } 59 55 60 56 static void (*ppc_clock_tick)(void) = ppc_clock_no_tick; 61 57 62 static int ppc_clock_exception_handler( BSP_Exception_frame *frame, unsigned number) 63 { 64 uint32_t delta = ppc_clock_decrementer_value; 65 uint32_t next = ppc_clock_next_time_base; 66 uint32_t dec = 0; 67 uint32_t now = 0; 68 uint32_t msr = 0; 69 70 do { 71 /* Increment clock ticks */ 72 Clock_driver_ticks += 1; 73 74 /* Enable external exceptions */ 75 msr = ppc_external_exceptions_enable(); 76 77 /* Call clock ticker */ 78 ppc_clock_tick(); 79 80 /* Restore machine state */ 81 ppc_external_exceptions_disable( msr); 82 83 /* Next time base */ 84 next += delta; 85 86 /* Current time */ 87 now = ppc_time_base(); 88 89 /* New decrementer value */ 90 dec = next - now; 91 } while (dec > delta); 92 93 /* Set decrementer */ 94 ppc_set_decrementer_register( dec); 95 96 /* Expected next time base */ 97 ppc_clock_next_time_base = next; 98 99 return 0; 100 } 101 102 static int ppc_clock_exception_handler_first( BSP_Exception_frame *frame, unsigned number) 103 { 104 /* We have to clear the first pending decrementer exception this way */ 105 106 if (ppc_decrementer_register() >= 0x80000000) { 107 ppc_clock_exception_handler( frame, number); 108 } 109 110 ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler); 111 112 return 0; 113 } 114 115 static int ppc_clock_exception_handler_booke( BSP_Exception_frame *frame, unsigned number) 116 { 117 uint32_t msr; 118 119 /* Acknowledge decrementer request */ 120 PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_TSR, BOOKE_TSR_DIS); 121 122 /* Increment clock ticks */ 123 Clock_driver_ticks += 1; 124 125 /* Enable external exceptions */ 126 msr = ppc_external_exceptions_enable(); 127 128 /* Call clock ticker */ 129 ppc_clock_tick(); 130 131 /* Restore machine state */ 132 ppc_external_exceptions_disable( msr); 133 134 return 0; 58 static int ppc_clock_exception_handler( 59 BSP_Exception_frame *frame, 60 unsigned number 61 ) 62 { 63 uint32_t delta = ppc_clock_decrementer_value; 64 uint32_t next = ppc_clock_next_time_base; 65 uint32_t dec = 0; 66 uint32_t now = 0; 67 uint32_t msr = 0; 68 69 do { 70 /* Increment clock ticks */ 71 Clock_driver_ticks += 1; 72 73 /* Enable external exceptions */ 74 msr = ppc_external_exceptions_enable(); 75 76 /* Call clock ticker */ 77 ppc_clock_tick(); 78 79 /* Restore machine state */ 80 ppc_external_exceptions_disable( msr); 81 82 /* Next time base */ 83 next += delta; 84 85 /* Current time */ 86 now = ppc_time_base(); 87 88 /* New decrementer value */ 89 dec = next - now; 90 } while (dec > delta); 91 92 /* Set decrementer */ 93 ppc_set_decrementer_register( dec); 94 95 /* Expected next time base */ 96 ppc_clock_next_time_base = next; 97 98 return 0; 99 } 100 101 static int ppc_clock_exception_handler_first( 102 BSP_Exception_frame *frame, 103 unsigned number 104 ) 105 { 106 /* We have to clear the first pending decrementer exception this way */ 107 108 if (ppc_decrementer_register() >= 0x80000000) { 109 ppc_clock_exception_handler( frame, number); 110 } 111 112 ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler); 113 114 return 0; 115 } 116 117 static int ppc_clock_exception_handler_booke( 118 BSP_Exception_frame *frame, 119 unsigned number 120 ) 121 { 122 uint32_t msr; 123 124 /* Acknowledge decrementer request */ 125 PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_TSR, BOOKE_TSR_DIS); 126 127 /* Increment clock ticks */ 128 Clock_driver_ticks += 1; 129 130 /* Enable external exceptions */ 131 msr = ppc_external_exceptions_enable(); 132 133 /* Call clock ticker */ 134 ppc_clock_tick(); 135 136 /* Restore machine state */ 137 ppc_external_exceptions_disable( msr); 138 139 return 0; 135 140 } 136 141 137 142 static int ppc_clock_exception_handler_ppc405(BSP_Exception_frame *frame, unsigned number) 138 143 { 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 144 uint32_t msr; 145 146 /* Acknowledge PIT request */ 147 PPC_SET_SPECIAL_PURPOSE_REGISTER(PPC405_TSR, BOOKE_TSR_DIS); 148 149 /* Increment clock ticks */ 150 Clock_driver_ticks += 1; 151 152 /* Enable external exceptions */ 153 msr = ppc_external_exceptions_enable(); 154 155 /* Call clock ticker */ 156 ppc_clock_tick(); 157 158 /* Restore machine state */ 159 ppc_external_exceptions_disable(msr); 160 161 return 0; 157 162 } 158 163 159 164 static uint32_t ppc_clock_nanoseconds_since_last_tick(void) 160 165 { 161 162 163 164 165 166 uint64_t k = ppc_clock_factor; 167 uint32_t c = ppc_decrementer_register(); 168 uint32_t i = ppc_clock_decrementer_value + 1; 169 170 return (uint32_t) (((i - c) * k) >> 32); 166 171 } 167 172 168 173 static uint32_t ppc_clock_nanoseconds_since_last_tick_ppc405(void) 169 174 { 170 171 172 173 174 175 176 177 178 175 uint64_t k = ppc_clock_factor; 176 uint32_t i = ppc_clock_decrementer_value; 177 uint32_t c = i - PPC_SPECIAL_PURPOSE_REGISTER(PPC405_PIT); 178 179 if ((PPC_SPECIAL_PURPOSE_REGISTER(PPC405_TSR) & BOOKE_TSR_DIS) != 0) { 180 c = i - PPC_SPECIAL_PURPOSE_REGISTER(PPC405_PIT) + i; 181 } 182 183 return (uint32_t) ((c * k) >> 32); 179 184 } 180 185 181 186 void Clock_exit(void) 182 187 { 183 184 185 186 187 188 } 189 190 rtems_device_driver Clock_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)191 { 192 uint64_t frequency = bsp_time_base_frequency; 193 uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); 194 uint32_t interval = (uint32_t) ((frequency * us_per_tick) / 1000000); 195 196 /* Make major/minor available to others such as shared memory driver */ 197 rtems_clock_major = major;198 rtems_clock_minor = minor;199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 } 188 /* Set the decrementer to the maximum value */ 189 ppc_set_decrementer_register( PPC_CLOCK_DECREMENTER_MAX); 190 191 /* Use default clock handler */ 192 ppc_clock_tick = ppc_clock_no_tick; 193 } 194 195 rtems_device_driver Clock_initialize( 196 rtems_device_major_number major, 197 rtems_device_minor_number minor, 198 void *arg 199 ) 200 { 201 uint64_t frequency = bsp_time_base_frequency; 202 uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); 203 uint32_t interval = (uint32_t) ((frequency * us_per_tick) / 1000000); 204 205 /* 206 * Set default ticker. 207 * 208 * The function rtems_clock_tick() returns a status code. This value 209 * will be discarded since the RTEMS documentation claims that it is 210 * always successful. 211 */ 212 ppc_clock_tick = (void (*)(void)) rtems_clock_tick; 213 214 /* Factor for nano seconds extension */ 215 ppc_clock_factor = (1000000000ULL << 32) / frequency; 216 217 if (ppc_cpu_is_bookE() != PPC_BOOKE_405) { 218 /* Decrementer value */ 219 ppc_clock_decrementer_value = interval - 1; 220 221 /* Check decrementer value */ 222 if (ppc_clock_decrementer_value == 0) { 223 ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX; 224 RTEMS_SYSLOG_ERROR( "decrementer value would be zero, will be set to maximum value instead\n"); 225 } 226 227 /* Set the nanoseconds since last tick handler */ 228 rtems_clock_set_nanoseconds_extension( ppc_clock_nanoseconds_since_last_tick); 229 230 if (ppc_cpu_is_bookE()) { 231 /* Set decrementer auto-reload value */ 232 PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_DECAR, ppc_clock_decrementer_value); 233 234 /* Install exception handler */ 235 ppc_exc_set_handler( ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_booke); 236 237 /* Enable decrementer and auto-reload */ 238 PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( BOOKE_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE); 239 } else { 240 /* Here the decrementer value is actually the interval */ 241 ++ppc_clock_decrementer_value; 242 243 /* Initialize next time base */ 244 ppc_clock_next_time_base = ppc_time_base() + ppc_clock_decrementer_value; 245 246 /* Install exception handler */ 247 ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler_first); 248 } 249 250 /* Set the decrementer value */ 251 ppc_set_decrementer_register( ppc_clock_decrementer_value); 252 } else { 253 /* PIT interval value */ 254 ppc_clock_decrementer_value = interval; 255 256 /* Set the nanoseconds since last tick handler */ 257 rtems_clock_set_nanoseconds_extension(ppc_clock_nanoseconds_since_last_tick_ppc405); 258 259 /* Install exception handler */ 260 ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_ppc405); 261 262 /* Enable PIT and auto-reload */ 263 PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS(PPC405_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE); 264 265 /* Set PIT auto-reload and initial value */ 266 PPC_SET_SPECIAL_PURPOSE_REGISTER(PPC405_PIT, interval); 267 } 268 269 return RTEMS_SUCCESSFUL; 270 }
Note: See TracChangeset
for help on using the changeset viewer.