public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v13 00/11] dmtimer adaptation to platform_driver
@ 2011-04-16 15:50 Tarun Kanti DebBarma
  2011-04-16 15:50 ` [PATCH v13 01/11] OMAP2+: dmtimer: add device names to flck nodes Tarun Kanti DebBarma
                   ` (11 more replies)
  0 siblings, 12 replies; 20+ messages in thread
From: Tarun Kanti DebBarma @ 2011-04-16 15:50 UTC (permalink / raw)
  To: linux-omap; +Cc: Tarun Kanti DebBarma

dmtimer adaptation to platform_driver.

This patch series is adaptation of dmtimer code to platform driver
using omap_device and omap_hwmod abstraction.

Baseline:
git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
Branch: devel-timer

Test Info:
* OMAP4430SDP: Functional tests done.
* OMAP3430SDP: Functional tests done 
* OMAP2420SDP: Functional tests done
* OMAP1710SDP: Build test done. Boot test pending.

v13:
(1) Handling of early timer removed because this is being taken care by
Tony's patch series.
(2) Timers reserved for clockevent/clocksource during early boot are
registered and marked reserved.
(3) Platform specific timer code merged to mach-omap2/timer.c.
(4) Timer capabilities are added in the hwmod database to each of the
omap timers.
(5) plat-omap/dmtimer.c plat-omap/include/plat/dmtimer.h are converted
to a driver by moving them to drivers/misc/timer-omap.c and 
include/linux/timer-omap.h

v12:
(1) Remove registration and initialization of all timers during early boot.
Initialize only the system timer which is set by the board file or default
value assigned to it. This timer is not considered later during rest of the
timers initialization.

(2) Use mutex instead of spinlock since there is no interrupt context.

(3) Remove hacky code to manage GPTIMER12 in mach-omap2/dmtimer.c. This is
now changed to use dev_attr instead to identify if it is a secure timer.
In the hwmod database, any secure timer entry can use this dev_attr so that
driver avoids registering tha particular timer.

(4) Removed reset function from OMAP1 and kept it back to its original place
in plat-omap/dmtimer.c, with modification of course. Instead of (is_omap16xx)
flag a new variable (needs_manual_reset) added. This flag is set for OMAP1.
So, call to reset function is made if this value is set implying that reset
is called only for OMAP1.

(5) Timer enable and disable functions cleanup with checks for early boot
condition removed. Added new interface wrapper function to configure
system timer clock source.

(6) Move OMAP4 specific register offsets from mach-omap2 to driver code
along with other register offset definitions.

(7) omap2_dm_timer_early_init() renamed to omap2_system_timer_init(),
omap2_dm_timer_normal_init() renamed to omap2_dm_timer_init().

(8) Use dev_err() instead of pr_err() in low level read/write functions.

TODO:
Somehow pm_runtime_suspended() does not seem to be working as expected
when used in omap_dm_timer_enable() and omap_dm_timer_disable().
Because of this the 'enabled' flag could not be eliminated.


v11:
(1) Removed early timer initialization call from omap2_init_common_devices()
in io.c. It is now called from omap2_gp_timer_init() in timer-gp.c as part
of following call sequence:
start_kernel()->time_init()->timer->init()->omap2_gp_timer_init()
(2) Basedlined on top of Paul's patch series mentioned above.

v10:
(1) Update PM runtime for active early timers so that PM runtime userspace
info is correct.
(2) Include code to configure timers to POSTED mode which got missed in
the previous version.
(3) Remove pm runtime_enable from OMAP1 specific code since this is not
applicable.

v9:
(1) In OMAP3 hwmod database, added entry for timer12 which was missing.
Beagle board uses timer12 as its millisecond timer.
(2) In OMAP3 hwmod database, rectified in-correct prcm configurations
for timer10 and timer11.
From:
       .prcm           = {
                       .module_bit = OMAP24XX_EN_GPT10_SHIFT,
                       .idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
       },
To:
       .prcm           = {
                       .module_bit = OMAP3430_EN_GPT10_SHIFT,
                       .idlest_idle_bit = OMAP3430_ST_GPT10_SHIFT,
               },
(3) In OMAP3 hwmod database, removed timer master port entry for all
timers because it is not supported.

static struct omap_hwmod_ocp_if *omap3xxx_timer7_masters[] = {
       &omap3xxx_l4_per__timer7,
};

(4) In OMAP4 hwmod database, added SIDLE_SMART_WKUP flag for
non-millisecond timers.
(5) In OMAP3 hwmod database, rectified sysconfig configuration for
non-millisecond timers.
From: omap_hwmod_sysc_type2 To: omap_hwmod_sysc_type1.
This was preventing system to go to RETENTION and OFF modes.

v8:
(1) Baselined on Tony's tree in omap-for-linus branch
(2) The last patch in v7 series has been removed because it is fixed
by following patch:
commit: 78f26e872f77b6312273216de1a8f836c6f2e143
OMAP: hwmod: Set autoidle after smartidle during _sysc_enable

v7:
(1) In omap1_dm_timer_set_src(), the computation of shift value to respective
dmtimer clock source was corrected:
From:
int n = (pdev->id) << 1;
To:
int n = (pdev->id - 1) << 1;
This change is needed because dmtimer is indexed from 1 now instead of 0.
(2) In  omap1_dm_timer_init(void) memory resource end address chnaged:
From:
res[0].end = base + 0xff;
To:
res[0].end = base + 0x46;
This was causing request_mem_region() failure in driver probe().
(3) In the export APIs there are some calls which are not applicable to OMAP1.
They have been made conditional now. They include following calls:

timer->fclk = clk_get(&timer->pdev->dev, "fck");
omap_dm_timer_enable()
omap_dm_timer_disable()

(4) Remove usage of cpu_is_omap16xx() and instead a flag has been added in
struct dmtimer_platform_data {
...
u32 is_omap16xx:1;
}
This flag is set to 1 in mach-omap1/dmtimer.c and set to 0 in mach-omap2/dmtimer.c
This flag is used in plat-omap/dmtimer.c wherever it needs to distiguish omap16xx.
(5) Remove #include <plat/omap_device.h> from mach-omap1/dmtimer.c
(6) Instead of using macros like INT_24XX_GPTIMERx, use the numbers
directly in OMAP2420, OMAP2430 and OMAP3xxx hwmod database.
(7) pm_runtime_get_sync() and pm_runtime_put_sync() return value check modified
from positive to negative value:
if (pm_runtime_get_sync(...) < 0) {
...
}

v6:
(1) Removed reset functions to mach-omap1/dmtimer.c.
Access to reset function from plat-omap/dmtimer.c is provided by means
of function pointer.
(2) Remove multiple calls to omap_device_build() for registering timer devices
during early and regular initialization. Regular device registration is now done
by reading data from temporary list. This list is populated during early init
where timer data is read from hwmod database and corresponding memory allocated.
(3) kfree(pdata) under error condition since platform_device_unregister does
not free its pdata.
(4) Removed extra header inclusion in mach-omap2 and plat-omap
NOTE: omap_dm_timer.<id> field could not be removed because during regular boot
there is no mechanism to match the current pdev with corresponding entry in the
timer list which was partially initialized during early boot.

v5:
(1) In mach-omap2/dmtimer.c merged the merged two different init functions
into a single one, viz: omap_timer_init(*oh, *user). Now this function is
used both during early init and later. The distinction is between the two
is made thriugh the *user field.
(2) Added timeout to low-level access routines in place of infinite while
loop which waits on write-pend register bit.
(3) Modified devices names from "omap-timer.x" to "omap_timer.x"
(4) Modified module description from "OMAP DUAL MODE TIMER DRIVER" to:
MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
(5) Use well-defined constants for new IP revision register constants instead
of hard-coded values.
(6) Use consistent naming mechanism by using _dm_timer_ instead of _dmtimer_
wherever applicable.
(7) Removed id field from omap_dm_timer{} since the same can be obtained from
pdev.
(8) clk_get() and clk_put() moved from probe() and remove() functions.
Now clk_get() is called when timer is acquired in the omap_dm_timer_prepare()
and clk_put() is called in omap_dm_timer_free().
(9) Incorporated general comments:
(i) Redundant Copyright information.
(ii) Typos in comments.
(iii) Modify subjects for hwmod database related patches.
(iv) Remove redundant comments from hwmod database as they would be lost during
auto-generation in the future.

v4:
(1) clock aliases are renamed as "32k_ck", "sys_ck" and "alt_ck"
(2) incorporate missing clk_put() for corresponding clk_get()
(3) modified clk_get()/clk_put() to be called once once in platform driver.
(4) consistent header for new files
(5) check return value of omap_hwmod_for_each_by_class() in device init
routines.
(6) remove is_abe_timer field in dmtimer_platform_data structure. this is
no longer needed with new input clock source aliasing.
(7) proper splitting of patch series
(8) remove register map from hwmod database.
(9) remove clock source strings array from hwmod database and associated
structure declaration from plat/dmtimer.h. this is no longer needed.
(10) remove dev_attr from hwmod database. this is no longer needed.
(11) use register offsets to identify OMAP 4 registers instead of register map.
(12) remove clock source name strings from hwmod database.
(13) introduce new mechanism for getting struct clk associated with clock source
names. this is achieved by adding clock alisases for all supported clock sources.
(14) remove clock setup functions in mach-omap2 for populating struct clk
associated with all input clock sources because this is no longer needed with
above implementation.
(15) device names changed from dmtimer to omap-timer
(16) device index starts from 1 instead of 0
(17) remove .init_name from hwmod database. this is not needed.
(18) introduce separate functions for reading/writing interrupt registers instead of
doing all operations within a single function.

v3:
(1) multi-line comment error correction
(2) provision to allow any of the available dmtimers as early timers
instead of restricting them to millisecond timers only.
(3) in 'struct omap_dmtimer{}' is_initialized flag is redundant and
so must be removed. if the element is found in the list it is already
initialized.
(4) remove 'found' flag in omap_dm_timer_request() and
omap_dm_timer_request_specific() functions.
this is not needed with alternate implementation.
(5) use .init_name to initialize device names so that it can be identified
during early boot as well. This is to avoid duplicate functions for clock
manipulations during early boot and later.
(6) remove redundant functions from mach-omap2 which are created just to
call pm functions like: pm_runtime_get_sync(),pm_runtime_put_sync(),..
and instead call them directly from plat-omap function api's.
(7) timer clock source names made part of hwmod database. source_clock[]
of type 'struct clk' is made part of platform data.
(8) clockactivity field initialized in hwmod database to preserve fclk
during idle. code which manipulate OCP config removed since they are
already taken care by hwmod framework.
(9) omap2_dm_timer_set_src() is optimized. Clock enable/disbale routines
moved to plat-omap layer and simplfied to the level so as not to sacrifice
intended functionality.
NOTE: During early boot clock management was requested to be placed upon
client drivers responsibility. this has not been done keeping in mind
that it would entail (i) multiple modifications of client drivers (ii) it
would violate the purpose of having a framework (open to debate).
(10) dmtimer register maps moved to hwmod database

v2:
(1) removed dedicated functions for early timer clock access.
instead, now we have common functions for early and normal timers.
(2) removed usage of clock source strings for reading corresponding
struct clks. this is now achieved through clock aliases introduced
for each input clock sources.
(3) IP revision to distinguish new IP standard and the rest and then
initialize dmtimer interrupt and functional offsets.
(4) provision to initialize all dmtimers as early timers.
(5) remove dm_timer_setup() function because this is no longer needed.
(6) modify the device index to start from 1 instead of 0.
(7) device name changed from dmtimer to omap-timer
(8) extract device ids' from hwmod name and same used for device build.
(9) additional resource allocation checks and free
(10) early timer variable initialization
(11) initialize timer_ip_type and register offsets in platform data structure.
(12) some more comments/logs

Tarun Kanti DebBarma (11):
  OMAP2+: dmtimer: add device names to flck nodes
  OMAP4: hwmod data: add dmtimer version information
  OMAP1: dmtimer: conversion to platform devices
  OMAP2+: dmtimer: convert to platform devices
  OMAP: dmtimer: platform driver
  dmtimer: switch-over to platform device driver
  OMAP: dmtimer: pm_runtime support
  OMAP: dmtimer: add timeout to low-level routines
  OMAP: dmtimer: use mutex instead of spinlock
  OMAP: dmtimer: mark clocksource and clockevent timers reserved
  OMAP: dmtimer: convert to a driver

 arch/arm/mach-omap1/Makefile               |    2 +-
 arch/arm/mach-omap1/dmtimer.c              |  173 ++++++++
 arch/arm/mach-omap1/pm.c                   |    2 +-
 arch/arm/mach-omap1/timer32k.c             |    2 +-
 arch/arm/mach-omap2/clock2420_data.c       |   52 +++-
 arch/arm/mach-omap2/clock2430_data.c       |   48 ++
 arch/arm/mach-omap2/clock3xxx_data.c       |   36 ++
 arch/arm/mach-omap2/clock44xx_data.c       |   33 ++
 arch/arm/mach-omap2/omap_hwmod_2420_data.c |   25 +-
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |   25 +-
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   30 ++-
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   28 ++
 arch/arm/mach-omap2/pm-debug.c             |    2 +-
 arch/arm/mach-omap2/timer.c                |  202 +++++++++-
 arch/arm/plat-omap/Makefile                |    1 -
 arch/arm/plat-omap/dmtimer.c               |  569 +++++++++++-------------
 arch/arm/plat-omap/include/plat/dmtimer.h  |  135 +++++--
 drivers/misc/Makefile                      |    1 +
 drivers/misc/timer-omap.c                  |  643 ++++++++++++++++++++++++++++
 drivers/tty/serial/omap-serial.c           |    2 +-
 include/linux/timer-omap.h                 |  351 +++++++++++++++
 21 files changed, 2003 insertions(+), 359 deletions(-)
 create mode 100644 arch/arm/mach-omap1/dmtimer.c
 create mode 100644 drivers/misc/timer-omap.c
 create mode 100644 include/linux/timer-omap.h


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v13 01/11] OMAP2+: dmtimer: add device names to flck nodes
  2011-04-16 15:50 [PATCH v13 00/11] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
@ 2011-04-16 15:50 ` Tarun Kanti DebBarma
  2011-04-16 15:50 ` [PATCH v13 02/11] OMAP4: hwmod data: add dmtimer version information Tarun Kanti DebBarma
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Tarun Kanti DebBarma @ 2011-04-16 15:50 UTC (permalink / raw)
  To: linux-omap; +Cc: Tarun Kanti DebBarma, Thara Gopinath

Add device name to OMAP2 dmtimer fclk nodes so that the fclk nodes can be
retrieved by doing a clk_get with the corresponding device pointers or
device names.

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com
Signed-off-by: Thara Gopinath <thara@ti.com>
Acked-by: Cousson, Benoit <b-cousson@ti.com>
---
 arch/arm/mach-omap2/clock2420_data.c |   52 ++++++++++++++++++++++++++++++++-
 arch/arm/mach-omap2/clock2430_data.c |   48 +++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/clock3xxx_data.c |   36 +++++++++++++++++++++++
 arch/arm/mach-omap2/clock44xx_data.c |   33 +++++++++++++++++++++
 4 files changed, 167 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index 2926d02..15114f5 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -1838,9 +1838,9 @@ static struct omap_clk omap2420_clks[] = {
 	CLK(NULL,	"gpt9_ick",	&gpt9_ick,	CK_242X),
 	CLK(NULL,	"gpt9_fck",	&gpt9_fck,	CK_242X),
 	CLK(NULL,	"gpt10_ick",	&gpt10_ick,	CK_242X),
-	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_242X),
+	CLK(NULL,	"gpt_10fck",	&gpt10_fck,	CK_242X),
 	CLK(NULL,	"gpt11_ick",	&gpt11_ick,	CK_242X),
-	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_242X),
+	CLK(NULL,	"gpt_11fck",	&gpt11_fck,	CK_242X),
 	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_242X),
 	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_242X),
 	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_242X),
@@ -1898,6 +1898,54 @@ static struct omap_clk omap2420_clks[] = {
 	CLK(NULL,	"pka_ick",	&pka_ick,	CK_242X),
 	CLK(NULL,	"usb_fck",	&usb_fck,	CK_242X),
 	CLK("musb-hdrc",	"fck",	&osc_ck,	CK_242X),
+	CLK("omap_timer.1",	"fck",	&gpt1_fck,	CK_242X),
+	CLK("omap_timer.2",	"fck",	&gpt2_fck,	CK_242X),
+	CLK("omap_timer.3",	"fck",	&gpt3_fck,	CK_242X),
+	CLK("omap_timer.4",	"fck",	&gpt4_fck,	CK_242X),
+	CLK("omap_timer.5",	"fck",	&gpt5_fck,	CK_242X),
+	CLK("omap_timer.6",	"fck",	&gpt6_fck,	CK_242X),
+	CLK("omap_timer.7",	"fck",	&gpt7_fck,	CK_242X),
+	CLK("omap_timer.8",	"fck",	&gpt8_fck,	CK_242X),
+	CLK("omap_timer.9",	"fck",	&gpt9_fck,	CK_242X),
+	CLK("omap_timer.10",	"fck",	&gpt10_fck,	CK_242X),
+	CLK("omap_timer.11",	"fck",	&gpt11_fck,	CK_242X),
+	CLK("omap_timer.12",	"fck",	&gpt12_fck,	CK_242X),
+	CLK("omap_timer.1",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.2",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.3",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.4",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.5",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.6",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.7",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.8",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.9",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.10",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.11",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.12",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.1",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.2",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.3",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.4",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.5",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.6",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.7",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.8",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.9",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.10",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.11",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.12",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.1",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.2",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.3",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.4",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.5",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.6",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.7",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.8",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.9",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.10",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.11",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.12",	"alt_ck",	&alt_ck,	CK_243X),
 };
 
 /*
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index 0c79d39..7b4e688 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -1998,6 +1998,54 @@ static struct omap_clk omap2430_clks[] = {
 	CLK(NULL,	"mdm_intc_ick",	&mdm_intc_ick,	CK_243X),
 	CLK("omap_hsmmc.0", "mmchsdb_fck",	&mmchsdb1_fck,	CK_243X),
 	CLK("omap_hsmmc.1", "mmchsdb_fck",	&mmchsdb2_fck,	CK_243X),
+	CLK("omap_timer.1",     "fck",  &gpt1_fck,      CK_243X),
+	CLK("omap_timer.2",     "fck",  &gpt2_fck,      CK_243X),
+	CLK("omap_timer.3",     "fck",  &gpt3_fck,      CK_243X),
+	CLK("omap_timer.4",     "fck",  &gpt4_fck,      CK_243X),
+	CLK("omap_timer.5",     "fck",  &gpt5_fck,      CK_243X),
+	CLK("omap_timer.6",     "fck",  &gpt6_fck,      CK_243X),
+	CLK("omap_timer.7",     "fck",  &gpt7_fck,      CK_243X),
+	CLK("omap_timer.8",     "fck",  &gpt8_fck,      CK_243X),
+	CLK("omap_timer.9",     "fck",  &gpt9_fck,      CK_243X),
+	CLK("omap_timer.10",    "fck",  &gpt10_fck,     CK_243X),
+	CLK("omap_timer.11",    "fck",  &gpt11_fck,     CK_243X),
+	CLK("omap_timer.12",    "fck",  &gpt12_fck,     CK_243X),
+	CLK("omap_timer.1",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.2",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.3",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.4",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.5",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.6",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.7",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.8",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.9",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.10",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.11",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.12",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.1",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.2",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.3",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.4",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.5",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.6",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.7",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.8",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.9",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.10",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.11",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.12",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.1",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.2",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.3",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.4",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.5",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.6",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.7",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.8",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.9",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.10",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.11",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.12",	"alt_ck",	&alt_ck,	CK_243X),
 };
 
 /*
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 75b119b..7d97525 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -3462,6 +3462,42 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK("musb-am35x",	"fck",		&hsotgusb_fck_am35xx,	CK_AM35XX),
 	CLK(NULL,	"hecc_ck",	&hecc_ck,	CK_AM35XX),
 	CLK(NULL,	"uart4_ick",	&uart4_ick_am35xx,	CK_AM35XX),
+	CLK("omap_timer.1",	"fck",	&gpt1_fck,	CK_3XXX),
+	CLK("omap_timer.2",	"fck",	&gpt2_fck,	CK_3XXX),
+	CLK("omap_timer.3",	"fck",	&gpt3_fck,	CK_3XXX),
+	CLK("omap_timer.4",	"fck",	&gpt4_fck,	CK_3XXX),
+	CLK("omap_timer.5",	"fck",	&gpt5_fck,	CK_3XXX),
+	CLK("omap_timer.6",	"fck",	&gpt6_fck,	CK_3XXX),
+	CLK("omap_timer.7",	"fck",	&gpt7_fck,	CK_3XXX),
+	CLK("omap_timer.8",	"fck",	&gpt8_fck,	CK_3XXX),
+	CLK("omap_timer.9",	"fck",	&gpt9_fck,	CK_3XXX),
+	CLK("omap_timer.10",    "fck",  &gpt10_fck,     CK_3XXX),
+	CLK("omap_timer.11",    "fck",  &gpt11_fck,     CK_3XXX),
+	CLK("omap_timer.12",    "fck",  &gpt12_fck,     CK_3XXX),
+	CLK("omap_timer.1",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.2",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.3",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.4",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.5",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.6",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.7",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.8",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.9",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.10",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.11",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.12",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.1",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.2",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.3",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.4",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.5",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.6",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.7",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.8",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.9",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.10",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.11",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.12",	"sys_ck",	&sys_ck,	CK_3XXX),
 };
 
 
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 276992d..0aa6a25 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3288,6 +3288,39 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"auxclkreq3_ck",		&auxclkreq3_ck,	CK_443X),
 	CLK(NULL,	"auxclkreq4_ck",		&auxclkreq4_ck,	CK_443X),
 	CLK(NULL,	"auxclkreq5_ck",		&auxclkreq5_ck,	CK_443X),
+	CLK("omap_timer.1",	"fck",			&timer1_fck,	CK_443X),
+	CLK("omap_timer.2",	"fck",			&timer2_fck,	CK_443X),
+	CLK("omap_timer.3",	"fck",			&timer3_fck,	CK_443X),
+	CLK("omap_timer.4",	"fck",			&timer4_fck,	CK_443X),
+	CLK("omap_timer.5",	"fck",			&timer5_fck,	CK_443X),
+	CLK("omap_timer.6",	"fck",			&timer6_fck,	CK_443X),
+	CLK("omap_timer.7",	"fck",			&timer7_fck,	CK_443X),
+	CLK("omap_timer.8",	"fck",			&timer8_fck,	CK_443X),
+	CLK("omap_timer.9",	"fck",			&timer9_fck,	CK_443X),
+	CLK("omap_timer.10",	"fck",			&timer10_fck,	CK_443X),
+	CLK("omap_timer.11",	"fck",			&timer11_fck,	CK_443X),
+	CLK("omap_timer.1",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.2",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.3",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.4",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.5",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.6",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.7",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.8",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.9",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.10",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.11",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.1",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.2",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.3",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.4",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.9",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.10",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.11",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.5",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.6",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.7",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.8",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
 };
 
 int __init omap4xxx_clk_init(void)
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v13 02/11] OMAP4: hwmod data: add dmtimer version information
  2011-04-16 15:50 [PATCH v13 00/11] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
  2011-04-16 15:50 ` [PATCH v13 01/11] OMAP2+: dmtimer: add device names to flck nodes Tarun Kanti DebBarma
@ 2011-04-16 15:50 ` Tarun Kanti DebBarma
  2011-04-16 15:50 ` [PATCH v13 03/11] OMAP1: dmtimer: conversion to platform devices Tarun Kanti DebBarma
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Tarun Kanti DebBarma @ 2011-04-16 15:50 UTC (permalink / raw)
  To: linux-omap; +Cc: Tarun Kanti DebBarma, Cousson, Benoit

OMAP4 has two groups of timers: version 1 timers are 1, 2, 10,
while the rest of the timers, 3-9, 11 are version 2 timers.
The version information is required by the driver so that they
could be handled correctly by it.

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
Acked-by: Cousson, Benoit <b-cousson@ti.com>
Cc: Cousson, Benoit <b-cousson@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    3 +++
 arch/arm/plat-omap/include/plat/dmtimer.h  |    4 +++-
 2 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index e2d8c28..a0af525 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -27,6 +27,7 @@
 #include <plat/mcspi.h>
 #include <plat/mcbsp.h>
 #include <plat/mmc.h>
+#include <plat/dmtimer.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -3995,6 +3996,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_timer_1ms_sysc = {
 static struct omap_hwmod_class omap44xx_timer_1ms_hwmod_class = {
 	.name	= "timer",
 	.sysc	= &omap44xx_timer_1ms_sysc,
+	.rev	= OMAP_TIMER_IP_VERSION_1,
 };
 
 static struct omap_hwmod_class_sysconfig omap44xx_timer_sysc = {
@@ -4010,6 +4012,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_timer_sysc = {
 static struct omap_hwmod_class omap44xx_timer_hwmod_class = {
 	.name	= "timer",
 	.sysc	= &omap44xx_timer_sysc,
+	.rev	= OMAP_TIMER_IP_VERSION_2,
 };
 
 /* timer1 */
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 6f4e388..543cec7 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -54,7 +54,9 @@
  * IP revision identifier so that Highlander IP
  * in OMAP4 can be distinguished.
  */
-#define OMAP_TIMER_IP_VERSION_1                        0x1
+#define OMAP_TIMER_IP_VERSION_1			0x1
+#define OMAP_TIMER_IP_VERSION_2			0x2
+
 struct omap_dm_timer;
 extern struct omap_dm_timer *gptimer_wakeup;
 struct clk;
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v13 03/11] OMAP1: dmtimer: conversion to platform devices
  2011-04-16 15:50 [PATCH v13 00/11] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
  2011-04-16 15:50 ` [PATCH v13 01/11] OMAP2+: dmtimer: add device names to flck nodes Tarun Kanti DebBarma
  2011-04-16 15:50 ` [PATCH v13 02/11] OMAP4: hwmod data: add dmtimer version information Tarun Kanti DebBarma
@ 2011-04-16 15:50 ` Tarun Kanti DebBarma
  2011-04-16 15:50 ` [PATCH v13 04/11] OMAP2+: dmtimer: convert " Tarun Kanti DebBarma
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Tarun Kanti DebBarma @ 2011-04-16 15:50 UTC (permalink / raw)
  To: linux-omap; +Cc: Thara Gopinath, Tarun Kanti DebBarma

From: Thara Gopinath <thara@ti.com>

Convert OMAP1 dmtimers into a platform devices and then registers with
device model framework so that it can be bound to corresponding driver.

Signed-off-by: Thara Gopinath <thara@ti.com>
Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
Acked-by: Cousson, Benoit <b-cousson@ti.com>
---
 arch/arm/mach-omap1/Makefile              |    2 +-
 arch/arm/mach-omap1/dmtimer.c             |  174 +++++++++++++++++++++++++++++
 arch/arm/plat-omap/dmtimer.c              |   52 ++-------
 arch/arm/plat-omap/include/plat/dmtimer.h |   10 +-
 4 files changed, 190 insertions(+), 48 deletions(-)
 create mode 100644 arch/arm/mach-omap1/dmtimer.c

diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index af98117..a0ae35f 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o
-obj-y += clock.o clock_data.o opp_data.o reset.o
+obj-y += clock.o clock_data.o opp_data.o reset.o dmtimer.o
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
diff --git a/arch/arm/mach-omap1/dmtimer.c b/arch/arm/mach-omap1/dmtimer.c
new file mode 100644
index 0000000..980b23b
--- /dev/null
+++ b/arch/arm/mach-omap1/dmtimer.c
@@ -0,0 +1,174 @@
+/**
+ * OMAP1 Dual-Mode Timers - platform device registration
+ *
+ * Contains first level initialization routines which internally
+ * generates timer device information and registers with linux
+ * device model. It also has low level function to chnage the timer
+ * input clock source.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+
+#include <plat/dmtimer.h>
+
+#define OMAP1610_GPTIMER1_BASE		0xfffb1400
+#define OMAP1610_GPTIMER2_BASE		0xfffb1c00
+#define OMAP1610_GPTIMER3_BASE		0xfffb2400
+#define OMAP1610_GPTIMER4_BASE		0xfffb2c00
+#define OMAP1610_GPTIMER5_BASE		0xfffb3400
+#define OMAP1610_GPTIMER6_BASE		0xfffb3c00
+#define OMAP1610_GPTIMER7_BASE		0xfffb7400
+#define OMAP1610_GPTIMER8_BASE		0xfffbd400
+
+#define OMAP1_DM_TIMER_COUNT		8
+
+static int omap1_dm_timer_set_src(struct platform_device *pdev,
+				int source)
+{
+	int n = (pdev->id - 1) << 1;
+	u32 l;
+
+	l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
+	l |= source << n;
+	omap_writel(l, MOD_CONF_CTRL_1);
+
+	return 0;
+}
+
+
+int __init omap1_dm_timer_init(void)
+{
+	int i;
+	int ret;
+	struct dmtimer_platform_data *pdata;
+	struct platform_device *pdev;
+
+	if (!cpu_is_omap16xx())
+		return 0;
+
+	for (i = 1; i <= OMAP1_DM_TIMER_COUNT; i++) {
+		struct resource res[2];
+		u32 base, irq;
+
+		switch (i) {
+		case 1:
+			base = OMAP1610_GPTIMER1_BASE;
+			irq = INT_1610_GPTIMER1;
+			break;
+		case 2:
+			base = OMAP1610_GPTIMER2_BASE;
+			irq = INT_1610_GPTIMER2;
+			break;
+		case 3:
+			base = OMAP1610_GPTIMER3_BASE;
+			irq = INT_1610_GPTIMER3;
+			break;
+		case 4:
+			base = OMAP1610_GPTIMER4_BASE;
+			irq = INT_1610_GPTIMER4;
+			break;
+		case 5:
+			base = OMAP1610_GPTIMER5_BASE;
+			irq = INT_1610_GPTIMER5;
+			break;
+		case 6:
+			base = OMAP1610_GPTIMER6_BASE;
+			irq = INT_1610_GPTIMER6;
+			break;
+		case 7:
+			base = OMAP1610_GPTIMER7_BASE;
+			irq = INT_1610_GPTIMER7;
+			break;
+		case 8:
+			base = OMAP1610_GPTIMER8_BASE;
+			irq = INT_1610_GPTIMER8;
+			break;
+		default:
+			/*
+			 * not supposed to reach here.
+			 * this is to remove warning.
+			 */
+			return -EINVAL;
+		}
+
+		pdev = platform_device_alloc("omap_timer", i);
+		if (!pdev) {
+			pr_err("%s: Failed to device alloc for dmtimer%d\n",
+				__func__, i);
+			return -ENOMEM;
+		}
+
+		memset(res, 0, 2 * sizeof(struct resource));
+		res[0].start = base;
+		res[0].end = base + 0x46;
+		res[0].flags = IORESOURCE_MEM;
+		res[1].start = irq;
+		res[1].end = irq;
+		res[1].flags = IORESOURCE_IRQ;
+		ret = platform_device_add_resources(pdev, res,
+				ARRAY_SIZE(res));
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to add resources.\n",
+				__func__);
+			goto err_free_pdev;
+		}
+
+		pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+		if (!pdata) {
+			dev_err(&pdev->dev, "%s: Failed to allocate pdata.\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err_free_pdata;
+		}
+
+		pdata->set_timer_src = omap1_dm_timer_set_src;
+		pdata->timer_ip_type = OMAP_TIMER_IP_VERSION_1;
+		pdata->needs_manual_reset = 1;
+
+		ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to add platform data.\n",
+				__func__);
+			goto err_free_pdata;
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to add platform device.\n",
+				__func__);
+			goto err_free_pdata;
+		}
+
+		dev_dbg(&pdev->dev, " Registered.\n");
+	}
+
+	return 0;
+
+err_free_pdata:
+	kfree(pdata);
+
+err_free_pdev:
+	platform_device_unregister(pdev);
+
+	return ret;
+}
+arch_initcall(omap1_dm_timer_init);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 5163cf4..a88fcdd 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -3,6 +3,12 @@
  *
  * OMAP Dual-Mode Timers
  *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * dmtimer adaptation to platform_driver.
