Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4e45e542 authored by Jayachandran C's avatar Jayachandran C Committed by John Crispin
Browse files

MIPS: Netlogic: Use PIC timer as a clocksource



The XLR/XLS/XLP PIC has a 8 countdown timers which run at the PIC
frequencey. One of these can be used as a clocksource to provide
timestamps that is common across cores. This can be used in place
of the count/compare clocksource which is per-CPU.

On XLR/XLS PIC registers are 32-bit, so we just use the lower 32-bits
of the PIC counter. On XLP, the whole 64-bit can be used.

Provide common macros and functions for PIC timer registers on XLR/XLS
and XLP, and use them to register a PIC clocksource.

Signed-off-by: default avatarJayachandran C <jchandra@broadcom.com>
Patchwork: http://patchwork.linux-mips.org/patch/4786/


Signed-off-by: default avatarJohn Crispin <blogic@openwrt.org>
parent a69ba629
Loading
Loading
Loading
Loading
+10 −2
Original line number Original line Diff line number Diff line
@@ -261,6 +261,8 @@
#define PIC_LOCAL_SCHEDULING		1
#define PIC_LOCAL_SCHEDULING		1
#define PIC_GLOBAL_SCHEDULING		0
#define PIC_GLOBAL_SCHEDULING		0


#define PIC_CLK_HZ			133333333

#define nlm_read_pic_reg(b, r)	nlm_read_reg64(b, r)
#define nlm_read_pic_reg(b, r)	nlm_read_reg64(b, r)
#define nlm_write_pic_reg(b, r, v) nlm_write_reg64(b, r, v)
#define nlm_write_pic_reg(b, r, v) nlm_write_reg64(b, r, v)
#define nlm_get_pic_pcibase(node) nlm_pcicfg_base(XLP_IO_PIC_OFFSET(node))
#define nlm_get_pic_pcibase(node) nlm_pcicfg_base(XLP_IO_PIC_OFFSET(node))
@@ -315,6 +317,12 @@ nlm_pic_read_timer(uint64_t base, int timer)
	return nlm_read_pic_reg(base, PIC_TIMER_COUNT(timer));
	return nlm_read_pic_reg(base, PIC_TIMER_COUNT(timer));
}
}


static inline uint32_t
nlm_pic_read_timer32(uint64_t base, int timer)
{
	return (uint32_t)nlm_read_pic_reg(base, PIC_TIMER_COUNT(timer));
}

static inline void
static inline void
nlm_pic_write_timer(uint64_t base, int timer, uint64_t value)
nlm_pic_write_timer(uint64_t base, int timer, uint64_t value)
{
{
@@ -376,9 +384,9 @@ nlm_pic_ack(uint64_t base, int irt_num)
}
}


static inline void
static inline void
nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt)
nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt, int en)
{
{
	nlm_pic_write_irt_direct(base, irt, 0, 0, 0, irq, hwt);
	nlm_pic_write_irt_direct(base, irt, en, 0, 0, irq, hwt);
}
}


int nlm_irq_to_irt(int irq);
int nlm_irq_to_irt(int irq);
+45 −3
Original line number Original line Diff line number Diff line
@@ -35,10 +35,11 @@
#ifndef _ASM_NLM_XLR_PIC_H
#ifndef _ASM_NLM_XLR_PIC_H
#define _ASM_NLM_XLR_PIC_H
#define _ASM_NLM_XLR_PIC_H


#define PIC_CLKS_PER_SEC		66666666ULL
#define PIC_CLK_HZ			66666666
/* PIC hardware interrupt numbers */
/* PIC hardware interrupt numbers */
#define PIC_IRT_WD_INDEX		0
#define PIC_IRT_WD_INDEX		0
#define PIC_IRT_TIMER_0_INDEX		1
#define PIC_IRT_TIMER_0_INDEX		1
#define PIC_IRT_TIMER_INDEX(i)		((i) + PIC_IRT_TIMER_0_INDEX)
#define PIC_IRT_TIMER_1_INDEX		2
#define PIC_IRT_TIMER_1_INDEX		2
#define PIC_IRT_TIMER_2_INDEX		3
#define PIC_IRT_TIMER_2_INDEX		3
#define PIC_IRT_TIMER_3_INDEX		4
#define PIC_IRT_TIMER_3_INDEX		4
@@ -99,6 +100,7 @@


