linux-omap.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v11 0/8] dmtimer adaptation to platform_driver
@ 2011-02-24 11:26 Tarun Kanti DebBarma
  2011-02-24 11:26 ` [PATCH v11 1/8] OMAP2+: dmtimer: add device names to flck nodes Tarun Kanti DebBarma
                   ` (8 more replies)
  0 siblings, 9 replies; 44+ messages in thread
From: Tarun Kanti DebBarma @ 2011-02-24 11:26 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.

NOTE: 
This patch series should be applied on-top of Paul's following patch
series:
http://www.spinics.net/lists/linux-omap/msg46725.html

Baseline:
git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
Branch: omap-for-linus

Test Info:
Tested on OMAP3, OMAP4. Bootup test on OMAP1710.
OMAP3 power test: Retention and Off mode.
OMAP2 platforms not tested because of existing issue in the branch.

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 (5):
  OMAP4: hwmod data: add dmtimer version information
  OMAP2+: dmtimer: convert to platform devices
  dmtimer: switch-over to platform device driver
  OMAP: dmtimer: pm_runtime support
  OMAP: dmtimer: add timeout to low-level routines

Thara Gopinath (3):
  OMAP2+: dmtimer: add device names to flck nodes
  OMAP1: dmtimer: conversion to platform devices
  OMAP: dmtimer: platform driver

 arch/arm/mach-omap1/Makefile               |    2 +-
 arch/arm/mach-omap1/dmtimer.c              |  214 ++++++++++
 arch/arm/mach-omap1/timer32k.c             |    4 -
 arch/arm/mach-omap2/Makefile               |    2 +-
 arch/arm/mach-omap2/clock2420_data.c       |   60 +++-
 arch/arm/mach-omap2/clock2430_data.c       |   60 +++-
 arch/arm/mach-omap2/clock3xxx_data.c       |   48 ++-
 arch/arm/mach-omap2/clock44xx_data.c       |   44 ++-
 arch/arm/mach-omap2/dmtimer.c              |  260 ++++++++++++
 arch/arm/mach-omap2/dmtimer.h              |   30 ++
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    3 +
 arch/arm/mach-omap2/timer-gp.c             |    4 +-
 arch/arm/plat-omap/dmtimer.c               |  607 ++++++++++++++--------------
 arch/arm/plat-omap/include/plat/dmtimer.h  |   27 ++-
 14 files changed, 1011 insertions(+), 354 deletions(-)
 create mode 100644 arch/arm/mach-omap1/dmtimer.c
 create mode 100644 arch/arm/mach-omap2/dmtimer.c
 create mode 100644 arch/arm/mach-omap2/dmtimer.h


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

* [PATCH v11 1/8] OMAP2+: dmtimer: add device names to flck nodes
  2011-02-24 11:26 [PATCH v11 0/8] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
@ 2011-02-24 11:26 ` Tarun Kanti DebBarma
  2011-02-24 11:26 ` [PATCH v11 2/8] OMAP4: hwmod data: add dmtimer version information Tarun Kanti DebBarma
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Tarun Kanti DebBarma @ 2011-02-24 11:26 UTC (permalink / raw)
  To: linux-omap; +Cc: Thara Gopinath

From: Thara Gopinath <thara@ti.com>

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.

NOTE: gpt1_fck is modified in patch-10 when we switch to platform device
driver. This is to make sure that each patch compiles and boots.

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 |   58 +++++++++++++++++++++++++++------
 arch/arm/mach-omap2/clock2430_data.c |   58 +++++++++++++++++++++++++++------
 arch/arm/mach-omap2/clock3xxx_data.c |   46 ++++++++++++++++++++------
 arch/arm/mach-omap2/clock44xx_data.c |   42 ++++++++++++++++++------
 4 files changed, 161 insertions(+), 43 deletions(-)

diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index 0a992bc..ee93d3c 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -1803,27 +1803,27 @@ static struct omap_clk omap2420_clks[] = {
 	CLK(NULL,	"gpt1_ick",	&gpt1_ick,	CK_242X),
 	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_242X),
 	CLK(NULL,	"gpt2_ick",	&gpt2_ick,	CK_242X),
-	CLK(NULL,	"gpt2_fck",	&gpt2_fck,	CK_242X),
+	CLK("omap_timer.2",	"fck",	&gpt2_fck,	CK_242X),
 	CLK(NULL,	"gpt3_ick",	&gpt3_ick,	CK_242X),
-	CLK(NULL,	"gpt3_fck",	&gpt3_fck,	CK_242X),
+	CLK("omap_timer.3",	"fck",	&gpt3_fck,	CK_242X),
 	CLK(NULL,	"gpt4_ick",	&gpt4_ick,	CK_242X),
-	CLK(NULL,	"gpt4_fck",	&gpt4_fck,	CK_242X),
+	CLK("omap_timer.4",	"fck",	&gpt4_fck,	CK_242X),
 	CLK(NULL,	"gpt5_ick",	&gpt5_ick,	CK_242X),
-	CLK(NULL,	"gpt5_fck",	&gpt5_fck,	CK_242X),
+	CLK("omap_timer.5",	"fck",	&gpt5_fck,	CK_242X),
 	CLK(NULL,	"gpt6_ick",	&gpt6_ick,	CK_242X),
-	CLK(NULL,	"gpt6_fck",	&gpt6_fck,	CK_242X),
+	CLK("omap_timer.6",	"fck",	&gpt6_fck,	CK_242X),
 	CLK(NULL,	"gpt7_ick",	&gpt7_ick,	CK_242X),
-	CLK(NULL,	"gpt7_fck",	&gpt7_fck,	CK_242X),
+	CLK("omap_timer.7",	"fck",	&gpt7_fck,	CK_242X),
 	CLK(NULL,	"gpt8_ick",	&gpt8_ick,	CK_242X),
-	CLK(NULL,	"gpt8_fck",	&gpt8_fck,	CK_242X),
+	CLK("omap_timer.8",	"fck",	&gpt8_fck,	CK_242X),
 	CLK(NULL,	"gpt9_ick",	&gpt9_ick,	CK_242X),
-	CLK(NULL,	"gpt9_fck",	&gpt9_fck,	CK_242X),
+	CLK("omap_timer.9",	"fck",	&gpt9_fck,	CK_242X),
 	CLK(NULL,	"gpt10_ick",	&gpt10_ick,	CK_242X),
-	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_242X),
+	CLK("omap_timer.10",	"fck",	&gpt10_fck,	CK_242X),
 	CLK(NULL,	"gpt11_ick",	&gpt11_ick,	CK_242X),
-	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_242X),
+	CLK("omap_timer.11",	"fck",	&gpt11_fck,	CK_242X),
 	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_242X),
-	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_242X),
+	CLK("omap_timer.12",	"fck",	&gpt12_fck,	CK_242X),
 	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_242X),
 	CLK("omap-mcbsp.1", "fck",	&mcbsp1_fck,	CK_242X),
 	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick,	CK_242X),
@@ -1878,6 +1878,42 @@ 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",	"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 c047dcd..24553ce 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -1907,27 +1907,27 @@ static struct omap_clk omap2430_clks[] = {
 	CLK(NULL,	"gpt1_ick",	&gpt1_ick,	CK_243X),
 	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_243X),
 	CLK(NULL,	"gpt2_ick",	&gpt2_ick,	CK_243X),
-	CLK(NULL,	"gpt2_fck",	&gpt2_fck,	CK_243X),
+	CLK("omap_timer.2",	"fck",	&gpt2_fck,	CK_243X),
 	CLK(NULL,	"gpt3_ick",	&gpt3_ick,	CK_243X),
-	CLK(NULL,	"gpt3_fck",	&gpt3_fck,	CK_243X),
+	CLK("omap_timer.3",	"fck",	&gpt3_fck,	CK_243X),
 	CLK(NULL,	"gpt4_ick",	&gpt4_ick,	CK_243X),
-	CLK(NULL,	"gpt4_fck",	&gpt4_fck,	CK_243X),
+	CLK("omap_timer.4",	"fck",	&gpt4_fck,	CK_243X),
 	CLK(NULL,	"gpt5_ick",	&gpt5_ick,	CK_243X),
-	CLK(NULL,	"gpt5_fck",	&gpt5_fck,	CK_243X),
+	CLK("omap_timer.5",	"fck",	&gpt5_fck,	CK_243X),
 	CLK(NULL,	"gpt6_ick",	&gpt6_ick,	CK_243X),
-	CLK(NULL,	"gpt6_fck",	&gpt6_fck,	CK_243X),
+	CLK("omap_timer.6",	"fck",	&gpt6_fck,	CK_243X),
 	CLK(NULL,	"gpt7_ick",	&gpt7_ick,	CK_243X),
-	CLK(NULL,	"gpt7_fck",	&gpt7_fck,	CK_243X),
+	CLK("omap_timer.7",	"fck",	&gpt7_fck,	CK_243X),
 	CLK(NULL,	"gpt8_ick",	&gpt8_ick,	CK_243X),
-	CLK(NULL,	"gpt8_fck",	&gpt8_fck,	CK_243X),
+	CLK("omap_timer.8",	"fck",	&gpt8_fck,	CK_243X),
 	CLK(NULL,	"gpt9_ick",	&gpt9_ick,	CK_243X),
-	CLK(NULL,	"gpt9_fck",	&gpt9_fck,	CK_243X),
+	CLK("omap_timer.9",	"fck",	&gpt9_fck,	CK_243X),
 	CLK(NULL,	"gpt10_ick",	&gpt10_ick,	CK_243X),
-	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_243X),
+	CLK("omap_timer.10",	"fck",	&gpt10_fck,	CK_243X),
 	CLK(NULL,	"gpt11_ick",	&gpt11_ick,	CK_243X),
-	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_243X),
+	CLK("omap_timer.11",	"fck",	&gpt11_fck,	CK_243X),
 	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_243X),
-	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_243X),
+	CLK("omap_timer.12",	"fck",	&gpt12_fck,	CK_243X),
 	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_243X),
 	CLK("omap-mcbsp.1", "fck",	&mcbsp1_fck,	CK_243X),
 	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick,	CK_243X),
@@ -1993,6 +1993,42 @@ static struct omap_clk omap2430_clks[] = {
 	CLK(NULL,	"mdm_intc_ick",	&mdm_intc_ick,	CK_243X),
 	CLK("mmci-omap-hs.0", "mmchsdb_fck",	&mmchsdb1_fck,	CK_243X),
 	CLK("mmci-omap-hs.1", "mmchsdb_fck", 	&mmchsdb2_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 f14d986..6a17982 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -3281,8 +3281,8 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK(NULL,	"modem_fck",	&modem_fck,	CK_34XX | CK_36XX),
 	CLK(NULL,	"sad2d_ick",	&sad2d_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"mad2d_ick",	&mad2d_ick,	CK_34XX | CK_36XX),
-	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_3XXX),
-	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_3XXX),
+	CLK("omap_timer.10",	"fck",	&gpt10_fck,	CK_3XXX),
+	CLK("omap_timer.11",	"fck",	&gpt11_fck,	CK_3XXX),
 	CLK(NULL,	"cpefuse_fck",	&cpefuse_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"ts_fck",	&ts_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
@@ -3393,14 +3393,14 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK(NULL,	"per_48m_fck",	&per_48m_fck,	CK_3XXX),
 	CLK(NULL,	"uart3_fck",	&uart3_fck,	CK_3XXX),
 	CLK(NULL,	"uart4_fck",	&uart4_fck,	CK_36XX),
-	CLK(NULL,	"gpt2_fck",	&gpt2_fck,	CK_3XXX),
-	CLK(NULL,	"gpt3_fck",	&gpt3_fck,	CK_3XXX),
-	CLK(NULL,	"gpt4_fck",	&gpt4_fck,	CK_3XXX),
-	CLK(NULL,	"gpt5_fck",	&gpt5_fck,	CK_3XXX),
-	CLK(NULL,	"gpt6_fck",	&gpt6_fck,	CK_3XXX),
-	CLK(NULL,	"gpt7_fck",	&gpt7_fck,	CK_3XXX),
-	CLK(NULL,	"gpt8_fck",	&gpt8_fck,	CK_3XXX),
-	CLK(NULL,	"gpt9_fck",	&gpt9_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(NULL,	"per_32k_alwon_fck", &per_32k_alwon_fck, CK_3XXX),
 	CLK(NULL,	"gpio6_dbck",	&gpio6_dbck,	CK_3XXX),
 	CLK(NULL,	"gpio5_dbck",	&gpio5_dbck,	CK_3XXX),
@@ -3441,7 +3441,7 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK(NULL,	"sr2_fck",	&sr2_fck,	CK_34XX | CK_36XX),
 	CLK(NULL,	"sr_l4_ick",	&sr_l4_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"secure_32k_fck", &secure_32k_fck, CK_3XXX),
-	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_3XXX),
+	CLK("omap_timer.12",	"fck",	&gpt12_fck,	CK_3XXX),
 	CLK(NULL,	"wdt1_fck",	&wdt1_fck,	CK_3XXX),
 	CLK(NULL,	"ipss_ick",	&ipss_ick,	CK_AM35XX),
 	CLK(NULL,	"rmii_ck",	&rmii_ck,	CK_AM35XX),
@@ -3454,6 +3454,30 @@ 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",	"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 de9ec8d..11997a3 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3182,16 +3182,16 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"smartreflex_iva_fck",		&smartreflex_iva_fck,	CK_443X),
 	CLK(NULL,	"smartreflex_mpu_fck",		&smartreflex_mpu_fck,	CK_443X),
 	CLK(NULL,	"gpt1_fck",			&timer1_fck,	CK_443X),
-	CLK(NULL,	"gpt10_fck",			&timer10_fck,	CK_443X),
-	CLK(NULL,	"gpt11_fck",			&timer11_fck,	CK_443X),
-	CLK(NULL,	"gpt2_fck",			&timer2_fck,	CK_443X),
-	CLK(NULL,	"gpt3_fck",			&timer3_fck,	CK_443X),
-	CLK(NULL,	"gpt4_fck",			&timer4_fck,	CK_443X),
-	CLK(NULL,	"gpt5_fck",			&timer5_fck,	CK_443X),
-	CLK(NULL,	"gpt6_fck",			&timer6_fck,	CK_443X),
-	CLK(NULL,	"gpt7_fck",			&timer7_fck,	CK_443X),
-	CLK(NULL,	"gpt8_fck",			&timer8_fck,	CK_443X),
-	CLK(NULL,	"gpt9_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.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(NULL,	"uart1_fck",			&uart1_fck,	CK_443X),
 	CLK(NULL,	"uart2_fck",			&uart2_fck,	CK_443X),
 	CLK(NULL,	"uart3_fck",			&uart3_fck,	CK_443X),
@@ -3275,6 +3275,28 @@ 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",	"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] 44+ messages in thread

* [PATCH v11 2/8] OMAP4: hwmod data: add dmtimer version information
  2011-02-24 11:26 [PATCH v11 0/8] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
  2011-02-24 11:26 ` [PATCH v11 1/8] OMAP2+: dmtimer: add device names to flck nodes Tarun Kanti DebBarma
@ 2011-02-24 11:26 ` Tarun Kanti DebBarma
  2011-03-04  0:24   ` Kevin Hilman
  2011-02-24 11:26 ` [PATCH v11 3/8] OMAP1: dmtimer: conversion to platform devices Tarun Kanti DebBarma
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 44+ messages in thread
From: Tarun Kanti DebBarma @ 2011-02-24 11:26 UTC (permalink / raw)
  To: linux-omap; +Cc: Tarun Kanti DebBarma

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>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    3 +++
 arch/arm/plat-omap/include/plat/dmtimer.h  |    2 ++
 2 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 79a8601..ee57742 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -25,6 +25,7 @@
 #include <plat/gpio.h>
 #include <plat/dma.h>
 #include <plat/mcspi.h>
+#include <plat/dmtimer.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -3940,6 +3941,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 = {
@@ -3955,6 +3957,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 d6c70d2..05a967e 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -55,6 +55,8 @@
  * in OMAP4 can be distinguished.
  */
 #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;
 extern struct sys_timer omap_timer;
-- 
1.6.0.4


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

* [PATCH v11 3/8] OMAP1: dmtimer: conversion to platform devices
  2011-02-24 11:26 [PATCH v11 0/8] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
  2011-02-24 11:26 ` [PATCH v11 1/8] OMAP2+: dmtimer: add device names to flck nodes Tarun Kanti DebBarma
  2011-02-24 11:26 ` [PATCH v11 2/8] OMAP4: hwmod data: add dmtimer version information Tarun Kanti DebBarma
@ 2011-02-24 11:26 ` Tarun Kanti DebBarma
  2011-02-24 11:26 ` [PATCH v11 4/8] OMAP2+: dmtimer: convert " Tarun Kanti DebBarma
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Tarun Kanti DebBarma @ 2011-02-24 11:26 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             |  214 +++++++++++++++++++++++++++++
 arch/arm/mach-omap1/timer32k.c            |    4 -
 arch/arm/plat-omap/dmtimer.c              |   64 +--------
 arch/arm/plat-omap/include/plat/dmtimer.h |   24 +++-
 5 files changed, 246 insertions(+), 62 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..d1e17fe