+ *
  * Copyright (C) 2005 Nokia Corporation
  * OMAP2 support by Juha Yrjola
  * API improvements and OMAP2 clock framework support by Timo Teras
@@ -43,25 +49,6 @@
 
 static int dm_timer_count;
 
-#ifdef CONFIG_ARCH_OMAP1
-static struct omap_dm_timer omap1_dm_timers[] = {
-	{ .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
-	{ .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
-	{ .phys_base = 0xfffb2400, .irq = INT_1610_GPTIMER3 },
-	{ .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 },
-	{ .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 },
-	{ .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 },
-	{ .phys_base = 0xfffb7400, .irq = INT_1610_GPTIMER7 },
-	{ .phys_base = 0xfffbd400, .irq = INT_1610_GPTIMER8 },
-};
-
-static const int omap1_dm_timer_count = ARRAY_SIZE(omap1_dm_timers);
-
-#else
-#define omap1_dm_timers			NULL
-#define omap1_dm_timer_count		0
-#endif	/* CONFIG_ARCH_OMAP1 */
-
 #ifdef CONFIG_ARCH_OMAP2
 static struct omap_dm_timer omap2_dm_timers[] = {
 	{ .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
@@ -440,23 +427,6 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer)
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
 
-#ifdef CONFIG_ARCH_OMAP1
-
-int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
-{
-	int n = (timer - dm_timers) << 1;
-	u32 l;
-
-	l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
-	l |= source << n;
-	omap_writel(l, MOD_CONF_CTRL_1);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
-
-#else
-
 int __omap_dm_timer_set_source(struct clk *timer_fck, struct clk *parent)
 {
 	int ret;
@@ -484,8 +454,6 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
 
-#endif
-
 void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
 			    unsigned int load)
 {
@@ -629,16 +597,12 @@ int __init omap_dm_timer_init(void)
 	struct omap_dm_timer *timer;
 	int i, map_size = SZ_8K;	/* Module 4KB + L4 4KB except on omap1 */
 
-	if (!(cpu_is_omap16xx() || cpu_class_is_omap2()))
+	if (!cpu_class_is_omap2())
 		return -ENODEV;
 
 	spin_lock_init(&dm_timer_lock);
 
-	if (cpu_class_is_omap1()) {
-		dm_timers = omap1_dm_timers;
-		dm_timer_count = omap1_dm_timer_count;
-		map_size = SZ_2K;
-	} else if (cpu_is_omap24xx()) {
+	if (cpu_is_omap24xx()) {
 		dm_timers = omap2_dm_timers;
 		dm_timer_count = omap2_dm_timer_count;
 		dm_source_names = omap2_dm_source_names;
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 543cec7..1b76450 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -57,10 +57,15 @@
 #define OMAP_TIMER_IP_VERSION_1			0x1
 #define OMAP_TIMER_IP_VERSION_2			0x2
 
-struct omap_dm_timer;
 extern struct omap_dm_timer *gptimer_wakeup;
 struct clk;
 
+struct dmtimer_platform_data {
+	int (*set_timer_src)(struct platform_device *pdev, int source);
+	int timer_ip_type;
+	u32 needs_manual_reset:1;
+};
+
 int omap_dm_timer_init(void);
 
 struct omap_dm_timer *omap_dm_timer_request(void);
@@ -211,14 +216,13 @@ int omap_dm_timers_active(void);
 struct omap_dm_timer {
 	unsigned long phys_base;
 	int irq;
-#ifdef CONFIG_ARCH_OMAP2PLUS
 	struct clk *iclk, *fclk;
-#endif
 	void __iomem *io_base;
 	unsigned long rate;
 	unsigned reserved:1;
 	unsigned enabled:1;
 	unsigned posted:1;
+	struct platform_device *pdev;
 };
 
 extern u32 sys_timer_reserved;
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v13 04/11] OMAP2+: dmtimer: convert to platform devices
  2011-04-16 15:50 [PATCH v13 00/11] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (2 preceding siblings ...)
  2011-04-16 15:50 ` [PATCH v13 03/11] OMAP1: dmtimer: conversion to platform devices Tarun Kanti DebBarma
@ 2011-04-16 15:50 ` Tarun Kanti DebBarma
  2011-04-25  9:38   ` DebBarma, Tarun Kanti
  2011-04-29 10:45   ` Santosh Shilimkar
  2011-04-16 15:50 ` [PATCH v13 05/11] OMAP: dmtimer: platform driver Tarun Kanti DebBarma
                   ` (7 subsequent siblings)
  11 siblings, 2 replies; 20+ messages in thread
From: Tarun Kanti DebBarma @ 2011-04-16 15:50 UTC (permalink / raw)
  To: linux-omap; +Cc: Tarun Kanti DebBarma, Thara Gopinath

Add routines to converts dmtimers to platform devices. The device data
is obtained from hwmod database of respective platform and is registered
to device model after successful binding to driver.
In addition, capability attribute of each of the timers is added in
hwmod database.

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
Signed-off-by: Thara Gopinath <thara@ti.com>
Acked-by: Cousson, Benoit <b-cousson@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c |   22 ++++
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |   22 ++++
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   27 +++++
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   25 +++++
 arch/arm/mach-omap2/timer.c                |  158 +++++++++++++++++++++++++++-
 arch/arm/plat-omap/dmtimer.c               |   17 ---
 arch/arm/plat-omap/include/plat/dmtimer.h  |   13 ++-
 7 files changed, 265 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index 8eb3ce1..1f7cb36 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -358,6 +358,16 @@ static struct omap_hwmod_class omap2420_timer_hwmod_class = {
 	.rev = OMAP_TIMER_IP_VERSION_1,
 };
 
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap2420_timer1_hwmod;
 static struct omap_hwmod_irq_info omap2420_timer1_mpu_irqs[] = {
@@ -402,6 +412,7 @@ static struct omap_hwmod omap2420_timer1_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer1_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -452,6 +463,7 @@ static struct omap_hwmod omap2420_timer2_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer2_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -502,6 +514,7 @@ static struct omap_hwmod omap2420_timer3_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer3_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -552,6 +565,7 @@ static struct omap_hwmod omap2420_timer4_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer4_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -602,6 +616,7 @@ static struct omap_hwmod omap2420_timer5_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer5_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -653,6 +668,7 @@ static struct omap_hwmod omap2420_timer6_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer6_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -703,6 +719,7 @@ static struct omap_hwmod omap2420_timer7_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer7_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -753,6 +770,7 @@ static struct omap_hwmod omap2420_timer8_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer8_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -803,6 +821,7 @@ static struct omap_hwmod omap2420_timer9_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer9_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -853,6 +872,7 @@ static struct omap_hwmod omap2420_timer10_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer10_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -903,6 +923,7 @@ static struct omap_hwmod omap2420_timer11_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer11_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -953,6 +974,7 @@ static struct omap_hwmod omap2420_timer12_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer12_slaves),
 	.class		= &omap2420_timer_hwmod_class,
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index a860fb5..d7c6487 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -459,6 +459,16 @@ static struct omap_hwmod_class omap2430_timer_hwmod_class = {
 	.rev = OMAP_TIMER_IP_VERSION_1,
 };
 
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap2430_timer1_hwmod;
 static struct omap_hwmod_irq_info omap2430_timer1_mpu_irqs[] = {
@@ -503,6 +513,7 @@ static struct omap_hwmod omap2430_timer1_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer1_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -553,6 +564,7 @@ static struct omap_hwmod omap2430_timer2_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer2_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -603,6 +615,7 @@ static struct omap_hwmod omap2430_timer3_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer3_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -653,6 +666,7 @@ static struct omap_hwmod omap2430_timer4_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer4_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -703,6 +717,7 @@ static struct omap_hwmod omap2430_timer5_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer5_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -753,6 +768,7 @@ static struct omap_hwmod omap2430_timer6_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer6_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -803,6 +819,7 @@ static struct omap_hwmod omap2430_timer7_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer7_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -853,6 +870,7 @@ static struct omap_hwmod omap2430_timer8_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer8_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -903,6 +921,7 @@ static struct omap_hwmod omap2430_timer9_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer9_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -953,6 +972,7 @@ static struct omap_hwmod omap2430_timer10_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer10_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -1003,6 +1023,7 @@ static struct omap_hwmod omap2430_timer11_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer11_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -1053,6 +1074,7 @@ static struct omap_hwmod omap2430_timer12_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer12_slaves),
 	.class		= &omap2430_timer_hwmod_class,
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index b98e2df..7fb2ecc 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -609,6 +609,21 @@ static struct omap_hwmod_class omap3xxx_timer_hwmod_class = {
 	.rev =  OMAP_TIMER_IP_VERSION_1,
 };
 
+/* secure timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_secure_dev_attr = {
+	.timer_capability       = OMAP_TIMER_SECURE,
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap3xxx_timer1_hwmod;
 static struct omap_hwmod_irq_info omap3xxx_timer1_mpu_irqs[] = {
@@ -653,6 +668,7 @@ static struct omap_hwmod omap3xxx_timer1_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer1_slaves),
 	.class		= &omap3xxx_timer_1ms_hwmod_class,
@@ -703,6 +719,7 @@ static struct omap_hwmod omap3xxx_timer2_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer2_slaves),
 	.class		= &omap3xxx_timer_1ms_hwmod_class,
@@ -753,6 +770,7 @@ static struct omap_hwmod omap3xxx_timer3_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer3_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -803,6 +821,7 @@ static struct omap_hwmod omap3xxx_timer4_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer4_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -853,6 +872,7 @@ static struct omap_hwmod omap3xxx_timer5_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer5_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -903,6 +923,7 @@ static struct omap_hwmod omap3xxx_timer6_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer6_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -953,6 +974,7 @@ static struct omap_hwmod omap3xxx_timer7_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer7_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -1003,6 +1025,7 @@ static struct omap_hwmod omap3xxx_timer8_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer8_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -1053,6 +1076,7 @@ static struct omap_hwmod omap3xxx_timer9_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer9_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -1103,6 +1127,7 @@ static struct omap_hwmod omap3xxx_timer10_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer10_slaves),
 	.class		= &omap3xxx_timer_1ms_hwmod_class,
@@ -1153,6 +1178,7 @@ static struct omap_hwmod omap3xxx_timer11_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer11_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -1203,6 +1229,7 @@ static struct omap_hwmod omap3xxx_timer12_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_secure_dev_attr,
 	.slaves		= omap3xxx_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer12_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 6485c90..ab6967b 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -4014,6 +4014,21 @@ static struct omap_hwmod_class omap44xx_timer_hwmod_class = {
 	.rev	= OMAP_TIMER_IP_VERSION_2,
 };
 
+/* secure timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_secure_dev_attr = {
+	.timer_capability	= OMAP_TIMER_SECURE,
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability	= OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability	= OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap44xx_timer1_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = {
@@ -4054,6 +4069,7 @@ static struct omap_hwmod omap44xx_timer1_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer1_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4099,6 +4115,7 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer2_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4144,6 +4161,7 @@ static struct omap_hwmod omap44xx_timer3_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer3_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4189,6 +4207,7 @@ static struct omap_hwmod omap44xx_timer4_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer4_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4253,6 +4272,7 @@ static struct omap_hwmod omap44xx_timer5_hwmod = {
 			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer5_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4317,6 +4337,7 @@ static struct omap_hwmod omap44xx_timer6_hwmod = {
 			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer6_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4381,6 +4402,7 @@ static struct omap_hwmod omap44xx_timer7_hwmod = {
 			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer7_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4445,6 +4467,7 @@ static struct omap_hwmod omap44xx_timer8_hwmod = {
 			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer8_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4490,6 +4513,7 @@ static struct omap_hwmod omap44xx_timer9_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer9_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4535,6 +4559,7 @@ static struct omap_hwmod omap44xx_timer10_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer10_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 2edeb1a..1c80337 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-omap2/timer-gp.c
+ * linux/arch/arm/mach-omap2/timer.c
  *
  * OMAP2 GP timer support.
  *
@@ -35,6 +35,7 @@
 #include <linux/irq.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/slab.h>
 
 #include <asm/mach/time.h>
 #include <plat/dmtimer.h>
@@ -42,6 +43,7 @@
 #include <asm/sched_clock.h>
 #include <plat/common.h>
 #include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 
 /* Parent clocks, eventually these will come from the clock framework */
 
@@ -129,6 +131,23 @@ static struct clock_event_device clockevent_gpt = {
 	.set_mode	= omap2_gp_timer_set_mode,
 };
 
+int __omap_dm_timer_set_source(struct clk *timer_fck, struct clk *parent)
+{
+	int ret;
+
+	clk_disable(timer_fck);
+	ret = clk_set_parent(timer_fck, parent);
+	clk_enable(timer_fck);
+
+	/*
+	 * When the functional clock disappears, too quick writes seem
+	 * to cause an abort. XXX Is this still necessary?
+	 */
+	__delay(300000);
+
+	return ret;
+}
+
 static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
 						int gptimer_id,
 						const char *fck_source)
@@ -359,3 +378,140 @@ struct sys_timer omap4_timer = {
 	.init	= omap4_timer_init,
 };
 #endif
+
+/**
+ * omap2_dm_timer_set_src - change the timer input clock source
+ * @pdev:	timer platform device pointer
+ * @source:	array index of parent clock source
+ */
+static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
+{
+	int ret;
+	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
+	struct clk *fclk, *new_fclk;
+	char *new_fclk_name = NULL;
+
+	fclk = clk_get(&pdev->dev, "fck");
+	if (IS_ERR_OR_NULL(fclk)) {
+		dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
+				__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	switch (source) {
+	case OMAP_TIMER_SRC_SYS_CLK:
+		new_fclk_name = "sys_ck";
+		break;
+
+	case OMAP_TIMER_SRC_32_KHZ:
+		if (unlikely(cpu_is_omap2420()))
+			new_fclk_name = "func_32k_ck";
+		else
+			new_fclk_name = "32k_ck";
+		break;
+
+	case OMAP_TIMER_SRC_EXT_CLK:
+		if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_1) {
+			new_fclk_name = "alt_ck";
+			break;
+		}
+		dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	new_fclk = clk_get(&pdev->dev, new_fclk_name);
+	if (IS_ERR_OR_NULL(new_fclk)) {
+		dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
+			__func__, __LINE__, new_fclk_name);
+		clk_put(fclk);
+		return -EINVAL;
+	}
+
+	ret = clk_set_parent(fclk, new_fclk);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(&pdev->dev, "%s: clk_set_parent() to %s FAILED\n",
+			__func__, new_fclk_name);
+		ret = -EINVAL;
+	}
+
+	clk_put(new_fclk);
+	clk_put(fclk);
+
+	return ret;
+}
+
+struct omap_device_pm_latency omap2_dmtimer_latency[] = {
+	{
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	},
+};
+
+/**
+ * omap_timer_init - build and register timer device with an
+ * associated timer hwmod
+ * @oh:	timer hwmod pointer to be used to build timer device
+ * @user:	parameter that can be passed from calling hwmod API
+ *
+ * Called by omap_hwmod_for_each_by_class to register each of the timer
+ * devices present in the system. The number of timer devices is known
+ * by parsing through the hwmod database for a given class name. At the
+ * end of function call memory is allocated for timer device and it is
+ * registered to the framework ready to be proved by the driver.
+ */
+static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
+{
+	int id;
+	int ret = 0;
+	char *name = "omap_timer";
+	struct dmtimer_platform_data *pdata;
+	struct omap_device *od;
+	struct omap_timer_capability_dev_attr *timer_dev_attr;
+
+	pr_debug("%s: %s\n", __func__, oh->name);
+
+	/* on secure device, do not register secure timer */
+	timer_dev_attr = oh->dev_attr;
+	if (omap_type() != OMAP2_DEVICE_TYPE_GP && timer_dev_attr)
+		if (timer_dev_attr->timer_capability == OMAP_TIMER_SECURE)
+			return ret;
+
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("%s: No memory for [%s]\n", __func__, oh->name);
+		return -ENOMEM;
+	}
+
+	/*
+	 * Extract the IDs from name field in hwmod database
+	 * and use the same for constructing ids' for the
+	 * timer devices. In a way, we are avoiding usage of
+	 * static variable witin the function to do the same.
+	 * CAUTION: We have to be careful and make sure the
+	 * name in hwmod database does not change in which case
+	 * we might either make corresponding change here or
+	 * switch back static variable mechanism.
+	 */
+	sscanf(oh->name, "timer%2d", &id);
+
+	pdata->set_timer_src = omap2_dm_timer_set_src;
+	pdata->timer_ip_type = oh->class->rev;
+	pdata->needs_manual_reset = 0;
+
+	od = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
+			omap2_dmtimer_latency,
+			ARRAY_SIZE(omap2_dmtimer_latency),
+			0);
+
+	if (IS_ERR(od)) {
+		pr_err("%s: Can't build omap_device for %s: %s.\n",
+			__func__, name, oh->name);
+		ret = -EINVAL;
+	}
+
+	kfree(pdata);
+
+	return ret;
+}
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index a88fcdd..0f3e9c9 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -427,23 +427,6 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer)
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
 
-int __omap_dm_timer_set_source(struct clk *timer_fck, struct clk *parent)
-{
-	int ret;
-
-	clk_disable(timer_fck);
-	ret = clk_set_parent(timer_fck, parent);
-	clk_enable(timer_fck);
-
-	/*
-	 * When the functional clock disappears, too quick writes seem
-	 * to cause an abort. XXX Is this still necessary?
-	 */
-	__delay(300000);
-
-	return ret;
-}
-
 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 {
 	if (source < 0 || source >= 3)
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index d59aa86..8fdfaad 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -1,5 +1,5 @@
 /*
- * arch/arm/plat-omap/include/mach/dmtimer.h
+ * arch/arm/plat-omap/include/plat/dmtimer.h
  *
  * OMAP Dual-Mode Timers
  *
@@ -35,6 +35,8 @@
 #ifndef __ASM_ARCH_DMTIMER_H
 #define __ASM_ARCH_DMTIMER_H
 
+#include <linux/platform_device.h>
+
 /* clock sources */
 #define OMAP_TIMER_SRC_SYS_CLK			0x00
 #define OMAP_TIMER_SRC_32_KHZ			0x01
@@ -57,6 +59,15 @@
 #define OMAP_TIMER_IP_VERSION_1			0x1
 #define OMAP_TIMER_IP_VERSION_2			0x2
 
+/* timer capabilities used in hwmod database */
+#define OMAP_TIMER_SECURE				0x80000000
+#define OMAP_TIMER_ALWON				0x40000000
+#define OMAP_TIMER_HAS_PWM				0x20000000
+
+struct omap_timer_capability_dev_attr {
+	u32 timer_capability;
+};
+
 extern struct omap_dm_timer *gptimer_wakeup;
 struct clk;
 
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v13 05/11] OMAP: dmtimer: platform driver
  2011-04-16 15:50 [PATCH v13 00/11] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (3 preceding siblings ...)
  2011-04-16 15:50 ` [PATCH v13 04/11] OMAP2+: dmtimer: convert " Tarun Kanti DebBarma
@ 2011-04-16 15:50 ` Tarun Kanti DebBarma
  2011-04-16 15:50 ` [PATCH v13 06/11] dmtimer: switch-over to platform device driver Tarun Kanti DebBarma
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Tarun Kanti DebBarma @ 2011-04-16 15:50 UTC (permalink / raw)
  To: linux-omap; +Cc: Tarun Kanti DebBarma, Thara Gopinath

Add dmtimer platform driver functions which include:
(1) platform driver initialization
(2) driver probe function
(3) driver remove function

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
Signed-off-by: Thara Gopinath <thara@ti.com>
Acked-by: Cousson, Benoit <b-cousson@ti.com>
---
 arch/arm/plat-omap/dmtimer.c              |  159 +++++++++++++++++++++++++++-
 arch/arm/plat-omap/include/plat/dmtimer.h |   11 ++
 2 files changed, 164 insertions(+), 6 deletions(-)

diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 0f3e9c9..b2398a7 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -35,15 +35,12 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/list.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/io.h>
-#include <linux/module.h>
-#include <mach/hardware.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
 #include <plat/dmtimer.h>
 #include <mach/irqs.h>
 
@@ -149,6 +146,7 @@ static const char **dm_source_names;
 static struct clk **dm_source_clocks;
 
 static spinlock_t dm_timer_lock;
+static LIST_HEAD(omap_timer_list);
 
 /*
  * Reads timer registers in posted and non-posted mode. The posted mode bit
@@ -575,6 +573,155 @@ int omap_dm_timers_active(void)
 }
 EXPORT_SYMBOL_GPL(omap_dm_timers_active);
 
+/**
+ * omap_dm_timer_probe - probe function called for every registered device
+ * @pdev:	pointer to current timer platform device
+ *
+ * Called by driver framework at the end of device registration for all
+ * timer devices.
+ */
+static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
+{
+	int ret;
+	unsigned long flags;
+	struct omap_dm_timer *timer;
+	struct resource *mem, *irq, *ioarea;
+	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
+		return -ENODEV;
+	}
+
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (unlikely(!irq)) {
+		dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
+		ret = -ENODEV;
+		goto err_free_pdev;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(!mem)) {
+		dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
+		ret = -ENODEV;
+		goto err_free_pdev;
+	}
+
+	ioarea = request_mem_region(mem->start, resource_size(mem),
+			pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
+		ret = -EBUSY;
+		goto err_free_pdev;
+	}
+
+	timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
+	if (!timer) {
+		dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_release_ioregion;
+	}
+
+	timer->io_base = ioremap(mem->start, resource_size(mem));
+	if (!timer->io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
+		ret = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_2) {
+		timer->func_offset = VERSION2_TIMER_WAKEUP_EN_REG_OFFSET;
+		timer->intr_offset = VERSION2_TIMER_STAT_REG_OFFSET;
+	} else {
+		timer->func_offset = 0;
+		timer->intr_offset = 0;
+	}
+
+	timer->id = pdev->id;
+	timer->irq = irq->start;
+	timer->pdev = pdev;
+	timer->reserved = 0;
+
+	/* add the timer element to the list */
+	spin_lock_irqsave(&dm_timer_lock, flags);
+	list_add_tail(&timer->node, &omap_timer_list);
+	spin_unlock_irqrestore(&dm_timer_lock, flags);
+
+	dev_dbg(&pdev->dev, "Device Probed.\n");
+
+	return 0;
+
+err_free_mem:
+	kfree(timer);
+
+err_release_ioregion:
+	release_mem_region(mem->start, resource_size(mem));
+
+err_free_pdev:
+	kfree(pdata);
+	platform_device_unregister(pdev);
+
+	return ret;
+}
+
+/**
+ * omap_dm_timer_remove - cleanup a registered timer device
+ * @pdev:	pointer to current timer platform device
+ *
+ * Called by driver framework whenever a timer device is unregistered.
+ * In addition to freeing platform resources it also deletes the timer
+ * entry from the local list.
+ */
+static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
+{
+	struct omap_dm_timer *timer, *tmp;
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	spin_lock_irqsave(&dm_timer_lock, flags);
+	list_for_each_entry_safe(timer, tmp, &omap_timer_list, node) {
+		if (timer->pdev->id == pdev->id) {
+			kfree(timer->pdev->dev.platform_data);
+			platform_device_del(timer->pdev);
+			list_del(&timer->node);
+			kfree(timer);
+			ret = 0;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&dm_timer_lock, flags);
+
+	return ret;
+}
+
+static struct platform_driver omap_dm_timer_driver = {
+	.probe  = omap_dm_timer_probe,
+	.remove = omap_dm_timer_remove,
+	.driver = {
+		.name   = "omap_timer",
+	},
+};
+
+static int __init omap_dm_timer_driver_init(void)
+{
+	return platform_driver_register(&omap_dm_timer_driver);
+}
+
+static void __exit omap_dm_timer_driver_exit(void)
+{
+	platform_driver_unregister(&omap_dm_timer_driver);
+}
+
+early_platform_init("earlytimer", &omap_dm_timer_driver);
+module_init(omap_dm_timer_driver_init);
+module_exit(omap_dm_timer_driver_exit);
+
+MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
+
 int __init omap_dm_timer_init(void)
 {
 	struct omap_dm_timer *timer;
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 00e1a4f..5d4bca1 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -59,6 +59,13 @@
 #define OMAP_TIMER_IP_VERSION_1			0x1
 #define OMAP_TIMER_IP_VERSION_2			0x2
 
+/*
+ * OMAP4 IP revision has different register offsets
+ * for interrupt registers and functional registers.
+ */
+#define VERSION2_TIMER_WAKEUP_EN_REG_OFFSET     0x14
+#define VERSION2_TIMER_STAT_REG_OFFSET          0x10
+
 /* timer capabilities used in hwmod database */
 #define OMAP_TIMER_SECURE				0x80000000
 #define OMAP_TIMER_ALWON				0x40000000
@@ -226,6 +233,7 @@ int omap_dm_timers_active(void);
 
 struct omap_dm_timer {
 	unsigned long phys_base;
+	int id;
 	int irq;
 	struct clk *iclk, *fclk;
 	void __iomem *io_base;
@@ -233,7 +241,10 @@ struct omap_dm_timer {
 	unsigned reserved:1;
 	unsigned enabled:1;
 	unsigned posted:1;
+	u8 func_offset;
+	u8 intr_offset;
 	struct platform_device *pdev;
+	struct list_head node;
 };
 
 extern u32 sys_timer_reserved;
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v13 06/11] dmtimer: switch-over to platform device driver
  2011-04-16 15:50 [PATCH v13 00/11] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (4 preceding siblings ...)
  2011-04-16 15:50 ` [PATCH v13 05/11] OMAP: dmtimer: platform driver Tarun Kanti DebBarma
@ 2011-04-16 15:50 ` Tarun Kanti DebBarma
  2011-04-16 15:50 ` [PATCH v13 07/11] OMAP: dmtimer: pm_runtime support Tarun Kanti DebBarma
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Tarun Kanti DebBarma @ 2011-04-16 15:50 UTC (permalink / raw)
  To: linux-omap; +Cc: Tarun Kanti DebBarma

Register timer devices by going through hwmod database using
hwmod API. The driver probes each of the registered devices.
Functionality which are already performed by hwmod framework
are removed from timer code. New set of timers present on
OMAP4 are now supported.

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
Acked-by: Cousson, Benoit <b-cousson@ti.com>
---
 arch/arm/mach-omap2/timer.c               |   44 +++-
 arch/arm/plat-omap/dmtimer.c              |  377 +++++++++--------------------
 arch/arm/plat-omap/include/plat/dmtimer.h |   74 ++++--
 3 files changed, 205 insertions(+), 290 deletions(-)

diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 1c80337..b7862ca 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -80,7 +80,8 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
 {
 	struct clock_event_device *evt = &clockevent_gpt;
 
-	__omap_dm_timer_write_status(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
+	__omap_dm_timer_write_status(clkev.io_base, OMAP_TIMER_INT_OVERFLOW,
+				0, clkev.intr_offset, clkev.func_offset);
 
 	evt->event_handler(evt);
 	return IRQ_HANDLED;
@@ -96,7 +97,7 @@ static int omap2_gp_timer_set_next_event(unsigned long cycles,
 					 struct clock_event_device *evt)
 {
 	__omap_dm_timer_load_start(clkev.io_base, OMAP_TIMER_CTRL_ST,
-						0xffffffff - cycles, 1);
+				0xffffffff - cycles, 1, clkev.func_offset);
 
 	return 0;
 }
@@ -105,8 +106,10 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
 				    struct clock_event_device *evt)
 {
 	u32 period;
+	unsigned long rate = clk_get_rate(clkev.fclk) + 1;
 
-	omap_dm_timer_stop(&clkev);
+	__omap_dm_timer_stop(clkev.io_base, rate, 0, true, clkev.intr_offset,
+				clkev.func_offset);
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
@@ -131,7 +134,7 @@ static struct clock_event_device clockevent_gpt = {
 	.set_mode	= omap2_gp_timer_set_mode,
 };
 
-int __omap_dm_timer_set_source(struct clk *timer_fck, struct clk *parent)
+static int __omap_dm_timer_set_source(struct clk *timer_fck, struct clk *parent)
 {
 	int ret;
 
@@ -204,6 +207,7 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
 		}
 	}
 	__omap_dm_timer_reset(timer, 1, 1);
+	__omap_dm_timer_set_posted(timer->io_base, timer->func_offset);
 
 	timer->rate = clk_get_rate(timer->fclk);
 
@@ -223,7 +227,8 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
 	omap2_gp_timer_irq.dev_id = (void *)&clkev;
 	setup_irq(clkev.irq, &omap2_gp_timer_irq);
 
-	__omap_dm_timer_int_enable(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
+	__omap_dm_timer_int_enable(clkev.io_base, OMAP_TIMER_INT_OVERFLOW,
+				0, clkev.intr_offset, clkev.func_offset);
 
 	clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
 				     clockevent_gpt.shift);
@@ -264,7 +269,8 @@ static struct omap_dm_timer clksrc;
 static DEFINE_CLOCK_DATA(cd);
 static cycle_t clocksource_read_cycles(struct clocksource *cs)
 {
-	return (cycle_t)__omap_dm_timer_read_counter(clksrc.io_base, 1);
+	return (cycle_t)__omap_dm_timer_read_counter(clksrc.io_base, 1,
+						clksrc.func_offset);
 }
 
 static struct clocksource clocksource_gpt = {
@@ -279,7 +285,8 @@ static void notrace dmtimer_update_sched_clock(void)
 {
 	u32 cyc;
 
-	cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
+	cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1,
+						clksrc.func_offset);
 
 	update_sched_clock(&cd, cyc, (u32)~0);
 }
@@ -289,7 +296,8 @@ unsigned long long notrace sched_clock(void)
 	u32 cyc = 0;
 
 	if (clksrc.reserved)
-		cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
+		cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1,
+							clksrc.func_offset);
 
 	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
@@ -515,3 +523,23 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
 
 	return ret;
 }