/* PIC Registers */
/* PIC Registers */
#define PIC_CTRL			0x00
#define PIC_CTRL			0x00
#define PIC_CTRL_STE			8	/* timer enable start bit */
#define PIC_IPI				0x04
#define PIC_IPI				0x04
#define PIC_INT_ACK			0x06
#define PIC_INT_ACK			0x06


@@ -251,12 +253,52 @@ nlm_pic_ack(uint64_t base, int irt)
}
}


static inline void
static inline void
nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt)
nlm_pic_init_irt(uint64_t base, int irt, int irq, int hwt, int en)
{
{
	nlm_write_reg(base, PIC_IRT_0(irt), (1u << hwt));
	nlm_write_reg(base, PIC_IRT_0(irt), (1u << hwt));
	/* local scheduling, invalid, level by default */
	/* local scheduling, invalid, level by default */
	nlm_write_reg(base, PIC_IRT_1(irt),
	nlm_write_reg(base, PIC_IRT_1(irt),
		(1 << 30) | (1 << 6) | irq);
		(en << 30) | (1 << 6) | irq);
}

static inline uint64_t
nlm_pic_read_timer(uint64_t base, int timer)
{
	uint32_t up1, up2, low;

	up1 = nlm_read_reg(base, PIC_TIMER_COUNT_1(timer));
	low = nlm_read_reg(base, PIC_TIMER_COUNT_0(timer));
	up2 = nlm_read_reg(base, PIC_TIMER_COUNT_1(timer));

	if (up1 != up2) /* wrapped, get the new low */
		low = nlm_read_reg(base, PIC_TIMER_COUNT_0(timer));
	return ((uint64_t)up2 << 32) | low;

}

static inline uint32_t
nlm_pic_read_timer32(uint64_t base, int timer)
{
	return nlm_read_reg(base, PIC_TIMER_COUNT_0(timer));
}

static inline void
nlm_pic_set_timer(uint64_t base, int timer, uint64_t value, int irq, int cpu)
{
	uint32_t up, low;
	uint64_t pic_ctrl = nlm_read_reg(base, PIC_CTRL);
	int en;

	en = (irq > 0);
	up = value >> 32;
	low = value & 0xFFFFFFFF;
	nlm_write_reg(base, PIC_TIMER_MAXVAL_0(timer), low);
	nlm_write_reg(base, PIC_TIMER_MAXVAL_1(timer), up);
	nlm_pic_init_irt(base, PIC_IRT_TIMER_INDEX(timer), irq, cpu, 0);

	/* enable the timer */
	pic_ctrl |= (1 << (PIC_CTRL_STE + timer));
	nlm_write_reg(base, PIC_CTRL, pic_ctrl);
}
}
#endif
#endif
#endif /* _ASM_NLM_XLR_PIC_H */
#endif /* _ASM_NLM_XLR_PIC_H */
+1 −1
Original line number Original line Diff line number Diff line
@@ -217,7 +217,7 @@ static void nlm_init_node_irqs(int node)
		nlm_setup_pic_irq(node, i, i, irt);
		nlm_setup_pic_irq(node, i, i, irt);
		/* set interrupts to first cpu in node */
		/* set interrupts to first cpu in node */
		nlm_pic_init_irt(nodep->picbase, irt, i,
		nlm_pic_init_irt(nodep->picbase, irt, i,
					node * NLM_CPUS_PER_NODE);
					node * NLM_CPUS_PER_NODE, 0);
		irqmask |= (1ull << i);
		irqmask |= (1ull << i);
	}
	}
	nodep->irqmask = irqmask;
	nodep->irqmask = irqmask;