--- /dev/null
+++ b/arch/arm/mach-omap1/dmtimer.c
@@ -0,0 +1,214 @@
+/**
+ * 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
+
+#define OMAP_TIMER_OCP_CFG_REG		0x10
+#define OMAP_TIMER_SYS_STAT_REG		0x14
+#define OMAP_TIMER_IF_CTRL_REG		0x40
+
+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;
+}
+
+static void omap1_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
+{
+	int c;
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
+	c = 0;
+	while (!(pdata->dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
+		c++;
+		if (c > 100000) {
+			printk(KERN_ERR "Timer failed to reset.\n");
+			return;
+		}
+	}
+}
+
+static void omap1_dm_timer_reset(struct omap_dm_timer *timer)
+{
+	u32 l;
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
+	if (timer->pdev->id != 1) {
+		pdata->dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
+		omap1_dm_timer_wait_for_reset(timer);
+	}
+
+	l = pdata->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 */
+	pdata->dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
+}
+
+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->dm_timer_reset = omap1_dm_timer_reset;
+		pdata->set_timer_src = omap1_dm_timer_set_src;
+
+		pdata->is_early_init = 1;
+		pdata->is_omap16xx = 1;
+		pdata->timer_ip_type = OMAP_TIMER_IP_VERSION_1;
+
+		pdata->intr_offset = 0;
+		pdata->func_offset = 0;
+
+		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/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
index 13d7b8f..dc4a8fd 100644
--- a/arch/arm/mach-omap1/timer32k.c
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -53,7 +53,6 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 #include <plat/common.h>
-#include <plat/dmtimer.h>
 
 /*
  * ---------------------------------------------------------------------------
@@ -184,9 +183,6 @@ bool __init omap_32k_timer_init(void)
 {
 	omap_init_clocksource_32k();
 
-#ifdef CONFIG_OMAP_DM_TIMER
-	omap_dm_timer_init();
-#endif
 	omap_init_32k_timer();
 
 	return true;
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 1d706cf..1bfaf09 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
@@ -150,39 +156,8 @@
 #define OMAP_TIMER_TICK_INT_MASK_COUNT_REG				\
 		(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
 
-struct omap_dm_timer {
-	unsigned long phys_base;
-	int irq;
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	struct clk *iclk, *fclk;
-#endif
-	void __iomem *io_base;
-	unsigned reserved:1;
-	unsigned enabled:1;
-	unsigned posted:1;
-};
-
 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 },
@@ -549,23 +524,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 omap_dm_timer *timer, int source)
 {
 	int ret = -EINVAL;
@@ -587,8 +545,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)
 {
@@ -738,16 +694,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 05a967e..4bfbfcc 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -57,11 +57,33 @@
 #define OMAP_TIMER_IP_VERSION_1                        0x1
 #define OMAP_TIMER_IP_VERSION_2                        0x2
 
-struct omap_dm_timer;
+struct omap_dm_timer {
+	unsigned long phys_base;
+	int irq;
+	struct clk *iclk, *fclk;
+	void __iomem *io_base;
+	unsigned reserved:1;
+	unsigned enabled:1;
+	unsigned posted:1;
+	struct platform_device *pdev;
+};
+
 extern struct omap_dm_timer *gptimer_wakeup;
 extern struct sys_timer omap_timer;
 struct clk;
 
+struct dmtimer_platform_data {
+	int (*set_timer_src)(struct platform_device *pdev, int source);
+	void (*dm_timer_reset)(struct omap_dm_timer *);
+	u32 (*dm_timer_read_reg)(struct omap_dm_timer *, u32);
+	void (*dm_timer_write_reg)(struct omap_dm_timer *, u32, u32);
+	int timer_ip_type;
+	u8 func_offset;
+	u8 intr_offset;
+	u32 is_early_init:1;
+	u32 is_omap16xx:1;
+};
+
 int omap_dm_timer_init(void);
 
 struct omap_dm_timer *omap_dm_timer_request(void);
-- 
1.6.0.4


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

* [PATCH v11 4/8] OMAP2+: dmtimer: convert to platform devices
  2011-02-24 11:26 [PATCH v11 0/8] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (2 preceding siblings ...)
  2011-02-24 11:26 ` [PATCH v11 3/8] OMAP1: dmtimer: conversion to platform devices Tarun Kanti DebBarma
@ 2011-02-24 11:26 ` Tarun Kanti DebBarma
  2011-03-04  1:01   ` Kevin Hilman
  2011-02-24 11:26 ` [PATCH v11 5/8] OMAP: dmtimer: platform driver Tarun Kanti DebBarma
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 44+ messages in thread
From: Tarun Kanti DebBarma @ 2011-02-24 11:26 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. It also provides
provision to access timers during early boot when pm_runtime framework
is not completely up and running.

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/Makefile  |    2 +-
 arch/arm/mach-omap2/dmtimer.c |  199 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 200 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-omap2/dmtimer.c

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 1c3635d..7e5014b 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \
-	 common.o gpio.o dma.o wd_timer.o
+	 common.o gpio.o dma.o wd_timer.o dmtimer.o
 
 omap-2-3-common				= irq.o sdrc.o
 hwmod-common				= omap_hwmod.o \
diff --git a/arch/arm/mach-omap2/dmtimer.c b/arch/arm/mach-omap2/dmtimer.c
new file mode 100644
index 0000000..00cebe9
--- /dev/null
+++ b/arch/arm/mach-omap2/dmtimer.c
@@ -0,0 +1,199 @@
+/**
+ * OMAP2+ Dual-Mode Timers - platform device registration
+ *
+ * Contains first level initialization routines which extracts timers
+ * information from hwmod database and registers with linux device model.
+ * It also has low level function to change 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/err.h>
+#include <linux/slab.h>
+
+#include <plat/dmtimer.h>
+#include <plat/omap_device.h>
+#include <plat/cpu.h>
+
+/*
+ * 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
+
+static int early_timer_count __initdata = 1;
+
+struct dm_timer_data {
+	struct omap_device *od;
+	struct dmtimer_platform_data *pdata;
+	struct list_head node;
+};
+
+static __initdata LIST_HEAD(dm_timer_data_list);
+
+/**
+ * omap2_dm_timer_set_src - change the timer input clock source
+ * @pdev:	timer platform device pointer
+ * @timer_clk:	current clock source
+ * @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 = clk_get(&pdev->dev, "fck");
+	struct clk *new_fclk;
+	char *fclk_name = "32k_ck"; /* default name */
+
+	switch (source) {
+	case OMAP_TIMER_SRC_SYS_CLK:
+		fclk_name = "sys_ck";
+		break;
+
+	case OMAP_TIMER_SRC_32_KHZ:
+		fclk_name = "32k_ck";
+		break;
+
+	case OMAP_TIMER_SRC_EXT_CLK:
+		if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_1) {
+			fclk_name = "alt_ck";
+			break;
+		}
+		dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	if (IS_ERR_OR_NULL(fclk)) {
+		dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	new_fclk = clk_get(&pdev->dev, fclk_name);
+	if (IS_ERR_OR_NULL(new_fclk)) {
+		dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
+			__func__, __LINE__, 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__, 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 dm_timer_data *timer_data = NULL;
+
+	pr_debug("%s: %s\n", __func__, oh->name);
+
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("%s: No memory for [%s]\n", __func__, oh->name);
+		return -ENOMEM;
+	}
+
+	pdata->is_early_init = 1;
+	pdata->is_omap16xx = 0;
+	pdata->dm_timer_reset = NULL;
+	pdata->set_timer_src = omap2_dm_timer_set_src;
+
+	pdata->timer_ip_type = oh->class->rev;
+	if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_2) {
+		pdata->func_offset = VERSION2_TIMER_WAKEUP_EN_REG_OFFSET;
+		pdata->intr_offset = VERSION2_TIMER_STAT_REG_OFFSET;
+	} else {
+		pdata->func_offset = 0;
+		pdata->intr_offset = 0;
+	}
+
+	/*
+	 * 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);
+
+	/* do registration of timer12 on GP device only */
+	if (id == 12 && omap_type() != OMAP2_DEVICE_TYPE_GP)
+		return ret;
+
+	od = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
+			omap2_dmtimer_latency,
+			ARRAY_SIZE(omap2_dmtimer_latency),
+			pdata->is_early_init);
+
+	if (IS_ERR(od)) {
+		pr_err("%s: Can't build omap_device for %s: %s.\n",
+			__func__, name, oh->name);
+		ret = -EINVAL;
+	} else if (pdata->is_early_init)
+		early_timer_count++;
+
+	timer_data = kzalloc(sizeof(*timer_data), GFP_KERNEL);
+	if (!timer_data) {
+		pr_debug("%s: no memory for dm_timer_data\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	/* store od and pdata to be used later during normal initialization */
+	timer_data->od = od;
+	timer_data->pdata = pdata;
+	list_add_tail(&timer_data->node, &dm_timer_data_list);
+
+	return ret;
+}
-- 
1.6.0.4


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

* [PATCH v11 5/8] OMAP: dmtimer: platform driver
  2011-02-24 11:26 [PATCH v11 0/8] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (3 preceding siblings ...)
  2011-02-24 11:26 ` [PATCH v11 4/8] OMAP2+: dmtimer: convert " Tarun Kanti DebBarma
@ 2011-02-24 11:26 ` Tarun Kanti DebBarma
  2011-03-04  0:35   ` Kevin Hilman
  2011-03-04  1:29   ` Kevin Hilman
  2011-02-24 11:26 ` [PATCH v11 6/8] dmtimer: switch-over to platform device driver Tarun Kanti DebBarma
                   ` (3 subsequent siblings)
  8 siblings, 2 replies; 44+ messages in thread
From: Tarun Kanti DebBarma @ 2011-02-24 11:26 UTC (permalink / raw)
  To: linux-omap; +Cc: Thara Gopinath, Tarun Kanti DebBarma

From: Thara Gopinath <thara@ti.com>

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              |  167 ++++++++++++++++++++++++++++-
 arch/arm/plat-omap/include/plat/dmtimer.h |    2 +
 2 files changed, 168 insertions(+), 1 deletions(-)

diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 1bfaf09..bfe6fd3 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -43,6 +43,9 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
 #include <mach/hardware.h>
 #include <plat/dmtimer.h>
 #include <mach/irqs.h>
@@ -257,7 +260,8 @@ 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
@@ -689,6 +693,167 @@ 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;
+	}
+
+	spin_lock_irqsave(&dm_timer_lock, flags);
+	list_for_each_entry(timer, &omap_timer_list, node)
+		if (!pdata->is_early_init && timer->id == pdev->id) {
+			timer->pdev = pdev;
+			spin_unlock_irqrestore(&dm_timer_lock, flags);
+			dev_dbg(&pdev->dev, "Regular Probed\n");
+			return 0;
+		}
+	spin_unlock_irqrestore(&dm_timer_lock, flags);
+
+	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;
+	}
+
+	/*
+	 * Following func pointers are required by OMAP1's reset code
+	 * in mach-omap1/dmtimer.c to access to low level read/write.
+	 */
+	if (pdata->is_omap16xx) {
+		pdata->dm_timer_read_reg = omap_dm_timer_read_reg;
+		pdata->dm_timer_write_reg = omap_dm_timer_write_reg;
+		pdata->is_early_init = 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, "Early 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 4bfbfcc..1a080db 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -59,6 +59,7 @@
 
 struct omap_dm_timer {
 	unsigned long phys_base;
+	int id;
 	int irq;
 	struct clk *iclk, *fclk;
 	void __iomem *io_base;
@@ -66,6 +67,7 @@ struct omap_dm_timer {
 	unsigned enabled:1;
 	unsigned posted:1;
 	struct platform_device *pdev;
+	struct list_head node;
 };
 
 extern struct omap_dm_timer *gptimer_wakeup;
-- 
1.6.0.4


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

* [PATCH v11 6/8] dmtimer: switch-over to platform device driver
  2011-02-24 11:26 [PATCH v11 0/8] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (4 preceding siblings ...)
  2011-02-24 11:26 ` [PATCH v11 5/8] OMAP: dmtimer: platform driver Tarun Kanti DebBarma
@ 2011-02-24 11:26 ` Tarun Kanti DebBarma
  2011-03-04  1:25   ` Kevin Hilman
  2011-03-04 17:23   ` Tony Lindgren
  2011-02-24 11:26 ` [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support Tarun Kanti DebBarma
                   ` (2 subsequent siblings)
  8 siblings, 2 replies; 44+ messages in thread
From: Tarun Kanti DebBarma @ 2011-02-24 11:26 UTC (permalink / raw)
  To: linux-omap; +Cc: Tarun Kanti DebBarma

switch-over to platform device driver through following changes:
(a) initiate dmtimer early initialization from omap2_gp_timer_init()
in timer-gp.c. This is equivalent of timer_init()->timer->init().
(b) modify plat-omap/dmtimer routines to use new register map and
platform data.

Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
Acked-by: Cousson, Benoit <b-cousson@ti.com>
---
 arch/arm/mach-omap2/clock2420_data.c      |    2 +-
 arch/arm/mach-omap2/clock2430_data.c      |    2 +-
 arch/arm/mach-omap2/clock3xxx_data.c      |    2 +-
 arch/arm/mach-omap2/clock44xx_data.c      |    2 +-
 arch/arm/mach-omap2/dmtimer.c             |   61 +++++
 arch/arm/mach-omap2/dmtimer.h             |   30 +++
 arch/arm/mach-omap2/timer-gp.c            |    4 +-
 arch/arm/plat-omap/dmtimer.c              |  350 ++++++++---------------------
 arch/arm/plat-omap/include/plat/dmtimer.h |    5 +-
 9 files changed, 190 insertions(+), 268 deletions(-)
 create mode 100644 arch/arm/mach-omap2/dmtimer.h

diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index ee93d3c..390d6aa 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -1801,7 +1801,7 @@ static struct omap_clk omap2420_clks[] = {
 	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_242X),
 	/* general l4 interface ck, multi-parent functional clk */
 	CLK(NULL,	"gpt1_ick",	&gpt1_ick,	CK_242X),
-	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_242X),
+	CLK("omap_timer.1",	"fck",	&gpt1_fck,	CK_242X),
 	CLK(NULL,	"gpt2_ick",	&gpt2_ick,	CK_242X),
 	CLK("omap_timer.2",	"fck",	&gpt2_fck,	CK_242X),
 	CLK(NULL,	"gpt3_ick",	&gpt3_ick,	CK_242X),
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index 24553ce..7a3e5a4 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -1905,7 +1905,7 @@ static struct omap_clk omap2430_clks[] = {
 	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_243X),
 	/* general l4 interface ck, multi-parent functional clk */
 	CLK(NULL,	"gpt1_ick",	&gpt1_ick,	CK_243X),
-	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_243X),
+	CLK("omap_timer.1",	"fck",	&gpt1_fck,	CK_243X),
 	CLK(NULL,	"gpt2_ick",	&gpt2_ick,	CK_243X),
 	CLK("omap_timer.2",	"fck",	&gpt2_fck,	CK_243X),
 	CLK(NULL,	"gpt3_ick",	&gpt3_ick,	CK_243X),
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 6a17982..506f59d 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -3374,7 +3374,7 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK(NULL,	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK("ehci-omap.0",	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"usim_fck",	&usim_fck,	CK_3430ES2PLUS | CK_36XX),
-	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_3XXX),
+	CLK("omap_timer.1",	"fck",	&gpt1_fck,	CK_3XXX),
 	CLK(NULL,	"wkup_32k_fck",	&wkup_32k_fck,	CK_3XXX),
 	CLK(NULL,	"gpio1_dbck",	&gpio1_dbck,	CK_3XXX),
 	CLK("omap_wdt",	"fck",		&wdt2_fck,	CK_3XXX),
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 11997a3..8f8b010 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3181,7 +3181,7 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"smartreflex_core_fck",		&smartreflex_core_fck,	CK_443X),
 	CLK(NULL,	"smartreflex_iva_fck",		&smartreflex_iva_fck,	CK_443X),
 	CLK(NULL,	"smartreflex_mpu_fck",		&smartreflex_mpu_fck,	CK_443X),
-	CLK(NULL,	"gpt1_fck",			&timer1_fck,	CK_443X),
+	CLK("omap_timer.1",	"fck",			&timer1_fck,	CK_443X),
 	CLK("omap_timer.10",	"fck",			&timer10_fck,	CK_443X),
 	CLK("omap_timer.11",	"fck",			&timer11_fck,	CK_443X),
 	CLK("omap_timer.2",	"fck",			&timer2_fck,	CK_443X),
diff --git a/arch/arm/mach-omap2/dmtimer.c b/arch/arm/mach-omap2/dmtimer.c
index 00cebe9..63d5ae7 100644
--- a/arch/arm/mach-omap2/dmtimer.c
+++ b/arch/arm/mach-omap2/dmtimer.c
@@ -197,3 +197,64 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
 
 	return ret;
 }
+
+/**
+ * omap2_dm_timer_early_init - top level early timer initialization
+ * called in the last part of omap2_init_common_hw
+ *
+ * Uses dedicated hwmod api to parse through hwmod database for
+ * given class name and then build and register the timer device.
+ * At the end driver is registered and early probe initiated.
+ */
+void __init omap2_dm_timer_early_init(void)
+{
+	int ret = omap_hwmod_for_each_by_class("timer",
+			omap_timer_init, NULL);
+
+	if (unlikely(ret)) {
+		pr_err("%s: device registration failed.\n", __func__);
+		return;
+	}
+
+	early_platform_driver_register_all("earlytimer");
+	early_platform_driver_probe("earlytimer", early_timer_count, 0);
+}
+
+/**
+ * omap2_dm_timer_normal_init - top level regular device initialization
+ *
+ * This initialization is done with od and pdata acquired during early
+ * initialization. They are stored in temporary array which is cleaned
+ * at the end of initialization.
+ */
+static int __init omap2_dm_timer_normal_init(void)
+{
+	int ret;
+	struct dm_timer_data *timer_data = NULL;
+
+
+	list_for_each_entry(timer_data, &dm_timer_data_list, node) {
+		timer_data->pdata->is_early_init = 0;
+		ret = platform_device_add_data(&timer_data->od->pdev,
+						timer_data->pdata,
+						sizeof(*timer_data->pdata));
+		if (ret) {
+			pr_err("%s: Failed to add platform data\n", __func__);
+			goto next;
+		}
+
+		ret = omap_device_register(timer_data->od);
+		if (ret)
+			pr_err("%s: Failed to add platform device\n",
+					__func__);
+		else
+			dev_dbg(&timer_data->od->pdev.dev, "%s: Registered\n",
+					__func__);
+next:
+		kfree(timer_data->pdata);
+		kfree(timer_data);
+	}
+
+	return 0;
+}
+arch_initcall(omap2_dm_timer_normal_init);
diff --git a/arch/arm/mach-omap2/dmtimer.h b/arch/arm/mach-omap2/dmtimer.h
new file mode 100644
index 0000000..baf5a59
--- /dev/null
+++ b/arch/arm/mach-omap2/dmtimer.h
@@ -0,0 +1,30 @@
+/**
+ * OMAP Dual-Mode Timers - early initialization interface
+ *
+ * Function interface called first to start dmtimer early initialization.
+ *
+ * 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.
+ */
+#ifndef __ASM_ARCH_DMTIMER_H
+#define __ASM_ARCH_DMTIMER_H
+
+/*
+ * dmtimer is required during early part of boot sequence even before
+ * device model and pm_runtime if fully up and running. This function
+ * is called from following sequence:
+ * start_kernel()->time_init()->timer->init()->omap2_gp_timer_init()
+ */
+void __init omap2_dm_timer_early_init(void);
+
+#endif
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index 878a96c..df5357a 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -43,6 +43,7 @@
 #include <plat/omap_hwmod.h>
 
 #include "timer-gp.h"
+#include "dmtimer.h"
 
 /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
 #define MAX_GPTIMER_ID		12
@@ -232,6 +233,7 @@ static void __init omap2_gp_clocksource_init(void)
 		printk(err2, clocksource_gpt.name);
 }
 #endif
+void omap2_dm_timer_early_init(void);
 
 static void __init omap2_gp_timer_init(void)
 {
@@ -241,7 +243,7 @@ static void __init omap2_gp_timer_init(void)
 		BUG_ON(!twd_base);
 	}
 #endif
-	omap_dm_timer_init();
+	omap2_dm_timer_early_init();
 
 	omap2_gp_clockevent_init();
 	omap2_gp_clocksource_init();
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index bfe6fd3..53f5205 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -35,20 +35,13 @@
  * 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 <linux/slab.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
-#include <mach/hardware.h>
 #include <plat/dmtimer.h>
-#include <mach/irqs.h>
 
 /* register offsets */
 #define _OMAP_TIMER_ID_OFFSET		0x00
@@ -159,117 +152,27 @@
 #define OMAP_TIMER_TICK_INT_MASK_COUNT_REG				\
 		(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
 
-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 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)
 {
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
+	if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
+		reg += pdata->func_offset;
+	else if (reg >= OMAP_TIMER_STAT_REG)
+		reg += pdata->intr_offset;
+
 	if (timer->posted)
 		while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
 				& (reg >> WPSHIFT))
@@ -277,15 +180,26 @@ static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
 	return readl(timer->io_base + (reg & 0xff));
 }
 
-/*
- * 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)
 {
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
+	if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
+		reg += pdata->func_offset;
+	else if (reg >= OMAP_TIMER_STAT_REG)
+		reg += pdata->intr_offset;
+
 	if (timer->posted)
 		while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
 				& (reg >> WPSHIFT))
@@ -293,40 +207,22 @@ static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
 	writel(value, timer->io_base + (reg & 0xff));
 }
 
-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;
-		}
-	}
-}
-
-static void omap_dm_timer_reset(struct omap_dm_timer *timer)
+static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
 {
-	u32 l;
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
 
-	if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
-		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
-		omap_dm_timer_wait_for_reset(timer);
+	timer->fclk = clk_get(&timer->pdev->dev, "fck");
+	if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
+		dev_err(&timer->pdev->dev, ": No fclk handle.\n");
+		return;
 	}
-	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
 
-	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 */
+	omap_dm_timer_enable(timer);
 
