Commit e9f6cb25 authored by Charles E. Youse's avatar Charles E. Youse Committed by Anas Nashif
Browse files

drivers/timer/loapic_timer.c: migrate to new local APIC accessors



More clearly differentiate MVIC vs. APIC timer code, and use new APIC
accessors in include/drivers/loapic.h. Remove extraneous comments, and
other light cleanup work.

This driver is in need of a serious overhaul -- despite appearing to
have support for TICKLESS_KERNEL and DEVICE_POWER_MANAGEMENT, bitrot
has taken its toll and the driver will not build with these enabled.
These should be removed or made to work... but not in this patch.

Old x2APIC-related accessors in kernel_arch_func.h are eliminated.

Signed-off-by: default avatarCharles E. Youse <charles.youse@intel.com>
parent aaecce4b
Loading
Loading
Loading
Loading
+0 −14
Original line number Diff line number Diff line
@@ -67,20 +67,6 @@ z_set_thread_return_value(struct k_thread *thread, unsigned int value)

extern void k_cpu_atomic_idle(unsigned int key);

#ifdef CONFIG_X2APIC
#define MSR_X2APIC_BASE 0x00000800

static inline u32_t read_x2apic(unsigned int reg)
{
	return z_x86_msr_read(MSR_X2APIC_BASE + reg);
}

static inline void write_x2apic(unsigned int reg, u32_t val)
{
	z_x86_msr_write(MSR_X2APIC_BASE + reg, val);
}
#endif

extern FUNC_NORETURN void z_x86_userspace_enter(k_thread_entry_t user_entry,
					       void *p1, void *p2, void *p3,
					       u32_t stack_end,
+14 −0
Original line number Diff line number Diff line
@@ -64,6 +64,20 @@ u32_t loapic_suspend_buf[LOPIC_SUSPEND_BITS_REQD / 32] = {0};
static u32_t loapic_device_power_state = DEVICE_PM_ACTIVE_STATE;
#endif

/*
 * this should not be a function at all, really, it should be
 * hand-coded in include/drivers/sysapic.h. but for now it remains
 * a function, just moved here from drivers/timer/loapic_timer.c
 * where it REALLY didn't belong.
 */

#ifdef CONFIG_X2APIC
void z_x2apic_eoi(void)
{
	x86_write_x2apic(LOAPIC_EOI, 0);
}
#endif

/**
 *
 * @brief Initialize the Local APIC or xAPIC
+50 −90
Original line number Diff line number Diff line
@@ -8,15 +8,6 @@
 * @file
 * @brief Intel Local APIC timer driver
 *
 * This module implements a kernel device driver for the Intel local APIC
 * timer device. It provides the standard "system clock driver" interfaces for
 * use with P6 (PentiumPro, II, III) and P7 (Pentium4) family processors.
 * The local APIC timer contains a 32-bit programmable down counter that
 * generates an interrupt for use by the local processor when it reaches zero.
 * The time base is derived from the processor's bus clock, divided by a value
 * specified in the divide configuration register. After reset, the timer is
 * initialized to zero.
 *
 * Typically, the local APIC timer operates in periodic mode. That is, after
 * its down counter reaches zero and triggers a timer interrupt, it is reset
 * to its initial value and the down counting continues.
@@ -91,32 +82,6 @@
#define LOAPIC_TIMER_PERIODIC 0x00020000 /* Timer Mode: Periodic */


/* Helpful macros and inlines for programming timer.
 * We support both standard LOAPIC, and MVIC which has a similar
 * interface
 */

#if defined(CONFIG_LOAPIC)
#define _REG_TIMER ((volatile u32_t *) \
			(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_TIMER))
#define _REG_TIMER_ICR ((volatile u32_t *) \
			(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_TIMER_ICR))
#define _REG_TIMER_CCR ((volatile u32_t *) \
			(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_TIMER_CCR))
#define _REG_TIMER_CFG ((volatile u32_t *) \
			(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_TIMER_CONFIG))
#define TIMER_IRQ		CONFIG_LOAPIC_TIMER_IRQ
#define TIMER_IRQ_PRIORITY	CONFIG_LOAPIC_TIMER_IRQ_PRIORITY
#elif defined(CONFIG_MVIC)

