Example #1
0
File: clock.c Project: AoLaD/rtems
static int ppc_clock_exception_handler(
  BSP_Exception_frame *frame,
  unsigned number
)
{
  uint32_t delta = ppc_clock_decrementer_value;
  uint32_t next = ppc_clock_next_time_base;
  uint32_t dec = 0;
  uint32_t now = 0;
  uint32_t msr = 0;

  do {
    /* Increment clock ticks */
    Clock_driver_ticks += 1;

    /* Enable external exceptions */
    msr = ppc_external_exceptions_enable();

    /* Call clock ticker  */
    ppc_clock_tick();

    /* Restore machine state */
    ppc_external_exceptions_disable( msr);

    /* Next time base */
    next += delta;

    /* Current time */
    now = ppc_time_base();

    /* New decrementer value */
    dec = next - now;
  } while (dec > delta);

  /* Set decrementer */
  ppc_set_decrementer_register( dec);

  /* Expected next time base */
  ppc_clock_next_time_base = next;

  return 0;
}
Example #2
0
rtems_device_driver Clock_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
	/* Current CPU type */
	ppc_cpu_id_t cpu_type = get_ppc_cpu_type();

	/* Make major/minor available to others such as shared memory driver */
	rtems_clock_major = major;
	rtems_clock_minor = minor;

	/*
	 * Set default ticker.
	 *
	 * The function rtems_clock_tick() returns a status code.  This value
	 * will be discarded since the RTEMS documentation claims that it is
	 * always successful.
	 */
	ppc_clock_tick = (void (*)(void)) rtems_clock_tick;

	/* Set the decrementer to the maximum value */
	ppc_set_decrementer_register( PPC_CLOCK_DECREMENTER_MAX);

	/* Decrementer value */
	ppc_clock_decrementer_value = bsp_clicks_per_usec * rtems_configuration_get_microseconds_per_tick() - 1;

	/* Check decrementer value */
	if (ppc_clock_decrementer_value == 0) {
		ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX;
		RTEMS_SYSLOG_ERROR( "decrementer value would be zero, will be set to maximum value instead\n");
	}

	/* Set the nanoseconds since last tick handler */
	rtems_clock_set_nanoseconds_extension( ppc_clock_nanoseconds_since_last_tick);

	if (ppc_cpu_is_bookE()) {
		/* Set decrementer auto-reload value */
		PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_DECAR, ppc_clock_decrementer_value);

		/* Install exception handler */
		ppc_exc_set_handler( ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_booke);

		/* Enable decrementer and auto-reload */
		PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( BOOKE_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE);
	} else if (cpu_type == PPC_e300c2 || cpu_type == PPC_e300c3) {
		/* TODO: Not tested for e300c2 */

		/* Enable auto-reload */
		PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( HID0, 0x00000040);

		/* Install exception handler */
		ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler_e300);
	} else {
		/* Here the decrementer value is actually the interval */
		++ppc_clock_decrementer_value;

		/* Initialize next time base */
		ppc_clock_next_time_base = ppc_time_base() + ppc_clock_decrementer_value;

		/* Install exception handler */
		ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler_first);
	}

	/* Set the decrementer value */
	ppc_set_decrementer_register( ppc_clock_decrementer_value);

	return RTEMS_SUCCESSFUL;
}
Example #3
0
static uint32_t t32mppc_clock_get_timecount(struct timecounter *tc)
{
  return ppc_time_base();
}
Example #4
0
File: clock.c Project: AoLaD/rtems
rtems_device_driver Clock_initialize(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void *arg
)
{
  uint64_t frequency = bsp_time_base_frequency;
  uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
  uint32_t interval = (uint32_t) ((frequency * us_per_tick) / 1000000);

  /*
   * Set default ticker.
   */
  ppc_clock_tick = rtems_timecounter_tick;

  if (ppc_cpu_is_bookE() != PPC_BOOKE_405) {
    /* Decrementer value */
    ppc_clock_decrementer_value = interval - 1;

    /* Check decrementer value */
    if (ppc_clock_decrementer_value == 0) {
      ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX;
      RTEMS_SYSLOG_ERROR( "decrementer value would be zero, will be set to maximum value instead\n");
    }
    if (ppc_cpu_is_bookE()) {
      /* Set decrementer auto-reload value */
      PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_DECAR, ppc_clock_decrementer_value);

      /* Install exception handler */
      ppc_exc_set_handler( ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_booke);

      /* Enable decrementer and auto-reload */
      PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( BOOKE_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE);
    } else {
      /* Here the decrementer value is actually the interval */
      ++ppc_clock_decrementer_value;

      /* Initialize next time base */
      ppc_clock_next_time_base = ppc_time_base() + ppc_clock_decrementer_value;

      /* Install exception handler */
      ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler_first);
    }

    /* Set the decrementer value */
    ppc_set_decrementer_register( ppc_clock_decrementer_value);
  } else {
    /* PIT interval value */
    ppc_clock_decrementer_value = interval;

    /* Install exception handler */
    ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_ppc405);

    /* Enable PIT and auto-reload */
    PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS(PPC405_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE);

    /* Set PIT auto-reload and initial value */
    PPC_SET_SPECIAL_PURPOSE_REGISTER(PPC405_PIT, interval);
  }

  /* Install timecounter */
  ppc_tc.tc_get_timecount = ppc_get_timecount;
  ppc_tc.tc_counter_mask = 0xffffffff;
  ppc_tc.tc_frequency = frequency;
  ppc_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
  rtems_timecounter_install(&ppc_tc);

  return RTEMS_SUCCESSFUL;
}