-	/*
-	 * Enable wake-up on OMAP2 CPUs.
-	 */
-	if (cpu_class_is_omap2())
-		l |= 1 << 2;
-	omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
+	if (pdata->dm_timer_reset)
+		pdata->dm_timer_reset(timer);
+
+	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
 
 	/* Match hardware reset default of posted mode */
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
@@ -334,31 +230,26 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
 	timer->posted = 1;
 }
 
-static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
-{
-	omap_dm_timer_enable(timer);
-	omap_dm_timer_reset(timer);
-}
-
 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;
 }
@@ -366,23 +257,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;
 }
@@ -390,10 +281,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;
 }
@@ -404,12 +295,7 @@ 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);
 
 	timer->enabled = 1;
 }
@@ -420,12 +306,7 @@ 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);
 
 	timer->enabled = 0;
 }
@@ -445,24 +326,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;
 }
@@ -507,20 +394,22 @@ 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;
 
 	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
+
+		if (!pdata->is_omap16xx) {
+			/* 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);
+		}
 	}
 	/* Ack possibly pending interrupt */
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
@@ -531,13 +420,15 @@ 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;
 
-	clk_disable(timer->fclk);
-	ret = clk_set_parent(timer->fclk, dm_source_clocks[source]);
-	clk_enable(timer->fclk);
+	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
@@ -674,13 +565,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;
 
@@ -853,58 +740,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);
-		}
-#endif
-	}
-
-	return 0;
-}
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 1a080db..15ac8a8 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -58,10 +58,9 @@
 #define OMAP_TIMER_IP_VERSION_2                        0x2
 
 struct omap_dm_timer {
-	unsigned long phys_base;
 	int id;
 	int irq;
-	struct clk *iclk, *fclk;
+	struct clk *fclk;
 	void __iomem *io_base;
 	unsigned reserved:1;
 	unsigned enabled:1;
@@ -86,8 +85,6 @@ struct dmtimer_platform_data {
 	u32 is_omap16xx: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);
-- 
1.6.0.4


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

* [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
  2011-02-24 11:26 [PATCH v11 0/8] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (5 preceding siblings ...)
  2011-02-24 11:26 ` [PATCH v11 6/8] dmtimer: switch-over to platform device driver Tarun Kanti DebBarma
@ 2011-02-24 11:26 ` Tarun Kanti DebBarma
  2011-03-04  1:22   ` Kevin Hilman
  2011-02-24 11:26 ` [PATCH v11 8/8] OMAP: dmtimer: add timeout to low-level routines Tarun Kanti DebBarma
  2011-02-25 14:08 ` [PATCH v11 0/8] dmtimer adaptation to platform_driver DebBarma, Tarun Kanti
  8 siblings, 1 reply; 44+ messages in thread
From: Tarun Kanti DebBarma @ 2011-02-24 11:26 UTC (permalink / raw)
  To: linux-omap; +Cc: Tarun Kanti DebBarma, Partha Basak

Add pm_runtime support to dmtimer. Since dmtimer is used during
early boot before pm_runtime is initialized completely there are
provisions to enable/disable clocks directly in the code during
early boot.

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 |   63 ++++++++++++++++++++++++++++++++++++------
 1 files changed, 54 insertions(+), 9 deletions(-)

diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 53f5205..fcac422 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -39,6 +39,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <plat/dmtimer.h>
@@ -211,13 +212,16 @@ static 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))) {
-		dev_err(&timer->pdev->dev, ": No fclk handle.\n");
-		return;
+	if (!pdata->is_omap16xx) {
+		timer->fclk = clk_get(&timer->pdev->dev, "fck");
+		if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
+			dev_err(&timer->pdev->dev, ": No fclk handle.\n");
+			return;
+		}
 	}
 
-	omap_dm_timer_enable(timer);
+	if (!pdata->is_omap16xx)
+		omap_dm_timer_enable(timer);
 
 	if (pdata->dm_timer_reset)
 		pdata->dm_timer_reset(timer);
@@ -292,10 +296,22 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_free);
 
 void omap_dm_timer_enable(struct omap_dm_timer *timer)
 {
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
 	if (timer->enabled)
 		return;
 
-	clk_enable(timer->fclk);
+	if (unlikely(pdata->is_early_init)) {
+		clk_enable(timer->fclk);
+		timer->enabled = 1;
+		return;
+	}
+
+	if (pm_runtime_get_sync(&timer->pdev->dev) < 0) {
+		dev_err(&timer->pdev->dev, "%s: pm_runtime_get_sync() FAILED\n",
+			__func__);
+		return;
+	}
 
 	timer->enabled = 1;
 }
@@ -303,10 +319,22 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
 
 void omap_dm_timer_disable(struct omap_dm_timer *timer)
 {
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+
 	if (!timer->enabled)
 		return;
 
-	clk_disable(timer->fclk);
+	if (unlikely(pdata->is_early_init)) {
+		clk_disable(timer->fclk);
+		timer->enabled = 0;
+		return;
+	}
+
+	if (pm_runtime_put_sync(&timer->pdev->dev) < 0) {
+		dev_err(&timer->pdev->dev, "%s: pm_runtime_put_sync() FAILED\n",
+			__func__);
+		return;
+	}
 
 	timer->enabled = 0;
 }
@@ -425,10 +453,12 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 	if (source < 0 || source >= 3)
 		return -EINVAL;
 
-	omap_dm_timer_disable(timer);
+	if (!pdata->is_omap16xx)
+		omap_dm_timer_disable(timer);
 	/* change the timer clock source */
 	ret = pdata->set_timer_src(timer->pdev, source);
-	omap_dm_timer_enable(timer);
+	if (!pdata->is_omap16xx)
+		omap_dm_timer_enable(timer);
 
 	/*
 	 * When the functional clock disappears, too quick writes seem
@@ -600,11 +630,26 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
+	/*
+	 * OMAP2+
+	 * Early timers are already registered and in list.
+	 * What we need to do during second phase of probe
+	 * is to assign the newly allocated/configured pdev
+	 * to timer->pdev. We also call pm_runtime_enable()
+	 * for each device because it could not be called
+	 * during early boot because pm_runtime framework
+	 * was not yet up and running.
+	 */
 	spin_lock_irqsave(&dm_timer_lock, flags);
 	list_for_each_entry(timer, &omap_timer_list, node)
 		if (!pdata->is_early_init && timer->id == pdev->id) {
 			timer->pdev = pdev;
 			spin_unlock_irqrestore(&dm_timer_lock, flags);
+			pm_runtime_enable(&pdev->dev);
+			/* update PM runtime for active early timers */
+			if (timer->reserved)
+				pm_runtime_get_sync(&pdev->dev);
+
 			dev_dbg(&pdev->dev, "Regular Probed\n");
 			return 0;
 		}
-- 
1.6.0.4


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

* [PATCH v11 8/8] OMAP: dmtimer: add timeout to low-level routines
  2011-02-24 11:26 [PATCH v11 0/8] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (6 preceding siblings ...)
  2011-02-24 11:26 ` [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support Tarun Kanti DebBarma
@ 2011-02-24 11:26 ` Tarun Kanti DebBarma
  2011-02-25 14:08 ` [PATCH v11 0/8] dmtimer adaptation to platform_driver DebBarma, Tarun Kanti
  8 siblings, 0 replies; 44+ messages in thread
From: Tarun Kanti DebBarma @ 2011-02-24 11:26 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/dmtimer.c |   33 +++++++++++++++++++++++++--------
 1 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index fcac422..a39d5ba 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -43,6 +43,7 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <plat/dmtimer.h>
+#include <plat/common.h>
 
 /* register offsets */
 #define _OMAP_TIMER_ID_OFFSET		0x00
@@ -153,6 +154,8 @@
 #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 */
+
 static LIST_HEAD(omap_timer_list);
 static DEFINE_SPINLOCK(dm_timer_lock);
 
@@ -168,16 +171,23 @@ static DEFINE_SPINLOCK(dm_timer_lock);
 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
 {
 	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+	int i = 0;
 
 	if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
 		reg += pdata->func_offset;
 	else if (reg >= OMAP_TIMER_STAT_REG)
 		reg += pdata->intr_offset;
 
-	if (timer->posted)
-		while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
-				& (reg >> WPSHIFT))
-			cpu_relax();
+	if (timer->posted) {
+		omap_test_timeout(!(readl(timer->io_base +
+			((OMAP_TIMER_WRITE_PEND_REG +
+			pdata->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 readl(timer->io_base + (reg & 0xff));
 }
 
@@ -195,16 +205,23 @@ static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
 						u32 value)
 {
 	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+	int i = 0;
 
 	if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
 		reg += pdata->func_offset;
 	else if (reg >= OMAP_TIMER_STAT_REG)
 		reg += pdata->intr_offset;
 
-	if (timer->posted)
-		while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
-				& (reg >> WPSHIFT))
-			cpu_relax();
+	if (timer->posted) {
+		omap_test_timeout(!(readl(timer->io_base +
+			((OMAP_TIMER_WRITE_PEND_REG +
+			pdata->func_offset) & 0xff)) & (reg >> WPSHIFT)),
+			MAX_WRITE_PEND_WAIT, i);
+
+		if (WARN_ON(i == MAX_WRITE_PEND_WAIT))
+			pr_err(": write timeout\n");
+	}
+
 	writel(value, timer->io_base + (reg & 0xff));
 }
 
-- 
1.6.0.4


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

* RE: [PATCH v11 0/8] dmtimer adaptation to platform_driver
  2011-02-24 11:26 [PATCH v11 0/8] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
                   ` (7 preceding siblings ...)
  2011-02-24 11:26 ` [PATCH v11 8/8] OMAP: dmtimer: add timeout to low-level routines Tarun Kanti DebBarma
@ 2011-02-25 14:08 ` DebBarma, Tarun Kanti
  8 siblings, 0 replies; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-02-25 14:08 UTC (permalink / raw)
  To: linux-omap@vger.kernel.org

> -----Original Message-----
> From: DebBarma, Tarun Kanti
> Sent: Thursday, February 24, 2011 4:57 PM
> To: linux-omap@vger.kernel.org
> Cc: DebBarma, Tarun Kanti
> Subject: [PATCH v11 0/8] dmtimer adaptation to platform_driver
> 
> dmtimer adaptation to platform_driver.
> 
> This patch series is adaptation of dmtimer code to platform driver
> using omap_device and omap_hwmod abstraction.
> 
> NOTE:
> This patch series should be applied on-top of Paul's following patch
> series:
> http://www.spinics.net/lists/linux-omap/msg46725.html
> 
> Baseline:
> git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
> Branch: omap-for-linus
> 
> Test Info:
> Tested on OMAP3, OMAP4. Bootup test on OMAP1710.
> OMAP3 power test: Retention and Off mode.
> OMAP2 platforms not tested because of existing issue in the branch.
I have re-based the changes on omap-testing branch and tested on
OMAP2420 and OMAP2430.
--
Tarun

> 
> 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 (5):
>   OMAP4: hwmod data: add dmtimer version information
>   OMAP2+: dmtimer: convert to platform devices
>   dmtimer: switch-over to platform device driver
>   OMAP: dmtimer: pm_runtime support
>   OMAP: dmtimer: add timeout to low-level routines
> 
> Thara Gopinath (3):
>   OMAP2+: dmtimer: add device names to flck nodes
>   OMAP1: dmtimer: conversion to platform devices
>   OMAP: dmtimer: platform driver
> 
>  arch/arm/mach-omap1/Makefile               |    2 +-
>  arch/arm/mach-omap1/dmtimer.c              |  214 ++++++++++
>  arch/arm/mach-omap1/timer32k.c             |    4 -
>  arch/arm/mach-omap2/Makefile               |    2 +-
>  arch/arm/mach-omap2/clock2420_data.c       |   60 +++-
>  arch/arm/mach-omap2/clock2430_data.c       |   60 +++-
>  arch/arm/mach-omap2/clock3xxx_data.c       |   48 ++-
>  arch/arm/mach-omap2/clock44xx_data.c       |   44 ++-
>  arch/arm/mach-omap2/dmtimer.c              |  260 ++++++++++++
>  arch/arm/mach-omap2/dmtimer.h              |   30 ++
>  arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    3 +
>  arch/arm/mach-omap2/timer-gp.c             |    4 +-
>  arch/arm/plat-omap/dmtimer.c               |  607 ++++++++++++++---------
> -----
>  arch/arm/plat-omap/include/plat/dmtimer.h  |   27 ++-
>  14 files changed, 1011 insertions(+), 354 deletions(-)
>  create mode 100644 arch/arm/mach-omap1/dmtimer.c
>  create mode 100644 arch/arm/mach-omap2/dmtimer.c
>  create mode 100644 arch/arm/mach-omap2/dmtimer.h


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

* Re: [PATCH v11 2/8] OMAP4: hwmod data: add dmtimer version information
  2011-02-24 11:26 ` [PATCH v11 2/8] OMAP4: hwmod data: add dmtimer version information Tarun Kanti DebBarma
@ 2011-03-04  0:24   ` Kevin Hilman
  2011-03-04  5:49     ` DebBarma, Tarun Kanti
  2011-03-04 11:16     ` Cousson, Benoit
  0 siblings, 2 replies; 44+ messages in thread
From: Kevin Hilman @ 2011-03-04  0:24 UTC (permalink / raw)
  To: Tarun Kanti DebBarma; +Cc: linux-omap

Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:

> 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>

Minor comment below, also needs an ack from Benoît...

> ---
>  arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    3 +++
>  arch/arm/plat-omap/include/plat/dmtimer.h  |    2 ++
>  2 files changed, 5 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> index 79a8601..ee57742 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> @@ -25,6 +25,7 @@
>  #include <plat/gpio.h>
>  #include <plat/dma.h>
>  #include <plat/mcspi.h>
> +#include <plat/dmtimer.h>
>  
>  #include "omap_hwmod_common_data.h"
>  
> @@ -3940,6 +3941,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,

Please use tab and align '=' with above lines.

>  };
>  
>  static struct omap_hwmod_class_sysconfig omap44xx_timer_sysc = {
> @@ -3955,6 +3957,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,

ditto

>  };
>  
>  /* timer1 */
> diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
> index d6c70d2..05a967e 100644
> --- a/arch/arm/plat-omap/include/plat/dmtimer.h
> +++ b/arch/arm/plat-omap/include/plat/dmtimer.h
> @@ -55,6 +55,8 @@
>   * in OMAP4 can be distinguished.
>   */
>  #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;
>  extern struct sys_timer omap_timer;
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v11 5/8] OMAP: dmtimer: platform driver
  2011-02-24 11:26 ` [PATCH v11 5/8] OMAP: dmtimer: platform driver Tarun Kanti DebBarma
@ 2011-03-04  0:35   ` Kevin Hilman
  2011-03-04  9:07     ` DebBarma, Tarun Kanti
  2011-03-04  1:29   ` Kevin Hilman
  1 sibling, 1 reply; 44+ messages in thread
From: Kevin Hilman @ 2011-03-04  0:35 UTC (permalink / raw)
  To: Tarun Kanti DebBarma; +Cc: linux-omap, Thara Gopinath

Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:

> From: Thara Gopinath <thara@ti.com>
>
> 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>

Some locking issues below...

> ---
>  arch/arm/plat-omap/dmtimer.c              |  167 ++++++++++++++++++++++++++++-
>  arch/arm/plat-omap/include/plat/dmtimer.h |    2 +
>  2 files changed, 168 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
> index 1bfaf09..bfe6fd3 100644
> --- a/arch/arm/plat-omap/dmtimer.c
> +++ b/arch/arm/plat-omap/dmtimer.c
> @@ -43,6 +43,9 @@
>  #include <linux/delay.h>
>  #include <linux/io.h>
>  #include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/err.h>
> +#include <linux/platform_device.h>
>  #include <mach/hardware.h>
>  #include <plat/dmtimer.h>
>  #include <mach/irqs.h>
> @@ -257,7 +260,8 @@ 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);

This spinlock is being used as a mutex.  Please use a mutex instead.

>  /*
>   * Reads timer registers in posted and non-posted mode. The posted mode bit
> @@ -689,6 +693,167 @@ 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;
> +	}
> +
> +	spin_lock_irqsave(&dm_timer_lock, flags);

Why do you need IRQ versions of the locks?   This lock is never used in
interrupt context.

Kevin

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

* Re: [PATCH v11 4/8] OMAP2+: dmtimer: convert to platform devices
  2011-02-24 11:26 ` [PATCH v11 4/8] OMAP2+: dmtimer: convert " Tarun Kanti DebBarma
@ 2011-03-04  1:01   ` Kevin Hilman
  2011-03-04  6:34     ` DebBarma, Tarun Kanti
  0 siblings, 1 reply; 44+ messages in thread
From: Kevin Hilman @ 2011-03-04  1:01 UTC (permalink / raw)
  To: Tarun Kanti DebBarma; +Cc: linux-omap, Thara Gopinath

Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:

> 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. It also provides
> provision to access timers during early boot when pm_runtime framework
> is not completely up and running.
>
> 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/Makefile  |    2 +-
>  arch/arm/mach-omap2/dmtimer.c |  199 +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 200 insertions(+), 1 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/dmtimer.c
>
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index 1c3635d..7e5014b 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -4,7 +4,7 @@
>  
>  # Common support
>  obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \
> -	 common.o gpio.o dma.o wd_timer.o
> +	 common.o gpio.o dma.o wd_timer.o dmtimer.o
>  
>  omap-2-3-common				= irq.o sdrc.o
>  hwmod-common				= omap_hwmod.o \
> diff --git a/arch/arm/mach-omap2/dmtimer.c b/arch/arm/mach-omap2/dmtimer.c
> new file mode 100644
> index 0000000..00cebe9
> --- /dev/null
> +++ b/arch/arm/mach-omap2/dmtimer.c
> @@ -0,0 +1,199 @@
> +/**
> + * OMAP2+ Dual-Mode Timers - platform device registration
> + *
> + * Contains first level initialization routines which extracts timers
> + * information from hwmod database and registers with linux device model.
> + * It also has low level function to change 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/err.h>
> +#include <linux/slab.h>
> +
> +#include <plat/dmtimer.h>
> +#include <plat/omap_device.h>
> +#include <plat/cpu.h>
> +
> +/*
> + * 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

These should be in the driver along with all the other register offsets.

This device code is already setting the IP rev type, the driver can
handle the rest.

> +static int early_timer_count __initdata = 1;

dumb question: why does this start at 1?

> +struct dm_timer_data {
> +	struct omap_device *od;
> +	struct dmtimer_platform_data *pdata;
> +	struct list_head node;
> +};
> +
> +static __initdata LIST_HEAD(dm_timer_data_list);
> +
> +/**
> + * omap2_dm_timer_set_src - change the timer input clock source
> + * @pdev:	timer platform device pointer
> + * @timer_clk:	current clock source
> + * @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 = clk_get(&pdev->dev, "fck");
> +	struct clk *new_fclk;
> +	char *fclk_name = "32k_ck"; /* default name */
> +
> +	switch (source) {
> +	case OMAP_TIMER_SRC_SYS_CLK:
> +		fclk_name = "sys_ck";
> +		break;
> +
> +	case OMAP_TIMER_SRC_32_KHZ:
> +		fclk_name = "32k_ck";
> +		break;
> +
> +	case OMAP_TIMER_SRC_EXT_CLK:
> +		if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_1) {
> +			fclk_name = "alt_ck";
> +			break;
> +		}
> +		dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
> +			__func__, __LINE__);
> +		return -EINVAL;
> +	}
> +
> +	if (IS_ERR_OR_NULL(fclk)) {
> +		dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
> +			__func__, __LINE__);
> +		return -EINVAL;
> +	}
> +
> +	new_fclk = clk_get(&pdev->dev, fclk_name);
> +	if (IS_ERR_OR_NULL(new_fclk)) {
> +		dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
> +			__func__, __LINE__, 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__, 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 dm_timer_data *timer_data = NULL;
> +
> +	pr_debug("%s: %s\n", __func__, oh->name);
> +
> +	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);

Memory leak.

This needs to be free'd after omap_device_build().  The platform_device
core makes a copy of the pdata (via kmemdup.)

> +	if (!pdata) {
> +		pr_err("%s: No memory for [%s]\n", __func__, oh->name);
> +		return -ENOMEM;
> +	}
> +
> +	pdata->is_early_init = 1;
> +	pdata->is_omap16xx = 0;
> +	pdata->dm_timer_reset = NULL;
> +	pdata->set_timer_src = omap2_dm_timer_set_src;
> +
> +	pdata->timer_ip_type = oh->class->rev;
> +	if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_2) {
> +		pdata->func_offset = VERSION2_TIMER_WAKEUP_EN_REG_OFFSET;
> +		pdata->intr_offset = VERSION2_TIMER_STAT_REG_OFFSET;
> +	} else {
> +		pdata->func_offset = 0;
> +		pdata->intr_offset = 0;
> +	}
> +
> +	/*
> +	 * 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);
> +
> +	/* do registration of timer12 on GP device only */
> +	if (id == 12 && omap_type() != OMAP2_DEVICE_TYPE_GP)
> +		return ret;

hmm, grumble

Is this true on OMAP4?  I thought GPT12 was not accessible on OMAP4 even
on GP devices.

As I've said a few times before, what we need here is some sort of
"capabilities" flag for each timer in the hwmod.  In addition to this
"secure-mode only" feature, there are other capabilities such as 1ms
timers, PWM capable, etc.

> +	od = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
> +			omap2_dmtimer_latency,
> +			ARRAY_SIZE(omap2_dmtimer_latency),
> +			pdata->is_early_init);
> +
> +	if (IS_ERR(od)) {
> +		pr_err("%s: Can't build omap_device for %s: %s.\n",
> +			__func__, name, oh->name);
> +		ret = -EINVAL;
> +	} else if (pdata->is_early_init)
> +		early_timer_count++;
> +
> +	timer_data = kzalloc(sizeof(*timer_data), GFP_KERNEL);
> +	if (!timer_data) {
> +		pr_debug("%s: no memory for dm_timer_data\n",
> +				__func__);
> +		return -ENOMEM;
> +	}
> +
> +	/* store od and pdata to be used later during normal initialization */
> +	timer_data->od = od;
> +	timer_data->pdata = pdata;
> +	list_add_tail(&timer_data->node, &dm_timer_data_list);
> +
> +	return ret;
> +}