#define _REG_TIMER	((volatile u32_t *)MVIC_LVTTIMER)
#define _REG_TIMER_ICR	((volatile u32_t *)MVIC_ICR)
#define _REG_TIMER_CCR	((volatile u32_t *)MVIC_CCR)
/* MVIC has no TIMER_CFG register */
#define TIMER_IRQ		CONFIG_MVIC_TIMER_IRQ
#define TIMER_IRQ_PRIORITY	-1
#endif

#if defined(CONFIG_TICKLESS_IDLE)
#define TIMER_MODE_ONE_SHOT     0
#define TIMER_MODE_PERIODIC     1
@@ -150,13 +115,6 @@ static u32_t reg_timer_cfg_save;
#endif
#endif

#ifdef CONFIG_X2APIC
void z_x2apic_eoi(void)
{
	write_x2apic(LOAPIC_EOI >> 4, 0);
}
#endif

/**
 *
 * @brief Set the timer for periodic mode
@@ -167,11 +125,12 @@ void z_x2apic_eoi(void)
 */
static inline void periodic_mode_set(void)
{
#ifndef CONFIG_X2APIC
	*_REG_TIMER |= LOAPIC_TIMER_PERIODIC;
#ifdef CONFIG_MVIC
	sys_write32(sys_read32(MVIC_LVTTIMER) | LOAPIC_TIMER_PERIODIC,
		    MVIC_LVTTIMER);
#else
	write_x2apic(LOAPIC_TIMER >> 4,
		     read_x2apic(LOAPIC_TIMER >> 4) | LOAPIC_TIMER_PERIODIC);
	x86_write_loapic(LOAPIC_TIMER,
		x86_read_loapic(LOAPIC_TIMER) | LOAPIC_TIMER_PERIODIC);
#endif
}

@@ -188,10 +147,10 @@ static inline void periodic_mode_set(void)
 */
static inline void initial_count_register_set(u32_t count)
{
#ifndef CONFIG_X2APIC
	*_REG_TIMER_ICR = count;
#ifdef CONFIG_MVIC
	sys_write32(count, MVIC_ICR);
#else
	write_x2apic(LOAPIC_TIMER_ICR >> 4, count);
	x86_write_loapic(LOAPIC_TIMER_ICR, count);
#endif
}

@@ -206,32 +165,15 @@ static inline void initial_count_register_set(u32_t count)
 */
static inline void one_shot_mode_set(void)
{
	*_REG_TIMER &= ~LOAPIC_TIMER_PERIODIC;
}
#endif /* CONFIG_TICKLESS_IDLE */

/**
 *
 * @brief Set the rate at which the timer is decremented
 *
 * This routine sets rate at which the timer is decremented to match the
 * external bus frequency.
 * This is not supported with MVIC, only real LOAPIC.
 *
 * @return N/A
 */
#ifndef CONFIG_MVIC
static inline void divide_configuration_register_set(void)
{
#ifndef CONFIG_X2APIC
	*_REG_TIMER_CFG = (*_REG_TIMER_CFG & ~0xf) | LOAPIC_TIMER_DIVBY_1;
#ifdef CONFIG_MVIC
	sys_write32(sys_read32(MVIC_LVTTIMER) & ~LOAPIC_TIMER_PERIODIC,
		MVIC_LVTTIMER);
#else
	write_x2apic(LOAPIC_TIMER_CONFIG >> 4,
		     (read_x2apic(LOAPIC_TIMER_CONFIG >> 4) & ~0xf)
		     | LOAPIC_TIMER_DIVBY_1);
	x86_write_loapic(LOAPIC_TIMER,
		x86_read_loapic(LOAPIC_TIMER) & ~LOAPIC_TIMER_PERIODIC);
#endif
}
#endif
#endif /* CONFIG_TICKLESS_IDLE */

#if defined(CONFIG_TICKLESS_KERNEL) || defined(CONFIG_TICKLESS_IDLE)
/**
@@ -246,10 +188,10 @@ static inline void divide_configuration_register_set(void)
 */
