Skip to contentSkip to conversation

CPM2 Timers API

PATCH In review Jason McMullan 1 participant 3 messages Mar 31, 2005 – Apr 1, 2005

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 CPM2 Timers API

Two patches:

cpm-timer.patch:

The base timers API for CPM2 timers

cpm-timer.mpc85xx-devices.patch:

MPC85xx support

Signature · 2 lines
Jason McMullan <[email protected]>
TimeSys Corporation

Description: MPC85xx support for CPM2 timers
Date: Thu Mar 31 14:49:49 EST 2005
Patches: linux-2.6.12-rc1.bk

Difference summary:

 arch/ppc/syslib/mpc85xx_devices.c |   25 +++++++++++++++++++++++++
 arch/ppc/syslib/mpc85xx_sys.c     |   17 ++++++++++-------
 include/asm-ppc/mpc85xx.h         |    1 +
 3 files changed, 36 insertions(+), 7 deletions(-)
arch/ppc/syslib/mpc85xx_devices.c +25 -0
diff -urN -X /home/jmcmullan/dontdiff linux-2.6/arch/ppc/syslib/mpc85xx_devices.c linux-2.6.patch/arch/ppc/syslib/mpc85xx_devices.c
@@ -19,6 +19,8 @@
 #include <linux/serial_8250.h>
 #include <linux/fsl_devices.h>
 #include <asm/mpc85xx.h>
+#include <asm/cpm2.h>
+#include <asm/immap_cpm2.h>
 #include <asm/irq.h>
 #include <asm/ppc_sys.h>
 
@@ -61,8 +63,14 @@
 		.iotype		= UPIO_MEM,
 		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ,
 	},
+	[2] = {
+		.flags = 0
+	}
 };
 
+#define CPM2_OFFSET(t)	((void *)(&((cpm2_map_t *)NULL)->t)-NULL)
+#define CPM2_END(t)	(CPM2_OFFSET(t)+(sizeof(((cpm2_map_t *)NULL)->t))-1)
+
 struct platform_device ppc_sys_platform_devices[] = {
 	[MPC85xx_TSEC1] = {
 		.name = "fsl-gianfar",
@@ -534,6 +542,23 @@
 			},
 		},
 	},
+	[MPC85xx_CPM_TIMER] = {
+		.name = "fsl-cpm-timer",
+		.id = 0,
+		.num_resources	= 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= CPM2_OFFSET(im_cpmtimer),
+				.end	= CPM2_END(im_cpmtimer),
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.start	= SIU_INT_TIMER1,
+				.end	= SIU_INT_TIMER4,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
 #endif /* CONFIG_CPM2 */
 };
 
arch/ppc/syslib/mpc85xx_sys.c +10 -7
diff -urN -X /home/jmcmullan/dontdiff linux-2.6/arch/ppc/syslib/mpc85xx_sys.c linux-2.6.patch/arch/ppc/syslib/mpc85xx_sys.c
@@ -36,7 +36,7 @@
 		.ppc_sys_name	= "8560",
 		.mask 		= 0xFFFF0000,
 		.value 		= 0x80700000,
-		.num_devices	= 19,
+		.num_devices	= 20,
 		.device_list	= (enum ppc_sys_devices[])
 		{
 			MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
@@ -46,13 +46,14 @@
 			MPC85xx_CPM_SCC2, MPC85xx_CPM_SCC3, MPC85xx_CPM_SCC4,
 			MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2, MPC85xx_CPM_FCC3,
 			MPC85xx_CPM_MCC1, MPC85xx_CPM_MCC2,
+			MPC85xx_CPM_TIMER,
 		},
 	},
 	{
 		.ppc_sys_name	= "8541",
 		.mask 		= 0xFFFF0000,
 		.value 		= 0x80720000,
-		.num_devices	= 13,
+		.num_devices	= 14,
 		.device_list	= (enum ppc_sys_devices[])
 		{
 			MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
@@ -60,13 +61,14 @@
 			MPC85xx_PERFMON, MPC85xx_DUART,
 			MPC85xx_CPM_SPI, MPC85xx_CPM_I2C,
 			MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
+			MPC85xx_CPM_TIMER,
 		},
 	},
 	{
 		.ppc_sys_name	= "8541E",
 		.mask 		= 0xFFFF0000,
 		.value 		= 0x807A0000,
-		.num_devices	= 14,
+		.num_devices	= 15,
 		.device_list	= (enum ppc_sys_devices[])
 		{
 			MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
@@ -74,13 +76,14 @@
 			MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
 			MPC85xx_CPM_SPI, MPC85xx_CPM_I2C,
 			MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
+			MPC85xx_CPM_TIMER,
 		},
 	},
 	{
 		.ppc_sys_name	= "8555",
 		.mask 		= 0xFFFF0000,
 		.value 		= 0x80710000,
-		.num_devices	= 19,
+		.num_devices	= 20,
 		.device_list	= (enum ppc_sys_devices[])
 		{
 			MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
@@ -90,14 +93,14 @@
 			MPC85xx_CPM_SCC2, MPC85xx_CPM_SCC3,
 			MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
 			MPC85xx_CPM_SMC1, MPC85xx_CPM_SMC2,
-			MPC85xx_CPM_USB,
+			MPC85xx_CPM_USB, MPC85xx_CPM_TIMER,
 		},
 	},
 	{
 		.ppc_sys_name	= "8555E",
 		.mask 		= 0xFFFF0000,
 		.value 		= 0x80790000,
-		.num_devices	= 20,
+		.num_devices	= 21,
 		.device_list	= (enum ppc_sys_devices[])
 		{
 			MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
@@ -107,7 +110,7 @@
 			MPC85xx_CPM_SCC2, MPC85xx_CPM_SCC3,
 			MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
 			MPC85xx_CPM_SMC1, MPC85xx_CPM_SMC2,
-			MPC85xx_CPM_USB,
+			MPC85xx_CPM_USB, MPC85xx_CPM_TIMER,
 		},
 	},
 	{	/* default match */
include/asm-ppc/mpc85xx.h +1 -0
diff -urN -X /home/jmcmullan/dontdiff linux-2.6/include/asm-ppc/mpc85xx.h linux-2.6.patch/include/asm-ppc/mpc85xx.h
@@ -127,6 +127,7 @@
 	MPC85xx_CPM_MCC2,
 	MPC85xx_CPM_SMC1,
 	MPC85xx_CPM_SMC2,
+	MPC85xx_CPM_TIMER,
 };
 
 #endif /* CONFIG_85xx */