Kevin

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

* Re: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
  2011-02-24 11:26 ` [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support Tarun Kanti DebBarma
@ 2011-03-04  1:22   ` Kevin Hilman
  2011-03-04  9:18     ` DebBarma, Tarun Kanti
  2011-03-04 17:28     ` Tony Lindgren
  0 siblings, 2 replies; 44+ messages in thread
From: Kevin Hilman @ 2011-03-04  1:22 UTC (permalink / raw)
  To: Tarun Kanti DebBarma; +Cc: linux-omap, Partha Basak

Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:

> Add pm_runtime support to dmtimer. Since dmtimer is used during
> early boot before pm_runtime is initialized completely there are
> provisions to enable/disable clocks directly in the code during
> early boot.

I'm still not crazy about the duplicate logic (both early & normal) in
all the enable/disable functions.

As I've suggested in the past, why not just do a clk_get, clk_enable in
when the early timers are initialized, then do a clk_disable, clk_put()
as soon as the "normal" device is ready and PM runtime is enabled.

That will greatly simplify the code and eliminate the unnecessary checks
for ->is_early_device which will always be false except for in early
boot (when these functions are not likely to be called anyways.)

> 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 |   63 ++++++++++++++++++++++++++++++++++++------
>  1 files changed, 54 insertions(+), 9 deletions(-)
>
> diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
> index 53f5205..fcac422 100644
> --- a/arch/arm/plat-omap/dmtimer.c
> +++ b/arch/arm/plat-omap/dmtimer.c
> @@ -39,6 +39,7 @@
>  #include <linux/delay.h>
>  #include <linux/io.h>
>  #include <linux/slab.h>
> +#include <linux/pm_runtime.h>
>  #include <linux/err.h>
>  #include <linux/platform_device.h>
>  #include <plat/dmtimer.h>
> @@ -211,13 +212,16 @@ static 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))) {
> -		dev_err(&timer->pdev->dev, ": No fclk handle.\n");
> -		return;
> +	if (!pdata->is_omap16xx) {

Is this 'is_omap16xx' really needed here?  If the clk_get fails, set
timer->fclk to NULL, and any other users of fclk should just check the
validity of timer->fclk.

> +		timer->fclk = clk_get(&timer->pdev->dev, "fck");
> +		if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
> +			dev_err(&timer->pdev->dev, ": No fclk handle.\n");
> +			return;
> +		}
>  	}
>  
> -	omap_dm_timer_enable(timer);
> +	if (!pdata->is_omap16xx)
> +		omap_dm_timer_enable(timer);

I don't think this if is needed, as runtime PM calls will essentially be
nops on OMAP1 anyways.

>  	if (pdata->dm_timer_reset)
>  		pdata->dm_timer_reset(timer);
> @@ -292,10 +296,22 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_free);
>  
>  void omap_dm_timer_enable(struct omap_dm_timer *timer)
>  {
> +	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
> +
>  	if (timer->enabled)
>  		return;
>  
> -	clk_enable(timer->fclk);
> +	if (unlikely(pdata->is_early_init)) {
> +		clk_enable(timer->fclk);
> +		timer->enabled = 1;
> +		return;
> +	}
> +
> +	if (pm_runtime_get_sync(&timer->pdev->dev) < 0) {
> +		dev_err(&timer->pdev->dev, "%s: pm_runtime_get_sync() FAILED\n",
> +			__func__);
> +		return;
> +	}
>  
>  	timer->enabled = 1;
>  }

Taking my above suggestion, this can be simplified to:

void omap_dm_timer_enable(struct omap_dm_timer *timer)
{
	pm_runtime_get_sync(&timer->pdev->dev);
}

Note that with runtime PM, the ->enabled flag is no longer needed
either, as you can simply check pm_runtime_suspended(dev) instead.

> @@ -303,10 +319,22 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
>  
>  void omap_dm_timer_disable(struct omap_dm_timer *timer)
>  {
> +	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
> +
>  	if (!timer->enabled)
>  		return;
>  
> -	clk_disable(timer->fclk);
> +	if (unlikely(pdata->is_early_init)) {
> +		clk_disable(timer->fclk);
> +		timer->enabled = 0;
> +		return;
> +	}
> +
> +	if (pm_runtime_put_sync(&timer->pdev->dev) < 0) {
> +		dev_err(&timer->pdev->dev, "%s: pm_runtime_put_sync() FAILED\n",
> +			__func__);
> +		return;
> +	}
>  
>  	timer->enabled = 0;
>  }

Likewise, this becomes

void omap_dm_timer_disable(struct omap_dm_timer *timer)
{
	pm_runtime_put_sync(&timer->pdev->dev);
}

> @@ -425,10 +453,12 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
>  	if (source < 0 || source >= 3)
>  		return -EINVAL;
>  
> -	omap_dm_timer_disable(timer);
> +	if (!pdata->is_omap16xx)

drop the if

> +		omap_dm_timer_disable(timer);
>  	/* change the timer clock source */
>  	ret = pdata->set_timer_src(timer->pdev, source);
> -	omap_dm_timer_enable(timer);
> +	if (!pdata->is_omap16xx)

and this one,

and with that, there are no users of is_omap16xx in this patch.

Kevin


> +		omap_dm_timer_enable(timer);
>  
>  	/*
>  	 * When the functional clock disappears, too quick writes seem
> @@ -600,11 +630,26 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
>  		return -ENODEV;
>  	}
>  
> +	/*
> +	 * OMAP2+
> +	 * Early timers are already registered and in list.
> +	 * What we need to do during second phase of probe
> +	 * is to assign the newly allocated/configured pdev
> +	 * to timer->pdev. We also call pm_runtime_enable()
> +	 * for each device because it could not be called
> +	 * during early boot because pm_runtime framework
> +	 * was not yet up and running.
> +	 */
>  	spin_lock_irqsave(&dm_timer_lock, flags);
>  	list_for_each_entry(timer, &omap_timer_list, node)
>  		if (!pdata->is_early_init && timer->id == pdev->id) {
>  			timer->pdev = pdev;
>  			spin_unlock_irqrestore(&dm_timer_lock, flags);
> +			pm_runtime_enable(&pdev->dev);
> +			/* update PM runtime for active early timers */
> +			if (timer->reserved)
> +				pm_runtime_get_sync(&pdev->dev);
> +
>  			dev_dbg(&pdev->dev, "Regular Probed\n");
>  			return 0;
>  		}

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

* Re: [PATCH v11 6/8] dmtimer: switch-over to platform device driver
  2011-02-24 11:26 ` [PATCH v11 6/8] dmtimer: switch-over to platform device driver Tarun Kanti DebBarma
@ 2011-03-04  1:25   ` Kevin Hilman
  2011-03-04  6:57     ` DebBarma, Tarun Kanti
  2011-03-04 17:23   ` Tony Lindgren
  1 sibling, 1 reply; 44+ messages in thread
From: Kevin Hilman @ 2011-03-04  1:25 UTC (permalink / raw)
  To: Tarun Kanti DebBarma; +Cc: linux-omap

Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:

> switch-over to platform device driver through following changes:
> (a) initiate dmtimer early initialization from omap2_gp_timer_init()
> in timer-gp.c. This is equivalent of timer_init()->timer->init().
> (b) modify plat-omap/dmtimer routines to use new register map and
> platform data.
>
> Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
> Acked-by: Cousson, Benoit <b-cousson@ti.com>

[...]