+
+/**
+ * omap2_dm_timer_init - top level regular device initialization
+ *
+ * Uses dedicated hwmod api to parse through hwmod database for
+ * given class name and then build and register the timer device.
+ */
+static int __init omap2_dm_timer_init(void)
+{
+	int ret;
+
+	ret = omap_hwmod_for_each_by_class("timer", omap_timer_init, NULL);
+	if (unlikely(ret)) {
+		pr_err("%s: device registration failed.\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+arch_initcall(omap2_dm_timer_init);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index b2398a7..d85791a 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -36,138 +36,55 @@
  */
 
 #include <linux/clk.h>
-#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 
 #include <plat/dmtimer.h>
-#include <mach/irqs.h>
-
-static int dm_timer_count;
-
-#ifdef CONFIG_ARCH_OMAP2
-static struct omap_dm_timer omap2_dm_timers[] = {
-	{ .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
-	{ .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
-	{ .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 },
-	{ .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 },
-	{ .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 },
-	{ .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 },
-	{ .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 },
-	{ .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 },
-	{ .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 },
-	{ .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
-	{ .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
-	{ .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
-};
-
-static const char *omap2_dm_source_names[] __initdata = {
-	"sys_ck",
-	"func_32k_ck",
-	"alt_ck",
-	NULL
-};
-
-static struct clk *omap2_dm_source_clocks[3];
-static const int omap2_dm_timer_count = ARRAY_SIZE(omap2_dm_timers);
-
-#else
-#define omap2_dm_timers			NULL
-#define omap2_dm_timer_count		0
-#define omap2_dm_source_names		NULL
-#define omap2_dm_source_clocks		NULL
-#endif	/* CONFIG_ARCH_OMAP2 */
-
-#ifdef CONFIG_ARCH_OMAP3
-static struct omap_dm_timer omap3_dm_timers[] = {
-	{ .phys_base = 0x48318000, .irq = INT_24XX_GPTIMER1 },
-	{ .phys_base = 0x49032000, .irq = INT_24XX_GPTIMER2 },
-	{ .phys_base = 0x49034000, .irq = INT_24XX_GPTIMER3 },
-	{ .phys_base = 0x49036000, .irq = INT_24XX_GPTIMER4 },
-	{ .phys_base = 0x49038000, .irq = INT_24XX_GPTIMER5 },
-	{ .phys_base = 0x4903A000, .irq = INT_24XX_GPTIMER6 },
-	{ .phys_base = 0x4903C000, .irq = INT_24XX_GPTIMER7 },
-	{ .phys_base = 0x4903E000, .irq = INT_24XX_GPTIMER8 },
-	{ .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 },
-	{ .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
-	{ .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
-	{ .phys_base = 0x48304000, .irq = INT_34XX_GPT12_IRQ },
-};
-
-static const char *omap3_dm_source_names[] __initdata = {
-	"sys_ck",
-	"omap_32k_fck",
-	NULL
-};
-
-static struct clk *omap3_dm_source_clocks[2];
-static const int omap3_dm_timer_count = ARRAY_SIZE(omap3_dm_timers);
-
-#else
-#define omap3_dm_timers			NULL
-#define omap3_dm_timer_count		0
-#define omap3_dm_source_names		NULL
-#define omap3_dm_source_clocks		NULL
-#endif	/* CONFIG_ARCH_OMAP3 */
-
-#ifdef CONFIG_ARCH_OMAP4
-static struct omap_dm_timer omap4_dm_timers[] = {
-	{ .phys_base = 0x4a318000, .irq = OMAP44XX_IRQ_GPT1 },
-	{ .phys_base = 0x48032000, .irq = OMAP44XX_IRQ_GPT2 },
-	{ .phys_base = 0x48034000, .irq = OMAP44XX_IRQ_GPT3 },
-	{ .phys_base = 0x48036000, .irq = OMAP44XX_IRQ_GPT4 },
-	{ .phys_base = 0x40138000, .irq = OMAP44XX_IRQ_GPT5 },
-	{ .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT6 },
-	{ .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT7 },
-	{ .phys_base = 0x4013e000, .irq = OMAP44XX_IRQ_GPT8 },
-	{ .phys_base = 0x4803e000, .irq = OMAP44XX_IRQ_GPT9 },
-	{ .phys_base = 0x48086000, .irq = OMAP44XX_IRQ_GPT10 },
-	{ .phys_base = 0x48088000, .irq = OMAP44XX_IRQ_GPT11 },
-	{ .phys_base = 0x4a320000, .irq = OMAP44XX_IRQ_GPT12 },
-};
-static const char *omap4_dm_source_names[] __initdata = {
-	"sys_clkin_ck",
-	"sys_32k_ck",
-	NULL
-};
-static struct clk *omap4_dm_source_clocks[2];
-static const int omap4_dm_timer_count = ARRAY_SIZE(omap4_dm_timers);
-
-#else
-#define omap4_dm_timers			NULL
-#define omap4_dm_timer_count		0
-#define omap4_dm_source_names		NULL
-#define omap4_dm_source_clocks		NULL
-#endif	/* CONFIG_ARCH_OMAP4 */
-
-static struct omap_dm_timer *dm_timers;
-static const char **dm_source_names;
-static struct clk **dm_source_clocks;
 
-static spinlock_t dm_timer_lock;
 static LIST_HEAD(omap_timer_list);
+static DEFINE_SPINLOCK(dm_timer_lock);
 
-/*
- * Reads timer registers in posted and non-posted mode. The posted mode bit
- * is encoded in reg. Note that in posted mode write pending bit must be
- * checked. Otherwise a read of a non completed write will produce an error.
+/**
+ * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
+ * @timer:      timer pointer over which read operation to perform
+ * @reg:        lowest byte holds the register offset
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode write
+ * pending bit must be checked. Otherwise a read of a non completed write
+ * will produce an error.
  */
 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
 {
-	return __omap_dm_timer_read(timer->io_base, reg, timer->posted);
+	if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
+		reg += timer->func_offset;
+	else if (reg >= OMAP_TIMER_STAT_REG)
+		reg += timer->intr_offset;
+
+	return __omap_dm_timer_read(timer->io_base, reg, timer->posted,
+					timer->func_offset);
 }
 
-/*
- * Writes timer registers in posted and non-posted mode. The posted mode bit
- * is encoded in reg. Note that in posted mode the write pending bit must be
- * checked. Otherwise a write on a register which has a pending write will be
- * lost.
+/**
+ * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
+ * @timer:      timer pointer over which write operation is to perform
+ * @reg:        lowest byte holds the register offset
+ * @value:      data to write into the register
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode the write
+ * pending bit must be checked. Otherwise a write on a register which has a
+ * pending write will be lost.
  */
 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
 						u32 value)
 {
-	__omap_dm_timer_write(timer->io_base, reg, value, timer->posted);
+	if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
+		reg += timer->func_offset;
+	else if (reg >= OMAP_TIMER_STAT_REG)
+		reg += timer->intr_offset;
+
+	__omap_dm_timer_write(timer->io_base, reg, value, timer->posted,
+				timer->func_offset);
 }
 
 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
@@ -201,61 +118,61 @@ void __omap_dm_timer_reset(struct omap_dm_timer *timer, int autoidle,
 		l |= 1 << 2;
 
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
-
-	/* Match hardware reset default of posted mode */
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
-			OMAP_TIMER_CTRL_POSTED);
-	timer->posted = 1;
 }
 
 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
 {
 	int autoidle = 0, wakeup = 0;
 
-	if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
+	if (timer->pdev->id != 1) {
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
 		omap_dm_timer_wait_for_reset(timer);
 	}
-	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
-
-	/* Enable autoidle on OMAP2 / OMAP3 */
-	if (cpu_is_omap24xx() || cpu_is_omap34xx())
-		autoidle = 1;
-
-	/*
-	 * Enable wake-up on OMAP2 CPUs.
-	 */
-	if (cpu_class_is_omap2())
-		wakeup = 1;
-
 	__omap_dm_timer_reset(timer, autoidle, wakeup);
 }
 
 void omap_dm_timer_prepare(struct omap_dm_timer *timer)
 {
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
+	timer->fclk = clk_get(&timer->pdev->dev, "fck");
+	if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
+		timer->fclk = NULL;
+		dev_err(&timer->pdev->dev, ": No fclk handle.\n");
+		return;
+	}
+
 	omap_dm_timer_enable(timer);
-	omap_dm_timer_reset(timer);
+
+	if (pdata->needs_manual_reset)
+		omap_dm_timer_reset(timer);
+
+	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
+
+	__omap_dm_timer_set_posted(timer->io_base, timer->func_offset);
+	timer->posted = 1;
 }
 
 struct omap_dm_timer *omap_dm_timer_request(void)
 {
-	struct omap_dm_timer *timer = NULL;
+	struct omap_dm_timer *timer = NULL, *t;
 	unsigned long flags;
-	int i;
 
 	spin_lock_irqsave(&dm_timer_lock, flags);
-	for (i = 0; i < dm_timer_count; i++) {
-		if (dm_timers[i].reserved)
+	list_for_each_entry(t, &omap_timer_list, node) {
+		if (t->reserved)
 			continue;
 
-		timer = &dm_timers[i];
+		timer = t;
 		timer->reserved = 1;
 		break;
 	}
 	spin_unlock_irqrestore(&dm_timer_lock, flags);
 
-	if (timer != NULL)
+	if (timer)
 		omap_dm_timer_prepare(timer);
+	else
+		pr_debug("%s: free timer not available.\n", __func__);
 
 	return timer;
 }
@@ -263,23 +180,23 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request);
 
 struct omap_dm_timer *omap_dm_timer_request_specific(int id)
 {
-	struct omap_dm_timer *timer;
+	struct omap_dm_timer *timer = NULL, *t;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dm_timer_lock, flags);
-	if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) {
-		spin_unlock_irqrestore(&dm_timer_lock, flags);
-		printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n",
-		       __FILE__, __LINE__, __func__, id);
-		dump_stack();
-		return NULL;
+	list_for_each_entry(t, &omap_timer_list, node) {
+		if (t->pdev->id == id && !t->reserved) {
+			timer = t;
+			timer->reserved = 1;
+			break;
+		}
 	}
-
-	timer = &dm_timers[id-1];
-	timer->reserved = 1;
 	spin_unlock_irqrestore(&dm_timer_lock, flags);
 
-	omap_dm_timer_prepare(timer);
+	if (timer)
+		omap_dm_timer_prepare(timer);
+	else
+		pr_debug("%s: timer%d not available.\n", __func__, id);
 
 	return timer;
 }
@@ -287,10 +204,10 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
 
 void omap_dm_timer_free(struct omap_dm_timer *timer)
 {
-	omap_dm_timer_enable(timer);
-	omap_dm_timer_reset(timer);
 	omap_dm_timer_disable(timer);
 
+	clk_put(timer->fclk);
+
 	WARN_ON(!timer->reserved);
 	timer->reserved = 0;
 }
@@ -301,12 +218,8 @@ void omap_dm_timer_enable(struct omap_dm_timer *timer)
 	if (timer->enabled)
 		return;
 
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	if (cpu_class_is_omap2()) {
-		clk_enable(timer->fclk);
-		clk_enable(timer->iclk);
-	}
-#endif
+	clk_enable(timer->fclk);
+	clk_enable(timer->iclk);
 
 	timer->enabled = 1;
 }
@@ -317,12 +230,8 @@ void omap_dm_timer_disable(struct omap_dm_timer *timer)
 	if (!timer->enabled)
 		return;
 
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	if (cpu_class_is_omap2()) {
-		clk_disable(timer->iclk);
-		clk_disable(timer->fclk);
-	}
-#endif
+	clk_disable(timer->fclk);
+	clk_disable(timer->iclk);
 
 	timer->enabled = 0;
 }
@@ -342,24 +251,30 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
  */
 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 {
-	int i;
+	int i = 0;
+	struct omap_dm_timer *timer = NULL;
+	unsigned long flags;
 
 	/* If ARMXOR cannot be idled this function call is unnecessary */
 	if (!(inputmask & (1 << 1)))
 		return inputmask;
 
 	/* If any active timer is using ARMXOR return modified mask */
-	for (i = 0; i < dm_timer_count; i++) {
+	spin_lock_irqsave(&dm_timer_lock, flags);
+	list_for_each_entry(timer, &omap_timer_list, node) {
+
 		u32 l;
 
-		l = omap_dm_timer_read_reg(&dm_timers[i], OMAP_TIMER_CTRL_REG);
+		l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 		if (l & OMAP_TIMER_CTRL_ST) {
 			if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
 				inputmask &= ~(1 << 1);
 			else
 				inputmask &= ~(1 << 2);
 		}
+		i++;
 	}
+	spin_unlock_irqrestore(&dm_timer_lock, flags);
 
 	return inputmask;
 }
@@ -403,35 +318,38 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_start);
 
 void omap_dm_timer_stop(struct omap_dm_timer *timer)
 {
-	u32 l;
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+	bool omap2 = true;
+	unsigned long rate = clk_get_rate(timer->fclk) + 1;
 
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
-	if (l & OMAP_TIMER_CTRL_ST) {
-		l &= ~0x1;
-		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
-#ifdef CONFIG_ARCH_OMAP2PLUS
-		/* Readback to make sure write has completed */
-		omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
-		 /*
-		  * Wait for functional clock period x 3.5 to make sure that
-		  * timer is stopped
-		  */
-		udelay(3500000 / clk_get_rate(timer->fclk) + 1);
-#endif
-	}
-	/* Ack possibly pending interrupt */
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
-			OMAP_TIMER_INT_OVERFLOW);
+	if (unlikely(pdata->needs_manual_reset))
+		omap2 = false;
+
+	__omap_dm_timer_stop(timer->io_base, rate, timer->posted, omap2,
+			timer->intr_offset, timer->func_offset);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
 
 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 {
+	int ret = -EINVAL;
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
 	if (source < 0 || source >= 3)
 		return -EINVAL;
 
-	return __omap_dm_timer_set_source(timer->fclk,
-						dm_source_clocks[source]);
+	omap_dm_timer_disable(timer);
+	/* change the timer clock source */
+	ret = pdata->set_timer_src(timer->pdev, source);
+	omap_dm_timer_enable(timer);
+
+	/*
+	 * When the functional clock disappears, too quick writes seem
+	 * to cause an abort. XXX Is this still necessary?
+	 */
+	__delay(300000);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
 
@@ -467,7 +385,8 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
 	}
 	l |= OMAP_TIMER_CTRL_ST;
 
-	__omap_dm_timer_load_start(timer->io_base, l, load, timer->posted);
+	__omap_dm_timer_load_start(timer->io_base, l, load, timer->posted,
+					timer->func_offset);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
 
@@ -520,7 +439,8 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
 void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
 				  unsigned int value)
 {
-	__omap_dm_timer_int_enable(timer->io_base, value);
+	__omap_dm_timer_int_enable(timer->io_base, value, timer->posted,
+			timer->intr_offset, timer->func_offset);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
 
@@ -536,13 +456,15 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
 
 void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
 {
-	__omap_dm_timer_write_status(timer->io_base, value);
+	__omap_dm_timer_write_status(timer->io_base, value, timer->posted,
+				timer->intr_offset, timer->func_offset);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
 
 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
 {
-	return __omap_dm_timer_read_counter(timer->io_base, timer->posted);
+	return __omap_dm_timer_read_counter(timer->io_base, timer->posted,
+						timer->func_offset);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
 
@@ -554,13 +476,9 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
 
 int omap_dm_timers_active(void)
 {
-	int i;
-
-	for (i = 0; i < dm_timer_count; i++) {
-		struct omap_dm_timer *timer;
-
-		timer = &dm_timers[i];
+	struct omap_dm_timer *timer;
 
+	list_for_each_entry(timer, &omap_timer_list, node) {
 		if (!timer->enabled)
 			continue;
 
@@ -721,66 +639,3 @@ MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRIVER_NAME);
 MODULE_AUTHOR("Texas Instruments Inc");
-
-int __init omap_dm_timer_init(void)
-{
-	struct omap_dm_timer *timer;
-	int i, map_size = SZ_8K;	/* Module 4KB + L4 4KB except on omap1 */
-
-	if (!cpu_class_is_omap2())
-		return -ENODEV;
-
-	spin_lock_init(&dm_timer_lock);
-
-	if (cpu_is_omap24xx()) {
-		dm_timers = omap2_dm_timers;
-		dm_timer_count = omap2_dm_timer_count;
-		dm_source_names = omap2_dm_source_names;
-		dm_source_clocks = omap2_dm_source_clocks;
-	} else if (cpu_is_omap34xx()) {
-		dm_timers = omap3_dm_timers;
-		dm_timer_count = omap3_dm_timer_count;
-		dm_source_names = omap3_dm_source_names;
-		dm_source_clocks = omap3_dm_source_clocks;
-	} else if (cpu_is_omap44xx()) {
-		dm_timers = omap4_dm_timers;
-		dm_timer_count = omap4_dm_timer_count;
-		dm_source_names = omap4_dm_source_names;
-		dm_source_clocks = omap4_dm_source_clocks;
-	}
-
-	if (cpu_class_is_omap2())
-		for (i = 0; dm_source_names[i] != NULL; i++)
-			dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);
-
-	if (cpu_is_omap243x())
-		dm_timers[0].phys_base = 0x49018000;
-
-	for (i = 0; i < dm_timer_count; i++) {
-		timer = &dm_timers[i];
-
-		/* Static mapping, never released */
-		timer->io_base = ioremap(timer->phys_base, map_size);
-		BUG_ON(!timer->io_base);
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-		if (cpu_class_is_omap2()) {
-			char clk_name[16];
-			sprintf(clk_name, "gpt%d_ick", i + 1);
-			timer->iclk = clk_get(NULL, clk_name);
-			sprintf(clk_name, "gpt%d_fck", i + 1);
-			timer->fclk = clk_get(NULL, clk_name);
-		}
-
-		/* One or two timers may be set up early for sys_timer */
-		if (sys_timer_reserved & (1  << i)) {
-			timer->reserved = 1;
-			timer->posted = 1;
-		}
-#endif
-	}
-
-	return 0;
-}
-
-arch_initcall(omap_dm_timer_init);
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 5d4bca1..3af2e86 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -36,6 +36,7 @@
 #define __ASM_ARCH_DMTIMER_H
 
 #include <linux/platform_device.h>
+#include <linux/delay.h>
 
 /* clock sources */
 #define OMAP_TIMER_SRC_SYS_CLK			0x00
@@ -76,7 +77,6 @@ struct omap_timer_capability_dev_attr {
 };
 
 extern struct omap_dm_timer *gptimer_wakeup;
-struct clk;
 
 struct dmtimer_platform_data {
 	int (*set_timer_src)(struct platform_device *pdev, int source);
@@ -84,8 +84,6 @@ struct dmtimer_platform_data {
 	u32 needs_manual_reset:1;
 };
 
-int omap_dm_timer_init(void);
-
 struct omap_dm_timer *omap_dm_timer_request(void);
 struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
 void omap_dm_timer_free(struct omap_dm_timer *timer);
@@ -250,14 +248,13 @@ struct omap_dm_timer {
 extern u32 sys_timer_reserved;
 void __omap_dm_timer_reset(struct omap_dm_timer *timer, int autoidle,
 				int wakeup);
-void omap_dm_timer_prepare(struct omap_dm_timer *timer);
-int __omap_dm_timer_set_source(struct clk *timer_fck, struct clk *parent);
-void __omap_dm_timer_stop(void __iomem *base, int posted, unsigned long rate);
 
-static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg, int posted)
+static inline u32
+__omap_dm_timer_read(void __iomem *base, u32 reg, int posted, u8 func_offset)
 {
 	if (posted)
-		while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
+		while (__raw_readl(base +
+			((OMAP_TIMER_WRITE_PEND_REG + func_offset) & 0xff))
 				& (reg >> WPSHIFT))
 			cpu_relax();
 
@@ -265,10 +262,11 @@ static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg, int posted)
 }
 
 static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val,
-						int posted)
+						int posted, u8 func_offset)
 {
 	if (posted)
-		while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
+		while (__raw_readl(base +
+			((OMAP_TIMER_WRITE_PEND_REG + func_offset) & 0xff))
 				& (reg >> WPSHIFT))
 			cpu_relax();
 
@@ -276,29 +274,63 @@ static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val,
 }
 
 static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl,
-						unsigned int load, int posted)
+			unsigned int load, int posted, u8 func_offset)
 {
-	__omap_dm_timer_write(base, OMAP_TIMER_COUNTER_REG, load, posted);
-	__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, ctrl, posted);
+	__omap_dm_timer_write(base, OMAP_TIMER_COUNTER_REG + func_offset,
+				load, posted, func_offset);
+	__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG + func_offset,
+				ctrl, posted, func_offset);
 }
 
 static inline void __omap_dm_timer_int_enable(void __iomem *base,
-						unsigned int value)
+		unsigned int value, int posted, u8 intr_offset, u8 func_offset)
 {
-	__omap_dm_timer_write(base, OMAP_TIMER_INT_EN_REG, value, 0);
-	__omap_dm_timer_write(base, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
+	__omap_dm_timer_write(base, OMAP_TIMER_INT_EN_REG + intr_offset,
+				value, posted, func_offset);
+	__omap_dm_timer_write(base, OMAP_TIMER_WAKEUP_EN_REG + func_offset,
+				value, posted, func_offset);
 }
 
-static inline unsigned int __omap_dm_timer_read_counter(void __iomem *base,
-							int posted)
+static inline unsigned int
+__omap_dm_timer_read_counter(void __iomem *base, int posted, u8 func_offset)
 {
-	return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG, posted);
+	return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG + func_offset,
+					posted,	func_offset);
 }
 
 static inline void __omap_dm_timer_write_status(void __iomem *base,
-						unsigned int value)
+		unsigned int value, int posted, u8 intr_offset, u8 func_offset)
+{
+	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG + intr_offset,
+				value, posted, func_offset);
+}
+
+static inline void
+__omap_dm_timer_set_posted(void __iomem *base, u8 func_offset)
 {
-	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG, value, 0);
+	__omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG + func_offset,
+				OMAP_TIMER_CTRL_POSTED, 0, func_offset);
 }
 
+static inline void __omap_dm_timer_stop(void __iomem *base, unsigned long rate,
+			int posted, bool omap2, u8 intr_offset, u8 func_offset)
+{
+	u32 l;
+
+	l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG + func_offset,
+					posted, func_offset);
+	if (l & OMAP_TIMER_CTRL_ST) {
+		l &= ~0x1;
+		__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG + func_offset,
+					l, posted, func_offset);
+		if (omap2) {
+			/* Readback to make sure write has completed */
+			__omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG +
+					func_offset, posted, func_offset);
+			udelay(3500000 / rate);
+		}
+	}
+	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG + intr_offset,
+				OMAP_TIMER_INT_OVERFLOW, posted, func_offset);
+}
 #endif /* __ASM_ARCH_DMTIMER_H */
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v13 07/11] OMAP: dmtimer: pm_runtime support
  2011-04-16 15:50 [PATCH v13 00/11] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (5 preceding siblings ...)
  2011-04-16 15:50 ` [PATCH v13 06/11] dmtimer: switch-over to platform device driver Tarun Kanti DebBarma
@ 2011-04-16 15:50 ` Tarun Kanti DebBarma
  2011-04-16 15:51 ` [PATCH v13 08/11] OMAP: dmtimer: add timeout to low-level routines Tarun Kanti DebBarma
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Tarun Kanti DebBarma @ 2011-04-16 15:50 UTC (permalink / raw)
  To: linux-omap; +Cc: Tarun Kanti DebBarma, Partha Basak

Add pm_runtime feature to dmtimer whereby _get_sync() is called within
omap_dm_timer_enable(), _put_sync() is called in omap_dm_timer_disable().

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
[p-basak2@ti.com: added pm_runtime logic in probe()]
Signed-off-by: Partha Basak <p-basak2@ti.com>
Reviewed-by: Varadarajan, Charulatha <charu@ti.com>
Acked-by: Cousson, Benoit <b-cousson@ti.com>
---
 arch/arm/plat-omap/dmtimer.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 8cd5cf6..b61edc2 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -38,6 +38,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 #include <linux/err.h>
 
 #include <plat/dmtimer.h>
@@ -218,8 +219,7 @@ void omap_dm_timer_enable(struct omap_dm_timer *timer)
 	if (timer->enabled)
 		return;
 
-	clk_enable(timer->fclk);
-	clk_enable(timer->iclk);
+	pm_runtime_get_sync(&timer->pdev->dev);
 
 	timer->enabled = 1;
 }
@@ -230,8 +230,7 @@ void omap_dm_timer_disable(struct omap_dm_timer *timer)
 	if (!timer->enabled)
 		return;
 
-	clk_disable(timer->fclk);
-	clk_disable(timer->iclk);
+	pm_runtime_put_sync(&timer->pdev->dev);
 
 	timer->enabled = 0;
 }
@@ -561,6 +560,10 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
 	timer->pdev = pdev;
 	timer->reserved = 0;
 
+	 /* Skip pm_runtime_enable for OMAP1 */
+	if (!pdata->needs_manual_reset)
+		pm_runtime_enable(&pdev->dev);
+
 	/* add the timer element to the list */
 	spin_lock_irqsave(&dm_timer_lock, flags);
 	list_add_tail(&timer->node, &omap_timer_list);
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v13 08/11] OMAP: dmtimer: add timeout to low-level routines
  2011-04-16 15:50 [PATCH v13 00/11] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (6 preceding siblings ...)
  2011-04-16 15:50 ` [PATCH v13 07/11] OMAP: dmtimer: pm_runtime support Tarun Kanti DebBarma
@ 2011-04-16 15:51 ` Tarun Kanti DebBarma
  2011-04-16 15:51 ` [PATCH v13 09/11] OMAP: dmtimer: use mutex instead of spinlock Tarun Kanti DebBarma
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Tarun Kanti DebBarma @ 2011-04-16 15:51 UTC (permalink / raw)
  To: linux-omap; +Cc: Tarun Kanti DebBarma

The low-level read and write access routines wait on write-pending register
in posted mode to make sure that previous write is complete on respective
registers. This waiting is done in an infinite while loop. Now it is being
modified to use timeout instead.

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
Reviewed-by: Varadarajan, Charulatha <charu@ti.com>
Acked-by: Cousson, Benoit <b-cousson@ti.com>
---
 arch/arm/plat-omap/include/plat/dmtimer.h |   33 ++++++++++++++++++++--------
 1 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 53fd69b..b1c8091 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -37,6 +37,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <plat/common.h>
 
 /* clock sources */
 #define OMAP_TIMER_SRC_SYS_CLK			0x00