static inline u32_t current_count_register_get(void)
{
#ifndef CONFIG_X2APIC
	return *_REG_TIMER_CCR;
#ifdef CONFIG_MVIC
	return sys_read32(MVIC_CCR);
#else
	return read_x2apic(LOAPIC_TIMER_CCR >> 4);
	return x86_read_loapic(LOAPIC_TIMER_CCR);
#endif
}
#endif
@@ -265,7 +207,11 @@ static inline u32_t current_count_register_get(void)
 */
static inline u32_t initial_count_register_get(void)
{
	return *_REG_TIMER_ICR;
#ifdef CONFIG_MVIC
	return sys_read32(MVIC_ICR);
#else
	return x86_read_loapic(LOAPIC_TIMER_ICR);
#endif
}
#endif /* CONFIG_TICKLESS_IDLE */

@@ -658,8 +604,11 @@ int z_clock_driver_init(struct device *device)
	tickless_idle_init();

#ifndef CONFIG_MVIC
	divide_configuration_register_set();
	x86_write_loapic(LOAPIC_TIMER_CONFIG,
		     (x86_read_loapic(LOAPIC_TIMER_CONFIG) & ~0xf)
		     | LOAPIC_TIMER_DIVBY_1);
#endif

#ifdef CONFIG_TICKLESS_KERNEL
	one_shot_mode_set();
#else
@@ -669,12 +618,15 @@ int z_clock_driver_init(struct device *device)
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
	loapic_timer_device_power_state = DEVICE_PM_ACTIVE_STATE;
#endif
	IRQ_CONNECT(TIMER_IRQ, TIMER_IRQ_PRIORITY, timer_int_handler, 0, 0);

	/* Everything has been configured. It is now safe to enable the
	 * interrupt
	 */
	irq_enable(TIMER_IRQ);
#ifdef CONFIG_MVIC
	IRQ_CONNECT(CONFIG_MVIC_TIMER_IRQ, -1, timer_int_handler, 0, 0);
	irq_enable(CONFIG_MVIC_TIMER_IRQ);
#else
	IRQ_CONNECT(CONFIG_LOAPIC_TIMER_IRQ, CONFIG_LOAPIC_TIMER_IRQ_PRIORITY,
		    timer_int_handler, 0, 0);
	irq_enable(CONFIG_LOAPIC_TIMER_IRQ);
#endif

	return 0;
}
@@ -684,9 +636,11 @@ static int sys_clock_suspend(struct device *dev)
{
	ARG_UNUSED(dev);

	reg_timer_save = *_REG_TIMER;
#ifndef CONFIG_MVIC
	reg_timer_cfg_save = *_REG_TIMER_CFG;
#ifdef CONFIG_MVIC
	reg_timer_save = sys_read32(MVIC_LVTTIMER);
#else
	reg_timer_save = x86_read_loapic(LOAPIC_TIMER);
	reg_timer_cfg_save = x86_read_loapic(LOAPIC_TIMER_CONFIG);
#endif

	loapic_timer_device_power_state = DEVICE_PM_SUSPEND_STATE;
@@ -698,9 +652,11 @@ static int sys_clock_resume(struct device *dev)
{
	ARG_UNUSED(dev);

	*_REG_TIMER = reg_timer_save;
#ifndef CONFIG_MVIC
	*_REG_TIMER_CFG = reg_timer_cfg_save;
#ifdef CONFIG_MVIC
	sys_write32(reg_timer_save, MVIC_LVTTIMER);
#else
	x86_write_loapic(LOAPIC_TIMER, reg_timer_save);
	x86_write_loapic(LOAPIC_TIMER_CONFIG, reg_timer_cfg_save);
#endif

	/*
@@ -802,9 +758,13 @@ void sys_clock_disable(void)

	key = irq_lock();

	irq_disable(TIMER_IRQ);
	initial_count_register_set(0);
#ifdef CONFIG_MVIC
	irq_disable(MVIC_TIMER_IRQ);
#else
	irq_disable(CONFIG_LOAPIC_TIMER_IRQ);
#endif

	initial_count_register_set(0);
	irq_unlock(key);
}