+52 −0
Original line number Original line Diff line number Diff line
@@ -35,16 +35,68 @@
#include <linux/init.h>
#include <linux/init.h>


#include <asm/time.h>
#include <asm/time.h>
#include <asm/cpu-features.h>

#include <asm/netlogic/interrupt.h>
#include <asm/netlogic/interrupt.h>
#include <asm/netlogic/common.h>
#include <asm/netlogic/common.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/common.h>

#if defined(CONFIG_CPU_XLP)
#include <asm/netlogic/xlp-hal/iomap.h>
#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/pic.h>
#elif defined(CONFIG_CPU_XLR)
#include <asm/netlogic/xlr/iomap.h>
#include <asm/netlogic/xlr/pic.h>
#include <asm/netlogic/xlr/xlr.h>
#else
#error "Unknown CPU"
#endif


unsigned int __cpuinit get_c0_compare_int(void)
unsigned int __cpuinit get_c0_compare_int(void)
{
{
	return IRQ_TIMER;
	return IRQ_TIMER;
}
}


static cycle_t nlm_get_pic_timer(struct clocksource *cs)
{
	uint64_t picbase = nlm_get_node(0)->picbase;

	return ~nlm_pic_read_timer(picbase, PIC_CLOCK_TIMER);
}

static cycle_t nlm_get_pic_timer32(struct clocksource *cs)
{
	uint64_t picbase = nlm_get_node(0)->picbase;

	return ~nlm_pic_read_timer32(picbase, PIC_CLOCK_TIMER);
}

static struct clocksource csrc_pic = {
	.name		= "PIC",
	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
};

static void nlm_init_pic_timer(void)
{
	uint64_t picbase = nlm_get_node(0)->picbase;

	nlm_pic_set_timer(picbase, PIC_CLOCK_TIMER, ~0ULL, 0, 0);
	if (current_cpu_data.cputype == CPU_XLR) {
		csrc_pic.mask	= CLOCKSOURCE_MASK(32);
		csrc_pic.read	= nlm_get_pic_timer32;
	} else {
		csrc_pic.mask	= CLOCKSOURCE_MASK(64);
		csrc_pic.read	= nlm_get_pic_timer;
	}
	csrc_pic.rating = 1000;
	clocksource_register_hz(&csrc_pic, PIC_CLK_HZ);
}

void __init plat_time_init(void)
void __init plat_time_init(void)
{
{
	nlm_init_pic_timer();
	mips_hpt_frequency = nlm_get_cpu_frequency();
	mips_hpt_frequency = nlm_get_cpu_frequency();
	pr_info("MIPS counter frequency [%ld]\n",
	pr_info("MIPS counter frequency [%ld]\n",
			(unsigned long)mips_hpt_frequency);
			(unsigned long)mips_hpt_frequency);
+1 −1
Original line number Original line Diff line number Diff line
@@ -64,7 +64,7 @@ void nlm_xlr_uart_out(struct uart_port *p, int offset, int value)
		.iotype		= UPIO_MEM32,		\
		.iotype		= UPIO_MEM32,		\
		.flags		= (UPF_SKIP_TEST |	\
		.flags		= (UPF_SKIP_TEST |	\
			 UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF),\
			 UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF),\
		.uartclk	= PIC_CLKS_PER_SEC,	\
		.uartclk	= PIC_CLK_HZ,		\
		.type		= PORT_16550A,		\
		.type		= PORT_16550A,		\
		.serial_in	= nlm_xlr_uart_in,	\
		.serial_in	= nlm_xlr_uart_in,	\
		.serial_out	= nlm_xlr_uart_out,	\
		.serial_out	= nlm_xlr_uart_out,	\
Loading