@@ -229,6 +230,8 @@ int omap_dm_timers_active(void);
 #define OMAP_TIMER_TICK_INT_MASK_COUNT_REG				\
 		(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
 
+#define MAX_WRITE_PEND_WAIT            10000 /* 10ms timeout delay */
+
 struct omap_dm_timer {
 	unsigned long phys_base;
 	int id;
@@ -254,11 +257,16 @@ void __omap_dm_timer_reset(struct omap_dm_timer *timer, int autoidle,
 static inline u32
 __omap_dm_timer_read(void __iomem *base, u32 reg, int posted, u8 func_offset)
 {
-	if (posted)
-		while (__raw_readl(base +
-			((OMAP_TIMER_WRITE_PEND_REG + func_offset) & 0xff))
-				& (reg >> WPSHIFT))
-			cpu_relax();
+	int i = 0;
+
+	if (posted) {
+		omap_test_timeout(!(__raw_readl(base +
+			((OMAP_TIMER_WRITE_PEND_REG + func_offset) & 0xff)) &
+			(reg >> WPSHIFT)), MAX_WRITE_PEND_WAIT, i);
+
+		if (WARN_ON_ONCE(i == MAX_WRITE_PEND_WAIT))
+			pr_err("read timeout.\n");
+	}
 
 	return __raw_readl(base + (reg & 0xff));
 }
@@ -266,11 +274,16 @@ __omap_dm_timer_read(void __iomem *base, u32 reg, int posted, u8 func_offset)
 static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val,
 						int posted, u8 func_offset)
 {
-	if (posted)
-		while (__raw_readl(base +
-			((OMAP_TIMER_WRITE_PEND_REG + func_offset) & 0xff))
-				& (reg >> WPSHIFT))
-			cpu_relax();
+	int i = 0;
+
+	if (posted) {
+		omap_test_timeout(!(__raw_readl(base +
+			((OMAP_TIMER_WRITE_PEND_REG + func_offset) & 0xff)) &
+			(reg >> WPSHIFT)), MAX_WRITE_PEND_WAIT, i);
+
+		if (WARN_ON(i == MAX_WRITE_PEND_WAIT))
+			pr_err("write timeout.\n");
+	}
 
 	__raw_writel(val, base + (reg & 0xff));
 }
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v13 09/11] OMAP: dmtimer: use mutex instead of spinlock
  2011-04-16 15:50 [PATCH v13 00/11] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (7 preceding siblings ...)
  2011-04-16 15:51 ` [PATCH v13 08/11] OMAP: dmtimer: add timeout to low-level routines Tarun Kanti DebBarma
@ 2011-04-16 15:51 ` Tarun Kanti DebBarma
  2011-04-16 15:51 ` [PATCH v13 10/11] OMAP: dmtimer: mark clocksource and clockevent timers reserved Tarun Kanti DebBarma
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Tarun Kanti DebBarma @ 2011-04-16 15:51 UTC (permalink / raw)
  To: linux-omap; +Cc: Tarun Kanti DebBarma

Since the spinlock is not used in any interrupt context we can
replace it with mutex instead.

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
---
 arch/arm/plat-omap/dmtimer.c |   27 +++++++++++----------------
 1 files changed, 11 insertions(+), 16 deletions(-)

diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index b61edc2..0716fdb 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -44,7 +44,7 @@
 #include <plat/dmtimer.h>
 
 static LIST_HEAD(omap_timer_list);
-static DEFINE_SPINLOCK(dm_timer_lock);
+static DEFINE_MUTEX(dm_timer_mutex);
 
 /**
  * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
@@ -157,9 +157,8 @@ void omap_dm_timer_prepare(struct omap_dm_timer *timer)
 struct omap_dm_timer *omap_dm_timer_request(void)
 {
 	struct omap_dm_timer *timer = NULL, *t;
-	unsigned long flags;
 
-	spin_lock_irqsave(&dm_timer_lock, flags);
+	mutex_lock(&dm_timer_mutex);
 	list_for_each_entry(t, &omap_timer_list, node) {
 		if (t->reserved)
 			continue;
@@ -168,7 +167,7 @@ struct omap_dm_timer *omap_dm_timer_request(void)
 		timer->reserved = 1;
 		break;
 	}
-	spin_unlock_irqrestore(&dm_timer_lock, flags);
+	mutex_unlock(&dm_timer_mutex);
 
 	if (timer)
 		omap_dm_timer_prepare(timer);
@@ -182,9 +181,8 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request);
 struct omap_dm_timer *omap_dm_timer_request_specific(int id)
 {
 	struct omap_dm_timer *timer = NULL, *t;
-	unsigned long flags;
 
-	spin_lock_irqsave(&dm_timer_lock, flags);
+	mutex_lock(&dm_timer_mutex);
 	list_for_each_entry(t, &omap_timer_list, node) {
 		if (t->pdev->id == id && !t->reserved) {
 			timer = t;
@@ -192,7 +190,7 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
 			break;
 		}
 	}
-	spin_unlock_irqrestore(&dm_timer_lock, flags);
+	mutex_unlock(&dm_timer_mutex);
 
 	if (timer)
 		omap_dm_timer_prepare(timer);
@@ -252,14 +250,13 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 {
 	int i = 0;
 	struct omap_dm_timer *timer = NULL;
-	unsigned long flags;
 
 	/* If ARMXOR cannot be idled this function call is unnecessary */
 	if (!(inputmask & (1 << 1)))
 		return inputmask;
 
 	/* If any active timer is using ARMXOR return modified mask */
-	spin_lock_irqsave(&dm_timer_lock, flags);
+	mutex_lock(&dm_timer_mutex);
 	list_for_each_entry(timer, &omap_timer_list, node) {
 
 		u32 l;
@@ -273,7 +270,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 		}
 		i++;
 	}
-	spin_unlock_irqrestore(&dm_timer_lock, flags);
+	mutex_unlock(&dm_timer_mutex);
 
 	return inputmask;
 }
@@ -500,7 +497,6 @@ EXPORT_SYMBOL_GPL(omap_dm_timers_active);
 static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
 {
 	int ret;
-	unsigned long flags;
 	struct omap_dm_timer *timer;
 	struct resource *mem, *irq, *ioarea;
 	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
@@ -565,9 +561,9 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
 		pm_runtime_enable(&pdev->dev);
 
 	/* add the timer element to the list */
-	spin_lock_irqsave(&dm_timer_lock, flags);
+	mutex_lock(&dm_timer_mutex);
 	list_add_tail(&timer->node, &omap_timer_list);
-	spin_unlock_irqrestore(&dm_timer_lock, flags);
+	mutex_unlock(&dm_timer_mutex);
 
 	dev_dbg(&pdev->dev, "Device Probed.\n");
 
@@ -597,10 +593,9 @@ err_free_pdev:
 static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
 {
 	struct omap_dm_timer *timer, *tmp;
-	unsigned long flags;
 	int ret = -EINVAL;
 
-	spin_lock_irqsave(&dm_timer_lock, flags);
+	mutex_lock(&dm_timer_mutex);
 	list_for_each_entry_safe(timer, tmp, &omap_timer_list, node) {
 		if (timer->pdev->id == pdev->id) {
 			kfree(timer->pdev->dev.platform_data);
@@ -611,7 +606,7 @@ static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
 			break;
 		}
 	}
-	spin_unlock_irqrestore(&dm_timer_lock, flags);
+	mutex_unlock(&dm_timer_mutex);
 
 	return ret;
 }
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v13 10/11] OMAP: dmtimer: mark clocksource and clockevent timers reserved
  2011-04-16 15:50 [PATCH v13 00/11] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (8 preceding siblings ...)
  2011-04-16 15:51 ` [PATCH v13 09/11] OMAP: dmtimer: use mutex instead of spinlock Tarun Kanti DebBarma
@ 2011-04-16 15:51 ` Tarun Kanti DebBarma
  2011-04-17  6:12   ` Santosh Shilimkar
  2011-04-25  9:41   ` DebBarma, Tarun Kanti
  2011-04-16 15:51 ` [PATCH v13 11/11] OMAP: dmtimer: convert to a driver Tarun Kanti DebBarma
  2011-04-29 11:05 ` [PATCH v13 00/11] dmtimer adaptation to platform_driver Santosh Shilimkar
  11 siblings, 2 replies; 20+ messages in thread
From: Tarun Kanti DebBarma @ 2011-04-16 15:51 UTC (permalink / raw)
  To: linux-omap; +Cc: Tarun Kanti DebBarma

In driver probe use sys_timer_reserved to identify which all timers
have already been used for clocksource and clockevent. Mark all those
timers as reserved so that no one else can use them.

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
---
 arch/arm/plat-omap/dmtimer.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index e15b3a8..8b6fd22 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -554,7 +554,13 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
 	timer->id = pdev->id;
 	timer->irq = irq->start;
 	timer->pdev = pdev;
-	timer->reserved = 0;
+#if defined(CONFIG_ARCH_OMAP2)
+	/* Mark clocksource and clockevent timers as reserved */
+	if ((sys_timer_reserved >> (pdev->id - 1)) & 0x1)
+		timer->reserved = 1;
+	else
+#endif
+		timer->reserved = 0;
 
 	 /* Skip pm_runtime_enable for OMAP1 */
 	if (!pdata->needs_manual_reset)
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v13 11/11] OMAP: dmtimer: convert to a driver
  2011-04-16 15:50 [PATCH v13 00/11] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (9 preceding siblings ...)
  2011-04-16 15:51 ` [PATCH v13 10/11] OMAP: dmtimer: mark clocksource and clockevent timers reserved Tarun Kanti DebBarma
@ 2011-04-16 15:51 ` Tarun Kanti DebBarma
  2011-04-29 10:51   ` Santosh Shilimkar
  2011-04-29 11:05 ` [PATCH v13 00/11] dmtimer adaptation to platform_driver Santosh Shilimkar
  11 siblings, 1 reply; 20+ messages in thread
From: Tarun Kanti DebBarma @ 2011-04-16 15:51 UTC (permalink / raw)
  To: linux-omap; +Cc: Tarun Kanti DebBarma

Make plat-omap/dmtimer.c a normal driver. It is moved to drivers/misc
as timer-omap.c and the corresponding header file has been moved to
include/linux as timer-omap.h. Files which included plat/dmtimer.h
are changed to include linux/timer-omap.h now.

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
---
 arch/arm/mach-omap1/dmtimer.c              |    3 +-
 arch/arm/mach-omap1/pm.c                   |    2 +-
 arch/arm/mach-omap1/timer32k.c             |    2 +-
 arch/arm/mach-omap2/omap_hwmod_2420_data.c |    3 +-
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |    3 +-
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |    3 +-
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    2 +-
 arch/arm/mach-omap2/pm-debug.c             |    2 +-
 arch/arm/mach-omap2/timer.c                |    2 +-
 arch/arm/plat-omap/Makefile                |    1 -
 drivers/misc/Makefile                      |    1 +
 drivers/misc/timer-omap.c                  |  643 ++++++++++++++++++++++++++++
 drivers/tty/serial/omap-serial.c           |    2 +-
 include/linux/timer-omap.h                 |  351 +++++++++++++++
 14 files changed, 1008 insertions(+), 12 deletions(-)
 create mode 100644 drivers/misc/timer-omap.c
 create mode 100644 include/linux/timer-omap.h

diff --git a/arch/arm/mach-omap1/dmtimer.c b/arch/arm/mach-omap1/dmtimer.c
index 980b23b..3a0cece 100644
--- a/arch/arm/mach-omap1/dmtimer.c
+++ b/arch/arm/mach-omap1/dmtimer.c
@@ -25,11 +25,10 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
+#include <linux/timer-omap.h>
 
 #include <mach/irqs.h>
 
-#include <plat/dmtimer.h>
-
 #define OMAP1610_GPTIMER1_BASE		0xfffb1400
 #define OMAP1610_GPTIMER2_BASE		0xfffb1c00
 #define OMAP1610_GPTIMER3_BASE		0xfffb2400
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index 98ba978..4344a70 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -42,6 +42,7 @@
 #include <linux/sysfs.h>
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/timer-omap.h>
 
 #include <asm/irq.h>
 #include <asm/atomic.h>
@@ -55,7 +56,6 @@
 #include <plat/tc.h>
 #include <plat/mux.h>
 #include <plat/dma.h>
-#include <plat/dmtimer.h>
 
 #include "pm.h"
 
diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
index 96604a5..83b4094 100644
--- a/arch/arm/mach-omap1/timer32k.c
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -45,6 +45,7 @@
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/io.h>
+#include <linux/timer-omap.h>
 
 #include <asm/system.h>
 #include <mach/hardware.h>
@@ -53,7 +54,6 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 #include <plat/common.h>
-#include <plat/dmtimer.h>
 
 /*
  * ---------------------------------------------------------------------------
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index 1f7cb36..fe080f4 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -11,6 +11,8 @@
  * XXX handle crossbar/shared link difference for L3?
  * XXX these should be marked initdata for multi-OMAP kernels
  */
+#include <linux/timer-omap.h>
+
 #include <plat/omap_hwmod.h>
 #include <mach/irqs.h>
 #include <plat/cpu.h>
@@ -19,7 +21,6 @@
 #include <plat/i2c.h>
 #include <plat/gpio.h>
 #include <plat/mcspi.h>
-#include <plat/dmtimer.h>
 #include <plat/l3_2xxx.h>
 #include <plat/l4_2xxx.h>
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index d7c6487..85dec8a 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -11,6 +11,8 @@
  * XXX handle crossbar/shared link difference for L3?
  * XXX these should be marked initdata for multi-OMAP kernels
  */
+#include <linux/timer-omap.h>
+
 #include <plat/omap_hwmod.h>
 #include <mach/irqs.h>
 #include <plat/cpu.h>
@@ -20,7 +22,6 @@
 #include <plat/gpio.h>
 #include <plat/mcbsp.h>
 #include <plat/mcspi.h>
-#include <plat/dmtimer.h>
 #include <plat/mmc.h>
 #include <plat/l3_2xxx.h>
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 7fb2ecc..2649ed8 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -13,6 +13,8 @@
  *
  * XXX these should be marked initdata for multi-OMAP kernels
  */
+#include <linux/timer-omap.h>
+
 #include <plat/omap_hwmod.h>
 #include <mach/irqs.h>
 #include <plat/cpu.h>
@@ -25,7 +27,6 @@
 #include <plat/mmc.h>
 #include <plat/mcbsp.h>
 #include <plat/mcspi.h>
-#include <plat/dmtimer.h>
 
 #include "omap_hwmod_common_data.h"
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index ab6967b..760d280 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -19,6 +19,7 @@
  */
 
 #include <linux/io.h>
+#include <linux/timer-omap.h>
 
 #include <plat/omap_hwmod.h>
 #include <plat/cpu.h>
@@ -27,7 +28,6 @@
 #include <plat/mcspi.h>
 #include <plat/mcbsp.h>
 #include <plat/mmc.h>
-#include <plat/dmtimer.h>
 
 #include "omap_hwmod_common_data.h"
 
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 6e19f10..404faf7 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -26,12 +26,12 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/timer-omap.h>
 
 #include <plat/clock.h>
 #include <plat/board.h>
 #include "powerdomain.h"
 #include "clockdomain.h"
-#include <plat/dmtimer.h>
 #include <plat/omap-pm.h>
 
 #include "cm2xxx_3xxx.h"
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index b7862ca..5fd2363 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -36,9 +36,9 @@
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/slab.h>
+#include <linux/timer-omap.h>
 
 #include <asm/mach/time.h>
-#include <plat/dmtimer.h>
 #include <asm/localtimer.h>
 #include <asm/sched_clock.h>
 #include <plat/common.h>
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index a4a1285..472eeed 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -22,7 +22,6 @@ obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
 obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o
 
 obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
-obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
 obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
 obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
 i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f546860..c95496d 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -44,3 +44,4 @@ obj-$(CONFIG_PCH_PHUB)		+= pch_phub.o
 obj-y				+= ti-st/
 obj-$(CONFIG_AB8500_PWM)	+= ab8500-pwm.o
 obj-y				+= lis3lv02d/
+obj-$(CONFIG_OMAP_DM_TIMER)	+= timer-omap.o
diff --git a/drivers/misc/timer-omap.c b/drivers/misc/timer-omap.c
new file mode 100644
index 0000000..4ee0571
--- /dev/null
+++ b/drivers/misc/timer-omap.c
@@ -0,0 +1,643 @@
+/*
+ * drivers/misc/timer-omap.c
+ *
+ * OMAP Dual-Mode Timers
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * dmtimer adaptation to platform_driver.
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * OMAP2 support by Juha Yrjola
+ * API improvements and OMAP2 clock framework support by Timo Teras
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/err.h>
+#include <linux/timer-omap.h>
+
+static LIST_HEAD(omap_timer_list);
+static DEFINE_MUTEX(dm_timer_mutex);
+
+/**
+ * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
+ * @timer:      timer pointer over which read operation to perform
+ * @reg:        lowest byte holds the register offset
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode write
+ * pending bit must be checked. Otherwise a read of a non completed write
+ * will produce an error.
+ */
+static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
+{
+	if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
+		reg += timer->func_offset;
+	else if (reg >= OMAP_TIMER_STAT_REG)
+		reg += timer->intr_offset;
+
+	return __omap_dm_timer_read(timer->io_base, reg, timer->posted,
+					timer->func_offset);
+}
+
+/**
+ * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
+ * @timer:      timer pointer over which write operation is to perform
+ * @reg:        lowest byte holds the register offset
+ * @value:      data to write into the register
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode the write
+ * pending bit must be checked. Otherwise a write on a register which has a
+ * pending write will be lost.
+ */
+static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
+						u32 value)
+{
+	if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
+		reg += timer->func_offset;
+	else if (reg >= OMAP_TIMER_STAT_REG)
+		reg += timer->intr_offset;
+
+	__omap_dm_timer_write(timer->io_base, reg, value, timer->posted,
+				timer->func_offset);
+}
+
+static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
+{
+	int c;
+
+	c = 0;
+	while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
+		c++;
+		if (c > 100000) {
+			printk(KERN_ERR "Timer failed to reset\n");
+			return;
+		}
+	}
+}
+
+/* Assumes the source clock has been set by caller */
+void __omap_dm_timer_reset(struct omap_dm_timer *timer, int autoidle,
+				int wakeup)
+{
+	u32 l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
+	l |= 0x02 << 3;  /* Set to smart-idle mode */
+	l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
+
+	if (autoidle)
+		l |= 0x1 << 0;
+
+	if (wakeup)
+		l |= 1 << 2;
+
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
+}
+
+static void omap_dm_timer_reset(struct omap_dm_timer *timer)
+{
+	int autoidle = 0, wakeup = 0;
+
+	if (timer->pdev->id != 1) {
+		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
+		omap_dm_timer_wait_for_reset(timer);
+	}
+	__omap_dm_timer_reset(timer, autoidle, wakeup);
+}
+
+void omap_dm_timer_prepare(struct omap_dm_timer *timer)
+{
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
+	timer->fclk = clk_get(&timer->pdev->dev, "fck");
+	if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
+		timer->fclk = NULL;
+		dev_err(&timer->pdev->dev, ": No fclk handle.\n");
+		return;
+	}
+
+	omap_dm_timer_enable(timer);
+
+	if (pdata->needs_manual_reset)
+		omap_dm_timer_reset(timer);
+
+	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
+
+	__omap_dm_timer_set_posted(timer->io_base, timer->func_offset);
+	timer->posted = 1;
+}
+
+struct omap_dm_timer *omap_dm_timer_request(void)
+{
+	struct omap_dm_timer *timer = NULL, *t;
+
+	mutex_lock(&dm_timer_mutex);
+	list_for_each_entry(t, &omap_timer_list, node) {
+		if (t->reserved)
+			continue;
+
+		timer = t;
+		timer->reserved = 1;
+		break;
+	}
+	mutex_unlock(&dm_timer_mutex);
+
+	if (timer)
+		omap_dm_timer_prepare(timer);
+	else
+		pr_debug("%s: free timer not available.\n", __func__);
+
+	return timer;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_request);
+
+struct omap_dm_timer *omap_dm_timer_request_specific(int id)
+{
+	struct omap_dm_timer *timer = NULL, *t;
+
+	mutex_lock(&dm_timer_mutex);
+	list_for_each_entry(t, &omap_timer_list, node) {
+		if (t->pdev->id == id && !t->reserved) {
+			timer = t;
+			timer->reserved = 1;
+			break;
+		}
+	}
+	mutex_unlock(&dm_timer_mutex);
+
+	if (timer)
+		omap_dm_timer_prepare(timer);
+	else
+		pr_debug("%s: timer%d not available.\n", __func__, id);
+
+	return timer;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
+
+void omap_dm_timer_free(struct omap_dm_timer *timer)
+{
+	omap_dm_timer_disable(timer);
+
+	clk_put(timer->fclk);
+
+	WARN_ON(!timer->reserved);
+	timer->reserved = 0;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_free);
+
+void omap_dm_timer_enable(struct omap_dm_timer *timer)
+{
+	if (timer->enabled)
+		return;
+
+	pm_runtime_get_sync(&timer->pdev->dev);
+
+	timer->enabled = 1;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
+
+void omap_dm_timer_disable(struct omap_dm_timer *timer)
+{
+	if (!timer->enabled)
+		return;
+
+	pm_runtime_put_sync(&timer->pdev->dev);
+
+	timer->enabled = 0;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
+
+int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
+{
+	return timer->irq;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
+
+#if defined(CONFIG_ARCH_OMAP1)
+
+/**
+ * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
+ * @inputmask: current value of idlect mask
+ */
+__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
+{
+	int i = 0;
+	struct omap_dm_timer *timer = NULL;
+
+	/* If ARMXOR cannot be idled this function call is unnecessary */
+	if (!(inputmask & (1 << 1)))
+		return inputmask;
+
+	/* If any active timer is using ARMXOR return modified mask */
+	mutex_lock(&dm_timer_mutex);
+	list_for_each_entry(timer, &omap_timer_list, node) {
+
+		u32 l;
+
+		l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+		if (l & OMAP_TIMER_CTRL_ST) {
+			if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
+				inputmask &= ~(1 << 1);
+			else
+				inputmask &= ~(1 << 2);
+		}
+		i++;
+	}
+	mutex_unlock(&dm_timer_mutex);
+
+	return inputmask;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
+
+#else
+
+struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
+{
+	return timer->fclk;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
+
+__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
+{
+	BUG();
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
+
+#endif
+
+void omap_dm_timer_trigger(struct omap_dm_timer *timer)
+{
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
+
+void omap_dm_timer_start(struct omap_dm_timer *timer)
+{
+	u32 l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	if (!(l & OMAP_TIMER_CTRL_ST)) {
+		l |= OMAP_TIMER_CTRL_ST;
+		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+	}
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_start);
+
+void omap_dm_timer_stop(struct omap_dm_timer *timer)
+{
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+	bool omap2 = true;
+	unsigned long rate = clk_get_rate(timer->fclk) + 1;
+
+	if (unlikely(pdata->needs_manual_reset))
+		omap2 = false;
+
+	__omap_dm_timer_stop(timer->io_base, rate, timer->posted, omap2,
+			timer->intr_offset, timer->func_offset);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
+
+int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
+{
+	int ret = -EINVAL;
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
+	if (source < 0 || source >= 3)
+		return -EINVAL;
+
+	omap_dm_timer_disable(timer);
+	/* change the timer clock source */
+	ret = pdata->set_timer_src(timer->pdev, source);
+	omap_dm_timer_enable(timer);
+
+	/*
+	 * When the functional clock disappears, too quick writes seem
+	 * to cause an abort. XXX Is this still necessary?
+	 */
+	__delay(300000);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
+
+void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
+			    unsigned int load)
+{
+	u32 l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	if (autoreload)
+		l |= OMAP_TIMER_CTRL_AR;
+	else
+		l &= ~OMAP_TIMER_CTRL_AR;
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
+
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
+
+/* Optimized set_load which removes costly spin wait in timer_start */
+void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
+					unsigned int load)
+{
+	u32 l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	if (autoreload) {
+		l |= OMAP_TIMER_CTRL_AR;
+		omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
+	} else {
+		l &= ~OMAP_TIMER_CTRL_AR;
+	}
+	l |= OMAP_TIMER_CTRL_ST;
+
+	__omap_dm_timer_load_start(timer->io_base, l, load, timer->posted,
+					timer->func_offset);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
+
+void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
+			     unsigned int match)
+{
+	u32 l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	if (enable)
+		l |= OMAP_TIMER_CTRL_CE;
+	else
+		l &= ~OMAP_TIMER_CTRL_CE;
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
+
+void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
+			   int toggle, int trigger)
+{
+	u32 l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
+	       OMAP_TIMER_CTRL_PT | (0x03 << 10));
+	if (def_on)
+		l |= OMAP_TIMER_CTRL_SCPWM;
+	if (toggle)
+		l |= OMAP_TIMER_CTRL_PT;
+	l |= trigger << 10;
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
+
+void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
+{
+	u32 l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
+	if (prescaler >= 0x00 && prescaler <= 0x07) {
+		l |= OMAP_TIMER_CTRL_PRE;
+		l |= prescaler << 2;
+	}
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
+
+void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
+				  unsigned int value)
+{
+	__omap_dm_timer_int_enable(timer->io_base, value, timer->posted,
+			timer->intr_offset, timer->func_offset);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
+
+unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
+{
+	unsigned int l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+
+	return l;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
+
+void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
+{
+	__omap_dm_timer_write_status(timer->io_base, value, timer->posted,
+				timer->intr_offset, timer->func_offset);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
+
+unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
+{
+	return __omap_dm_timer_read_counter(timer->io_base, timer->posted,
+						timer->func_offset);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
+
+void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
+{
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
+
+int omap_dm_timers_active(void)
+{
+	struct omap_dm_timer *timer;
+
+	list_for_each_entry(timer, &omap_timer_list, node) {
+		if (!timer->enabled)
+			continue;
+
+		if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
+		    OMAP_TIMER_CTRL_ST) {
+			return 1;
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timers_active);
+
+/**
+ * omap_dm_timer_probe - probe function called for every registered device
+ * @pdev:	pointer to current timer platform device
+ *
+ * Called by driver framework at the end of device registration for all
+ * timer devices.
+ */
+static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct omap_dm_timer *timer;
+	struct resource *mem, *irq, *ioarea;
+	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
+		return -ENODEV;
+	}
+
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (unlikely(!irq)) {
+		dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
+		ret = -ENODEV;
+		goto err_free_pdev;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(!mem)) {
+		dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
+		ret = -ENODEV;
+		goto err_free_pdev;
+	}
+
+	ioarea = request_mem_region(mem->start, resource_size(mem),
+			pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
+		ret = -EBUSY;
+		goto err_free_pdev;
+	}
+
+	timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
+	if (!timer) {
+		dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_release_ioregion;
+	}
+
+	timer->io_base = ioremap(mem->start, resource_size(mem));
+	if (!timer->io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
+		ret = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_2) {
+		timer->func_offset = VERSION2_TIMER_WAKEUP_EN_REG_OFFSET;
+		timer->intr_offset = VERSION2_TIMER_STAT_REG_OFFSET;
+	} else {
+		timer->func_offset = 0;
+		timer->intr_offset = 0;
+	}
+
+	timer->id = pdev->id;
+	timer->irq = irq->start;
+	timer->pdev = pdev;
+#if defined(CONFIG_ARCH_OMAP2)
+	/* Mark clocksource and clockevent timers as reserved */
+	if ((sys_timer_reserved >> (pdev->id - 1)) & 0x1)
+		timer->reserved = 1;
+	else
+#endif
+		timer->reserved = 0;
+
+	 /* Skip pm_runtime_enable for OMAP1 */
+	if (!pdata->needs_manual_reset)
+		pm_runtime_enable(&pdev->dev);
+
+	/* add the timer element to the list */
+	mutex_lock(&dm_timer_mutex);
+	list_add_tail(&timer->node, &omap_timer_list);
+	mutex_unlock(&dm_timer_mutex);
+
+	dev_dbg(&pdev->dev, "Device Probed.\n");
+
+	return 0;
+
+err_free_mem:
+	kfree(timer);
+
+err_release_ioregion:
+	release_mem_region(mem->start, resource_size(mem));
+
+err_free_pdev:
+	kfree(pdata);
+	platform_device_unregister(pdev);
+
+	return ret;
+}
+
+/**
+ * omap_dm_timer_remove - cleanup a registered timer device
+ * @pdev:	pointer to current timer platform device
+ *
+ * Called by driver framework whenever a timer device is unregistered.
+ * In addition to freeing platform resources it also deletes the timer
+ * entry from the local list.
+ */
+static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
+{
+	struct omap_dm_timer *timer, *tmp;
+	int ret = -EINVAL;
+
+	mutex_lock(&dm_timer_mutex);
+	list_for_each_entry_safe(timer, tmp, &omap_timer_list, node) {
+		if (timer->pdev->id == pdev->id) {
+			kfree(timer->pdev->dev.platform_data);
+			platform_device_del(timer->pdev);
+			list_del(&timer->node);
+			kfree(timer);
+			ret = 0;
+			break;
+		}
+	}
+	mutex_unlock(&dm_timer_mutex);
+
+	return ret;
+}
+
+static struct platform_driver omap_dm_timer_driver = {
+	.probe  = omap_dm_timer_probe,
+	.remove = omap_dm_timer_remove,
+	.driver = {
+		.name   = "omap_timer",
+	},
+};
+
+static int __init omap_dm_timer_driver_init(void)
+{
+	return platform_driver_register(&omap_dm_timer_driver);
+}
+
+static void __exit omap_dm_timer_driver_exit(void)
+{
+	platform_driver_unregister(&omap_dm_timer_driver);
+}
+
+early_platform_init("earlytimer", &omap_dm_timer_driver);
+module_init(omap_dm_timer_driver_init);
+module_exit(omap_dm_timer_driver_exit);
+
+MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 7635379..a8178eb 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -37,9 +37,9 @@
 #include <linux/clk.h>
 #include <linux/serial_core.h>
 #include <linux/irq.h>
+#include <linux/timer-omap.h>
 
 #include <plat/dma.h>
-#include <plat/dmtimer.h>
 #include <plat/omap-serial.h>
 
 static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
diff --git a/include/linux/timer-omap.h b/include/linux/timer-omap.h
new file mode 100644
index 0000000..a6b4cac
--- /dev/null
+++ b/include/linux/timer-omap.h
@@ -0,0 +1,351 @@
+/*
+ * include/linux/timer-omap.h
+ *
+ * OMAP Dual-Mode Timers
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Platform device conversion and hwmod support.
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
+ * PWM and clock framwork support by Timo Teras.
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_ARCH_DMTIMER_H
+#define __ASM_ARCH_DMTIMER_H
+
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+
+/* clock sources */
+#define OMAP_TIMER_SRC_SYS_CLK			0x00
+#define OMAP_TIMER_SRC_32_KHZ			0x01
+#define OMAP_TIMER_SRC_EXT_CLK			0x02
+
+/* timer interrupt enable bits */
+#define OMAP_TIMER_INT_CAPTURE			(1 << 2)
+#define OMAP_TIMER_INT_OVERFLOW			(1 << 1)
+#define OMAP_TIMER_INT_MATCH			(1 << 0)
+
+/* trigger types */
+#define OMAP_TIMER_TRIGGER_NONE			0x00
+#define OMAP_TIMER_TRIGGER_OVERFLOW		0x01
+#define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE	0x02
+
+/*
+ * IP revision identifier so that Highlander IP
+ * in OMAP4 can be distinguished.
+ */
+#define OMAP_TIMER_IP_VERSION_1			0x1
+#define OMAP_TIMER_IP_VERSION_2			0x2
+
+/*
+ * OMAP4 IP revision has different register offsets
+ * for interrupt registers and functional registers.
+ */
+#define VERSION2_TIMER_WAKEUP_EN_REG_OFFSET     0x14
+#define VERSION2_TIMER_STAT_REG_OFFSET          0x10
+
+/* timer capabilities used in hwmod database */
+#define OMAP_TIMER_SECURE				0x80000000
+#define OMAP_TIMER_ALWON				0x40000000
+#define OMAP_TIMER_HAS_PWM				0x20000000
+
+struct omap_timer_capability_dev_attr {
+	u32 timer_capability;
+};
+
+extern struct omap_dm_timer *gptimer_wakeup;
+
+struct dmtimer_platform_data {
+	int (*set_timer_src)(struct platform_device *pdev, int source);
+	int timer_ip_type;
+	u32 needs_manual_reset:1;
+};
+
+struct omap_dm_timer *omap_dm_timer_request(void);
+struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
+void omap_dm_timer_free(struct omap_dm_timer *timer);
+void omap_dm_timer_enable(struct omap_dm_timer *timer);
+void omap_dm_timer_disable(struct omap_dm_timer *timer);
+
+int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
+
+u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
+struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer);
+
+void omap_dm_timer_trigger(struct omap_dm_timer *timer);
+void omap_dm_timer_start(struct omap_dm_timer *timer);
+void omap_dm_timer_stop(struct omap_dm_timer *timer);
+
+int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
+void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
+void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
+void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
+void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
+void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
+
+void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
+
+unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
+void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
+unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
+void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
+
+int omap_dm_timers_active(void);
+
+/*
+ * Do not use the defines below, they are not needed. They should be only
+ * used by dmtimer.c and sys_timer related code.
+ */
+
+/* register offsets */
+#define _OMAP_TIMER_ID_OFFSET		0x00
+#define _OMAP_TIMER_OCP_CFG_OFFSET	0x10
+#define _OMAP_TIMER_SYS_STAT_OFFSET	0x14
+#define _OMAP_TIMER_STAT_OFFSET		0x18
+#define _OMAP_TIMER_INT_EN_OFFSET	0x1c
+#define _OMAP_TIMER_WAKEUP_EN_OFFSET	0x20
+#define _OMAP_TIMER_CTRL_OFFSET		0x24
+#define		OMAP_TIMER_CTRL_GPOCFG		(1 << 14)
+#define		OMAP_TIMER_CTRL_CAPTMODE	(1 << 13)
+#define		OMAP_TIMER_CTRL_PT		(1 << 12)
+#define		OMAP_TIMER_CTRL_TCM_LOWTOHIGH	(0x1 << 8)
+#define		OMAP_TIMER_CTRL_TCM_HIGHTOLOW	(0x2 << 8)
+#define		OMAP_TIMER_CTRL_TCM_BOTHEDGES	(0x3 << 8)
+#define		OMAP_TIMER_CTRL_SCPWM		(1 << 7)
+#define		OMAP_TIMER_CTRL_CE		(1 << 6) /* compare enable */
+#define		OMAP_TIMER_CTRL_PRE		(1 << 5) /* prescaler enable */
+#define		OMAP_TIMER_CTRL_PTV_SHIFT	2 /* prescaler value shift */
+#define		OMAP_TIMER_CTRL_POSTED		(1 << 2)
+#define		OMAP_TIMER_CTRL_AR		(1 << 1) /* auto-reload enable */
+#define		OMAP_TIMER_CTRL_ST		(1 << 0) /* start timer */
+#define _OMAP_TIMER_COUNTER_OFFSET	0x28
+#define _OMAP_TIMER_LOAD_OFFSET		0x2c
+#define _OMAP_TIMER_TRIGGER_OFFSET	0x30
+#define _OMAP_TIMER_WRITE_PEND_OFFSET	0x34
+#define		WP_NONE			0	/* no write pending bit */
+#define		WP_TCLR			(1 << 0)
+#define		WP_TCRR			(1 << 1)
+#define		WP_TLDR			(1 << 2)
+#define		WP_TTGR			(1 << 3)
+#define		WP_TMAR			(1 << 4)
+#define		WP_TPIR			(1 << 5)
+#define		WP_TNIR			(1 << 6)
+#define		WP_TCVR			(1 << 7)
+#define		WP_TOCR			(1 << 8)
+#define		WP_TOWR			(1 << 9)
+#define _OMAP_TIMER_MATCH_OFFSET	0x38
+#define _OMAP_TIMER_CAPTURE_OFFSET	0x3c
+#define _OMAP_TIMER_IF_CTRL_OFFSET	0x40
+#define _OMAP_TIMER_CAPTURE2_OFFSET		0x44	/* TCAR2, 34xx only */
+#define _OMAP_TIMER_TICK_POS_OFFSET		0x48	/* TPIR, 34xx only */
+#define _OMAP_TIMER_TICK_NEG_OFFSET		0x4c	/* TNIR, 34xx only */
+#define _OMAP_TIMER_TICK_COUNT_OFFSET		0x50	/* TCVR, 34xx only */
+#define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET	0x54	/* TOCR, 34xx only */
+#define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET	0x58	/* TOWR, 34xx only */
+
+/* register offsets with the write pending bit encoded */
+#define	WPSHIFT					16
+
+#define OMAP_TIMER_ID_REG			(_OMAP_TIMER_ID_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_OCP_CFG_REG			(_OMAP_TIMER_OCP_CFG_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_SYS_STAT_REG			(_OMAP_TIMER_SYS_STAT_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_STAT_REG			(_OMAP_TIMER_STAT_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_INT_EN_REG			(_OMAP_TIMER_INT_EN_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_WAKEUP_EN_REG		(_OMAP_TIMER_WAKEUP_EN_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_CTRL_REG			(_OMAP_TIMER_CTRL_OFFSET \
+							| (WP_TCLR << WPSHIFT))
+
+#define OMAP_TIMER_COUNTER_REG			(_OMAP_TIMER_COUNTER_OFFSET \
+							| (WP_TCRR << WPSHIFT))
+
+#define OMAP_TIMER_LOAD_REG			(_OMAP_TIMER_LOAD_OFFSET \
+							| (WP_TLDR << WPSHIFT))
+
+#define OMAP_TIMER_TRIGGER_REG			(_OMAP_TIMER_TRIGGER_OFFSET \
+							| (WP_TTGR << WPSHIFT))
+
+#define OMAP_TIMER_WRITE_PEND_REG		(_OMAP_TIMER_WRITE_PEND_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_MATCH_REG			(_OMAP_TIMER_MATCH_OFFSET \
+							| (WP_TMAR << WPSHIFT))
+
+#define OMAP_TIMER_CAPTURE_REG			(_OMAP_TIMER_CAPTURE_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_IF_CTRL_REG			(_OMAP_TIMER_IF_CTRL_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_CAPTURE2_REG			(_OMAP_TIMER_CAPTURE2_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_TICK_POS_REG			(_OMAP_TIMER_TICK_POS_OFFSET \
+							| (WP_TPIR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_NEG_REG			(_OMAP_TIMER_TICK_NEG_OFFSET \
+							| (WP_TNIR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_COUNT_REG		(_OMAP_TIMER_TICK_COUNT_OFFSET \
+							| (WP_TCVR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_INT_MASK_SET_REG				\
+		(_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG				\
+		(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
+
+#define MAX_WRITE_PEND_WAIT            10000 /* 10ms timeout delay */
+
+struct omap_dm_timer {
+	unsigned long phys_base;
+	int id;
+	int irq;
+	struct clk *iclk, *fclk;
+	void __iomem *io_base;
+	unsigned long rate;
+	unsigned reserved:1;
+	unsigned enabled:1;
+	unsigned posted:1;
+	u8 func_offset;
+	u8 intr_offset;
+	struct platform_device *pdev;
+	struct list_head node;
+};
+
+extern u32 sys_timer_reserved;
+void __omap_dm_timer_reset(struct omap_dm_timer *timer, int autoidle,
+				int wakeup);
+
+static inline u32
+__omap_dm_timer_read(void __iomem *base, u32 reg, int posted, u8 func_offset)
+{
+	int i = 0;
+
+	if (posted) {
+		omap_test_timeout(!(__raw_readl(base +
+			((OMAP_TIMER_WRITE_PEND_REG + func_offset) & 0xff)) &
+			(reg >> WPSHIFT)), MAX_WRITE_PEND_WAIT, i);
+
+		if (WARN_ON_ONCE(i == MAX_WRITE_PEND_WAIT))
+			pr_err("read timeout.\n");
+	}
+
+	return __raw_readl(base + (reg & 0xff));
+}
+
+static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val,
+						int posted, u8 func_offset)
+{
+	int i = 0;
+
+	if (posted) {
+		omap_test_timeout(!(__raw_readl(base +
+			((OMAP_TIMER_WRITE_PEND_REG + func_offset) & 0xff)) &
+			(reg >> WPSHIFT)), MAX_WRITE_PEND_WAIT, i);
+
+		if (WARN_ON(i == MAX_WRITE_PEND_WAIT))
+			pr_err("write timeout.\n");
+	}
+
+	__raw_writel(val, base + (reg & 0xff));
+}
+
+static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl,
+			unsigned int load, int posted, u8 func_offset)
+{
+	__omap_dm_timer_write(base, OMAP_TIMER_COUNTER_REG + func_offset,
+				load, posted, func_offset);
+	__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG + func_offset,
+				ctrl, posted, func_offset);
+}
+
+static inline void __omap_dm_timer_int_enable(void __iomem *base,
+		unsigned int value, int posted, u8 intr_offset, u8 func_offset)
+{
+	__omap_dm_timer_write(base, OMAP_TIMER_INT_EN_REG + intr_offset,
+				value, posted, func_offset);
+	__omap_dm_timer_write(base, OMAP_TIMER_WAKEUP_EN_REG + func_offset,
+				value, posted, func_offset);
+}
+
+static inline unsigned int
+__omap_dm_timer_read_counter(void __iomem *base, int posted, u8 func_offset)
+{
+	return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG + func_offset,
+					posted,	func_offset);
+}
+
+static inline void __omap_dm_timer_write_status(void __iomem *base,
+		unsigned int value, int posted, u8 intr_offset, u8 func_offset)
+{
+	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG + intr_offset,
+				value, posted, func_offset);
+}
+
+static inline void
+__omap_dm_timer_set_posted(void __iomem *base, u8 func_offset)
+{
+	__omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG + func_offset,
+				OMAP_TIMER_CTRL_POSTED, 0, func_offset);
+}
+
+static inline void __omap_dm_timer_stop(void __iomem *base, unsigned long rate,
+			int posted, bool omap2, u8 intr_offset, u8 func_offset)
+{
+	u32 l;
+
+	l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG + func_offset,
+					posted, func_offset);
+	if (l & OMAP_TIMER_CTRL_ST) {
+		l &= ~0x1;
+		__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG + func_offset,
+					l, posted, func_offset);
+		if (omap2) {
+			/* Readback to make sure write has completed */
+			__omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG +
+					func_offset, posted, func_offset);
+			udelay(3500000 / rate);
+		}
+	}
+	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG + intr_offset,
+				OMAP_TIMER_INT_OVERFLOW, posted, func_offset);
+}
+#endif /* __ASM_ARCH_DMTIMER_H */
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v13 10/11] OMAP: dmtimer: mark clocksource and clockevent timers reserved
  2011-04-16 15:51 ` [PATCH v13 10/11] OMAP: dmtimer: mark clocksource and clockevent timers reserved Tarun Kanti DebBarma
@ 2011-04-17  6:12   ` Santosh Shilimkar
  2011-04-18  5:50     ` DebBarma, Tarun Kanti
  2011-04-25  9:41   ` DebBarma, Tarun Kanti
  1 sibling, 1 reply; 20+ messages in thread
From: Santosh Shilimkar @ 2011-04-17  6:12 UTC (permalink / raw)
  To: Tarun Kanti DebBarma; +Cc: linux-omap

On 4/16/2011 9:21 PM, Tarun Kanti DebBarma wrote:
> In driver probe use sys_timer_reserved to identify which all timers
> have already been used for clocksource and clockevent. Mark all those
> timers as reserved so that no one else can use them.
>
> Signed-off-by: Tarun Kanti DebBarma<tarun.kanti@ti.com>
> ---
>   arch/arm/plat-omap/dmtimer.c |    8 +++++++-
>   1 files changed, 7 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
> index e15b3a8..8b6fd22 100644
> --- a/arch/arm/plat-omap/dmtimer.c
> +++ b/arch/arm/plat-omap/dmtimer.c
> @@ -554,7 +554,13 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
>   	timer->id = pdev->id;
>   	timer->irq = irq->start;
>   	timer->pdev = pdev;
> -	timer->reserved = 0;
> +#if defined(CONFIG_ARCH_OMAP2)

Do you mean CONFIG_ARCH_OMAP2PLUS here ?

> +	/* Mark clocksource and clockevent timers as reserved */
> +	if ((sys_timer_reserved>>  (pdev->id - 1))&  0x1)
> +		timer->reserved = 1;
> +	else
> +#endif
> +		timer->reserved = 0;
>
>   	 /* Skip pm_runtime_enable for OMAP1 */
>   	if (!pdata->needs_manual_reset)


^ permalink raw reply	[flat|nested] 20+ messages in thread

* RE: [PATCH v13 10/11] OMAP: dmtimer: mark clocksource and clockevent timers reserved
  2011-04-17  6:12   ` Santosh Shilimkar
@ 2011-04-18  5:50     ` DebBarma, Tarun Kanti
  0 siblings, 0 replies; 20+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-04-18  5:50 UTC (permalink / raw)
  To: Shilimkar, Santosh; +Cc: linux-omap@vger.kernel.org

> -----Original Message-----
> From: Shilimkar, Santosh
> Sent: Sunday, April 17, 2011 11:42 AM
> To: DebBarma, Tarun Kanti
> Cc: linux-omap@vger.kernel.org
> Subject: Re: [PATCH v13 10/11] OMAP: dmtimer: mark clocksource and
> clockevent timers reserved
> 
> On 4/16/2011 9:21 PM, Tarun Kanti DebBarma wrote:
> > In driver probe use sys_timer_reserved to identify which all timers
> > have already been used for clocksource and clockevent. Mark all those
> > timers as reserved so that no one else can use them.
> >
> > Signed-off-by: Tarun Kanti DebBarma<tarun.kanti@ti.com>
> > ---
> >   arch/arm/plat-omap/dmtimer.c |    8 +++++++-
> >   1 files changed, 7 insertions(+), 1 deletions(-)
> >
> > diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
> > index e15b3a8..8b6fd22 100644
> > --- a/arch/arm/plat-omap/dmtimer.c
> > +++ b/arch/arm/plat-omap/dmtimer.c
> > @@ -554,7 +554,13 @@ static int __devinit omap_dm_timer_probe(struct
> platform_device *pdev)
> >   	timer->id = pdev->id;
> >   	timer->irq = irq->start;
> >   	timer->pdev = pdev;
> > -	timer->reserved = 0;
> > +#if defined(CONFIG_ARCH_OMAP2)
> 
> Do you mean CONFIG_ARCH_OMAP2PLUS here ?
Yes, I will correct. Thanks.
--
Tarun
> 
> > +	/* Mark clocksource and clockevent timers as reserved */
> > +	if ((sys_timer_reserved>>  (pdev->id - 1))&  0x1)
> > +		timer->reserved = 1;
> > +	else
> > +#endif
> > +		timer->reserved = 0;
> >
> >   	 /* Skip pm_runtime_enable for OMAP1 */
> >   	if (!pdata->needs_manual_reset)


^ permalink raw reply	[flat|nested] 20+ messages in thread

* RE: [PATCH v13 04/11] OMAP2+: dmtimer: convert to platform devices
  2011-04-16 15:50 ` [PATCH v13 04/11] OMAP2+: dmtimer: convert " Tarun Kanti DebBarma
@ 2011-04-25  9:38   ` DebBarma, Tarun Kanti
  2011-04-29 10:45   ` Santosh Shilimkar
  1 sibling, 0 replies; 20+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-04-25  9:38 UTC (permalink / raw)
  To: linux-omap@vger.kernel.org; +Cc: Gopinath, Thara

[-- Attachment #1: Type: text/plain, Size: 32155 bytes --]

Add routines to converts dmtimers to platform devices. The device data
is obtained from hwmod database of respective platform and is registered
to device model after successful binding to driver.
In addition, capability attribute of each of the timers is added in
hwmod database.

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
Signed-off-by: Thara Gopinath <thara@ti.com>
Acked-by: Cousson, Benoit <b-cousson@ti.com>
---
Missed adding capability attribute to timer11.

 arch/arm/mach-omap2/omap_hwmod_2420_data.c |   22 ++++
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |   22 ++++
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   27 +++++
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   26 +++++
 arch/arm/mach-omap2/timer.c                |  158 +++++++++++++++++++++++++++-
 arch/arm/plat-omap/dmtimer.c               |   17 ---
 arch/arm/plat-omap/include/plat/dmtimer.h  |   13 ++-
 7 files changed, 266 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index 8eb3ce1..1f7cb36 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -358,6 +358,16 @@ static struct omap_hwmod_class omap2420_timer_hwmod_class = {
        .rev = OMAP_TIMER_IP_VERSION_1,
 };

+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+       .timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+       .timer_capability       = OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap2420_timer1_hwmod;
 static struct omap_hwmod_irq_info omap2420_timer1_mpu_irqs[] = {
@@ -402,6 +412,7 @@ static struct omap_hwmod omap2420_timer1_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2420_timer1_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_timer1_slaves),
        .class          = &omap2420_timer_hwmod_class,
@@ -452,6 +463,7 @@ static struct omap_hwmod omap2420_timer2_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2420_timer2_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_timer2_slaves),
        .class          = &omap2420_timer_hwmod_class,
@@ -502,6 +514,7 @@ static struct omap_hwmod omap2420_timer3_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2420_timer3_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_timer3_slaves),
        .class          = &omap2420_timer_hwmod_class,