Description: CPM2 Timers API
Date: Thu Mar 31 14:49:49 EST 2005
Patches: linux-2.6.12-rc1.bk

Difference summary:

 arch/ppc/Kconfig            |    6 
 arch/ppc/syslib/Makefile    |    1 
 arch/ppc/syslib/cpm_timer.c |  522 ++++++++++++++++++++++++++++++++++++++++++++
 include/asm-ppc/cpm_timer.h |   74 ++++++
 4 files changed, 603 insertions(+)
arch/ppc/Kconfig +6 -0
diff -urN -X /home/jmcmullan/dontdiff linux-2.6/arch/ppc/Kconfig linux-2.6.patch/arch/ppc/Kconfig
@@ -713,6 +713,12 @@
 	  you wish to build a kernel for a machine with a CPM2 coprocessor
 	  on it (826x, 827x, 8560).
 
+config CPM_TIMER
+	tristate "CPM2 Timers"
+	depends on 8260 || 85xx
+	help
+	  Includes kernel support for CPM2 timers
+
 config PPC_CHRP
 	bool
 	depends on PPC_MULTIPLATFORM
arch/ppc/syslib/cpm_timer.c +522 -0

522 lines not on this page · raw message

arch/ppc/syslib/Makefile +1 -0
diff -urN -X /home/jmcmullan/dontdiff linux-2.6/arch/ppc/syslib/Makefile linux-2.6.patch/arch/ppc/syslib/Makefile
@@ -84,6 +84,7 @@
 obj-$(CONFIG_PCI_8260)		+= m8260_pci.o indirect_pci.o
 obj-$(CONFIG_8260_PCI9)		+= m8260_pci_erratum9.o
 obj-$(CONFIG_CPM2)		+= cpm2_common.o cpm2_pic.o
+obj-$(CONFIG_CPM_TIMER)		+= cpm_timer.o
 ifeq ($(CONFIG_PPC_GEN550),y)
 obj-$(CONFIG_KGDB)		+= gen550_kgdb.o gen550_dbg.o
 obj-$(CONFIG_SERIAL_TEXT_DEBUG)	+= gen550_dbg.o
include/asm-ppc/cpm_timer.h +74 -0

74 lines not on this page · raw message

#1 lore raw

A brown bag error handling and Lindent patch, to be applied in that order, to my previous CPM timers patch.

Signature · 2 lines
Jason McMullan <[email protected]>
TimeSys Corporation
arch/ppc/syslib/cpm_timer.c renamed from arch/ppc/syslib/cpm_timer.c.orig +7 -3
@@ -114,12 +114,16 @@
 
 	tm->start = (timer_id>>4)&0xf;
 	tm->end   = timer_id & 0xf;