> @@ -507,20 +394,22 @@ 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;
>  
>  	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
> +
> +		if (!pdata->is_omap16xx) {
> +			/* 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);
> +		}

Can't this 'is_omap16xx' check just be using the IP revision?


>  	}

Kevin

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

* Re: [PATCH v11 5/8] OMAP: dmtimer: platform driver
  2011-02-24 11:26 ` [PATCH v11 5/8] OMAP: dmtimer: platform driver Tarun Kanti DebBarma
  2011-03-04  0:35   ` Kevin Hilman
@ 2011-03-04  1:29   ` Kevin Hilman
  2011-03-04  6:56     ` DebBarma, Tarun Kanti
  1 sibling, 1 reply; 44+ messages in thread
From: Kevin Hilman @ 2011-03-04  1:29 UTC (permalink / raw)
  To: Tarun Kanti DebBarma; +Cc: linux-omap, Thara Gopinath

Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:

> From: Thara Gopinath <thara@ti.com>
>
> 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>

[...]

> +/**
> + * 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;
> +	}
> +
> +	spin_lock_irqsave(&dm_timer_lock, flags);
> +	list_for_each_entry(timer, &omap_timer_list, node)
> +		if (!pdata->is_early_init && timer->id == pdev->id) {
> +			timer->pdev = pdev;
> +			spin_unlock_irqrestore(&dm_timer_lock, flags);
> +			dev_dbg(&pdev->dev, "Regular Probed\n");
> +			return 0;
> +		}
> +	spin_unlock_irqrestore(&dm_timer_lock, flags);
> +
> +	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;
> +	}
> +
> +	/*
> +	 * Following func pointers are required by OMAP1's reset code
> +	 * in mach-omap1/dmtimer.c to access to low level read/write.
> +	 */
> +	if (pdata->is_omap16xx) {
> +		pdata->dm_timer_read_reg = omap_dm_timer_read_reg;
> +		pdata->dm_timer_write_reg = omap_dm_timer_write_reg;
> +		pdata->is_early_init = 0;
> +	}

Can this 'is_omap16xx' check be replaced with an IP revision check?

Kevin


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

* RE: [PATCH v11 2/8] OMAP4: hwmod data: add dmtimer version information
  2011-03-04  0:24   ` Kevin Hilman
@ 2011-03-04  5:49     ` DebBarma, Tarun Kanti
  2011-03-04 11:16     ` Cousson, Benoit
  1 sibling, 0 replies; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-04  5:49 UTC (permalink / raw)
  To: Hilman, Kevin; +Cc: linux-omap@vger.kernel.org

> -----Original Message-----
> From: Hilman, Kevin
> Sent: Friday, March 04, 2011 5:54 AM
> To: DebBarma, Tarun Kanti
> Cc: linux-omap@vger.kernel.org
> Subject: Re: [PATCH v11 2/8] OMAP4: hwmod data: add dmtimer version
> information
> 
> Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:
> 
> > 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>
> 
> Minor comment below, also needs an ack from Benoît...
Ok.
> 
> > ---
> >  arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    3 +++
> >  arch/arm/plat-omap/include/plat/dmtimer.h  |    2 ++
> >  2 files changed, 5 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-
> omap2/omap_hwmod_44xx_data.c
> > index 79a8601..ee57742 100644
> > --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> > +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> > @@ -25,6 +25,7 @@
> >  #include <plat/gpio.h>
> >  #include <plat/dma.h>
> >  #include <plat/mcspi.h>
> > +#include <plat/dmtimer.h>
> >
> >  #include "omap_hwmod_common_data.h"
> >
> > @@ -3940,6 +3941,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,
> 
> Please use tab and align '=' with above lines.
Yes.

> 
> >  };
> >
> >  static struct omap_hwmod_class_sysconfig omap44xx_timer_sysc = {
> > @@ -3955,6 +3957,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,
> 
> ditto
Yes.
> 
> >  };
> >
> >  /* timer1 */
> > diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-
> omap/include/plat/dmtimer.h
> > index d6c70d2..05a967e 100644
> > --- a/arch/arm/plat-omap/include/plat/dmtimer.h
> > +++ b/arch/arm/plat-omap/include/plat/dmtimer.h
> > @@ -55,6 +55,8 @@
> >   * in OMAP4 can be distinguished.
> >   */
> >  #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;
> >  extern struct sys_timer omap_timer;
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* RE: [PATCH v11 4/8] OMAP2+: dmtimer: convert to platform devices
  2011-03-04  1:01   ` Kevin Hilman
@ 2011-03-04  6:34     ` DebBarma, Tarun Kanti
  2011-03-04 17:25       ` Kevin Hilman
  0 siblings, 1 reply; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-04  6:34 UTC (permalink / raw)
  To: Hilman, Kevin; +Cc: linux-omap@vger.kernel.org, Gopinath, Thara

> -----Original Message-----
> From: Hilman, Kevin
> Sent: Friday, March 04, 2011 6:32 AM
> To: DebBarma, Tarun Kanti
> Cc: linux-omap@vger.kernel.org; Gopinath, Thara
> Subject: Re: [PATCH v11 4/8] OMAP2+: dmtimer: convert to platform devices
> 
> Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:
> 
> > 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. It also provides
> > provision to access timers during early boot when pm_runtime framework
> > is not completely up and running.
> >
> > 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/Makefile  |    2 +-
> >  arch/arm/mach-omap2/dmtimer.c |  199
> +++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 200 insertions(+), 1 deletions(-)
> >  create mode 100644 arch/arm/mach-omap2/dmtimer.c
> >
> > diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> > index 1c3635d..7e5014b 100644
> > --- a/arch/arm/mach-omap2/Makefile
> > +++ b/arch/arm/mach-omap2/Makefile
> > @@ -4,7 +4,7 @@
> >
> >  # Common support
> >  obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o
> pm.o \
> > -	 common.o gpio.o dma.o wd_timer.o
> > +	 common.o gpio.o dma.o wd_timer.o dmtimer.o
> >
> >  omap-2-3-common				= irq.o sdrc.o
> >  hwmod-common				= omap_hwmod.o \
> > diff --git a/arch/arm/mach-omap2/dmtimer.c b/arch/arm/mach-
> omap2/dmtimer.c
> > new file mode 100644
> > index 0000000..00cebe9
> > --- /dev/null
> > +++ b/arch/arm/mach-omap2/dmtimer.c
> > @@ -0,0 +1,199 @@
> > +/**
> > + * OMAP2+ Dual-Mode Timers - platform device registration
> > + *
> > + * Contains first level initialization routines which extracts timers
> > + * information from hwmod database and registers with linux device
> model.
> > + * It also has low level function to change 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/err.h>
> > +#include <linux/slab.h>
> > +
> > +#include <plat/dmtimer.h>
> > +#include <plat/omap_device.h>
> > +#include <plat/cpu.h>
> > +
> > +/*
> > + * 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
> 
> These should be in the driver along with all the other register offsets.
> 
> This device code is already setting the IP rev type, the driver can
> handle the rest.
Ok, I will make the changes.

> 
> > +static int early_timer_count __initdata = 1;
> 
> dumb question: why does this start at 1?
> 
This is related to one of your early comments where this variable is used:
early_platform_driver_probe("earlytimer", early_timer_count, 0);
It was passed as early_timer_count + 1, as static variable starts at 0.
So it is just to avoid this addition of 1.

> > +struct dm_timer_data {
> > +	struct omap_device *od;
> > +	struct dmtimer_platform_data *pdata;
> > +	struct list_head node;
> > +};
> > +
> > +static __initdata LIST_HEAD(dm_timer_data_list);
> > +
> > +/**
> > + * omap2_dm_timer_set_src - change the timer input clock source
> > + * @pdev:	timer platform device pointer
> > + * @timer_clk:	current clock source
> > + * @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 = clk_get(&pdev->dev, "fck");
> > +	struct clk *new_fclk;
> > +	char *fclk_name = "32k_ck"; /* default name */
> > +
> > +	switch (source) {
> > +	case OMAP_TIMER_SRC_SYS_CLK:
> > +		fclk_name = "sys_ck";
> > +		break;
> > +
> > +	case OMAP_TIMER_SRC_32_KHZ:
> > +		fclk_name = "32k_ck";
> > +		break;
> > +
> > +	case OMAP_TIMER_SRC_EXT_CLK:
> > +		if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_1) {
> > +			fclk_name = "alt_ck";
> > +			break;
> > +		}
> > +		dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
> > +			__func__, __LINE__);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (IS_ERR_OR_NULL(fclk)) {
> > +		dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
> > +			__func__, __LINE__);
> > +		return -EINVAL;
> > +	}
> > +
> > +	new_fclk = clk_get(&pdev->dev, fclk_name);
> > +	if (IS_ERR_OR_NULL(new_fclk)) {
> > +		dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
> > +			__func__, __LINE__, 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__, 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 dm_timer_data *timer_data = NULL;
> > +
> > +	pr_debug("%s: %s\n", __func__, oh->name);
> > +
> > +	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
> 
> Memory leak.
> 
> This needs to be free'd after omap_device_build().  The platform_device
> core makes a copy of the pdata (via kmemdup.)
Yes, it was there and I missed it while implementing the double registration
Issue :( Thanks!

> 
> > +	if (!pdata) {
> > +		pr_err("%s: No memory for [%s]\n", __func__, oh->name);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	pdata->is_early_init = 1;
> > +	pdata->is_omap16xx = 0;
> > +	pdata->dm_timer_reset = NULL;
> > +	pdata->set_timer_src = omap2_dm_timer_set_src;
> > +
> > +	pdata->timer_ip_type = oh->class->rev;
> > +	if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_2) {
> > +		pdata->func_offset = VERSION2_TIMER_WAKEUP_EN_REG_OFFSET;
> > +		pdata->intr_offset = VERSION2_TIMER_STAT_REG_OFFSET;
> > +	} else {
> > +		pdata->func_offset = 0;
> > +		pdata->intr_offset = 0;
> > +	}
> > +
> > +	/*
> > +	 * 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);
> > +
> > +	/* do registration of timer12 on GP device only */
> > +	if (id == 12 && omap_type() != OMAP2_DEVICE_TYPE_GP)
> > +		return ret;
> 
> hmm, grumble
> 
> Is this true on OMAP4?  I thought GPT12 was not accessible on OMAP4 even
> on GP devices.
On OMAP4 hwmod database there is no entry for GPT12.
So, this condition would NOT be applicable to OMAP4 at all as I understand.
Of course, as I see it the comment is not very clear and I can change that.

> 
> As I've said a few times before, what we need here is some sort of
> "capabilities" flag for each timer in the hwmod.  In addition to this
> "secure-mode only" feature, there are other capabilities such as 1ms
> timers, PWM capable, etc.
I can consider this. However I feel this would take sometime to align on the
Final choice/option of implementation.
So, is the above implementation acceptable for now? 

> 
> > +	od = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
> > +			omap2_dmtimer_latency,
> > +			ARRAY_SIZE(omap2_dmtimer_latency),
> > +			pdata->is_early_init);
> > +
> > +	if (IS_ERR(od)) {
> > +		pr_err("%s: Can't build omap_device for %s: %s.\n",
> > +			__func__, name, oh->name);
> > +		ret = -EINVAL;
> > +	} else if (pdata->is_early_init)
> > +		early_timer_count++;
> > +
> > +	timer_data = kzalloc(sizeof(*timer_data), GFP_KERNEL);
> > +	if (!timer_data) {
> > +		pr_debug("%s: no memory for dm_timer_data\n",
> > +				__func__);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	/* store od and pdata to be used later during normal initialization
> */
> > +	timer_data->od = od;
> > +	timer_data->pdata = pdata;
> > +	list_add_tail(&timer_data->node, &dm_timer_data_list);
> > +
> > +	return ret;
> > +}
> 
> Kevin

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

* RE: [PATCH v11 5/8] OMAP: dmtimer: platform driver
  2011-03-04  1:29   ` Kevin Hilman
@ 2011-03-04  6:56     ` DebBarma, Tarun Kanti
  2011-03-04 16:53       ` Kevin Hilman
  0 siblings, 1 reply; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-04  6:56 UTC (permalink / raw)
  To: Hilman, Kevin; +Cc: linux-omap@vger.kernel.org, Gopinath, Thara

> -----Original Message-----
> From: Hilman, Kevin
> Sent: Friday, March 04, 2011 6:59 AM
> To: DebBarma, Tarun Kanti
> Cc: linux-omap@vger.kernel.org; Gopinath, Thara
> Subject: Re: [PATCH v11 5/8] OMAP: dmtimer: platform driver
> 
> Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:
> 
> > From: Thara Gopinath <thara@ti.com>
> >
> > 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>
> 
> [...]
> 
> > +/**
> > + * 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;
> > +	}
> > +
> > +	spin_lock_irqsave(&dm_timer_lock, flags);
> > +	list_for_each_entry(timer, &omap_timer_list, node)
> > +		if (!pdata->is_early_init && timer->id == pdev->id) {
> > +			timer->pdev = pdev;
> > +			spin_unlock_irqrestore(&dm_timer_lock, flags);
> > +			dev_dbg(&pdev->dev, "Regular Probed\n");
> > +			return 0;
> > +		}
> > +	spin_unlock_irqrestore(&dm_timer_lock, flags);
> > +
> > +	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;
> > +	}
> > +
> > +	/*
> > +	 * Following func pointers are required by OMAP1's reset code
> > +	 * in mach-omap1/dmtimer.c to access to low level read/write.
> > +	 */
> > +	if (pdata->is_omap16xx) {
> > +		pdata->dm_timer_read_reg = omap_dm_timer_read_reg;
> > +		pdata->dm_timer_write_reg = omap_dm_timer_write_reg;
> > +		pdata->is_early_init = 0;
> > +	}
> 
> Can this 'is_omap16xx' check be replaced with an IP revision check?
Hmm, this not really!
Unless we introduce a new version to indicate OMAP1.
If this is what you mean I will make the change.

> 
> Kevin


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

* RE: [PATCH v11 6/8] dmtimer: switch-over to platform device driver
  2011-03-04  1:25   ` Kevin Hilman
@ 2011-03-04  6:57     ` DebBarma, Tarun Kanti
  0 siblings, 0 replies; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-04  6:57 UTC (permalink / raw)
  To: Hilman, Kevin; +Cc: linux-omap@vger.kernel.org

> -----Original Message-----
> From: Hilman, Kevin
> Sent: Friday, March 04, 2011 6:56 AM
> To: DebBarma, Tarun Kanti
> Cc: linux-omap@vger.kernel.org
> Subject: Re: [PATCH v11 6/8] dmtimer: switch-over to platform device
> driver
> 
> Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:
> 
> > switch-over to platform device driver through following changes:
> > (a) initiate dmtimer early initialization from omap2_gp_timer_init()
> > in timer-gp.c. This is equivalent of timer_init()->timer->init().
> > (b) modify plat-omap/dmtimer routines to use new register map and
> > platform data.
> >
> > Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com>
> > Acked-by: Cousson, Benoit <b-cousson@ti.com>
> 
> [...]
> 
> > @@ -507,20 +394,22 @@ 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;
> >
> >  	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
> > +
> > +		if (!pdata->is_omap16xx) {
> > +			/* 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);
> > +		}
> 
> Can't this 'is_omap16xx' check just be using the IP revision?
OK, I will introduce a new version to cover this.

> 
> 
> >  	}
> 
> Kevin

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

* RE: [PATCH v11 5/8] OMAP: dmtimer: platform driver
  2011-03-04  0:35   ` Kevin Hilman
@ 2011-03-04  9:07     ` DebBarma, Tarun Kanti
  0 siblings, 0 replies; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-04  9:07 UTC (permalink / raw)
  To: Hilman, Kevin; +Cc: linux-omap@vger.kernel.org, Gopinath, Thara

> -----Original Message-----
> From: Hilman, Kevin
> Sent: Friday, March 04, 2011 6:05 AM
> To: DebBarma, Tarun Kanti
> Cc: linux-omap@vger.kernel.org; Gopinath, Thara
> Subject: Re: [PATCH v11 5/8] OMAP: dmtimer: platform driver
> 
> Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:
> 
> > From: Thara Gopinath <thara@ti.com>
> >
> > 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>
> 
> Some locking issues below...
> 
> > ---
> >  arch/arm/plat-omap/dmtimer.c              |  167
> ++++++++++++++++++++++++++++-
> >  arch/arm/plat-omap/include/plat/dmtimer.h |    2 +
> >  2 files changed, 168 insertions(+), 1 deletions(-)
> >
> > diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
> > index 1bfaf09..bfe6fd3 100644
> > --- a/arch/arm/plat-omap/dmtimer.c
> > +++ b/arch/arm/plat-omap/dmtimer.c
> > @@ -43,6 +43,9 @@
> >  #include <linux/delay.h>
> >  #include <linux/io.h>
> >  #include <linux/module.h>
> > +#include <linux/slab.h>
> > +#include <linux/err.h>
> > +#include <linux/platform_device.h>
> >  #include <mach/hardware.h>
> >  #include <plat/dmtimer.h>
> >  #include <mach/irqs.h>
> > @@ -257,7 +260,8 @@ 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);
> 
> This spinlock is being used as a mutex.  Please use a mutex instead.
Alright, I will use mutex instead.

> 
> >  /*
> >   * Reads timer registers in posted and non-posted mode. The posted mode
> bit
> > @@ -689,6 +693,167 @@ 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;
> > +	}
> > +
> > +	spin_lock_irqsave(&dm_timer_lock, flags);
> 
> Why do you need IRQ versions of the locks?   This lock is never used in
> interrupt context.
Yes.
> 
> Kevin

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

* RE: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
  2011-03-04  1:22   ` Kevin Hilman
@ 2011-03-04  9:18     ` DebBarma, Tarun Kanti
  2011-03-04 17:28     ` Tony Lindgren
  1 sibling, 0 replies; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-04  9:18 UTC (permalink / raw)
  To: Hilman, Kevin; +Cc: linux-omap@vger.kernel.org, Basak, Partha

> -----Original Message-----
> From: Hilman, Kevin
> Sent: Friday, March 04, 2011 6:53 AM
> To: DebBarma, Tarun Kanti
> Cc: linux-omap@vger.kernel.org; Basak, Partha
> Subject: Re: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
> 
> Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:
> 
> > Add pm_runtime support to dmtimer. Since dmtimer is used during
> > early boot before pm_runtime is initialized completely there are
> > provisions to enable/disable clocks directly in the code during
> > early boot.
> 
> I'm still not crazy about the duplicate logic (both early & normal) in
> all the enable/disable functions.
> 
> As I've suggested in the past, why not just do a clk_get, clk_enable in
> when the early timers are initialized, then do a clk_disable, clk_put()
> as soon as the "normal" device is ready and PM runtime is enabled.
> 
> That will greatly simplify the code and eliminate the unnecessary checks
> for ->is_early_device which will always be false except for in early
> boot (when these functions are not likely to be called anyways.)
I will do the cleanup.

> 
> > 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 |   63
> ++++++++++++++++++++++++++++++++++++------
> >  1 files changed, 54 insertions(+), 9 deletions(-)
> >
> > diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
> > index 53f5205..fcac422 100644
> > --- a/arch/arm/plat-omap/dmtimer.c
> > +++ b/arch/arm/plat-omap/dmtimer.c
> > @@ -39,6 +39,7 @@
> >  #include <linux/delay.h>
> >  #include <linux/io.h>
> >  #include <linux/slab.h>
> > +#include <linux/pm_runtime.h>
> >  #include <linux/err.h>
> >  #include <linux/platform_device.h>
> >  #include <plat/dmtimer.h>
> > @@ -211,13 +212,16 @@ static 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))) {
> > -		dev_err(&timer->pdev->dev, ": No fclk handle.\n");
> > -		return;
> > +	if (!pdata->is_omap16xx) {
> 
> Is this 'is_omap16xx' really needed here?  If the clk_get fails, set
> timer->fclk to NULL, and any other users of fclk should just check the
> validity of timer->fclk.
OK.

> 
> > +		timer->fclk = clk_get(&timer->pdev->dev, "fck");
> > +		if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
> > +			dev_err(&timer->pdev->dev, ": No fclk handle.\n");
> > +			return;
> > +		}
> >  	}
> >
> > -	omap_dm_timer_enable(timer);
> > +	if (!pdata->is_omap16xx)
> > +		omap_dm_timer_enable(timer);
> 
> I don't think this if is needed, as runtime PM calls will essentially be
> nops on OMAP1 anyways.
Right, I will remove the check.

> 
> >  	if (pdata->dm_timer_reset)
> >  		pdata->dm_timer_reset(timer);
> > @@ -292,10 +296,22 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_free);
> >
> >  void omap_dm_timer_enable(struct omap_dm_timer *timer)
> >  {
> > +	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
> > +
> >  	if (timer->enabled)
> >  		return;
> >
> > -	clk_enable(timer->fclk);
> > +	if (unlikely(pdata->is_early_init)) {
> > +		clk_enable(timer->fclk);
> > +		timer->enabled = 1;
> > +		return;
> > +	}
> > +
> > +	if (pm_runtime_get_sync(&timer->pdev->dev) < 0) {
> > +		dev_err(&timer->pdev->dev, "%s: pm_runtime_get_sync() FAILED\n",
> > +			__func__);
> > +		return;
> > +	}
> >
> >  	timer->enabled = 1;
> >  }
> 
> Taking my above suggestion, this can be simplified to:
> 
> void omap_dm_timer_enable(struct omap_dm_timer *timer)
> {
> 	pm_runtime_get_sync(&timer->pdev->dev);
> }
> 
> Note that with runtime PM, the ->enabled flag is no longer needed
> either, as you can simply check pm_runtime_suspended(dev) instead.
Sounds good!

> 
> > @@ -303,10 +319,22 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
> >
> >  void omap_dm_timer_disable(struct omap_dm_timer *timer)
> >  {
> > +	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
> > +
> >  	if (!timer->enabled)
> >  		return;
> >
> > -	clk_disable(timer->fclk);
> > +	if (unlikely(pdata->is_early_init)) {
> > +		clk_disable(timer->fclk);
> > +		timer->enabled = 0;
> > +		return;
> > +	}
> > +
> > +	if (pm_runtime_put_sync(&timer->pdev->dev) < 0) {
> > +		dev_err(&timer->pdev->dev, "%s: pm_runtime_put_sync() FAILED\n",
> > +			__func__);
> > +		return;
> > +	}
> >
> >  	timer->enabled = 0;
> >  }
> 
> Likewise, this becomes
> 
> void omap_dm_timer_disable(struct omap_dm_timer *timer)
> {
> 	pm_runtime_put_sync(&timer->pdev->dev);
> }
Yes.

> 
> > @@ -425,10 +453,12 @@ int omap_dm_timer_set_source(struct omap_dm_timer
> *timer, int source)
> >  	if (source < 0 || source >= 3)
> >  		return -EINVAL;
> >
> > -	omap_dm_timer_disable(timer);
> > +	if (!pdata->is_omap16xx)
> 
> drop the if
Yes.

> 
> > +		omap_dm_timer_disable(timer);
> >  	/* change the timer clock source */
> >  	ret = pdata->set_timer_src(timer->pdev, source);
> > -	omap_dm_timer_enable(timer);
> > +	if (!pdata->is_omap16xx)
> 
> and this one,
> 
> and with that, there are no users of is_omap16xx in this patch.
Right!

> 
> Kevin
> 
> 
> > +		omap_dm_timer_enable(timer);
> >
> >  	/*
> >  	 * When the functional clock disappears, too quick writes seem
> > @@ -600,11 +630,26 @@ static int __devinit omap_dm_timer_probe(struct
> platform_device *pdev)
> >  		return -ENODEV;
> >  	}
> >
> > +	/*
> > +	 * OMAP2+
> > +	 * Early timers are already registered and in list.
> > +	 * What we need to do during second phase of probe
> > +	 * is to assign the newly allocated/configured pdev
> > +	 * to timer->pdev. We also call pm_runtime_enable()
> > +	 * for each device because it could not be called
> > +	 * during early boot because pm_runtime framework
> > +	 * was not yet up and running.
> > +	 */
> >  	spin_lock_irqsave(&dm_timer_lock, flags);
> >  	list_for_each_entry(timer, &omap_timer_list, node)
> >  		if (!pdata->is_early_init && timer->id == pdev->id) {
> >  			timer->pdev = pdev;
> >  			spin_unlock_irqrestore(&dm_timer_lock, flags);
> > +			pm_runtime_enable(&pdev->dev);
> > +			/* update PM runtime for active early timers */
> > +			if (timer->reserved)
> > +				pm_runtime_get_sync(&pdev->dev);
> > +
> >  			dev_dbg(&pdev->dev, "Regular Probed\n");
> >  			return 0;
> >  		}

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

* Re: [PATCH v11 2/8] OMAP4: hwmod data: add dmtimer version information
  2011-03-04  0:24   ` Kevin Hilman
  2011-03-04  5:49     ` DebBarma, Tarun Kanti
@ 2011-03-04 11:16     ` Cousson, Benoit
  2011-03-07 11:19       ` DebBarma, Tarun Kanti
  1 sibling, 1 reply; 44+ messages in thread
From: Cousson, Benoit @ 2011-03-04 11:16 UTC (permalink / raw)
  To: Hilman, Kevin, DebBarma, Tarun Kanti; +Cc: linux-omap@vger.kernel.org

On 3/4/2011 1:24 AM, Hilman, Kevin wrote:
> Tarun Kanti DebBarma<tarun.kanti@ti.com>  writes:
>
>> 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>
>
> Minor comment below, also needs an ack from Benoît...

Oops, I missed that one.

Tarun,
I will be good to add me in Cc in order to avoid that.
In general it is always good to Cc the maintainers.

Once the tabs are fixed;
Acked-by: Benoit Cousson <b-cousson@ti.com>

>
>> ---
>>   arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    3 +++
>>   arch/arm/plat-omap/include/plat/dmtimer.h  |    2 ++
>>   2 files changed, 5 insertions(+), 0 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
>> index 79a8601..ee57742 100644
>> --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
>> +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
>> @@ -25,6 +25,7 @@
>>   #include<plat/gpio.h>
>>   #include<plat/dma.h>
>>   #include<plat/mcspi.h>
>> +#include<plat/dmtimer.h>
>>
>>   #include "omap_hwmod_common_data.h"
>>
>> @@ -3940,6 +3941,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,
>
> Please use tab and align '=' with above lines.
>
>>   };
>>
>>   static struct omap_hwmod_class_sysconfig omap44xx_timer_sysc = {
>> @@ -3955,6 +3957,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,
>
> ditto
>
>>   };
>>
>>   /* timer1 */
>> diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
>> index d6c70d2..05a967e 100644
>> --- a/arch/arm/plat-omap/include/plat/dmtimer.h
>> +++ b/arch/arm/plat-omap/include/plat/dmtimer.h
>> @@ -55,6 +55,8 @@
>>    * in OMAP4 can be distinguished.
>>    */
>>   #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;
>>   extern struct sys_timer omap_timer;
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v11 5/8] OMAP: dmtimer: platform driver
  2011-03-04  6:56     ` DebBarma, Tarun Kanti
@ 2011-03-04 16:53       ` Kevin Hilman
  2011-03-04 19:07         ` DebBarma, Tarun Kanti
  0 siblings, 1 reply; 44+ messages in thread
From: Kevin Hilman @ 2011-03-04 16:53 UTC (permalink / raw)
  To: DebBarma, Tarun Kanti; +Cc: linux-omap@vger.kernel.org, Gopinath, Thara

"DebBarma, Tarun Kanti" <tarun.kanti@ti.com> writes:

>> -----Original Message-----
>> From: Hilman, Kevin
>> Sent: Friday, March 04, 2011 6:59 AM
>> To: DebBarma, Tarun Kanti
>> Cc: linux-omap@vger.kernel.org; Gopinath, Thara
>> Subject: Re: [PATCH v11 5/8] OMAP: dmtimer: platform driver
>> 
>> Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:
>> 
>> > From: Thara Gopinath <thara@ti.com>
>> >
>> > 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>
>> 
>> [...]
>> 
>> > +/**
>> > + * 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;
>> > +	}
>> > +
>> > +	spin_lock_irqsave(&dm_timer_lock, flags);
>> > +	list_for_each_entry(timer, &omap_timer_list, node)
>> > +		if (!pdata->is_early_init && timer->id == pdev->id) {
>> > +			timer->pdev = pdev;
>> > +			spin_unlock_irqrestore(&dm_timer_lock, flags);
>> > +			dev_dbg(&pdev->dev, "Regular Probed\n");
>> > +			return 0;
>> > +		}
>> > +	spin_unlock_irqrestore(&dm_timer_lock, flags);
>> > +
>> > +	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;
>> > +	}
>> > +
>> > +	/*
>> > +	 * Following func pointers are required by OMAP1's reset code
>> > +	 * in mach-omap1/dmtimer.c to access to low level read/write.
>> > +	 */
>> > +	if (pdata->is_omap16xx) {
>> > +		pdata->dm_timer_read_reg = omap_dm_timer_read_reg;
>> > +		pdata->dm_timer_write_reg = omap_dm_timer_write_reg;
>> > +		pdata->is_early_init = 0;
>> > +	}
>> 
>> Can this 'is_omap16xx' check be replaced with an IP revision check?
> Hmm, this not really!
> Unless we introduce a new version to indicate OMAP1.

Ah, I see. Looks like the revision change was after OMAP3, I thought it
was after OMAP1.  Sorry.

> If this is what you mean I will make the change.

An OMAP1 check would make this more clear, but really the flag should be
a bool called something like "needs_manual_reset" since after all the
other 'is_omap16xx' checks are removed, this is the only one left.

That being said, I still don't really like this redirection, and find it
rather non intuitive.  I'm basically not crazy about the driver passing
functions into the device-specific code.  Typically the device-specific
code passes functions into the driver.  I see why it's done for the
reset logic, but it's a bit confusing: device code sets 'is_omap16xx'
flag for driver, driver checks flag and sets function pointers for
device code. 

What's probably cleaner is to just move the reset functions (back) into
the driver, but only set the reset pointer if pdata->needs_manual_reset
== true, and that flag will only be set on OMAP1 since OMAP2+ is using
hwmod.

Kevin

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

* Re: [PATCH v11 6/8] dmtimer: switch-over to platform device driver
  2011-02-24 11:26 ` [PATCH v11 6/8] dmtimer: switch-over to platform device driver Tarun Kanti DebBarma
  2011-03-04  1:25   ` Kevin Hilman
@ 2011-03-04 17:23   ` Tony Lindgren
  2011-03-04 18:52     ` DebBarma, Tarun Kanti
  1 sibling, 1 reply; 44+ messages in thread
From: Tony Lindgren @ 2011-03-04 17:23 UTC (permalink / raw)
  To: Tarun Kanti DebBarma; +Cc: linux-omap

* Tarun Kanti DebBarma <tarun.kanti@ti.com> [110224 03:23]:
> --- a/arch/arm/mach-omap2/dmtimer.c
> +++ b/arch/arm/mach-omap2/dmtimer.c
> @@ -197,3 +197,64 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
>  
>  	return ret;
>  }
> +
> +/**
> + * omap2_dm_timer_early_init - top level early timer initialization
> + * called in the last part of omap2_init_common_hw
> + *
> + * Uses dedicated hwmod api to parse through hwmod database for
> + * given class name and then build and register the timer device.
> + * At the end driver is registered and early probe initiated.
> + */
> +void __init omap2_dm_timer_early_init(void)
> +{
> +	int ret = omap_hwmod_for_each_by_class("timer",
> +			omap_timer_init, NULL);

Here we really only want to initialize the system timer. The rest we
want to do later, so let's not init all of them early.

Regards,

Tony

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

* Re: [PATCH v11 4/8] OMAP2+: dmtimer: convert to platform devices
  2011-03-04  6:34     ` DebBarma, Tarun Kanti