@@ -552,6 +565,7 @@ static struct omap_hwmod omap2420_timer4_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2420_timer4_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_timer4_slaves),
        .class          = &omap2420_timer_hwmod_class,
@@ -602,6 +616,7 @@ static struct omap_hwmod omap2420_timer5_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2420_timer5_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_timer5_slaves),
        .class          = &omap2420_timer_hwmod_class,
@@ -653,6 +668,7 @@ static struct omap_hwmod omap2420_timer6_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2420_timer6_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_timer6_slaves),
        .class          = &omap2420_timer_hwmod_class,
@@ -703,6 +719,7 @@ static struct omap_hwmod omap2420_timer7_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2420_timer7_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_timer7_slaves),
        .class          = &omap2420_timer_hwmod_class,
@@ -753,6 +770,7 @@ static struct omap_hwmod omap2420_timer8_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2420_timer8_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_timer8_slaves),
        .class          = &omap2420_timer_hwmod_class,
@@ -803,6 +821,7 @@ static struct omap_hwmod omap2420_timer9_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap2420_timer9_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_timer9_slaves),
        .class          = &omap2420_timer_hwmod_class,
@@ -853,6 +872,7 @@ static struct omap_hwmod omap2420_timer10_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap2420_timer10_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_timer10_slaves),
        .class          = &omap2420_timer_hwmod_class,
@@ -903,6 +923,7 @@ static struct omap_hwmod omap2420_timer11_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap2420_timer11_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_timer11_slaves),
        .class          = &omap2420_timer_hwmod_class,
@@ -953,6 +974,7 @@ static struct omap_hwmod omap2420_timer12_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap2420_timer12_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_timer12_slaves),
        .class          = &omap2420_timer_hwmod_class,
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index a860fb5..d7c6487 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -459,6 +459,16 @@ static struct omap_hwmod_class omap2430_timer_hwmod_class = {
        .rev = OMAP_TIMER_IP_VERSION_1,
 };

+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+       .timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+       .timer_capability       = OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap2430_timer1_hwmod;
 static struct omap_hwmod_irq_info omap2430_timer1_mpu_irqs[] = {
@@ -503,6 +513,7 @@ static struct omap_hwmod omap2430_timer1_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2430_timer1_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_timer1_slaves),
        .class          = &omap2430_timer_hwmod_class,
@@ -553,6 +564,7 @@ static struct omap_hwmod omap2430_timer2_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2430_timer2_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_timer2_slaves),
        .class          = &omap2430_timer_hwmod_class,
@@ -603,6 +615,7 @@ static struct omap_hwmod omap2430_timer3_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2430_timer3_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_timer3_slaves),
        .class          = &omap2430_timer_hwmod_class,
@@ -653,6 +666,7 @@ static struct omap_hwmod omap2430_timer4_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2430_timer4_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_timer4_slaves),
        .class          = &omap2430_timer_hwmod_class,
@@ -703,6 +717,7 @@ static struct omap_hwmod omap2430_timer5_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2430_timer5_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_timer5_slaves),
        .class          = &omap2430_timer_hwmod_class,
@@ -753,6 +768,7 @@ static struct omap_hwmod omap2430_timer6_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2430_timer6_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_timer6_slaves),
        .class          = &omap2430_timer_hwmod_class,
@@ -803,6 +819,7 @@ static struct omap_hwmod omap2430_timer7_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2430_timer7_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_timer7_slaves),
        .class          = &omap2430_timer_hwmod_class,
@@ -853,6 +870,7 @@ static struct omap_hwmod omap2430_timer8_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap2430_timer8_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_timer8_slaves),
        .class          = &omap2430_timer_hwmod_class,
@@ -903,6 +921,7 @@ static struct omap_hwmod omap2430_timer9_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap2430_timer9_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_timer9_slaves),
        .class          = &omap2430_timer_hwmod_class,
@@ -953,6 +972,7 @@ static struct omap_hwmod omap2430_timer10_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap2430_timer10_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_timer10_slaves),
        .class          = &omap2430_timer_hwmod_class,
@@ -1003,6 +1023,7 @@ static struct omap_hwmod omap2430_timer11_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap2430_timer11_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_timer11_slaves),
        .class          = &omap2430_timer_hwmod_class,
@@ -1053,6 +1074,7 @@ static struct omap_hwmod omap2430_timer12_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap2430_timer12_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_timer12_slaves),
        .class          = &omap2430_timer_hwmod_class,
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index b98e2df..7fb2ecc 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -609,6 +609,21 @@ static struct omap_hwmod_class omap3xxx_timer_hwmod_class = {
        .rev =  OMAP_TIMER_IP_VERSION_1,
 };

+/* secure timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_secure_dev_attr = {
+       .timer_capability       = OMAP_TIMER_SECURE,
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+       .timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+       .timer_capability       = OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap3xxx_timer1_hwmod;
 static struct omap_hwmod_irq_info omap3xxx_timer1_mpu_irqs[] = {
@@ -653,6 +668,7 @@ static struct omap_hwmod omap3xxx_timer1_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT1_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap3xxx_timer1_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_timer1_slaves),
        .class          = &omap3xxx_timer_1ms_hwmod_class,
@@ -703,6 +719,7 @@ static struct omap_hwmod omap3xxx_timer2_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap3xxx_timer2_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_timer2_slaves),
        .class          = &omap3xxx_timer_1ms_hwmod_class,
@@ -753,6 +770,7 @@ static struct omap_hwmod omap3xxx_timer3_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT3_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap3xxx_timer3_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_timer3_slaves),
        .class          = &omap3xxx_timer_hwmod_class,
@@ -803,6 +821,7 @@ static struct omap_hwmod omap3xxx_timer4_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT4_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap3xxx_timer4_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_timer4_slaves),
        .class          = &omap3xxx_timer_hwmod_class,
@@ -853,6 +872,7 @@ static struct omap_hwmod omap3xxx_timer5_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT5_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap3xxx_timer5_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_timer5_slaves),
        .class          = &omap3xxx_timer_hwmod_class,
@@ -903,6 +923,7 @@ static struct omap_hwmod omap3xxx_timer6_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT6_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap3xxx_timer6_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_timer6_slaves),
        .class          = &omap3xxx_timer_hwmod_class,
@@ -953,6 +974,7 @@ static struct omap_hwmod omap3xxx_timer7_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT7_SHIFT,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap3xxx_timer7_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_timer7_slaves),
        .class          = &omap3xxx_timer_hwmod_class,
@@ -1003,6 +1025,7 @@ static struct omap_hwmod omap3xxx_timer8_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT8_SHIFT,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap3xxx_timer8_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_timer8_slaves),
        .class          = &omap3xxx_timer_hwmod_class,
@@ -1053,6 +1076,7 @@ static struct omap_hwmod omap3xxx_timer9_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT9_SHIFT,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap3xxx_timer9_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_timer9_slaves),
        .class          = &omap3xxx_timer_hwmod_class,
@@ -1103,6 +1127,7 @@ static struct omap_hwmod omap3xxx_timer10_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT10_SHIFT,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap3xxx_timer10_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_timer10_slaves),
        .class          = &omap3xxx_timer_1ms_hwmod_class,
@@ -1153,6 +1178,7 @@ static struct omap_hwmod omap3xxx_timer11_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT11_SHIFT,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap3xxx_timer11_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_timer11_slaves),
        .class          = &omap3xxx_timer_hwmod_class,
@@ -1203,6 +1229,7 @@ static struct omap_hwmod omap3xxx_timer12_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT12_SHIFT,
                },
        },
+       .dev_attr       = &capability_secure_dev_attr,
        .slaves         = omap3xxx_timer12_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_timer12_slaves),
        .class          = &omap3xxx_timer_hwmod_class,
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 6485c90..38d5848 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -4014,6 +4014,21 @@ static struct omap_hwmod_class omap44xx_timer_hwmod_class = {
        .rev    = OMAP_TIMER_IP_VERSION_2,
 };

+/* secure timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_secure_dev_attr = {
+       .timer_capability       = OMAP_TIMER_SECURE,
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+       .timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+       .timer_capability       = OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap44xx_timer1_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = {
@@ -4054,6 +4069,7 @@ static struct omap_hwmod omap44xx_timer1_hwmod = {
                        .clkctrl_reg = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap44xx_timer1_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_timer1_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4099,6 +4115,7 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
                        .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap44xx_timer2_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_timer2_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4144,6 +4161,7 @@ static struct omap_hwmod omap44xx_timer3_hwmod = {
                        .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap44xx_timer3_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_timer3_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4189,6 +4207,7 @@ static struct omap_hwmod omap44xx_timer4_hwmod = {
                        .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap44xx_timer4_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_timer4_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4253,6 +4272,7 @@ static struct omap_hwmod omap44xx_timer5_hwmod = {
                        .clkctrl_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap44xx_timer5_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_timer5_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4317,6 +4337,7 @@ static struct omap_hwmod omap44xx_timer6_hwmod = {
                        .clkctrl_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap44xx_timer6_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_timer6_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4381,6 +4402,7 @@ static struct omap_hwmod omap44xx_timer7_hwmod = {
                        .clkctrl_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
                },
        },
+       .dev_attr       = &capability_alwon_dev_attr,
        .slaves         = omap44xx_timer7_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_timer7_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4445,6 +4467,7 @@ static struct omap_hwmod omap44xx_timer8_hwmod = {
                        .clkctrl_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap44xx_timer8_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_timer8_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4490,6 +4513,7 @@ static struct omap_hwmod omap44xx_timer9_hwmod = {
                        .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap44xx_timer9_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_timer9_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4535,6 +4559,7 @@ static struct omap_hwmod omap44xx_timer10_hwmod = {
                        .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap44xx_timer10_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_timer10_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4580,6 +4605,7 @@ static struct omap_hwmod omap44xx_timer11_hwmod = {
                        .clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
                },
        },
+       .dev_attr       = &capability_pwm_dev_attr,
        .slaves         = omap44xx_timer11_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_timer11_slaves),
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 2edeb1a..1c80337 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-omap2/timer-gp.c
+ * linux/arch/arm/mach-omap2/timer.c
  *
  * OMAP2 GP timer support.
  *
@@ -35,6 +35,7 @@
 #include <linux/irq.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/slab.h>

 #include <asm/mach/time.h>
 #include <plat/dmtimer.h>
@@ -42,6 +43,7 @@
 #include <asm/sched_clock.h>
 #include <plat/common.h>
 #include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>

 /* Parent clocks, eventually these will come from the clock framework */

@@ -129,6 +131,23 @@ static struct clock_event_device clockevent_gpt = {
        .set_mode       = omap2_gp_timer_set_mode,
 };

+int __omap_dm_timer_set_source(struct clk *timer_fck, struct clk *parent)
+{
+       int ret;
+
+       clk_disable(timer_fck);
+       ret = clk_set_parent(timer_fck, parent);
+       clk_enable(timer_fck);
+
+       /*
+        * When the functional clock disappears, too quick writes seem
+        * to cause an abort. XXX Is this still necessary?
+        */
+       __delay(300000);
+
+       return ret;
+}
+
 static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
                                                int gptimer_id,
                                                const char *fck_source)
@@ -359,3 +378,140 @@ struct sys_timer omap4_timer = {
        .init   = omap4_timer_init,
 };
 #endif
+
+/**
+ * omap2_dm_timer_set_src - change the timer input clock source
+ * @pdev:      timer platform device pointer
+ * @source:    array index of parent clock source
+ */
+static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
+{
+       int ret;
+       struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
+       struct clk *fclk, *new_fclk;
+       char *new_fclk_name = NULL;
+
+       fclk = clk_get(&pdev->dev, "fck");
+       if (IS_ERR_OR_NULL(fclk)) {
+               dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
+                               __func__, __LINE__);
+               return -EINVAL;
+       }
+
+       switch (source) {
+       case OMAP_TIMER_SRC_SYS_CLK:
+               new_fclk_name = "sys_ck";
+               break;
+
+       case OMAP_TIMER_SRC_32_KHZ:
+               if (unlikely(cpu_is_omap2420()))
+                       new_fclk_name = "func_32k_ck";
+               else
+                       new_fclk_name = "32k_ck";
+               break;
+
+       case OMAP_TIMER_SRC_EXT_CLK:
+               if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_1) {
+                       new_fclk_name = "alt_ck";
+                       break;
+               }
+               dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
+                       __func__, __LINE__);
+               return -EINVAL;
+       }
+
+       new_fclk = clk_get(&pdev->dev, new_fclk_name);
+       if (IS_ERR_OR_NULL(new_fclk)) {
+               dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
+                       __func__, __LINE__, new_fclk_name);
+               clk_put(fclk);
+               return -EINVAL;
+       }
+
+       ret = clk_set_parent(fclk, new_fclk);
+       if (IS_ERR_VALUE(ret)) {
+               dev_err(&pdev->dev, "%s: clk_set_parent() to %s FAILED\n",
+                       __func__, new_fclk_name);
+               ret = -EINVAL;
+       }
+
+       clk_put(new_fclk);
+       clk_put(fclk);
+
+       return ret;
+}
+
+struct omap_device_pm_latency omap2_dmtimer_latency[] = {
+       {
+               .deactivate_func = omap_device_idle_hwmods,
+               .activate_func   = omap_device_enable_hwmods,
+               .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+       },
+};
+
+/**
+ * omap_timer_init - build and register timer device with an
+ * associated timer hwmod
+ * @oh:        timer hwmod pointer to be used to build timer device
+ * @user:      parameter that can be passed from calling hwmod API
+ *
+ * Called by omap_hwmod_for_each_by_class to register each of the timer
+ * devices present in the system. The number of timer devices is known
+ * by parsing through the hwmod database for a given class name. At the
+ * end of function call memory is allocated for timer device and it is
+ * registered to the framework ready to be proved by the driver.
+ */
+static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
+{
+       int id;
+       int ret = 0;
+       char *name = "omap_timer";
+       struct dmtimer_platform_data *pdata;
+       struct omap_device *od;
+       struct omap_timer_capability_dev_attr *timer_dev_attr;
+
+       pr_debug("%s: %s\n", __func__, oh->name);
+
+       /* on secure device, do not register secure timer */
+       timer_dev_attr = oh->dev_attr;
+       if (omap_type() != OMAP2_DEVICE_TYPE_GP && timer_dev_attr)
+               if (timer_dev_attr->timer_capability == OMAP_TIMER_SECURE)
+                       return ret;
+
+       pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               pr_err("%s: No memory for [%s]\n", __func__, oh->name);
+               return -ENOMEM;
+       }
+
+       /*
+        * Extract the IDs from name field in hwmod database
+        * and use the same for constructing ids' for the
+        * timer devices. In a way, we are avoiding usage of
+        * static variable witin the function to do the same.
+        * CAUTION: We have to be careful and make sure the
+        * name in hwmod database does not change in which case
+        * we might either make corresponding change here or
+        * switch back static variable mechanism.
+        */
+       sscanf(oh->name, "timer%2d", &id);
+
+       pdata->set_timer_src = omap2_dm_timer_set_src;
+       pdata->timer_ip_type = oh->class->rev;
+       pdata->needs_manual_reset = 0;
+
+       od = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
+                       omap2_dmtimer_latency,
+                       ARRAY_SIZE(omap2_dmtimer_latency),
+                       0);
+
+       if (IS_ERR(od)) {
+               pr_err("%s: Can't build omap_device for %s: %s.\n",
+                       __func__, name, oh->name);
+               ret = -EINVAL;
+       }
+
+       kfree(pdata);
+
+       return ret;
+}
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index a88fcdd..0f3e9c9 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -427,23 +427,6 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer)
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);

-int __omap_dm_timer_set_source(struct clk *timer_fck, struct clk *parent)
-{
-       int ret;
-
-       clk_disable(timer_fck);
-       ret = clk_set_parent(timer_fck, parent);
-       clk_enable(timer_fck);
-
-       /*
-        * When the functional clock disappears, too quick writes seem
-        * to cause an abort. XXX Is this still necessary?
-        */
-       __delay(300000);
-
-       return ret;
-}
-
 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 {
        if (source < 0 || source >= 3)
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 1b76450..00e1a4f 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -1,5 +1,5 @@
 /*
- * arch/arm/plat-omap/include/mach/dmtimer.h
+ * arch/arm/plat-omap/include/plat/dmtimer.h
  *
  * OMAP Dual-Mode Timers
  *
@@ -35,6 +35,8 @@
 #ifndef __ASM_ARCH_DMTIMER_H
 #define __ASM_ARCH_DMTIMER_H

+#include <linux/platform_device.h>
+
 /* clock sources */
 #define OMAP_TIMER_SRC_SYS_CLK                 0x00
 #define OMAP_TIMER_SRC_32_KHZ                  0x01
@@ -57,6 +59,15 @@
 #define OMAP_TIMER_IP_VERSION_1                        0x1
 #define OMAP_TIMER_IP_VERSION_2                        0x2

+/* timer capabilities used in hwmod database */
+#define OMAP_TIMER_SECURE                              0x80000000
+#define OMAP_TIMER_ALWON                               0x40000000
+#define OMAP_TIMER_HAS_PWM                             0x20000000
+
+struct omap_timer_capability_dev_attr {
+       u32 timer_capability;
+};
+
 extern struct omap_dm_timer *gptimer_wakeup;
 struct clk;

--
1.6.0.4


[-- Attachment #2: 0004-OMAP2-dmtimer-convert-to-platform-devices.patch --]
[-- Type: application/octet-stream, Size: 26152 bytes --]

From e62143961be3e162340032ea714dfa67a53de688 Mon Sep 17 00:00:00 2001
From: Tarun Kanti DebBarma <tarun.kanti@ti.com>
Date: Mon, 18 Apr 2011 15:33:59 +0530
Subject: [PATCH v14 04/12] OMAP2+: dmtimer: convert to platform devices

Add routines to converts dmtimers to platform devices. The device data
is obtained from hwmod database of respective platform and is registered
to device model after successful binding to driver.
In addition, capability attribute of each of the timers is added in
hwmod database.

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
Signed-off-by: Thara Gopinath <thara@ti.com>
Acked-by: Cousson, Benoit <b-cousson@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c |   22 ++++
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |   22 ++++
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   27 +++++
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   26 +++++
 arch/arm/mach-omap2/timer.c                |  158 +++++++++++++++++++++++++++-
 arch/arm/plat-omap/dmtimer.c               |   17 ---
 arch/arm/plat-omap/include/plat/dmtimer.h  |   13 ++-
 7 files changed, 266 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index 8eb3ce1..1f7cb36 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -358,6 +358,16 @@ static struct omap_hwmod_class omap2420_timer_hwmod_class = {
 	.rev = OMAP_TIMER_IP_VERSION_1,
 };
 
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap2420_timer1_hwmod;
 static struct omap_hwmod_irq_info omap2420_timer1_mpu_irqs[] = {
@@ -402,6 +412,7 @@ static struct omap_hwmod omap2420_timer1_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer1_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -452,6 +463,7 @@ static struct omap_hwmod omap2420_timer2_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer2_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -502,6 +514,7 @@ static struct omap_hwmod omap2420_timer3_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer3_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -552,6 +565,7 @@ static struct omap_hwmod omap2420_timer4_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer4_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -602,6 +616,7 @@ static struct omap_hwmod omap2420_timer5_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer5_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -653,6 +668,7 @@ static struct omap_hwmod omap2420_timer6_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer6_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -703,6 +719,7 @@ static struct omap_hwmod omap2420_timer7_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer7_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -753,6 +770,7 @@ static struct omap_hwmod omap2420_timer8_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer8_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -803,6 +821,7 @@ static struct omap_hwmod omap2420_timer9_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer9_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -853,6 +872,7 @@ static struct omap_hwmod omap2420_timer10_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer10_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -903,6 +923,7 @@ static struct omap_hwmod omap2420_timer11_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer11_slaves),
 	.class		= &omap2420_timer_hwmod_class,
@@ -953,6 +974,7 @@ static struct omap_hwmod omap2420_timer12_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer12_slaves),
 	.class		= &omap2420_timer_hwmod_class,
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index a860fb5..d7c6487 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -459,6 +459,16 @@ static struct omap_hwmod_class omap2430_timer_hwmod_class = {
 	.rev = OMAP_TIMER_IP_VERSION_1,
 };
 
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap2430_timer1_hwmod;
 static struct omap_hwmod_irq_info omap2430_timer1_mpu_irqs[] = {
@@ -503,6 +513,7 @@ static struct omap_hwmod omap2430_timer1_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer1_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -553,6 +564,7 @@ static struct omap_hwmod omap2430_timer2_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer2_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -603,6 +615,7 @@ static struct omap_hwmod omap2430_timer3_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer3_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -653,6 +666,7 @@ static struct omap_hwmod omap2430_timer4_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer4_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -703,6 +717,7 @@ static struct omap_hwmod omap2430_timer5_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer5_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -753,6 +768,7 @@ static struct omap_hwmod omap2430_timer6_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer6_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -803,6 +819,7 @@ static struct omap_hwmod omap2430_timer7_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer7_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -853,6 +870,7 @@ static struct omap_hwmod omap2430_timer8_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer8_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -903,6 +921,7 @@ static struct omap_hwmod omap2430_timer9_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer9_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -953,6 +972,7 @@ static struct omap_hwmod omap2430_timer10_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer10_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -1003,6 +1023,7 @@ static struct omap_hwmod omap2430_timer11_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer11_slaves),
 	.class		= &omap2430_timer_hwmod_class,
@@ -1053,6 +1074,7 @@ static struct omap_hwmod omap2430_timer12_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr       = &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer12_slaves),
 	.class		= &omap2430_timer_hwmod_class,
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index b98e2df..7fb2ecc 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -609,6 +609,21 @@ static struct omap_hwmod_class omap3xxx_timer_hwmod_class = {
 	.rev =  OMAP_TIMER_IP_VERSION_1,
 };
 