-	if (tm->start > 3)
+	if (tm->start > 3) {
+		kfree(tm);
 		return -EINVAL;
+	}
 
 	if ((tm->end != tm->start) && 
-	    ((tm->start & 1) || (tm->end != (tm->start+1))))
-	    return -EINVAL;
+	    ((tm->start & 1) || (tm->end != (tm->start+1)))) {
+		kfree(tm);
+		return -EINVAL;
+	}
 
 	err = request_resource(&cpm_timer_resource,tm);
 	if (err < 0) {
arch/ppc/syslib/cpm_timer.c +47 -44

242 lines not on this page · raw message

#2 lore raw

And here's the test-case kernel module....

Signature · 2 lines
Jason McMullan <[email protected]>
TimeSys Corporation

/*
* CPM Timers test
*
* Copyright 2004, Timesys Corp.
* Jason McMullan <[email protected]>
*/

#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/wait.h>

#include <asm/cpm_timer.h>

static int failed = 0;
static volatile int once, every;

static wait_queue_head_t queue;

#define FAILED(x, args...) do { failed++; printk(KERN_INFO "cpm_timer_test: " x , ## args ); if (tm != NULL) { cpm_timer_stop(tm); cpm_timer_free(tm); } return -EINVAL; } while (0)

static void cpm_timer_test_callback(cpm_timer_t tm, void *data)

{
	if (data == &once) {
		unsigned long val = cpm_timer_get_ticks(tm);
		printk(KERN_INFO "cpm_timer_test: Called once at tick %ld.\n",
		       val);
		once++;
		wmb();
	}

	if (data == &every) {
		unsigned long val = cpm_timer_get_ticks(tm);
		printk(KERN_INFO
		       "cpm_timer_test: Called every(%d), tick %ld.\n", every,
		       val);
		every++;
		if (every > 5)
			cpm_timer_call_none(tm);
		wmb();
	}

	wake_up_interruptible(&queue);
}

static int test_timer(int timer_id)

{
	cpm_timer_t tm = NULL;
	int err;
	unsigned long res, val;

	printk(KERN_INFO "cpm_timer_test: Test timer ID 0x%.2x\n", timer_id);
	err = cpm_timer_alloc(timer_id, &tm);
	if (err < 0)
		FAILED("Can't allocate timer 0x%.2x\n", timer_id);

	res = cpm_timer_get_resolution(tm);
	printk(KERN_INFO "cpm_timer_test: nanoseconds/tick = %ld\n", res);

	val = cpm_timer_get_ticks(tm);
	printk(KERN_INFO "cpm_timer_test: current value = %ld\n", val);

	cpm_timer_stop(tm);
	cpm_timer_reset(tm);
	val = cpm_timer_get_ticks(tm);
	printk(KERN_INFO "cpm_timer_test: value after stop/reset= %ld\n", val);
	if (val != 0)
		FAILED("Timer 0x%.2x didn't stop!\n", timer_id);

	cpm_timer_start(tm);
	udelay(5);
	val = cpm_timer_get_ticks(tm);
	udelay(5);
	res = cpm_timer_get_ticks(tm);
	printk(KERN_INFO "cpm_timer_test: value after  5 us= %ld\n", val);
	printk(KERN_INFO "cpm_timer_test: value after 10 us= %ld\n", res);
	if (val == 0 || res == 0)
		FAILED("Timer 0x%.2x didn't increment!\n", timer_id);

	init_waitqueue_head(&queue);

	once = 0;
	err =
	    cpm_timer_call_once(tm, 50000, cpm_timer_test_callback,
				(void *)&once);
	if (err < 0)
		FAILED("Can't call cpm_timer_call_once for 0x%.2x\n", timer_id);

	printk(KERN_INFO "cpm_timer_test: Waiting for one-shot...\n");
	cpm_timer_start(tm);
	err = wait_event_interruptible(queue, once != 0);
	if (err < 0)
		FAILED("Interrupted sleep for 0x%.2x\n", timer_id);

	every = 0;
	err =
	    cpm_timer_call_every(tm, 50000, cpm_timer_test_callback,
				 (void *)&every);
	if (err < 0)
		FAILED("Can't call cpm_timer_call_every for 0x%.2x\n",
		       timer_id);

	printk(KERN_INFO "cpm_timer_test: Waiting for multi-shot x5...\n");
	cpm_timer_start(tm);
	err = wait_event_interruptible(queue, every > 5);
	if (err < 0)
		FAILED("Interrupted sleep for 0x%.2x\n", timer_id);
	cpm_timer_call_none(tm);
	printk(KERN_INFO "cpm_timer_test: Counted up to %d.\n", every);

	cpm_timer_stop(tm);
	cpm_timer_free(tm);

	return 0;
}

static int cpm_timer_test_init(void)

{
	int err;

	printk(KERN_INFO "CPM2 Timer Test Module.\n");

#define TEST(x) do { err=test_timer(x); if (err != 0) goto bad; } while (0)

	TEST(CPM2_TIMER16_1);
	TEST(CPM2_TIMER16_2);
	TEST(CPM2_TIMER16_3);
	TEST(CPM2_TIMER16_4);

	TEST(CPM2_TIMER32_1);
	TEST(CPM2_TIMER32_2);

      bad:
	if (failed) {
		printk(KERN_INFO "cpm_timer_test: FAILED %d tests\n", failed);
	} else {
		printk(KERN_INFO "cpm_timer_test: PASSED\n");
	}

	return 0;
}

static void cpm_timer_test_exit(void)

{
	printk(KERN_INFO "CPM2 Timer Test Module unloaded.\n");
	return;
}

MODULE_LICENSE("GPL");
module_init(cpm_timer_test_init);
module_exit(cpm_timer_test_exit);