@ 2011-03-04 17:25       ` Kevin Hilman
  2011-03-04 19:24         ` DebBarma, Tarun Kanti
  0 siblings, 1 reply; 44+ messages in thread
From: Kevin Hilman @ 2011-03-04 17:25 UTC (permalink / raw)
  To: DebBarma, Tarun Kanti; +Cc: linux-omap@vger.kernel.org, Gopinath, Thara

"DebBarma, Tarun Kanti" <tarun.kanti@ti.com> writes:

>> -----Original Message-----
>> From: Hilman, Kevin
>> Sent: Friday, March 04, 2011 6:32 AM
>> To: DebBarma, Tarun Kanti
>> Cc: linux-omap@vger.kernel.org; Gopinath, Thara
>> Subject: Re: [PATCH v11 4/8] OMAP2+: dmtimer: convert to platform devices
>> 
>> Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:
>> 
>> > 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. It also provides
>> > provision to access timers during early boot when pm_runtime framework
>> > is not completely up and running.
>> >
>> > 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/Makefile  |    2 +-
>> >  arch/arm/mach-omap2/dmtimer.c |  199
>> +++++++++++++++++++++++++++++++++++++++++
>> >  2 files changed, 200 insertions(+), 1 deletions(-)
>> >  create mode 100644 arch/arm/mach-omap2/dmtimer.c
>> >
>> > diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
>> > index 1c3635d..7e5014b 100644
>> > --- a/arch/arm/mach-omap2/Makefile
>> > +++ b/arch/arm/mach-omap2/Makefile
>> > @@ -4,7 +4,7 @@
>> >
>> >  # Common support
>> >  obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o
>> pm.o \
>> > -	 common.o gpio.o dma.o wd_timer.o
>> > +	 common.o gpio.o dma.o wd_timer.o dmtimer.o
>> >
>> >  omap-2-3-common				= irq.o sdrc.o
>> >  hwmod-common				= omap_hwmod.o \
>> > diff --git a/arch/arm/mach-omap2/dmtimer.c b/arch/arm/mach-
>> omap2/dmtimer.c
>> > new file mode 100644
>> > index 0000000..00cebe9
>> > --- /dev/null
>> > +++ b/arch/arm/mach-omap2/dmtimer.c
>> > @@ -0,0 +1,199 @@
>> > +/**
>> > + * OMAP2+ Dual-Mode Timers - platform device registration
>> > + *
>> > + * Contains first level initialization routines which extracts timers
>> > + * information from hwmod database and registers with linux device
>> model.
>> > + * It also has low level function to change 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/err.h>
>> > +#include <linux/slab.h>
>> > +
>> > +#include <plat/dmtimer.h>
>> > +#include <plat/omap_device.h>
>> > +#include <plat/cpu.h>
>> > +
>> > +/*
>> > + * 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
>> 
>> These should be in the driver along with all the other register offsets.
>> 
>> This device code is already setting the IP rev type, the driver can
>> handle the rest.
> Ok, I will make the changes.
>
>> 
>> > +static int early_timer_count __initdata = 1;
>> 
>> dumb question: why does this start at 1?
>> 
> This is related to one of your early comments where this variable is used:
> early_platform_driver_probe("earlytimer", early_timer_count, 0);
> It was passed as early_timer_count + 1, as static variable starts at 0.
> So it is just to avoid this addition of 1.

I see, but this change doesn't make it any more readable, IMO.

How about just create a local variable 'id = early_timer_count + 1',
and pass id as the 2nd argument.  That way it's clear that it's being
used for the ID.

>> > +struct dm_timer_data {
>> > +	struct omap_device *od;
>> > +	struct dmtimer_platform_data *pdata;
>> > +	struct list_head node;
>> > +};
>> > +
>> > +static __initdata LIST_HEAD(dm_timer_data_list);
>> > +
>> > +/**
>> > + * omap2_dm_timer_set_src - change the timer input clock source
>> > + * @pdev:	timer platform device pointer
>> > + * @timer_clk:	current clock source
>> > + * @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 = clk_get(&pdev->dev, "fck");
>> > +	struct clk *new_fclk;
>> > +	char *fclk_name = "32k_ck"; /* default name */
>> > +
>> > +	switch (source) {
>> > +	case OMAP_TIMER_SRC_SYS_CLK:
>> > +		fclk_name = "sys_ck";
>> > +		break;
>> > +
>> > +	case OMAP_TIMER_SRC_32_KHZ:
>> > +		fclk_name = "32k_ck";
>> > +		break;
>> > +
>> > +	case OMAP_TIMER_SRC_EXT_CLK:
>> > +		if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_1) {
>> > +			fclk_name = "alt_ck";
>> > +			break;
>> > +		}
>> > +		dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
>> > +			__func__, __LINE__);
>> > +		return -EINVAL;
>> > +	}
>> > +
>> > +	if (IS_ERR_OR_NULL(fclk)) {
>> > +		dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
>> > +			__func__, __LINE__);
>> > +		return -EINVAL;
>> > +	}
>> > +
>> > +	new_fclk = clk_get(&pdev->dev, fclk_name);
>> > +	if (IS_ERR_OR_NULL(new_fclk)) {
>> > +		dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
>> > +			__func__, __LINE__, 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__, 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 dm_timer_data *timer_data = NULL;
>> > +
>> > +	pr_debug("%s: %s\n", __func__, oh->name);
>> > +
>> > +	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
>> 
>> Memory leak.
>> 
>> This needs to be free'd after omap_device_build().  The platform_device
>> core makes a copy of the pdata (via kmemdup.)
> Yes, it was there and I missed it while implementing the double registration
> Issue :( Thanks!
>
>> 
>> > +	if (!pdata) {
>> > +		pr_err("%s: No memory for [%s]\n", __func__, oh->name);
>> > +		return -ENOMEM;
>> > +	}
>> > +
>> > +	pdata->is_early_init = 1;
>> > +	pdata->is_omap16xx = 0;
>> > +	pdata->dm_timer_reset = NULL;
>> > +	pdata->set_timer_src = omap2_dm_timer_set_src;
>> > +
>> > +	pdata->timer_ip_type = oh->class->rev;
>> > +	if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_2) {
>> > +		pdata->func_offset = VERSION2_TIMER_WAKEUP_EN_REG_OFFSET;
>> > +		pdata->intr_offset = VERSION2_TIMER_STAT_REG_OFFSET;
>> > +	} else {
>> > +		pdata->func_offset = 0;
>> > +		pdata->intr_offset = 0;
>> > +	}
>> > +
>> > +	/*
>> > +	 * 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);
>> > +
>> > +	/* do registration of timer12 on GP device only */
>> > +	if (id == 12 && omap_type() != OMAP2_DEVICE_TYPE_GP)
>> > +		return ret;
>> 
>> hmm, grumble
>> 
>> Is this true on OMAP4?  I thought GPT12 was not accessible on OMAP4 even
>> on GP devices.
>
> On OMAP4 hwmod database there is no entry for GPT12.
> So, this condition would NOT be applicable to OMAP4 at all as I understand.

Not really true.  

Just like OMAP3, OMAP4 has a secure-mode GPT12.  (c.f. OMAP4430 ES2.x
NDA TRM HS Security Addendum vI, Chapter 6.1 Secure Timers.)  What's not
clear (and needs to be tested) is whether this timer is available on GP
devices.

Benoit gave me a GPT12 hwmod for OMAP4 and I boot tested it on top of
your series and it seems to work fine on my ES2.0 GP Panda, so we should
just add the GPT12 hwmod and make it behave just like OMAP3.

> Of course, as I see it the comment is not very clear and I can change that.
>
>> 
>> As I've said a few times before, what we need here is some sort of
>> "capabilities" flag for each timer in the hwmod.  In addition to this
>> "secure-mode only" feature, there are other capabilities such as 1ms
>> timers, PWM capable, etc.
> I can consider this. However I feel this would take sometime to align on the
> Final choice/option of implementation.

Yes, it would take some time, which is why I've been suggesing this
feature since this series was first proposed a few months ago.

> So, is the above implementation acceptable for now? 

If it can be done without feeling like a hack.  

Personally, I think a better short-term hack would be to have a dev_attr
flag for "secure" rather than a hard-coded check for timer 12.

Kevin

>> 
>> > +	od = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
>> > +			omap2_dmtimer_latency,
>> > +			ARRAY_SIZE(omap2_dmtimer_latency),
>> > +			pdata->is_early_init);
>> > +
>> > +	if (IS_ERR(od)) {
>> > +		pr_err("%s: Can't build omap_device for %s: %s.\n",
>> > +			__func__, name, oh->name);
>> > +		ret = -EINVAL;
>> > +	} else if (pdata->is_early_init)
>> > +		early_timer_count++;
>> > +
>> > +	timer_data = kzalloc(sizeof(*timer_data), GFP_KERNEL);
>> > +	if (!timer_data) {
>> > +		pr_debug("%s: no memory for dm_timer_data\n",
>> > +				__func__);
>> > +		return -ENOMEM;
>> > +	}
>> > +
>> > +	/* store od and pdata to be used later during normal initialization
>> */
>> > +	timer_data->od = od;
>> > +	timer_data->pdata = pdata;
>> > +	list_add_tail(&timer_data->node, &dm_timer_data_list);
>> > +
>> > +	return ret;
>> > +}
>> 
>> Kevin

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

* Re: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
  2011-03-04  1:22   ` Kevin Hilman
  2011-03-04  9:18     ` DebBarma, Tarun Kanti
@ 2011-03-04 17:28     ` Tony Lindgren
  2011-03-04 18:57       ` DebBarma, Tarun Kanti
  1 sibling, 1 reply; 44+ messages in thread
From: Tony Lindgren @ 2011-03-04 17:28 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Tarun Kanti DebBarma, linux-omap, Partha Basak

* Kevin Hilman <khilman@ti.com> [110303 17:22]:
> Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:
> 
> > Add pm_runtime support to dmtimer. Since dmtimer is used during
> > early boot before pm_runtime is initialized completely there are
> > provisions to enable/disable clocks directly in the code during
> > early boot.
> 
> I'm still not crazy about the duplicate logic (both early & normal) in
> all the enable/disable functions.
> 
> As I've suggested in the past, why not just do a clk_get, clk_enable in
> when the early timers are initialized, then do a clk_disable, clk_put()
> as soon as the "normal" device is ready and PM runtime is enabled.

Even better would be to have separate handling for the system timer
with minimal dependencies to anything.

> That will greatly simplify the code and eliminate the unnecessary checks
> for ->is_early_device which will always be false except for in early
> boot (when these functions are not likely to be called anyways.)

And please note that only the system timer needs to be initialized early.
We might as well treat the system timer separately to avoid these issues.

Regards,

Tony

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

* RE: [PATCH v11 6/8] dmtimer: switch-over to platform device driver
  2011-03-04 17:23   ` Tony Lindgren
@ 2011-03-04 18:52     ` DebBarma, Tarun Kanti
  2011-03-04 19:37       ` Tony Lindgren
  0 siblings, 1 reply; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-04 18:52 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org

> -----Original Message-----
> From: Tony Lindgren [mailto:tony@atomide.com]
> Sent: Friday, March 04, 2011 10:53 PM
> To: DebBarma, Tarun Kanti
> Cc: linux-omap@vger.kernel.org
> Subject: Re: [PATCH v11 6/8] dmtimer: switch-over to platform device
> driver
> 
> * Tarun Kanti DebBarma <tarun.kanti@ti.com> [110224 03:23]:
> > --- a/arch/arm/mach-omap2/dmtimer.c
> > +++ b/arch/arm/mach-omap2/dmtimer.c
> > @@ -197,3 +197,64 @@ static int __init omap_timer_init(struct omap_hwmod
> *oh, void *unused)
> >
> >  	return ret;
> >  }
> > +
> > +/**
> > + * omap2_dm_timer_early_init - top level early timer initialization
> > + * called in the last part of omap2_init_common_hw
> > + *
> > + * Uses dedicated hwmod api to parse through hwmod database for
> > + * given class name and then build and register the timer device.
> > + * At the end driver is registered and early probe initiated.
> > + */
> > +void __init omap2_dm_timer_early_init(void)
> > +{
> > +	int ret = omap_hwmod_for_each_by_class("timer",
> > +			omap_timer_init, NULL);
> 
> Here we really only want to initialize the system timer. The rest we
> want to do later, so let's not init all of them early.
So, that is how it was at the beginning.
Later we realized different platforms can use different timers for this.
For example, beagle uses GPT12. Therefore, as part of one of the comments,
We decided to provide flexibility so that any of the timers could be used.
--
Tarun

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

* RE: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
  2011-03-04 17:28     ` Tony Lindgren
@ 2011-03-04 18:57       ` DebBarma, Tarun Kanti
  2011-03-04 19:37         ` Tony Lindgren
  0 siblings, 1 reply; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-04 18:57 UTC (permalink / raw)
  To: Tony Lindgren, Hilman, Kevin; +Cc: linux-omap@vger.kernel.org, Basak, Partha

> -----Original Message-----
> From: Tony Lindgren [mailto:tony@atomide.com]
> Sent: Friday, March 04, 2011 10:59 PM
> To: Hilman, Kevin
> Cc: DebBarma, Tarun Kanti; linux-omap@vger.kernel.org; Basak, Partha
> Subject: Re: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
> 
> * Kevin Hilman <khilman@ti.com> [110303 17:22]:
> > Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:
> >
> > > Add pm_runtime support to dmtimer. Since dmtimer is used during
> > > early boot before pm_runtime is initialized completely there are
> > > provisions to enable/disable clocks directly in the code during
> > > early boot.
> >
> > I'm still not crazy about the duplicate logic (both early & normal) in
> > all the enable/disable functions.
> >
> > As I've suggested in the past, why not just do a clk_get, clk_enable in
> > when the early timers are initialized, then do a clk_disable, clk_put()
> > as soon as the "normal" device is ready and PM runtime is enabled.
> 
> Even better would be to have separate handling for the system timer
> with minimal dependencies to anything.
> 
> > That will greatly simplify the code and eliminate the unnecessary checks
> > for ->is_early_device which will always be false except for in early
> > boot (when these functions are not likely to be called anyways.)
> 
> And please note that only the system timer needs to be initialized early.
> We might as well treat the system timer separately to avoid these issues.
> 
Yes, this is applicable normally for the system timer only.
But as I said earlier, we are giving flexibility whereby any one of the GPTs
Can be system timer.
--
Tarun

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

* RE: [PATCH v11 5/8] OMAP: dmtimer: platform driver
  2011-03-04 16:53       ` Kevin Hilman
@ 2011-03-04 19:07         ` DebBarma, Tarun Kanti
  0 siblings, 0 replies; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-04 19:07 UTC (permalink / raw)
  To: Hilman, Kevin; +Cc: linux-omap@vger.kernel.org, Gopinath, Thara

> -----Original Message-----
> From: Hilman, Kevin
> Sent: Friday, March 04, 2011 10:23 PM
> To: DebBarma, Tarun Kanti
> Cc: linux-omap@vger.kernel.org; Gopinath, Thara
> Subject: Re: [PATCH v11 5/8] OMAP: dmtimer: platform driver
> 
> "DebBarma, Tarun Kanti" <tarun.kanti@ti.com> writes:
> 
> >> -----Original Message-----
> >> From: Hilman, Kevin
> >> Sent: Friday, March 04, 2011 6:59 AM
> >> To: DebBarma, Tarun Kanti
> >> Cc: linux-omap@vger.kernel.org; Gopinath, Thara
> >> Subject: Re: [PATCH v11 5/8] OMAP: dmtimer: platform driver
> >>
> >> Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:
> >>
> >> > From: Thara Gopinath <thara@ti.com>
> >> >
> >> > 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>
> >>
> >> [...]
> >>
> >> > +/**
> >> > + * 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;
> >> > +	}
> >> > +
> >> > +	spin_lock_irqsave(&dm_timer_lock, flags);
> >> > +	list_for_each_entry(timer, &omap_timer_list, node)
> >> > +		if (!pdata->is_early_init && timer->id == pdev->id) {
> >> > +			timer->pdev = pdev;
> >> > +			spin_unlock_irqrestore(&dm_timer_lock, flags);
> >> > +			dev_dbg(&pdev->dev, "Regular Probed\n");
> >> > +			return 0;
> >> > +		}
> >> > +	spin_unlock_irqrestore(&dm_timer_lock, flags);
> >> > +
> >> > +	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;
> >> > +	}
> >> > +
> >> > +	/*
> >> > +	 * Following func pointers are required by OMAP1's reset code
> >> > +	 * in mach-omap1/dmtimer.c to access to low level read/write.
> >> > +	 */
> >> > +	if (pdata->is_omap16xx) {
> >> > +		pdata->dm_timer_read_reg = omap_dm_timer_read_reg;
> >> > +		pdata->dm_timer_write_reg = omap_dm_timer_write_reg;
> >> > +		pdata->is_early_init = 0;
> >> > +	}
> >>
> >> Can this 'is_omap16xx' check be replaced with an IP revision check?
> > Hmm, this not really!
> > Unless we introduce a new version to indicate OMAP1.
> 
> Ah, I see. Looks like the revision change was after OMAP3, I thought it
> was after OMAP1.  Sorry.
> 
> > If this is what you mean I will make the change.
> 
> An OMAP1 check would make this more clear, but really the flag should be
> a bool called something like "needs_manual_reset" since after all the
> other 'is_omap16xx' checks are removed, this is the only one left.
> 
> That being said, I still don't really like this redirection, and find it
> rather non intuitive.  I'm basically not crazy about the driver passing
> functions into the device-specific code.  Typically the device-specific
> code passes functions into the driver.  I see why it's done for the
> reset logic, but it's a bit confusing: device code sets 'is_omap16xx'
> flag for driver, driver checks flag and sets function pointers for
> device code.
> 
> What's probably cleaner is to just move the reset functions (back) into
> the driver, but only set the reset pointer if pdata->needs_manual_reset
> == true, and that flag will only be set on OMAP1 since OMAP2+ is using
> hwmod.
Alright, I will make this change.
--
Tarun

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