+/* secure timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_secure_dev_attr = {
+	.timer_capability       = OMAP_TIMER_SECURE,
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap3xxx_timer1_hwmod;
 static struct omap_hwmod_irq_info omap3xxx_timer1_mpu_irqs[] = {
@@ -653,6 +668,7 @@ static struct omap_hwmod omap3xxx_timer1_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer1_slaves),
 	.class		= &omap3xxx_timer_1ms_hwmod_class,
@@ -703,6 +719,7 @@ static struct omap_hwmod omap3xxx_timer2_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer2_slaves),
 	.class		= &omap3xxx_timer_1ms_hwmod_class,
@@ -753,6 +770,7 @@ static struct omap_hwmod omap3xxx_timer3_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer3_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -803,6 +821,7 @@ static struct omap_hwmod omap3xxx_timer4_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer4_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -853,6 +872,7 @@ static struct omap_hwmod omap3xxx_timer5_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer5_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -903,6 +923,7 @@ static struct omap_hwmod omap3xxx_timer6_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer6_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -953,6 +974,7 @@ static struct omap_hwmod omap3xxx_timer7_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer7_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -1003,6 +1025,7 @@ static struct omap_hwmod omap3xxx_timer8_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer8_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -1053,6 +1076,7 @@ static struct omap_hwmod omap3xxx_timer9_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer9_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -1103,6 +1127,7 @@ static struct omap_hwmod omap3xxx_timer10_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer10_slaves),
 	.class		= &omap3xxx_timer_1ms_hwmod_class,
@@ -1153,6 +1178,7 @@ static struct omap_hwmod omap3xxx_timer11_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer11_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
@@ -1203,6 +1229,7 @@ static struct omap_hwmod omap3xxx_timer12_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_secure_dev_attr,
 	.slaves		= omap3xxx_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer12_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 6485c90..38d5848 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -4014,6 +4014,21 @@ static struct omap_hwmod_class omap44xx_timer_hwmod_class = {
 	.rev	= OMAP_TIMER_IP_VERSION_2,
 };
 
+/* secure timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_secure_dev_attr = {
+	.timer_capability	= OMAP_TIMER_SECURE,
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability	= OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability	= OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap44xx_timer1_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = {
@@ -4054,6 +4069,7 @@ static struct omap_hwmod omap44xx_timer1_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer1_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4099,6 +4115,7 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer2_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4144,6 +4161,7 @@ static struct omap_hwmod omap44xx_timer3_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer3_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4189,6 +4207,7 @@ static struct omap_hwmod omap44xx_timer4_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer4_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4253,6 +4272,7 @@ static struct omap_hwmod omap44xx_timer5_hwmod = {
 			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer5_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4317,6 +4337,7 @@ static struct omap_hwmod omap44xx_timer6_hwmod = {
 			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer6_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4381,6 +4402,7 @@ static struct omap_hwmod omap44xx_timer7_hwmod = {
 			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer7_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4445,6 +4467,7 @@ static struct omap_hwmod omap44xx_timer8_hwmod = {
 			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer8_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4490,6 +4513,7 @@ static struct omap_hwmod omap44xx_timer9_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer9_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4535,6 +4559,7 @@ static struct omap_hwmod omap44xx_timer10_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer10_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -4580,6 +4605,7 @@ static struct omap_hwmod omap44xx_timer11_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
 		},
 	},
+	.dev_attr       = &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer11_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 2edeb1a..1c80337 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-omap2/timer-gp.c
+ * linux/arch/arm/mach-omap2/timer.c
  *
  * OMAP2 GP timer support.
  *
@@ -35,6 +35,7 @@
 #include <linux/irq.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/slab.h>
 
 #include <asm/mach/time.h>
 #include <plat/dmtimer.h>
@@ -42,6 +43,7 @@
 #include <asm/sched_clock.h>
 #include <plat/common.h>
 #include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 
 /* Parent clocks, eventually these will come from the clock framework */
 
@@ -129,6 +131,23 @@ static struct clock_event_device clockevent_gpt = {
 	.set_mode	= omap2_gp_timer_set_mode,
 };
 
+int __omap_dm_timer_set_source(struct clk *timer_fck, struct clk *parent)
+{
+	int ret;
+
+	clk_disable(timer_fck);
+	ret = clk_set_parent(timer_fck, parent);
+	clk_enable(timer_fck);
+
+	/*
+	 * When the functional clock disappears, too quick writes seem
+	 * to cause an abort. XXX Is this still necessary?
+	 */
+	__delay(300000);
+
+	return ret;
+}
+
 static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
 						int gptimer_id,
 						const char *fck_source)
@@ -359,3 +378,140 @@ struct sys_timer omap4_timer = {
 	.init	= omap4_timer_init,
 };
 #endif
+
+/**
+ * omap2_dm_timer_set_src - change the timer input clock source
+ * @pdev:	timer platform device pointer
+ * @source:	array index of parent clock source
+ */
+static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
+{
+	int ret;
+	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
+	struct clk *fclk, *new_fclk;
+	char *new_fclk_name = NULL;
+
+	fclk = clk_get(&pdev->dev, "fck");
+	if (IS_ERR_OR_NULL(fclk)) {
+		dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
+				__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	switch (source) {
+	case OMAP_TIMER_SRC_SYS_CLK:
+		new_fclk_name = "sys_ck";
+		break;
+
+	case OMAP_TIMER_SRC_32_KHZ:
+		if (unlikely(cpu_is_omap2420()))
+			new_fclk_name = "func_32k_ck";
+		else
+			new_fclk_name = "32k_ck";
+		break;
+
+	case OMAP_TIMER_SRC_EXT_CLK:
+		if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_1) {
+			new_fclk_name = "alt_ck";
+			break;
+		}
+		dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	new_fclk = clk_get(&pdev->dev, new_fclk_name);
+	if (IS_ERR_OR_NULL(new_fclk)) {
+		dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
+			__func__, __LINE__, new_fclk_name);
+		clk_put(fclk);
+		return -EINVAL;
+	}
+
+	ret = clk_set_parent(fclk, new_fclk);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(&pdev->dev, "%s: clk_set_parent() to %s FAILED\n",
+			__func__, new_fclk_name);
+		ret = -EINVAL;
+	}
+
+	clk_put(new_fclk);
+	clk_put(fclk);
+
+	return ret;
+}
+
+struct omap_device_pm_latency omap2_dmtimer_latency[] = {
+	{
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	},
+};
+
+/**
+ * omap_timer_init - build and register timer device with an
+ * associated timer hwmod
+ * @oh:	timer hwmod pointer to be used to build timer device
+ * @user:	parameter that can be passed from calling hwmod API
+ *
+ * Called by omap_hwmod_for_each_by_class to register each of the timer
+ * devices present in the system. The number of timer devices is known
+ * by parsing through the hwmod database for a given class name. At the
+ * end of function call memory is allocated for timer device and it is
+ * registered to the framework ready to be proved by the driver.
+ */
+static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
+{
+	int id;
+	int ret = 0;
+	char *name = "omap_timer";
+	struct dmtimer_platform_data *pdata;
+	struct omap_device *od;
+	struct omap_timer_capability_dev_attr *timer_dev_attr;
+
+	pr_debug("%s: %s\n", __func__, oh->name);
+
+	/* on secure device, do not register secure timer */
+	timer_dev_attr = oh->dev_attr;
+	if (omap_type() != OMAP2_DEVICE_TYPE_GP && timer_dev_attr)
+		if (timer_dev_attr->timer_capability == OMAP_TIMER_SECURE)
+			return ret;
+
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("%s: No memory for [%s]\n", __func__, oh->name);
+		return -ENOMEM;
+	}
+
+	/*
+	 * Extract the IDs from name field in hwmod database
+	 * and use the same for constructing ids' for the
+	 * timer devices. In a way, we are avoiding usage of
+	 * static variable witin the function to do the same.
+	 * CAUTION: We have to be careful and make sure the
+	 * name in hwmod database does not change in which case
+	 * we might either make corresponding change here or
+	 * switch back static variable mechanism.
+	 */
+	sscanf(oh->name, "timer%2d", &id);
+
+	pdata->set_timer_src = omap2_dm_timer_set_src;
+	pdata->timer_ip_type = oh->class->rev;
+	pdata->needs_manual_reset = 0;
+
+	od = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
+			omap2_dmtimer_latency,
+			ARRAY_SIZE(omap2_dmtimer_latency),
+			0);
+
+	if (IS_ERR(od)) {
+		pr_err("%s: Can't build omap_device for %s: %s.\n",
+			__func__, name, oh->name);
+		ret = -EINVAL;
+	}
+
+	kfree(pdata);
+
+	return ret;
+}
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index a88fcdd..0f3e9c9 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -427,23 +427,6 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer)
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
 
