summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHirufmi Yagi <yagi@lineo.co.jp>2012-07-02 15:18:31 +0900
committerJustin Waters <justin.waters@timesys.com>2012-07-03 17:15:31 -0400
commit7a66fb115ea0b388558d204fe8e353ae6d964af3 (patch)
tree5d219ae3237ee1198dfcb8d2f5c17b310bcbc97e
parent6f09f2ffe5a9cdac5f3dd00682437063785ff8e0 (diff)
Add: timers
-rw-r--r--arch/arm/mach-mvf/board-twr_vf600.c92
-rw-r--r--drivers/char/Kconfig18
-rw-r--r--drivers/char/Makefile4
-rw-r--r--drivers/char/ftimer.c395
-rw-r--r--drivers/char/ftimer.h59
-rw-r--r--drivers/char/ftimer_reg.h339
-rw-r--r--drivers/char/lptimer.c349
-rw-r--r--drivers/char/lptimer.h77
-rw-r--r--drivers/char/lptimer_reg.h33
-rw-r--r--drivers/char/mvf_timer_master.c113
-rw-r--r--drivers/char/pitimer.c323
-rw-r--r--drivers/char/pitimer.h40
-rw-r--r--drivers/char/pitimer_reg.h37
13 files changed, 1879 insertions, 0 deletions
diff --git a/arch/arm/mach-mvf/board-twr_vf600.c b/arch/arm/mach-mvf/board-twr_vf600.c
index c8c68e72a2ed..f7ac6863c242 100644
--- a/arch/arm/mach-mvf/board-twr_vf600.c
+++ b/arch/arm/mach-mvf/board-twr_vf600.c
@@ -257,6 +257,94 @@ static struct platform_device edma_device = {
.resource = edma_resources,
};
+
+//
+// Timer resources
+//
+// pit
+static struct resource pit_resources[] = {
+ [0] = {
+ .start = MVF_PIT_BASE_ADDR,
+ .end = MVF_PIT_BASE_ADDR + 0x1000,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = MXC_INT_PIT,
+ .end = MXC_INT_PIT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device pit_device = {
+ .name = "mvf-pit",
+ .id = 0,
+ .num_resources = 2,
+ .resource = pit_resources,
+};
+
+// ftm 0
+static struct resource ftm0_resources[] = {
+ [0] = {
+ .start = MVF_FTM0_BASE_ADDR,
+ .end = MVF_FTM0_BASE_ADDR + 0x1000,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = MXC_INT_FTM0,
+ .end = MXC_INT_FTM0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ftm0_device = {
+ .name = "mvf-ftm",
+ .id = 0,
+ .num_resources = 2,
+ .resource = ftm0_resources,
+};
+
+// ftm 1
+static struct resource ftm1_resources[] = {
+ [0] = {
+ .start = MVF_FTM1_BASE_ADDR,
+ .end = MVF_FTM1_BASE_ADDR + 0x1000,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = MXC_INT_FTM1,
+ .end = MXC_INT_FTM1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ftm1_device = {
+ .name = "mvf-ftm",
+ .id = 1,
+ .num_resources = 2,
+ .resource = ftm1_resources,
+};
+
+// pit
+static struct resource lpt_resources[] = {
+ [0] = {
+ .start = MVF_LPTMR_BASE_ADDR,
+ .end = MVF_LPTMR_BASE_ADDR + 0x1000,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = MXC_INT_LP_TIMER0,
+ .end = MXC_INT_LP_TIMER0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device lpt_device = {
+ .name = "mvf-lpt",
+ .id = 0,
+ .num_resources = 2,
+ .resource = lpt_resources,
+};
+
static void twr_vf600_suspend_enter(void)
{
/* suspend preparation */
@@ -301,6 +389,10 @@ static void __init twr_vf600_init(void)
mvf_init_fec(fec_data);
platform_device_register(&edma_device);
+ platform_device_register(&pit_device);
+ platform_device_register(&ftm0_device);
+ platform_device_register(&ftm1_device);
+ platform_device_register(&lpt_device);
vf600_add_android_device_buttons();
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 125645af6e80..15e7af6c024d 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -644,5 +644,23 @@ config MXS_VIIM
help
Support for access to MXS Virtual IIM device, most people should say N here.
+config FTM
+ bool "Flex Timer Module support"
+ depends on SOC_VF6XX
+ help
+ Support Flex Timer Module.
+
+config LPTMR
+ bool "Low Power Timer Module support"
+ depends on SOC_VF6XX
+ help
+ Support Low Power Timer Module.
+
+config PIT
+ bool "Periodic Interrupt Timer Module support"
+ depends on SOC_VF6XX
+ help
+ Support Periodic Interrupt Timer Module.
+
endmenu
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 813845aec98e..d312faeda3b3 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -65,5 +65,9 @@ obj-$(CONFIG_RAMOOPS) += ramoops.o
obj-$(CONFIG_MXC_IIM) += mxc_iim.o
obj-$(CONFIG_MXS_VIIM) += mxs_viim.o
+obj-$(CONFIG_FTM) += ftimer.o
+obj-$(CONFIG_LPTMR) += lptimer.o
+obj-$(CONFIG_PIT) += pitimer.o
+
obj-$(CONFIG_JS_RTC) += js-rtc.o
js-rtc-y = rtc.o
diff --git a/drivers/char/ftimer.c b/drivers/char/ftimer.c
new file mode 100644
index 000000000000..88a31997ef8f
--- /dev/null
+++ b/drivers/char/ftimer.c
@@ -0,0 +1,395 @@
+/*
+ * drivers/char/ftimer.c
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/cdev.h>
+#include <asm/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <mach/clock.h>
+#include "ftimer_reg.h"
+#include "ftimer.h"
+
+// define for timer master
+#define TIMER_MASTER_MAX_TIMER 2
+#define TIMER_MASTER_ENUM_AVAILABLE FMT_AVAILABLE_CHANNEL
+#define TIMER_MASTER_ENUM_MAXCHANNEL FMT1
+#include "mvf_timer_master.c"
+
+
+////////////////////////////////////////////////////////////////
+
+#define FTM_DRIVER_NAME "ftm"
+
+struct mvf_ftm_dev {
+ struct clk *clk;
+ void __iomem *membase;
+ int irq;
+ unsigned long configured;
+ unsigned long refer_ch;
+ void (*event_handler)(int);
+};
+
+void ftm_module_enable( void __iomem *membase)
+{
+ unsigned long val;
+
+ val = readl(membase + FTM_MODE_OFFSET);
+ if (!( val & FTM_MODE_FTMEN)){
+ val |= ( FTM_MODE_FTMEN | FTM_MODE_INIT);
+ writel(val, membase + FTM_MODE_OFFSET);
+ }
+}
+
+void ftm_module_disable( void __iomem *membase)
+{
+ unsigned long val;
+
+ val = readl(membase + FTM_MODE_OFFSET);
+ val &= ~FTM_MODE_FTMEN;
+ writel(val, membase + FTM_MODE_OFFSET);
+}
+
+
+void ftm_write_protect_on( void __iomem *membase)
+{
+ unsigned long val;
+
+ val = readl(membase + FTM_FMS_OFFSET);
+ if ( !(val & FTM_FMS_WPEN)){
+ val |= FTM_FMS_WPEN;
+ writel(val, membase + FTM_FMS_OFFSET);
+ }
+}
+
+void ftm_write_protect_off( void __iomem *membase)
+{
+ unsigned long val,val2;
+
+ val = readl(membase + FTM_MODE_OFFSET);
+ val2 = readl(membase + FTM_FMS_OFFSET);
+ if ( val2 & FTM_FMS_WPEN){
+ val |= FTM_MODE_WPDIS;
+ writel(val, membase + FTM_MODE_OFFSET);
+ }
+
+}
+
+static int in_ftm_timer_stop( struct mvf_ftm_dev *timedevptr)
+{
+ void __iomem *membase;
+ unsigned long val;
+
+ membase = timedevptr->membase;
+
+ val = readl(membase + FTM_SC_OFFSET);
+ val &= ~FTM_SC_TOIE;
+
+ // interrupt disable
+ writel( val, membase + FTM_SC_OFFSET);
+
+ return 0;
+}
+
+static int in_ftm_timer_start( struct mvf_ftm_dev *timedevptr)
+{
+ void __iomem *membase;
+ unsigned long val;
+ int ret;
+
+ membase = timedevptr->membase;
+
+ ret = 0;
+
+ if ( timedevptr->configured){
+ // read sc reg
+ val = readl(membase + FTM_SC_OFFSET);
+ val |= FTM_SC_TOIE;
+
+ // clear counter
+ writel(0, membase + FTM_CNT_OFFSET);
+
+ // interrupt enable
+ writel( val, membase + FTM_SC_OFFSET);
+ }else{
+ ret = -EAGAIN;
+ }
+
+ return ret;
+}
+
+static irqreturn_t ftm_int_handler(int irq, void *dev_id)
+{
+ struct mvf_ftm_dev *timedevptr = dev_id;
+ unsigned long val;
+ irqreturn_t iret;
+
+ iret = IRQ_HANDLED;
+
+ val = readl( timedevptr->membase + FTM_SC_OFFSET);
+ if (val & FTM_SC_TOF){
+
+ if ( timedevptr->event_handler){
+ (*timedevptr->event_handler)( timedevptr->refer_ch);
+ }
+ val &= ~FTM_SC_TOF;
+ writel( val, timedevptr->membase + FTM_SC_OFFSET);
+ }else{
+ iret = IRQ_NONE;
+ }
+
+ return iret;
+
+}
+
+int ftm_enable_timer( int timer_handle)
+{
+ struct platform_device *pdev;
+ struct mvf_ftm_dev *timedevptr;
+
+ if ( !timer_master_is_opened(timer_handle)){
+ return -EAGAIN;
+ }
+
+ pdev = timer_master_get_pdev(timer_handle);
+ timedevptr = platform_get_drvdata(pdev);
+
+ return in_ftm_timer_start( timedevptr);
+}
+EXPORT_SYMBOL( ftm_enable_timer);
+
+int ftm_disable_timer( int timer_handle)
+{
+ struct platform_device *pdev;
+ struct mvf_ftm_dev *timedevptr;
+
+ if ( !timer_master_is_opened(timer_handle)){
+ return -EAGAIN;
+ }
+ pdev = timer_master_get_pdev(timer_handle);
+ timedevptr = platform_get_drvdata(pdev);
+
+
+ return in_ftm_timer_stop( timedevptr);
+}
+EXPORT_SYMBOL(ftm_disable_timer);
+
+
+int ftm_alloc_timer( ftm_channel ch)
+{
+ return timer_master_alloc_timer(ch);
+}
+EXPORT_SYMBOL(ftm_alloc_timer);
+
+int ftm_free_timer (int timer_handle)
+{
+ if ( !ftm_disable_timer( timer_handle)){
+ return timer_master_free( timer_handle);
+ }
+
+ return -EAGAIN;
+}
+EXPORT_SYMBOL(ftm_free_timer);
+
+int ftm_read_counter( int timer_handle, unsigned long *counter)
+{
+ struct platform_device *pdev;
+ struct mvf_ftm_dev *timedevptr;
+
+ if ( !timer_master_is_opened( timer_handle)){
+ return -EAGAIN;
+ }
+ pdev = timer_master_get_pdev(timer_handle);
+ timedevptr = platform_get_drvdata(pdev);
+
+ // 16bit timer
+ *counter = readl( timedevptr->membase + FTM_CNT_OFFSET) & 0x0000ffff;
+
+ return 0;
+}
+EXPORT_SYMBOL(ftm_read_counter);
+
+int ftm_param_set( int timer_handle, struct mvf_ftm_request *req, void (*event_handler)(int))
+{
+ void __iomem *membase;
+ struct platform_device *pdev;
+ struct mvf_ftm_dev *timedevptr;
+ unsigned long val;
+
+ if ( !timer_master_is_opened( timer_handle)){
+ return -EAGAIN;
+ }
+
+ pdev = timer_master_get_pdev(timer_handle);
+ timedevptr = platform_get_drvdata(pdev);
+
+ membase = timedevptr->membase;
+ if ( req == NULL){
+ printk( KERN_ERR"FTM param error \n");
+ return -EINVAL;
+ }
+
+ if( req->clocksource > FTM_PARAM_CLK_EXTERNAL){
+ printk( KERN_ERR"FTM clock source setting error\n");
+ return -EINVAL;
+ }
+
+ if( req->divider > FTM_PARAM_DIV_BY_128){
+ printk( KERN_ERR"FTM clock divider error\n");
+ return -EINVAL;
+ }
+
+ // WP off
+ ftm_write_protect_off( membase);
+
+ // enable ip
+ ftm_module_enable( membase);
+
+ // set clksrc and divider. IE is OFF.
+ val = (req->clocksource << 3) | req->divider;
+ writel(val, membase + FTM_SC_OFFSET);
+
+ // counter initial value(=reset value)
+ writel(req->start, membase + FTM_CNTIN_OFFSET);
+ // modulo value(=max count)
+ writel(req->end, membase + FTM_MOD_OFFSET);
+
+ timedevptr->event_handler = event_handler;
+ timedevptr->refer_ch = timer_handle;
+
+ timedevptr->configured++;
+ // check 32bit cyclic
+ if( timedevptr->configured == 0){
+ timedevptr->configured++;
+ }
+
+ ftm_write_protect_on( membase);
+
+ return 0;
+}
+EXPORT_SYMBOL(ftm_param_set);
+
+static __devinit
+int ftm_probe(struct platform_device *pdev)
+{
+ int size;
+ int result;
+ struct resource *ftm_membase, *ftm_irq;
+ struct mvf_ftm_dev *timedevptr;
+
+ ftm_membase = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ ftm_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if (!ftm_irq || !ftm_membase){
+ printk(KERN_WARNING"FTM resource allocation failed\n");
+ return -ENODEV;
+ }
+
+ timedevptr = kzalloc(sizeof(struct mvf_ftm_dev), GFP_KERNEL);
+ if (!timedevptr) {
+ printk(KERN_WARNING"FTM malloc fail.\n");
+ return -ENOMEM;
+ }
+
+ if ( pdev->id == 0){
+ timedevptr->clk = clk_get(&pdev->dev, "ftm0_clk");
+ }else{
+ timedevptr->clk = clk_get(&pdev->dev, "ftm1_clk");
+ }
+ if ( IS_ERR( timedevptr->clk )) {
+ dev_err(&pdev->dev, "Could not get FTM %d clock \n",pdev->id );
+ return PTR_ERR( timedevptr->clk);
+ }
+ clk_enable( timedevptr->clk);
+
+ size = ftm_membase->end - ftm_membase->start + 1;
+ timedevptr->membase = ioremap(ftm_membase->start, size);
+ if (!timedevptr->membase){
+ printk(KERN_WARNING"FTM ioremap failed.\n");
+ return -ENOMEM;
+ }
+ timedevptr->irq = ftm_irq->start;
+
+ result = request_irq(timedevptr->irq, ftm_int_handler, 0, FTM_DRIVER_NAME, timedevptr);
+ if (result < 0) {
+ printk(KERN_WARNING"FTM Error %d can't get irq.\n", result);
+ return result;
+ }
+
+ platform_set_drvdata(pdev, timedevptr);
+
+ timer_master_register_platform(pdev);
+
+ return 0;
+}
+
+static int __devexit ftm_remove(struct platform_device *pdev)
+{
+ struct mvf_ftm_dev *timedevptr;
+
+ timedevptr = platform_get_drvdata(pdev);
+
+ // disable all
+ writel( 0, timedevptr->membase + FTM_SC_OFFSET);
+ in_ftm_timer_stop( timedevptr);
+ clk_disable( timedevptr->clk);
+ kfree( timedevptr);
+
+ return 0;
+}
+
+static struct platform_driver ftm_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "mvf-ftm",
+ },
+ .probe = ftm_probe,
+ .remove = ftm_remove,
+};
+
+static int __init ftm_plat_dev_init(void)
+{
+ return platform_driver_register(&ftm_driver);
+}
+
+static void __exit ftm_plat_dev_cleanup(void)
+{
+ platform_driver_unregister(&ftm_driver);
+}
+
+module_init(ftm_plat_dev_init);
+module_exit(ftm_plat_dev_cleanup);
diff --git a/drivers/char/ftimer.h b/drivers/char/ftimer.h
new file mode 100644
index 000000000000..7ee985a1b476
--- /dev/null
+++ b/drivers/char/ftimer.h
@@ -0,0 +1,59 @@
+/*
+ * drivers/char/ftimer.h
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+struct mvf_ftm_request{
+ unsigned long clocksource;
+ unsigned long divider;
+ unsigned short start;
+ unsigned short end;
+};
+
+typedef enum {
+ FMT0,
+ FMT1,
+ FMT_AVAILABLE_CHANNEL
+} ftm_channel;
+
+
+// clock source
+#define FTM_PARAM_CLK_NOCLOCK 0x00
+#define FTM_PARAM_CLK_SYSTEMCLOCK 0x01
+#define FTM_PARAM_CLK_FIXEDFREQ 0x02
+#define FTM_PARAM_CLK_EXTERNAL 0x03
+
+// divider
+#define FTM_PARAM_DIV_BY_1 0x00
+#define FTM_PARAM_DIV_BY_2 0x01
+#define FTM_PARAM_DIV_BY_4 0x02
+#define FTM_PARAM_DIV_BY_8 0x03
+#define FTM_PARAM_DIV_BY_16 0x04
+#define FTM_PARAM_DIV_BY_32 0x05
+#define FTM_PARAM_DIV_BY_64 0x06
+#define FTM_PARAM_DIV_BY_128 0x07
+
+int ftm_alloc_timer( ftm_channel ch);
+int ftm_free_timer( int timer_handle);
+int ftm_enable_timer( int timer_handle);
+int ftm_disable_timer( int timer_handle);
+int ftm_read_counter( int timer_handle, unsigned long *counter);
+int ftm_param_set( int timer_handle, struct mvf_ftm_request *req, void (*event_handler)(int));
+
diff --git a/drivers/char/ftimer_reg.h b/drivers/char/ftimer_reg.h
new file mode 100644
index 000000000000..8bc139b228b9
--- /dev/null
+++ b/drivers/char/ftimer_reg.h
@@ -0,0 +1,339 @@
+/*
+ * drivers/char/ftimer_reg.h
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * based on NuttX RTOS (http://nuttx.sourceforge.net/)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _FTM_H
+#define _FTM_H
+
+#define FTM_SC_OFFSET 0x0000 /* Status and Control */
+#define FTM_CNT_OFFSET 0x0004 /* Counter */
+#define FTM_MOD_OFFSET 0x0008 /* Modulo */
+
+#define FTM_CSC_OFFSET(n) (0x000c+((n)<<3) /* Channel (n) Status and Control */
+#define FTM_CV_OFFSET(n) (0x0010+((n)<<3) /* Channel (n) Value */
+#define FTM_C0SC_OFFSET 0x000c /* Channel 0 Status and Control */
+#define FTM_C0V_OFFSET 0x0010 /* Channel 0 Value */
+#define FTM_C1SC_OFFSET 0x0014 /* Channel 1 Status and Control */
+#define FTM_C1V_OFFSET 0x0018 /* Channel 1 Value */
+#define FTM_C2SC_OFFSET 0x001c /* Channel 2 Status and Control */
+#define FTM_C2V_OFFSET 0x0020 /* Channel 2 Value */
+#define FTM_C3SC_OFFSET 0x0024 /* Channel 3 Status and Control */
+#define FTM_C3V_OFFSET 0x0028 /* Channel 3 Value */
+#define FTM_C4SC_OFFSET 0x002c /* Channel 4 Status and Control */
+#define FTM_C4V_OFFSET 0x0030 /* Channel 4 Value */
+#define FTM_C5SC_OFFSET 0x0034 /* Channel 5 Status and Control */
+#define FTM_C5V_OFFSET 0x0038 /* Channel 5 Value */
+#define FTM_C6SC_OFFSET 0x003c /* Channel 6 Status and Control */
+#define FTM_C6V_OFFSET 0x0040 /* Channel 6 Value */
+#define FTM_C7SC_OFFSET 0x0044 /* Channel 7 Status and Control */
+#define FTM_C7V_OFFSET 0x0048 /* Channel 7 Value */
+
+#define FTM_CNTIN_OFFSET 0x004c /* Counter Initial Value */
+#define FTM_STATUS_OFFSET 0x0050 /* Capture and Compare Status */
+#define FTM_MODE_OFFSET 0x0054 /* Features Mode Selection */
+#define FTM_SYNC_OFFSET 0x0058 /* Synchronization */
+#define FTM_OUTINIT_OFFSET 0x005c /* Initial State for Channels Output */
+#define FTM_OUTMASK_OFFSET 0x0060 /* Output Mask */
+#define FTM_COMBINE_OFFSET 0x0064 /* Function for Linked Channels */
+#define FTM_DEADTIME_OFFSET 0x0068 /* Deadtime Insertion Control */
+#define FTM_EXTTRIG_OFFSET 0x006c /* FTM External Trigger */
+#define FTM_POL_OFFSET 0x0070 /* Channels Polarity */
+#define FTM_FMS_OFFSET 0x0074 /* Fault Mode Status */
+#define FTM_FILTER_OFFSET 0x0078 /* Input Capture Filter Control */
+#define FTM_FLTCTRL_OFFSET 0x007c /* Fault Control */
+#define FTM_QDCTRL_OFFSET 0x0080 /* Quadrature Decoder Control and Status */
+#define FTM_CONF_OFFSET 0x0084 /* Configuration */
+#define FTM_FLTPOL_OFFSET 0x0088 /* FTM Fault Input Polarity */
+#define FTM_SYNCONF_OFFSET 0x008c /* Synchronization Configuration */
+#define FTM_INVCTRL_OFFSET 0x0090 /* FTM Inverting Control */
+#define FTM_SWOCTRL_OFFSET 0x0094 /* FTM Software Output Control */
+#define FTM_PWMLOAD_OFFSET 0x0098 /* FTM PWM Load */
+
+#define FTM_SC_PS_SHIFT (0) /* Bits 0-2: Prescale Factor Selection */
+#define FTM_SC_PS_MASK (7 << FTM_SC_PS_SHIFT)
+# define FTM_SC_PS_1 (0 << FTM_SC_PS_SHIFT)
+# define FTM_SC_PS_2 (1 << FTM_SC_PS_SHIFT)
+# define FTM_SC_PS_4 (2 << FTM_SC_PS_SHIFT)
+# define FTM_SC_PS_8 (3 << FTM_SC_PS_SHIFT)
+# define FTM_SC_PS_16 (4 << FTM_SC_PS_SHIFT)
+# define FTM_SC_PS_32 (5 << FTM_SC_PS_SHIFT)
+# define FTM_SC_PS_64 (6 << FTM_SC_PS_SHIFT)
+# define FTM_SC_PS_128 (7 << FTM_SC_PS_SHIFT)
+#define FTM_SC_CLKS_SHIFT (3) /* Bits 3-4: Clock Source Selection */
+#define FTM_SC_CLKS_MASK (3 << FTM_SC_CLKS_SHIFT)
+# define FTM_SC_CLKS_NONE (0 << FTM_SC_CLKS_SHIFT) /* No clock selected */
+# define FTM_SC_CLKS_SYSCLK (1 << FTM_SC_CLKS_SHIFT) /* System clock */
+# define FTM_SC_CLKS_FIXED (2 << FTM_SC_CLKS_SHIFT) /* Fixed frequency clock */
+# define FTM_SC_CLKS_EXTCLK (3 << FTM_SC_CLKS_SHIFT) /* External clock */
+#define FTM_SC_CPWMS (1 << 5) /* Bit 5: Center-aligned PWM Select */
+#define FTM_SC_TOIE (1 << 6) /* Bit 6: Timer Overflow Interrupt Enable */
+#define FTM_SC_TOF (1 << 7) /* Bit 7: Timer Overflow Flag */
+ /* Bits 8-31: Reserved */
+
+#define FTM_CNT_SHIFT (0) /* Bits 0-15: Counter value */
+#define FTM_CNT_MASK (0xffff << FTM_CNT_SHIFT)
+ /* Bits 16-31: Reserved */
+
+
+#define FTM_MOD_SHIFT (0) /* Bits 0-15: Modulo value */
+#define FTM_MOD_MASK (0xffff << FTM_MOD_SHIFT)
+ /* Bits 16-31: Reserved */
+
+#define FTM_CSC_DMA (1 << 0) /* Bit 0: DMA Enable */
+ /* Bit 1: Reserved */
+#define FTM_CSC_ELSA (1 << 2) /* Bit 2: Edge or Level Select */
+#define FTM_CSC_ELSB (1 << 3) /* Bit 3: Edge or Level Select */
+#define FTM_CSC_MSA (1 << 4) /* Bit 4: Channel Mode Select */
+#define FTM_CSC_MSB (1 << 5) /* Bit 5: Channel Mode Select */
+#define FTM_CSC_CHIE (1 << 6) /* Bit 6: Channel Interrupt Enable */
+#define FTM_CSC_CHF (1 << 7) /* Bit 7: Channel Flag */
+
+#define FTM_CV_SHIFT (0) /* Bits 0-15: Channel Value */
+#define FTM_CV_MASK (0xffff << FTM_CV_SHIFT)
+ /* Bits 16-31: Reserved */
+
+#define FTM_CNTIN_SHIFT (0) /* Bits 0-15: Initial Value of the FTM Counter */
+#define FTM_CNTIN_MASK (0xffff << FTM_CNTIN_SHIFT)
+ /* Bits 16-31: Reserved */
+
+#define FTM_STATUS(n) (1 << (n)) /* Channel (n) Flag, n=0..7 */
+ /* Bits 8-31: Reserved */
+#define FTM_MODE_FTMEN (1 << 0) /* Bit 0: FTM Enable */
+#define FTM_MODE_INIT (1 << 1) /* Bit 1: Initialize the Channels Output */
+#define FTM_MODE_WPDIS (1 << 2) /* Bit 2: Write Protection Disable */
+#define FTM_MODE_PWMSYNC (1 << 3) /* Bit 3: PWM Synchronization Mode */
+#define FTM_MODE_CAPTEST (1 << 4) /* Bit 4: Capture Test Mode Enable */
+#define FTM_MODE_FAULTM_SHIFT (5) /* Bits 5-6: Fault Control Mode */
+#define FTM_MODE_FAULTM_MASK (3 << FTM_MODE_FAULTM_SHIFT)
+# define FTM_MODE_FAULTM_DISABLED (0 << FTM_MODE_FAULTM_SHIFT) /* Disabled */
+# define FTM_MODE_FAULTM_EVEN (1 << FTM_MODE_FAULTM_SHIFT) /* Enable even channels, manual fault clearing */
+# define FTM_MODE_FAULTM_MANUAL (2 << FTM_MODE_FAULTM_SHIFT) /* Enable all channels, manual fault clearing */
+# define FTM_MODE_FAULTM_AUTO (3 << FTM_MODE_FAULTM_SHIFT) /* Enable all channels, automatic fault clearing */
+#define FTM_MODE_FAULTIE (1 << 7) /* Bit 7: Fault Interrupt Enable */
+ /* Bits 8-31: Reserved */
+/* Synchronization */
+
+#define FTM_SYNC_CNTMIN (1 << 0) /* Bit 0: Minimum loading point enable */
+#define FTM_SYNC_CNTMAX (1 << 1) /* Bit 1: Maximum loading point enable */
+#define FTM_SYNC_REINIT (1 << 2) /* Bit 2: FTM Counter Reinitialization by Synchron */
+#define FTM_SYNC_SYNCHOM (1 << 3) /* Bit 3: Output Mask Synchronization */
+#define FTM_SYNC_TRIG0 (1 << 4) /* Bit 4: PWM Synchronization Hardware Trigger 0 */
+#define FTM_SYNC_TRIG1 (1 << 5) /* Bit 5: PWM Synchronization Hardware Trigger 1 */
+#define FTM_SYNC_TRIG2 (1 << 6) /* Bit 6: PWM Synchronization Hardware Trigger 2 */
+#define FTM_SYNC_SWSYNC (1 << 7) /* Bit 7: PWM Synchronization Software Trigger */
+ /* Bits 8-31: Reserved */
+/* Initial State for Channels Output */
+
+#define FTM_OUTINIT(n) (1 << (n)) /* Channel (n) Output Initialization Value, n=0..7 */
+ /* Bits 8-31: Reserved */
+/* Output Mask */
+
+#define FTM_OUTMASK(n) (1 << (n)) /* Channel (n) Output Mask, n=0..7 */
+ /* Bits 8-31: Reserved */
+/* Function for Linked Channels */
+
+#define FTM_COMBINE_COMBINE0 (1 << 0) /* Bit 0: Combine Channels for n = 0 */
+#define FTM_COMBINE_COMP0 (1 << 1) /* Bit 1: Complement of Channel (n) for n = 0 */
+#define FTM_COMBINE_DECAPEN0 (1 << 2) /* Bit 2: Dual Edge Capture Mode Enable for n = 0 */
+#define FTM_COMBINE_DECAP0 (1 << 3) /* Bit 3: Dual Edge Capture Mode Captures for n = 0 */
+#define FTM_COMBINE_DTEN0 (1 << 4) /* Bit 4: Deadtime Enable for n = 0 */
+#define FTM_COMBINE_SYNCEN0 (1 << 5) /* Bit 5: Synchronization Enable for n = 0 */
+#define FTM_COMBINE_FAULTEN0 (1 << 6) /* Bit 6: Fault Control Enable for n = 0 */
+ /* Bit 7: Reserved */
+#define FTM_COMBINE_COMBINE1 (1 << 8) /* Bit 8: Combine Channels for n = 2 */
+#define FTM_COMBINE_COMP1 (1 << 9) /* Bit 9: Complement of Channel (n) for n = 2 */
+#define FTM_COMBINE_DECAPEN1 (1 << 10) /* Bit 10: Dual Edge Capture Mode Enable for n = 2 */
+#define FTM_COMBINE_DECAP1 (1 << 11) /* Bit 11: Dual Edge Capture Mode Captures for n = 2 */
+#define FTM_COMBINE_DTEN1 (1 << 12) /* Bit 12: Deadtime Enable for n = 2 */
+#define FTM_COMBINE_SYNCEN1 (1 << 13) /* Bit 13: Synchronization Enable for n = 2 */
+#define FTM_COMBINE_FAULTEN1 (1 << 14) /* Bit 14: Fault Control Enable for n = 2 */
+ /* Bit 15: Reserved */
+#define FTM_COMBINE_COMBINE2 (1 << 16) /* Bit 16: Combine Channels for n = 4 */
+#define FTM_COMBINE_COMP2 (1 << 17) /* Bit 17: Complement of Channel (n) for n = 4 */
+#define FTM_COMBINE_DECAPEN2 (1 << 18) /* Bit 18: Dual Edge Capture Mode Enable for n = 4 */
+#define FTM_COMBINE_DECAP2 (1 << 19) /* Bit 19: Dual Edge Capture Mode Captures for n = 4 */
+#define FTM_COMBINE_DTEN2 (1 << 20) /* Bit 20: Deadtime Enable for n = 4 */
+#define FTM_COMBINE_SYNCEN2 (1 << 21) /* Bit 21: Synchronization Enable for n = 4 */
+#define FTM_COMBINE_FAULTEN2 (1 << 22) /* Bit 22: Fault Control Enable for n = 4 */
+ /* Bit 23: Reserved */
+#define FTM_COMBINE_COMBINE3 (1 << 24) /* Bit 24: Combine Channels for n = 6 */
+#define FTM_COMBINE_COMP3 (1 << 25) /* Bit 25: Complement of Channel (n) for n = 6 */
+#define FTM_COMBINE_DECAPEN3 (1 << 26) /* Bit 26: Dual Edge Capture Mode Enable for n = 6 */
+#define FTM_COMBINE_DECAP3 (1 << 27) /* Bit 27: Dual Edge Capture Mode Captures for n = 6 */
+#define FTM_COMBINE_DTEN3 (1 << 28) /* Bit 28: Deadtime Enable for n = 6 */
+#define FTM_COMBINE_SYNCEN3 (1 << 29) /* Bit 29: Synchronization Enable for n = 6 */
+#define FTM_COMBINE_FAULTEN3 (1 << 30) /* Bit 30: Fault Control Enable for n = 6 */
+ /* Bit 31: Reserved */
+/* Deadtime Insertion Control */
+
+#define FTM_DEADTIME_DTVAL_SHIFT (0) /* Bits 0-5: Deadtime Value */
+#define FTM_DEADTIME_DTVAL_MASK (63 << FTM_DEADTIME_DTVAL_SHIFT)
+#define FTM_DEADTIME_DTPS_SHIFT (6) /* Bits 6-7: Deadtime Prescaler Value */
+#define FTM_DEADTIME_DTPS_MASK (3 << FTM_DEADTIME_DTPS_SHIFT)
+# define FTM_DEADTIME_DTPS_DIV1 (0 << FTM_DEADTIME_DTPS_SHIFT)
+# define FTM_DEADTIME_DTPS_DIV4 (2 << FTM_DEADTIME_DTPS_SHIFT)
+# define FTM_DEADTIME_DTPS_DIV16 (3 << FTM_DEADTIME_DTPS_SHIFT)
+ /* Bits 8-31: Reserved */
+/* FTM External Trigger */
+
+#define FTM_EXTTRIG_CH2TRIG (1 << 0) /* Bit 0: Channel 2 Trigger Enable */
+#define FTM_EXTTRIG_CH3TRIG (1 << 1) /* Bit 1: Channel 3 Trigger Enable */
+#define FTM_EXTTRIG_CH4TRIG (1 << 2) /* Bit 2: Channel 4 Trigger Enable */
+#define FTM_EXTTRIG_CH5TRIG (1 << 3) /* Bit 3: Channel 5 Trigger Enable */
+#define FTM_EXTTRIG_CH0TRIG (1 << 4) /* Bit 4: Channel 0 Trigger Enable */
+#define FTM_EXTTRIG_CH1TRIG (1 << 5) /* Bit 5: Channel 1 Trigger Enable */
+#define FTM_EXTTRIG_INITTRIGEN (1 << 6) /* Bit 6: Initialization Trigger Enable */
+#define FTM_EXTTRIG_TRIGF (1 << 7) /* Bit 7: Channel Trigger Flag */
+ /* Bits 8-31: Reserved */
+/* Channels Polarity */
+
+#define FTM_POL(n) (1 << (n)) /* Channel (n) Polarity, n=0..7 */
+ /* Bits 8-31: Reserved */
+
+/* Fault Mode Status */
+
+#define FTM_FMS_FAULTF0 (1 << 0) /* Bit 0: Fault Detection Flag 0 */
+#define FTM_FMS_FAULTF1 (1 << 1) /* Bit 1: Fault Detection Flag 1 */
+#define FTM_FMS_FAULTF2 (1 << 2) /* Bit 2: Fault Detection Flag 2 */
+#define FTM_FMS_FAULTF3 (1 << 3) /* Bit 3: Fault Detection Flag 3 */
+ /* Bit 4: Reserved */
+#define FTM_FMS_FAULTIN (1 << 5) /* Bit 5: Fault Inputs */
+#define FTM_FMS_WPEN (1 << 6) /* Bit 6: Write Protection Enable */
+#define FTM_FMS_FAULTF (1 << 7) /* Bit 7: Fault Detection Flag */
+ /* Bits 8-31: Reserved */
+/* Input Capture Filter Control */
+
+#define FTM_FILTER_CH0FVAL_SHIFT (0) /* Bits 0-3: Channel 0 Input Filter */
+#define FTM_FILTER_CH0FVAL_MASK (15 << FTM_FILTER_CH0FVAL_SHIFT)
+#define FTM_FILTER_CH1FVAL_SHIFT (4) /* Bits 4-7: Channel 1 Input Filter */
+#define FTM_FILTER_CH1FVAL_MASK (15 << FTM_FILTER_CH1FVAL_SHIFT)
+#define FTM_FILTER_CH2FVAL_SHIFT (8) /* Bits 8-11: Channel 2 Input Filter */
+#define FTM_FILTER_CH2FVAL_MASK (15 << FTM_FILTER_CH2FVAL_SHIFT)
+#define FTM_FILTER_CH3FVAL_SHIFT (12) /* Bits 12-15: Channel 3 Input Filter */
+#define FTM_FILTER_CH3FVAL_MASK (15 << FTM_FILTER_CH3FVAL_SHIFT)
+ /* Bits 16-31: Reserved */
+/* Fault Control */
+
+#define FTM_FLTCTRL_FAULT0EN (1 << 0) /* Bit 0: Fault Input 0 Enable */
+#define FTM_FLTCTRL_FAULT1EN (1 << 1) /* Bit 1: Fault Input 1 Enable */
+#define FTM_FLTCTRL_FAULT2EN (1 << 2) /* Bit 2: Fault Input 2 Enable */
+#define FTM_FLTCTRL_FAULT3EN (1 << 3) /* Bit 3: Fault Input 3 Enable */
+#define FTM_FLTCTRL_FFLTR0EN (1 << 4) /* Bit 4: Fault Input 0 Filter Enable */
+#define FTM_FLTCTRL_FFLTR1EN (1 << 5) /* Bit 5: Fault Input 1 Filter Enable */
+#define FTM_FLTCTRL_FFLTR2EN (1 << 6) /* Bit 6: Fault Input 2 Filter Enable */
+#define FTM_FLTCTRL_FFLTR3EN (1 << 7) /* Bit 7: Fault Input 3 Filter Enable */
+#define FTM_FLTCTRL_FFVAL_SHIFT (8) /* Bits 8-11: Fault Input Filter */
+#define FTM_FLTCTRL_FFVAL_MASK (15 << FTM_FLTCTRL_FFVAL_SHIFT)
+ /* Bits 12-31: Reserved */
+/* Quadrature Decoder Control and Status */
+
+#define FTM_QDCTRL_QUADEN (1 << 0) /* Bit 0: Quadrature Decoder Mode Enable */
+#define FTM_QDCTRL_TOFDIR (1 << 1) /* Bit 1: Timer Overflow Direction in Quadrature Decoder Mode */
+#define FTM_QDCTRL_QUADIR (1 << 2) /* Bit 2: FTM Counter Direction in Quadrature Decoder Mode */
+#define FTM_QDCTRL_QUADMODE (1 << 3) /* Bit 3: Quadrature Decoder Mode */
+#define FTM_QDCTRL_PHBPOL (1 << 4) /* Bit 4: Phase B Input Polarity */
+#define FTM_QDCTRL_PHAPOL (1 << 5) /* Bit 5: Phase A Input Polarity */
+#define FTM_QDCTRL_PHBFLTREN (1 << 6) /* Bit 6: Phase B Input Filter Enable */
+#define FTM_QDCTRL_PHAFLTREN (1 << 7) /* Bit 7: Phase A Input Filter Enable */
+ /* Bits 8-31: Reserved */
+/* Configuration */
+
+#define FTM_CONF_NUMTOF_SHIFT (0) /* Bits 0-4: TOF Frequency */
+#define FTM_CONF_NUMTOF_MASK (31 << FTM_CONF_NUMTOF_SHIFT)
+ /* Bit 5: Reserved */
+#define FTM_CONF_BDMMODE_SHIFT (6) /* Bits 6-7: BDM Mode */
+#define FTM_CONF_BDMMODE_MASK (3 << FTM_CONF_BDMMODE_SHIFT)
+ /* Bit 8: Reserved */
+#define FTM_CONF_GTBEEN (1 << 9) /* Bit 9: Global time base enable */
+#define FTM_CONF_GTBEOUT (1 << 10) /* Bit 10: Global time base output */
+ /* Bits 11-31: Reserved */
+/* FTM Fault Input Polarity */
+
+#define FTM_FLTPOL_FLT0POL (1 << 0) /* Bit 0: Fault Input 0 Polarity */
+#define FTM_FLTPOL_FLT1POL (1 << 1) /* Bit 1: Fault Input 1 Polarity */
+#define FTM_FLTPOL_FLT2POL (1 << 2) /* Bit 2: Fault Input 2 Polarity */
+#define FTM_FLTPOL_FLT3POL (1 << 3) /* Bit 3: Fault Input 3 Polarity */
+ /* Bits 4-31: Reserved */
+/* Synchronization Configuration */
+
+#define FTM_SYNCONF_HWTRIGMODE (1 << 0) /* Bit 0: Hardware Trigger Mode */
+ /* Bit 1: Reserved */
+#define FTM_SYNCONF_CNTINC (1 << 2) /* Bit 2: CNTIN register synchronization */
+ /* Bit 3: Reserved */
+#define FTM_SYNCONF_INVC (1 << 4) /* Bit 4: INVCTRL register synchronization */
+#define FTM_SYNCONF_SWOC (1 << 5) /* Bit 5: SWOCTRL register synchronization */
+ /* Bit 6: Reserved */
+#define FTM_SYNCONF_SYNCMODE (1 << 7) /* Bit 7: Synchronization Mode */
+#define FTM_SYNCONF_SWRSTCNT (1 << 8) /* Bit 8: FTM counter synchronization (S/W) */
+#define FTM_SYNCONF_SWWRBUF (1 << 9) /* Bit 9: MOD, CNTIN, and CV registers synchronization (S/W) */
+#define FTM_SYNCONF_SWOM (1 << 10) /* Bit 10: Output mask synchronization (S/W) */
+#define FTM_SYNCONF_SWINVC (1 << 11) /* Bit 11: Inverting control synchronization (S/W) */
+#define FTM_SYNCONF_SWSOC (1 << 12) /* Bit 12: Software output control synchronization (S/W) */
+ /* Bits 13-15: Reserved */
+#define FTM_SYNCONF_HWRSTCNT (1 << 16) /* Bit 16: FTM counter synchronization (H/W) */
+#define FTM_SYNCONF_HWWRBUF (1 << 17) /* Bit 17: MOD, CNTIN, and CV registers synchronization (H/W) */
+#define FTM_SYNCONF_HWOM (1 << 18) /* Bit 18: Output mask synchronization (H/W) */
+#define FTM_SYNCONF_HWINVC (1 << 19) /* Bit 19: Inverting control synchronization (H/W) */
+#define FTM_SYNCONF_HWSOC (1 << 20) /* Bit 20: Software output control synchronization (H/W) */
+ /* Bits 21-31: Reserved */
+/* FTM Inverting Control */
+
+#define FTM_INVCTRL_INV0EN (1 << 0) /* Bit 0: Pair Channels 0 Inverting Enable */
+#define FTM_INVCTRL_INV1EN (1 << 1) /* Bit 1: Pair Channels 1 Inverting Enable */
+#define FTM_INVCTRL_INV2EN (1 << 2) /* Bit 2: Pair Channels 2 Inverting Enable */
+#define FTM_INVCTRL_INV3EN (1 << 3) /* Bit 3: Pair Channels 3 Inverting Enable */
+ /* Bits 4-31: Reserved */
+/* FTM Software Output Control */
+
+//#define FTM_SWOCTRL_CH7OC(n) (1 << (n)) /* Bits 0-7: Channel (n) Software Output Control Enable */
+#define FTM_SWOCTRL_CH0OC (1 << 0) /* Bit 0: Channel 0 Software Output Control Enable */
+#define FTM_SWOCTRL_CH1OC (1 << 1) /* Bit 1: Channel 1 Software Output Control Enable */
+#define FTM_SWOCTRL_CH2OC (1 << 2) /* Bit 2: Channel 2 Software Output Control Enable */
+#define FTM_SWOCTRL_CH3OC (1 << 3) /* Bit 3: Channel 3 Software Output Control Enable */
+#define FTM_SWOCTRL_CH4OC (1 << 4) /* Bit 4: Channel 4 Software Output Control Enable */
+#define FTM_SWOCTRL_CH5OC (1 << 5) /* Bit 5: Channel 5 Software Output Control Enable */
+#define FTM_SWOCTRL_CH6OC (1 << 6) /* Bit 6: Channel 6 Software Output Control Enable */
+#define FTM_SWOCTRL_CH7OC (1 << 7) /* Bit 7: Channel 7 Software Output Control Enable */
+#define FTM_SWOCTRL_CHOCV(n) (1 << ((n)+8)) /* Bits 8-15: Channel (n) Software Output Control Value */
+#define FTM_SWOCTRL_CH0OCV (1 << 8) /* Bit 8: Channel 0 Software Output Control Value */
+#define FTM_SWOCTRL_CH1OCV (1 << 9) /* Bit 9: Channel 1 Software Output Control Value */
+#define FTM_SWOCTRL_CH2OCV (1 << 10) /* Bit 10: Channel 2 Software Output Control Value */
+#define FTM_SWOCTRL_CH3OCV (1 << 11) /* Bit 11: Channel 3 Software Output Control Value */
+#define FTM_SWOCTRL_CH4OCV (1 << 12) /* Bit 12: Channel 4 Software Output Control Value */
+#define FTM_SWOCTRL_CH5OCV (1 << 13) /* Bit 13: Channel 5 Software Output Control Value */
+#define FTM_SWOCTRL_CH6OCV (1 << 14) /* Bit 14: Channel 6 Software Output Control Value */
+#define FTM_SWOCTRL_CH7OCV (1 << 15) /* Bit 15: Channel 7 Software Output Control Value */
+ /* Bits 16-31: Reserved */
+/* FTM PWM Load */
+
+//#define FTM_PWMLOAD_CH7SEL(n) (1 << (n)) /* Bits 0-7: Channel (n) Select */
+#define FTM_PWMLOAD_CH0SEL (1 << 0) /* Bit 0: Channel 0 Select */
+#define FTM_PWMLOAD_CH1SEL (1 << 1) /* Bit 1: Channel 1 Select */
+#define FTM_PWMLOAD_CH2SEL (1 << 2) /* Bit 2: Channel 2 Select */
+#define FTM_PWMLOAD_CH3SEL (1 << 3) /* Bit 3: Channel 3 Select */
+#define FTM_PWMLOAD_CH4SEL (1 << 4) /* Bit 4: Channel 4 Select */
+#define FTM_PWMLOAD_CH5SEL (1 << 5) /* Bit 5: Channel 5 Select */
+#define FTM_PWMLOAD_CH6SEL (1 << 6) /* Bit 6: Channel 6 Select */
+#define FTM_PWMLOAD_CH7SEL (1 << 7) /* Bit 7: Channel 7 Select */
+ /* Bit 8: Reserved */
+#define FTM_PWMLOAD_LDOK (1 << 9) /* Bit 9: Load Enable */
+ /* Bits 10-31: Reserved */
+#endif
diff --git a/drivers/char/lptimer.c b/drivers/char/lptimer.c
new file mode 100644
index 000000000000..3203580beda1
--- /dev/null
+++ b/drivers/char/lptimer.c
@@ -0,0 +1,349 @@
+/*
+ * drivers/char/lptimer.c
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/cdev.h>
+#include <asm/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <mach/clock.h>
+#include "lptimer_reg.h"
+#include "lptimer.h"
+
+// define for timer master
+#define TIMER_MASTER_MAX_TIMER 1
+#define TIMER_MASTER_ENUM_AVAILABLE 1
+#define TIMER_MASTER_ENUM_MAXCHANNEL 1
+#include "mvf_timer_master.c"
+
+////////////////////////////////////////////////////////////////
+
+#define LPT_DRIVER_NAME "lpt"
+
+struct mvf_lpt_dev {
+ void __iomem *membase;
+ int irq;
+ unsigned long configured;
+ void (*event_handler)(void);
+ struct clk *clk;
+};
+
+
+static irqreturn_t lpt_int_handler(int irq, void *dev_id)
+{
+ struct mvf_lpt_dev *timedevptr = dev_id;
+ unsigned long val;
+ irqreturn_t iret;
+
+ iret = IRQ_HANDLED;
+
+ val = readl( timedevptr->membase + LPTMR_CSR_OFFSET);
+ if (val & LPTMR_CSR_TCF){
+
+ if ( timedevptr->event_handler){
+ (*timedevptr->event_handler)();
+ }
+ // clear 1 write.
+ writel( val, timedevptr->membase + LPTMR_CSR_OFFSET);
+ }else{
+ iret = IRQ_NONE;
+ }
+
+ return iret;
+
+}
+
+int lpt_enable_timer( int timer_handle)
+{
+ struct platform_device *pdev;
+ struct mvf_lpt_dev *timedevptr;
+ void __iomem *membase;
+ unsigned long val;
+
+ if ( !timer_master_is_opened(timer_handle)){
+ return -EAGAIN;
+ }
+
+ pdev = timer_master_get_pdev(timer_handle);
+ timedevptr = platform_get_drvdata(pdev);
+
+ if ( !timedevptr->configured){
+ return -EAGAIN;
+ }
+
+ membase = timedevptr->membase;
+
+ // When TEN is set,the LPTMR is enabled.
+ // While writing 1 to this field, CSR[5:1]
+ // must not be altered.
+ val = readl(membase + LPTMR_CSR_OFFSET);
+ val |= ( LPTMR_CSR_TEN|LPTMR_CSR_TIE);
+ writel( val, membase + LPTMR_CSR_TEN);
+
+ return 0;
+}
+EXPORT_SYMBOL(lpt_enable_timer);
+
+int lpt_disable_timer( int timer_handle)
+{
+ struct platform_device *pdev;
+ struct mvf_lpt_dev *timedevptr;
+ void __iomem *membase;
+ unsigned long val;
+
+ if ( !timer_master_is_opened(timer_handle)){
+ return -EAGAIN;
+ }
+
+ pdev = timer_master_get_pdev(timer_handle);
+ timedevptr = platform_get_drvdata(pdev);
+
+ if ( !timedevptr->configured){
+ return -EAGAIN;
+ }
+
+ membase = timedevptr->membase;
+
+ // When TEN is clear, it resets the LPTMR internal logic,
+ // including the CNR and TCF.
+ val = readl(membase + LPTMR_CSR_OFFSET);
+ val &= ~LPTMR_CSR_TEN;
+ writel( val, membase + LPTMR_CSR_TEN);
+
+ return 0;
+}
+EXPORT_SYMBOL(lpt_disable_timer);
+
+int lpt_alloc_timer( void)
+{
+ return timer_master_alloc_timer(0);
+}
+EXPORT_SYMBOL(lpt_alloc_timer);
+
+int lpt_free_timer( int timer_handle)
+{
+ if ( !lpt_disable_timer( timer_handle)){
+ return timer_master_free( timer_handle);
+ }
+
+ return -EAGAIN;
+}
+EXPORT_SYMBOL( lpt_free_timer);
+
+int lpt_read_counter( int timer_handle, unsigned long *counter)
+{
+ struct platform_device *pdev;
+ struct mvf_lpt_dev *timedevptr;
+
+ if ( !timer_master_is_opened( timer_handle)){
+ return -EAGAIN;
+ }
+ pdev = timer_master_get_pdev(timer_handle);
+ timedevptr = platform_get_drvdata(pdev);
+
+ // 16bit timer
+ *counter = readl( timedevptr->membase + LPTMR_CNR_OFFSET) & 0x0000ffff;
+
+ return 0;
+}
+EXPORT_SYMBOL( lpt_read_counter);
+
+int lpt_param_set( int timer_handle, struct mvf_lpt_request *req, void (*event_handler)(void))
+{
+ void __iomem *membase;
+ struct platform_device *pdev;
+ struct mvf_lpt_dev *timedevptr;
+ unsigned long val;
+
+ if ( !timer_master_is_opened( timer_handle)){
+ return -EAGAIN;
+ }
+
+ pdev = timer_master_get_pdev(timer_handle);
+ timedevptr = platform_get_drvdata(pdev);
+
+ membase = timedevptr->membase;
+ if ( req == NULL){
+ printk( KERN_ERR"lptmr param error \n");
+ return -EINVAL;
+ }
+
+ if( req->timer_mode > LPT_PARAM_TM_PULSECOUNTER){
+ printk( KERN_ERR"lptmr clock mode setting error\n");
+ return -EINVAL;
+ }
+
+ if( req->pulse_pin_polarity > LPT_PARAM_PPP_ACTIVELOW){
+ printk( KERN_ERR"lptmr clock pin polarity error\n");
+ return -EINVAL;
+ }
+
+ if( req->pulse_pin_select > LPT_PARAM_PPS_INPUT3){
+ printk( KERN_ERR"lptmr clock pin polarity error\n");
+ return -EINVAL;
+ }
+
+ if( req->prs_clock_sel > LPT_PARAM_PCS_CLOCK3){
+ printk( KERN_ERR"lptmr clock select error\n");
+ return -EINVAL;
+ }
+
+ if( req->prs_bypass > LPT_PARAM_PB_GF_BYPASS){
+ printk( KERN_ERR"lptmr clock bypass error\n");
+ return -EINVAL;
+ }
+
+
+ if( req->prs_value > LPT_PARAM_PV_DIV65536_RISE32768){
+ printk( KERN_ERR"lptmr clock bypass error\n");
+ return -EINVAL;
+ }
+
+ if( req->compare_value > 0x0000ffff){
+ printk( KERN_ERR"lptmr clock compare value over 16bit\n");
+ }
+
+
+ // clear all param
+ writel( 0, membase + LPTMR_CSR_OFFSET);
+
+ // CSR : TMS(1) TPP(3) TPS(4-5)
+ val = ( req->timer_mode << 1) | ( req->pulse_pin_polarity << 3) | ( req->pulse_pin_select << 4);
+ writel( val, membase + LPTMR_CSR_OFFSET);
+
+ // PSR : PCS(0) PBYP(2) PRESCALE(3-6)
+ val = ( req->prs_clock_sel) | ( req->prs_bypass << 2) | ( req->prs_value << 3);
+ writel( val, membase + LPTMR_PSR_OFFSET);
+
+ // compare
+ writel( req->compare_value, membase + LPTMR_CMR_OFFSET);
+
+ timedevptr->event_handler = event_handler;
+ timedevptr->configured++;
+ // check 32bit cyclic
+ if( timedevptr->configured ==0){
+ timedevptr->configured++;
+ }
+
+
+ return 0;
+}
+EXPORT_SYMBOL( lpt_param_set);
+
+static __devinit
+int lpt_probe(struct platform_device *pdev)
+{
+ int size;
+ int result;
+ struct resource *lptmr_membase, *lptmr_irq;
+ struct mvf_lpt_dev *timedevptr;
+
+ lptmr_membase = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ lptmr_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if (!lptmr_irq || !lptmr_membase){
+ printk(KERN_WARNING"lptmr resource allocation failed\n");
+ return -ENODEV;
+ }
+
+ timedevptr = kzalloc(sizeof(struct mvf_lpt_dev), GFP_KERNEL);
+ if (!timedevptr) {
+ printk(KERN_WARNING"lptmr malloc fail.\n");
+ return -ENOMEM;
+ }
+ timedevptr->clk = clk_get(&pdev->dev, "lptmr_clk");
+ if ( IS_ERR( timedevptr->clk )) {
+ dev_err(&pdev->dev, "Could not low power timer clk\n");
+ return PTR_ERR( timedevptr->clk);
+ }
+ clk_enable( timedevptr->clk);
+
+ size = lptmr_membase->end - lptmr_membase->start + 1;
+ timedevptr->membase = ioremap(lptmr_membase->start, size);
+ if (!timedevptr->membase){
+ printk(KERN_WARNING"lptmr ioremap failed.\n");
+ return -ENOMEM;
+ }
+ timedevptr->irq = lptmr_irq->start;
+
+ result = request_irq(timedevptr->irq, lpt_int_handler, 0, LPT_DRIVER_NAME, timedevptr);
+ if (result < 0) {
+ printk(KERN_WARNING"lptmr Error %d can't get irq.\n", result);
+ return result;
+ }
+
+ platform_set_drvdata(pdev, timedevptr);
+
+ timer_master_register_platform(pdev);
+
+ return 0;
+}
+
+static int __devexit lpt_remove(struct platform_device *pdev)
+{
+ struct mvf_lpt_dev *timedevptr;
+
+ timedevptr = platform_get_drvdata(pdev);
+
+ // disable all
+ lpt_disable_timer( 0);
+ clk_disable( timedevptr->clk);
+ kfree( timedevptr);
+ return 0;
+}
+
+static struct platform_driver lpt_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "mvf-lpt",
+ },
+ .probe = lpt_probe,
+ .remove = lpt_remove,
+};
+
+static int __init lpt_plat_dev_init(void)
+{
+ return platform_driver_register(&lpt_driver);
+}
+
+static void __exit lpt_plat_dev_cleanup(void)
+{
+ platform_driver_unregister(&lpt_driver);
+}
+
+module_init(lpt_plat_dev_init);
+module_exit(lpt_plat_dev_cleanup);
diff --git a/drivers/char/lptimer.h b/drivers/char/lptimer.h
new file mode 100644
index 000000000000..e04a60df0a1d
--- /dev/null
+++ b/drivers/char/lptimer.h
@@ -0,0 +1,77 @@
+/*
+ * drivers/char/lptimer.h
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+struct mvf_lpt_request{
+ unsigned long compare_value;
+ unsigned short timer_mode;
+
+ unsigned short pulse_pin_polarity;
+ unsigned short pulse_pin_select;
+
+ unsigned short prs_clock_sel;
+ unsigned short prs_bypass;
+ unsigned short prs_value;
+};
+
+
+#define LPT_PARAM_TM_TIMECOUNTER 0
+#define LPT_PARAM_TM_PULSECOUNTER 1
+
+#define LPT_PARAM_PPP_ACTIVEHIGH 0
+#define LPT_PARAM_PPP_ACTIVELOW 1
+
+#define LPT_PARAM_PPS_INPUT0 0
+#define LPT_PARAM_PPS_INPUT1 1
+#define LPT_PARAM_PPS_INPUT2 2
+#define LPT_PARAM_PPS_INPUT3 3
+
+
+#define LPT_PARAM_PCS_CLOCK0 0
+#define LPT_PARAM_PCS_CLOCK1 1
+#define LPT_PARAM_PCS_CLOCK2 2
+#define LPT_PARAM_PCS_CLOCK3 3
+
+#define LPT_PARAM_PB_GF_ENABLE 0
+#define LPT_PARAM_PB_GF_BYPASS 1
+
+#define LPT_PARAM_PV_DIV2_NA 0
+#define LPT_PARAM_PV_DIV4_RISE2 1
+#define LPT_PARAM_PV_DIV8_RISE4 2
+#define LPT_PARAM_PV_DIV16_RISE8 3
+#define LPT_PARAM_PV_DIV32_RISE16 4
+#define LPT_PARAM_PV_DIV64_RISE32 5
+#define LPT_PARAM_PV_DIV128_RISE64 6
+#define LPT_PARAM_PV_DIV256_RISE128 7
+#define LPT_PARAM_PV_DIV512_RISE256 8
+#define LPT_PARAM_PV_DIV1024_RISE512 9
+#define LPT_PARAM_PV_DIV2048_RISE1024 10
+#define LPT_PARAM_PV_DIV4096_RISE2048 11
+#define LPT_PARAM_PV_DIV8192_RISE4096 12
+#define LPT_PARAM_PV_DIV16384_RISE8192 13
+#define LPT_PARAM_PV_DIV32768_RISE16384 14
+#define LPT_PARAM_PV_DIV65536_RISE32768 15
+
+int lpt_alloc_timer( void);
+int lpt_free_timer(int timer_handle);
+int lpt_enable_timer( int timer_handle);
+int lpt_disable_timer( int timer_handle);
+int lpt_read_counter(int timer_handle, unsigned long *counter);
+int lpt_param_set( int timer_handle, struct mvf_lpt_request *req, void (*event_handler)(void));
diff --git a/drivers/char/lptimer_reg.h b/drivers/char/lptimer_reg.h
new file mode 100644
index 000000000000..fc78e2708266
--- /dev/null
+++ b/drivers/char/lptimer_reg.h
@@ -0,0 +1,33 @@
+/*
+ * drivers/char/lptimer_reg.h
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define LPTMR_CSR_OFFSET 0x0000
+#define LPTMR_CSR_TEN 0x01
+#define LPTMR_CSR_TMS 0x02
+#define LPTMR_CSR_TFC 0x04
+#define LPTMR_CSR_TPP 0x08
+#define LPTMR_CSR_TIE 0x40
+#define LPTMR_CSR_TCF 0x80
+
+
+#define LPTMR_PSR_OFFSET 0x0004
+#define LPTMR_CMR_OFFSET 0x0008
+#define LPTMR_CNR_OFFSET 0x000C
+
diff --git a/drivers/char/mvf_timer_master.c b/drivers/char/mvf_timer_master.c
new file mode 100644
index 000000000000..56d134d499be
--- /dev/null
+++ b/drivers/char/mvf_timer_master.c
@@ -0,0 +1,113 @@
+/*
+ * drivers/char/mvf_timer_master.c
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+struct timer_master_control{
+ int probe_cnt;
+ int is_opened[ TIMER_MASTER_MAX_TIMER];
+#define TIMER_AVAILABLE 0
+#define TIMER_BUSY 1
+ struct platform_device *plat_timerdev[ TIMER_MASTER_MAX_TIMER];
+};
+
+static struct timer_master_control master_control;
+
+static int timer_master_is_valid_handle(int index)
+{
+ int val;
+
+ val = 0;
+ // error check
+ if ( index > TIMER_MASTER_ENUM_AVAILABLE) val = -EINVAL;
+
+ return val;
+}
+
+static int timer_master_is_opened(int index)
+{
+ int ret;
+
+ ret = timer_master_is_valid_handle(index);
+ if ( ret < 0) return ret;
+
+ return master_control.is_opened[index];
+}
+
+#if 0
+static int timer_master_set_eventhandler( int timer_handle, void (*event_handler)(void))
+{
+ master_control.event_handler[ timer_handle] = event_handler;
+ return 0;
+}
+#endif
+
+
+static struct platform_device *timer_master_get_pdev(int index)
+{
+ return master_control.plat_timerdev[ index];
+}
+
+static void timer_master_register_platform(struct platform_device *plat)
+{
+ int index = master_control.probe_cnt;
+
+ if (master_control.probe_cnt >= TIMER_MASTER_MAX_TIMER){
+ printk(KERN_WARNING"Timer regist count overflow\n");
+ }else{
+ master_control.plat_timerdev[ index] = plat;
+ master_control.probe_cnt++;
+ }
+}
+
+static int timer_master_alloc_timer( int index)
+{
+ int i,ret;
+
+ ret = timer_master_is_valid_handle( index);
+ if ( ret < 0) return ret;
+
+ ret = -EBUSY;
+ if ( index == TIMER_MASTER_ENUM_AVAILABLE){
+ for ( i = 0; i < TIMER_MASTER_MAX_TIMER; i ++){
+ if ( master_control.is_opened[ i] == TIMER_AVAILABLE){
+ master_control.is_opened[ i] = TIMER_BUSY;
+ ret = i;
+ }
+ }
+ }else
+ if ( master_control.is_opened[ index] == TIMER_AVAILABLE){
+ master_control.is_opened[ index] = TIMER_BUSY;
+ ret = index;
+ }
+
+ return ret;
+}
+
+static int timer_master_free(int index)
+{
+ int ret;
+
+ ret = timer_master_is_valid_handle(index);
+ if ( ret < 0) return ret;
+
+ master_control.is_opened[ index] = TIMER_AVAILABLE;
+
+ return 0;
+}
+
diff --git a/drivers/char/pitimer.c b/drivers/char/pitimer.c
new file mode 100644
index 000000000000..b83da781e76c
--- /dev/null
+++ b/drivers/char/pitimer.c
@@ -0,0 +1,323 @@
+/*
+ * drivers/char/pitimer.c
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/cdev.h>
+#include <asm/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <mach/clock.h>
+#include "pitimer_reg.h"
+#include "pitimer.h"
+
+// define for timer master
+#define TIMER_MASTER_MAX_TIMER 8
+#define TIMER_MASTER_ENUM_AVAILABLE PIT_AVAILABLE_CHANNEL
+#define TIMER_MASTER_ENUM_MAXCHANNEL PIT7
+#include "mvf_timer_master.c"
+
+
+// define for pit
+#define PIT_MAXCHANNEL 8
+
+////////////////////////////////////////////////////////////////
+
+#define PIT_DRIVER_NAME "pit"
+
+struct mvf_pit_dev {
+ void __iomem *membase;
+ int irq;
+ unsigned long configured[ PIT_MAXCHANNEL];
+ unsigned long refer_ch[ PIT_MAXCHANNEL];
+ void (*event_handler[ PIT_MAXCHANNEL])(int);
+ struct clk *clk;
+};
+
+
+static irqreturn_t pit_int_handler(int irq, void *dev_id)
+{
+ struct mvf_pit_dev *timedevptr = dev_id;
+ unsigned long val;
+ irqreturn_t iret;
+ int i;
+
+ iret = IRQ_NONE;
+
+ for ( i = 0; i < PIT_MAXCHANNEL; i ++){
+ if ( timedevptr->configured[ i]){
+ val = readl( timedevptr->membase + PIT_TFLG_OFFSET( i));
+ if ( val & PIT_TFLG_TIF){
+ (*timedevptr->event_handler[i])( timedevptr->refer_ch[ i]);
+ }
+ // ack
+ writel( val, timedevptr->membase + PIT_TFLG_OFFSET( i));
+ iret = IRQ_HANDLED;
+ }
+ }
+
+ return iret;
+
+}
+
+int pit_enable_timer( int timer_handle)
+{
+ struct platform_device *pdev;
+ struct mvf_pit_dev *timedevptr;
+ void __iomem *membase;
+ unsigned long val;
+ int i;
+
+ if ( !timer_master_is_opened( timer_handle)){
+ return -EAGAIN;
+ }
+
+ pdev = timer_master_get_pdev(timer_handle);
+ timedevptr = platform_get_drvdata(pdev);
+ i = timer_handle % PIT_MAXCHANNEL;
+
+ if ( !timedevptr->configured[ i]){
+ return -EAGAIN;
+ }
+
+ membase = timedevptr->membase;
+
+ writel( PIT_TFLG_TIF, timedevptr->membase + PIT_TFLG_OFFSET( i));
+ val = PIT_TCTR_TEN | PIT_TCTR_TIE;
+ writel( val, membase + PIT_TCTRL_OFFSET( i));
+
+ return 0;
+}
+EXPORT_SYMBOL(pit_enable_timer);
+
+int pit_disable_timer( int timer_handle)
+{
+ int i;
+ struct platform_device *pdev;
+ struct mvf_pit_dev *timedevptr;
+ void __iomem *membase;
+
+
+ if ( !timer_master_is_opened( timer_handle)){
+ return -EAGAIN;
+ }
+
+ pdev = timer_master_get_pdev( timer_handle);
+ timedevptr = platform_get_drvdata( pdev);
+
+ i = timer_handle % PIT_MAXCHANNEL;
+ if ( !timedevptr->configured[ i]){
+ return -EAGAIN;
+ }
+
+ membase = timedevptr->membase;
+
+ writel( 0, membase + PIT_TCTRL_OFFSET( i));
+
+ return 0;
+}
+EXPORT_SYMBOL(pit_disable_timer);
+
+int pit_alloc_timer( pit_channel ch)
+{
+ return timer_master_alloc_timer( ch);
+}
+EXPORT_SYMBOL(pit_alloc_timer);
+
+int pit_free_timer( int timer_handle)
+{
+ if ( !pit_disable_timer( timer_handle)){
+ return timer_master_free( timer_handle);
+ }
+
+ return -EAGAIN;
+}
+EXPORT_SYMBOL( pit_free_timer);
+
+int pit_read_counter( int timer_handle, unsigned long *counter)
+{
+ struct platform_device *pdev;
+ struct mvf_pit_dev *timedevptr;
+ int i;
+
+ if ( !timer_master_is_opened( timer_handle)){
+ return -EAGAIN;
+ }
+ pdev = timer_master_get_pdev(timer_handle);
+ timedevptr = platform_get_drvdata(pdev);
+
+ i = timer_handle % PIT_MAXCHANNEL;
+
+ // 33bit timer
+ *counter = readl( timedevptr->membase + PIT_CVAL_OFFSET(i));
+
+ return 0;
+}
+EXPORT_SYMBOL( pit_read_counter);
+
+int pit_param_set( int timer_handle, unsigned long load_val, void (*event_handler)(int))
+{
+ int i;
+ void __iomem *membase;
+ struct platform_device *pdev;
+ struct mvf_pit_dev *timedevptr;
+
+
+ if ( !timer_master_is_opened( timer_handle)){
+ return -EAGAIN;
+ }
+
+ pdev = timer_master_get_pdev(timer_handle);
+ timedevptr = platform_get_drvdata(pdev);
+
+ membase = timedevptr->membase;
+ i = timer_handle % PIT_MAXCHANNEL;
+
+ writel( load_val, membase + PIT_LDVAL_OFFSET(i));
+
+ timedevptr->refer_ch[ i] = timer_handle;
+ timedevptr->event_handler[ i] = event_handler;
+
+ timedevptr->configured[ i]++;
+ // check 32bit cyclic
+ if( timedevptr->configured[ i] == 0){
+ timedevptr->configured[ i]++;
+ }
+
+
+ return 0;
+}
+EXPORT_SYMBOL( pit_param_set);
+
+static __devinit
+int pit_probe(struct platform_device *pdev)
+{
+ int size;
+ int result;
+ int i;
+ unsigned long val;
+ struct resource *pit_membase, *pit_irq;
+ struct mvf_pit_dev *timedevptr;
+
+ pit_membase = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ pit_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if (!pit_irq || !pit_membase){
+ printk(KERN_WARNING"PIT resource allocation failed\n");
+ return -ENODEV;
+ }
+
+ timedevptr = kzalloc(sizeof(struct mvf_pit_dev), GFP_KERNEL);
+ if (!timedevptr) {
+ printk(KERN_WARNING"PIT malloc fail.\n");
+ return -ENOMEM;
+ }
+ timedevptr->clk = clk_get(&pdev->dev, "pit_clk");
+ if ( IS_ERR( timedevptr->clk )) {
+ dev_err(&pdev->dev, "Could not pit clk\n");
+ return PTR_ERR( timedevptr->clk);
+ }
+ clk_enable( timedevptr->clk);
+
+ size = pit_membase->end - pit_membase->start + 1;
+ timedevptr->membase = ioremap(pit_membase->start, size);
+ if (!timedevptr->membase){
+ printk(KERN_WARNING"PIT ioremap failed.\n");
+ return -ENOMEM;
+ }
+ timedevptr->irq = pit_irq->start;
+
+ result = request_irq(timedevptr->irq, pit_int_handler, 0, PIT_DRIVER_NAME, timedevptr);
+ if (result < 0) {
+ printk(KERN_WARNING"PIT Error %d can't get irq.\n", result);
+ return result;
+ }
+
+ platform_set_drvdata(pdev, timedevptr);
+
+ // for each channel
+ for ( i = 0; i < TIMER_MASTER_MAX_TIMER; i ++){
+ timer_master_register_platform( pdev);
+ }
+
+ val = readl( timedevptr->membase + PIT_MCR_OFFSET);
+ if( (val & PIT_MCR_MDIS)){
+ // timer clock start
+ writel( 0, timedevptr->membase + PIT_MCR_OFFSET);
+ }else{
+ // assume PIT 0 is kernel system tick
+ pit_alloc_timer( PIT0);
+ printk(KERN_WARNING"Maybe PIT0 is system tick\n");
+ }
+
+ return 0;
+}
+
+static int __devexit pit_remove(struct platform_device *pdev)
+{
+ struct mvf_pit_dev *timedevptr;
+
+ timedevptr = platform_get_drvdata(pdev);
+
+ // disable all
+ pit_disable_timer( 0);
+ clk_disable( timedevptr->clk);
+ kfree( timedevptr);
+
+ return 0;
+}
+
+static struct platform_driver pit_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "mvf-pit",
+ },
+ .probe = pit_probe,
+ .remove = pit_remove,
+};
+
+static int __init pit_plat_dev_init(void)
+{
+ return platform_driver_register(&pit_driver);
+}
+
+static void __exit pit_plat_dev_cleanup(void)
+{
+ platform_driver_unregister(&pit_driver);
+}
+
+module_init(pit_plat_dev_init);
+module_exit(pit_plat_dev_cleanup);
diff --git a/drivers/char/pitimer.h b/drivers/char/pitimer.h
new file mode 100644
index 000000000000..0e1c22c0dd49
--- /dev/null
+++ b/drivers/char/pitimer.h
@@ -0,0 +1,40 @@
+/*
+ * drivers/char/pitimer.h
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+typedef enum {
+ PIT0,
+ PIT1,
+ PIT2,
+ PIT3,
+ PIT4,
+ PIT5,
+ PIT6,
+ PIT7,
+ PIT_AVAILABLE_CHANNEL
+} pit_channel;
+
+
+int pit_alloc_timer( pit_channel ch);
+int pit_free_timer(int timer_handle);
+int pit_enable_timer( int timer_handle);
+int pit_disable_timer( int timer_handle);
+int pit_read_counter(int timer_handle, unsigned long *counter);
+int pit_param_set( int timer_handle, unsigned long load_val, void (*event_handler)(int));
diff --git a/drivers/char/pitimer_reg.h b/drivers/char/pitimer_reg.h
new file mode 100644
index 000000000000..4f9aae4d6513
--- /dev/null
+++ b/drivers/char/pitimer_reg.h
@@ -0,0 +1,37 @@
+/*
+ * drivers/char/pitimer_reg.h
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define PIT_MCR_OFFSET 0x00
+#define PIT_MCR_FRZ 0x01
+#define PIT_MCR_MDIS 0x02
+
+#define PIT_LTMR64H_OFFSET 0x04
+#define PIT_LTMR64L_OFFSET 0x08
+
+
+#define PIT_LDVAL_OFFSET(x) ( ( x * 0x10) + 0x100)
+#define PIT_CVAL_OFFSET(x) ( ( x * 0x10) + 0x104)
+#define PIT_TCTRL_OFFSET(x) ( ( x * 0x10) + 0x108)
+#define PIT_TCTR_TEN 0x01
+#define PIT_TCTR_TIE 0x02
+#define PIT_TCTR_CHN 0x04
+
+#define PIT_TFLG_OFFSET(x) ( ( x * 0x10) + 0x10c)
+#define PIT_TFLG_TIF 0x01