* RE: [PATCH v11 4/8] OMAP2+: dmtimer: convert to platform devices
  2011-03-04 17:25       ` Kevin Hilman
@ 2011-03-04 19:24         ` DebBarma, Tarun Kanti
  0 siblings, 0 replies; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-04 19:24 UTC (permalink / raw)
  To: Hilman, Kevin; +Cc: linux-omap@vger.kernel.org, Gopinath, Thara

> -----Original Message-----
> From: Hilman, Kevin
> Sent: Friday, March 04, 2011 10:55 PM
> To: DebBarma, Tarun Kanti
> Cc: linux-omap@vger.kernel.org; Gopinath, Thara
> Subject: Re: [PATCH v11 4/8] OMAP2+: dmtimer: convert to platform devices
> 
> "DebBarma, Tarun Kanti" <tarun.kanti@ti.com> writes:
> 
> >> -----Original Message-----
> >> From: Hilman, Kevin
> >> Sent: Friday, March 04, 2011 6:32 AM
> >> To: DebBarma, Tarun Kanti
> >> Cc: linux-omap@vger.kernel.org; Gopinath, Thara
> >> Subject: Re: [PATCH v11 4/8] OMAP2+: dmtimer: convert to platform
> devices
> >>
> >> Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:
> >>
> >> > 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. It also provides
> >> > provision to access timers during early boot when pm_runtime
> framework
> >> > is not completely up and running.
> >> >
> >> > 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/Makefile  |    2 +-
> >> >  arch/arm/mach-omap2/dmtimer.c |  199
> >> +++++++++++++++++++++++++++++++++++++++++
> >> >  2 files changed, 200 insertions(+), 1 deletions(-)
> >> >  create mode 100644 arch/arm/mach-omap2/dmtimer.c
> >> >
> >> > diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-
> omap2/Makefile
> >> > index 1c3635d..7e5014b 100644
> >> > --- a/arch/arm/mach-omap2/Makefile
> >> > +++ b/arch/arm/mach-omap2/Makefile
> >> > @@ -4,7 +4,7 @@
> >> >
> >> >  # Common support
> >> >  obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-
> gp.o
> >> pm.o \
> >> > -	 common.o gpio.o dma.o wd_timer.o
> >> > +	 common.o gpio.o dma.o wd_timer.o dmtimer.o
> >> >
> >> >  omap-2-3-common				= irq.o sdrc.o
> >> >  hwmod-common				= omap_hwmod.o \
> >> > diff --git a/arch/arm/mach-omap2/dmtimer.c b/arch/arm/mach-
> >> omap2/dmtimer.c
> >> > new file mode 100644
> >> > index 0000000..00cebe9
> >> > --- /dev/null
> >> > +++ b/arch/arm/mach-omap2/dmtimer.c
> >> > @@ -0,0 +1,199 @@
> >> > +/**
> >> > + * OMAP2+ Dual-Mode Timers - platform device registration
> >> > + *
> >> > + * Contains first level initialization routines which extracts
> timers
> >> > + * information from hwmod database and registers with linux device
> >> model.
> >> > + * It also has low level function to change 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/err.h>
> >> > +#include <linux/slab.h>
> >> > +
> >> > +#include <plat/dmtimer.h>
> >> > +#include <plat/omap_device.h>
> >> > +#include <plat/cpu.h>
> >> > +
> >> > +/*
> >> > + * 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
> >>
> >> These should be in the driver along with all the other register
> offsets.
> >>
> >> This device code is already setting the IP rev type, the driver can
> >> handle the rest.
> > Ok, I will make the changes.
> >
> >>
> >> > +static int early_timer_count __initdata = 1;
> >>
> >> dumb question: why does this start at 1?
> >>
> > This is related to one of your early comments where this variable is
> used:
> > early_platform_driver_probe("earlytimer", early_timer_count, 0);
> > It was passed as early_timer_count + 1, as static variable starts at 0.
> > So it is just to avoid this addition of 1.
> 
> I see, but this change doesn't make it any more readable, IMO.
> 
> How about just create a local variable 'id = early_timer_count + 1',
> and pass id as the 2nd argument.  That way it's clear that it's being
> used for the ID.
OK.

> 
> >> > +struct dm_timer_data {
> >> > +	struct omap_device *od;
> >> > +	struct dmtimer_platform_data *pdata;
> >> > +	struct list_head node;
> >> > +};
> >> > +
> >> > +static __initdata LIST_HEAD(dm_timer_data_list);
> >> > +
> >> > +/**
> >> > + * omap2_dm_timer_set_src - change the timer input clock source
> >> > + * @pdev:	timer platform device pointer
> >> > + * @timer_clk:	current clock source
> >> > + * @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 = clk_get(&pdev->dev, "fck");
> >> > +	struct clk *new_fclk;
> >> > +	char *fclk_name = "32k_ck"; /* default name */
> >> > +
> >> > +	switch (source) {
> >> > +	case OMAP_TIMER_SRC_SYS_CLK:
> >> > +		fclk_name = "sys_ck";
> >> > +		break;
> >> > +
> >> > +	case OMAP_TIMER_SRC_32_KHZ:
> >> > +		fclk_name = "32k_ck";
> >> > +		break;
> >> > +
> >> > +	case OMAP_TIMER_SRC_EXT_CLK:
> >> > +		if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_1) {
> >> > +			fclk_name = "alt_ck";
> >> > +			break;
> >> > +		}
> >> > +		dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
> >> > +			__func__, __LINE__);
> >> > +		return -EINVAL;
> >> > +	}
> >> > +
> >> > +	if (IS_ERR_OR_NULL(fclk)) {
> >> > +		dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
> >> > +			__func__, __LINE__);
> >> > +		return -EINVAL;
> >> > +	}
> >> > +
> >> > +	new_fclk = clk_get(&pdev->dev, fclk_name);
> >> > +	if (IS_ERR_OR_NULL(new_fclk)) {
> >> > +		dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
> >> > +			__func__, __LINE__, 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__, 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 dm_timer_data *timer_data = NULL;
> >> > +
> >> > +	pr_debug("%s: %s\n", __func__, oh->name);
> >> > +
> >> > +	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
> >>
> >> Memory leak.
> >>
> >> This needs to be free'd after omap_device_build().  The platform_device
> >> core makes a copy of the pdata (via kmemdup.)
> > Yes, it was there and I missed it while implementing the double
> registration
> > Issue :( Thanks!
BTW, I realized that pdata is freed later at the end of normal registration.

> >
> >>
> >> > +	if (!pdata) {
> >> > +		pr_err("%s: No memory for [%s]\n", __func__, oh->name);
> >> > +		return -ENOMEM;
> >> > +	}
> >> > +
> >> > +	pdata->is_early_init = 1;
> >> > +	pdata->is_omap16xx = 0;
> >> > +	pdata->dm_timer_reset = NULL;
> >> > +	pdata->set_timer_src = omap2_dm_timer_set_src;
> >> > +
> >> > +	pdata->timer_ip_type = oh->class->rev;
> >> > +	if (pdata->timer_ip_type == OMAP_TIMER_IP_VERSION_2) {
> >> > +		pdata->func_offset = VERSION2_TIMER_WAKEUP_EN_REG_OFFSET;
> >> > +		pdata->intr_offset = VERSION2_TIMER_STAT_REG_OFFSET;
> >> > +	} else {
> >> > +		pdata->func_offset = 0;
> >> > +		pdata->intr_offset = 0;
> >> > +	}
> >> > +
> >> > +	/*
> >> > +	 * 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);
> >> > +
> >> > +	/* do registration of timer12 on GP device only */
> >> > +	if (id == 12 && omap_type() != OMAP2_DEVICE_TYPE_GP)
> >> > +		return ret;
> >>
> >> hmm, grumble
> >>
> >> Is this true on OMAP4?  I thought GPT12 was not accessible on OMAP4
> even
> >> on GP devices.
> >
> > On OMAP4 hwmod database there is no entry for GPT12.
> > So, this condition would NOT be applicable to OMAP4 at all as I
> understand.
> 
> Not really true.
> 
> Just like OMAP3, OMAP4 has a secure-mode GPT12.  (c.f. OMAP4430 ES2.x
> NDA TRM HS Security Addendum vI, Chapter 6.1 Secure Timers.)  What's not
> clear (and needs to be tested) is whether this timer is available on GP
> devices.
As far as I remember GP does not have GPT12, unlike OMAP3.
Anyways, I can confirm once again.

> 
> Benoit gave me a GPT12 hwmod for OMAP4 and I boot tested it on top of
> your series and it seems to work fine on my ES2.0 GP Panda, so we should
> just add the GPT12 hwmod and make it behave just like OMAP3.
Ok, I was not aware of this.

> 
> > Of course, as I see it the comment is not very clear and I can change
> that.
> >
> >>
> >> As I've said a few times before, what we need here is some sort of
> >> "capabilities" flag for each timer in the hwmod.  In addition to this
> >> "secure-mode only" feature, there are other capabilities such as 1ms
> >> timers, PWM capable, etc.
> > I can consider this. However I feel this would take sometime to align on
> the
> > Final choice/option of implementation.
> 
> Yes, it would take some time, which is why I've been suggesing this
> feature since this series was first proposed a few months ago.
Looks like I have definitely missed this point somehow.
Sorry about that.

> 
> > So, is the above implementation acceptable for now?
> 
> If it can be done without feeling like a hack.
> 
> Personally, I think a better short-term hack would be to have a dev_attr
> flag for "secure" rather than a hard-coded check for timer 12.
Yes, I will try out this change.
--
Tarun

> 
> >>
> >> > +	od = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
> >> > +			omap2_dmtimer_latency,
> >> > +			ARRAY_SIZE(omap2_dmtimer_latency),
> >> > +			pdata->is_early_init);
> >> > +
> >> > +	if (IS_ERR(od)) {
> >> > +		pr_err("%s: Can't build omap_device for %s: %s.\n",
> >> > +			__func__, name, oh->name);
> >> > +		ret = -EINVAL;
> >> > +	} else if (pdata->is_early_init)
> >> > +		early_timer_count++;
> >> > +
> >> > +	timer_data = kzalloc(sizeof(*timer_data), GFP_KERNEL);
> >> > +	if (!timer_data) {
> >> > +		pr_debug("%s: no memory for dm_timer_data\n",
> >> > +				__func__);
> >> > +		return -ENOMEM;
> >> > +	}
> >> > +
> >> > +	/* store od and pdata to be used later during normal
> initialization
> >> */
> >> > +	timer_data->od = od;
> >> > +	timer_data->pdata = pdata;
> >> > +	list_add_tail(&timer_data->node, &dm_timer_data_list);
> >> > +
> >> > +	return ret;
> >> > +}
> >>
> >> Kevin

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

* Re: [PATCH v11 6/8] dmtimer: switch-over to platform device driver
  2011-03-04 18:52     ` DebBarma, Tarun Kanti
@ 2011-03-04 19:37       ` Tony Lindgren
  2011-03-04 19:41         ` DebBarma, Tarun Kanti
  2011-03-05  7:54         ` Santosh Shilimkar
  0 siblings, 2 replies; 44+ messages in thread
From: Tony Lindgren @ 2011-03-04 19:37 UTC (permalink / raw)
  To: DebBarma, Tarun Kanti; +Cc: linux-omap@vger.kernel.org

* DebBarma, Tarun Kanti <tarun.kanti@ti.com> [110304 10:50]:
> > -----Original Message-----
> > From: Tony Lindgren [mailto:tony@atomide.com]
> > Sent: Friday, March 04, 2011 10:53 PM
> > To: DebBarma, Tarun Kanti
> > Cc: linux-omap@vger.kernel.org
> > Subject: Re: [PATCH v11 6/8] dmtimer: switch-over to platform device
> > driver
> > 
> > * Tarun Kanti DebBarma <tarun.kanti@ti.com> [110224 03:23]:
> > > --- a/arch/arm/mach-omap2/dmtimer.c
> > > +++ b/arch/arm/mach-omap2/dmtimer.c
> > > @@ -197,3 +197,64 @@ static int __init omap_timer_init(struct omap_hwmod
> > *oh, void *unused)
> > >
> > >  	return ret;
> > >  }
> > > +
> > > +/**
> > > + * omap2_dm_timer_early_init - top level early timer initialization
> > > + * called in the last part of omap2_init_common_hw
> > > + *
> > > + * Uses dedicated hwmod api to parse through hwmod database for
> > > + * given class name and then build and register the timer device.
> > > + * At the end driver is registered and early probe initiated.
> > > + */
> > > +void __init omap2_dm_timer_early_init(void)
> > > +{
> > > +	int ret = omap_hwmod_for_each_by_class("timer",
> > > +			omap_timer_init, NULL);
> > 
> > Here we really only want to initialize the system timer. The rest we
> > want to do later, so let's not init all of them early.
> So, that is how it was at the beginning.
> Later we realized different platforms can use different timers for this.
> For example, beagle uses GPT12. Therefore, as part of one of the comments,
> We decided to provide flexibility so that any of the timers could be used.

You can still do it, just register the one that's being used and mark
it reserved so it won't get initialized again later on.

Tony

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

* Re: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
  2011-03-04 18:57       ` DebBarma, Tarun Kanti
@ 2011-03-04 19:37         ` Tony Lindgren
  2011-03-04 19:52           ` DebBarma, Tarun Kanti
  0 siblings, 1 reply; 44+ messages in thread
From: Tony Lindgren @ 2011-03-04 19:37 UTC (permalink / raw)
  To: DebBarma, Tarun Kanti
  Cc: Hilman, Kevin, linux-omap@vger.kernel.org, Basak, Partha

* DebBarma, Tarun Kanti <tarun.kanti@ti.com> [110304 10:55]:
> > -----Original Message-----
> > From: Tony Lindgren [mailto:tony@atomide.com]
> > Sent: Friday, March 04, 2011 10:59 PM
> > To: Hilman, Kevin
> > Cc: DebBarma, Tarun Kanti; linux-omap@vger.kernel.org; Basak, Partha
> > Subject: Re: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
> > 
> > * Kevin Hilman <khilman@ti.com> [110303 17:22]:
> > > Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:
> > >
> > > > Add pm_runtime support to dmtimer. Since dmtimer is used during
> > > > early boot before pm_runtime is initialized completely there are
> > > > provisions to enable/disable clocks directly in the code during
> > > > early boot.
> > >
> > > I'm still not crazy about the duplicate logic (both early & normal) in
> > > all the enable/disable functions.
> > >
> > > As I've suggested in the past, why not just do a clk_get, clk_enable in
> > > when the early timers are initialized, then do a clk_disable, clk_put()
> > > as soon as the "normal" device is ready and PM runtime is enabled.
> > 
> > Even better would be to have separate handling for the system timer
> > with minimal dependencies to anything.
> > 
> > > That will greatly simplify the code and eliminate the unnecessary checks
> > > for ->is_early_device which will always be false except for in early
> > > boot (when these functions are not likely to be called anyways.)
> > 
> > And please note that only the system timer needs to be initialized early.
> > We might as well treat the system timer separately to avoid these issues.
> > 
> Yes, this is applicable normally for the system timer only.
> But as I said earlier, we are giving flexibility whereby any one of the GPTs
> Can be system timer.

Any one of them can be used, but no need to register the others this early.

Tony

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

* RE: [PATCH v11 6/8] dmtimer: switch-over to platform device driver
  2011-03-04 19:37       ` Tony Lindgren
@ 2011-03-04 19:41         ` DebBarma, Tarun Kanti
  2011-03-05  7:54         ` Santosh Shilimkar
  1 sibling, 0 replies; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-04 19:41 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org

> -----Original Message-----
> From: Tony Lindgren [mailto:tony@atomide.com]
> Sent: Saturday, March 05, 2011 1:07 AM
> To: DebBarma, Tarun Kanti
> Cc: linux-omap@vger.kernel.org
> Subject: Re: [PATCH v11 6/8] dmtimer: switch-over to platform device
> driver
> 
> * DebBarma, Tarun Kanti <tarun.kanti@ti.com> [110304 10:50]:
> > > -----Original Message-----
> > > From: Tony Lindgren [mailto:tony@atomide.com]
> > > Sent: Friday, March 04, 2011 10:53 PM
> > > To: DebBarma, Tarun Kanti
> > > Cc: linux-omap@vger.kernel.org
> > > Subject: Re: [PATCH v11 6/8] dmtimer: switch-over to platform device
> > > driver
> > >
> > > * Tarun Kanti DebBarma <tarun.kanti@ti.com> [110224 03:23]:
> > > > --- a/arch/arm/mach-omap2/dmtimer.c
> > > > +++ b/arch/arm/mach-omap2/dmtimer.c
> > > > @@ -197,3 +197,64 @@ static int __init omap_timer_init(struct
> omap_hwmod
> > > *oh, void *unused)
> > > >
> > > >  	return ret;
> > > >  }
> > > > +
> > > > +/**
> > > > + * omap2_dm_timer_early_init - top level early timer initialization
> > > > + * called in the last part of omap2_init_common_hw
> > > > + *
> > > > + * Uses dedicated hwmod api to parse through hwmod database for
> > > > + * given class name and then build and register the timer device.
> > > > + * At the end driver is registered and early probe initiated.
> > > > + */
> > > > +void __init omap2_dm_timer_early_init(void)
> > > > +{
> > > > +	int ret = omap_hwmod_for_each_by_class("timer",
> > > > +			omap_timer_init, NULL);
> > >
> > > Here we really only want to initialize the system timer. The rest we
> > > want to do later, so let's not init all of them early.
> > So, that is how it was at the beginning.
> > Later we realized different platforms can use different timers for this.
> > For example, beagle uses GPT12. Therefore, as part of one of the
> comments,
> > We decided to provide flexibility so that any of the timers could be
> used.
> 
> You can still do it, just register the one that's being used and mark
> it reserved so it won't get initialized again later on.
May be I was not clear in my explanation.
Yes, you are right, the system timer gets reserved early and initialized.
Later it is NOT initialized again.
> 
> Tony

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

* RE: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
  2011-03-04 19:37         ` Tony Lindgren
@ 2011-03-04 19:52           ` DebBarma, Tarun Kanti
  2011-03-05  0:01             ` Tony Lindgren
  0 siblings, 1 reply; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-04 19:52 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: Hilman, Kevin, linux-omap@vger.kernel.org, Basak, Partha

Tony, Kevin,
[...]
> > >
> > > * Kevin Hilman <khilman@ti.com> [110303 17:22]:
> > > > Tarun Kanti DebBarma <tarun.kanti@ti.com> writes:
> > > >
> > > > > Add pm_runtime support to dmtimer. Since dmtimer is used during
> > > > > early boot before pm_runtime is initialized completely there are
> > > > > provisions to enable/disable clocks directly in the code during
> > > > > early boot.
> > > >
> > > > I'm still not crazy about the duplicate logic (both early & normal)
> in
> > > > all the enable/disable functions.
> > > >
> > > > As I've suggested in the past, why not just do a clk_get, clk_enable
> in
> > > > when the early timers are initialized, then do a clk_disable,
> clk_put()
> > > > as soon as the "normal" device is ready and PM runtime is enabled.
> > >
> > > Even better would be to have separate handling for the system timer
> > > with minimal dependencies to anything.
> > >
> > > > That will greatly simplify the code and eliminate the unnecessary
> checks
> > > > for ->is_early_device which will always be false except for in early
> > > > boot (when these functions are not likely to be called anyways.)
> > >
> > > And please note that only the system timer needs to be initialized
> early.
> > > We might as well treat the system timer separately to avoid these
> issues.
> > >
> > Yes, this is applicable normally for the system timer only.
> > But as I said earlier, we are giving flexibility whereby any one of the
> GPTs
> > Can be system timer.
> 
> Any one of them can be used, but no need to register the others this
> early.
In that case we have to associate probably a dev attribute to system timer.
Do you have alternate proposal?

> 
> Tony

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

* Re: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
  2011-03-04 19:52           ` DebBarma, Tarun Kanti
@ 2011-03-05  0:01             ` Tony Lindgren
  2011-03-05  0:22               ` DebBarma, Tarun Kanti
  0 siblings, 1 reply; 44+ messages in thread
From: Tony Lindgren @ 2011-03-05  0:01 UTC (permalink / raw)
  To: DebBarma, Tarun Kanti
  Cc: Hilman, Kevin, linux-omap@vger.kernel.org, Basak, Partha

* DebBarma, Tarun Kanti <tarun.kanti@ti.com> [110304 11:50]:
>
> In that case we have to associate probably a dev attribute to system timer.
> Do you have alternate proposal?

No need for that. Keep the system timer code to the minimum so
it does not have any unnecessary dependencies. That code needs to
be running early and efficient, while the other timers should
really be a device driver.

You can have shared timer read/write functions that don't depend
on dev. And you can just tag the pysical timer used for system
timer as reserved.

Then you can initialize the other timers later on and skip the
system timer. For the other timers you can have dev oriented
timer read/write wrapper functions for the other timers.

Cheers,

Tony

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

* RE: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
  2011-03-05  0:01             ` Tony Lindgren
@ 2011-03-05  0:22               ` DebBarma, Tarun Kanti
  2011-03-08  0:10                 ` Tony Lindgren
  0 siblings, 1 reply; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-05  0:22 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: Hilman, Kevin, linux-omap@vger.kernel.org, Basak, Partha

> -----Original Message-----
> From: Tony Lindgren [mailto:tony@atomide.com]
> Sent: Saturday, March 05, 2011 5:32 AM
> To: DebBarma, Tarun Kanti
> Cc: Hilman, Kevin; linux-omap@vger.kernel.org; Basak, Partha
> Subject: Re: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
> 
> * DebBarma, Tarun Kanti <tarun.kanti@ti.com> [110304 11:50]:
> >
> > In that case we have to associate probably a dev attribute to system
> timer.
> > Do you have alternate proposal?
> 
> No need for that. Keep the system timer code to the minimum so
> it does not have any unnecessary dependencies. That code needs to
> be running early and efficient, while the other timers should
> really be a device driver.
> 
> You can have shared timer read/write functions that don't depend
> on dev. And you can just tag the pysical timer used for system
> timer as reserved.
> 
> Then you can initialize the other timers later on and skip the
> system timer. For the other timers you can have dev oriented
> timer read/write wrapper functions for the other timers.
There is a single timer list created during driver probe.
It can not be done separately for system timer except through
Common build and probe. If we try other way it would get complicated
I believe with the current design because clockevent management code
in timer-gp.c calls common exported APIs.

Now, coming back to our present requirement where we initialize
Only the system timer early and is skipped later, here is the plan:

(1) Have a separate class in hwmod database with unique name "system_timer"
(2) Initialize just this one during early init

> 
> Cheers,
> 
> Tony

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

* RE: [PATCH v11 6/8] dmtimer: switch-over to platform device driver
  2011-03-04 19:37       ` Tony Lindgren
  2011-03-04 19:41         ` DebBarma, Tarun Kanti
@ 2011-03-05  7:54         ` Santosh Shilimkar
  2011-03-07 12:54           ` DebBarma, Tarun Kanti
  1 sibling, 1 reply; 44+ messages in thread
From: Santosh Shilimkar @ 2011-03-05  7:54 UTC (permalink / raw)
  To: Tony Lindgren, Tarun Kanti DebBarma; +Cc: linux-omap

> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
> owner@vger.kernel.org] On Behalf Of Tony Lindgren
> Sent: Saturday, March 05, 2011 1:07 AM
> To: DebBarma, Tarun Kanti
> Cc: linux-omap@vger.kernel.org
> Subject: Re: [PATCH v11 6/8] dmtimer: switch-over to platform device
> driver
>
> * DebBarma, Tarun Kanti <tarun.kanti@ti.com> [110304 10:50]:
> > > -----Original Message-----
> > > From: Tony Lindgren [mailto:tony@atomide.com]
> > > Sent: Friday, March 04, 2011 10:53 PM
> > > To: DebBarma, Tarun Kanti
> > > Cc: linux-omap@vger.kernel.org
> > > Subject: Re: [PATCH v11 6/8] dmtimer: switch-over to platform
> device
> > > driver
> > >
> > > * Tarun Kanti DebBarma <tarun.kanti@ti.com> [110224 03:23]:
> > > > --- a/arch/arm/mach-omap2/dmtimer.c
> > > > +++ b/arch/arm/mach-omap2/dmtimer.c
> > > > @@ -197,3 +197,64 @@ static int __init omap_timer_init(struct
> omap_hwmod
> > > *oh, void *unused)
> > > >
> > > >  	return ret;
> > > >  }
> > > > +
> > > > +/**
> > > > + * omap2_dm_timer_early_init - top level early timer
> initialization
> > > > + * called in the last part of omap2_init_common_hw
> > > > + *
> > > > + * Uses dedicated hwmod api to parse through hwmod database
> for
> > > > + * given class name and then build and register the timer
> device.
> > > > + * At the end driver is registered and early probe initiated.
> > > > + */
> > > > +void __init omap2_dm_timer_early_init(void)
> > > > +{
> > > > +	int ret = omap_hwmod_for_each_by_class("timer",
> > > > +			omap_timer_init, NULL);
> > >
> > > Here we really only want to initialize the system timer. The
> rest we
> > > want to do later, so let's not init all of them early.
> > So, that is how it was at the beginning.
> > Later we realized different platforms can use different timers for
> this.
> > For example, beagle uses GPT12. Therefore, as part of one of the
> comments,
> > We decided to provide flexibility so that any of the timers could
> be used.
>
> You can still do it, just register the one that's being used and
> mark it reserved so it won't get initialized again later on.
>

I agree with Tony. We can still registers only the system
timer because the timer ID is known well before we do
initialization.

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

* RE: [PATCH v11 2/8] OMAP4: hwmod data: add dmtimer version information
  2011-03-04 11:16     ` Cousson, Benoit
@ 2011-03-07 11:19       ` DebBarma, Tarun Kanti
  0 siblings, 0 replies; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-07 11:19 UTC (permalink / raw)
  To: Cousson, Benoit, Hilman, Kevin; +Cc: linux-omap@vger.kernel.org

> -----Original Message-----
> From: Cousson, Benoit
> Sent: Friday, March 04, 2011 4:47 PM
> To: Hilman, Kevin; DebBarma, Tarun Kanti
> Cc: linux-omap@vger.kernel.org
> Subject: Re: [PATCH v11 2/8] OMAP4: hwmod data: add dmtimer version
> information
> 
> On 3/4/2011 1:24 AM, Hilman, Kevin wrote:
> > Tarun Kanti DebBarma<tarun.kanti@ti.com>  writes:
> >
> >> 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>
> >
> > Minor comment below, also needs an ack from Benoît...
> 
> Oops, I missed that one.
> 
> Tarun,
> I will be good to add me in Cc in order to avoid that.
> In general it is always good to Cc the maintainers.
> 
> Once the tabs are fixed;
> Acked-by: Benoit Cousson <b-cousson@ti.com>
I will Cc. Thanks.
--
Tarun
> 
> >
> >> ---
> >>   arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    3 +++
> >>   arch/arm/plat-omap/include/plat/dmtimer.h  |    2 ++
> >>   2 files changed, 5 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> >> index 79a8601..ee57742 100644
> >> --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> >> +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> >> @@ -25,6 +25,7 @@
> >>   #include<plat/gpio.h>
> >>   #include<plat/dma.h>
> >>   #include<plat/mcspi.h>
> >> +#include<plat/dmtimer.h>
> >>
> >>   #include "omap_hwmod_common_data.h"
> >>
> >> @@ -3940,6 +3941,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,
> >
> > Please use tab and align '=' with above lines.
> >
> >>   };
> >>
> >>   static struct omap_hwmod_class_sysconfig omap44xx_timer_sysc = {
> >> @@ -3955,6 +3957,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,
> >
> > ditto
> >
> >>   };
> >>
> >>   /* timer1 */
> >> diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-
> omap/include/plat/dmtimer.h
> >> index d6c70d2..05a967e 100644
> >> --- a/arch/arm/plat-omap/include/plat/dmtimer.h
> >> +++ b/arch/arm/plat-omap/include/plat/dmtimer.h
> >> @@ -55,6 +55,8 @@
> >>    * in OMAP4 can be distinguished.
> >>    */
> >>   #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;
> >>   extern struct sys_timer omap_timer;
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* RE: [PATCH v11 6/8] dmtimer: switch-over to platform device driver
  2011-03-05  7:54         ` Santosh Shilimkar
@ 2011-03-07 12:54           ` DebBarma, Tarun Kanti
  2011-03-08  0:07             ` Tony Lindgren
  0 siblings, 1 reply; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-07 12:54 UTC (permalink / raw)
  To: Shilimkar, Santosh, Tony Lindgren; +Cc: linux-omap@vger.kernel.org

Tony, Santosh,
[...]
> > > > > +void __init omap2_dm_timer_early_init(void)
> > > > > +{
> > > > > +	int ret = omap_hwmod_for_each_by_class("timer",
> > > > > +			omap_timer_init, NULL);
> > > >
> > > > Here we really only want to initialize the system timer. The
> > rest we
> > > > want to do later, so let's not init all of them early.
> > > So, that is how it was at the beginning.
> > > Later we realized different platforms can use different timers for
> > this.
> > > For example, beagle uses GPT12. Therefore, as part of one of the
> > comments,
> > > We decided to provide flexibility so that any of the timers could
> > be used.
> >
> > You can still do it, just register the one that's being used and
> > mark it reserved so it won't get initialized again later on.
> >
> 
> I agree with Tony. We can still registers only the system
> timer because the timer ID is known well before we do
> initialization.
I must say, there was a gap in my understanding of the comment.
So, here is the implementation change:

-> Call omap2_dm_timer_early_init(u8 gptimer_id) from omap2_gp_timer_init()
-> Initialize only gptimer_id inside this function
-> In the regular init skip initialization of gptimer_id

As a result of this, we can rid of double registration and related code.
--
Tarun

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

* Re: [PATCH v11 6/8] dmtimer: switch-over to platform device driver
  2011-03-07 12:54           ` DebBarma, Tarun Kanti
@ 2011-03-08  0:07             ` Tony Lindgren
  2011-03-08  0:11               ` DebBarma, Tarun Kanti
  0 siblings, 1 reply; 44+ messages in thread
From: Tony Lindgren @ 2011-03-08  0:07 UTC (permalink / raw)
  To: DebBarma, Tarun Kanti; +Cc: Shilimkar, Santosh, linux-omap@vger.kernel.org

* DebBarma, Tarun Kanti <tarun.kanti@ti.com> [110307 04:52]:
> > 
> > I agree with Tony. We can still registers only the system
> > timer because the timer ID is known well before we do
> > initialization.
> I must say, there was a gap in my understanding of the comment.
> So, here is the implementation change:
> 
> -> Call omap2_dm_timer_early_init(u8 gptimer_id) from omap2_gp_timer_init()
> -> Initialize only gptimer_id inside this function
> -> In the regular init skip initialization of gptimer_id
> 
> As a result of this, we can rid of double registration and related code.

I suggest we keep the system timer completely separate from the
rest of the timers. This way we avoid adding hwmod dependencies
early on when the system timer is initialized, and can still
use hwmod for handling the the rest of the timers nicely.

The rest of the timers can then become just a regular device
driver that ignores the physical system timer.

Regards,

Tony

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

* Re: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
  2011-03-05  0:22               ` DebBarma, Tarun Kanti
@ 2011-03-08  0:10                 ` Tony Lindgren
  2011-03-08  0:13                   ` DebBarma, Tarun Kanti
  0 siblings, 1 reply; 44+ messages in thread
From: Tony Lindgren @ 2011-03-08  0:10 UTC (permalink / raw)
  To: DebBarma, Tarun Kanti
  Cc: Hilman, Kevin, linux-omap@vger.kernel.org, Basak, Partha

* DebBarma, Tarun Kanti <tarun.kanti@ti.com> [110304 16:20]:
> 
> Now, coming back to our present requirement where we initialize
> Only the system timer early and is skipped later, here is the plan:
> 
> (1) Have a separate class in hwmod database with unique name "system_timer"
> (2) Initialize just this one during early init

Let's keep the system timer code completely separate. For the
system timer we really just need to implement one function to
reprogram one timer.

What you've implemented is pretty much done for the rest of
the timers and allows us to turn them into a regular device
driver eventually.

Regards,

Tony

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

* RE: [PATCH v11 6/8] dmtimer: switch-over to platform device driver
  2011-03-08  0:07             ` Tony Lindgren
@ 2011-03-08  0:11               ` DebBarma, Tarun Kanti
  0 siblings, 0 replies; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-08  0:11 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: Shilimkar, Santosh, linux-omap@vger.kernel.org

> -----Original Message-----
> From: Tony Lindgren [mailto:tony@atomide.com]
> Sent: Tuesday, March 08, 2011 5:37 AM
> To: DebBarma, Tarun Kanti
> Cc: Shilimkar, Santosh; linux-omap@vger.kernel.org
> Subject: Re: [PATCH v11 6/8] dmtimer: switch-over to platform device
> driver
> 
> * DebBarma, Tarun Kanti <tarun.kanti@ti.com> [110307 04:52]:
> > >
> > > I agree with Tony. We can still registers only the system
> > > timer because the timer ID is known well before we do
> > > initialization.
> > I must say, there was a gap in my understanding of the comment.
> > So, here is the implementation change:
> >
> > -> Call omap2_dm_timer_early_init(u8 gptimer_id) from
> omap2_gp_timer_init()
> > -> Initialize only gptimer_id inside this function
> > -> In the regular init skip initialization of gptimer_id
> >
> > As a result of this, we can rid of double registration and related code.
> 
> I suggest we keep the system timer completely separate from the
> rest of the timers. This way we avoid adding hwmod dependencies
> early on when the system timer is initialized, and can still
> use hwmod for handling the the rest of the timers nicely.
Yes, just the system timer is initialized now.
We just call omap_hwmod_setup_one() to initialize system timer.

> 
> The rest of the timers can then become just a regular device
> driver that ignores the physical system timer.
Right, system timer is NOT touched at all later.

> 
> Regards,
> 
> Tony

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

* RE: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
  2011-03-08  0:10                 ` Tony Lindgren
@ 2011-03-08  0:13                   ` DebBarma, Tarun Kanti
  0 siblings, 0 replies; 44+ messages in thread
From: DebBarma, Tarun Kanti @ 2011-03-08  0:13 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: Hilman, Kevin, linux-omap@vger.kernel.org, Basak, Partha

> -----Original Message-----
> From: Tony Lindgren [mailto:tony@atomide.com]
> Sent: Tuesday, March 08, 2011 5:40 AM
> To: DebBarma, Tarun Kanti
> Cc: Hilman, Kevin; linux-omap@vger.kernel.org; Basak, Partha
> Subject: Re: [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support
> 
> * DebBarma, Tarun Kanti <tarun.kanti@ti.com> [110304 16:20]:
> >
> > Now, coming back to our present requirement where we initialize
> > Only the system timer early and is skipped later, here is the plan:
> >
> > (1) Have a separate class in hwmod database with unique name
> "system_timer"
> > (2) Initialize just this one during early init
> 
> Let's keep the system timer code completely separate. For the
> system timer we really just need to implement one function to
> reprogram one timer.
> 
> What you've implemented is pretty much done for the rest of
> the timers and allows us to turn them into a regular device
> driver eventually.
YES. So, this proposal of mine can be ignored now. 

> 
> Regards,
> 
> Tony

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

end of thread, other threads:[~2011-03-08  0:13 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-02-24 11:26 [PATCH v11 0/8] dmtimer adaptation to platform_driver Tarun Kanti DebBarma
2011-02-24 11:26 ` [PATCH v11 1/8] OMAP2+: dmtimer: add device names to flck nodes Tarun Kanti DebBarma
2011-02-24 11:26 ` [PATCH v11 2/8] OMAP4: hwmod data: add dmtimer version information Tarun Kanti DebBarma
2011-03-04  0:24   ` Kevin Hilman
2011-03-04  5:49     ` DebBarma, Tarun Kanti
2011-03-04 11:16     ` Cousson, Benoit
2011-03-07 11:19       ` DebBarma, Tarun Kanti
2011-02-24 11:26 ` [PATCH v11 3/8] OMAP1: dmtimer: conversion to platform devices Tarun Kanti DebBarma
2011-02-24 11:26 ` [PATCH v11 4/8] OMAP2+: dmtimer: convert " Tarun Kanti DebBarma
2011-03-04  1:01   ` Kevin Hilman
2011-03-04  6:34     ` DebBarma, Tarun Kanti
2011-03-04 17:25       ` Kevin Hilman
2011-03-04 19:24         ` DebBarma, Tarun Kanti
2011-02-24 11:26 ` [PATCH v11 5/8] OMAP: dmtimer: platform driver Tarun Kanti DebBarma
2011-03-04  0:35   ` Kevin Hilman
2011-03-04  9:07     ` DebBarma, Tarun Kanti
2011-03-04  1:29   ` Kevin Hilman
2011-03-04  6:56     ` DebBarma, Tarun Kanti
2011-03-04 16:53       ` Kevin Hilman
2011-03-04 19:07         ` DebBarma, Tarun Kanti
2011-02-24 11:26 ` [PATCH v11 6/8] dmtimer: switch-over to platform device driver Tarun Kanti DebBarma
2011-03-04  1:25   ` Kevin Hilman
2011-03-04  6:57     ` DebBarma, Tarun Kanti
2011-03-04 17:23   ` Tony Lindgren
2011-03-04 18:52     ` DebBarma, Tarun Kanti
2011-03-04 19:37       ` Tony Lindgren
2011-03-04 19:41         ` DebBarma, Tarun Kanti
2011-03-05  7:54         ` Santosh Shilimkar
2011-03-07 12:54           ` DebBarma, Tarun Kanti
2011-03-08  0:07             ` Tony Lindgren
2011-03-08  0:11               ` DebBarma, Tarun Kanti
2011-02-24 11:26 ` [PATCH v11 7/8] OMAP: dmtimer: pm_runtime support Tarun Kanti DebBarma
2011-03-04  1:22   ` Kevin Hilman
2011-03-04  9:18     ` DebBarma, Tarun Kanti
2011-03-04 17:28     ` Tony Lindgren
2011-03-04 18:57       ` DebBarma, Tarun Kanti
2011-03-04 19:37         ` Tony Lindgren
2011-03-04 19:52           ` DebBarma, Tarun Kanti
2011-03-05  0:01             ` Tony Lindgren
2011-03-05  0:22               ` DebBarma, Tarun Kanti
2011-03-08  0:10                 ` Tony Lindgren
2011-03-08  0:13                   ` DebBarma, Tarun Kanti
2011-02-24 11:26 ` [PATCH v11 8/8] OMAP: dmtimer: add timeout to low-level routines Tarun Kanti DebBarma
2011-02-25 14:08 ` [PATCH v11 0/8] dmtimer adaptation to platform_driver DebBarma, Tarun Kanti

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).