-int __omap_dm_timer_set_source(struct clk *timer_fck, struct clk *parent)
-{
-	int ret;
-
-	clk_disable(timer_fck);
-	ret = clk_set_parent(timer_fck, parent);
-	clk_enable(timer_fck);
-
-	/*
-	 * When the functional clock disappears, too quick writes seem
-	 * to cause an abort. XXX Is this still necessary?
-	 */
-	__delay(300000);
-
-	return ret;
-}
-
 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 {
 	if (source < 0 || source >= 3)
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 1b76450..00e1a4f 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -1,5 +1,5 @@
 /*
- * arch/arm/plat-omap/include/mach/dmtimer.h
+ * arch/arm/plat-omap/include/plat/dmtimer.h
  *
  * OMAP Dual-Mode Timers
  *
@@ -35,6 +35,8 @@
 #ifndef __ASM_ARCH_DMTIMER_H
 #define __ASM_ARCH_DMTIMER_H
 
+#include <linux/platform_device.h>
+
 /* clock sources */
 #define OMAP_TIMER_SRC_SYS_CLK			0x00
 #define OMAP_TIMER_SRC_32_KHZ			0x01
@@ -57,6 +59,15 @@
 #define OMAP_TIMER_IP_VERSION_1			0x1
 #define OMAP_TIMER_IP_VERSION_2			0x2
 
+/* timer capabilities used in hwmod database */
+#define OMAP_TIMER_SECURE				0x80000000
+#define OMAP_TIMER_ALWON				0x40000000
+#define OMAP_TIMER_HAS_PWM				0x20000000
+
+struct omap_timer_capability_dev_attr {
+	u32 timer_capability;
+};
+
 extern struct omap_dm_timer *gptimer_wakeup;
 struct clk;
 
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* RE: [PATCH v13 10/11] OMAP: dmtimer: mark clocksource and clockevent timers reserved
  2011-04-16 15:51 ` [PATCH v13 10/11] OMAP: dmtimer: mark clocksource and clockevent timers reserved Tarun Kanti DebBarma
  2011-04-17  6:12   ` Santosh Shilimkar
@ 2011-04-25  9:41   ` DebBarma, Tarun Kanti
  2011-04-29 10:40     ` Santosh Shilimkar
  1 sibling, 1 reply; 20+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-04-25  9:41 UTC (permalink / raw)
  To: linux-omap@vger.kernel.org

[-- Attachment #1: Type: text/plain, Size: 1098 bytes --]

In driver probe use sys_timer_reserved to identify which all timers
have already been used for clocksource and clockevent. Mark all those
timers as reserved so that no one else can use them.

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
---
Changed CONFIG_ARCH_OMAP2 to CONFIG_ARCH_OMAP2PLUS.

 arch/arm/plat-omap/dmtimer.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index e15b3a8..14d01ec 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -554,7 +554,13 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
 	timer->id = pdev->id;
 	timer->irq = irq->start;
 	timer->pdev = pdev;
-	timer->reserved = 0;
+#if defined(CONFIG_ARCH_OMAP2PLUS)
+	/* Mark clocksource and clockevent timers as reserved */
+	if ((sys_timer_reserved >> (pdev->id - 1)) & 0x1)
+		timer->reserved = 1;
+	else
+#endif
+		timer->reserved = 0;
 
 	 /* Skip pm_runtime_enable for OMAP1 */
 	if (!pdata->needs_manual_reset)
-- 
1.6.0.4


[-- Attachment #2: 0010-OMAP-dmtimer-mark-clocksource-and-clockevent-timer.patch --]
[-- Type: application/octet-stream, Size: 1260 bytes --]

From 0efd4f86014a7ebe5b1ec33e39296ff272f5537c Mon Sep 17 00:00:00 2001
From: Tarun Kanti DebBarma <tarun.kanti@ti.com>
Date: Mon, 18 Apr 2011 15:23:20 +0530
Subject: [PATCH v14 10/12] OMAP: dmtimer: mark clocksource and clockevent timers reserved

In driver probe use sys_timer_reserved to identify which all timers
have already been used for clocksource and clockevent. Mark all those
timers as reserved so that no one else can use them.

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
---
 arch/arm/plat-omap/dmtimer.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index e15b3a8..14d01ec 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -554,7 +554,13 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
 	timer->id = pdev->id;
 	timer->irq = irq->start;
 	timer->pdev = pdev;
-	timer->reserved = 0;
+#if defined(CONFIG_ARCH_OMAP2PLUS)
+	/* Mark clocksource and clockevent timers as reserved */
+	if ((sys_timer_reserved >> (pdev->id - 1)) & 0x1)
+		timer->reserved = 1;
+	else
+#endif
+		timer->reserved = 0;
 
 	 /* Skip pm_runtime_enable for OMAP1 */
 	if (!pdata->needs_manual_reset)
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v13 10/11] OMAP: dmtimer: mark clocksource and clockevent timers reserved
  2011-04-25  9:41   ` DebBarma, Tarun Kanti
@ 2011-04-29 10:40     ` Santosh Shilimkar
  0 siblings, 0 replies; 20+ messages in thread
From: Santosh Shilimkar @ 2011-04-29 10:40 UTC (permalink / raw)
  To: DebBarma, Tarun Kanti; +Cc: linux-omap@vger.kernel.org

Tarun,

On 4/25/2011 3:11 PM, DebBarma, Tarun Kanti wrote:
> In driver probe use sys_timer_reserved to identify which all timers
> have already been used for clocksource and clockevent. Mark all those
> timers as reserved so that no one else can use them.
>
> Signed-off-by: Tarun Kanti DebBarma<tarun.kanti@ti.com>
> ---
> Changed CONFIG_ARCH_OMAP2 to CONFIG_ARCH_OMAP2PLUS.
>
>   arch/arm/plat-omap/dmtimer.c |    8 +++++++-
>   1 files changed, 7 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
> index e15b3a8..14d01ec 100644
> --- a/arch/arm/plat-omap/dmtimer.c
> +++ b/arch/arm/plat-omap/dmtimer.c
> @@ -554,7 +554,13 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
>   	timer->id = pdev->id;
>   	timer->irq = irq->start;
>   	timer->pdev = pdev;
> -	timer->reserved = 0;
> +#if defined(CONFIG_ARCH_OMAP2PLUS)

Do you really need this. You might want to reserve timer on
OMAP1 as well. Avoid #ifdefery

> +	/* Mark clocksource and clockevent timers as reserved */
> +	if ((sys_timer_reserved>>  (pdev->id - 1))&  0x1)
> +		timer->reserved = 1;
> +	else
> +#endif
> +		timer->reserved = 0;
>
>   	 /* Skip pm_runtime_enable for OMAP1 */
>   	if (!pdata->needs_manual_reset)


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v13 04/11] OMAP2+: dmtimer: convert to platform devices
  2011-04-16 15:50 ` [PATCH v13 04/11] OMAP2+: dmtimer: convert " Tarun Kanti DebBarma
  2011-04-25  9:38   ` DebBarma, Tarun Kanti
@ 2011-04-29 10:45   ` Santosh Shilimkar
  1 sibling, 0 replies; 20+ messages in thread
From: Santosh Shilimkar @ 2011-04-29 10:45 UTC (permalink / raw)
  To: Tarun Kanti DebBarma; +Cc: linux-omap, Thara Gopinath

On 4/16/2011 9:20 PM, Tarun Kanti DebBarma wrote:
> Add routines to converts dmtimers to platform devices. The device data
> is obtained from hwmod database of respective platform and is registered
> to device model after successful binding to driver.
> In addition, capability attribute of each of the timers is added in
> hwmod database.
>
> Signed-off-by: Tarun Kanti DebBarma<tarun.kanti@ti.com>
> Signed-off-by: Thara Gopinath<thara@ti.com>
> Acked-by: Cousson, Benoit<b-cousson@ti.com>
> ---
>   arch/arm/mach-omap2/omap_hwmod_2420_data.c |   22 ++++
>   arch/arm/mach-omap2/omap_hwmod_2430_data.c |   22 ++++
>   arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   27 +++++
>   arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   25 +++++
>   arch/arm/mach-omap2/timer.c                |  158 +++++++++++++++++++++++++++-
>   arch/arm/plat-omap/dmtimer.c               |   17 ---
>   arch/arm/plat-omap/include/plat/dmtimer.h  |   13 ++-
>   7 files changed, 265 insertions(+), 19 deletions(-)
>
[...]

> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
> index 2edeb1a..1c80337 100644
> --- a/arch/arm/mach-omap2/timer.c
> +++ b/arch/arm/mach-omap2/timer.c
> @@ -1,5 +1,5 @@
>   /*
> - * linux/arch/arm/mach-omap2/timer-gp.c
> + * linux/arch/arm/mach-omap2/timer.c
>    *
>    * OMAP2 GP timer support.
>    *
> @@ -35,6 +35,7 @@
>   #include<linux/irq.h>
>   #include<linux/clocksource.h>
>   #include<linux/clockchips.h>
> +#include<linux/slab.h>
>
>   #include<asm/mach/time.h>
>   #include<plat/dmtimer.h>
> @@ -42,6 +43,7 @@
>   #include<asm/sched_clock.h>
>   #include<plat/common.h>
>   #include<plat/omap_hwmod.h>
> +#include<plat/omap_device.h>
>
>   /* Parent clocks, eventually these will come from the clock framework */
>
> @@ -129,6 +131,23 @@ static struct clock_event_device clockevent_gpt = {
>   	.set_mode	= omap2_gp_timer_set_mode,
>   };
>
> +int __omap_dm_timer_set_source(struct clk *timer_fck, struct clk *parent)
> +{
> +	int ret;
> +
> +	clk_disable(timer_fck);
> +	ret = clk_set_parent(timer_fck, parent);
> +	clk_enable(timer_fck);
> +
> +	/*
> +	 * When the functional clock disappears, too quick writes seem
> +	 * to cause an abort. XXX Is this still necessary?
> +	 */
> +	__delay(300000);
> +
> +	return ret;
> +}
> +
>   static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
>   						int gptimer_id,
>   						const char *fck_source)
> @@ -359,3 +378,140 @@ struct sys_timer omap4_timer = {
>   	.init	= omap4_timer_init,
>   };
>   #endif
> +
> +/**
> + * omap2_dm_timer_set_src - change the timer input clock source
> + * @pdev:	timer platform device pointer
> + * @source:	array index of parent clock source
> + */
> +static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
> +{
> +	int ret;
> +	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
> +	struct clk *fclk, *new_fclk;
> +	char *new_fclk_name = NULL;
> +
> +	fclk = clk_get(&pdev->dev, "fck");
> +	if (IS_ERR_OR_NULL(fclk)) {
> +		dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
> +				__func__, __LINE__);
> +		return -EINVAL;
> +	}
> +
> +	switch (source) {
> +	case OMAP_TIMER_SRC_SYS_CLK:
> +		new_fclk_name = "sys_ck";
> +		break;
> +
> +	case OMAP_TIMER_SRC_32_KHZ:
> +		if (unlikely(cpu_is_omap2420()))
> +			new_fclk_name = "func_32k_ck";
> +		else
> +			new_fclk_name = "32k_ck";
> +		break;
> +
> +	case OMAP_TIMER_SRC_EXT_CLK:
> +		if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_1) {
> +			new_fclk_name = "alt_ck";
> +			break;
> +		}
> +		dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
> +			__func__, __LINE__);
> +		return -EINVAL;
> +	}
> +
> +	new_fclk = clk_get(&pdev->dev, new_fclk_name);
> +	if (IS_ERR_OR_NULL(new_fclk)) {
> +		dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
> +			__func__, __LINE__, new_fclk_name);
> +		clk_put(fclk);
> +		return -EINVAL;
> +	}
> +
> +	ret = clk_set_parent(fclk, new_fclk);
> +	if (IS_ERR_VALUE(ret)) {
> +		dev_err(&pdev->dev, "%s: clk_set_parent() to %s FAILED\n",
> +			__func__, new_fclk_name);
> +		ret = -EINVAL;
> +	}
> +
> +	clk_put(new_fclk);
> +	clk_put(fclk);
> +
> +	return ret;
> +}

I see two functions doing same job of switching timer
clock-source between 32 K and sysclock. This should
be fixed.

Regards
Santosh




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v13 11/11] OMAP: dmtimer: convert to a driver
  2011-04-16 15:51 ` [PATCH v13 11/11] OMAP: dmtimer: convert to a driver Tarun Kanti DebBarma
@ 2011-04-29 10:51   ` Santosh Shilimkar
  0 siblings, 0 replies; 20+ messages in thread
From: Santosh Shilimkar @ 2011-04-29 10:51 UTC (permalink / raw)
  To: Tarun Kanti DebBarma; +Cc: linux-omap

Tarun,

On 4/16/2011 9:21 PM, Tarun Kanti DebBarma wrote:
> Make plat-omap/dmtimer.c a normal driver. It is moved to drivers/misc
> as timer-omap.c and the corresponding header file has been moved to
> include/linux as timer-omap.h. Files which included plat/dmtimer.h
> are changed to include linux/timer-omap.h now.
>
> Signed-off-by: Tarun Kanti DebBarma<tarun.kanti@ti.com>
> ---
>   arch/arm/mach-omap1/dmtimer.c              |    3 +-
>   arch/arm/mach-omap1/pm.c                   |    2 +-
>   arch/arm/mach-omap1/timer32k.c             |    2 +-
>   arch/arm/mach-omap2/omap_hwmod_2420_data.c |    3 +-
>   arch/arm/mach-omap2/omap_hwmod_2430_data.c |    3 +-
>   arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |    3 +-
>   arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    2 +-
>   arch/arm/mach-omap2/pm-debug.c             |    2 +-
>   arch/arm/mach-omap2/timer.c                |    2 +-
>   arch/arm/plat-omap/Makefile                |    1 -
>   drivers/misc/Makefile                      |    1 +
>   drivers/misc/timer-omap.c                  |  643 ++++++++++++++++++++++++++++
>   drivers/tty/serial/omap-serial.c           |    2 +-
>   include/linux/timer-omap.h                 |  351 +++++++++++++++
>   14 files changed, 1008 insertions(+), 12 deletions(-)
>   create mode 100644 drivers/misc/timer-omap.c
>   create mode 100644 include/linux/timer-omap.h
>

[...]

> diff --git a/drivers/misc/timer-omap.c b/drivers/misc/timer-omap.c
> new file mode 100644
> index 0000000..4ee0571
> --- /dev/null
> +++ b/drivers/misc/timer-omap.c
[...]

> +
> +#if defined(CONFIG_ARCH_OMAP1)

Well this is suppose to be device driver so no place
for SOC #ifdef. You should remove this ...

> +
> +/**
> + * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
> + * @inputmask: current value of idlect mask
> + */
> +__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
> +{
> +	int i = 0;
> +	struct omap_dm_timer *timer = NULL;
> +
> +	/* If ARMXOR cannot be idled this function call is unnecessary */
> +	if (!(inputmask&  (1<<  1)))
> +		return inputmask;
> +

[...]

> + * omap_dm_timer_probe - probe function called for every registered device
> + * @pdev:	pointer to current timer platform device
> + *
> + * Called by driver framework at the end of device registration for all
> + * timer devices.
> + */
> +static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	struct omap_dm_timer *timer;
> +	struct resource *mem, *irq, *ioarea;
> +	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
> +
> +	if (!pdata) {
> +		dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (unlikely(!irq)) {
> +		dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
> +		ret = -ENODEV;
> +		goto err_free_pdev;
> +	}
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (unlikely(!mem)) {
> +		dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
> +		ret = -ENODEV;
> +		goto err_free_pdev;
> +	}
> +
> +	ioarea = request_mem_region(mem->start, resource_size(mem),
> +			pdev->name);
> +	if (!ioarea) {
> +		dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
> +		ret = -EBUSY;
> +		goto err_free_pdev;
> +	}
> +
> +	timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
> +	if (!timer) {
> +		dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
> +			__func__);
> +		ret = -ENOMEM;
> +		goto err_release_ioregion;
> +	}
> +
> +	timer->io_base = ioremap(mem->start, resource_size(mem));
> +	if (!timer->io_base) {
> +		dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
> +		ret = -ENOMEM;
> +		goto err_free_mem;
> +	}
> +
> +	if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_2) {
> +		timer->func_offset = VERSION2_TIMER_WAKEUP_EN_REG_OFFSET;
> +		timer->intr_offset = VERSION2_TIMER_STAT_REG_OFFSET;
> +	} else {
> +		timer->func_offset = 0;
> +		timer->intr_offset = 0;
> +	}
> +
> +	timer->id = pdev->id;
> +	timer->irq = irq->start;
> +	timer->pdev = pdev;
> +#if defined(CONFIG_ARCH_OMAP2)

This one too ..

[...]

> diff --git a/include/linux/timer-omap.h b/include/linux/timer-omap.h
> new file mode 100644
> index 0000000..a6b4cac
> --- /dev/null
> +++ b/include/linux/timer-omap.h
> @@ -0,0 +1,351 @@
> +/*
> + * include/linux/timer-omap.h
> + *
> + * OMAP Dual-Mode Timers
> + *

[...]

> +/* register offsets */
> +#define _OMAP_TIMER_ID_OFFSET		0x00
> +#define _OMAP_TIMER_OCP_CFG_OFFSET	0x10
> +#define _OMAP_TIMER_SYS_STAT_OFFSET	0x14
> +#define _OMAP_TIMER_STAT_OFFSET		0x18
> +#define _OMAP_TIMER_INT_EN_OFFSET	0x1c
> +#define _OMAP_TIMER_WAKEUP_EN_OFFSET	0x20
> +#define _OMAP_TIMER_CTRL_OFFSET		0x24
> +#define		OMAP_TIMER_CTRL_GPOCFG		(1<<  14)
> +#define		OMAP_TIMER_CTRL_CAPTMODE	(1<<  13)
> +#define		OMAP_TIMER_CTRL_PT		(1<<  12)
> +#define		OMAP_TIMER_CTRL_TCM_LOWTOHIGH	(0x1<<  8)
> +#define		OMAP_TIMER_CTRL_TCM_HIGHTOLOW	(0x2<<  8)
> +#define		OMAP_TIMER_CTRL_TCM_BOTHEDGES	(0x3<<  8)
> +#define		OMAP_TIMER_CTRL_SCPWM		(1<<  7)
> +#define		OMAP_TIMER_CTRL_CE		(1<<  6) /* compare enable */
> +#define		OMAP_TIMER_CTRL_PRE		(1<<  5) /* prescaler enable */
> +#define		OMAP_TIMER_CTRL_PTV_SHIFT	2 /* prescaler value shift */
> +#define		OMAP_TIMER_CTRL_POSTED		(1<<  2)
> +#define		OMAP_TIMER_CTRL_AR		(1<<  1) /* auto-reload enable */
> +#define		OMAP_TIMER_CTRL_ST		(1<<  0) /* start timer */
Fix the indentation above and in rest of the file.

Regards
Santosh

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v13 00/11] dmtimer adaptation to platform_driver
  2011-04-16 15:50 [PATCH v13 00/11] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (10 preceding siblings ...)
  2011-04-16 15:51 ` [PATCH v13 11/11] OMAP: dmtimer: convert to a driver Tarun Kanti DebBarma
@ 2011-04-29 11:05 ` Santosh Shilimkar
  11 siblings, 0 replies; 20+ messages in thread
From: Santosh Shilimkar @ 2011-04-29 11:05 UTC (permalink / raw)
  To: Tarun Kanti DebBarma; +Cc: l-o, Tony Lindgren

Tarun,

On 4/16/2011 9:20 PM, Tarun Kanti DebBarma wrote:
> dmtimer adaptation to platform_driver.
>
> This patch series is adaptation of dmtimer code to platform driver
> using omap_device and omap_hwmod abstraction.
>
> Baseline:
> git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
> Branch: devel-timer
>

[...]

>
> Tarun Kanti DebBarma (11):
>    OMAP2+: dmtimer: add device names to flck nodes
>    OMAP4: hwmod data: add dmtimer version information
>    OMAP1: dmtimer: conversion to platform devices
>    OMAP2+: dmtimer: convert to platform devices
>    OMAP: dmtimer: platform driver
>    dmtimer: switch-over to platform device driver
>    OMAP: dmtimer: pm_runtime support
>    OMAP: dmtimer: add timeout to low-level routines
>    OMAP: dmtimer: use mutex instead of spinlock
>    OMAP: dmtimer: mark clocksource and clockevent timers reserved
>    OMAP: dmtimer: convert to a driver
>
>   arch/arm/mach-omap1/Makefile               |    2 +-
>   arch/arm/mach-omap1/dmtimer.c              |  173 ++++++++
>   arch/arm/mach-omap1/pm.c                   |    2 +-
>   arch/arm/mach-omap1/timer32k.c             |    2 +-
>   arch/arm/mach-omap2/clock2420_data.c       |   52 +++-
>   arch/arm/mach-omap2/clock2430_data.c       |   48 ++
>   arch/arm/mach-omap2/clock3xxx_data.c       |   36 ++
>   arch/arm/mach-omap2/clock44xx_data.c       |   33 ++
>   arch/arm/mach-omap2/omap_hwmod_2420_data.c |   25 +-
>   arch/arm/mach-omap2/omap_hwmod_2430_data.c |   25 +-
>   arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   30 ++-
>   arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   28 ++
>   arch/arm/mach-omap2/pm-debug.c             |    2 +-
>   arch/arm/mach-omap2/timer.c                |  202 +++++++++-
>   arch/arm/plat-omap/Makefile                |    1 -
>   arch/arm/plat-omap/dmtimer.c               |  569 +++++++++++-------------
>   arch/arm/plat-omap/include/plat/dmtimer.h  |  135 +++++--
>   drivers/misc/Makefile                      |    1 +
>   drivers/misc/timer-omap.c                  |  643 ++++++++++++++++++++++++++++
>   drivers/tty/serial/omap-serial.c           |    2 +-
>   include/linux/timer-omap.h                 |  351 +++++++++++++++
>   21 files changed, 2003 insertions(+), 359 deletions(-)
>   create mode 100644 arch/arm/mach-omap1/dmtimer.c
>   create mode 100644 drivers/misc/timer-omap.c
>   create mode 100644 include/linux/timer-omap.h
>
While reviewing this series I realised that you haven't removed
the files after moving the files to drivers/*. That's why we
don't see the negative diffstat from arch/arm/*omap*/

Look at the diffstat with updated patch below. A whopping
~1000 lines from arch/arm/* are getting removed.

Any ways wait for Tony to review this series before posting
next version.

Regards
Santosh


 From d9df922c74648659eca9959c0906d4c4c8e5113c Mon Sep 17 00:00:00 2001
From: Tarun Kanti DebBarma <tarun.kanti@ti.com>
Date: Fri, 29 Apr 2011 14:44:50 +0530
Subject: [PATCH] timer: move the OMAP timer driver to drivers/misc

Make plat-omap/dmtimer.c a normal driver. It is moved to drivers/misc
as timer-omap.c and the corresponding header file has been moved to
include/linux as timer-omap.h. Files which included plat/dmtimer.h
are changed to include linux/timer-omap.h now.

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
---
  arch/arm/mach-omap1/dmtimer.c              |    3 +-
  arch/arm/mach-omap1/pm.c                   |    2 +-
  arch/arm/mach-omap1/timer32k.c             |    2 +-
  arch/arm/mach-omap2/omap_hwmod_2420_data.c |    3 +-
  arch/arm/mach-omap2/omap_hwmod_2430_data.c |    3 +-
  arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |    3 +-
  arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    2 +-
  arch/arm/mach-omap2/pm-debug.c             |    2 +-
  arch/arm/mach-omap2/timer.c                |    2 +-
  arch/arm/plat-omap/Makefile                |    1 -
  arch/arm/plat-omap/dmtimer.c               |  645 
----------------------------
  arch/arm/plat-omap/include/plat/dmtimer.h  |  349 ---------------
  drivers/misc/Makefile                      |    1 +
  drivers/misc/timer-omap.c                  |  642 
+++++++++++++++++++++++++++
  drivers/tty/serial/omap-serial.c           |    2 +-
  include/linux/timer-omap.h                 |  351 +++++++++++++++
  16 files changed, 1007 insertions(+), 1006 deletions(-)
  delete mode 100644 arch/arm/plat-omap/dmtimer.c
  delete mode 100644 arch/arm/plat-omap/include/plat/dmtimer.h
  create mode 100644 drivers/misc/timer-omap.c
  create mode 100644 include/linux/timer-omap.h

diff --git a/arch/arm/mach-omap1/dmtimer.c b/arch/arm/mach-omap1/dmtimer.c
index 980b23b..3a0cece 100644
--- a/arch/arm/mach-omap1/dmtimer.c
+++ b/arch/arm/mach-omap1/dmtimer.c
@@ -25,11 +25,10 @@
  #include <linux/err.h>
  #include <linux/slab.h>
  #include <linux/platform_device.h>
+#include <linux/timer-omap.h>

  #include <mach/irqs.h>

-#include <plat/dmtimer.h>
-
  #define OMAP1610_GPTIMER1_BASE		0xfffb1400
  #define OMAP1610_GPTIMER2_BASE		0xfffb1c00
  #define OMAP1610_GPTIMER3_BASE		0xfffb2400
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index 98ba978..4344a70 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -42,6 +42,7 @@
  #include <linux/sysfs.h>
  #include <linux/module.h>
  #include <linux/io.h>
+#include <linux/timer-omap.h>

  #include <asm/irq.h>
  #include <asm/atomic.h>
@@ -55,7 +56,6 @@
  #include <plat/tc.h>
  #include <plat/mux.h>
  #include <plat/dma.h>
-#include <plat/dmtimer.h>

  #include "pm.h"

diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
index 96604a5..83b4094 100644
--- a/arch/arm/mach-omap1/timer32k.c
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -45,6 +45,7 @@
  #include <linux/clocksource.h>
  #include <linux/clockchips.h>
  #include <linux/io.h>
+#include <linux/timer-omap.h>

  #include <asm/system.h>
  #include <mach/hardware.h>
@@ -53,7 +54,6 @@
  #include <asm/mach/irq.h>
  #include <asm/mach/time.h>
  #include <plat/common.h>
-#include <plat/dmtimer.h>

  /*
   * 
---------------------------------------------------------------------------
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c 
b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index 1f7cb36..fe080f4 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -11,6 +11,8 @@
   * XXX handle crossbar/shared link difference for L3?
   * XXX these should be marked initdata for multi-OMAP kernels
   */
+#include <linux/timer-omap.h>
+
  #include <plat/omap_hwmod.h>
  #include <mach/irqs.h>
  #include <plat/cpu.h>
@@ -19,7 +21,6 @@
  #include <plat/i2c.h>
  #include <plat/gpio.h>
  #include <plat/mcspi.h>
-#include <plat/dmtimer.h>
  #include <plat/l3_2xxx.h>
  #include <plat/l4_2xxx.h>

diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c 
b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index d7c6487..85dec8a 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -11,6 +11,8 @@
   * XXX handle crossbar/shared link difference for L3?
   * XXX these should be marked initdata for multi-OMAP kernels
   */
+#include <linux/timer-omap.h>
+
  #include <plat/omap_hwmod.h>
  #include <mach/irqs.h>
  #include <plat/cpu.h>
@@ -20,7 +22,6 @@
  #include <plat/gpio.h>
  #include <plat/mcbsp.h>
  #include <plat/mcspi.h>
-#include <plat/dmtimer.h>
  #include <plat/mmc.h>
  #include <plat/l3_2xxx.h>

diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c 
b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 7fb2ecc..2649ed8 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -13,6 +13,8 @@
   *
   * XXX these should be marked initdata for multi-OMAP kernels
   */
+#include <linux/timer-omap.h>
+
  #include <plat/omap_hwmod.h>
  #include <mach/irqs.h>
  #include <plat/cpu.h>
@@ -25,7 +27,6 @@
  #include <plat/mmc.h>
  #include <plat/mcbsp.h>
  #include <plat/mcspi.h>
-#include <plat/dmtimer.h>

  #include "omap_hwmod_common_data.h"

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c 
b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 38d5848..35204ef 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -19,6 +19,7 @@
   */

  #include <linux/io.h>
+#include <linux/timer-omap.h>

  #include <plat/omap_hwmod.h>
  #include <plat/cpu.h>
@@ -27,7 +28,6 @@
  #include <plat/mcspi.h>
  #include <plat/mcbsp.h>
  #include <plat/mmc.h>
-#include <plat/dmtimer.h>

  #include "omap_hwmod_common_data.h"

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 6e19f10..404faf7 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -26,12 +26,12 @@
  #include <linux/io.h>
  #include <linux/module.h>
  #include <linux/slab.h>
+#include <linux/timer-omap.h>

  #include <plat/clock.h>
  #include <plat/board.h>
  #include "powerdomain.h"
  #include "clockdomain.h"
-#include <plat/dmtimer.h>
  #include <plat/omap-pm.h>

  #include "cm2xxx_3xxx.h"
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index b7862ca..5fd2363 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -36,9 +36,9 @@
  #include <linux/clocksource.h>
  #include <linux/clockchips.h>
  #include <linux/slab.h>
+#include <linux/timer-omap.h>

  #include <asm/mach/time.h>
-#include <plat/dmtimer.h>
  #include <asm/localtimer.h>
  #include <asm/sched_clock.h>
  #include <plat/common.h>
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index a4a1285..472eeed 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -22,7 +22,6 @@ obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
  obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o

  obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
-obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
  obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
  obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
  i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
deleted file mode 100644
index 14d01ec..0000000
--- a/arch/arm/plat-omap/dmtimer.c
+++ /dev/null
@@ -1,645 +0,0 @@
-/*
- * linux/arch/arm/plat-omap/dmtimer.c
- *
- * OMAP Dual-Mode Timers
- *
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
- * Tarun Kanti DebBarma <tarun.kanti@ti.com>
- * Thara Gopinath <thara@ti.com>
- *
- * dmtimer adaptation to platform_driver.
- *
- * Copyright (C) 2005 Nokia Corporation
- * OMAP2 support by Juha Yrjola
- * API improvements and OMAP2 clock framework support by Timo Teras
- *
- * Copyright (C) 2009 Texas Instruments
- * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
- *
- * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
-#include <linux/err.h>
-
-#include <plat/dmtimer.h>
-
-static LIST_HEAD(omap_timer_list);
-static DEFINE_MUTEX(dm_timer_mutex);
-
-/**
- * omap_dm_timer_read_reg - read timer registers in posted and 
non-posted mode
- * @timer:      timer pointer over which read operation to perform
- * @reg:        lowest byte holds the register offset
- *
- * The posted mode bit is encoded in reg. Note that in posted mode write
- * pending bit must be checked. Otherwise a read of a non completed write
- * will produce an error.
- */
-static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, 
u32 reg)
-{
-	if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
-		reg += timer->func_offset;
-	else if (reg >= OMAP_TIMER_STAT_REG)
-		reg += timer->intr_offset;
-
-	return __omap_dm_timer_read(timer->io_base, reg, timer->posted,
-					timer->func_offset);
-}
-
-/**
- * omap_dm_timer_write_reg - write timer registers in posted and 
non-posted mode
- * @timer:      timer pointer over which write operation is to perform
- * @reg:        lowest byte holds the register offset
- * @value:      data to write into the register
- *
- * The posted mode bit is encoded in reg. Note that in posted mode the 
write
- * pending bit must be checked. Otherwise a write on a register which has a
- * pending write will be lost.
- */
-static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
-						u32 value)
-{
-	if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
-		reg += timer->func_offset;
-	else if (reg >= OMAP_TIMER_STAT_REG)
-		reg += timer->intr_offset;
-
-	__omap_dm_timer_write(timer->io_base, reg, value, timer->posted,
-				timer->func_offset);
-}
-
-static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
-{
-	int c;
-
-	c = 0;
-	while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
-		c++;
-		if (c > 100000) {
-			printk(KERN_ERR "Timer failed to reset\n");
-			return;
-		}
-	}
-}
-
-/* Assumes the source clock has been set by caller */
-void __omap_dm_timer_reset(struct omap_dm_timer *timer, int autoidle,
-				int wakeup)
-{
-	u32 l;
-
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
-	l |= 0x02 << 3;  /* Set to smart-idle mode */
-	l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
-
-	if (autoidle)
-		l |= 0x1 << 0;
-
-	if (wakeup)
-		l |= 1 << 2;
-
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
-}
-
-static void omap_dm_timer_reset(struct omap_dm_timer *timer)
-{
-	int autoidle = 0, wakeup = 0;
-
-	if (timer->pdev->id != 1) {
-		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
-		omap_dm_timer_wait_for_reset(timer);
-	}
-	__omap_dm_timer_reset(timer, autoidle, wakeup);
-}
-
-void omap_dm_timer_prepare(struct omap_dm_timer *timer)
-{
-	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
-
-	timer->fclk = clk_get(&timer->pdev->dev, "fck");
-	if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
-		timer->fclk = NULL;
-		dev_err(&timer->pdev->dev, ": No fclk handle.\n");
-		return;
-	}
-
-	omap_dm_timer_enable(timer);
-
-	if (pdata->needs_manual_reset)
-		omap_dm_timer_reset(timer);
-
-	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
-
-	__omap_dm_timer_set_posted(timer->io_base, timer->func_offset);
-	timer->posted = 1;
-}
-
-struct omap_dm_timer *omap_dm_timer_request(void)
-{
-	struct omap_dm_timer *timer = NULL, *t;
-
-	mutex_lock(&dm_timer_mutex);
-	list_for_each_entry(t, &omap_timer_list, node) {
-		if (t->reserved)
-			continue;
-
-		timer = t;
-		timer->reserved = 1;
-		break;
-	}
-	mutex_unlock(&dm_timer_mutex);
-
-	if (timer)
-		omap_dm_timer_prepare(timer);
-	else
-		pr_debug("%s: free timer not available.\n", __func__);
-
-	return timer;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_request);
-
-struct omap_dm_timer *omap_dm_timer_request_specific(int id)
-{
-	struct omap_dm_timer *timer = NULL, *t;
-
-	mutex_lock(&dm_timer_mutex);
-	list_for_each_entry(t, &omap_timer_list, node) {
-		if (t->pdev->id == id && !t->reserved) {
-			timer = t;
-			timer->reserved = 1;
-			break;
-		}
-	}
-	mutex_unlock(&dm_timer_mutex);
-
-	if (timer)
-		omap_dm_timer_prepare(timer);
-	else
-		pr_debug("%s: timer%d not available.\n", __func__, id);
-
-	return timer;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
-
-void omap_dm_timer_free(struct omap_dm_timer *timer)
-{
-	omap_dm_timer_disable(timer);
-
-	clk_put(timer->fclk);
-
-	WARN_ON(!timer->reserved);
-	timer->reserved = 0;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_free);
-
-void omap_dm_timer_enable(struct omap_dm_timer *timer)
-{
-	if (timer->enabled)
-		return;
-
-	pm_runtime_get_sync(&timer->pdev->dev);
-
-	timer->enabled = 1;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
-
-void omap_dm_timer_disable(struct omap_dm_timer *timer)
-{
-	if (!timer->enabled)
-		return;
-
-	pm_runtime_put_sync(&timer->pdev->dev);
-
-	timer->enabled = 0;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
-
-int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
-{
-	return timer->irq;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
-
-#if defined(CONFIG_ARCH_OMAP1)
-
-/**
- * omap_dm_timer_modify_idlect_mask - Check if any running timers use 
ARMXOR
- * @inputmask: current value of idlect mask
- */
-__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
-{
-	int i = 0;
-	struct omap_dm_timer *timer = NULL;
-
-	/* If ARMXOR cannot be idled this function call is unnecessary */
-	if (!(inputmask & (1 << 1)))
-		return inputmask;
-
-	/* If any active timer is using ARMXOR return modified mask */
-	mutex_lock(&dm_timer_mutex);
-	list_for_each_entry(timer, &omap_timer_list, node) {
-
-		u32 l;
-
-		l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
-		if (l & OMAP_TIMER_CTRL_ST) {
-			if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
-				inputmask &= ~(1 << 1);
-			else
-				inputmask &= ~(1 << 2);
-		}
-		i++;
-	}
-	mutex_unlock(&dm_timer_mutex);
-
-	return inputmask;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
-
-#else
-
-struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
-{
-	return timer->fclk;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
-
-__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
-{
-	BUG();
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
-
-#endif
-
-void omap_dm_timer_trigger(struct omap_dm_timer *timer)
-{
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
-
-void omap_dm_timer_start(struct omap_dm_timer *timer)
-{
-	u32 l;
-
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
-	if (!(l & OMAP_TIMER_CTRL_ST)) {
-		l |= OMAP_TIMER_CTRL_ST;
-		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
-	}
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_start);
-
-void omap_dm_timer_stop(struct omap_dm_timer *timer)
-{
-	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
-	bool omap2 = true;
-	unsigned long rate = clk_get_rate(timer->fclk) + 1;
-
-	if (unlikely(pdata->needs_manual_reset))
-		omap2 = false;
-
-	__omap_dm_timer_stop(timer->io_base, rate, timer->posted, omap2,
-			timer->intr_offset, timer->func_offset);
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
-
-int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
-{
-	int ret = -EINVAL;
-	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
-
-	if (source < 0 || source >= 3)
-		return -EINVAL;
-
-	omap_dm_timer_disable(timer);
-	/* change the timer clock source */
-	ret = pdata->set_timer_src(timer->pdev, source);
-	omap_dm_timer_enable(timer);
-
-	/*
-	 * When the functional clock disappears, too quick writes seem
-	 * to cause an abort. XXX Is this still necessary?
-	 */
-	__delay(300000);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
-
-void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
-			    unsigned int load)
-{
-	u32 l;
-
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
-	if (autoreload)
-		l |= OMAP_TIMER_CTRL_AR;
-	else
-		l &= ~OMAP_TIMER_CTRL_AR;
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
-
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
-
-/* Optimized set_load which removes costly spin wait in timer_start */
-void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int 
autoreload,
-                            unsigned int load)
-{
-	u32 l;
-
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
-	if (autoreload) {
-		l |= OMAP_TIMER_CTRL_AR;
-		omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
-	} else {
-		l &= ~OMAP_TIMER_CTRL_AR;
-	}
-	l |= OMAP_TIMER_CTRL_ST;
-
-	__omap_dm_timer_load_start(timer->io_base, l, load, timer->posted,
-					timer->func_offset);
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
-
-void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
-			     unsigned int match)
-{
-	u32 l;
-
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
-	if (enable)
-		l |= OMAP_TIMER_CTRL_CE;
-	else
-		l &= ~OMAP_TIMER_CTRL_CE;
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
-
-void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
-			   int toggle, int trigger)
-{
-	u32 l;
-
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
-	l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
-	       OMAP_TIMER_CTRL_PT | (0x03 << 10));
-	if (def_on)
-		l |= OMAP_TIMER_CTRL_SCPWM;
-	if (toggle)
-		l |= OMAP_TIMER_CTRL_PT;
-	l |= trigger << 10;
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
-
-void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int 
prescaler)
-{
-	u32 l;
-
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
-	l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
-	if (prescaler >= 0x00 && prescaler <= 0x07) {
-		l |= OMAP_TIMER_CTRL_PRE;
-		l |= prescaler << 2;
-	}
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
-
-void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
-				  unsigned int value)
-{
-	__omap_dm_timer_int_enable(timer->io_base, value, timer->posted,
-			timer->intr_offset, timer->func_offset);
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
-
-unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
-{
-	unsigned int l;
-
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
-
-	return l;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
-
-void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned 
int value)
-{
-	__omap_dm_timer_write_status(timer->io_base, value, timer->posted,
-				timer->intr_offset, timer->func_offset);
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
-
-unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
-{
-	return __omap_dm_timer_read_counter(timer->io_base, timer->posted,
-						timer->func_offset);
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
-
-void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned 
int value)
-{
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
-
-int omap_dm_timers_active(void)
-{
-	struct omap_dm_timer *timer;
-
-	list_for_each_entry(timer, &omap_timer_list, node) {
-		if (!timer->enabled)
-			continue;
-
-		if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
-		    OMAP_TIMER_CTRL_ST) {
-			return 1;
-		}
-	}
-	return 0;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timers_active);
-
-/**
- * omap_dm_timer_probe - probe function called for every registered device
- * @pdev:	pointer to current timer platform device
- *
- * Called by driver framework at the end of device registration for all
- * timer devices.
- */
-static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
-{
-	int ret;
-	struct omap_dm_timer *timer;
-	struct resource *mem, *irq, *ioarea;
-	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
-		return -ENODEV;
-	}
-
-	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (unlikely(!irq)) {
-		dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
-		ret = -ENODEV;
-		goto err_free_pdev;
-	}
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (unlikely(!mem)) {
-		dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
-		ret = -ENODEV;
-		goto err_free_pdev;
-	}
-
-	ioarea = request_mem_region(mem->start, resource_size(mem),
-			pdev->name);
-	if (!ioarea) {
-		dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
-		ret = -EBUSY;
-		goto err_free_pdev;
-	}
-
-	timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
-	if (!timer) {
-		dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
-			__func__);
-		ret = -ENOMEM;
-		goto err_release_ioregion;
-	}
-
-	timer->io_base = ioremap(mem->start, resource_size(mem));
-	if (!timer->io_base) {
-		dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
-		ret = -ENOMEM;
-		goto err_free_mem;
-	}
-
-	if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_2) {
-		timer->func_offset = VERSION2_TIMER_WAKEUP_EN_REG_OFFSET;
-		timer->intr_offset = VERSION2_TIMER_STAT_REG_OFFSET;
-	} else {
-		timer->func_offset = 0;
-		timer->intr_offset = 0;
-	}
-
-	timer->id = pdev->id;
-	timer->irq = irq->start;
-	timer->pdev = pdev;
-#if defined(CONFIG_ARCH_OMAP2PLUS)
-	/* Mark clocksource and clockevent timers as reserved */
-	if ((sys_timer_reserved >> (pdev->id - 1)) & 0x1)
-		timer->reserved = 1;
-	else
-#endif
-		timer->reserved = 0;
-
-	 /* Skip pm_runtime_enable for OMAP1 */
-	if (!pdata->needs_manual_reset)
-		pm_runtime_enable(&pdev->dev);
-
-	/* add the timer element to the list */
-	mutex_lock(&dm_timer_mutex);
-	list_add_tail(&timer->node, &omap_timer_list);
-	mutex_unlock(&dm_timer_mutex);
-
-	dev_dbg(&pdev->dev, "Device Probed.\n");
-
-	return 0;
-
-err_free_mem:
-	kfree(timer);
-
-err_release_ioregion:
-	release_mem_region(mem->start, resource_size(mem));
-
-err_free_pdev:
-	kfree(pdata);
-	platform_device_unregister(pdev);
-
-	return ret;
-}
-
-/**
- * omap_dm_timer_remove - cleanup a registered timer device
- * @pdev:	pointer to current timer platform device
- *
- * Called by driver framework whenever a timer device is unregistered.
- * In addition to freeing platform resources it also deletes the timer
- * entry from the local list.
- */
-static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
-{
-	struct omap_dm_timer *timer, *tmp;
-	int ret = -EINVAL;
-
-	mutex_lock(&dm_timer_mutex);
-	list_for_each_entry_safe(timer, tmp, &omap_timer_list, node) {
-		if (timer->pdev->id == pdev->id) {
-			kfree(timer->pdev->dev.platform_data);
-			platform_device_del(timer->pdev);
-			list_del(&timer->node);
-			kfree(timer);
-			ret = 0;
-			break;
-		}
-	}
-	mutex_unlock(&dm_timer_mutex);
-
-	return ret;
-}
-
-static struct platform_driver omap_dm_timer_driver = {
-	.probe  = omap_dm_timer_probe,
-	.remove = omap_dm_timer_remove,
-	.driver = {
-		.name   = "omap_timer",
-	},
-};
-
-static int __init omap_dm_timer_driver_init(void)
-{
-	return platform_driver_register(&omap_dm_timer_driver);
-}
-
-static void __exit omap_dm_timer_driver_exit(void)
-{
-	platform_driver_unregister(&omap_dm_timer_driver);
-}
-
-early_platform_init("earlytimer", &omap_dm_timer_driver);
-module_init(omap_dm_timer_driver_init);
-module_exit(omap_dm_timer_driver_exit);
-
-MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRIVER_NAME);
-MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h 
b/arch/arm/plat-omap/include/plat/dmtimer.h
deleted file mode 100644
index 9093b65..0000000
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * arch/arm/plat-omap/include/plat/dmtimer.h
- *
- * OMAP Dual-Mode Timers
- *
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
- * Tarun Kanti DebBarma <tarun.kanti@ti.com>
- * Thara Gopinath <thara@ti.com>
- *
- * Platform device conversion and hwmod support.
- *
- * Copyright (C) 2005 Nokia Corporation
- * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
- * PWM and clock framwork support by Timo Teras.
- *
- * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ASM_ARCH_DMTIMER_H
-#define __ASM_ARCH_DMTIMER_H
-
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <plat/common.h>
-
-/* clock sources */
-#define OMAP_TIMER_SRC_SYS_CLK			0x00
-#define OMAP_TIMER_SRC_32_KHZ			0x01
-#define OMAP_TIMER_SRC_EXT_CLK			0x02
-
-/* timer interrupt enable bits */
-#define OMAP_TIMER_INT_CAPTURE			(1 << 2)
-#define OMAP_TIMER_INT_OVERFLOW			(1 << 1)
-#define OMAP_TIMER_INT_MATCH			(1 << 0)
-
-/* trigger types */
-#define OMAP_TIMER_TRIGGER_NONE			0x00
-#define OMAP_TIMER_TRIGGER_OVERFLOW		0x01
-#define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE	0x02
-
-/*
- * IP revision identifier so that Highlander IP
- * in OMAP4 can be distinguished.
- */
-#define OMAP_TIMER_IP_VERSION_1			0x1
-#define OMAP_TIMER_IP_VERSION_2			0x2
-
-/*
- * OMAP4 IP revision has different register offsets
- * for interrupt registers and functional registers.
- */
-#define VERSION2_TIMER_WAKEUP_EN_REG_OFFSET     0x14
-#define VERSION2_TIMER_STAT_REG_OFFSET          0x10
-
-/* timer capabilities used in hwmod database */
-#define OMAP_TIMER_SECURE				0x80000000
-#define OMAP_TIMER_ALWON				0x40000000
-#define OMAP_TIMER_HAS_PWM				0x20000000
-
-struct omap_timer_capability_dev_attr {
-	u32 timer_capability;
-};
-
-extern struct omap_dm_timer *gptimer_wakeup;
-
-struct dmtimer_platform_data {
-	int (*set_timer_src)(struct platform_device *pdev, int source);
-	int timer_ip_type;
-	u32 needs_manual_reset:1;
-};
-
-struct omap_dm_timer *omap_dm_timer_request(void);
-struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
-void omap_dm_timer_free(struct omap_dm_timer *timer);
-void omap_dm_timer_enable(struct omap_dm_timer *timer);
-void omap_dm_timer_disable(struct omap_dm_timer *timer);
-
-int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
-
-u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
-struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer);
-
-void omap_dm_timer_trigger(struct omap_dm_timer *timer);
-void omap_dm_timer_start(struct omap_dm_timer *timer);
-void omap_dm_timer_stop(struct omap_dm_timer *timer);
-
-int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
-void omap_dm_timer_set_load(struct omap_dm_timer *timer, int 
autoreload, unsigned int value);
-void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int 
autoreload, unsigned int value);
-void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, 
unsigned int match);
-void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int 
toggle, int trigger);
-void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int 
prescaler);
-
-void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned 
int value);
-
-unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
-void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned 
int value);
-unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
-void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned 
int value);
-
-int omap_dm_timers_active(void);
-
-/*
- * Do not use the defines below, they are not needed. They should be only
- * used by dmtimer.c and sys_timer related code.
- */
-
-/* register offsets */
-#define _OMAP_TIMER_ID_OFFSET		0x00
-#define _OMAP_TIMER_OCP_CFG_OFFSET	0x10
-#define _OMAP_TIMER_SYS_STAT_OFFSET	0x14
-#define _OMAP_TIMER_STAT_OFFSET		0x18
-#define _OMAP_TIMER_INT_EN_OFFSET	0x1c
-#define _OMAP_TIMER_WAKEUP_EN_OFFSET	0x20
-#define _OMAP_TIMER_CTRL_OFFSET		0x24
-#define		OMAP_TIMER_CTRL_GPOCFG		(1 << 14)
-#define		OMAP_TIMER_CTRL_CAPTMODE	(1 << 13)
-#define		OMAP_TIMER_CTRL_PT		(1 << 12)
-#define		OMAP_TIMER_CTRL_TCM_LOWTOHIGH	(0x1 << 8)
-#define		OMAP_TIMER_CTRL_TCM_HIGHTOLOW	(0x2 << 8)
-#define		OMAP_TIMER_CTRL_TCM_BOTHEDGES	(0x3 << 8)
-#define		OMAP_TIMER_CTRL_SCPWM		(1 << 7)
-#define		OMAP_TIMER_CTRL_CE		(1 << 6) /* compare enable */
-#define		OMAP_TIMER_CTRL_PRE		(1 << 5) /* prescaler enable */
-#define		OMAP_TIMER_CTRL_PTV_SHIFT	2 /* prescaler value shift */
-#define		OMAP_TIMER_CTRL_POSTED		(1 << 2)
-#define		OMAP_TIMER_CTRL_AR		(1 << 1) /* auto-reload enable */
-#define		OMAP_TIMER_CTRL_ST		(1 << 0) /* start timer */
-#define _OMAP_TIMER_COUNTER_OFFSET	0x28
-#define _OMAP_TIMER_LOAD_OFFSET		0x2c
-#define _OMAP_TIMER_TRIGGER_OFFSET	0x30
-#define _OMAP_TIMER_WRITE_PEND_OFFSET	0x34
-#define		WP_NONE			0	/* no write pending bit */
-#define		WP_TCLR			(1 << 0)
-#define		WP_TCRR			(1 << 1)
-#define		WP_TLDR			(1 << 2)
-#define		WP_TTGR			(1 << 3)
-#define		WP_TMAR			(1 << 4)
-#define		WP_TPIR			(1 << 5)
-#define		WP_TNIR			(1 << 6)
-#define		WP_TCVR			(1 << 7)
-#define		WP_TOCR			(1 << 8)
-#define		WP_TOWR			(1 << 9)
-#define _OMAP_TIMER_MATCH_OFFSET	0x38
-#define _OMAP_TIMER_CAPTURE_OFFSET	0x3c
-#define _OMAP_TIMER_IF_CTRL_OFFSET	0x40
-#define _OMAP_TIMER_CAPTURE2_OFFSET		0x44	/* TCAR2, 34xx only */
-#define _OMAP_TIMER_TICK_POS_OFFSET		0x48	/* TPIR, 34xx only */
-#define _OMAP_TIMER_TICK_NEG_OFFSET		0x4c	/* TNIR, 34xx only */
-#define _OMAP_TIMER_TICK_COUNT_OFFSET		0x50	/* TCVR, 34xx only */
-#define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET	0x54	/* TOCR, 34xx only */
-#define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET	0x58	/* TOWR, 34xx only */
-
-/* register offsets with the write pending bit encoded */
-#define	WPSHIFT					16
-
-#define OMAP_TIMER_ID_REG			(_OMAP_TIMER_ID_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_OCP_CFG_REG			(_OMAP_TIMER_OCP_CFG_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_SYS_STAT_REG			(_OMAP_TIMER_SYS_STAT_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_STAT_REG			(_OMAP_TIMER_STAT_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_INT_EN_REG			(_OMAP_TIMER_INT_EN_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_WAKEUP_EN_REG		(_OMAP_TIMER_WAKEUP_EN_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_CTRL_REG			(_OMAP_TIMER_CTRL_OFFSET \
-							| (WP_TCLR << WPSHIFT))
-
-#define OMAP_TIMER_COUNTER_REG			(_OMAP_TIMER_COUNTER_OFFSET \
-							| (WP_TCRR << WPSHIFT))
-
-#define OMAP_TIMER_LOAD_REG			(_OMAP_TIMER_LOAD_OFFSET \
-							| (WP_TLDR << WPSHIFT))
-
-#define OMAP_TIMER_TRIGGER_REG			(_OMAP_TIMER_TRIGGER_OFFSET \
-							| (WP_TTGR << WPSHIFT))
-
-#define OMAP_TIMER_WRITE_PEND_REG		(_OMAP_TIMER_WRITE_PEND_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_MATCH_REG			(_OMAP_TIMER_MATCH_OFFSET \
-							| (WP_TMAR << WPSHIFT))
-
-#define OMAP_TIMER_CAPTURE_REG			(_OMAP_TIMER_CAPTURE_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_IF_CTRL_REG			(_OMAP_TIMER_IF_CTRL_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_CAPTURE2_REG			(_OMAP_TIMER_CAPTURE2_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_TICK_POS_REG			(_OMAP_TIMER_TICK_POS_OFFSET \
-							| (WP_TPIR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_NEG_REG			(_OMAP_TIMER_TICK_NEG_OFFSET \
-							| (WP_TNIR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_COUNT_REG		(_OMAP_TIMER_TICK_COUNT_OFFSET \
-							| (WP_TCVR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_INT_MASK_SET_REG				\
-		(_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG				\
-		(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
-
-#define MAX_WRITE_PEND_WAIT            10000 /* 10ms timeout delay */
-
-struct omap_dm_timer {
-	unsigned long phys_base;
-	int id;
-	int irq;
-	struct clk *iclk, *fclk;
-	void __iomem *io_base;
-	unsigned long rate;
-	unsigned reserved:1;
-	unsigned enabled:1;
-	unsigned posted:1;
-	u8 func_offset;
-	u8 intr_offset;
-	struct platform_device *pdev;
-	struct list_head node;
-};
-
-extern u32 sys_timer_reserved;
-void __omap_dm_timer_reset(struct omap_dm_timer *timer, int autoidle,
-				int wakeup);
-
-static inline u32
-__omap_dm_timer_read(void __iomem *base, u32 reg, int posted, u8 
func_offset)
-{
-	int i = 0;
-
-	if (posted) {
-		omap_test_timeout(!(__raw_readl(base +
-			((OMAP_TIMER_WRITE_PEND_REG + func_offset) & 0xff)) &
-			(reg >> WPSHIFT)), MAX_WRITE_PEND_WAIT, i);
-
-		if (WARN_ON_ONCE(i == MAX_WRITE_PEND_WAIT))
-			pr_err("read timeout.\n");
-	}
-
-	return __raw_readl(base + (reg & 0xff));
-}
-
-static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, 
u32 val,
-						int posted, u8 func_offset)
-{
-	int i = 0;
-
-	if (posted) {
-		omap_test_timeout(!(__raw_readl(base +
-			((OMAP_TIMER_WRITE_PEND_REG + func_offset) & 0xff)) &
-			(reg >> WPSHIFT)), MAX_WRITE_PEND_WAIT, i);
-
-		if (WARN_ON(i == MAX_WRITE_PEND_WAIT))
-			pr_err("write timeout.\n");
-	}
-
-	__raw_writel(val, base + (reg & 0xff));
-}
-
-static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl,
-			unsigned int load, int posted, u8 func_offset)
-{
-	__omap_dm_timer_write(base, OMAP_TIMER_COUNTER_REG + func_offset,
-				load, posted, func_offset);
-	__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG + func_offset,
-				ctrl, posted, func_offset);
-}
-
-static inline void __omap_dm_timer_int_enable(void __iomem *base,
-		unsigned int value, int posted, u8 intr_offset, u8 func_offset)
-{
-	__omap_dm_timer_write(base, OMAP_TIMER_INT_EN_REG + intr_offset,
-				value, posted, func_offset);
-	__omap_dm_timer_write(base, OMAP_TIMER_WAKEUP_EN_REG + func_offset,
-				value, posted, func_offset);
-}
-
-static inline unsigned int
-__omap_dm_timer_read_counter(void __iomem *base, int posted, u8 
func_offset)
-{
-	return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG + func_offset,
-					posted,	func_offset);
-}
-
-static inline void __omap_dm_timer_write_status(void __iomem *base,
-		unsigned int value, int posted, u8 intr_offset, u8 func_offset)
-{
-	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG + intr_offset,
-				value, posted, func_offset);
-}
-
-static inline void
-__omap_dm_timer_set_posted(void __iomem *base, u8 func_offset)
-{
-	__omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG + func_offset,
-				OMAP_TIMER_CTRL_POSTED, 0, func_offset);
-}
-
-static inline void __omap_dm_timer_stop(void __iomem *base, unsigned 
long rate,
-			int posted, bool omap2, u8 intr_offset, u8 func_offset)
-{
-	u32 l;
-
-	l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG + func_offset,
-					posted, func_offset);
-	if (l & OMAP_TIMER_CTRL_ST) {
-		l &= ~0x1;
-		__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG + func_offset,
-					l, posted, func_offset);
-		if (omap2) {
-			/* Readback to make sure write has completed */
-			__omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG +
-					func_offset, posted, func_offset);
-			udelay(3500000 / rate);
-		}
-	}
-	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG + intr_offset,
-				OMAP_TIMER_INT_OVERFLOW, posted, func_offset);
-}
-#endif /* __ASM_ARCH_DMTIMER_H */
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f546860..c95496d 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -44,3 +44,4 @@ obj-$(CONFIG_PCH_PHUB)		+= pch_phub.o
  obj-y				+= ti-st/
  obj-$(CONFIG_AB8500_PWM)	+= ab8500-pwm.o
  obj-y				+= lis3lv02d/
+obj-$(CONFIG_OMAP_DM_TIMER)	+= timer-omap.o
diff --git a/drivers/misc/timer-omap.c b/drivers/misc/timer-omap.c
new file mode 100644
index 0000000..22e4352
--- /dev/null
+++ b/drivers/misc/timer-omap.c
@@ -0,0 +1,642 @@
+/*
+ * linux/arch/arm/plat-omap/dmtimer.c
+ *
+ * OMAP Dual-Mode Timers
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * dmtimer adaptation to platform_driver.
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * OMAP2 support by Juha Yrjola
+ * API improvements and OMAP2 clock framework support by Timo Teras
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/err.h>
+#include <linux/timer-omap.h>
+
+static LIST_HEAD(omap_timer_list);
+static DEFINE_MUTEX(dm_timer_mutex);
+
+/**
+ * omap_dm_timer_read_reg - read timer registers in posted and 
non-posted mode
+ * @timer:      timer pointer over which read operation to perform
+ * @reg:        lowest byte holds the register offset
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode write
+ * pending bit must be checked. Otherwise a read of a non completed write
+ * will produce an error.
+ */
+static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, 
u32 reg)
+{
+	if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
+		reg += timer->func_offset;
+	else if (reg >= OMAP_TIMER_STAT_REG)
+		reg += timer->intr_offset;
+
+	return __omap_dm_timer_read(timer->io_base, reg, timer->posted,
+					timer->func_offset);
+}
+
+/**
+ * omap_dm_timer_write_reg - write timer registers in posted and 
non-posted mode
+ * @timer:      timer pointer over which write operation is to perform
+ * @reg:        lowest byte holds the register offset
+ * @value:      data to write into the register
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode the 
write
+ * pending bit must be checked. Otherwise a write on a register which has a
+ * pending write will be lost.
+ */
+static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
+						u32 value)
+{
+	if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
+		reg += timer->func_offset;
+	else if (reg >= OMAP_TIMER_STAT_REG)
+		reg += timer->intr_offset;
+
+	__omap_dm_timer_write(timer->io_base, reg, value, timer->posted,
+				timer->func_offset);
+}
+
+static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
+{
+	int c;
+
+	c = 0;
+	while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
+		c++;
+		if (c > 100000) {
+			printk(KERN_ERR "Timer failed to reset\n");
+			return;
+		}
+	}
+}
+
+/* Assumes the source clock has been set by caller */
+void __omap_dm_timer_reset(struct omap_dm_timer *timer, int autoidle,
+				int wakeup)
+{
+	u32 l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
+	l |= 0x02 << 3;  /* Set to smart-idle mode */
+	l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
+
+	if (autoidle)
+		l |= 0x1 << 0;
+
+	if (wakeup)
+		l |= 1 << 2;
+
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
+}
+
+static void omap_dm_timer_reset(struct omap_dm_timer *timer)
+{
+	int autoidle = 0, wakeup = 0;
+
+	if (timer->pdev->id != 1) {
+		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
+		omap_dm_timer_wait_for_reset(timer);
+	}
+	__omap_dm_timer_reset(timer, autoidle, wakeup);
+}
+
+void omap_dm_timer_prepare(struct omap_dm_timer *timer)
+{
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
+	timer->fclk = clk_get(&timer->pdev->dev, "fck");
+	if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
+		timer->fclk = NULL;
+		dev_err(&timer->pdev->dev, ": No fclk handle.\n");
+		return;
+	}
+
+	omap_dm_timer_enable(timer);
+
+	if (pdata->needs_manual_reset)
+		omap_dm_timer_reset(timer);
+
+	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
+
+	__omap_dm_timer_set_posted(timer->io_base, timer->func_offset);
+	timer->posted = 1;
+}
+
+struct omap_dm_timer *omap_dm_timer_request(void)
+{
+	struct omap_dm_timer *timer = NULL, *t;
+
+	mutex_lock(&dm_timer_mutex);
+	list_for_each_entry(t, &omap_timer_list, node) {
+		if (t->reserved)
+			continue;
+
+		timer = t;
+		timer->reserved = 1;
+		break;
+	}
+	mutex_unlock(&dm_timer_mutex);
+
+	if (timer)
+		omap_dm_timer_prepare(timer);
+	else
+		pr_debug("%s: free timer not available.\n", __func__);
+
+	return timer;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_request);
+
+struct omap_dm_timer *omap_dm_timer_request_specific(int id)
+{
+	struct omap_dm_timer *timer = NULL, *t;
+
+	mutex_lock(&dm_timer_mutex);
+	list_for_each_entry(t, &omap_timer_list, node) {
+		if (t->pdev->id == id && !t->reserved) {
+			timer = t;
+			timer->reserved = 1;
+			break;
+		}
+	}
+	mutex_unlock(&dm_timer_mutex);
+
+	if (timer)
+		omap_dm_timer_prepare(timer);
+	else
+		pr_debug("%s: timer%d not available.\n", __func__, id);
+
+	return timer;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
+
+void omap_dm_timer_free(struct omap_dm_timer *timer)
+{
+	omap_dm_timer_disable(timer);
+
+	clk_put(timer->fclk);
+
+	WARN_ON(!timer->reserved);
+	timer->reserved = 0;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_free);
+
+void omap_dm_timer_enable(struct omap_dm_timer *timer)
+{
+	if (timer->enabled)
+		return;
+
+	pm_runtime_get_sync(&timer->pdev->dev);
+
+	timer->enabled = 1;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
+
+void omap_dm_timer_disable(struct omap_dm_timer *timer)
+{
+	if (!timer->enabled)
+		return;
+
+	pm_runtime_put_sync(&timer->pdev->dev);
+
+	timer->enabled = 0;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
+
+int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
+{
+	return timer->irq;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
+
+#if defined(CONFIG_ARCH_OMAP1)
+
+/**
+ * omap_dm_timer_modify_idlect_mask - Check if any running timers use 
ARMXOR
+ * @inputmask: current value of idlect mask
+ */
+__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
+{
+	int i = 0;
+	struct omap_dm_timer *timer = NULL;
+
+	/* If ARMXOR cannot be idled this function call is unnecessary */
+	if (!(inputmask & (1 << 1)))
+		return inputmask;
+
+	/* If any active timer is using ARMXOR return modified mask */
+	mutex_lock(&dm_timer_mutex);
+	list_for_each_entry(timer, &omap_timer_list, node) {
+
+		u32 l;
+
+		l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+		if (l & OMAP_TIMER_CTRL_ST) {
+			if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
+				inputmask &= ~(1 << 1);
+			else
+				inputmask &= ~(1 << 2);
+		}
+		i++;
+	}
+	mutex_unlock(&dm_timer_mutex);
+
+	return inputmask;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
+
+#else
+
+struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
+{
+	return timer->fclk;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
+
+__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
+{
+	BUG();
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
+
+#endif
+
+void omap_dm_timer_trigger(struct omap_dm_timer *timer)
+{
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
+
+void omap_dm_timer_start(struct omap_dm_timer *timer)
+{
+	u32 l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	if (!(l & OMAP_TIMER_CTRL_ST)) {
+		l |= OMAP_TIMER_CTRL_ST;
+		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+	}
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_start);
+
+void omap_dm_timer_stop(struct omap_dm_timer *timer)
+{
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+	bool omap2 = true;
+	unsigned long rate = clk_get_rate(timer->fclk) + 1;
+
+	if (unlikely(pdata->needs_manual_reset))
+		omap2 = false;
+
+	__omap_dm_timer_stop(timer->io_base, rate, timer->posted, omap2,
+			timer->intr_offset, timer->func_offset);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
+
+int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
+{
+	int ret = -EINVAL;
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
+	if (source < 0 || source >= 3)
+		return -EINVAL;
+
+	omap_dm_timer_disable(timer);
+	/* change the timer clock source */
+	ret = pdata->set_timer_src(timer->pdev, source);
+	omap_dm_timer_enable(timer);
+
+	/*
+	 * When the functional clock disappears, too quick writes seem
+	 * to cause an abort. XXX Is this still necessary?
+	 */
+	__delay(300000);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
+
+void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
+			    unsigned int load)
+{
+	u32 l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	if (autoreload)
+		l |= OMAP_TIMER_CTRL_AR;
+	else
+		l &= ~OMAP_TIMER_CTRL_AR;
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
+
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
+
+/* Optimized set_load which removes costly spin wait in timer_start */
+void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int 
autoreload,
+				unsigned int load)
+{
+	u32 l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	if (autoreload) {
+		l |= OMAP_TIMER_CTRL_AR;
+		omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
+	} else {
+		l &= ~OMAP_TIMER_CTRL_AR;
+	}
+	l |= OMAP_TIMER_CTRL_ST;
+
+	__omap_dm_timer_load_start(timer->io_base, l, load, timer->posted,
+					timer->func_offset);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
+
+void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
+			     unsigned int match)
+{
+	u32 l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	if (enable)
+		l |= OMAP_TIMER_CTRL_CE;
+	else
+		l &= ~OMAP_TIMER_CTRL_CE;
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
+
+void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
+			   int toggle, int trigger)
+{
+	u32 l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
+	       OMAP_TIMER_CTRL_PT | (0x03 << 10));
+	if (def_on)
+		l |= OMAP_TIMER_CTRL_SCPWM;
+	if (toggle)
+		l |= OMAP_TIMER_CTRL_PT;
+	l |= trigger << 10;
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
+
+void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int 
prescaler)
+{
+	u32 l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
+	if (prescaler >= 0x00 && prescaler <= 0x07) {
+		l |= OMAP_TIMER_CTRL_PRE;
+		l |= prescaler << 2;
+	}
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
+
+void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
+				  unsigned int value)
+{
+	__omap_dm_timer_int_enable(timer->io_base, value, timer->posted,
+			timer->intr_offset, timer->func_offset);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
+
+unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
+{
+	unsigned int l;
+
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+
+	return l;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
+
+void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned 
int value)
+{
+	__omap_dm_timer_write_status(timer->io_base, value, timer->posted,
+				timer->intr_offset, timer->func_offset);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
+
+unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
+{
+	return __omap_dm_timer_read_counter(timer->io_base, timer->posted,
+						timer->func_offset);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
+
+void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned 
int value)
+{
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
+}
+EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
+
+int omap_dm_timers_active(void)
+{
+	struct omap_dm_timer *timer;
+
+	list_for_each_entry(timer, &omap_timer_list, node) {
+		if (!timer->enabled)
+			continue;
+
+		if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
+		    OMAP_TIMER_CTRL_ST) {
+			return 1;
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(omap_dm_timers_active);
+
+/**
+ * omap_dm_timer_probe - probe function called for every registered device
+ * @pdev:	pointer to current timer platform device
+ *
+ * Called by driver framework at the end of device registration for all
+ * timer devices.
+ */
+static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct omap_dm_timer *timer;
+	struct resource *mem, *irq, *ioarea;
+	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
+		return -ENODEV;
+	}
+
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (unlikely(!irq)) {
+		dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
+		ret = -ENODEV;
+		goto err_free_pdev;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(!mem)) {
+		dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
+		ret = -ENODEV;
+		goto err_free_pdev;
+	}
+
+	ioarea = request_mem_region(mem->start, resource_size(mem),
+			pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
+		ret = -EBUSY;
+		goto err_free_pdev;
+	}
+
+	timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
+	if (!timer) {
+		dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_release_ioregion;
+	}
+
+	timer->io_base = ioremap(mem->start, resource_size(mem));
+	if (!timer->io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
+		ret = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_2) {
+		timer->func_offset = VERSION2_TIMER_WAKEUP_EN_REG_OFFSET;
+		timer->intr_offset = VERSION2_TIMER_STAT_REG_OFFSET;
+	} else {
+		timer->func_offset = 0;
+		timer->intr_offset = 0;
+	}
+
+	timer->id = pdev->id;
+	timer->irq = irq->start;
+	timer->pdev = pdev;
+#if defined(CONFIG_ARCH_OMAP2PLUS)
+	/* Mark clocksource and clockevent timers as reserved */
+	if ((sys_timer_reserved >> (pdev->id - 1)) & 0x1)
+		timer->reserved = 1;
+	else
+#endif
+		timer->reserved = 0;
+
+	 /* Skip pm_runtime_enable for OMAP1 */
+	if (!pdata->needs_manual_reset)
+		pm_runtime_enable(&pdev->dev);
+
+	/* add the timer element to the list */
+	mutex_lock(&dm_timer_mutex);
+	list_add_tail(&timer->node, &omap_timer_list);
+	mutex_unlock(&dm_timer_mutex);
+
+	dev_dbg(&pdev->dev, "Device Probed.\n");
+
+	return 0;
+
+err_free_mem:
+	kfree(timer);
+
+err_release_ioregion:
+	release_mem_region(mem->start, resource_size(mem));
+
+err_free_pdev:
+	kfree(pdata);
+	platform_device_unregister(pdev);
+
+	return ret;
+}
+
+/**
+ * omap_dm_timer_remove - cleanup a registered timer device
+ * @pdev:	pointer to current timer platform device
+ *
+ * Called by driver framework whenever a timer device is unregistered.
+ * In addition to freeing platform resources it also deletes the timer
+ * entry from the local list.
+ */
+static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
+{
+	struct omap_dm_timer *timer, *tmp;
+	int ret = -EINVAL;
+
+	mutex_lock(&dm_timer_mutex);
+	list_for_each_entry_safe(timer, tmp, &omap_timer_list, node) {
+		if (timer->pdev->id == pdev->id) {
+			kfree(timer->pdev->dev.platform_data);
+			platform_device_del(timer->pdev);
+			list_del(&timer->node);
+			kfree(timer);
+			ret = 0;
+			break;
+		}
+	}
+	mutex_unlock(&dm_timer_mutex);
+
+	return ret;
+}
+
+static struct platform_driver omap_dm_timer_driver = {
+	.probe  = omap_dm_timer_probe,
+	.remove = omap_dm_timer_remove,
+	.driver = {
+		.name   = "omap_timer",
+	},
+};
+
+static int __init omap_dm_timer_driver_init(void)
+{
+	return platform_driver_register(&omap_dm_timer_driver);
+}
+
+static void __exit omap_dm_timer_driver_exit(void)
+{
+	platform_driver_unregister(&omap_dm_timer_driver);
+}
+
+early_platform_init("earlytimer", &omap_dm_timer_driver);
+module_init(omap_dm_timer_driver_init);
+module_exit(omap_dm_timer_driver_exit);
+
+MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/drivers/tty/serial/omap-serial.c 
b/drivers/tty/serial/omap-serial.c
index 7635379..a8178eb 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -37,9 +37,9 @@
  #include <linux/clk.h>
  #include <linux/serial_core.h>
  #include <linux/irq.h>
+#include <linux/timer-omap.h>

  #include <plat/dma.h>
-#include <plat/dmtimer.h>
  #include <plat/omap-serial.h>

  static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
diff --git a/include/linux/timer-omap.h b/include/linux/timer-omap.h
new file mode 100644
index 0000000..f72a975
--- /dev/null
+++ b/include/linux/timer-omap.h
@@ -0,0 +1,351 @@
+/*
+ * arch/arm/plat-omap/include/plat/dmtimer.h
+ *
+ * OMAP Dual-Mode Timers
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Platform device conversion and hwmod support.
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
+ * PWM and clock framwork support by Timo Teras.
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_ARCH_DMTIMER_H
+#define __ASM_ARCH_DMTIMER_H
+
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+
+/* clock sources */
+#define OMAP_TIMER_SRC_SYS_CLK			0x00
+#define OMAP_TIMER_SRC_32_KHZ			0x01
+#define OMAP_TIMER_SRC_EXT_CLK			0x02
+
+/* timer interrupt enable bits */
+#define OMAP_TIMER_INT_CAPTURE			(1 << 2)
+#define OMAP_TIMER_INT_OVERFLOW			(1 << 1)
+#define OMAP_TIMER_INT_MATCH			(1 << 0)
+
+/* trigger types */
+#define OMAP_TIMER_TRIGGER_NONE			0x00
+#define OMAP_TIMER_TRIGGER_OVERFLOW		0x01
+#define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE	0x02
+
+/*
+ * IP revision identifier so that Highlander IP
+ * in OMAP4 can be distinguished.
+ */
+#define OMAP_TIMER_IP_VERSION_1			0x1
+#define OMAP_TIMER_IP_VERSION_2			0x2
+
+/*
+ * OMAP4 IP revision has different register offsets
+ * for interrupt registers and functional registers.
+ */
+#define VERSION2_TIMER_WAKEUP_EN_REG_OFFSET     0x14
+#define VERSION2_TIMER_STAT_REG_OFFSET          0x10
+
+/* timer capabilities used in hwmod database */
+#define OMAP_TIMER_SECURE				0x80000000
+#define OMAP_TIMER_ALWON				0x40000000
+#define OMAP_TIMER_HAS_PWM				0x20000000
+
+struct omap_timer_capability_dev_attr {
+	u32 timer_capability;
+};
+
+extern struct omap_dm_timer *gptimer_wakeup;
+
+struct dmtimer_platform_data {
+	int (*set_timer_src)(struct platform_device *pdev, int source);
+	int timer_ip_type;
+	u32 needs_manual_reset:1;
+};
+
+struct omap_dm_timer *omap_dm_timer_request(void);
+struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
+void omap_dm_timer_free(struct omap_dm_timer *timer);
+void omap_dm_timer_enable(struct omap_dm_timer *timer);
+void omap_dm_timer_disable(struct omap_dm_timer *timer);
+
+int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
+
+u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
+struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer);
+
+void omap_dm_timer_trigger(struct omap_dm_timer *timer);
+void omap_dm_timer_start(struct omap_dm_timer *timer);
+void omap_dm_timer_stop(struct omap_dm_timer *timer);
+
+int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
+void omap_dm_timer_set_load(struct omap_dm_timer *timer, int 
autoreload, unsigned int value);
+void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int 
autoreload, unsigned int value);
+void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, 
unsigned int match);
+void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int 
toggle, int trigger);
+void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int 
prescaler);
+
+void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned 
int value);
+
+unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
+void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned 
int value);
+unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
+void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned 
int value);
+
+int omap_dm_timers_active(void);
+
+/*
+ * Do not use the defines below, they are not needed. They should be only
+ * used by dmtimer.c and sys_timer related code.
+ */
+
+/* register offsets */
+#define _OMAP_TIMER_ID_OFFSET		0x00
+#define _OMAP_TIMER_OCP_CFG_OFFSET	0x10
+#define _OMAP_TIMER_SYS_STAT_OFFSET	0x14
+#define _OMAP_TIMER_STAT_OFFSET		0x18
+#define _OMAP_TIMER_INT_EN_OFFSET	0x1c
+#define _OMAP_TIMER_WAKEUP_EN_OFFSET	0x20
+#define _OMAP_TIMER_CTRL_OFFSET		0x24
+#define		OMAP_TIMER_CTRL_GPOCFG		(1 << 14)
+#define		OMAP_TIMER_CTRL_CAPTMODE	(1 << 13)
+#define		OMAP_TIMER_CTRL_PT		(1 << 12)
+#define		OMAP_TIMER_CTRL_TCM_LOWTOHIGH	(0x1 << 8)
+#define		OMAP_TIMER_CTRL_TCM_HIGHTOLOW	(0x2 << 8)
+#define		OMAP_TIMER_CTRL_TCM_BOTHEDGES	(0x3 << 8)
+#define		OMAP_TIMER_CTRL_SCPWM		(1 << 7)
+#define		OMAP_TIMER_CTRL_CE		(1 << 6) /* compare enable */
+#define		OMAP_TIMER_CTRL_PRE		(1 << 5) /* prescaler enable */
+#define		OMAP_TIMER_CTRL_PTV_SHIFT	2 /* prescaler value shift */
+#define		OMAP_TIMER_CTRL_POSTED		(1 << 2)
+#define		OMAP_TIMER_CTRL_AR		(1 << 1) /* auto-reload enable */
+#define		OMAP_TIMER_CTRL_ST		(1 << 0) /* start timer */
+#define _OMAP_TIMER_COUNTER_OFFSET	0x28
+#define _OMAP_TIMER_LOAD_OFFSET		0x2c
+#define _OMAP_TIMER_TRIGGER_OFFSET	0x30
+#define _OMAP_TIMER_WRITE_PEND_OFFSET	0x34
+#define		WP_NONE			0	/* no write pending bit */
+#define		WP_TCLR			(1 << 0)
+#define		WP_TCRR			(1 << 1)
+#define		WP_TLDR			(1 << 2)
+#define		WP_TTGR			(1 << 3)
+#define		WP_TMAR			(1 << 4)
+#define		WP_TPIR			(1 << 5)
+#define		WP_TNIR			(1 << 6)
+#define		WP_TCVR			(1 << 7)
+#define		WP_TOCR			(1 << 8)
+#define		WP_TOWR			(1 << 9)
+#define _OMAP_TIMER_MATCH_OFFSET	0x38
+#define _OMAP_TIMER_CAPTURE_OFFSET	0x3c
+#define _OMAP_TIMER_IF_CTRL_OFFSET	0x40
+#define _OMAP_TIMER_CAPTURE2_OFFSET		0x44	/* TCAR2, 34xx only */
+#define _OMAP_TIMER_TICK_POS_OFFSET		0x48	/* TPIR, 34xx only */
+#define _OMAP_TIMER_TICK_NEG_OFFSET		0x4c	/* TNIR, 34xx only */
+#define _OMAP_TIMER_TICK_COUNT_OFFSET		0x50	/* TCVR, 34xx only */
+#define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET	0x54	/* TOCR, 34xx only */
+#define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET	0x58	/* TOWR, 34xx only */
+
+/* register offsets with the write pending bit encoded */
+#define	WPSHIFT					16
+
+#define OMAP_TIMER_ID_REG			(_OMAP_TIMER_ID_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_OCP_CFG_REG			(_OMAP_TIMER_OCP_CFG_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_SYS_STAT_REG			(_OMAP_TIMER_SYS_STAT_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_STAT_REG			(_OMAP_TIMER_STAT_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_INT_EN_REG			(_OMAP_TIMER_INT_EN_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_WAKEUP_EN_REG		(_OMAP_TIMER_WAKEUP_EN_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_CTRL_REG			(_OMAP_TIMER_CTRL_OFFSET \
+							| (WP_TCLR << WPSHIFT))
+
+#define OMAP_TIMER_COUNTER_REG			(_OMAP_TIMER_COUNTER_OFFSET \
+							| (WP_TCRR << WPSHIFT))
+
+#define OMAP_TIMER_LOAD_REG			(_OMAP_TIMER_LOAD_OFFSET \
+							| (WP_TLDR << WPSHIFT))
+
+#define OMAP_TIMER_TRIGGER_REG			(_OMAP_TIMER_TRIGGER_OFFSET \
+							| (WP_TTGR << WPSHIFT))
+
+#define OMAP_TIMER_WRITE_PEND_REG		(_OMAP_TIMER_WRITE_PEND_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_MATCH_REG			(_OMAP_TIMER_MATCH_OFFSET \
+							| (WP_TMAR << WPSHIFT))
+
+#define OMAP_TIMER_CAPTURE_REG			(_OMAP_TIMER_CAPTURE_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_IF_CTRL_REG			(_OMAP_TIMER_IF_CTRL_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_CAPTURE2_REG			(_OMAP_TIMER_CAPTURE2_OFFSET \
+							| (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_TICK_POS_REG			(_OMAP_TIMER_TICK_POS_OFFSET \
+							| (WP_TPIR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_NEG_REG			(_OMAP_TIMER_TICK_NEG_OFFSET \
+							| (WP_TNIR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_COUNT_REG		(_OMAP_TIMER_TICK_COUNT_OFFSET \
+							| (WP_TCVR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_INT_MASK_SET_REG				\
+		(_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG				\
+		(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
+
+#define MAX_WRITE_PEND_WAIT            10000 /* 10ms timeout delay */
+
+struct omap_dm_timer {
+	unsigned long phys_base;
+	int id;
+	int irq;
+	struct clk *iclk, *fclk;
+	void __iomem *io_base;
+	unsigned long rate;
+	unsigned reserved:1;
+	unsigned enabled:1;
+	unsigned posted:1;
+	u8 func_offset;
+	u8 intr_offset;
+	struct platform_device *pdev;
+	struct list_head node;
+};
+
+extern u32 sys_timer_reserved;
+void __omap_dm_timer_reset(struct omap_dm_timer *timer, int autoidle,
+				int wakeup);
+
+static inline u32
+__omap_dm_timer_read(void __iomem *base, u32 reg, int posted, u8 
func_offset)
+{
+	int i = 0;
+
+	if (posted) {
+		omap_test_timeout(!(__raw_readl(base +
+			((OMAP_TIMER_WRITE_PEND_REG + func_offset) & 0xff)) &
+			(reg >> WPSHIFT)), MAX_WRITE_PEND_WAIT, i);
+
+		if (WARN_ON_ONCE(i == MAX_WRITE_PEND_WAIT))
+			pr_err("read timeout.\n");
+	}
+
+	return __raw_readl(base + (reg & 0xff));
+}
+
+static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, 
u32 val,
+						int posted, u8 func_offset)
+{
+	int i = 0;
+
+	if (posted) {
+		omap_test_timeout(!(__raw_readl(base +
+			((OMAP_TIMER_WRITE_PEND_REG + func_offset) & 0xff)) &
+			(reg >> WPSHIFT)), MAX_WRITE_PEND_WAIT, i);
+
+		if (WARN_ON(i == MAX_WRITE_PEND_WAIT))
+			pr_err("write timeout.\n");
+	}
+
+	__raw_writel(val, base + (reg & 0xff));
+}
+
+static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl,
+			unsigned int load, int posted, u8 func_offset)
+{
+	__omap_dm_timer_write(base, OMAP_TIMER_COUNTER_REG + func_offset,
+				load, posted, func_offset);
+	__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG + func_offset,
+				ctrl, posted, func_offset);
+}
+
+static inline void __omap_dm_timer_int_enable(void __iomem *base,
+		unsigned int value, int posted, u8 intr_offset, u8 func_offset)
+{
+	__omap_dm_timer_write(base, OMAP_TIMER_INT_EN_REG + intr_offset,
+				value, posted, func_offset);
+	__omap_dm_timer_write(base, OMAP_TIMER_WAKEUP_EN_REG + func_offset,
+				value, posted, func_offset);
+}
+
+static inline unsigned int
+__omap_dm_timer_read_counter(void __iomem *base, int posted, u8 
func_offset)
+{
+	return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG + func_offset,
+					posted,	func_offset);
+}
+
+static inline void __omap_dm_timer_write_status(void __iomem *base,
+		unsigned int value, int posted, u8 intr_offset, u8 func_offset)
+{
+	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG + intr_offset,
+				value, posted, func_offset);
+}
+
+static inline void
+__omap_dm_timer_set_posted(void __iomem *base, u8 func_offset)
+{
+	__omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG + func_offset,
+				OMAP_TIMER_CTRL_POSTED, 0, func_offset);
+}
+
+static inline void __omap_dm_timer_stop(void __iomem *base, unsigned 
long rate,
+			int posted, bool omap2, u8 intr_offset, u8 func_offset)
+{
+	u32 l;
+
+	l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG + func_offset,
+					posted, func_offset);
+	if (l & OMAP_TIMER_CTRL_ST) {
+		l &= ~0x1;
+		__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG + func_offset,
+					l, posted, func_offset);
+		if (omap2) {
+			/* Readback to make sure write has completed */
+			__omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG +
+					func_offset, posted, func_offset);
+			udelay(3500000 / rate);
+		}
+	}
+	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG + intr_offset,
+				OMAP_TIMER_INT_OVERFLOW, posted, func_offset);
+}
+#endif /* __ASM_ARCH_DMTIMER_H */
-- 
1.6.0.4




^ permalink raw reply related	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2011-04-29 11:06 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-16 15:50 [PATCH v13 00/11] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
2011-04-16 15:50 ` [PATCH v13 01/11] OMAP2+: dmtimer: add device names to flck nodes Tarun Kanti DebBarma
2011-04-16 15:50 ` [PATCH v13 02/11] OMAP4: hwmod data: add dmtimer version information Tarun Kanti DebBarma
2011-04-16 15:50 ` [PATCH v13 03/11] OMAP1: dmtimer: conversion to platform devices Tarun Kanti DebBarma
2011-04-16 15:50 ` [PATCH v13 04/11] OMAP2+: dmtimer: convert " Tarun Kanti DebBarma
2011-04-25  9:38   ` DebBarma, Tarun Kanti
2011-04-29 10:45   ` Santosh Shilimkar
2011-04-16 15:50 ` [PATCH v13 05/11] OMAP: dmtimer: platform driver Tarun Kanti DebBarma
2011-04-16 15:50 ` [PATCH v13 06/11] dmtimer: switch-over to platform device driver Tarun Kanti DebBarma
2011-04-16 15:50 ` [PATCH v13 07/11] OMAP: dmtimer: pm_runtime support Tarun Kanti DebBarma
2011-04-16 15:51 ` [PATCH v13 08/11] OMAP: dmtimer: add timeout to low-level routines Tarun Kanti DebBarma
2011-04-16 15:51 ` [PATCH v13 09/11] OMAP: dmtimer: use mutex instead of spinlock Tarun Kanti DebBarma
2011-04-16 15:51 ` [PATCH v13 10/11] OMAP: dmtimer: mark clocksource and clockevent timers reserved Tarun Kanti DebBarma
2011-04-17  6:12   ` Santosh Shilimkar
2011-04-18  5:50     ` DebBarma, Tarun Kanti
2011-04-25  9:41   ` DebBarma, Tarun Kanti
2011-04-29 10:40     ` Santosh Shilimkar
2011-04-16 15:51 ` [PATCH v13 11/11] OMAP: dmtimer: convert to a driver Tarun Kanti DebBarma
2011-04-29 10:51   ` Santosh Shilimkar
2011-04-29 11:05 ` [PATCH v13 00/11] dmtimer adaptation to platform_driver Santosh Shilimkar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox