All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/14] ARM: samsung-time: Prepare for multiplatform support
@ 2013-04-04 16:36 ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:36 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

This series is an attempt to make the samsung-time clocksource driver ready
for multiplatform kernels. It moves the driver to drivers/clocksource, cleans
it up from uses of static platform-specific definitions, simplifies timer
interrupt handling and adds Device Tree support.

Only samsung-time driver is reworked to use the master driver at this time,
since the PWM driver can be already considered broken at the moment and
needs separate series of several patches to fix and clean it up, which
I am already working on.

Tested on Universal C210 board with Device Tree. Not tested without
Device Tree, since it has been already broken before this series.
Compile tested for other related SoCs.

Changes since v3:
(http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16664/)
 - Changed the design to use common (master) driver for operations that
   can be done from both clocksource and PWM drivers (as suggested by
   Arnd Bergmann) - needed to properly synchronize access to PWM registers
 - Moved handling of PWM prescaler and divider to master driver

Changes since v2:
(http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16158)
 - Addressed comments from Rob Herring and Mark Rutland
 - Removed unused register definitions
 - Replaced samsung,source-timer and samsung,event-timer properties
   with samsung,pwm-outputs property that defines which PWM channels
   are reserved for PWM outputs on particular platform
 - Split non-DT and DT initialization into two functions
 - Fixed a copy paste error

Changes since v1:
(http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16005)
 - Addressed comments from Mark Rutland
 - Documented struct samsung_timer_variant
 - Dropped inactive mail addresses from CC

Tomasz Figa (14):
  ARM: SAMSUNG: Move samsung-time to drivers/clocksource
  clocksource: samsung-time: Drop useless defines from public header
  clocksource: samsung-time: Use local register definitions
  mfd: Add Samsung PWM/timer master driver
  ARM: SAMSUNG: Unify base address definitions of timer block
  ARM: SAMSUNG: Add new PWM platform device
  ARM: SAMSUNG: Set PWM platform data
  clocksource: samsung-time: Use Samsung PWM/timer master driver
  clocksource: samsung-time: Use variant data to get SoC-specific bits
  clocksource: samsung-time: Use master driver to configure dividers
  clocksource: samsung-time: Use clk_prepare_enable
  clocksource: samsung-time: Use master driver to control PWM channels
  clocksource: samsung-time: Move IRQ mask/ack handling to the driver
  ARM: SAMSUNG: Remove unused PWM timer IRQ chip code

 .../devicetree/bindings/pwm/pwm-samsung.txt        |  37 ++
 arch/arm/Kconfig                                   |   1 -
 arch/arm/mach-exynos/common.c                      |  10 +
 arch/arm/mach-exynos/include/mach/irqs.h           |   3 +-
 arch/arm/mach-exynos/include/mach/map.h            |   1 +
 arch/arm/mach-s3c24xx/common.c                     |  10 +
 arch/arm/mach-s3c24xx/include/mach/irqs.h          |   6 +
 arch/arm/mach-s3c24xx/include/mach/map.h           |   2 +
 arch/arm/mach-s3c64xx/common.c                     |  14 +-
 arch/arm/mach-s3c64xx/include/mach/irqs.h          |   8 -
 arch/arm/mach-s3c64xx/include/mach/map.h           |   1 +
 arch/arm/mach-s5p64x0/common.c                     |  10 +
 arch/arm/mach-s5p64x0/include/mach/irqs.h          |   2 -
 arch/arm/mach-s5p64x0/include/mach/map.h           |   1 +
 arch/arm/mach-s5pc100/common.c                     |  10 +
 arch/arm/mach-s5pc100/include/mach/irqs.h          |   2 -
 arch/arm/mach-s5pc100/include/mach/map.h           |   1 +
 arch/arm/mach-s5pv210/common.c                     |  10 +
 arch/arm/mach-s5pv210/include/mach/irqs.h          |   2 -
 arch/arm/mach-s5pv210/include/mach/map.h           |   1 +
 arch/arm/plat-samsung/Kconfig                      |  14 -
 arch/arm/plat-samsung/Makefile                     |   2 -
 arch/arm/plat-samsung/devs.c                       |  33 +-
 arch/arm/plat-samsung/include/plat/devs.h          |   1 +
 arch/arm/plat-samsung/include/plat/irq-vic-timer.h |  13 -
 arch/arm/plat-samsung/include/plat/irqs.h          |   9 -
 arch/arm/plat-samsung/include/plat/samsung-time.h  |  38 +-
 arch/arm/plat-samsung/irq-vic-timer.c              |  98 -----
 arch/arm/plat-samsung/s5p-irq.c                    |   3 -
 arch/arm/plat-samsung/samsung-time.c               | 394 ------------------
 drivers/clocksource/Kconfig                        |   8 +
 drivers/clocksource/Makefile                       |   1 +
 drivers/clocksource/samsung-time.c                 | 298 ++++++++++++++
 drivers/mfd/Kconfig                                |   3 +
 drivers/mfd/Makefile                               |   1 +
 drivers/mfd/samsung-pwm.c                          | 439 +++++++++++++++++++++
 drivers/pwm/Kconfig                                |   1 +
 include/linux/mfd/samsung-pwm.h                    |  49 +++
 include/linux/platform_data/samsung-pwm.h          |  29 ++
 39 files changed, 983 insertions(+), 583 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pwm/pwm-samsung.txt
 delete mode 100644 arch/arm/plat-samsung/include/plat/irq-vic-timer.h
 delete mode 100644 arch/arm/plat-samsung/irq-vic-timer.c
 delete mode 100644 arch/arm/plat-samsung/samsung-time.c
 create mode 100644 drivers/clocksource/samsung-time.c
 create mode 100644 drivers/mfd/samsung-pwm.c
 create mode 100644 include/linux/mfd/samsung-pwm.h
 create mode 100644 include/linux/platform_data/samsung-pwm.h

-- 
1.8.1.5

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

* [PATCH v4 00/14] ARM: samsung-time: Prepare for multiplatform support
@ 2013-04-04 16:36 ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:36 UTC (permalink / raw)
  To: linux-arm-kernel

This series is an attempt to make the samsung-time clocksource driver ready
for multiplatform kernels. It moves the driver to drivers/clocksource, cleans
it up from uses of static platform-specific definitions, simplifies timer
interrupt handling and adds Device Tree support.

Only samsung-time driver is reworked to use the master driver at this time,
since the PWM driver can be already considered broken at the moment and
needs separate series of several patches to fix and clean it up, which
I am already working on.

Tested on Universal C210 board with Device Tree. Not tested without
Device Tree, since it has been already broken before this series.
Compile tested for other related SoCs.

Changes since v3:
(http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16664/)
 - Changed the design to use common (master) driver for operations that
   can be done from both clocksource and PWM drivers (as suggested by
   Arnd Bergmann) - needed to properly synchronize access to PWM registers
 - Moved handling of PWM prescaler and divider to master driver

Changes since v2:
(http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16158)
 - Addressed comments from Rob Herring and Mark Rutland
 - Removed unused register definitions
 - Replaced samsung,source-timer and samsung,event-timer properties
   with samsung,pwm-outputs property that defines which PWM channels
   are reserved for PWM outputs on particular platform
 - Split non-DT and DT initialization into two functions
 - Fixed a copy paste error

Changes since v1:
(http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16005)
 - Addressed comments from Mark Rutland
 - Documented struct samsung_timer_variant
 - Dropped inactive mail addresses from CC

Tomasz Figa (14):
  ARM: SAMSUNG: Move samsung-time to drivers/clocksource
  clocksource: samsung-time: Drop useless defines from public header
  clocksource: samsung-time: Use local register definitions
  mfd: Add Samsung PWM/timer master driver
  ARM: SAMSUNG: Unify base address definitions of timer block
  ARM: SAMSUNG: Add new PWM platform device
  ARM: SAMSUNG: Set PWM platform data
  clocksource: samsung-time: Use Samsung PWM/timer master driver
  clocksource: samsung-time: Use variant data to get SoC-specific bits
  clocksource: samsung-time: Use master driver to configure dividers
  clocksource: samsung-time: Use clk_prepare_enable
  clocksource: samsung-time: Use master driver to control PWM channels
  clocksource: samsung-time: Move IRQ mask/ack handling to the driver
  ARM: SAMSUNG: Remove unused PWM timer IRQ chip code

 .../devicetree/bindings/pwm/pwm-samsung.txt        |  37 ++
 arch/arm/Kconfig                                   |   1 -
 arch/arm/mach-exynos/common.c                      |  10 +
 arch/arm/mach-exynos/include/mach/irqs.h           |   3 +-
 arch/arm/mach-exynos/include/mach/map.h            |   1 +
 arch/arm/mach-s3c24xx/common.c                     |  10 +
 arch/arm/mach-s3c24xx/include/mach/irqs.h          |   6 +
 arch/arm/mach-s3c24xx/include/mach/map.h           |   2 +
 arch/arm/mach-s3c64xx/common.c                     |  14 +-
 arch/arm/mach-s3c64xx/include/mach/irqs.h          |   8 -
 arch/arm/mach-s3c64xx/include/mach/map.h           |   1 +
 arch/arm/mach-s5p64x0/common.c                     |  10 +
 arch/arm/mach-s5p64x0/include/mach/irqs.h          |   2 -
 arch/arm/mach-s5p64x0/include/mach/map.h           |   1 +
 arch/arm/mach-s5pc100/common.c                     |  10 +
 arch/arm/mach-s5pc100/include/mach/irqs.h          |   2 -
 arch/arm/mach-s5pc100/include/mach/map.h           |   1 +
 arch/arm/mach-s5pv210/common.c                     |  10 +
 arch/arm/mach-s5pv210/include/mach/irqs.h          |   2 -
 arch/arm/mach-s5pv210/include/mach/map.h           |   1 +
 arch/arm/plat-samsung/Kconfig                      |  14 -
 arch/arm/plat-samsung/Makefile                     |   2 -
 arch/arm/plat-samsung/devs.c                       |  33 +-
 arch/arm/plat-samsung/include/plat/devs.h          |   1 +
 arch/arm/plat-samsung/include/plat/irq-vic-timer.h |  13 -
 arch/arm/plat-samsung/include/plat/irqs.h          |   9 -
 arch/arm/plat-samsung/include/plat/samsung-time.h  |  38 +-
 arch/arm/plat-samsung/irq-vic-timer.c              |  98 -----
 arch/arm/plat-samsung/s5p-irq.c                    |   3 -
 arch/arm/plat-samsung/samsung-time.c               | 394 ------------------
 drivers/clocksource/Kconfig                        |   8 +
 drivers/clocksource/Makefile                       |   1 +
 drivers/clocksource/samsung-time.c                 | 298 ++++++++++++++
 drivers/mfd/Kconfig                                |   3 +
 drivers/mfd/Makefile                               |   1 +
 drivers/mfd/samsung-pwm.c                          | 439 +++++++++++++++++++++
 drivers/pwm/Kconfig                                |   1 +
 include/linux/mfd/samsung-pwm.h                    |  49 +++
 include/linux/platform_data/samsung-pwm.h          |  29 ++
 39 files changed, 983 insertions(+), 583 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pwm/pwm-samsung.txt
 delete mode 100644 arch/arm/plat-samsung/include/plat/irq-vic-timer.h
 delete mode 100644 arch/arm/plat-samsung/irq-vic-timer.c
 delete mode 100644 arch/arm/plat-samsung/samsung-time.c
 create mode 100644 drivers/clocksource/samsung-time.c
 create mode 100644 drivers/mfd/samsung-pwm.c
 create mode 100644 include/linux/mfd/samsung-pwm.h
 create mode 100644 include/linux/platform_data/samsung-pwm.h

-- 
1.8.1.5

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

* [PATCH v4 01/14] ARM: SAMSUNG: Move samsung-time to drivers/clocksource
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 16:36   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:36 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

This patch moves the Samsung PWM-based high resolution timer support
code from arch/arm/plat-samsung to drivers/clocksource.

This is a prerequisite for further work on making the driver more
multiplatform and Device Tree friendly.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/plat-samsung/Kconfig        |   8 -
 arch/arm/plat-samsung/Makefile       |   1 -
 arch/arm/plat-samsung/samsung-time.c | 394 -----------------------------------
 drivers/clocksource/Kconfig          |   7 +
 drivers/clocksource/Makefile         |   1 +
 drivers/clocksource/samsung-time.c   | 394 +++++++++++++++++++++++++++++++++++
 6 files changed, 402 insertions(+), 403 deletions(-)
 delete mode 100644 arch/arm/plat-samsung/samsung-time.c
 create mode 100644 drivers/clocksource/samsung-time.c

diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 54d1861..6f632ba 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -60,14 +60,6 @@ config S3C_LOWLEVEL_UART_PORT
 	  this configuration should be between zero and two. The port
 	  must have been initialised by the boot-loader before use.
 
-# timer options
-
-config SAMSUNG_HRT
-	bool
-	select SAMSUNG_DEV_PWM
-	help
-	  Use the High Resolution timer support
-
 # clock options
 
 config SAMSUNG_CLOCK
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index a23c460..87494e1 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -12,7 +12,6 @@ obj-				:=
 # Objects we always build independent of SoC choice
 
 obj-y				+= init.o cpu.o
-obj-$(CONFIG_SAMSUNG_HRT) 	+= samsung-time.o
 
 obj-$(CONFIG_SAMSUNG_CLOCK)	+= clock.o
 obj-$(CONFIG_SAMSUNG_CLOCK)	+= pwm-clock.o
diff --git a/arch/arm/plat-samsung/samsung-time.c b/arch/arm/plat-samsung/samsung-time.c
deleted file mode 100644
index f899cbc..0000000
--- a/arch/arm/plat-samsung/samsung-time.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * samsung - Common hr-timer support (s3c and s5p)
- *
- * 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.
-*/
-
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/clockchips.h>
-#include <linux/platform_device.h>
-
-#include <asm/smp_twd.h>
-#include <asm/mach/time.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/sched_clock.h>
-
-#include <mach/map.h>
-#include <plat/devs.h>
-#include <plat/regs-timer.h>
-#include <plat/samsung-time.h>
-
-static struct clk *tin_event;
-static struct clk *tin_source;
-static struct clk *tdiv_event;
-static struct clk *tdiv_source;
-static struct clk *timerclk;
-static struct samsung_timer_source timer_source;
-static unsigned long clock_count_per_tick;
-static void samsung_timer_resume(void);
-
-static void samsung_time_stop(enum samsung_timer_mode mode)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	switch (mode) {
-	case SAMSUNG_PWM0:
-		tcon &= ~S3C2410_TCON_T0START;
-		break;
-
-	case SAMSUNG_PWM1:
-		tcon &= ~S3C2410_TCON_T1START;
-		break;
-
-	case SAMSUNG_PWM2:
-		tcon &= ~S3C2410_TCON_T2START;
-		break;
-
-	case SAMSUNG_PWM3:
-		tcon &= ~S3C2410_TCON_T3START;
-		break;
-
-	case SAMSUNG_PWM4:
-		tcon &= ~S3C2410_TCON_T4START;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void samsung_time_setup(enum samsung_timer_mode mode, unsigned long tcnt)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	tcnt--;
-
-	switch (mode) {
-	case SAMSUNG_PWM0:
-		tcon &= ~(0x0f << 0);
-		tcon |= S3C2410_TCON_T0MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM1:
-		tcon &= ~(0x0f << 8);
-		tcon |= S3C2410_TCON_T1MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM2:
-		tcon &= ~(0x0f << 12);
-		tcon |= S3C2410_TCON_T2MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM3:
-		tcon &= ~(0x0f << 16);
-		tcon |= S3C2410_TCON_T3MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM4:
-		tcon &= ~(0x07 << 20);
-		tcon |= S3C2410_TCON_T4MANUALUPD;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-
-	__raw_writel(tcnt, S3C2410_TCNTB(mode));
-	__raw_writel(tcnt, S3C2410_TCMPB(mode));
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void samsung_time_start(enum samsung_timer_mode mode, bool periodic)
-{
-	unsigned long tcon;
-
-	tcon  = __raw_readl(S3C2410_TCON);
-
-	switch (mode) {
-	case SAMSUNG_PWM0:
-		tcon |= S3C2410_TCON_T0START;
-		tcon &= ~S3C2410_TCON_T0MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T0RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T0RELOAD;
-		break;
-
-	case SAMSUNG_PWM1:
-		tcon |= S3C2410_TCON_T1START;
-		tcon &= ~S3C2410_TCON_T1MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T1RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T1RELOAD;
-		break;
-
-	case SAMSUNG_PWM2:
-		tcon |= S3C2410_TCON_T2START;
-		tcon &= ~S3C2410_TCON_T2MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T2RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T2RELOAD;
-		break;
-
-	case SAMSUNG_PWM3:
-		tcon |= S3C2410_TCON_T3START;
-		tcon &= ~S3C2410_TCON_T3MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T3RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T3RELOAD;
-		break;
-
-	case SAMSUNG_PWM4:
-		tcon |= S3C2410_TCON_T4START;
-		tcon &= ~S3C2410_TCON_T4MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T4RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T4RELOAD;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static int samsung_set_next_event(unsigned long cycles,
-				struct clock_event_device *evt)
-{
-	samsung_time_setup(timer_source.event_id, cycles);
-	samsung_time_start(timer_source.event_id, NON_PERIODIC);
-
-	return 0;
-}
-
-static void samsung_set_mode(enum clock_event_mode mode,
-				struct clock_event_device *evt)
-{
-	samsung_time_stop(timer_source.event_id);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		samsung_time_setup(timer_source.event_id, clock_count_per_tick);
-		samsung_time_start(timer_source.event_id, PERIODIC);
-		break;
-
-	case CLOCK_EVT_MODE_ONESHOT:
-		break;
-
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-		break;
-
-	case CLOCK_EVT_MODE_RESUME:
-		samsung_timer_resume();
-		break;
-	}
-}
-
-static void samsung_timer_resume(void)
-{
-	/* event timer restart */
-	samsung_time_setup(timer_source.event_id, clock_count_per_tick);
-	samsung_time_start(timer_source.event_id, PERIODIC);
-
-	/* source timer restart */
-	samsung_time_setup(timer_source.source_id, TCNT_MAX);
-	samsung_time_start(timer_source.source_id, PERIODIC);
-}
-
-void __init samsung_set_timer_source(enum samsung_timer_mode event,
-				 enum samsung_timer_mode source)
-{
-	s3c_device_timer[event].dev.bus = &platform_bus_type;
-	s3c_device_timer[source].dev.bus = &platform_bus_type;
-
-	timer_source.event_id = event;
-	timer_source.source_id = source;
-}
-
-static struct clock_event_device time_event_device = {
-	.name		= "samsung_event_timer",
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.rating		= 200,
-	.set_next_event	= samsung_set_next_event,
-	.set_mode	= samsung_set_mode,
-};
-
-static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = dev_id;
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction samsung_clock_event_irq = {
-	.name		= "samsung_time_irq",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= samsung_clock_event_isr,
-	.dev_id		= &time_event_device,
-};
-
-static void __init samsung_clockevent_init(void)
-{
-	unsigned long pclk;
-	unsigned long clock_rate;
-	unsigned int irq_number;
-	struct clk *tscaler;
-
-	pclk = clk_get_rate(timerclk);
-
-	tscaler = clk_get_parent(tdiv_event);
-
-	clk_set_rate(tscaler, pclk / TSCALER_DIV);
-	clk_set_rate(tdiv_event, pclk / TDIV);
-	clk_set_parent(tin_event, tdiv_event);
-
-	clock_rate = clk_get_rate(tin_event);
-	clock_count_per_tick = clock_rate / HZ;
-
-	time_event_device.cpumask = cpumask_of(0);
-	clockevents_config_and_register(&time_event_device, clock_rate, 1, -1);
-
-	irq_number = timer_source.event_id + IRQ_TIMER0;
-	setup_irq(irq_number, &samsung_clock_event_irq);
-}
-
-static void __iomem *samsung_timer_reg(void)
-{
-	unsigned long offset = 0;
-
-	switch (timer_source.source_id) {
-	case SAMSUNG_PWM0:
-	case SAMSUNG_PWM1:
-	case SAMSUNG_PWM2:
-	case SAMSUNG_PWM3:
-		offset = (timer_source.source_id * 0x0c) + 0x14;
-		break;
-
-	case SAMSUNG_PWM4:
-		offset = 0x40;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
-		return NULL;
-	}
-
-	return S3C_TIMERREG(offset);
-}
-
-/*
- * Override the global weak sched_clock symbol with this
- * local implementation which uses the clocksource to get some
- * better resolution when scheduling the kernel. We accept that
- * this wraps around for now, since it is just a relative time
- * stamp. (Inspired by U300 implementation.)
- */
-static u32 notrace samsung_read_sched_clock(void)
-{
-	void __iomem *reg = samsung_timer_reg();
-
-	if (!reg)
-		return 0;
-
-	return ~__raw_readl(reg);
-}
-
-static void __init samsung_clocksource_init(void)
-{
-	unsigned long pclk;
-	unsigned long clock_rate;
-
-	pclk = clk_get_rate(timerclk);
-
-	clk_set_rate(tdiv_source, pclk / TDIV);
-	clk_set_parent(tin_source, tdiv_source);
-
-	clock_rate = clk_get_rate(tin_source);
-
-	samsung_time_setup(timer_source.source_id, TCNT_MAX);
-	samsung_time_start(timer_source.source_id, PERIODIC);
-
-	setup_sched_clock(samsung_read_sched_clock, TSIZE, clock_rate);
-
-	if (clocksource_mmio_init(samsung_timer_reg(), "samsung_clocksource_timer",
-			clock_rate, 250, TSIZE, clocksource_mmio_readl_down))
-		panic("samsung_clocksource_timer: can't register clocksource\n");
-}
-
-static void __init samsung_timer_resources(void)
-{
-
-	unsigned long event_id = timer_source.event_id;
-	unsigned long source_id = timer_source.source_id;
-	char devname[15];
-
-	timerclk = clk_get(NULL, "timers");
-	if (IS_ERR(timerclk))
-		panic("failed to get timers clock for timer");
-
-	clk_enable(timerclk);
-
-	sprintf(devname, "s3c24xx-pwm.%lu", event_id);
-	s3c_device_timer[event_id].id = event_id;
-	s3c_device_timer[event_id].dev.init_name = devname;
-
-	tin_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tin");
-	if (IS_ERR(tin_event))
-		panic("failed to get pwm-tin clock for event timer");
-
-	tdiv_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tdiv");
-	if (IS_ERR(tdiv_event))
-		panic("failed to get pwm-tdiv clock for event timer");
-
-	clk_enable(tin_event);
-
-	sprintf(devname, "s3c24xx-pwm.%lu", source_id);
-	s3c_device_timer[source_id].id = source_id;
-	s3c_device_timer[source_id].dev.init_name = devname;
-
-	tin_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tin");
-	if (IS_ERR(tin_source))
-		panic("failed to get pwm-tin clock for source timer");
-
-	tdiv_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tdiv");
-	if (IS_ERR(tdiv_source))
-		panic("failed to get pwm-tdiv clock for source timer");
-
-	clk_enable(tin_source);
-}
-
-void __init samsung_timer_init(void)
-{
-	samsung_timer_resources();
-	samsung_clockevent_init();
-	samsung_clocksource_init();
-}
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index e8c4532..dd20f6a 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -25,6 +25,13 @@ config DW_APB_TIMER_OF
 config ARMADA_370_XP_TIMER
 	bool
 
+config SAMSUNG_HRT
+	bool
+	depends on PLAT_SAMSUNG
+	select SAMSUNG_DEV_PWM
+	help
+	  Use the high resolution timer support on Samsung platforms.
+
 config SUNXI_TIMER
 	bool
 
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 1c1b15d..0d68580 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_CLKSRC_NOMADIK_MTU)	+= nomadik-mtu.o
 obj-$(CONFIG_CLKSRC_DBX500_PRCMU)	+= clksrc-dbx500-prcmu.o
 obj-$(CONFIG_ARMADA_370_XP_TIMER)	+= time-armada-370-xp.o
 obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835_timer.o
+obj-$(CONFIG_SAMSUNG_HRT) 	+= samsung-time.o
 obj-$(CONFIG_SUNXI_TIMER)	+= sunxi_timer.o
 obj-$(CONFIG_ARCH_TEGRA)	+= tegra20_timer.o
 obj-$(CONFIG_VT8500_TIMER)	+= vt8500_timer.o
diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
new file mode 100644
index 0000000..f899cbc
--- /dev/null
+++ b/drivers/clocksource/samsung-time.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * samsung - Common hr-timer support (s3c and s5p)
+ *
+ * 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.
+*/
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/platform_device.h>
+
+#include <asm/smp_twd.h>
+#include <asm/mach/time.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/sched_clock.h>
+
+#include <mach/map.h>
+#include <plat/devs.h>
+#include <plat/regs-timer.h>
+#include <plat/samsung-time.h>
+
+static struct clk *tin_event;
+static struct clk *tin_source;
+static struct clk *tdiv_event;
+static struct clk *tdiv_source;
+static struct clk *timerclk;
+static struct samsung_timer_source timer_source;
+static unsigned long clock_count_per_tick;
+static void samsung_timer_resume(void);
+
+static void samsung_time_stop(enum samsung_timer_mode mode)
+{
+	unsigned long tcon;
+
+	tcon = __raw_readl(S3C2410_TCON);
+
+	switch (mode) {
+	case SAMSUNG_PWM0:
+		tcon &= ~S3C2410_TCON_T0START;
+		break;
+
+	case SAMSUNG_PWM1:
+		tcon &= ~S3C2410_TCON_T1START;
+		break;
+
+	case SAMSUNG_PWM2:
+		tcon &= ~S3C2410_TCON_T2START;
+		break;
+
+	case SAMSUNG_PWM3:
+		tcon &= ~S3C2410_TCON_T3START;
+		break;
+
+	case SAMSUNG_PWM4:
+		tcon &= ~S3C2410_TCON_T4START;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", mode);
+		break;
+	}
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static void samsung_time_setup(enum samsung_timer_mode mode, unsigned long tcnt)
+{
+	unsigned long tcon;
+
+	tcon = __raw_readl(S3C2410_TCON);
+
+	tcnt--;
+
+	switch (mode) {
+	case SAMSUNG_PWM0:
+		tcon &= ~(0x0f << 0);
+		tcon |= S3C2410_TCON_T0MANUALUPD;
+		break;
+
+	case SAMSUNG_PWM1:
+		tcon &= ~(0x0f << 8);
+		tcon |= S3C2410_TCON_T1MANUALUPD;
+		break;
+
+	case SAMSUNG_PWM2:
+		tcon &= ~(0x0f << 12);
+		tcon |= S3C2410_TCON_T2MANUALUPD;
+		break;
+
+	case SAMSUNG_PWM3:
+		tcon &= ~(0x0f << 16);
+		tcon |= S3C2410_TCON_T3MANUALUPD;
+		break;
+
+	case SAMSUNG_PWM4:
+		tcon &= ~(0x07 << 20);
+		tcon |= S3C2410_TCON_T4MANUALUPD;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", mode);
+		break;
+	}
+
+	__raw_writel(tcnt, S3C2410_TCNTB(mode));
+	__raw_writel(tcnt, S3C2410_TCMPB(mode));
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static void samsung_time_start(enum samsung_timer_mode mode, bool periodic)
+{
+	unsigned long tcon;
+
+	tcon  = __raw_readl(S3C2410_TCON);
+
+	switch (mode) {
+	case SAMSUNG_PWM0:
+		tcon |= S3C2410_TCON_T0START;
+		tcon &= ~S3C2410_TCON_T0MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T0RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T0RELOAD;
+		break;
+
+	case SAMSUNG_PWM1:
+		tcon |= S3C2410_TCON_T1START;
+		tcon &= ~S3C2410_TCON_T1MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T1RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T1RELOAD;
+		break;
+
+	case SAMSUNG_PWM2:
+		tcon |= S3C2410_TCON_T2START;
+		tcon &= ~S3C2410_TCON_T2MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T2RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T2RELOAD;
+		break;
+
+	case SAMSUNG_PWM3:
+		tcon |= S3C2410_TCON_T3START;
+		tcon &= ~S3C2410_TCON_T3MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T3RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T3RELOAD;
+		break;
+
+	case SAMSUNG_PWM4:
+		tcon |= S3C2410_TCON_T4START;
+		tcon &= ~S3C2410_TCON_T4MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T4RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T4RELOAD;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", mode);
+		break;
+	}
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static int samsung_set_next_event(unsigned long cycles,
+				struct clock_event_device *evt)
+{
+	samsung_time_setup(timer_source.event_id, cycles);
+	samsung_time_start(timer_source.event_id, NON_PERIODIC);
+
+	return 0;
+}
+
+static void samsung_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	samsung_time_stop(timer_source.event_id);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		samsung_time_setup(timer_source.event_id, clock_count_per_tick);
+		samsung_time_start(timer_source.event_id, PERIODIC);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+		samsung_timer_resume();
+		break;
+	}
+}
+
+static void samsung_timer_resume(void)
+{
+	/* event timer restart */
+	samsung_time_setup(timer_source.event_id, clock_count_per_tick);
+	samsung_time_start(timer_source.event_id, PERIODIC);
+
+	/* source timer restart */
+	samsung_time_setup(timer_source.source_id, TCNT_MAX);
+	samsung_time_start(timer_source.source_id, PERIODIC);
+}
+
+void __init samsung_set_timer_source(enum samsung_timer_mode event,
+				 enum samsung_timer_mode source)
+{
+	s3c_device_timer[event].dev.bus = &platform_bus_type;
+	s3c_device_timer[source].dev.bus = &platform_bus_type;
+
+	timer_source.event_id = event;
+	timer_source.source_id = source;
+}
+
+static struct clock_event_device time_event_device = {
+	.name		= "samsung_event_timer",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 200,
+	.set_next_event	= samsung_set_next_event,
+	.set_mode	= samsung_set_mode,
+};
+
+static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction samsung_clock_event_irq = {
+	.name		= "samsung_time_irq",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= samsung_clock_event_isr,
+	.dev_id		= &time_event_device,
+};
+
+static void __init samsung_clockevent_init(void)
+{
+	unsigned long pclk;
+	unsigned long clock_rate;
+	unsigned int irq_number;
+	struct clk *tscaler;
+
+	pclk = clk_get_rate(timerclk);
+
+	tscaler = clk_get_parent(tdiv_event);
+
+	clk_set_rate(tscaler, pclk / TSCALER_DIV);
+	clk_set_rate(tdiv_event, pclk / TDIV);
+	clk_set_parent(tin_event, tdiv_event);
+
+	clock_rate = clk_get_rate(tin_event);
+	clock_count_per_tick = clock_rate / HZ;
+
+	time_event_device.cpumask = cpumask_of(0);
+	clockevents_config_and_register(&time_event_device, clock_rate, 1, -1);
+
+	irq_number = timer_source.event_id + IRQ_TIMER0;
+	setup_irq(irq_number, &samsung_clock_event_irq);
+}
+
+static void __iomem *samsung_timer_reg(void)
+{
+	unsigned long offset = 0;
+
+	switch (timer_source.source_id) {
+	case SAMSUNG_PWM0:
+	case SAMSUNG_PWM1:
+	case SAMSUNG_PWM2:
+	case SAMSUNG_PWM3:
+		offset = (timer_source.source_id * 0x0c) + 0x14;
+		break;
+
+	case SAMSUNG_PWM4:
+		offset = 0x40;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
+		return NULL;
+	}
+
+	return S3C_TIMERREG(offset);
+}
+
+/*
+ * Override the global weak sched_clock symbol with this
+ * local implementation which uses the clocksource to get some
+ * better resolution when scheduling the kernel. We accept that
+ * this wraps around for now, since it is just a relative time
+ * stamp. (Inspired by U300 implementation.)
+ */
+static u32 notrace samsung_read_sched_clock(void)
+{
+	void __iomem *reg = samsung_timer_reg();
+
+	if (!reg)
+		return 0;
+
+	return ~__raw_readl(reg);
+}
+
+static void __init samsung_clocksource_init(void)
+{
+	unsigned long pclk;
+	unsigned long clock_rate;
+
+	pclk = clk_get_rate(timerclk);
+
+	clk_set_rate(tdiv_source, pclk / TDIV);
+	clk_set_parent(tin_source, tdiv_source);
+
+	clock_rate = clk_get_rate(tin_source);
+
+	samsung_time_setup(timer_source.source_id, TCNT_MAX);
+	samsung_time_start(timer_source.source_id, PERIODIC);
+
+	setup_sched_clock(samsung_read_sched_clock, TSIZE, clock_rate);
+
+	if (clocksource_mmio_init(samsung_timer_reg(), "samsung_clocksource_timer",
+			clock_rate, 250, TSIZE, clocksource_mmio_readl_down))
+		panic("samsung_clocksource_timer: can't register clocksource\n");
+}
+
+static void __init samsung_timer_resources(void)
+{
+
+	unsigned long event_id = timer_source.event_id;
+	unsigned long source_id = timer_source.source_id;
+	char devname[15];
+
+	timerclk = clk_get(NULL, "timers");
+	if (IS_ERR(timerclk))
+		panic("failed to get timers clock for timer");
+
+	clk_enable(timerclk);
+
+	sprintf(devname, "s3c24xx-pwm.%lu", event_id);
+	s3c_device_timer[event_id].id = event_id;
+	s3c_device_timer[event_id].dev.init_name = devname;
+
+	tin_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tin");
+	if (IS_ERR(tin_event))
+		panic("failed to get pwm-tin clock for event timer");
+
+	tdiv_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tdiv");
+	if (IS_ERR(tdiv_event))
+		panic("failed to get pwm-tdiv clock for event timer");
+
+	clk_enable(tin_event);
+
+	sprintf(devname, "s3c24xx-pwm.%lu", source_id);
+	s3c_device_timer[source_id].id = source_id;
+	s3c_device_timer[source_id].dev.init_name = devname;
+
+	tin_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tin");
+	if (IS_ERR(tin_source))
+		panic("failed to get pwm-tin clock for source timer");
+
+	tdiv_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tdiv");
+	if (IS_ERR(tdiv_source))
+		panic("failed to get pwm-tdiv clock for source timer");
+
+	clk_enable(tin_source);
+}
+
+void __init samsung_timer_init(void)
+{
+	samsung_timer_resources();
+	samsung_clockevent_init();
+	samsung_clocksource_init();
+}
-- 
1.8.1.5

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

* [PATCH v4 01/14] ARM: SAMSUNG: Move samsung-time to drivers/clocksource
@ 2013-04-04 16:36   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:36 UTC (permalink / raw)
  To: linux-arm-kernel

This patch moves the Samsung PWM-based high resolution timer support
code from arch/arm/plat-samsung to drivers/clocksource.

This is a prerequisite for further work on making the driver more
multiplatform and Device Tree friendly.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/plat-samsung/Kconfig        |   8 -
 arch/arm/plat-samsung/Makefile       |   1 -
 arch/arm/plat-samsung/samsung-time.c | 394 -----------------------------------
 drivers/clocksource/Kconfig          |   7 +
 drivers/clocksource/Makefile         |   1 +
 drivers/clocksource/samsung-time.c   | 394 +++++++++++++++++++++++++++++++++++
 6 files changed, 402 insertions(+), 403 deletions(-)
 delete mode 100644 arch/arm/plat-samsung/samsung-time.c
 create mode 100644 drivers/clocksource/samsung-time.c

diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 54d1861..6f632ba 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -60,14 +60,6 @@ config S3C_LOWLEVEL_UART_PORT
 	  this configuration should be between zero and two. The port
 	  must have been initialised by the boot-loader before use.
 
-# timer options
-
-config SAMSUNG_HRT
-	bool
-	select SAMSUNG_DEV_PWM
-	help
-	  Use the High Resolution timer support
-
 # clock options
 
 config SAMSUNG_CLOCK
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index a23c460..87494e1 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -12,7 +12,6 @@ obj-				:=
 # Objects we always build independent of SoC choice
 
 obj-y				+= init.o cpu.o
-obj-$(CONFIG_SAMSUNG_HRT) 	+= samsung-time.o
 
 obj-$(CONFIG_SAMSUNG_CLOCK)	+= clock.o
 obj-$(CONFIG_SAMSUNG_CLOCK)	+= pwm-clock.o
diff --git a/arch/arm/plat-samsung/samsung-time.c b/arch/arm/plat-samsung/samsung-time.c
deleted file mode 100644
index f899cbc..0000000
--- a/arch/arm/plat-samsung/samsung-time.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * samsung - Common hr-timer support (s3c and s5p)
- *
- * 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.
-*/
-
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/clockchips.h>
-#include <linux/platform_device.h>
-
-#include <asm/smp_twd.h>
-#include <asm/mach/time.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/sched_clock.h>
-
-#include <mach/map.h>
-#include <plat/devs.h>
-#include <plat/regs-timer.h>
-#include <plat/samsung-time.h>
-
-static struct clk *tin_event;
-static struct clk *tin_source;
-static struct clk *tdiv_event;
-static struct clk *tdiv_source;
-static struct clk *timerclk;
-static struct samsung_timer_source timer_source;
-static unsigned long clock_count_per_tick;
-static void samsung_timer_resume(void);
-
-static void samsung_time_stop(enum samsung_timer_mode mode)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	switch (mode) {
-	case SAMSUNG_PWM0:
-		tcon &= ~S3C2410_TCON_T0START;
-		break;
-
-	case SAMSUNG_PWM1:
-		tcon &= ~S3C2410_TCON_T1START;
-		break;
-
-	case SAMSUNG_PWM2:
-		tcon &= ~S3C2410_TCON_T2START;
-		break;
-
-	case SAMSUNG_PWM3:
-		tcon &= ~S3C2410_TCON_T3START;
-		break;
-
-	case SAMSUNG_PWM4:
-		tcon &= ~S3C2410_TCON_T4START;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void samsung_time_setup(enum samsung_timer_mode mode, unsigned long tcnt)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	tcnt--;
-
-	switch (mode) {
-	case SAMSUNG_PWM0:
-		tcon &= ~(0x0f << 0);
-		tcon |= S3C2410_TCON_T0MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM1:
-		tcon &= ~(0x0f << 8);
-		tcon |= S3C2410_TCON_T1MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM2:
-		tcon &= ~(0x0f << 12);
-		tcon |= S3C2410_TCON_T2MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM3:
-		tcon &= ~(0x0f << 16);
-		tcon |= S3C2410_TCON_T3MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM4:
-		tcon &= ~(0x07 << 20);
-		tcon |= S3C2410_TCON_T4MANUALUPD;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-
-	__raw_writel(tcnt, S3C2410_TCNTB(mode));
-	__raw_writel(tcnt, S3C2410_TCMPB(mode));
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void samsung_time_start(enum samsung_timer_mode mode, bool periodic)
-{
-	unsigned long tcon;
-
-	tcon  = __raw_readl(S3C2410_TCON);
-
-	switch (mode) {
-	case SAMSUNG_PWM0:
-		tcon |= S3C2410_TCON_T0START;
-		tcon &= ~S3C2410_TCON_T0MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T0RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T0RELOAD;
-		break;
-
-	case SAMSUNG_PWM1:
-		tcon |= S3C2410_TCON_T1START;
-		tcon &= ~S3C2410_TCON_T1MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T1RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T1RELOAD;
-		break;
-
-	case SAMSUNG_PWM2:
-		tcon |= S3C2410_TCON_T2START;
-		tcon &= ~S3C2410_TCON_T2MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T2RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T2RELOAD;
-		break;
-
-	case SAMSUNG_PWM3:
-		tcon |= S3C2410_TCON_T3START;
-		tcon &= ~S3C2410_TCON_T3MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T3RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T3RELOAD;
-		break;
-
-	case SAMSUNG_PWM4:
-		tcon |= S3C2410_TCON_T4START;
-		tcon &= ~S3C2410_TCON_T4MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T4RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T4RELOAD;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static int samsung_set_next_event(unsigned long cycles,
-				struct clock_event_device *evt)
-{
-	samsung_time_setup(timer_source.event_id, cycles);
-	samsung_time_start(timer_source.event_id, NON_PERIODIC);
-
-	return 0;
-}
-
-static void samsung_set_mode(enum clock_event_mode mode,
-				struct clock_event_device *evt)
-{
-	samsung_time_stop(timer_source.event_id);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		samsung_time_setup(timer_source.event_id, clock_count_per_tick);
-		samsung_time_start(timer_source.event_id, PERIODIC);
-		break;
-
-	case CLOCK_EVT_MODE_ONESHOT:
-		break;
-
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-		break;
-
-	case CLOCK_EVT_MODE_RESUME:
-		samsung_timer_resume();
-		break;
-	}
-}
-
-static void samsung_timer_resume(void)
-{
-	/* event timer restart */
-	samsung_time_setup(timer_source.event_id, clock_count_per_tick);
-	samsung_time_start(timer_source.event_id, PERIODIC);
-
-	/* source timer restart */
-	samsung_time_setup(timer_source.source_id, TCNT_MAX);
-	samsung_time_start(timer_source.source_id, PERIODIC);
-}
-
-void __init samsung_set_timer_source(enum samsung_timer_mode event,
-				 enum samsung_timer_mode source)
-{
-	s3c_device_timer[event].dev.bus = &platform_bus_type;
-	s3c_device_timer[source].dev.bus = &platform_bus_type;
-
-	timer_source.event_id = event;
-	timer_source.source_id = source;
-}
-
-static struct clock_event_device time_event_device = {
-	.name		= "samsung_event_timer",
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.rating		= 200,
-	.set_next_event	= samsung_set_next_event,
-	.set_mode	= samsung_set_mode,
-};
-
-static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = dev_id;
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction samsung_clock_event_irq = {
-	.name		= "samsung_time_irq",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= samsung_clock_event_isr,
-	.dev_id		= &time_event_device,
-};
-
-static void __init samsung_clockevent_init(void)
-{
-	unsigned long pclk;
-	unsigned long clock_rate;
-	unsigned int irq_number;
-	struct clk *tscaler;
-
-	pclk = clk_get_rate(timerclk);
-
-	tscaler = clk_get_parent(tdiv_event);
-
-	clk_set_rate(tscaler, pclk / TSCALER_DIV);
-	clk_set_rate(tdiv_event, pclk / TDIV);
-	clk_set_parent(tin_event, tdiv_event);
-
-	clock_rate = clk_get_rate(tin_event);
-	clock_count_per_tick = clock_rate / HZ;
-
-	time_event_device.cpumask = cpumask_of(0);
-	clockevents_config_and_register(&time_event_device, clock_rate, 1, -1);
-
-	irq_number = timer_source.event_id + IRQ_TIMER0;
-	setup_irq(irq_number, &samsung_clock_event_irq);
-}
-
-static void __iomem *samsung_timer_reg(void)
-{
-	unsigned long offset = 0;
-
-	switch (timer_source.source_id) {
-	case SAMSUNG_PWM0:
-	case SAMSUNG_PWM1:
-	case SAMSUNG_PWM2:
-	case SAMSUNG_PWM3:
-		offset = (timer_source.source_id * 0x0c) + 0x14;
-		break;
-
-	case SAMSUNG_PWM4:
-		offset = 0x40;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
-		return NULL;
-	}
-
-	return S3C_TIMERREG(offset);
-}
-
-/*
- * Override the global weak sched_clock symbol with this
- * local implementation which uses the clocksource to get some
- * better resolution when scheduling the kernel. We accept that
- * this wraps around for now, since it is just a relative time
- * stamp. (Inspired by U300 implementation.)
- */
-static u32 notrace samsung_read_sched_clock(void)
-{
-	void __iomem *reg = samsung_timer_reg();
-
-	if (!reg)
-		return 0;
-
-	return ~__raw_readl(reg);
-}
-
-static void __init samsung_clocksource_init(void)
-{
-	unsigned long pclk;
-	unsigned long clock_rate;
-
-	pclk = clk_get_rate(timerclk);
-
-	clk_set_rate(tdiv_source, pclk / TDIV);
-	clk_set_parent(tin_source, tdiv_source);
-
-	clock_rate = clk_get_rate(tin_source);
-
-	samsung_time_setup(timer_source.source_id, TCNT_MAX);
-	samsung_time_start(timer_source.source_id, PERIODIC);
-
-	setup_sched_clock(samsung_read_sched_clock, TSIZE, clock_rate);
-
-	if (clocksource_mmio_init(samsung_timer_reg(), "samsung_clocksource_timer",
-			clock_rate, 250, TSIZE, clocksource_mmio_readl_down))
-		panic("samsung_clocksource_timer: can't register clocksource\n");
-}
-
-static void __init samsung_timer_resources(void)
-{
-
-	unsigned long event_id = timer_source.event_id;
-	unsigned long source_id = timer_source.source_id;
-	char devname[15];
-
-	timerclk = clk_get(NULL, "timers");
-	if (IS_ERR(timerclk))
-		panic("failed to get timers clock for timer");
-
-	clk_enable(timerclk);
-
-	sprintf(devname, "s3c24xx-pwm.%lu", event_id);
-	s3c_device_timer[event_id].id = event_id;
-	s3c_device_timer[event_id].dev.init_name = devname;
-
-	tin_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tin");
-	if (IS_ERR(tin_event))
-		panic("failed to get pwm-tin clock for event timer");
-
-	tdiv_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tdiv");
-	if (IS_ERR(tdiv_event))
-		panic("failed to get pwm-tdiv clock for event timer");
-
-	clk_enable(tin_event);
-
-	sprintf(devname, "s3c24xx-pwm.%lu", source_id);
-	s3c_device_timer[source_id].id = source_id;
-	s3c_device_timer[source_id].dev.init_name = devname;
-
-	tin_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tin");
-	if (IS_ERR(tin_source))
-		panic("failed to get pwm-tin clock for source timer");
-
-	tdiv_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tdiv");
-	if (IS_ERR(tdiv_source))
-		panic("failed to get pwm-tdiv clock for source timer");
-
-	clk_enable(tin_source);
-}
-
-void __init samsung_timer_init(void)
-{
-	samsung_timer_resources();
-	samsung_clockevent_init();
-	samsung_clocksource_init();
-}
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index e8c4532..dd20f6a 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -25,6 +25,13 @@ config DW_APB_TIMER_OF
 config ARMADA_370_XP_TIMER
 	bool
 
+config SAMSUNG_HRT
+	bool
+	depends on PLAT_SAMSUNG
+	select SAMSUNG_DEV_PWM
+	help
+	  Use the high resolution timer support on Samsung platforms.
+
 config SUNXI_TIMER
 	bool
 
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 1c1b15d..0d68580 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_CLKSRC_NOMADIK_MTU)	+= nomadik-mtu.o
 obj-$(CONFIG_CLKSRC_DBX500_PRCMU)	+= clksrc-dbx500-prcmu.o
 obj-$(CONFIG_ARMADA_370_XP_TIMER)	+= time-armada-370-xp.o
 obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835_timer.o
+obj-$(CONFIG_SAMSUNG_HRT) 	+= samsung-time.o
 obj-$(CONFIG_SUNXI_TIMER)	+= sunxi_timer.o
 obj-$(CONFIG_ARCH_TEGRA)	+= tegra20_timer.o
 obj-$(CONFIG_VT8500_TIMER)	+= vt8500_timer.o
diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
new file mode 100644
index 0000000..f899cbc
--- /dev/null
+++ b/drivers/clocksource/samsung-time.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * samsung - Common hr-timer support (s3c and s5p)
+ *
+ * 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.
+*/
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/platform_device.h>
+
+#include <asm/smp_twd.h>
+#include <asm/mach/time.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/sched_clock.h>
+
+#include <mach/map.h>
+#include <plat/devs.h>
+#include <plat/regs-timer.h>
+#include <plat/samsung-time.h>
+
+static struct clk *tin_event;
+static struct clk *tin_source;
+static struct clk *tdiv_event;
+static struct clk *tdiv_source;
+static struct clk *timerclk;
+static struct samsung_timer_source timer_source;
+static unsigned long clock_count_per_tick;
+static void samsung_timer_resume(void);
+
+static void samsung_time_stop(enum samsung_timer_mode mode)
+{
+	unsigned long tcon;
+
+	tcon = __raw_readl(S3C2410_TCON);
+
+	switch (mode) {
+	case SAMSUNG_PWM0:
+		tcon &= ~S3C2410_TCON_T0START;
+		break;
+
+	case SAMSUNG_PWM1:
+		tcon &= ~S3C2410_TCON_T1START;
+		break;
+
+	case SAMSUNG_PWM2:
+		tcon &= ~S3C2410_TCON_T2START;
+		break;
+
+	case SAMSUNG_PWM3:
+		tcon &= ~S3C2410_TCON_T3START;
+		break;
+
+	case SAMSUNG_PWM4:
+		tcon &= ~S3C2410_TCON_T4START;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", mode);
+		break;
+	}
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static void samsung_time_setup(enum samsung_timer_mode mode, unsigned long tcnt)
+{
+	unsigned long tcon;
+
+	tcon = __raw_readl(S3C2410_TCON);
+
+	tcnt--;
+
+	switch (mode) {
+	case SAMSUNG_PWM0:
+		tcon &= ~(0x0f << 0);
+		tcon |= S3C2410_TCON_T0MANUALUPD;
+		break;
+
+	case SAMSUNG_PWM1:
+		tcon &= ~(0x0f << 8);
+		tcon |= S3C2410_TCON_T1MANUALUPD;
+		break;
+
+	case SAMSUNG_PWM2:
+		tcon &= ~(0x0f << 12);
+		tcon |= S3C2410_TCON_T2MANUALUPD;
+		break;
+
+	case SAMSUNG_PWM3:
+		tcon &= ~(0x0f << 16);
+		tcon |= S3C2410_TCON_T3MANUALUPD;
+		break;
+
+	case SAMSUNG_PWM4:
+		tcon &= ~(0x07 << 20);
+		tcon |= S3C2410_TCON_T4MANUALUPD;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", mode);
+		break;
+	}
+
+	__raw_writel(tcnt, S3C2410_TCNTB(mode));
+	__raw_writel(tcnt, S3C2410_TCMPB(mode));
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static void samsung_time_start(enum samsung_timer_mode mode, bool periodic)
+{
+	unsigned long tcon;
+
+	tcon  = __raw_readl(S3C2410_TCON);
+
+	switch (mode) {
+	case SAMSUNG_PWM0:
+		tcon |= S3C2410_TCON_T0START;
+		tcon &= ~S3C2410_TCON_T0MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T0RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T0RELOAD;
+		break;
+
+	case SAMSUNG_PWM1:
+		tcon |= S3C2410_TCON_T1START;
+		tcon &= ~S3C2410_TCON_T1MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T1RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T1RELOAD;
+		break;
+
+	case SAMSUNG_PWM2:
+		tcon |= S3C2410_TCON_T2START;
+		tcon &= ~S3C2410_TCON_T2MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T2RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T2RELOAD;
+		break;
+
+	case SAMSUNG_PWM3:
+		tcon |= S3C2410_TCON_T3START;
+		tcon &= ~S3C2410_TCON_T3MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T3RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T3RELOAD;
+		break;
+
+	case SAMSUNG_PWM4:
+		tcon |= S3C2410_TCON_T4START;
+		tcon &= ~S3C2410_TCON_T4MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T4RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T4RELOAD;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", mode);
+		break;
+	}
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static int samsung_set_next_event(unsigned long cycles,
+				struct clock_event_device *evt)
+{
+	samsung_time_setup(timer_source.event_id, cycles);
+	samsung_time_start(timer_source.event_id, NON_PERIODIC);
+
+	return 0;
+}
+
+static void samsung_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	samsung_time_stop(timer_source.event_id);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		samsung_time_setup(timer_source.event_id, clock_count_per_tick);
+		samsung_time_start(timer_source.event_id, PERIODIC);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+		samsung_timer_resume();
+		break;
+	}
+}
+
+static void samsung_timer_resume(void)
+{
+	/* event timer restart */
+	samsung_time_setup(timer_source.event_id, clock_count_per_tick);
+	samsung_time_start(timer_source.event_id, PERIODIC);
+
+	/* source timer restart */
+	samsung_time_setup(timer_source.source_id, TCNT_MAX);
+	samsung_time_start(timer_source.source_id, PERIODIC);
+}
+
+void __init samsung_set_timer_source(enum samsung_timer_mode event,
+				 enum samsung_timer_mode source)
+{
+	s3c_device_timer[event].dev.bus = &platform_bus_type;
+	s3c_device_timer[source].dev.bus = &platform_bus_type;
+
+	timer_source.event_id = event;
+	timer_source.source_id = source;
+}
+
+static struct clock_event_device time_event_device = {
+	.name		= "samsung_event_timer",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 200,
+	.set_next_event	= samsung_set_next_event,
+	.set_mode	= samsung_set_mode,
+};
+
+static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction samsung_clock_event_irq = {
+	.name		= "samsung_time_irq",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= samsung_clock_event_isr,
+	.dev_id		= &time_event_device,
+};
+
+static void __init samsung_clockevent_init(void)
+{
+	unsigned long pclk;
+	unsigned long clock_rate;
+	unsigned int irq_number;
+	struct clk *tscaler;
+
+	pclk = clk_get_rate(timerclk);
+
+	tscaler = clk_get_parent(tdiv_event);
+
+	clk_set_rate(tscaler, pclk / TSCALER_DIV);
+	clk_set_rate(tdiv_event, pclk / TDIV);
+	clk_set_parent(tin_event, tdiv_event);
+
+	clock_rate = clk_get_rate(tin_event);
+	clock_count_per_tick = clock_rate / HZ;
+
+	time_event_device.cpumask = cpumask_of(0);
+	clockevents_config_and_register(&time_event_device, clock_rate, 1, -1);
+
+	irq_number = timer_source.event_id + IRQ_TIMER0;
+	setup_irq(irq_number, &samsung_clock_event_irq);
+}
+
+static void __iomem *samsung_timer_reg(void)
+{
+	unsigned long offset = 0;
+
+	switch (timer_source.source_id) {
+	case SAMSUNG_PWM0:
+	case SAMSUNG_PWM1:
+	case SAMSUNG_PWM2:
+	case SAMSUNG_PWM3:
+		offset = (timer_source.source_id * 0x0c) + 0x14;
+		break;
+
+	case SAMSUNG_PWM4:
+		offset = 0x40;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
+		return NULL;
+	}
+
+	return S3C_TIMERREG(offset);
+}
+
+/*
+ * Override the global weak sched_clock symbol with this
+ * local implementation which uses the clocksource to get some
+ * better resolution when scheduling the kernel. We accept that
+ * this wraps around for now, since it is just a relative time
+ * stamp. (Inspired by U300 implementation.)
+ */
+static u32 notrace samsung_read_sched_clock(void)
+{
+	void __iomem *reg = samsung_timer_reg();
+
+	if (!reg)
+		return 0;
+
+	return ~__raw_readl(reg);
+}
+
+static void __init samsung_clocksource_init(void)
+{
+	unsigned long pclk;
+	unsigned long clock_rate;
+
+	pclk = clk_get_rate(timerclk);
+
+	clk_set_rate(tdiv_source, pclk / TDIV);
+	clk_set_parent(tin_source, tdiv_source);
+
+	clock_rate = clk_get_rate(tin_source);
+
+	samsung_time_setup(timer_source.source_id, TCNT_MAX);
+	samsung_time_start(timer_source.source_id, PERIODIC);
+
+	setup_sched_clock(samsung_read_sched_clock, TSIZE, clock_rate);
+
+	if (clocksource_mmio_init(samsung_timer_reg(), "samsung_clocksource_timer",
+			clock_rate, 250, TSIZE, clocksource_mmio_readl_down))
+		panic("samsung_clocksource_timer: can't register clocksource\n");
+}
+
+static void __init samsung_timer_resources(void)
+{
+
+	unsigned long event_id = timer_source.event_id;
+	unsigned long source_id = timer_source.source_id;
+	char devname[15];
+
+	timerclk = clk_get(NULL, "timers");
+	if (IS_ERR(timerclk))
+		panic("failed to get timers clock for timer");
+
+	clk_enable(timerclk);
+
+	sprintf(devname, "s3c24xx-pwm.%lu", event_id);
+	s3c_device_timer[event_id].id = event_id;
+	s3c_device_timer[event_id].dev.init_name = devname;
+
+	tin_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tin");
+	if (IS_ERR(tin_event))
+		panic("failed to get pwm-tin clock for event timer");
+
+	tdiv_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tdiv");
+	if (IS_ERR(tdiv_event))
+		panic("failed to get pwm-tdiv clock for event timer");
+
+	clk_enable(tin_event);
+
+	sprintf(devname, "s3c24xx-pwm.%lu", source_id);
+	s3c_device_timer[source_id].id = source_id;
+	s3c_device_timer[source_id].dev.init_name = devname;
+
+	tin_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tin");
+	if (IS_ERR(tin_source))
+		panic("failed to get pwm-tin clock for source timer");
+
+	tdiv_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tdiv");
+	if (IS_ERR(tdiv_source))
+		panic("failed to get pwm-tdiv clock for source timer");
+
+	clk_enable(tin_source);
+}
+
+void __init samsung_timer_init(void)
+{
+	samsung_timer_resources();
+	samsung_clockevent_init();
+	samsung_clocksource_init();
+}
-- 
1.8.1.5

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

* [PATCH v4 02/14] clocksource: samsung-time: Drop useless defines from public header
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 16:36   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:36 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

This patch cleans up public header from useless definitions.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/plat-samsung/include/plat/samsung-time.h |  6 ------
 drivers/clocksource/samsung-time.c                | 10 +++++-----
 2 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/arch/arm/plat-samsung/include/plat/samsung-time.h b/arch/arm/plat-samsung/include/plat/samsung-time.h
index 4cc99bb..5d098ef 100644
--- a/arch/arm/plat-samsung/include/plat/samsung-time.h
+++ b/arch/arm/plat-samsung/include/plat/samsung-time.h
@@ -27,9 +27,6 @@ struct samsung_timer_source {
 	unsigned int source_id;
 };
 
-/* Be able to sleep for atleast 4 seconds (usually more) */
-#define SAMSUNG_TIMER_MIN_RANGE	4
-
 #if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S5PC100)
 #define TCNT_MAX		0xffff
 #define TSCALER_DIV		25
@@ -42,9 +39,6 @@ struct samsung_timer_source {
 #define TSIZE			32
 #endif
 
-#define NON_PERIODIC		0
-#define PERIODIC		1
-
 extern void __init samsung_set_timer_source(enum samsung_timer_mode event,
 					enum samsung_timer_mode source);
 
diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index f899cbc..d4d7e3e 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -182,7 +182,7 @@ static int samsung_set_next_event(unsigned long cycles,
 				struct clock_event_device *evt)
 {
 	samsung_time_setup(timer_source.event_id, cycles);
-	samsung_time_start(timer_source.event_id, NON_PERIODIC);
+	samsung_time_start(timer_source.event_id, false);
 
 	return 0;
 }
@@ -195,7 +195,7 @@ static void samsung_set_mode(enum clock_event_mode mode,
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		samsung_time_setup(timer_source.event_id, clock_count_per_tick);
-		samsung_time_start(timer_source.event_id, PERIODIC);
+		samsung_time_start(timer_source.event_id, true);
 		break;
 
 	case CLOCK_EVT_MODE_ONESHOT:
@@ -215,11 +215,11 @@ static void samsung_timer_resume(void)
 {
 	/* event timer restart */
 	samsung_time_setup(timer_source.event_id, clock_count_per_tick);
-	samsung_time_start(timer_source.event_id, PERIODIC);
+	samsung_time_start(timer_source.event_id, true);
 
 	/* source timer restart */
 	samsung_time_setup(timer_source.source_id, TCNT_MAX);
-	samsung_time_start(timer_source.source_id, PERIODIC);
+	samsung_time_start(timer_source.source_id, true);
 }
 
 void __init samsung_set_timer_source(enum samsung_timer_mode event,
@@ -335,7 +335,7 @@ static void __init samsung_clocksource_init(void)
 	clock_rate = clk_get_rate(tin_source);
 
 	samsung_time_setup(timer_source.source_id, TCNT_MAX);
-	samsung_time_start(timer_source.source_id, PERIODIC);
+	samsung_time_start(timer_source.source_id, true);
 
 	setup_sched_clock(samsung_read_sched_clock, TSIZE, clock_rate);
 
-- 
1.8.1.5

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

* [PATCH v4 02/14] clocksource: samsung-time: Drop useless defines from public header
@ 2013-04-04 16:36   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:36 UTC (permalink / raw)
  To: linux-arm-kernel

This patch cleans up public header from useless definitions.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/plat-samsung/include/plat/samsung-time.h |  6 ------
 drivers/clocksource/samsung-time.c                | 10 +++++-----
 2 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/arch/arm/plat-samsung/include/plat/samsung-time.h b/arch/arm/plat-samsung/include/plat/samsung-time.h
index 4cc99bb..5d098ef 100644
--- a/arch/arm/plat-samsung/include/plat/samsung-time.h
+++ b/arch/arm/plat-samsung/include/plat/samsung-time.h
@@ -27,9 +27,6 @@ struct samsung_timer_source {
 	unsigned int source_id;
 };
 
-/* Be able to sleep for atleast 4 seconds (usually more) */
-#define SAMSUNG_TIMER_MIN_RANGE	4
-
 #if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S5PC100)
 #define TCNT_MAX		0xffff
 #define TSCALER_DIV		25
@@ -42,9 +39,6 @@ struct samsung_timer_source {
 #define TSIZE			32
 #endif
 
-#define NON_PERIODIC		0
-#define PERIODIC		1
-
 extern void __init samsung_set_timer_source(enum samsung_timer_mode event,
 					enum samsung_timer_mode source);
 
diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index f899cbc..d4d7e3e 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -182,7 +182,7 @@ static int samsung_set_next_event(unsigned long cycles,
 				struct clock_event_device *evt)
 {
 	samsung_time_setup(timer_source.event_id, cycles);
-	samsung_time_start(timer_source.event_id, NON_PERIODIC);
+	samsung_time_start(timer_source.event_id, false);
 
 	return 0;
 }
@@ -195,7 +195,7 @@ static void samsung_set_mode(enum clock_event_mode mode,
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		samsung_time_setup(timer_source.event_id, clock_count_per_tick);
-		samsung_time_start(timer_source.event_id, PERIODIC);
+		samsung_time_start(timer_source.event_id, true);
 		break;
 
 	case CLOCK_EVT_MODE_ONESHOT:
@@ -215,11 +215,11 @@ static void samsung_timer_resume(void)
 {
 	/* event timer restart */
 	samsung_time_setup(timer_source.event_id, clock_count_per_tick);
-	samsung_time_start(timer_source.event_id, PERIODIC);
+	samsung_time_start(timer_source.event_id, true);
 
 	/* source timer restart */
 	samsung_time_setup(timer_source.source_id, TCNT_MAX);
-	samsung_time_start(timer_source.source_id, PERIODIC);
+	samsung_time_start(timer_source.source_id, true);
 }
 
 void __init samsung_set_timer_source(enum samsung_timer_mode event,
@@ -335,7 +335,7 @@ static void __init samsung_clocksource_init(void)
 	clock_rate = clk_get_rate(tin_source);
 
 	samsung_time_setup(timer_source.source_id, TCNT_MAX);
-	samsung_time_start(timer_source.source_id, PERIODIC);
+	samsung_time_start(timer_source.source_id, true);
 
 	setup_sched_clock(samsung_read_sched_clock, TSIZE, clock_rate);
 
-- 
1.8.1.5

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

* [PATCH v4 03/14] clocksource: samsung-time: Use local register definitions
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 16:37   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

This patch copies PWM timer register definitions to samsung-time.c. The
original header in plat is being kept for now, since it is also used by
other code that also needs to be reworked to be multiplatform-friendly.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/clocksource/samsung-time.c | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index d4d7e3e..bccc291 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -24,9 +24,43 @@
 
 #include <mach/map.h>
 #include <plat/devs.h>
-#include <plat/regs-timer.h>
 #include <plat/samsung-time.h>
 
+#define S3C_TIMERREG(x) (S3C_VA_TIMER + (x))
+#define S3C_TIMERREG2(tmr,reg) S3C_TIMERREG((reg)+0x0c+((tmr)*0x0c))
+
+#define S3C2410_TCON	      S3C_TIMERREG(0x08)
+#define S3C64XX_TINT_CSTAT    S3C_TIMERREG(0x44)
+
+/* for each timer, we have an count buffer, an compare buffer and
+ * an observation buffer
+*/
+
+/* WARNING - timer 4 has no buffer reg, and it's observation is at +4 */
+
+#define S3C2410_TCNTB(tmr)    S3C_TIMERREG2(tmr, 0x00)
+#define S3C2410_TCMPB(tmr)    S3C_TIMERREG2(tmr, 0x04)
+
+#define S3C2410_TCON_T4RELOAD	  (1<<22)
+#define S3C2410_TCON_T4MANUALUPD  (1<<21)
+#define S3C2410_TCON_T4START	  (1<<20)
+
+#define S3C2410_TCON_T3RELOAD	  (1<<19)
+#define S3C2410_TCON_T3MANUALUPD  (1<<17)
+#define S3C2410_TCON_T3START	  (1<<16)
+
+#define S3C2410_TCON_T2RELOAD	  (1<<15)
+#define S3C2410_TCON_T2MANUALUPD  (1<<13)
+#define S3C2410_TCON_T2START	  (1<<12)
+
+#define S3C2410_TCON_T1RELOAD	  (1<<11)
+#define S3C2410_TCON_T1MANUALUPD  (1<<9)
+#define S3C2410_TCON_T1START	  (1<<8)
+
+#define S3C2410_TCON_T0RELOAD	  (1<<3)
+#define S3C2410_TCON_T0MANUALUPD  (1<<1)
+#define S3C2410_TCON_T0START	  (1<<0)
+
 static struct clk *tin_event;
 static struct clk *tin_source;
 static struct clk *tdiv_event;
-- 
1.8.1.5

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

* [PATCH v4 03/14] clocksource: samsung-time: Use local register definitions
@ 2013-04-04 16:37   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

This patch copies PWM timer register definitions to samsung-time.c. The
original header in plat is being kept for now, since it is also used by
other code that also needs to be reworked to be multiplatform-friendly.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/clocksource/samsung-time.c | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index d4d7e3e..bccc291 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -24,9 +24,43 @@
 
 #include <mach/map.h>
 #include <plat/devs.h>
-#include <plat/regs-timer.h>
 #include <plat/samsung-time.h>
 
+#define S3C_TIMERREG(x) (S3C_VA_TIMER + (x))
+#define S3C_TIMERREG2(tmr,reg) S3C_TIMERREG((reg)+0x0c+((tmr)*0x0c))
+
+#define S3C2410_TCON	      S3C_TIMERREG(0x08)
+#define S3C64XX_TINT_CSTAT    S3C_TIMERREG(0x44)
+
+/* for each timer, we have an count buffer, an compare buffer and
+ * an observation buffer
+*/
+
+/* WARNING - timer 4 has no buffer reg, and it's observation is at +4 */
+
+#define S3C2410_TCNTB(tmr)    S3C_TIMERREG2(tmr, 0x00)
+#define S3C2410_TCMPB(tmr)    S3C_TIMERREG2(tmr, 0x04)
+
+#define S3C2410_TCON_T4RELOAD	  (1<<22)
+#define S3C2410_TCON_T4MANUALUPD  (1<<21)
+#define S3C2410_TCON_T4START	  (1<<20)
+
+#define S3C2410_TCON_T3RELOAD	  (1<<19)
+#define S3C2410_TCON_T3MANUALUPD  (1<<17)
+#define S3C2410_TCON_T3START	  (1<<16)
+
+#define S3C2410_TCON_T2RELOAD	  (1<<15)
+#define S3C2410_TCON_T2MANUALUPD  (1<<13)
+#define S3C2410_TCON_T2START	  (1<<12)
+
+#define S3C2410_TCON_T1RELOAD	  (1<<11)
+#define S3C2410_TCON_T1MANUALUPD  (1<<9)
+#define S3C2410_TCON_T1START	  (1<<8)
+
+#define S3C2410_TCON_T0RELOAD	  (1<<3)
+#define S3C2410_TCON_T0MANUALUPD  (1<<1)
+#define S3C2410_TCON_T0START	  (1<<0)
+
 static struct clk *tin_event;
 static struct clk *tin_source;
 static struct clk *tdiv_event;
-- 
1.8.1.5

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

* [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 16:37   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

This patch adds master driver for PWM/timer block available on many
Samsung SoCs providing clocksource and PWM output capabilities.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 .../devicetree/bindings/pwm/pwm-samsung.txt        |  37 ++
 drivers/clocksource/Kconfig                        |   1 +
 drivers/mfd/Kconfig                                |   3 +
 drivers/mfd/Makefile                               |   1 +
 drivers/mfd/samsung-pwm.c                          | 439 +++++++++++++++++++++
 drivers/pwm/Kconfig                                |   1 +
 include/linux/mfd/samsung-pwm.h                    |  49 +++
 include/linux/platform_data/samsung-pwm.h          |  28 ++
 8 files changed, 559 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/pwm-samsung.txt
 create mode 100644 drivers/mfd/samsung-pwm.c
 create mode 100644 include/linux/mfd/samsung-pwm.h
 create mode 100644 include/linux/platform_data/samsung-pwm.h

diff --git a/Documentation/devicetree/bindings/pwm/pwm-samsung.txt b/Documentation/devicetree/bindings/pwm/pwm-samsung.txt
new file mode 100644
index 0000000..8ed4c11
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-samsung.txt
@@ -0,0 +1,37 @@
+* Samsung PWM timers
+
+Samsung SoCs contain PWM timer blocks which can be used for system clock source
+and clock event timers, as well as to drive SoC outputs with PWM signal. Each
+PWM timer block provides 5 PWM channels (not all of them can drive physical
+outputs - see SoC and board manual).
+
+Be aware that this driver supports clock event only on CPU 0. It can
+provide SMP support together with ARM dummy_timer, but only in periodic tick
+mode.
+
+Required properties:
+- compatible : should be one of following:
+    samsung,s3c2410-pwm - for 16-bit timers present on S3C24xx SoCs
+    samsung,s3c6400-pwm - for 32-bit timers present on S3C64xx SoCs
+    samsung,s5p6440-pwm - for 32-bit timers present on S5P64x0 SoCs
+    samsung,s5pc100-pwm - for 32-bit timers present on S5PC100, S5PV210,
+			  Exynos4210, Exynos4x12 and Exynos5250 SoCs
+- reg: base address and size of register area
+- interrupts: list of timer interrupts (one interrupt per timer, starting at
+  timer 0)
+- #pwm-cells: number of cells used for PWM specifier - must be 2
+
+Optional properties:
+- samsung,pwm-outputs: list of PWM channels used as PWM outputs on particular
+    platform - an array of up to 5 elements being indices of PWM channels
+    (from 0 to 4), the order does not matter.
+
+Example:
+	pwm@7f006000 {
+		compatible = "samsung,s3c6400-pwm";
+		reg = <0x7f006000 0x1000>;
+		interrupt-parent = <&vic0>;
+		interrupts = <23>, <24>, <25>, <27>, <28>;
+		samsung,pwm-outputs = <0>, <1>;
+		#pwm-cells = <2>;
+	}
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index dd20f6a..a69a5b7 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -29,6 +29,7 @@ config SAMSUNG_HRT
 	bool
 	depends on PLAT_SAMSUNG
 	select SAMSUNG_DEV_PWM
+	select MFD_SAMSUNG_PWM
 	help
 	  Use the high resolution timer support on Samsung platforms.
 
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 3ab3a11..c25425c 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1015,6 +1015,9 @@ config MFD_PM8XXX_IRQ
 	  This is required to use certain other PM 8xxx features, such as GPIO
 	  and MPP.
 
+config MFD_SAMSUNG_PWM
+	bool
+
 config TPS65911_COMPARATOR
 	tristate
 
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index b90409c..513d9c9 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -145,6 +145,7 @@ obj-$(CONFIG_MFD_RC5T583)	+= rc5t583.o rc5t583-irq.o
 obj-$(CONFIG_MFD_SEC_CORE)	+= sec-core.o sec-irq.o
 obj-$(CONFIG_MFD_SYSCON)	+= syscon.o
 obj-$(CONFIG_MFD_LM3533)	+= lm3533-core.o lm3533-ctrlbank.o
+obj-$(CONFIG_MFD_SAMSUNG_PWM)	+= samsung-pwm.o
 obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o vexpress-sysreg.o
 obj-$(CONFIG_MFD_RETU)		+= retu-mfd.o
 obj-$(CONFIG_MFD_AS3711)	+= as3711.o
diff --git a/drivers/mfd/samsung-pwm.c b/drivers/mfd/samsung-pwm.c
new file mode 100644
index 0000000..ece426e
--- /dev/null
+++ b/drivers/mfd/samsung-pwm.c
@@ -0,0 +1,439 @@
+/*
+ * Samsung PWM/timers MFD driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *
+ * Author: Tomasz Figa <t.figa@samsung.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.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/mfd/samsung-pwm.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_data/samsung-pwm.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#define REG_TCFG0			0x00
+#define REG_TCFG1			0x04
+#define REG_TCON			0x08
+
+#define REG_TCNTB(chan)			(0x0c + 12 * (chan))
+#define REG_TCMPB(chan)			(0x10 + 12 * (chan))
+
+#define TCON_START(chan)		(1 << (4 * (chan) + 0))
+#define TCON_MANUALUPDATE(chan)		(1 << (4 * (chan) + 1))
+#define TCON_INVERT(chan)		(1 << (4 * (chan) + 2))
+#define TCON_AUTORELOAD(chan)		(1 << (4 * (chan) + 3))
+
+#define TCFG0_PRESCALER_MASK		0xff
+#define TCFG0_PRESCALER1_SHIFT		8
+
+#define TCFG1_SHIFT(x)	  		((x) * 4)
+#define TCFG1_MUX_MASK	  		0xf
+
+struct samsung_pwm_drvdata {
+	struct samsung_pwm pwm;
+	struct platform_device *pdev;
+	struct resource resource;
+	struct list_head list;
+	spinlock_t slock;
+	unsigned long request_mask;
+};
+
+static LIST_HEAD(pwm_list);
+
+static inline struct samsung_pwm_drvdata *to_drvdata(struct samsung_pwm *pwm)
+{
+	return container_of(pwm, struct samsung_pwm_drvdata, pwm);
+}
+
+void samsung_pwm_start(struct samsung_pwm *pwm,
+					unsigned int channel, bool periodic)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+	unsigned long flags;
+	u32 reg;
+
+	if (channel > 0)
+		++channel;
+
+	spin_lock_irqsave(&drvdata->slock, flags);
+
+	reg = readl(pwm->base + REG_TCON);
+	reg &= ~TCON_MANUALUPDATE(channel);
+	reg |= TCON_START(channel);
+	if (periodic)
+		reg |= TCON_AUTORELOAD(channel);
+	else
+		reg &= ~TCON_AUTORELOAD(channel);
+	writel(reg, pwm->base + REG_TCON);
+
+	spin_unlock_irqrestore(&drvdata->slock, flags);
+}
+EXPORT_SYMBOL(samsung_pwm_start);
+
+void samsung_pwm_stop(struct samsung_pwm *pwm, unsigned int channel)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+	unsigned long flags;
+	u32 reg;
+
+	if (channel > 0)
+		++channel;
+
+	spin_lock_irqsave(&drvdata->slock, flags);
+
+	reg = readl(pwm->base + REG_TCON);
+	reg &= ~TCON_START(channel);
+	writel(reg, pwm->base + REG_TCON);
+
+	spin_unlock_irqrestore(&drvdata->slock, flags);
+}
+EXPORT_SYMBOL(samsung_pwm_stop);
+
+void samsung_pwm_setup(struct samsung_pwm *pwm, unsigned int channel,
+							u32 tcmp, u32 tcnt)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+	unsigned long flags;
+	u32 reg;
+
+	writel(tcnt, pwm->base + REG_TCNTB(channel));
+	writel(tcmp, pwm->base + REG_TCMPB(channel));
+
+	if (channel > 0)
+		++channel;
+
+	spin_lock_irqsave(&drvdata->slock, flags);
+
+	reg = readl(pwm->base + REG_TCON);
+	reg &= ~TCON_START(channel);
+	reg |= TCON_MANUALUPDATE(channel);
+	writel(reg, pwm->base + REG_TCON);
+
+	spin_unlock_irqrestore(&drvdata->slock, flags);
+}
+EXPORT_SYMBOL(samsung_pwm_setup);
+
+void samsung_pwm_set_flags(struct samsung_pwm *pwm,
+					unsigned int channel, u32 pwm_flags)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+	unsigned long flags;
+	u32 reg;
+
+	if (channel > 0)
+		++channel;
+
+	spin_lock_irqsave(&drvdata->slock, flags);
+
+	reg = readl(pwm->base + REG_TCON);
+
+	if (pwm_flags & SAMSUNG_PWM_INVERT)
+		reg |= TCON_INVERT(channel);
+	else
+		reg &= ~TCON_INVERT(channel);
+
+	writel(reg, pwm->base + REG_TCON);
+
+	spin_unlock_irqrestore(&drvdata->slock, flags);
+}
+EXPORT_SYMBOL(samsung_pwm_set_flags);
+
+void samsung_pwm_set_prescale(struct samsung_pwm *pwm,
+					unsigned int channel, u16 prescale)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+	unsigned long flags;
+	u8 shift = 0;
+	u32 reg;
+
+	if (channel >= 2)
+		shift = TCFG0_PRESCALER1_SHIFT;
+
+	spin_lock_irqsave(&drvdata->slock, flags);
+
+	reg = readl(pwm->base + REG_TCFG0);
+	reg &= ~(TCFG0_PRESCALER_MASK << shift);
+	reg |= (prescale - 1) << shift;
+	writel(reg, pwm->base + REG_TCFG0);
+
+	spin_unlock_irqrestore(&drvdata->slock, flags);
+}
+EXPORT_SYMBOL(samsung_pwm_set_prescale);
+
+void samsung_pwm_set_divisor(struct samsung_pwm *pwm,
+					unsigned int channel, u8 divisor)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+	u8 shift = TCFG1_SHIFT(channel);
+	unsigned long flags;
+	u32 reg;
+	u8 bits;
+
+	bits = (fls(divisor) - 1) - pwm->variant.div_base;
+
+	spin_lock_irqsave(&drvdata->slock, flags);
+
+	reg = readl(pwm->base + REG_TCFG1);
+	reg &= ~(TCFG1_MUX_MASK << shift);
+	reg |= bits << shift;
+	writel(reg, pwm->base + REG_TCFG1);
+
+	spin_unlock_irqrestore(&drvdata->slock, flags);
+}
+EXPORT_SYMBOL(samsung_pwm_set_divisor);
+
+int samsung_pwm_request(struct samsung_pwm *pwm, unsigned int channel)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+
+	if (test_and_set_bit(channel, &drvdata->request_mask))
+		return -EBUSY;
+
+	return 0;
+}
+EXPORT_SYMBOL(samsung_pwm_request);
+
+void samsung_pwm_free(struct samsung_pwm *pwm, unsigned int channel)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+
+	clear_bit(channel, &drvdata->request_mask);
+}
+EXPORT_SYMBOL(samsung_pwm_free);
+
+#ifdef CONFIG_OF
+static int samsung_pwm_parse_dt(struct samsung_pwm *pwm)
+{
+	struct samsung_pwm_variant *variant = &pwm->variant;
+	struct device_node *np = pwm->of_node;
+	struct property *prop;
+	const __be32 *cur;
+	u32 val;
+	int i;
+
+	for (i = 0; i < SAMSUNG_PWM_NUM; ++i)
+		pwm->irq[i] = irq_of_parse_and_map(np, i);
+
+	of_property_for_each_u32(np, "samsung,pwm-outputs", prop, cur, val) {
+		if (val >= SAMSUNG_PWM_NUM) {
+			pr_warning("%s: invalid channel index in samsung,pwm-outputs property\n",
+								__func__);
+			continue;
+		}
+		variant->output_mask |= 1 << val;
+	}
+
+	return 0;
+}
+
+static const struct samsung_pwm_variant s3c24xx_variant = {
+	.bits		= 16,
+	.div_base	= 1,
+	.has_tint_cstat	= false,
+	.tclk_mask	= (1 << 4),
+};
+
+static const struct samsung_pwm_variant s3c64xx_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= (1 << 7) | (1 << 6) | (1 << 5),
+};
+
+static const struct samsung_pwm_variant s5p64x0_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= 0,
+};
+
+static const struct samsung_pwm_variant s5p_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= (1 << 5),
+};
+
+static const struct of_device_id samsung_pwm_matches[] = {
+	{ .compatible = "samsung,s3c2410-pwm", .data = &s3c24xx_variant, },
+	{ .compatible = "samsung,s3c6400-pwm", .data = &s3c64xx_variant, },
+	{ .compatible = "samsung,s5p6440-pwm", .data = &s5p64x0_variant, },
+	{ .compatible = "samsung,s5pc100-pwm", .data = &s5p_variant, },
+	{},
+};
+
+static struct samsung_pwm_drvdata *samsung_pwm_of_add(struct device_node *np)
+{
+	const struct samsung_pwm_variant *variant;
+	const struct of_device_id *match;
+	struct samsung_pwm_drvdata *pwm;
+	int ret;
+
+	if (!np) {
+		np = of_find_matching_node(NULL, samsung_pwm_matches);
+		if (!np) {
+			pr_err("%s: could not find PWM device\n", __func__);
+			return ERR_PTR(-ENODEV);
+		}
+	}
+
+	match = of_match_node(samsung_pwm_matches, np);
+	if (!match) {
+		pr_err("%s: failed to match given OF node\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+	variant = match->data;
+
+	pwm = kzalloc(sizeof(*pwm), GFP_KERNEL);
+	if (!pwm) {
+		pr_err("%s: could not allocate PWM device struct\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pwm->pwm.variant = *variant;
+	pwm->pwm.of_node = np;
+	spin_lock_init(&pwm->slock);
+
+	ret = of_address_to_resource(np, 0, &pwm->resource);
+	if (ret < 0) {
+		pr_err("%s: could not get IO resource\n", __func__);
+		goto err_free;
+	}
+
+	ret = samsung_pwm_parse_dt(&pwm->pwm);
+	if (ret < 0) {
+		pr_err("%s: failed to parse device tree node\n", __func__);
+		goto err_free;
+	}
+
+	list_add_tail(&pwm->list, &pwm_list);
+
+	return pwm;
+
+err_free:
+	kfree(pwm);
+
+	return ERR_PTR(ret);
+}
+#else
+static struct samsung_pwm_drvdata *samsung_pwm_of_add(struct device_node *np)
+{
+	return ERR_PTR(-ENODEV);
+}
+#endif
+
+static struct samsung_pwm_drvdata *samsung_pwm_add(struct platform_device *pdev)
+{
+	struct samsung_pwm_variant *variant = pdev->dev.platform_data;
+	struct samsung_pwm_drvdata *pwm;
+	struct resource *res;
+	int i;
+
+	if (!variant) {
+		pr_err("%s: no platform data specified\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	pwm = kzalloc(sizeof(*pwm), GFP_KERNEL);
+	if (!pwm) {
+		pr_err("%s: could not allocate PWM device struct\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pwm->pwm.variant = *variant;
+	pwm->pdev = pdev;
+	spin_lock_init(&pwm->slock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		pr_err("%s: could not get IO resource\n", __func__);
+		kfree(pwm);
+		return ERR_PTR(-EINVAL);
+	}
+	pwm->resource = *res;
+
+	for (i = 0; i < SAMSUNG_PWM_NUM; ++i)
+		pwm->pwm.irq[i] = platform_get_irq(pdev, i);
+
+	list_add_tail(&pwm->list, &pwm_list);
+
+	return pwm;
+}
+
+static struct samsung_pwm_drvdata *samsung_pwm_find(struct platform_device *pdev)
+{
+	struct samsung_pwm_drvdata *pwm;
+	struct device_node *np = NULL;
+
+	list_for_each_entry(pwm, &pwm_list, list) {
+		if (!pdev || pwm->pdev == pdev)
+			return pwm;
+		if (pdev->dev.of_node && pdev->dev.of_node == pwm->pwm.of_node)
+			return pwm;
+	}
+
+	if (pdev) {
+		np = pdev->dev.of_node;
+		if (!np)
+			return samsung_pwm_add(pdev);
+	}
+
+	return samsung_pwm_of_add(np);
+}
+
+struct samsung_pwm *samsung_pwm_get(struct platform_device *pdev)
+{
+	struct samsung_pwm_drvdata *pwm;
+	struct resource *res;
+
+	pwm = samsung_pwm_find(pdev);
+	if (IS_ERR(pwm)) {
+		pr_err("%s: failed to instantiate PWM device\n", __func__);
+		return &pwm->pwm;
+	}
+
+	if (pwm->pwm.base)
+		return &pwm->pwm;
+
+	res = request_mem_region(pwm->resource.start,
+				resource_size(&pwm->resource), "samsung-pwm");
+	if (!res) {
+		pr_err("%s: failed to request IO mem region\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pwm->pwm.base = ioremap(res->start, resource_size(res));
+	if (!pwm->pwm.base) {
+		pr_err("%s: failed to map PWM registers\n", __func__);
+		release_mem_region(res->start, resource_size(res));
+		return ERR_PTR(-ENOMEM);
+	}
+
+	return &pwm->pwm;
+}
+EXPORT_SYMBOL(samsung_pwm_get);
+
+int samsung_pwm_register(struct platform_device *pdev)
+{
+	struct samsung_pwm_drvdata *pwm;
+
+	pwm = samsung_pwm_add(pdev);
+	if (IS_ERR(pwm))
+		return PTR_ERR(pwm);
+
+	return 0;
+}
+EXPORT_SYMBOL(samsung_pwm_register);
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 0e0bfa0..c80070b 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -118,6 +118,7 @@ config PWM_PXA
 config PWM_SAMSUNG
 	tristate "Samsung PWM support"
 	depends on PLAT_SAMSUNG
+	select MFD_SAMSUNG_PWM
 	help
 	  Generic PWM framework driver for Samsung.
 
diff --git a/include/linux/mfd/samsung-pwm.h b/include/linux/mfd/samsung-pwm.h
new file mode 100644
index 0000000..e54456e
--- /dev/null
+++ b/include/linux/mfd/samsung-pwm.h
@@ -0,0 +1,49 @@
+/*
+ * Samsung PWM/timers MFD driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *
+ * Author: Tomasz Figa <t.figa@samsung.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.
+ */
+
+#ifndef MFD_SAMSUNG_PWM_H_
+#define MFD_SAMSUNG_PWM_H_
+
+#include <linux/platform_data/samsung-pwm.h>
+
+#define SAMSUNG_PWM_NUM		5
+
+#define SAMSUNG_PWM_INVERT	(1 << 0)
+
+struct platform_device;
+
+struct samsung_pwm {
+	struct samsung_pwm_variant variant;
+	struct device_node *of_node;
+	void __iomem *base;
+	int irq[SAMSUNG_PWM_NUM];
+};
+
+extern void samsung_pwm_start(struct samsung_pwm *pwm,
+					unsigned int channel, bool periodic);
+extern void samsung_pwm_stop(struct samsung_pwm *pwm, unsigned int channel);
+extern void samsung_pwm_setup(struct samsung_pwm *pwm, unsigned int channel,
+							u32 tcmp, u32 tcnt);
+
+extern void samsung_pwm_set_flags(struct samsung_pwm *pwm,
+					unsigned int channel, u32 flags);
+extern void samsung_pwm_set_prescale(struct samsung_pwm *pwm,
+					unsigned int channel, u16 prescale);
+extern void samsung_pwm_set_divisor(struct samsung_pwm *pwm,
+					unsigned int channel, u8 divisor);
+
+extern int samsung_pwm_request(struct samsung_pwm *pwm, unsigned int channel);
+extern void samsung_pwm_free(struct samsung_pwm *pwm, unsigned int channel);
+
+extern struct samsung_pwm *samsung_pwm_get(struct platform_device *pdev);
+
+#endif
diff --git a/include/linux/platform_data/samsung-pwm.h b/include/linux/platform_data/samsung-pwm.h
new file mode 100644
index 0000000..8c48dbb
--- /dev/null
+++ b/include/linux/platform_data/samsung-pwm.h
@@ -0,0 +1,28 @@
+/*
+ * Samsung PWM/timers driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *
+ * Author: Tomasz Figa <t.figa@samsung.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.
+ */
+
+#ifndef PLATFORM_DATA_SAMSUNG_PWM_H_
+#define PLATFORM_DATA_SAMSUNG_PWM_H_
+
+struct platform_device;
+
+struct samsung_pwm_variant {
+	u8 bits;
+	u8 div_base;
+	u8 tclk_mask;
+	u8 output_mask;
+	bool has_tint_cstat;
+};
+
+extern int samsung_pwm_register(struct platform_device *pdev);
+
+#endif
-- 
1.8.1.5

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

* [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
@ 2013-04-04 16:37   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds master driver for PWM/timer block available on many
Samsung SoCs providing clocksource and PWM output capabilities.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 .../devicetree/bindings/pwm/pwm-samsung.txt        |  37 ++
 drivers/clocksource/Kconfig                        |   1 +
 drivers/mfd/Kconfig                                |   3 +
 drivers/mfd/Makefile                               |   1 +
 drivers/mfd/samsung-pwm.c                          | 439 +++++++++++++++++++++
 drivers/pwm/Kconfig                                |   1 +
 include/linux/mfd/samsung-pwm.h                    |  49 +++
 include/linux/platform_data/samsung-pwm.h          |  28 ++
 8 files changed, 559 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/pwm-samsung.txt
 create mode 100644 drivers/mfd/samsung-pwm.c
 create mode 100644 include/linux/mfd/samsung-pwm.h
 create mode 100644 include/linux/platform_data/samsung-pwm.h

diff --git a/Documentation/devicetree/bindings/pwm/pwm-samsung.txt b/Documentation/devicetree/bindings/pwm/pwm-samsung.txt
new file mode 100644
index 0000000..8ed4c11
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-samsung.txt
@@ -0,0 +1,37 @@
+* Samsung PWM timers
+
+Samsung SoCs contain PWM timer blocks which can be used for system clock source
+and clock event timers, as well as to drive SoC outputs with PWM signal. Each
+PWM timer block provides 5 PWM channels (not all of them can drive physical
+outputs - see SoC and board manual).
+
+Be aware that this driver supports clock event only on CPU 0. It can
+provide SMP support together with ARM dummy_timer, but only in periodic tick
+mode.
+
+Required properties:
+- compatible : should be one of following:
+    samsung,s3c2410-pwm - for 16-bit timers present on S3C24xx SoCs
+    samsung,s3c6400-pwm - for 32-bit timers present on S3C64xx SoCs
+    samsung,s5p6440-pwm - for 32-bit timers present on S5P64x0 SoCs
+    samsung,s5pc100-pwm - for 32-bit timers present on S5PC100, S5PV210,
+			  Exynos4210, Exynos4x12 and Exynos5250 SoCs
+- reg: base address and size of register area
+- interrupts: list of timer interrupts (one interrupt per timer, starting at
+  timer 0)
+- #pwm-cells: number of cells used for PWM specifier - must be 2
+
+Optional properties:
+- samsung,pwm-outputs: list of PWM channels used as PWM outputs on particular
+    platform - an array of up to 5 elements being indices of PWM channels
+    (from 0 to 4), the order does not matter.
+
+Example:
+	pwm at 7f006000 {
+		compatible = "samsung,s3c6400-pwm";
+		reg = <0x7f006000 0x1000>;
+		interrupt-parent = <&vic0>;
+		interrupts = <23>, <24>, <25>, <27>, <28>;
+		samsung,pwm-outputs = <0>, <1>;
+		#pwm-cells = <2>;
+	}
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index dd20f6a..a69a5b7 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -29,6 +29,7 @@ config SAMSUNG_HRT
 	bool
 	depends on PLAT_SAMSUNG
 	select SAMSUNG_DEV_PWM
+	select MFD_SAMSUNG_PWM
 	help
 	  Use the high resolution timer support on Samsung platforms.
 
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 3ab3a11..c25425c 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1015,6 +1015,9 @@ config MFD_PM8XXX_IRQ
 	  This is required to use certain other PM 8xxx features, such as GPIO
 	  and MPP.
 
+config MFD_SAMSUNG_PWM
+	bool
+
 config TPS65911_COMPARATOR
 	tristate
 
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index b90409c..513d9c9 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -145,6 +145,7 @@ obj-$(CONFIG_MFD_RC5T583)	+= rc5t583.o rc5t583-irq.o
 obj-$(CONFIG_MFD_SEC_CORE)	+= sec-core.o sec-irq.o
 obj-$(CONFIG_MFD_SYSCON)	+= syscon.o
 obj-$(CONFIG_MFD_LM3533)	+= lm3533-core.o lm3533-ctrlbank.o
+obj-$(CONFIG_MFD_SAMSUNG_PWM)	+= samsung-pwm.o
 obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o vexpress-sysreg.o
 obj-$(CONFIG_MFD_RETU)		+= retu-mfd.o
 obj-$(CONFIG_MFD_AS3711)	+= as3711.o
diff --git a/drivers/mfd/samsung-pwm.c b/drivers/mfd/samsung-pwm.c
new file mode 100644
index 0000000..ece426e
--- /dev/null
+++ b/drivers/mfd/samsung-pwm.c
@@ -0,0 +1,439 @@
+/*
+ * Samsung PWM/timers MFD driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *
+ * Author: Tomasz Figa <t.figa@samsung.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.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/mfd/samsung-pwm.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_data/samsung-pwm.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#define REG_TCFG0			0x00
+#define REG_TCFG1			0x04
+#define REG_TCON			0x08
+
+#define REG_TCNTB(chan)			(0x0c + 12 * (chan))
+#define REG_TCMPB(chan)			(0x10 + 12 * (chan))
+
+#define TCON_START(chan)		(1 << (4 * (chan) + 0))
+#define TCON_MANUALUPDATE(chan)		(1 << (4 * (chan) + 1))
+#define TCON_INVERT(chan)		(1 << (4 * (chan) + 2))
+#define TCON_AUTORELOAD(chan)		(1 << (4 * (chan) + 3))
+
+#define TCFG0_PRESCALER_MASK		0xff
+#define TCFG0_PRESCALER1_SHIFT		8
+
+#define TCFG1_SHIFT(x)	  		((x) * 4)
+#define TCFG1_MUX_MASK	  		0xf
+
+struct samsung_pwm_drvdata {
+	struct samsung_pwm pwm;
+	struct platform_device *pdev;
+	struct resource resource;
+	struct list_head list;
+	spinlock_t slock;
+	unsigned long request_mask;
+};
+
+static LIST_HEAD(pwm_list);
+
+static inline struct samsung_pwm_drvdata *to_drvdata(struct samsung_pwm *pwm)
+{
+	return container_of(pwm, struct samsung_pwm_drvdata, pwm);
+}
+
+void samsung_pwm_start(struct samsung_pwm *pwm,
+					unsigned int channel, bool periodic)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+	unsigned long flags;
+	u32 reg;
+
+	if (channel > 0)
+		++channel;
+
+	spin_lock_irqsave(&drvdata->slock, flags);
+
+	reg = readl(pwm->base + REG_TCON);
+	reg &= ~TCON_MANUALUPDATE(channel);
+	reg |= TCON_START(channel);
+	if (periodic)
+		reg |= TCON_AUTORELOAD(channel);
+	else
+		reg &= ~TCON_AUTORELOAD(channel);
+	writel(reg, pwm->base + REG_TCON);
+
+	spin_unlock_irqrestore(&drvdata->slock, flags);
+}
+EXPORT_SYMBOL(samsung_pwm_start);
+
+void samsung_pwm_stop(struct samsung_pwm *pwm, unsigned int channel)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+	unsigned long flags;
+	u32 reg;
+
+	if (channel > 0)
+		++channel;
+
+	spin_lock_irqsave(&drvdata->slock, flags);
+
+	reg = readl(pwm->base + REG_TCON);
+	reg &= ~TCON_START(channel);
+	writel(reg, pwm->base + REG_TCON);
+
+	spin_unlock_irqrestore(&drvdata->slock, flags);
+}
+EXPORT_SYMBOL(samsung_pwm_stop);
+
+void samsung_pwm_setup(struct samsung_pwm *pwm, unsigned int channel,
+							u32 tcmp, u32 tcnt)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+	unsigned long flags;
+	u32 reg;
+
+	writel(tcnt, pwm->base + REG_TCNTB(channel));
+	writel(tcmp, pwm->base + REG_TCMPB(channel));
+
+	if (channel > 0)
+		++channel;
+
+	spin_lock_irqsave(&drvdata->slock, flags);
+
+	reg = readl(pwm->base + REG_TCON);
+	reg &= ~TCON_START(channel);
+	reg |= TCON_MANUALUPDATE(channel);
+	writel(reg, pwm->base + REG_TCON);
+
+	spin_unlock_irqrestore(&drvdata->slock, flags);
+}
+EXPORT_SYMBOL(samsung_pwm_setup);
+
+void samsung_pwm_set_flags(struct samsung_pwm *pwm,
+					unsigned int channel, u32 pwm_flags)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+	unsigned long flags;
+	u32 reg;
+
+	if (channel > 0)
+		++channel;
+
+	spin_lock_irqsave(&drvdata->slock, flags);
+
+	reg = readl(pwm->base + REG_TCON);
+
+	if (pwm_flags & SAMSUNG_PWM_INVERT)
+		reg |= TCON_INVERT(channel);
+	else
+		reg &= ~TCON_INVERT(channel);
+
+	writel(reg, pwm->base + REG_TCON);
+
+	spin_unlock_irqrestore(&drvdata->slock, flags);
+}
+EXPORT_SYMBOL(samsung_pwm_set_flags);
+
+void samsung_pwm_set_prescale(struct samsung_pwm *pwm,
+					unsigned int channel, u16 prescale)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+	unsigned long flags;
+	u8 shift = 0;
+	u32 reg;
+
+	if (channel >= 2)
+		shift = TCFG0_PRESCALER1_SHIFT;
+
+	spin_lock_irqsave(&drvdata->slock, flags);
+
+	reg = readl(pwm->base + REG_TCFG0);
+	reg &= ~(TCFG0_PRESCALER_MASK << shift);
+	reg |= (prescale - 1) << shift;
+	writel(reg, pwm->base + REG_TCFG0);
+
+	spin_unlock_irqrestore(&drvdata->slock, flags);
+}
+EXPORT_SYMBOL(samsung_pwm_set_prescale);
+
+void samsung_pwm_set_divisor(struct samsung_pwm *pwm,
+					unsigned int channel, u8 divisor)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+	u8 shift = TCFG1_SHIFT(channel);
+	unsigned long flags;
+	u32 reg;
+	u8 bits;
+
+	bits = (fls(divisor) - 1) - pwm->variant.div_base;
+
+	spin_lock_irqsave(&drvdata->slock, flags);
+
+	reg = readl(pwm->base + REG_TCFG1);
+	reg &= ~(TCFG1_MUX_MASK << shift);
+	reg |= bits << shift;
+	writel(reg, pwm->base + REG_TCFG1);
+
+	spin_unlock_irqrestore(&drvdata->slock, flags);
+}
+EXPORT_SYMBOL(samsung_pwm_set_divisor);
+
+int samsung_pwm_request(struct samsung_pwm *pwm, unsigned int channel)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+
+	if (test_and_set_bit(channel, &drvdata->request_mask))
+		return -EBUSY;
+
+	return 0;
+}
+EXPORT_SYMBOL(samsung_pwm_request);
+
+void samsung_pwm_free(struct samsung_pwm *pwm, unsigned int channel)
+{
+	struct samsung_pwm_drvdata *drvdata = to_drvdata(pwm);
+
+	clear_bit(channel, &drvdata->request_mask);
+}
+EXPORT_SYMBOL(samsung_pwm_free);
+
+#ifdef CONFIG_OF
+static int samsung_pwm_parse_dt(struct samsung_pwm *pwm)
+{
+	struct samsung_pwm_variant *variant = &pwm->variant;
+	struct device_node *np = pwm->of_node;
+	struct property *prop;
+	const __be32 *cur;
+	u32 val;
+	int i;
+
+	for (i = 0; i < SAMSUNG_PWM_NUM; ++i)
+		pwm->irq[i] = irq_of_parse_and_map(np, i);
+
+	of_property_for_each_u32(np, "samsung,pwm-outputs", prop, cur, val) {
+		if (val >= SAMSUNG_PWM_NUM) {
+			pr_warning("%s: invalid channel index in samsung,pwm-outputs property\n",
+								__func__);
+			continue;
+		}
+		variant->output_mask |= 1 << val;
+	}
+
+	return 0;
+}
+
+static const struct samsung_pwm_variant s3c24xx_variant = {
+	.bits		= 16,
+	.div_base	= 1,
+	.has_tint_cstat	= false,
+	.tclk_mask	= (1 << 4),
+};
+
+static const struct samsung_pwm_variant s3c64xx_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= (1 << 7) | (1 << 6) | (1 << 5),
+};
+
+static const struct samsung_pwm_variant s5p64x0_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= 0,
+};
+
+static const struct samsung_pwm_variant s5p_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= (1 << 5),
+};
+
+static const struct of_device_id samsung_pwm_matches[] = {
+	{ .compatible = "samsung,s3c2410-pwm", .data = &s3c24xx_variant, },
+	{ .compatible = "samsung,s3c6400-pwm", .data = &s3c64xx_variant, },
+	{ .compatible = "samsung,s5p6440-pwm", .data = &s5p64x0_variant, },
+	{ .compatible = "samsung,s5pc100-pwm", .data = &s5p_variant, },
+	{},
+};
+
+static struct samsung_pwm_drvdata *samsung_pwm_of_add(struct device_node *np)
+{
+	const struct samsung_pwm_variant *variant;
+	const struct of_device_id *match;
+	struct samsung_pwm_drvdata *pwm;
+	int ret;
+
+	if (!np) {
+		np = of_find_matching_node(NULL, samsung_pwm_matches);
+		if (!np) {
+			pr_err("%s: could not find PWM device\n", __func__);
+			return ERR_PTR(-ENODEV);
+		}
+	}
+
+	match = of_match_node(samsung_pwm_matches, np);
+	if (!match) {
+		pr_err("%s: failed to match given OF node\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+	variant = match->data;
+
+	pwm = kzalloc(sizeof(*pwm), GFP_KERNEL);
+	if (!pwm) {
+		pr_err("%s: could not allocate PWM device struct\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pwm->pwm.variant = *variant;
+	pwm->pwm.of_node = np;
+	spin_lock_init(&pwm->slock);
+
+	ret = of_address_to_resource(np, 0, &pwm->resource);
+	if (ret < 0) {
+		pr_err("%s: could not get IO resource\n", __func__);
+		goto err_free;
+	}
+
+	ret = samsung_pwm_parse_dt(&pwm->pwm);
+	if (ret < 0) {
+		pr_err("%s: failed to parse device tree node\n", __func__);
+		goto err_free;
+	}
+
+	list_add_tail(&pwm->list, &pwm_list);
+
+	return pwm;
+
+err_free:
+	kfree(pwm);
+
+	return ERR_PTR(ret);
+}
+#else
+static struct samsung_pwm_drvdata *samsung_pwm_of_add(struct device_node *np)
+{
+	return ERR_PTR(-ENODEV);
+}
+#endif
+
+static struct samsung_pwm_drvdata *samsung_pwm_add(struct platform_device *pdev)
+{
+	struct samsung_pwm_variant *variant = pdev->dev.platform_data;
+	struct samsung_pwm_drvdata *pwm;
+	struct resource *res;
+	int i;
+
+	if (!variant) {
+		pr_err("%s: no platform data specified\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	pwm = kzalloc(sizeof(*pwm), GFP_KERNEL);
+	if (!pwm) {
+		pr_err("%s: could not allocate PWM device struct\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pwm->pwm.variant = *variant;
+	pwm->pdev = pdev;
+	spin_lock_init(&pwm->slock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		pr_err("%s: could not get IO resource\n", __func__);
+		kfree(pwm);
+		return ERR_PTR(-EINVAL);
+	}
+	pwm->resource = *res;
+
+	for (i = 0; i < SAMSUNG_PWM_NUM; ++i)
+		pwm->pwm.irq[i] = platform_get_irq(pdev, i);
+
+	list_add_tail(&pwm->list, &pwm_list);
+
+	return pwm;
+}
+
+static struct samsung_pwm_drvdata *samsung_pwm_find(struct platform_device *pdev)
+{
+	struct samsung_pwm_drvdata *pwm;
+	struct device_node *np = NULL;
+
+	list_for_each_entry(pwm, &pwm_list, list) {
+		if (!pdev || pwm->pdev == pdev)
+			return pwm;
+		if (pdev->dev.of_node && pdev->dev.of_node == pwm->pwm.of_node)
+			return pwm;
+	}
+
+	if (pdev) {
+		np = pdev->dev.of_node;
+		if (!np)
+			return samsung_pwm_add(pdev);
+	}
+
+	return samsung_pwm_of_add(np);
+}
+
+struct samsung_pwm *samsung_pwm_get(struct platform_device *pdev)
+{
+	struct samsung_pwm_drvdata *pwm;
+	struct resource *res;
+
+	pwm = samsung_pwm_find(pdev);
+	if (IS_ERR(pwm)) {
+		pr_err("%s: failed to instantiate PWM device\n", __func__);
+		return &pwm->pwm;
+	}
+
+	if (pwm->pwm.base)
+		return &pwm->pwm;
+
+	res = request_mem_region(pwm->resource.start,
+				resource_size(&pwm->resource), "samsung-pwm");
+	if (!res) {
+		pr_err("%s: failed to request IO mem region\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pwm->pwm.base = ioremap(res->start, resource_size(res));
+	if (!pwm->pwm.base) {
+		pr_err("%s: failed to map PWM registers\n", __func__);
+		release_mem_region(res->start, resource_size(res));
+		return ERR_PTR(-ENOMEM);
+	}
+
+	return &pwm->pwm;
+}
+EXPORT_SYMBOL(samsung_pwm_get);
+
+int samsung_pwm_register(struct platform_device *pdev)
+{
+	struct samsung_pwm_drvdata *pwm;
+
+	pwm = samsung_pwm_add(pdev);
+	if (IS_ERR(pwm))
+		return PTR_ERR(pwm);
+
+	return 0;
+}
+EXPORT_SYMBOL(samsung_pwm_register);
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 0e0bfa0..c80070b 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -118,6 +118,7 @@ config PWM_PXA
 config PWM_SAMSUNG
 	tristate "Samsung PWM support"
 	depends on PLAT_SAMSUNG
+	select MFD_SAMSUNG_PWM
 	help
 	  Generic PWM framework driver for Samsung.
 
diff --git a/include/linux/mfd/samsung-pwm.h b/include/linux/mfd/samsung-pwm.h
new file mode 100644
index 0000000..e54456e
--- /dev/null
+++ b/include/linux/mfd/samsung-pwm.h
@@ -0,0 +1,49 @@
+/*
+ * Samsung PWM/timers MFD driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *
+ * Author: Tomasz Figa <t.figa@samsung.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.
+ */
+
+#ifndef MFD_SAMSUNG_PWM_H_
+#define MFD_SAMSUNG_PWM_H_
+
+#include <linux/platform_data/samsung-pwm.h>
+
+#define SAMSUNG_PWM_NUM		5
+
+#define SAMSUNG_PWM_INVERT	(1 << 0)
+
+struct platform_device;
+
+struct samsung_pwm {
+	struct samsung_pwm_variant variant;
+	struct device_node *of_node;
+	void __iomem *base;
+	int irq[SAMSUNG_PWM_NUM];
+};
+
+extern void samsung_pwm_start(struct samsung_pwm *pwm,
+					unsigned int channel, bool periodic);
+extern void samsung_pwm_stop(struct samsung_pwm *pwm, unsigned int channel);
+extern void samsung_pwm_setup(struct samsung_pwm *pwm, unsigned int channel,
+							u32 tcmp, u32 tcnt);
+
+extern void samsung_pwm_set_flags(struct samsung_pwm *pwm,
+					unsigned int channel, u32 flags);
+extern void samsung_pwm_set_prescale(struct samsung_pwm *pwm,
+					unsigned int channel, u16 prescale);
+extern void samsung_pwm_set_divisor(struct samsung_pwm *pwm,
+					unsigned int channel, u8 divisor);
+
+extern int samsung_pwm_request(struct samsung_pwm *pwm, unsigned int channel);
+extern void samsung_pwm_free(struct samsung_pwm *pwm, unsigned int channel);
+
+extern struct samsung_pwm *samsung_pwm_get(struct platform_device *pdev);
+
+#endif
diff --git a/include/linux/platform_data/samsung-pwm.h b/include/linux/platform_data/samsung-pwm.h
new file mode 100644
index 0000000..8c48dbb
--- /dev/null
+++ b/include/linux/platform_data/samsung-pwm.h
@@ -0,0 +1,28 @@
+/*
+ * Samsung PWM/timers driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *
+ * Author: Tomasz Figa <t.figa@samsung.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.
+ */
+
+#ifndef PLATFORM_DATA_SAMSUNG_PWM_H_
+#define PLATFORM_DATA_SAMSUNG_PWM_H_
+
+struct platform_device;
+
+struct samsung_pwm_variant {
+	u8 bits;
+	u8 div_base;
+	u8 tclk_mask;
+	u8 output_mask;
+	bool has_tint_cstat;
+};
+
+extern int samsung_pwm_register(struct platform_device *pdev);
+
+#endif
-- 
1.8.1.5

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

* [PATCH v4 05/14] ARM: SAMSUNG: Unify base address definitions of timer block
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 16:37   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

This patch makes all defintions of timer block base address use the same
prefix to allow using the common name to define platform device
resource.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-exynos/include/mach/map.h  | 1 +
 arch/arm/mach-s3c24xx/include/mach/map.h | 2 ++
 arch/arm/mach-s3c64xx/include/mach/map.h | 1 +
 arch/arm/mach-s5p64x0/include/mach/map.h | 1 +
 arch/arm/mach-s5pc100/include/mach/map.h | 1 +
 arch/arm/mach-s5pv210/include/mach/map.h | 1 +
 6 files changed, 7 insertions(+)

diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 99e0a79..7167aba 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -272,6 +272,7 @@
 #define SAMSUNG_PA_ADC			EXYNOS4_PA_ADC
 #define SAMSUNG_PA_ADC1			EXYNOS4_PA_ADC1
 #define SAMSUNG_PA_KEYPAD		EXYNOS4_PA_KEYPAD
+#define SAMSUNG_PA_TIMER		EXYNOS4_PA_TIMER
 
 /* Compatibility UART */
 
diff --git a/arch/arm/mach-s3c24xx/include/mach/map.h b/arch/arm/mach-s3c24xx/include/mach/map.h
index 8ba381f..444793f 100644
--- a/arch/arm/mach-s3c24xx/include/mach/map.h
+++ b/arch/arm/mach-s3c24xx/include/mach/map.h
@@ -167,4 +167,6 @@
 #define S3C_PA_SPI0		S3C2443_PA_SPI0
 #define S3C_PA_SPI1		S3C2443_PA_SPI1
 
+#define SAMSUNG_PA_TIMER	S3C2410_PA_TIMER
+
 #endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s3c64xx/include/mach/map.h b/arch/arm/mach-s3c64xx/include/mach/map.h
index 8e2097b..f55ccb1 100644
--- a/arch/arm/mach-s3c64xx/include/mach/map.h
+++ b/arch/arm/mach-s3c64xx/include/mach/map.h
@@ -121,5 +121,6 @@
 #define SAMSUNG_PA_ADC		S3C64XX_PA_ADC
 #define SAMSUNG_PA_CFCON	S3C64XX_PA_CFCON
 #define SAMSUNG_PA_KEYPAD	S3C64XX_PA_KEYPAD
+#define SAMSUNG_PA_TIMER	S3C64XX_PA_TIMER
 
 #endif /* __ASM_ARCH_6400_MAP_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/map.h b/arch/arm/mach-s5p64x0/include/mach/map.h
index 0c0175d..50a6e96 100644
--- a/arch/arm/mach-s5p64x0/include/mach/map.h
+++ b/arch/arm/mach-s5p64x0/include/mach/map.h
@@ -76,6 +76,7 @@
 #define S5P_PA_TIMER		S5P64X0_PA_TIMER
 
 #define SAMSUNG_PA_ADC		S5P64X0_PA_ADC
+#define SAMSUNG_PA_TIMER	S5P64X0_PA_TIMER
 
 /* UART */
 
diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h
index 54bc4f8..2550b61 100644
--- a/arch/arm/mach-s5pc100/include/mach/map.h
+++ b/arch/arm/mach-s5pc100/include/mach/map.h
@@ -116,6 +116,7 @@
 #define SAMSUNG_PA_ADC			S5PC100_PA_TSADC
 #define SAMSUNG_PA_CFCON		S5PC100_PA_CFCON
 #define SAMSUNG_PA_KEYPAD		S5PC100_PA_KEYPAD
+#define SAMSUNG_PA_TIMER		S5PC100_PA_TIMER
 
 #define S5PC100_VA_OTHERS		(S3C_VA_SYS + 0x10000)
 
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h
index b7c8a19..763929a 100644
--- a/arch/arm/mach-s5pv210/include/mach/map.h
+++ b/arch/arm/mach-s5pv210/include/mach/map.h
@@ -139,6 +139,7 @@
 #define SAMSUNG_PA_ADC			S5PV210_PA_ADC
 #define SAMSUNG_PA_CFCON		S5PV210_PA_CFCON
 #define SAMSUNG_PA_KEYPAD		S5PV210_PA_KEYPAD
+#define SAMSUNG_PA_TIMER		S5PV210_PA_TIMER
 
 /* UART */
 
-- 
1.8.1.5

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

* [PATCH v4 05/14] ARM: SAMSUNG: Unify base address definitions of timer block
@ 2013-04-04 16:37   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

This patch makes all defintions of timer block base address use the same
prefix to allow using the common name to define platform device
resource.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-exynos/include/mach/map.h  | 1 +
 arch/arm/mach-s3c24xx/include/mach/map.h | 2 ++
 arch/arm/mach-s3c64xx/include/mach/map.h | 1 +
 arch/arm/mach-s5p64x0/include/mach/map.h | 1 +
 arch/arm/mach-s5pc100/include/mach/map.h | 1 +
 arch/arm/mach-s5pv210/include/mach/map.h | 1 +
 6 files changed, 7 insertions(+)

diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 99e0a79..7167aba 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -272,6 +272,7 @@
 #define SAMSUNG_PA_ADC			EXYNOS4_PA_ADC
 #define SAMSUNG_PA_ADC1			EXYNOS4_PA_ADC1
 #define SAMSUNG_PA_KEYPAD		EXYNOS4_PA_KEYPAD
+#define SAMSUNG_PA_TIMER		EXYNOS4_PA_TIMER
 
 /* Compatibility UART */
 
diff --git a/arch/arm/mach-s3c24xx/include/mach/map.h b/arch/arm/mach-s3c24xx/include/mach/map.h
index 8ba381f..444793f 100644
--- a/arch/arm/mach-s3c24xx/include/mach/map.h
+++ b/arch/arm/mach-s3c24xx/include/mach/map.h
@@ -167,4 +167,6 @@
 #define S3C_PA_SPI0		S3C2443_PA_SPI0
 #define S3C_PA_SPI1		S3C2443_PA_SPI1
 
+#define SAMSUNG_PA_TIMER	S3C2410_PA_TIMER
+
 #endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s3c64xx/include/mach/map.h b/arch/arm/mach-s3c64xx/include/mach/map.h
index 8e2097b..f55ccb1 100644
--- a/arch/arm/mach-s3c64xx/include/mach/map.h
+++ b/arch/arm/mach-s3c64xx/include/mach/map.h
@@ -121,5 +121,6 @@
 #define SAMSUNG_PA_ADC		S3C64XX_PA_ADC
 #define SAMSUNG_PA_CFCON	S3C64XX_PA_CFCON
 #define SAMSUNG_PA_KEYPAD	S3C64XX_PA_KEYPAD
+#define SAMSUNG_PA_TIMER	S3C64XX_PA_TIMER
 
 #endif /* __ASM_ARCH_6400_MAP_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/map.h b/arch/arm/mach-s5p64x0/include/mach/map.h
index 0c0175d..50a6e96 100644
--- a/arch/arm/mach-s5p64x0/include/mach/map.h
+++ b/arch/arm/mach-s5p64x0/include/mach/map.h
@@ -76,6 +76,7 @@
 #define S5P_PA_TIMER		S5P64X0_PA_TIMER
 
 #define SAMSUNG_PA_ADC		S5P64X0_PA_ADC
+#define SAMSUNG_PA_TIMER	S5P64X0_PA_TIMER
 
 /* UART */
 
diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h
index 54bc4f8..2550b61 100644
--- a/arch/arm/mach-s5pc100/include/mach/map.h
+++ b/arch/arm/mach-s5pc100/include/mach/map.h
@@ -116,6 +116,7 @@
 #define SAMSUNG_PA_ADC			S5PC100_PA_TSADC
 #define SAMSUNG_PA_CFCON		S5PC100_PA_CFCON
 #define SAMSUNG_PA_KEYPAD		S5PC100_PA_KEYPAD
+#define SAMSUNG_PA_TIMER		S5PC100_PA_TIMER
 
 #define S5PC100_VA_OTHERS		(S3C_VA_SYS + 0x10000)
 
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h
index b7c8a19..763929a 100644
--- a/arch/arm/mach-s5pv210/include/mach/map.h
+++ b/arch/arm/mach-s5pv210/include/mach/map.h
@@ -139,6 +139,7 @@
 #define SAMSUNG_PA_ADC			S5PV210_PA_ADC
 #define SAMSUNG_PA_CFCON		S5PV210_PA_CFCON
 #define SAMSUNG_PA_KEYPAD		S5PV210_PA_KEYPAD
+#define SAMSUNG_PA_TIMER		S5PV210_PA_TIMER
 
 /* UART */
 
-- 
1.8.1.5

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

* [PATCH v4 06/14] ARM: SAMSUNG: Add new PWM platform device
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 16:37   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

This patch adds new samsung_device_pwm platform device that represents
the whole PWM/timer block and includes memory and IRQ resources.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/plat-samsung/devs.c              | 16 ++++++++++++++++
 arch/arm/plat-samsung/include/plat/devs.h |  1 +
 2 files changed, 17 insertions(+)

diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index e1124d9..bfae4dd 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -1168,6 +1168,22 @@ struct platform_device s3c_device_timer[] = {
 };
 #endif /* CONFIG_SAMSUNG_DEV_PWM */
 
+static struct resource samsung_pwm_resource[] = {
+	DEFINE_RES_IRQ(IRQ_TIMER0),
+	DEFINE_RES_IRQ(IRQ_TIMER1),
+	DEFINE_RES_IRQ(IRQ_TIMER2),
+	DEFINE_RES_IRQ(IRQ_TIMER3),
+	DEFINE_RES_IRQ(IRQ_TIMER4),
+	DEFINE_RES_MEM(SAMSUNG_PA_TIMER, SZ_4K),
+};
+
+struct platform_device samsung_device_pwm = {
+	.name		= "samsung-pwm",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(samsung_pwm_resource),
+	.resource	= samsung_pwm_resource,
+};
+
 /* RTC */
 
 #ifdef CONFIG_PLAT_S3C24XX
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 87d501f..0dc4ac4 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -134,6 +134,7 @@ extern struct platform_device exynos4_device_spdif;
 
 extern struct platform_device samsung_asoc_idma;
 extern struct platform_device samsung_device_keypad;
+extern struct platform_device samsung_device_pwm;
 
 /* s3c2440 specific devices */
 
-- 
1.8.1.5

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

* [PATCH v4 06/14] ARM: SAMSUNG: Add new PWM platform device
@ 2013-04-04 16:37   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds new samsung_device_pwm platform device that represents
the whole PWM/timer block and includes memory and IRQ resources.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/plat-samsung/devs.c              | 16 ++++++++++++++++
 arch/arm/plat-samsung/include/plat/devs.h |  1 +
 2 files changed, 17 insertions(+)

diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index e1124d9..bfae4dd 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -1168,6 +1168,22 @@ struct platform_device s3c_device_timer[] = {
 };
 #endif /* CONFIG_SAMSUNG_DEV_PWM */
 
+static struct resource samsung_pwm_resource[] = {
+	DEFINE_RES_IRQ(IRQ_TIMER0),
+	DEFINE_RES_IRQ(IRQ_TIMER1),
+	DEFINE_RES_IRQ(IRQ_TIMER2),
+	DEFINE_RES_IRQ(IRQ_TIMER3),
+	DEFINE_RES_IRQ(IRQ_TIMER4),
+	DEFINE_RES_MEM(SAMSUNG_PA_TIMER, SZ_4K),
+};
+
+struct platform_device samsung_device_pwm = {
+	.name		= "samsung-pwm",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(samsung_pwm_resource),
+	.resource	= samsung_pwm_resource,
+};
+
 /* RTC */
 
 #ifdef CONFIG_PLAT_S3C24XX
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 87d501f..0dc4ac4 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -134,6 +134,7 @@ extern struct platform_device exynos4_device_spdif;
 
 extern struct platform_device samsung_asoc_idma;
 extern struct platform_device samsung_device_keypad;
+extern struct platform_device samsung_device_pwm;
 
 /* s3c2440 specific devices */
 
-- 
1.8.1.5

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

* [PATCH v4 07/14] ARM: SAMSUNG: Set PWM platform data
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 16:37   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

This patch adds PWM platform data needed for legacy (non-DT) platforms
to handle SoC-specific bits of the PWM/timer block.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-exynos/common.c  | 10 ++++++++++
 arch/arm/mach-s3c24xx/common.c | 10 ++++++++++
 arch/arm/mach-s3c64xx/common.c | 10 ++++++++++
 arch/arm/mach-s5p64x0/common.c | 10 ++++++++++
 arch/arm/mach-s5pc100/common.c | 10 ++++++++++
 arch/arm/mach-s5pv210/common.c | 10 ++++++++++
 6 files changed, 60 insertions(+)

diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 9cd857e..2b1ef98 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/gpio.h>
+#include <linux/platform_data/samsung-pwm.h>
 #include <linux/sched.h>
 #include <linux/serial_core.h>
 #include <linux/of.h>
@@ -378,6 +379,13 @@ void __init exynos_init_io(struct map_desc *mach_desc, int size)
 	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
 }
 
+static struct samsung_pwm_variant exynos4_pwm_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= (1 << 5),
+};
+
 static void __init exynos4_map_io(void)
 {
 	iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
@@ -419,6 +427,8 @@ static void __init exynos4_map_io(void)
 	s5p_hdmi_setname("exynos4-hdmi");
 
 	s3c64xx_spi_setname("exynos4210-spi");
+
+	samsung_device_pwm.dev.platform_data = &exynos4_pwm_variant;
 }
 
 static void __init exynos5_map_io(void)
diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c
index d97533d..c09c6ba 100644
--- a/arch/arm/mach-s3c24xx/common.c
+++ b/arch/arm/mach-s3c24xx/common.c
@@ -27,6 +27,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/serial_core.h>
+#include <linux/platform_data/samsung-pwm.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/io.h>
@@ -216,6 +217,13 @@ static void s3c24xx_default_idle(void)
 		     S3C2410_CLKCON);
 }
 
+static struct samsung_pwm_variant s3c24xx_pwm_variant = {
+	.bits		= 16,
+	.div_base	= 1,
+	.has_tint_cstat	= false,
+	.tclk_mask	= (1 << 4),
+};
+
 void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 {
 	arm_pm_idle = s3c24xx_default_idle;
@@ -232,6 +240,8 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 	s3c24xx_init_cpu();
 
 	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
+
+	samsung_device_pwm.dev.platform_data = &s3c24xx_pwm_variant;
 }
 
 /* Serial port registrations */
diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c
index 0b9c0ba..526b45e 100644
--- a/arch/arm/mach-s3c64xx/common.c
+++ b/arch/arm/mach-s3c64xx/common.c
@@ -26,6 +26,7 @@
 #include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/irqchip/arm-vic.h>
+#include <linux/platform_data/samsung-pwm.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -148,6 +149,13 @@ static struct device s3c64xx_dev = {
 	.bus	= &s3c64xx_subsys,
 };
 
+static struct samsung_pwm_variant s3c64xx_pwm_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= (1 << 7) | (1 << 6) | (1 << 5),
+};
+
 /* read cpu identification code */
 
 void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
@@ -160,6 +168,8 @@ void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
 	s3c64xx_init_cpu();
 
 	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
+
+	samsung_device_pwm.dev.platform_data = &s3c64xx_pwm_variant;
 }
 
 static __init int s3c64xx_dev_init(void)
diff --git a/arch/arm/mach-s5p64x0/common.c b/arch/arm/mach-s5p64x0/common.c
index 8ae5800..5cd3048 100644
--- a/arch/arm/mach-s5p64x0/common.c
+++ b/arch/arm/mach-s5p64x0/common.c
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/serial_core.h>
+#include <linux/platform_data/samsung-pwm.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/dma-mapping.h>
@@ -156,6 +157,13 @@ static void s5p64x0_idle(void)
 	cpu_do_idle();
 }
 
+static struct samsung_pwm_variant s5p64x0_pwm_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= 0,
+};
+
 /*
  * s5p64x0_map_io
  *
@@ -173,6 +181,8 @@ void __init s5p64x0_init_io(struct map_desc *mach_desc, int size)
 	s5p_init_cpu(S5P64X0_SYS_ID);
 
 	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
+
+	samsung_device_pwm.dev.platform_data = &s5p64x0_pwm_variant;
 }
 
 void __init s5p6440_map_io(void)
diff --git a/arch/arm/mach-s5pc100/common.c b/arch/arm/mach-s5pc100/common.c
index cc6e561..d21938e 100644
--- a/arch/arm/mach-s5pc100/common.c
+++ b/arch/arm/mach-s5pc100/common.c
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/serial_core.h>
+#include <linux/platform_data/samsung-pwm.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
 
@@ -131,6 +132,13 @@ static struct map_desc s5pc100_iodesc[] __initdata = {
 	}
 };
 
+static struct samsung_pwm_variant s5pc100_pwm_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= (1 << 5),
+};
+
 /*
  * s5pc100_map_io
  *
@@ -148,6 +156,8 @@ void __init s5pc100_init_io(struct map_desc *mach_desc, int size)
 	s5p_init_cpu(S5P_VA_CHIPID);
 
 	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
+
+	samsung_device_pwm.dev.platform_data = &s5pc100_pwm_variant;
 }
 
 void __init s5pc100_map_io(void)
diff --git a/arch/arm/mach-s5pv210/common.c b/arch/arm/mach-s5pv210/common.c
index 9dfe93e..a3fc208 100644
--- a/arch/arm/mach-s5pv210/common.c
+++ b/arch/arm/mach-s5pv210/common.c
@@ -19,6 +19,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/device.h>
+#include <linux/platform_data/samsung-pwm.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/dma-mapping.h>
@@ -148,6 +149,13 @@ void s5pv210_restart(char mode, const char *cmd)
 	__raw_writel(0x1, S5P_SWRESET);
 }
 
+static struct samsung_pwm_variant s5pv210_pwm_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= (1 << 5),
+};
+
 /*
  * s5pv210_map_io
  *
@@ -165,6 +173,8 @@ void __init s5pv210_init_io(struct map_desc *mach_desc, int size)
 	s5p_init_cpu(S5P_VA_CHIPID);
 
 	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
+
+	samsung_device_pwm.dev.platform_data = &s5pv210_pwm_variant;
 }
 
 void __init s5pv210_map_io(void)
-- 
1.8.1.5

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

* [PATCH v4 07/14] ARM: SAMSUNG: Set PWM platform data
@ 2013-04-04 16:37   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds PWM platform data needed for legacy (non-DT) platforms
to handle SoC-specific bits of the PWM/timer block.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-exynos/common.c  | 10 ++++++++++
 arch/arm/mach-s3c24xx/common.c | 10 ++++++++++
 arch/arm/mach-s3c64xx/common.c | 10 ++++++++++
 arch/arm/mach-s5p64x0/common.c | 10 ++++++++++
 arch/arm/mach-s5pc100/common.c | 10 ++++++++++
 arch/arm/mach-s5pv210/common.c | 10 ++++++++++
 6 files changed, 60 insertions(+)

diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 9cd857e..2b1ef98 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/gpio.h>
+#include <linux/platform_data/samsung-pwm.h>
 #include <linux/sched.h>
 #include <linux/serial_core.h>
 #include <linux/of.h>
@@ -378,6 +379,13 @@ void __init exynos_init_io(struct map_desc *mach_desc, int size)
 	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
 }
 
+static struct samsung_pwm_variant exynos4_pwm_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= (1 << 5),
+};
+
 static void __init exynos4_map_io(void)
 {
 	iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
@@ -419,6 +427,8 @@ static void __init exynos4_map_io(void)
 	s5p_hdmi_setname("exynos4-hdmi");
 
 	s3c64xx_spi_setname("exynos4210-spi");
+
+	samsung_device_pwm.dev.platform_data = &exynos4_pwm_variant;
 }
 
 static void __init exynos5_map_io(void)
diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c
index d97533d..c09c6ba 100644
--- a/arch/arm/mach-s3c24xx/common.c
+++ b/arch/arm/mach-s3c24xx/common.c
@@ -27,6 +27,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/serial_core.h>
+#include <linux/platform_data/samsung-pwm.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/io.h>
@@ -216,6 +217,13 @@ static void s3c24xx_default_idle(void)
 		     S3C2410_CLKCON);
 }
 
+static struct samsung_pwm_variant s3c24xx_pwm_variant = {
+	.bits		= 16,
+	.div_base	= 1,
+	.has_tint_cstat	= false,
+	.tclk_mask	= (1 << 4),
+};
+
 void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 {
 	arm_pm_idle = s3c24xx_default_idle;
@@ -232,6 +240,8 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 	s3c24xx_init_cpu();
 
 	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
+
+	samsung_device_pwm.dev.platform_data = &s3c24xx_pwm_variant;
 }
 
 /* Serial port registrations */
diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c
index 0b9c0ba..526b45e 100644
--- a/arch/arm/mach-s3c64xx/common.c
+++ b/arch/arm/mach-s3c64xx/common.c
@@ -26,6 +26,7 @@
 #include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/irqchip/arm-vic.h>
+#include <linux/platform_data/samsung-pwm.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -148,6 +149,13 @@ static struct device s3c64xx_dev = {
 	.bus	= &s3c64xx_subsys,
 };
 
+static struct samsung_pwm_variant s3c64xx_pwm_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= (1 << 7) | (1 << 6) | (1 << 5),
+};
+
 /* read cpu identification code */
 
 void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
@@ -160,6 +168,8 @@ void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
 	s3c64xx_init_cpu();
 
 	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
+
+	samsung_device_pwm.dev.platform_data = &s3c64xx_pwm_variant;
 }
 
 static __init int s3c64xx_dev_init(void)
diff --git a/arch/arm/mach-s5p64x0/common.c b/arch/arm/mach-s5p64x0/common.c
index 8ae5800..5cd3048 100644
--- a/arch/arm/mach-s5p64x0/common.c
+++ b/arch/arm/mach-s5p64x0/common.c
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/serial_core.h>
+#include <linux/platform_data/samsung-pwm.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/dma-mapping.h>
@@ -156,6 +157,13 @@ static void s5p64x0_idle(void)
 	cpu_do_idle();
 }
 
+static struct samsung_pwm_variant s5p64x0_pwm_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= 0,
+};
+
 /*
  * s5p64x0_map_io
  *
@@ -173,6 +181,8 @@ void __init s5p64x0_init_io(struct map_desc *mach_desc, int size)
 	s5p_init_cpu(S5P64X0_SYS_ID);
 
 	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
+
+	samsung_device_pwm.dev.platform_data = &s5p64x0_pwm_variant;
 }
 
 void __init s5p6440_map_io(void)
diff --git a/arch/arm/mach-s5pc100/common.c b/arch/arm/mach-s5pc100/common.c
index cc6e561..d21938e 100644
--- a/arch/arm/mach-s5pc100/common.c
+++ b/arch/arm/mach-s5pc100/common.c
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/serial_core.h>
+#include <linux/platform_data/samsung-pwm.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
 
@@ -131,6 +132,13 @@ static struct map_desc s5pc100_iodesc[] __initdata = {
 	}
 };
 
+static struct samsung_pwm_variant s5pc100_pwm_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= (1 << 5),
+};
+
 /*
  * s5pc100_map_io
  *
@@ -148,6 +156,8 @@ void __init s5pc100_init_io(struct map_desc *mach_desc, int size)
 	s5p_init_cpu(S5P_VA_CHIPID);
 
 	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
+
+	samsung_device_pwm.dev.platform_data = &s5pc100_pwm_variant;
 }
 
 void __init s5pc100_map_io(void)
diff --git a/arch/arm/mach-s5pv210/common.c b/arch/arm/mach-s5pv210/common.c
index 9dfe93e..a3fc208 100644
--- a/arch/arm/mach-s5pv210/common.c
+++ b/arch/arm/mach-s5pv210/common.c
@@ -19,6 +19,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/device.h>
+#include <linux/platform_data/samsung-pwm.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/dma-mapping.h>
@@ -148,6 +149,13 @@ void s5pv210_restart(char mode, const char *cmd)
 	__raw_writel(0x1, S5P_SWRESET);
 }
 
+static struct samsung_pwm_variant s5pv210_pwm_variant = {
+	.bits		= 32,
+	.div_base	= 0,
+	.has_tint_cstat	= true,
+	.tclk_mask	= (1 << 5),
+};
+
 /*
  * s5pv210_map_io
  *
@@ -165,6 +173,8 @@ void __init s5pv210_init_io(struct map_desc *mach_desc, int size)
 	s5p_init_cpu(S5P_VA_CHIPID);
 
 	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
+
+	samsung_device_pwm.dev.platform_data = &s5pv210_pwm_variant;
 }
 
 void __init s5pv210_map_io(void)
-- 
1.8.1.5

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

* [PATCH v4 08/14] clocksource: samsung-time: Use Samsung PWM/timer master driver
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 16:37   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

This patch modifies the samsung-time clocksource driver to use the
interface provided by Samsung PWM/timer master driver to get platform
data.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/plat-samsung/devs.c                      |  7 ++++
 arch/arm/plat-samsung/include/plat/samsung-time.h | 17 +++++++--
 drivers/clocksource/samsung-time.c                | 44 ++++++++++++++---------
 include/linux/platform_data/samsung-pwm.h         |  1 +
 4 files changed, 51 insertions(+), 18 deletions(-)

diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index bfae4dd..747763d 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -57,6 +57,7 @@
 #include <plat/keypad.h>
 #include <linux/platform_data/mmc-s3cmci.h>
 #include <linux/platform_data/mtd-nand-s3c2410.h>
+#include <plat/samsung-time.h>
 #include <plat/sdhci.h>
 #include <linux/platform_data/touchscreen-s3c2410.h>
 #include <linux/platform_data/usb-s3c2410_udc.h>
@@ -1184,6 +1185,12 @@ struct platform_device samsung_device_pwm = {
 	.resource	= samsung_pwm_resource,
 };
 
+void samsung_timer_init(void)
+{
+	samsung_pwm_register(&samsung_device_pwm);
+	samsung_time_init();
+}
+
 /* RTC */
 
 #ifdef CONFIG_PLAT_S3C24XX
diff --git a/arch/arm/plat-samsung/include/plat/samsung-time.h b/arch/arm/plat-samsung/include/plat/samsung-time.h
index 5d098ef..c0f35cc 100644
--- a/arch/arm/plat-samsung/include/plat/samsung-time.h
+++ b/arch/arm/plat-samsung/include/plat/samsung-time.h
@@ -13,6 +13,10 @@
 #ifndef __ASM_PLAT_SAMSUNG_TIME_H
 #define __ASM_PLAT_SAMSUNG_TIME_H __FILE__
 
+#include <linux/platform_data/samsung-pwm.h>
+
+#include <plat/devs.h>
+
 /* SAMSUNG HR-Timer Clock mode */
 enum samsung_timer_mode {
 	SAMSUNG_PWM0,
@@ -39,8 +43,17 @@ struct samsung_timer_source {
 #define TSIZE			32
 #endif
 
-extern void __init samsung_set_timer_source(enum samsung_timer_mode event,
-					enum samsung_timer_mode source);
+static inline void samsung_set_timer_source(enum samsung_timer_mode event,
+					enum samsung_timer_mode source)
+{
+	struct samsung_pwm_variant *variant;
+
+	variant = samsung_device_pwm.dev.platform_data;
+	BUG_ON(!variant);
+
+	variant->output_mask = (1 << 5) - 1;
+	variant->output_mask &= ~((1 << event) | (1 << source));
+}
 
 extern void __init samsung_timer_init(void);
 
diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index bccc291..11d7a54 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -14,19 +14,14 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/clockchips.h>
+#include <linux/mfd/samsung-pwm.h>
 #include <linux/platform_device.h>
 
-#include <asm/smp_twd.h>
-#include <asm/mach/time.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
 #include <asm/sched_clock.h>
 
-#include <mach/map.h>
 #include <plat/devs.h>
 #include <plat/samsung-time.h>
-
-#define S3C_TIMERREG(x) (S3C_VA_TIMER + (x))
+#define S3C_TIMERREG(x) (pwm->base + (x))
 #define S3C_TIMERREG2(tmr,reg) S3C_TIMERREG((reg)+0x0c+((tmr)*0x0c))
 
 #define S3C2410_TCON	      S3C_TIMERREG(0x08)
@@ -61,6 +56,7 @@
 #define S3C2410_TCON_T0MANUALUPD  (1<<1)
 #define S3C2410_TCON_T0START	  (1<<0)
 
+static struct samsung_pwm *pwm;
 static struct clk *tin_event;
 static struct clk *tin_source;
 static struct clk *tdiv_event;
@@ -256,16 +252,9 @@ static void samsung_timer_resume(void)
 	samsung_time_start(timer_source.source_id, true);
 }
 
-void __init samsung_set_timer_source(enum samsung_timer_mode event,
-				 enum samsung_timer_mode source)
-{
 	s3c_device_timer[event].dev.bus = &platform_bus_type;
 	s3c_device_timer[source].dev.bus = &platform_bus_type;
 
-	timer_source.event_id = event;
-	timer_source.source_id = source;
-}
-
 static struct clock_event_device time_event_device = {
 	.name		= "samsung_event_timer",
 	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
@@ -311,7 +300,7 @@ static void __init samsung_clockevent_init(void)
 	time_event_device.cpumask = cpumask_of(0);
 	clockevents_config_and_register(&time_event_device, clock_rate, 1, -1);
 
-	irq_number = timer_source.event_id + IRQ_TIMER0;
+	irq_number = pwm->irq[timer_source.event_id];
 	setup_irq(irq_number, &samsung_clock_event_irq);
 }
 
@@ -420,8 +409,31 @@ static void __init samsung_timer_resources(void)
 	clk_enable(tin_source);
 }
 
-void __init samsung_timer_init(void)
+void __init samsung_time_init(void)
 {
+	u8 mask;
+	int channel;
+
+	pwm = samsung_pwm_get(NULL);
+	if (IS_ERR(pwm))
+		panic("failed to get PWM device");
+
+	mask = ~pwm->variant.output_mask & ((1 << SAMSUNG_PWM_NUM) - 1);
+	channel = fls(mask) - 1;
+	if (channel < 0)
+		panic("failed to find PWM channel for clocksource");
+	timer_source.source_id = channel;
+
+	samsung_pwm_request(pwm, channel);
+
+	mask &= ~(1 << channel);
+	channel = fls(mask) - 1;
+	if (channel < 0)
+		panic("failed to find PWM channel for clock event");
+	timer_source.event_id = channel;
+
+	samsung_pwm_request(pwm, channel);
+
 	samsung_timer_resources();
 	samsung_clockevent_init();
 	samsung_clocksource_init();
diff --git a/include/linux/platform_data/samsung-pwm.h b/include/linux/platform_data/samsung-pwm.h
index 8c48dbb..ca6c488 100644
--- a/include/linux/platform_data/samsung-pwm.h
+++ b/include/linux/platform_data/samsung-pwm.h
@@ -24,5 +24,6 @@ struct samsung_pwm_variant {
 };
 
 extern int samsung_pwm_register(struct platform_device *pdev);
+extern void samsung_time_init(void);
 
 #endif
-- 
1.8.1.5

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

* [PATCH v4 08/14] clocksource: samsung-time: Use Samsung PWM/timer master driver
@ 2013-04-04 16:37   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

This patch modifies the samsung-time clocksource driver to use the
interface provided by Samsung PWM/timer master driver to get platform
data.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/plat-samsung/devs.c                      |  7 ++++
 arch/arm/plat-samsung/include/plat/samsung-time.h | 17 +++++++--
 drivers/clocksource/samsung-time.c                | 44 ++++++++++++++---------
 include/linux/platform_data/samsung-pwm.h         |  1 +
 4 files changed, 51 insertions(+), 18 deletions(-)

diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index bfae4dd..747763d 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -57,6 +57,7 @@
 #include <plat/keypad.h>
 #include <linux/platform_data/mmc-s3cmci.h>
 #include <linux/platform_data/mtd-nand-s3c2410.h>
+#include <plat/samsung-time.h>
 #include <plat/sdhci.h>
 #include <linux/platform_data/touchscreen-s3c2410.h>
 #include <linux/platform_data/usb-s3c2410_udc.h>
@@ -1184,6 +1185,12 @@ struct platform_device samsung_device_pwm = {
 	.resource	= samsung_pwm_resource,
 };
 
+void samsung_timer_init(void)
+{
+	samsung_pwm_register(&samsung_device_pwm);
+	samsung_time_init();
+}
+
 /* RTC */
 
 #ifdef CONFIG_PLAT_S3C24XX
diff --git a/arch/arm/plat-samsung/include/plat/samsung-time.h b/arch/arm/plat-samsung/include/plat/samsung-time.h
index 5d098ef..c0f35cc 100644
--- a/arch/arm/plat-samsung/include/plat/samsung-time.h
+++ b/arch/arm/plat-samsung/include/plat/samsung-time.h
@@ -13,6 +13,10 @@
 #ifndef __ASM_PLAT_SAMSUNG_TIME_H
 #define __ASM_PLAT_SAMSUNG_TIME_H __FILE__
 
+#include <linux/platform_data/samsung-pwm.h>
+
+#include <plat/devs.h>
+
 /* SAMSUNG HR-Timer Clock mode */
 enum samsung_timer_mode {
 	SAMSUNG_PWM0,
@@ -39,8 +43,17 @@ struct samsung_timer_source {
 #define TSIZE			32
 #endif
 
-extern void __init samsung_set_timer_source(enum samsung_timer_mode event,
-					enum samsung_timer_mode source);
+static inline void samsung_set_timer_source(enum samsung_timer_mode event,
+					enum samsung_timer_mode source)
+{
+	struct samsung_pwm_variant *variant;
+
+	variant = samsung_device_pwm.dev.platform_data;
+	BUG_ON(!variant);
+
+	variant->output_mask = (1 << 5) - 1;
+	variant->output_mask &= ~((1 << event) | (1 << source));
+}
 
 extern void __init samsung_timer_init(void);
 
diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index bccc291..11d7a54 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -14,19 +14,14 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/clockchips.h>
+#include <linux/mfd/samsung-pwm.h>
 #include <linux/platform_device.h>
 
-#include <asm/smp_twd.h>
-#include <asm/mach/time.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
 #include <asm/sched_clock.h>
 
-#include <mach/map.h>
 #include <plat/devs.h>
 #include <plat/samsung-time.h>
-
-#define S3C_TIMERREG(x) (S3C_VA_TIMER + (x))
+#define S3C_TIMERREG(x) (pwm->base + (x))
 #define S3C_TIMERREG2(tmr,reg) S3C_TIMERREG((reg)+0x0c+((tmr)*0x0c))
 
 #define S3C2410_TCON	      S3C_TIMERREG(0x08)
@@ -61,6 +56,7 @@
 #define S3C2410_TCON_T0MANUALUPD  (1<<1)
 #define S3C2410_TCON_T0START	  (1<<0)
 
+static struct samsung_pwm *pwm;
 static struct clk *tin_event;
 static struct clk *tin_source;
 static struct clk *tdiv_event;
@@ -256,16 +252,9 @@ static void samsung_timer_resume(void)
 	samsung_time_start(timer_source.source_id, true);
 }
 
-void __init samsung_set_timer_source(enum samsung_timer_mode event,
-				 enum samsung_timer_mode source)
-{
 	s3c_device_timer[event].dev.bus = &platform_bus_type;
 	s3c_device_timer[source].dev.bus = &platform_bus_type;
 
-	timer_source.event_id = event;
-	timer_source.source_id = source;
-}
-
 static struct clock_event_device time_event_device = {
 	.name		= "samsung_event_timer",
 	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
@@ -311,7 +300,7 @@ static void __init samsung_clockevent_init(void)
 	time_event_device.cpumask = cpumask_of(0);
 	clockevents_config_and_register(&time_event_device, clock_rate, 1, -1);
 
-	irq_number = timer_source.event_id + IRQ_TIMER0;
+	irq_number = pwm->irq[timer_source.event_id];
 	setup_irq(irq_number, &samsung_clock_event_irq);
 }
 
@@ -420,8 +409,31 @@ static void __init samsung_timer_resources(void)
 	clk_enable(tin_source);
 }
 
-void __init samsung_timer_init(void)
+void __init samsung_time_init(void)
 {
+	u8 mask;
+	int channel;
+
+	pwm = samsung_pwm_get(NULL);
+	if (IS_ERR(pwm))
+		panic("failed to get PWM device");
+
+	mask = ~pwm->variant.output_mask & ((1 << SAMSUNG_PWM_NUM) - 1);
+	channel = fls(mask) - 1;
+	if (channel < 0)
+		panic("failed to find PWM channel for clocksource");
+	timer_source.source_id = channel;
+
+	samsung_pwm_request(pwm, channel);
+
+	mask &= ~(1 << channel);
+	channel = fls(mask) - 1;
+	if (channel < 0)
+		panic("failed to find PWM channel for clock event");
+	timer_source.event_id = channel;
+
+	samsung_pwm_request(pwm, channel);
+
 	samsung_timer_resources();
 	samsung_clockevent_init();
 	samsung_clocksource_init();
diff --git a/include/linux/platform_data/samsung-pwm.h b/include/linux/platform_data/samsung-pwm.h
index 8c48dbb..ca6c488 100644
--- a/include/linux/platform_data/samsung-pwm.h
+++ b/include/linux/platform_data/samsung-pwm.h
@@ -24,5 +24,6 @@ struct samsung_pwm_variant {
 };
 
 extern int samsung_pwm_register(struct platform_device *pdev);
+extern void samsung_time_init(void);
 
 #endif
-- 
1.8.1.5

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

* [PATCH v4 09/14] clocksource: samsung-time: Use variant data to get SoC-specific bits
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 16:37   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

This patch modifies the driver to calculate SoC-specific parameters from
variant data received from PWM/timer master driver.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/plat-samsung/include/plat/samsung-time.h | 17 --------
 drivers/clocksource/samsung-time.c                | 51 ++++++++++++++++++-----
 2 files changed, 41 insertions(+), 27 deletions(-)

diff --git a/arch/arm/plat-samsung/include/plat/samsung-time.h b/arch/arm/plat-samsung/include/plat/samsung-time.h
index c0f35cc..785c6b7 100644
--- a/arch/arm/plat-samsung/include/plat/samsung-time.h
+++ b/arch/arm/plat-samsung/include/plat/samsung-time.h
@@ -26,23 +26,6 @@ enum samsung_timer_mode {
 	SAMSUNG_PWM4,
 };
 
-struct samsung_timer_source {
-	unsigned int event_id;
-	unsigned int source_id;
-};
-
-#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S5PC100)
-#define TCNT_MAX		0xffff
-#define TSCALER_DIV		25
-#define TDIV			50
-#define TSIZE			16
-#else
-#define TCNT_MAX		0xffffffff
-#define TSCALER_DIV		2
-#define TDIV			2
-#define TSIZE			32
-#endif
-
 static inline void samsung_set_timer_source(enum samsung_timer_mode event,
 					enum samsung_timer_mode source)
 {
diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index 11d7a54..4fa6f6f 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -20,7 +20,6 @@
 #include <asm/sched_clock.h>
 
 #include <plat/devs.h>
-#include <plat/samsung-time.h>
 #define S3C_TIMERREG(x) (pwm->base + (x))
 #define S3C_TIMERREG2(tmr,reg) S3C_TIMERREG((reg)+0x0c+((tmr)*0x0c))
 
@@ -56,6 +55,22 @@
 #define S3C2410_TCON_T0MANUALUPD  (1<<1)
 #define S3C2410_TCON_T0START	  (1<<0)
 
+enum samsung_timer_mode {
+	SAMSUNG_PWM0,
+	SAMSUNG_PWM1,
+	SAMSUNG_PWM2,
+	SAMSUNG_PWM3,
+	SAMSUNG_PWM4,
+};
+
+struct samsung_timer_source {
+	unsigned int event_id;
+	unsigned int source_id;
+	u32 tcnt_max;
+	u16 tscaler_div;
+	u16 tdiv;
+};
+
 static struct samsung_pwm *pwm;
 static struct clk *tin_event;
 static struct clk *tin_source;
@@ -248,7 +263,7 @@ static void samsung_timer_resume(void)
 	samsung_time_start(timer_source.event_id, true);
 
 	/* source timer restart */
-	samsung_time_setup(timer_source.source_id, TCNT_MAX);
+	samsung_time_setup(timer_source.source_id, timer_source.tcnt_max);
 	samsung_time_start(timer_source.source_id, true);
 }
 
@@ -290,15 +305,17 @@ static void __init samsung_clockevent_init(void)
 
 	tscaler = clk_get_parent(tdiv_event);
 
-	clk_set_rate(tscaler, pclk / TSCALER_DIV);
-	clk_set_rate(tdiv_event, pclk / TDIV);
+	clk_set_rate(tscaler, pclk / timer_source.tscaler_div);
+	clk_set_rate(tdiv_event,
+			pclk / (timer_source.tscaler_div * timer_source.tdiv));
 	clk_set_parent(tin_event, tdiv_event);
 
 	clock_rate = clk_get_rate(tin_event);
 	clock_count_per_tick = clock_rate / HZ;
 
 	time_event_device.cpumask = cpumask_of(0);
-	clockevents_config_and_register(&time_event_device, clock_rate, 1, -1);
+	clockevents_config_and_register(&time_event_device, clock_rate,
+						1, timer_source.tcnt_max);
 
 	irq_number = pwm->irq[timer_source.event_id];
 	setup_irq(irq_number, &samsung_clock_event_irq);
@@ -349,21 +366,26 @@ static void __init samsung_clocksource_init(void)
 {
 	unsigned long pclk;
 	unsigned long clock_rate;
+	int ret;
 
 	pclk = clk_get_rate(timerclk);
 
-	clk_set_rate(tdiv_source, pclk / TDIV);
+	clk_set_rate(tdiv_source,
+			pclk / (timer_source.tscaler_div * timer_source.tdiv));
 	clk_set_parent(tin_source, tdiv_source);
 
 	clock_rate = clk_get_rate(tin_source);
 
-	samsung_time_setup(timer_source.source_id, TCNT_MAX);
+	samsung_time_setup(timer_source.source_id, timer_source.tcnt_max);
 	samsung_time_start(timer_source.source_id, true);
 
-	setup_sched_clock(samsung_read_sched_clock, TSIZE, clock_rate);
+	setup_sched_clock(samsung_read_sched_clock,
+						pwm->variant.bits, clock_rate);
 
-	if (clocksource_mmio_init(samsung_timer_reg(), "samsung_clocksource_timer",
-			clock_rate, 250, TSIZE, clocksource_mmio_readl_down))
+	ret = clocksource_mmio_init(samsung_timer_reg(),
+			"samsung_clocksource_timer", clock_rate, 250,
+			pwm->variant.bits, clocksource_mmio_readl_down);
+	if (ret)
 		panic("samsung_clocksource_timer: can't register clocksource\n");
 }
 
@@ -407,6 +429,15 @@ static void __init samsung_timer_resources(void)
 		panic("failed to get pwm-tdiv clock for source timer");
 
 	clk_enable(tin_source);
+
+	timer_source.tcnt_max = (1UL << pwm->variant.bits) - 1;
+	if (pwm->variant.bits == 16) {
+		timer_source.tscaler_div = 25;
+		timer_source.tdiv = 2;
+	} else {
+		timer_source.tscaler_div = 2;
+		timer_source.tdiv = 1;
+	}
 }
 
 void __init samsung_time_init(void)
-- 
1.8.1.5

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

* [PATCH v4 09/14] clocksource: samsung-time: Use variant data to get SoC-specific bits
@ 2013-04-04 16:37   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

This patch modifies the driver to calculate SoC-specific parameters from
variant data received from PWM/timer master driver.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/plat-samsung/include/plat/samsung-time.h | 17 --------
 drivers/clocksource/samsung-time.c                | 51 ++++++++++++++++++-----
 2 files changed, 41 insertions(+), 27 deletions(-)

diff --git a/arch/arm/plat-samsung/include/plat/samsung-time.h b/arch/arm/plat-samsung/include/plat/samsung-time.h
index c0f35cc..785c6b7 100644
--- a/arch/arm/plat-samsung/include/plat/samsung-time.h
+++ b/arch/arm/plat-samsung/include/plat/samsung-time.h
@@ -26,23 +26,6 @@ enum samsung_timer_mode {
 	SAMSUNG_PWM4,
 };
 
-struct samsung_timer_source {
-	unsigned int event_id;
-	unsigned int source_id;
-};
-
-#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S5PC100)
-#define TCNT_MAX		0xffff
-#define TSCALER_DIV		25
-#define TDIV			50
-#define TSIZE			16
-#else
-#define TCNT_MAX		0xffffffff
-#define TSCALER_DIV		2
-#define TDIV			2
-#define TSIZE			32
-#endif
-
 static inline void samsung_set_timer_source(enum samsung_timer_mode event,
 					enum samsung_timer_mode source)
 {
diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index 11d7a54..4fa6f6f 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -20,7 +20,6 @@
 #include <asm/sched_clock.h>
 
 #include <plat/devs.h>
-#include <plat/samsung-time.h>
 #define S3C_TIMERREG(x) (pwm->base + (x))
 #define S3C_TIMERREG2(tmr,reg) S3C_TIMERREG((reg)+0x0c+((tmr)*0x0c))
 
@@ -56,6 +55,22 @@
 #define S3C2410_TCON_T0MANUALUPD  (1<<1)
 #define S3C2410_TCON_T0START	  (1<<0)
 
+enum samsung_timer_mode {
+	SAMSUNG_PWM0,
+	SAMSUNG_PWM1,
+	SAMSUNG_PWM2,
+	SAMSUNG_PWM3,
+	SAMSUNG_PWM4,
+};
+
+struct samsung_timer_source {
+	unsigned int event_id;
+	unsigned int source_id;
+	u32 tcnt_max;
+	u16 tscaler_div;
+	u16 tdiv;
+};
+
 static struct samsung_pwm *pwm;
 static struct clk *tin_event;
 static struct clk *tin_source;
@@ -248,7 +263,7 @@ static void samsung_timer_resume(void)
 	samsung_time_start(timer_source.event_id, true);
 
 	/* source timer restart */
-	samsung_time_setup(timer_source.source_id, TCNT_MAX);
+	samsung_time_setup(timer_source.source_id, timer_source.tcnt_max);
 	samsung_time_start(timer_source.source_id, true);
 }
 
@@ -290,15 +305,17 @@ static void __init samsung_clockevent_init(void)
 
 	tscaler = clk_get_parent(tdiv_event);
 
-	clk_set_rate(tscaler, pclk / TSCALER_DIV);
-	clk_set_rate(tdiv_event, pclk / TDIV);
+	clk_set_rate(tscaler, pclk / timer_source.tscaler_div);
+	clk_set_rate(tdiv_event,
+			pclk / (timer_source.tscaler_div * timer_source.tdiv));
 	clk_set_parent(tin_event, tdiv_event);
 
 	clock_rate = clk_get_rate(tin_event);
 	clock_count_per_tick = clock_rate / HZ;
 
 	time_event_device.cpumask = cpumask_of(0);
-	clockevents_config_and_register(&time_event_device, clock_rate, 1, -1);
+	clockevents_config_and_register(&time_event_device, clock_rate,
+						1, timer_source.tcnt_max);
 
 	irq_number = pwm->irq[timer_source.event_id];
 	setup_irq(irq_number, &samsung_clock_event_irq);
@@ -349,21 +366,26 @@ static void __init samsung_clocksource_init(void)
 {
 	unsigned long pclk;
 	unsigned long clock_rate;
+	int ret;
 
 	pclk = clk_get_rate(timerclk);
 
-	clk_set_rate(tdiv_source, pclk / TDIV);
+	clk_set_rate(tdiv_source,
+			pclk / (timer_source.tscaler_div * timer_source.tdiv));
 	clk_set_parent(tin_source, tdiv_source);
 
 	clock_rate = clk_get_rate(tin_source);
 
-	samsung_time_setup(timer_source.source_id, TCNT_MAX);
+	samsung_time_setup(timer_source.source_id, timer_source.tcnt_max);
 	samsung_time_start(timer_source.source_id, true);
 
-	setup_sched_clock(samsung_read_sched_clock, TSIZE, clock_rate);
+	setup_sched_clock(samsung_read_sched_clock,
+						pwm->variant.bits, clock_rate);
 
-	if (clocksource_mmio_init(samsung_timer_reg(), "samsung_clocksource_timer",
-			clock_rate, 250, TSIZE, clocksource_mmio_readl_down))
+	ret = clocksource_mmio_init(samsung_timer_reg(),
+			"samsung_clocksource_timer", clock_rate, 250,
+			pwm->variant.bits, clocksource_mmio_readl_down);
+	if (ret)
 		panic("samsung_clocksource_timer: can't register clocksource\n");
 }
 
@@ -407,6 +429,15 @@ static void __init samsung_timer_resources(void)
 		panic("failed to get pwm-tdiv clock for source timer");
 
 	clk_enable(tin_source);
+
+	timer_source.tcnt_max = (1UL << pwm->variant.bits) - 1;
+	if (pwm->variant.bits == 16) {
+		timer_source.tscaler_div = 25;
+		timer_source.tdiv = 2;
+	} else {
+		timer_source.tscaler_div = 2;
+		timer_source.tdiv = 1;
+	}
 }
 
 void __init samsung_time_init(void)
-- 
1.8.1.5

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

* [PATCH v4 10/14] clocksource: samsung-time: Use master driver to configure dividers
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 16:37   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

This patch modifies the driver to use functions provided by master
driver to configure PWM frequency dividers.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/clocksource/samsung-time.c | 61 +++++---------------------------------
 1 file changed, 8 insertions(+), 53 deletions(-)

diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index 4fa6f6f..e617d37 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -19,7 +19,6 @@
 
 #include <asm/sched_clock.h>
 
-#include <plat/devs.h>
 #define S3C_TIMERREG(x) (pwm->base + (x))
 #define S3C_TIMERREG2(tmr,reg) S3C_TIMERREG((reg)+0x0c+((tmr)*0x0c))
 
@@ -72,10 +71,6 @@ struct samsung_timer_source {
 };
 
 static struct samsung_pwm *pwm;
-static struct clk *tin_event;
-static struct clk *tin_source;
-static struct clk *tdiv_event;
-static struct clk *tdiv_source;
 static struct clk *timerclk;
 static struct samsung_timer_source timer_source;
 static unsigned long clock_count_per_tick;
@@ -267,9 +262,6 @@ static void samsung_timer_resume(void)
 	samsung_time_start(timer_source.source_id, true);
 }
 
-	s3c_device_timer[event].dev.bus = &platform_bus_type;
-	s3c_device_timer[source].dev.bus = &platform_bus_type;
-
 static struct clock_event_device time_event_device = {
 	.name		= "samsung_event_timer",
 	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
@@ -299,18 +291,14 @@ static void __init samsung_clockevent_init(void)
 	unsigned long pclk;
 	unsigned long clock_rate;
 	unsigned int irq_number;
-	struct clk *tscaler;
 
 	pclk = clk_get_rate(timerclk);
 
-	tscaler = clk_get_parent(tdiv_event);
-
-	clk_set_rate(tscaler, pclk / timer_source.tscaler_div);
-	clk_set_rate(tdiv_event,
-			pclk / (timer_source.tscaler_div * timer_source.tdiv));
-	clk_set_parent(tin_event, tdiv_event);
+	samsung_pwm_set_prescale(pwm, timer_source.event_id,
+						timer_source.tscaler_div);
+	samsung_pwm_set_divisor(pwm, timer_source.event_id, timer_source.tdiv);
 
-	clock_rate = clk_get_rate(tin_event);
+	clock_rate = pclk / (timer_source.tscaler_div * timer_source.tdiv);
 	clock_count_per_tick = clock_rate / HZ;
 
 	time_event_device.cpumask = cpumask_of(0);
@@ -370,11 +358,11 @@ static void __init samsung_clocksource_init(void)
 
 	pclk = clk_get_rate(timerclk);
 
-	clk_set_rate(tdiv_source,
-			pclk / (timer_source.tscaler_div * timer_source.tdiv));
-	clk_set_parent(tin_source, tdiv_source);
+	samsung_pwm_set_prescale(pwm, timer_source.source_id,
+						timer_source.tscaler_div);
+	samsung_pwm_set_divisor(pwm, timer_source.source_id, timer_source.tdiv);
 
-	clock_rate = clk_get_rate(tin_source);
+	clock_rate = pclk / (timer_source.tscaler_div * timer_source.tdiv);
 
 	samsung_time_setup(timer_source.source_id, timer_source.tcnt_max);
 	samsung_time_start(timer_source.source_id, true);
@@ -391,43 +379,10 @@ static void __init samsung_clocksource_init(void)
 
 static void __init samsung_timer_resources(void)
 {
-
-	unsigned long event_id = timer_source.event_id;
-	unsigned long source_id = timer_source.source_id;
-	char devname[15];
-
 	timerclk = clk_get(NULL, "timers");
 	if (IS_ERR(timerclk))
 		panic("failed to get timers clock for timer");
 
-	clk_enable(timerclk);
-
-	sprintf(devname, "s3c24xx-pwm.%lu", event_id);
-	s3c_device_timer[event_id].id = event_id;
-	s3c_device_timer[event_id].dev.init_name = devname;
-
-	tin_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tin");
-	if (IS_ERR(tin_event))
-		panic("failed to get pwm-tin clock for event timer");
-
-	tdiv_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tdiv");
-	if (IS_ERR(tdiv_event))
-		panic("failed to get pwm-tdiv clock for event timer");
-
-	clk_enable(tin_event);
-
-	sprintf(devname, "s3c24xx-pwm.%lu", source_id);
-	s3c_device_timer[source_id].id = source_id;
-	s3c_device_timer[source_id].dev.init_name = devname;
-
-	tin_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tin");
-	if (IS_ERR(tin_source))
-		panic("failed to get pwm-tin clock for source timer");
-
-	tdiv_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tdiv");
-	if (IS_ERR(tdiv_source))
-		panic("failed to get pwm-tdiv clock for source timer");
-
 	clk_enable(tin_source);
 
 	timer_source.tcnt_max = (1UL << pwm->variant.bits) - 1;
-- 
1.8.1.5

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

* [PATCH v4 10/14] clocksource: samsung-time: Use master driver to configure dividers
@ 2013-04-04 16:37   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

This patch modifies the driver to use functions provided by master
driver to configure PWM frequency dividers.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/clocksource/samsung-time.c | 61 +++++---------------------------------
 1 file changed, 8 insertions(+), 53 deletions(-)

diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index 4fa6f6f..e617d37 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -19,7 +19,6 @@
 
 #include <asm/sched_clock.h>
 
-#include <plat/devs.h>
 #define S3C_TIMERREG(x) (pwm->base + (x))
 #define S3C_TIMERREG2(tmr,reg) S3C_TIMERREG((reg)+0x0c+((tmr)*0x0c))
 
@@ -72,10 +71,6 @@ struct samsung_timer_source {
 };
 
 static struct samsung_pwm *pwm;
-static struct clk *tin_event;
-static struct clk *tin_source;
-static struct clk *tdiv_event;
-static struct clk *tdiv_source;
 static struct clk *timerclk;
 static struct samsung_timer_source timer_source;
 static unsigned long clock_count_per_tick;
@@ -267,9 +262,6 @@ static void samsung_timer_resume(void)
 	samsung_time_start(timer_source.source_id, true);
 }
 
-	s3c_device_timer[event].dev.bus = &platform_bus_type;
-	s3c_device_timer[source].dev.bus = &platform_bus_type;
-
 static struct clock_event_device time_event_device = {
 	.name		= "samsung_event_timer",
 	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
@@ -299,18 +291,14 @@ static void __init samsung_clockevent_init(void)
 	unsigned long pclk;
 	unsigned long clock_rate;
 	unsigned int irq_number;
-	struct clk *tscaler;
 
 	pclk = clk_get_rate(timerclk);
 
-	tscaler = clk_get_parent(tdiv_event);
-
-	clk_set_rate(tscaler, pclk / timer_source.tscaler_div);
-	clk_set_rate(tdiv_event,
-			pclk / (timer_source.tscaler_div * timer_source.tdiv));
-	clk_set_parent(tin_event, tdiv_event);
+	samsung_pwm_set_prescale(pwm, timer_source.event_id,
+						timer_source.tscaler_div);
+	samsung_pwm_set_divisor(pwm, timer_source.event_id, timer_source.tdiv);
 
-	clock_rate = clk_get_rate(tin_event);
+	clock_rate = pclk / (timer_source.tscaler_div * timer_source.tdiv);
 	clock_count_per_tick = clock_rate / HZ;
 
 	time_event_device.cpumask = cpumask_of(0);
@@ -370,11 +358,11 @@ static void __init samsung_clocksource_init(void)
 
 	pclk = clk_get_rate(timerclk);
 
-	clk_set_rate(tdiv_source,
-			pclk / (timer_source.tscaler_div * timer_source.tdiv));
-	clk_set_parent(tin_source, tdiv_source);
+	samsung_pwm_set_prescale(pwm, timer_source.source_id,
+						timer_source.tscaler_div);
+	samsung_pwm_set_divisor(pwm, timer_source.source_id, timer_source.tdiv);
 
-	clock_rate = clk_get_rate(tin_source);
+	clock_rate = pclk / (timer_source.tscaler_div * timer_source.tdiv);
 
 	samsung_time_setup(timer_source.source_id, timer_source.tcnt_max);
 	samsung_time_start(timer_source.source_id, true);
@@ -391,43 +379,10 @@ static void __init samsung_clocksource_init(void)
 
 static void __init samsung_timer_resources(void)
 {
-
-	unsigned long event_id = timer_source.event_id;
-	unsigned long source_id = timer_source.source_id;
-	char devname[15];
-
 	timerclk = clk_get(NULL, "timers");
 	if (IS_ERR(timerclk))
 		panic("failed to get timers clock for timer");
 
-	clk_enable(timerclk);
-
-	sprintf(devname, "s3c24xx-pwm.%lu", event_id);
-	s3c_device_timer[event_id].id = event_id;
-	s3c_device_timer[event_id].dev.init_name = devname;
-
-	tin_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tin");
-	if (IS_ERR(tin_event))
-		panic("failed to get pwm-tin clock for event timer");
-
-	tdiv_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tdiv");
-	if (IS_ERR(tdiv_event))
-		panic("failed to get pwm-tdiv clock for event timer");
-
-	clk_enable(tin_event);
-
-	sprintf(devname, "s3c24xx-pwm.%lu", source_id);
-	s3c_device_timer[source_id].id = source_id;
-	s3c_device_timer[source_id].dev.init_name = devname;
-
-	tin_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tin");
-	if (IS_ERR(tin_source))
-		panic("failed to get pwm-tin clock for source timer");
-
-	tdiv_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tdiv");
-	if (IS_ERR(tdiv_source))
-		panic("failed to get pwm-tdiv clock for source timer");
-
 	clk_enable(tin_source);
 
 	timer_source.tcnt_max = (1UL << pwm->variant.bits) - 1;
-- 
1.8.1.5

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

* [PATCH v4 11/14] clocksource: samsung-time: Use clk_prepare_enable
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 16:37   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

This patch modifies the driver to use clk_prepare_enable instead of
clk_enable, as required to be compliant with Common Clock Framework.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/clocksource/samsung-time.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index e617d37..7674882 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -383,7 +383,7 @@ static void __init samsung_timer_resources(void)
 	if (IS_ERR(timerclk))
 		panic("failed to get timers clock for timer");
 
-	clk_enable(tin_source);
+	clk_prepare_enable(timerclk);
 
 	timer_source.tcnt_max = (1UL << pwm->variant.bits) - 1;
 	if (pwm->variant.bits == 16) {
-- 
1.8.1.5

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

* [PATCH v4 11/14] clocksource: samsung-time: Use clk_prepare_enable
@ 2013-04-04 16:37   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

This patch modifies the driver to use clk_prepare_enable instead of
clk_enable, as required to be compliant with Common Clock Framework.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/clocksource/samsung-time.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index e617d37..7674882 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -383,7 +383,7 @@ static void __init samsung_timer_resources(void)
 	if (IS_ERR(timerclk))
 		panic("failed to get timers clock for timer");
 
-	clk_enable(tin_source);
+	clk_prepare_enable(timerclk);
 
 	timer_source.tcnt_max = (1UL << pwm->variant.bits) - 1;
 	if (pwm->variant.bits == 16) {
-- 
1.8.1.5

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

* [PATCH v4 12/14] clocksource: samsung-time: Use master driver to control PWM channels
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 16:37   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

This patch modifies the driver to use functions provided by the master
driver to control status of PWM channels instead of modifying shared
registers directly.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/clocksource/samsung-time.c | 168 ++++---------------------------------
 1 file changed, 15 insertions(+), 153 deletions(-)

diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index 7674882..9425955 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -76,153 +76,11 @@ static struct samsung_timer_source timer_source;
 static unsigned long clock_count_per_tick;
 static void samsung_timer_resume(void);
 
-static void samsung_time_stop(enum samsung_timer_mode mode)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	switch (mode) {
-	case SAMSUNG_PWM0:
-		tcon &= ~S3C2410_TCON_T0START;
-		break;
-
-	case SAMSUNG_PWM1:
-		tcon &= ~S3C2410_TCON_T1START;
-		break;
-
-	case SAMSUNG_PWM2:
-		tcon &= ~S3C2410_TCON_T2START;
-		break;
-
-	case SAMSUNG_PWM3:
-		tcon &= ~S3C2410_TCON_T3START;
-		break;
-
-	case SAMSUNG_PWM4:
-		tcon &= ~S3C2410_TCON_T4START;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void samsung_time_setup(enum samsung_timer_mode mode, unsigned long tcnt)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	tcnt--;
-
-	switch (mode) {
-	case SAMSUNG_PWM0:
-		tcon &= ~(0x0f << 0);
-		tcon |= S3C2410_TCON_T0MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM1:
-		tcon &= ~(0x0f << 8);
-		tcon |= S3C2410_TCON_T1MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM2:
-		tcon &= ~(0x0f << 12);
-		tcon |= S3C2410_TCON_T2MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM3:
-		tcon &= ~(0x0f << 16);
-		tcon |= S3C2410_TCON_T3MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM4:
-		tcon &= ~(0x07 << 20);
-		tcon |= S3C2410_TCON_T4MANUALUPD;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-
-	__raw_writel(tcnt, S3C2410_TCNTB(mode));
-	__raw_writel(tcnt, S3C2410_TCMPB(mode));
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void samsung_time_start(enum samsung_timer_mode mode, bool periodic)
-{
-	unsigned long tcon;
-
-	tcon  = __raw_readl(S3C2410_TCON);
-
-	switch (mode) {
-	case SAMSUNG_PWM0:
-		tcon |= S3C2410_TCON_T0START;
-		tcon &= ~S3C2410_TCON_T0MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T0RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T0RELOAD;
-		break;
-
-	case SAMSUNG_PWM1:
-		tcon |= S3C2410_TCON_T1START;
-		tcon &= ~S3C2410_TCON_T1MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T1RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T1RELOAD;
-		break;
-
-	case SAMSUNG_PWM2:
-		tcon |= S3C2410_TCON_T2START;
-		tcon &= ~S3C2410_TCON_T2MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T2RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T2RELOAD;
-		break;
-
-	case SAMSUNG_PWM3:
-		tcon |= S3C2410_TCON_T3START;
-		tcon &= ~S3C2410_TCON_T3MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T3RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T3RELOAD;
-		break;
-
-	case SAMSUNG_PWM4:
-		tcon |= S3C2410_TCON_T4START;
-		tcon &= ~S3C2410_TCON_T4MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T4RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T4RELOAD;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
 static int samsung_set_next_event(unsigned long cycles,
 				struct clock_event_device *evt)
 {
-	samsung_time_setup(timer_source.event_id, cycles);
-	samsung_time_start(timer_source.event_id, false);
+	samsung_pwm_setup(pwm, timer_source.event_id, cycles - 1, cycles - 1);
+	samsung_pwm_start(pwm, timer_source.event_id, false);
 
 	return 0;
 }
@@ -230,12 +88,13 @@ static int samsung_set_next_event(unsigned long cycles,
 static void samsung_set_mode(enum clock_event_mode mode,
 				struct clock_event_device *evt)
 {
-	samsung_time_stop(timer_source.event_id);
+	samsung_pwm_stop(pwm, timer_source.event_id);
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		samsung_time_setup(timer_source.event_id, clock_count_per_tick);
-		samsung_time_start(timer_source.event_id, true);
+		samsung_pwm_setup(pwm, timer_source.event_id,
+			clock_count_per_tick - 1, clock_count_per_tick - 1);
+		samsung_pwm_start(pwm, timer_source.event_id, true);
 		break;
 
 	case CLOCK_EVT_MODE_ONESHOT:
@@ -254,12 +113,14 @@ static void samsung_set_mode(enum clock_event_mode mode,
 static void samsung_timer_resume(void)
 {
 	/* event timer restart */
-	samsung_time_setup(timer_source.event_id, clock_count_per_tick);
-	samsung_time_start(timer_source.event_id, true);
+	samsung_pwm_setup(pwm, timer_source.event_id,
+			clock_count_per_tick - 1, clock_count_per_tick - 1);
+	samsung_pwm_start(pwm, timer_source.event_id, true);
 
 	/* source timer restart */
-	samsung_time_setup(timer_source.source_id, timer_source.tcnt_max);
-	samsung_time_start(timer_source.source_id, true);
+	samsung_pwm_setup(pwm, timer_source.source_id,
+				timer_source.tcnt_max, timer_source.tcnt_max);
+	samsung_pwm_start(pwm, timer_source.source_id, true);
 }
 
 static struct clock_event_device time_event_device = {
@@ -364,8 +225,9 @@ static void __init samsung_clocksource_init(void)
 
 	clock_rate = pclk / (timer_source.tscaler_div * timer_source.tdiv);
 
-	samsung_time_setup(timer_source.source_id, timer_source.tcnt_max);
-	samsung_time_start(timer_source.source_id, true);
+	samsung_pwm_setup(pwm, timer_source.source_id,
+				timer_source.tcnt_max, timer_source.tcnt_max);
+	samsung_pwm_start(pwm, timer_source.source_id, true);
 
 	setup_sched_clock(samsung_read_sched_clock,
 						pwm->variant.bits, clock_rate);
-- 
1.8.1.5

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

* [PATCH v4 12/14] clocksource: samsung-time: Use master driver to control PWM channels
@ 2013-04-04 16:37   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

This patch modifies the driver to use functions provided by the master
driver to control status of PWM channels instead of modifying shared
registers directly.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/clocksource/samsung-time.c | 168 ++++---------------------------------
 1 file changed, 15 insertions(+), 153 deletions(-)

diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index 7674882..9425955 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -76,153 +76,11 @@ static struct samsung_timer_source timer_source;
 static unsigned long clock_count_per_tick;
 static void samsung_timer_resume(void);
 
-static void samsung_time_stop(enum samsung_timer_mode mode)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	switch (mode) {
-	case SAMSUNG_PWM0:
-		tcon &= ~S3C2410_TCON_T0START;
-		break;
-
-	case SAMSUNG_PWM1:
-		tcon &= ~S3C2410_TCON_T1START;
-		break;
-
-	case SAMSUNG_PWM2:
-		tcon &= ~S3C2410_TCON_T2START;
-		break;
-
-	case SAMSUNG_PWM3:
-		tcon &= ~S3C2410_TCON_T3START;
-		break;
-
-	case SAMSUNG_PWM4:
-		tcon &= ~S3C2410_TCON_T4START;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void samsung_time_setup(enum samsung_timer_mode mode, unsigned long tcnt)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	tcnt--;
-
-	switch (mode) {
-	case SAMSUNG_PWM0:
-		tcon &= ~(0x0f << 0);
-		tcon |= S3C2410_TCON_T0MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM1:
-		tcon &= ~(0x0f << 8);
-		tcon |= S3C2410_TCON_T1MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM2:
-		tcon &= ~(0x0f << 12);
-		tcon |= S3C2410_TCON_T2MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM3:
-		tcon &= ~(0x0f << 16);
-		tcon |= S3C2410_TCON_T3MANUALUPD;
-		break;
-
-	case SAMSUNG_PWM4:
-		tcon &= ~(0x07 << 20);
-		tcon |= S3C2410_TCON_T4MANUALUPD;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-
-	__raw_writel(tcnt, S3C2410_TCNTB(mode));
-	__raw_writel(tcnt, S3C2410_TCMPB(mode));
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void samsung_time_start(enum samsung_timer_mode mode, bool periodic)
-{
-	unsigned long tcon;
-
-	tcon  = __raw_readl(S3C2410_TCON);
-
-	switch (mode) {
-	case SAMSUNG_PWM0:
-		tcon |= S3C2410_TCON_T0START;
-		tcon &= ~S3C2410_TCON_T0MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T0RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T0RELOAD;
-		break;
-
-	case SAMSUNG_PWM1:
-		tcon |= S3C2410_TCON_T1START;
-		tcon &= ~S3C2410_TCON_T1MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T1RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T1RELOAD;
-		break;
-
-	case SAMSUNG_PWM2:
-		tcon |= S3C2410_TCON_T2START;
-		tcon &= ~S3C2410_TCON_T2MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T2RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T2RELOAD;
-		break;
-
-	case SAMSUNG_PWM3:
-		tcon |= S3C2410_TCON_T3START;
-		tcon &= ~S3C2410_TCON_T3MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T3RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T3RELOAD;
-		break;
-
-	case SAMSUNG_PWM4:
-		tcon |= S3C2410_TCON_T4START;
-		tcon &= ~S3C2410_TCON_T4MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T4RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T4RELOAD;
-		break;
-
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", mode);
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
 static int samsung_set_next_event(unsigned long cycles,
 				struct clock_event_device *evt)
 {
-	samsung_time_setup(timer_source.event_id, cycles);
-	samsung_time_start(timer_source.event_id, false);
+	samsung_pwm_setup(pwm, timer_source.event_id, cycles - 1, cycles - 1);
+	samsung_pwm_start(pwm, timer_source.event_id, false);
 
 	return 0;
 }
@@ -230,12 +88,13 @@ static int samsung_set_next_event(unsigned long cycles,
 static void samsung_set_mode(enum clock_event_mode mode,
 				struct clock_event_device *evt)
 {
-	samsung_time_stop(timer_source.event_id);
+	samsung_pwm_stop(pwm, timer_source.event_id);
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		samsung_time_setup(timer_source.event_id, clock_count_per_tick);
-		samsung_time_start(timer_source.event_id, true);
+		samsung_pwm_setup(pwm, timer_source.event_id,
+			clock_count_per_tick - 1, clock_count_per_tick - 1);
+		samsung_pwm_start(pwm, timer_source.event_id, true);
 		break;
 
 	case CLOCK_EVT_MODE_ONESHOT:
@@ -254,12 +113,14 @@ static void samsung_set_mode(enum clock_event_mode mode,
 static void samsung_timer_resume(void)
 {
 	/* event timer restart */
-	samsung_time_setup(timer_source.event_id, clock_count_per_tick);
-	samsung_time_start(timer_source.event_id, true);
+	samsung_pwm_setup(pwm, timer_source.event_id,
+			clock_count_per_tick - 1, clock_count_per_tick - 1);
+	samsung_pwm_start(pwm, timer_source.event_id, true);
 
 	/* source timer restart */
-	samsung_time_setup(timer_source.source_id, timer_source.tcnt_max);
-	samsung_time_start(timer_source.source_id, true);
+	samsung_pwm_setup(pwm, timer_source.source_id,
+				timer_source.tcnt_max, timer_source.tcnt_max);
+	samsung_pwm_start(pwm, timer_source.source_id, true);
 }
 
 static struct clock_event_device time_event_device = {
@@ -364,8 +225,9 @@ static void __init samsung_clocksource_init(void)
 
 	clock_rate = pclk / (timer_source.tscaler_div * timer_source.tdiv);
 
-	samsung_time_setup(timer_source.source_id, timer_source.tcnt_max);
-	samsung_time_start(timer_source.source_id, true);
+	samsung_pwm_setup(pwm, timer_source.source_id,
+				timer_source.tcnt_max, timer_source.tcnt_max);
+	samsung_pwm_start(pwm, timer_source.source_id, true);
 
 	setup_sched_clock(samsung_read_sched_clock,
 						pwm->variant.bits, clock_rate);
-- 
1.8.1.5

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

* [PATCH v4 13/14] clocksource: samsung-time: Move IRQ mask/ack handling to the driver
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 16:37   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

Since the clocksource driver is the only user of PWM timer interrupts,
there is no need to create an IRQ chip for handling them.

This patch the way of PWM timer interrupt handling to use real VIC/GIC
interrupt signals and handle PWM mask/ack register internally in
samsung-time driver.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-exynos/include/mach/irqs.h  |  3 +--
 arch/arm/mach-s3c24xx/include/mach/irqs.h |  6 ++++++
 arch/arm/mach-s3c64xx/common.c            |  3 ---
 arch/arm/mach-s3c64xx/include/mach/irqs.h |  8 --------
 arch/arm/mach-s5p64x0/include/mach/irqs.h |  2 --
 arch/arm/mach-s5pc100/include/mach/irqs.h |  2 --
 arch/arm/mach-s5pv210/include/mach/irqs.h |  2 --
 arch/arm/plat-samsung/devs.c              | 20 ++++++++++----------
 arch/arm/plat-samsung/include/plat/irqs.h |  9 ---------
 arch/arm/plat-samsung/s5p-irq.c           |  2 --
 drivers/clocksource/samsung-time.c        | 10 ++++++++++
 11 files changed, 27 insertions(+), 40 deletions(-)

diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h
index 35fe6d5..6fbe229 100644
--- a/arch/arm/mach-exynos/include/mach/irqs.h
+++ b/arch/arm/mach-exynos/include/mach/irqs.h
@@ -464,10 +464,9 @@
 #define S5P_EINT_BASE2			(S5P_EINT_BASE1 + 16)
 #define S5P_GPIOINT_BASE		(S5P_EINT_BASE1 + 32)
 #define IRQ_GPIO_END			(S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
-#define IRQ_TIMER_BASE			(IRQ_GPIO_END + 64)
 
 /* Set the default NR_IRQS */
 
-#define NR_IRQS				(IRQ_TIMER_BASE + IRQ_TIMER_COUNT)
+#define NR_IRQS				(IRQ_GPIO_END + 64)
 
 #endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s3c24xx/include/mach/irqs.h b/arch/arm/mach-s3c24xx/include/mach/irqs.h
index 43cada8..1ecbadb 100644
--- a/arch/arm/mach-s3c24xx/include/mach/irqs.h
+++ b/arch/arm/mach-s3c24xx/include/mach/irqs.h
@@ -207,6 +207,12 @@
 #define IRQ_LCD_VSYNC		IRQ_S3C2443_LCD3
 #define IRQ_LCD_SYSTEM		IRQ_S3C2443_LCD2
 
+#define IRQ_TIMER0_VIC		IRQ_TIMER0
+#define IRQ_TIMER1_VIC		IRQ_TIMER1
+#define IRQ_TIMER2_VIC		IRQ_TIMER2
+#define IRQ_TIMER3_VIC		IRQ_TIMER3
+#define IRQ_TIMER4_VIC		IRQ_TIMER4
+
 #ifdef CONFIG_CPU_S3C2440
 #define IRQ_S3C244X_AC97 IRQ_S3C2440_AC97
 #else
diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c
index 526b45e..5dca83a 100644
--- a/arch/arm/mach-s3c64xx/common.c
+++ b/arch/arm/mach-s3c64xx/common.c
@@ -198,9 +198,6 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
 	/* initialise the pair of VICs */
 	vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, IRQ_VIC0_RESUME);
 	vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, IRQ_VIC1_RESUME);
-
-	/* add the timer sub-irqs */
-	s3c_init_vic_timer_irq(5, IRQ_TIMER0);
 }
 
 #define eint_offset(irq)	((irq) - IRQ_EINT(0))
diff --git a/arch/arm/mach-s3c64xx/include/mach/irqs.h b/arch/arm/mach-s3c64xx/include/mach/irqs.h
index 96d60e0..67bbd1d 100644
--- a/arch/arm/mach-s3c64xx/include/mach/irqs.h
+++ b/arch/arm/mach-s3c64xx/include/mach/irqs.h
@@ -107,14 +107,6 @@
 #define IRQ_TC			IRQ_PENDN
 #define IRQ_ADC			S3C64XX_IRQ_VIC1(31)
 
-#define S3C64XX_TIMER_IRQ(x)	S3C_IRQ(64 + (x))
-
-#define IRQ_TIMER0		S3C64XX_TIMER_IRQ(0)
-#define IRQ_TIMER1		S3C64XX_TIMER_IRQ(1)
-#define IRQ_TIMER2		S3C64XX_TIMER_IRQ(2)
-#define IRQ_TIMER3		S3C64XX_TIMER_IRQ(3)
-#define IRQ_TIMER4		S3C64XX_TIMER_IRQ(4)
-
 /* compatibility for device defines */
 
 #define IRQ_IIC1		IRQ_S3C6410_IIC1
diff --git a/arch/arm/mach-s5p64x0/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h
index 5b845e8..53982db 100644
--- a/arch/arm/mach-s5p64x0/include/mach/irqs.h
+++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h
@@ -141,8 +141,6 @@
 
 #define IRQ_EINT_GROUP(grp, x)	(IRQ_EINT_GROUP##grp##_BASE + (x))
 
-#define IRQ_TIMER_BASE		(11)
-
 /* Set the default NR_IRQS */
 
 #define NR_IRQS			(IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h
index 2870f12..d2eb475 100644
--- a/arch/arm/mach-s5pc100/include/mach/irqs.h
+++ b/arch/arm/mach-s5pc100/include/mach/irqs.h
@@ -97,8 +97,6 @@
 #define IRQ_SDMFIQ		S5P_IRQ_VIC2(31)
 #define IRQ_VIC_END		S5P_IRQ_VIC2(31)
 
-#define IRQ_TIMER_BASE		(11)
-
 #define S5P_EINT_BASE1		(S5P_IRQ_VIC0(0))
 #define S5P_EINT_BASE2		(IRQ_VIC_END + 1)
 
diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
index e777e01..5e0de3a 100644
--- a/arch/arm/mach-s5pv210/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv210/include/mach/irqs.h
@@ -118,8 +118,6 @@
 #define IRQ_MDNIE3		S5P_IRQ_VIC3(8)
 #define IRQ_VIC_END		S5P_IRQ_VIC3(31)
 
-#define IRQ_TIMER_BASE		(11)
-
 #define S5P_EINT_BASE1		(S5P_IRQ_VIC0(0))
 #define S5P_EINT_BASE2		(IRQ_VIC_END + 1)
 
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 747763d..cdeaf26 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -1161,20 +1161,20 @@ arch_initcall(s5p_pmu_init);
  */
 
 struct platform_device s3c_device_timer[] = {
-	[0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) },
-	[1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) },
-	[2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) },
-	[3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) },
-	[4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) },
+	[0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0_VIC) },
+	[1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1_VIC) },
+	[2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2_VIC) },
+	[3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3_VIC) },
+	[4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4_VIC) },
 };
 #endif /* CONFIG_SAMSUNG_DEV_PWM */
 
 static struct resource samsung_pwm_resource[] = {
-	DEFINE_RES_IRQ(IRQ_TIMER0),
-	DEFINE_RES_IRQ(IRQ_TIMER1),
-	DEFINE_RES_IRQ(IRQ_TIMER2),
-	DEFINE_RES_IRQ(IRQ_TIMER3),
-	DEFINE_RES_IRQ(IRQ_TIMER4),
+	DEFINE_RES_IRQ(IRQ_TIMER0_VIC),
+	DEFINE_RES_IRQ(IRQ_TIMER1_VIC),
+	DEFINE_RES_IRQ(IRQ_TIMER2_VIC),
+	DEFINE_RES_IRQ(IRQ_TIMER3_VIC),
+	DEFINE_RES_IRQ(IRQ_TIMER4_VIC),
 	DEFINE_RES_MEM(SAMSUNG_PA_TIMER, SZ_4K),
 };
 
diff --git a/arch/arm/plat-samsung/include/plat/irqs.h b/arch/arm/plat-samsung/include/plat/irqs.h
index df46b77..039001c 100644
--- a/arch/arm/plat-samsung/include/plat/irqs.h
+++ b/arch/arm/plat-samsung/include/plat/irqs.h
@@ -44,15 +44,6 @@
 #define S5P_IRQ_VIC2(x)		(S5P_VIC2_BASE + (x))
 #define S5P_IRQ_VIC3(x)		(S5P_VIC3_BASE + (x))
 
-#define S5P_TIMER_IRQ(x)	(IRQ_TIMER_BASE + (x))
-
-#define IRQ_TIMER0		S5P_TIMER_IRQ(0)
-#define IRQ_TIMER1		S5P_TIMER_IRQ(1)
-#define IRQ_TIMER2		S5P_TIMER_IRQ(2)
-#define IRQ_TIMER3		S5P_TIMER_IRQ(3)
-#define IRQ_TIMER4		S5P_TIMER_IRQ(4)
-#define IRQ_TIMER_COUNT		(5)
-
 #define IRQ_EINT(x)		((x) < 16 ? ((x) + S5P_EINT_BASE1) \
 					: ((x) - 16 + S5P_EINT_BASE2))
 
diff --git a/arch/arm/plat-samsung/s5p-irq.c b/arch/arm/plat-samsung/s5p-irq.c
index 103e371..ce8564d 100644
--- a/arch/arm/plat-samsung/s5p-irq.c
+++ b/arch/arm/plat-samsung/s5p-irq.c
@@ -29,6 +29,4 @@ void __init s5p_init_irq(u32 *vic, u32 num_vic)
 	for (irq = 0; irq < num_vic; irq++)
 		vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0);
 #endif
-
-	s3c_init_vic_timer_irq(5, IRQ_TIMER0);
 }
diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index 9425955..d9a3d60 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -135,6 +135,11 @@ static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id)
 {
 	struct clock_event_device *evt = dev_id;
 
+	if (pwm->variant.has_tint_cstat) {
+		u32 mask = (1 << timer_source.event_id);
+		writel(mask | (mask << 5), S3C64XX_TINT_CSTAT);
+	}
+
 	evt->event_handler(evt);
 
 	return IRQ_HANDLED;
@@ -168,6 +173,11 @@ static void __init samsung_clockevent_init(void)
 
 	irq_number = pwm->irq[timer_source.event_id];
 	setup_irq(irq_number, &samsung_clock_event_irq);
+
+	if (pwm->variant.has_tint_cstat) {
+		u32 mask = (1 << timer_source.event_id);
+		writel(mask | (mask << 5), S3C64XX_TINT_CSTAT);
+	}
 }
 
 static void __iomem *samsung_timer_reg(void)
-- 
1.8.1.5

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

* [PATCH v4 13/14] clocksource: samsung-time: Move IRQ mask/ack handling to the driver
@ 2013-04-04 16:37   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

Since the clocksource driver is the only user of PWM timer interrupts,
there is no need to create an IRQ chip for handling them.

This patch the way of PWM timer interrupt handling to use real VIC/GIC
interrupt signals and handle PWM mask/ack register internally in
samsung-time driver.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-exynos/include/mach/irqs.h  |  3 +--
 arch/arm/mach-s3c24xx/include/mach/irqs.h |  6 ++++++
 arch/arm/mach-s3c64xx/common.c            |  3 ---
 arch/arm/mach-s3c64xx/include/mach/irqs.h |  8 --------
 arch/arm/mach-s5p64x0/include/mach/irqs.h |  2 --
 arch/arm/mach-s5pc100/include/mach/irqs.h |  2 --
 arch/arm/mach-s5pv210/include/mach/irqs.h |  2 --
 arch/arm/plat-samsung/devs.c              | 20 ++++++++++----------
 arch/arm/plat-samsung/include/plat/irqs.h |  9 ---------
 arch/arm/plat-samsung/s5p-irq.c           |  2 --
 drivers/clocksource/samsung-time.c        | 10 ++++++++++
 11 files changed, 27 insertions(+), 40 deletions(-)

diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h
index 35fe6d5..6fbe229 100644
--- a/arch/arm/mach-exynos/include/mach/irqs.h
+++ b/arch/arm/mach-exynos/include/mach/irqs.h
@@ -464,10 +464,9 @@
 #define S5P_EINT_BASE2			(S5P_EINT_BASE1 + 16)
 #define S5P_GPIOINT_BASE		(S5P_EINT_BASE1 + 32)
 #define IRQ_GPIO_END			(S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
-#define IRQ_TIMER_BASE			(IRQ_GPIO_END + 64)
 
 /* Set the default NR_IRQS */
 
-#define NR_IRQS				(IRQ_TIMER_BASE + IRQ_TIMER_COUNT)
+#define NR_IRQS				(IRQ_GPIO_END + 64)
 
 #endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s3c24xx/include/mach/irqs.h b/arch/arm/mach-s3c24xx/include/mach/irqs.h
index 43cada8..1ecbadb 100644
--- a/arch/arm/mach-s3c24xx/include/mach/irqs.h
+++ b/arch/arm/mach-s3c24xx/include/mach/irqs.h
@@ -207,6 +207,12 @@
 #define IRQ_LCD_VSYNC		IRQ_S3C2443_LCD3
 #define IRQ_LCD_SYSTEM		IRQ_S3C2443_LCD2
 
+#define IRQ_TIMER0_VIC		IRQ_TIMER0
+#define IRQ_TIMER1_VIC		IRQ_TIMER1
+#define IRQ_TIMER2_VIC		IRQ_TIMER2
+#define IRQ_TIMER3_VIC		IRQ_TIMER3
+#define IRQ_TIMER4_VIC		IRQ_TIMER4
+
 #ifdef CONFIG_CPU_S3C2440
 #define IRQ_S3C244X_AC97 IRQ_S3C2440_AC97
 #else
diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c
index 526b45e..5dca83a 100644
--- a/arch/arm/mach-s3c64xx/common.c
+++ b/arch/arm/mach-s3c64xx/common.c
@@ -198,9 +198,6 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
 	/* initialise the pair of VICs */
 	vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, IRQ_VIC0_RESUME);
 	vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, IRQ_VIC1_RESUME);
-
-	/* add the timer sub-irqs */
-	s3c_init_vic_timer_irq(5, IRQ_TIMER0);
 }
 
 #define eint_offset(irq)	((irq) - IRQ_EINT(0))
diff --git a/arch/arm/mach-s3c64xx/include/mach/irqs.h b/arch/arm/mach-s3c64xx/include/mach/irqs.h
index 96d60e0..67bbd1d 100644
--- a/arch/arm/mach-s3c64xx/include/mach/irqs.h
+++ b/arch/arm/mach-s3c64xx/include/mach/irqs.h
@@ -107,14 +107,6 @@
 #define IRQ_TC			IRQ_PENDN
 #define IRQ_ADC			S3C64XX_IRQ_VIC1(31)
 
-#define S3C64XX_TIMER_IRQ(x)	S3C_IRQ(64 + (x))
-
-#define IRQ_TIMER0		S3C64XX_TIMER_IRQ(0)
-#define IRQ_TIMER1		S3C64XX_TIMER_IRQ(1)
-#define IRQ_TIMER2		S3C64XX_TIMER_IRQ(2)
-#define IRQ_TIMER3		S3C64XX_TIMER_IRQ(3)
-#define IRQ_TIMER4		S3C64XX_TIMER_IRQ(4)
-
 /* compatibility for device defines */
 
 #define IRQ_IIC1		IRQ_S3C6410_IIC1
diff --git a/arch/arm/mach-s5p64x0/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h
index 5b845e8..53982db 100644
--- a/arch/arm/mach-s5p64x0/include/mach/irqs.h
+++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h
@@ -141,8 +141,6 @@
 
 #define IRQ_EINT_GROUP(grp, x)	(IRQ_EINT_GROUP##grp##_BASE + (x))
 
-#define IRQ_TIMER_BASE		(11)
-
 /* Set the default NR_IRQS */
 
 #define NR_IRQS			(IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h
index 2870f12..d2eb475 100644
--- a/arch/arm/mach-s5pc100/include/mach/irqs.h
+++ b/arch/arm/mach-s5pc100/include/mach/irqs.h
@@ -97,8 +97,6 @@
 #define IRQ_SDMFIQ		S5P_IRQ_VIC2(31)
 #define IRQ_VIC_END		S5P_IRQ_VIC2(31)
 
-#define IRQ_TIMER_BASE		(11)
-
 #define S5P_EINT_BASE1		(S5P_IRQ_VIC0(0))
 #define S5P_EINT_BASE2		(IRQ_VIC_END + 1)
 
diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
index e777e01..5e0de3a 100644
--- a/arch/arm/mach-s5pv210/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv210/include/mach/irqs.h
@@ -118,8 +118,6 @@
 #define IRQ_MDNIE3		S5P_IRQ_VIC3(8)
 #define IRQ_VIC_END		S5P_IRQ_VIC3(31)
 
-#define IRQ_TIMER_BASE		(11)
-
 #define S5P_EINT_BASE1		(S5P_IRQ_VIC0(0))
 #define S5P_EINT_BASE2		(IRQ_VIC_END + 1)
 
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 747763d..cdeaf26 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -1161,20 +1161,20 @@ arch_initcall(s5p_pmu_init);
  */
 
 struct platform_device s3c_device_timer[] = {
-	[0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) },
-	[1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) },
-	[2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) },
-	[3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) },
-	[4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) },
+	[0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0_VIC) },
+	[1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1_VIC) },
+	[2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2_VIC) },
+	[3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3_VIC) },
+	[4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4_VIC) },
 };
 #endif /* CONFIG_SAMSUNG_DEV_PWM */
 
 static struct resource samsung_pwm_resource[] = {
-	DEFINE_RES_IRQ(IRQ_TIMER0),
-	DEFINE_RES_IRQ(IRQ_TIMER1),
-	DEFINE_RES_IRQ(IRQ_TIMER2),
-	DEFINE_RES_IRQ(IRQ_TIMER3),
-	DEFINE_RES_IRQ(IRQ_TIMER4),
+	DEFINE_RES_IRQ(IRQ_TIMER0_VIC),
+	DEFINE_RES_IRQ(IRQ_TIMER1_VIC),
+	DEFINE_RES_IRQ(IRQ_TIMER2_VIC),
+	DEFINE_RES_IRQ(IRQ_TIMER3_VIC),
+	DEFINE_RES_IRQ(IRQ_TIMER4_VIC),
 	DEFINE_RES_MEM(SAMSUNG_PA_TIMER, SZ_4K),
 };
 
diff --git a/arch/arm/plat-samsung/include/plat/irqs.h b/arch/arm/plat-samsung/include/plat/irqs.h
index df46b77..039001c 100644
--- a/arch/arm/plat-samsung/include/plat/irqs.h
+++ b/arch/arm/plat-samsung/include/plat/irqs.h
@@ -44,15 +44,6 @@
 #define S5P_IRQ_VIC2(x)		(S5P_VIC2_BASE + (x))
 #define S5P_IRQ_VIC3(x)		(S5P_VIC3_BASE + (x))
 
-#define S5P_TIMER_IRQ(x)	(IRQ_TIMER_BASE + (x))
-
-#define IRQ_TIMER0		S5P_TIMER_IRQ(0)
-#define IRQ_TIMER1		S5P_TIMER_IRQ(1)
-#define IRQ_TIMER2		S5P_TIMER_IRQ(2)
-#define IRQ_TIMER3		S5P_TIMER_IRQ(3)
-#define IRQ_TIMER4		S5P_TIMER_IRQ(4)
-#define IRQ_TIMER_COUNT		(5)
-
 #define IRQ_EINT(x)		((x) < 16 ? ((x) + S5P_EINT_BASE1) \
 					: ((x) - 16 + S5P_EINT_BASE2))
 
diff --git a/arch/arm/plat-samsung/s5p-irq.c b/arch/arm/plat-samsung/s5p-irq.c
index 103e371..ce8564d 100644
--- a/arch/arm/plat-samsung/s5p-irq.c
+++ b/arch/arm/plat-samsung/s5p-irq.c
@@ -29,6 +29,4 @@ void __init s5p_init_irq(u32 *vic, u32 num_vic)
 	for (irq = 0; irq < num_vic; irq++)
 		vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0);
 #endif
-
-	s3c_init_vic_timer_irq(5, IRQ_TIMER0);
 }
diff --git a/drivers/clocksource/samsung-time.c b/drivers/clocksource/samsung-time.c
index 9425955..d9a3d60 100644
--- a/drivers/clocksource/samsung-time.c
+++ b/drivers/clocksource/samsung-time.c
@@ -135,6 +135,11 @@ static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id)
 {
 	struct clock_event_device *evt = dev_id;
 
+	if (pwm->variant.has_tint_cstat) {
+		u32 mask = (1 << timer_source.event_id);
+		writel(mask | (mask << 5), S3C64XX_TINT_CSTAT);
+	}
+
 	evt->event_handler(evt);
 
 	return IRQ_HANDLED;
@@ -168,6 +173,11 @@ static void __init samsung_clockevent_init(void)
 
 	irq_number = pwm->irq[timer_source.event_id];
 	setup_irq(irq_number, &samsung_clock_event_irq);
+
+	if (pwm->variant.has_tint_cstat) {
+		u32 mask = (1 << timer_source.event_id);
+		writel(mask | (mask << 5), S3C64XX_TINT_CSTAT);
+	}
 }
 
 static void __iomem *samsung_timer_reg(void)
-- 
1.8.1.5

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

* [PATCH v4 14/14] ARM: SAMSUNG: Remove unused PWM timer IRQ chip code
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 16:37   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree-discuss, linux-samsung-soc, sameo, kgene.kim,
	kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa, heiko,
	robherring2, m.szyprowski, arnd, john.stultz, tglx, Tomasz Figa

As the need for an IRQ chip handling PWM timer interrupt chaining is
gone now, this patch removes all the code made unnecessary.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/Kconfig                                   |  1 -
 arch/arm/mach-s3c64xx/common.c                     |  1 -
 arch/arm/plat-samsung/Kconfig                      |  6 --
 arch/arm/plat-samsung/Makefile                     |  1 -
 arch/arm/plat-samsung/include/plat/irq-vic-timer.h | 13 ---
 arch/arm/plat-samsung/irq-vic-timer.c              | 98 ----------------------
 arch/arm/plat-samsung/s5p-irq.c                    |  1 -
 7 files changed, 121 deletions(-)
 delete mode 100644 arch/arm/plat-samsung/include/plat/irq-vic-timer.h
 delete mode 100644 arch/arm/plat-samsung/irq-vic-timer.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index dd68dec..ed584d4 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -806,7 +806,6 @@ config ARCH_S3C64XX
 	select S3C_GPIO_TRACK
 	select SAMSUNG_CLKSRC
 	select SAMSUNG_GPIOLIB_4BIT
-	select SAMSUNG_IRQ_VIC_TIMER
 	select USB_ARCH_HAS_OHCI
 	help
 	  Samsung S3C64XX series based systems
diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c
index 5dca83a..e2134b0 100644
--- a/arch/arm/mach-s3c64xx/common.c
+++ b/arch/arm/mach-s3c64xx/common.c
@@ -42,7 +42,6 @@
 #include <plat/pm.h>
 #include <plat/gpio-cfg.h>
 #include <plat/irq-uart.h>
-#include <plat/irq-vic-timer.h>
 #include <plat/regs-irqtype.h>
 #include <plat/regs-serial.h>
 #include <plat/watchdog-reset.h>
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 6f632ba..9951879 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -27,7 +27,6 @@ config PLAT_S5P
 	select S5P_GPIO_DRVSTR
 	select SAMSUNG_CLKSRC if !COMMON_CLK
 	select SAMSUNG_GPIOLIB_4BIT
-	select SAMSUNG_IRQ_VIC_TIMER
 	help
 	  Base platform code for Samsung's S5P series SoC.
 
@@ -79,11 +78,6 @@ config S5P_CLOCK
 
 # options for IRQ support
 
-config SAMSUNG_IRQ_VIC_TIMER
-       bool
-       help
-         Internal configuration to build the VIC timer interrupt code.
-
 config S5P_IRQ
 	def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
 	help
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 87494e1..ae2a0fd 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -19,7 +19,6 @@ obj-$(CONFIG_SAMSUNG_CLOCK)	+= pwm-clock.o
 obj-$(CONFIG_SAMSUNG_CLKSRC)	+= clock-clksrc.o
 obj-$(CONFIG_S5P_CLOCK)		+= s5p-clock.o
 
-obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o
 obj-$(CONFIG_S5P_IRQ)		+= s5p-irq.o
 obj-$(CONFIG_S5P_EXT_INT)	+= s5p-irq-eint.o
 obj-$(CONFIG_S5P_GPIO_INT)	+= s5p-irq-gpioint.o
diff --git a/arch/arm/plat-samsung/include/plat/irq-vic-timer.h b/arch/arm/plat-samsung/include/plat/irq-vic-timer.h
deleted file mode 100644
index 5b9c42f..0000000
--- a/arch/arm/plat-samsung/include/plat/irq-vic-timer.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/irq-vic-timer.h
- *
- * Copyright (c) 2010 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for Samsung SoC IRQ VIC timer
- *
- * 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.
-*/
-
-extern void s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq);
diff --git a/arch/arm/plat-samsung/irq-vic-timer.c b/arch/arm/plat-samsung/irq-vic-timer.c
deleted file mode 100644
index f980cf3..0000000
--- a/arch/arm/plat-samsung/irq-vic-timer.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/* arch/arm/plat-samsung/irq-vic-timer.c
- *	originally part of arch/arm/plat-s3c64xx/irq.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64XX - Interrupt handling
- *
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <mach/map.h>
-#include <plat/cpu.h>
-#include <plat/irq-vic-timer.h>
-#include <plat/regs-timer.h>
-
-#include <asm/mach/irq.h>
-
-static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc)
-{
-	struct irq_chip *chip = irq_get_chip(irq);
-	chained_irq_enter(chip, desc);
-	generic_handle_irq((int)desc->irq_data.handler_data);
-	chained_irq_exit(chip, desc);
-}
-
-/* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */
-static void s3c_irq_timer_ack(struct irq_data *d)
-{
-	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-	u32 mask = (1 << 5) << (d->irq - gc->irq_base);
-
-	irq_reg_writel(mask | gc->mask_cache, gc->reg_base);
-}
-
-/**
- * s3c_init_vic_timer_irq() - initialise timer irq chanined off VIC.\
- * @num: Number of timers to initialize
- * @timer_irq: Base IRQ number to be used for the timers.
- *
- * Register the necessary IRQ chaining and support for the timer IRQs
- * chained of the VIC.
- */
-void __init s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq)
-{
-	unsigned int pirq[5] = { IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC,
-				 IRQ_TIMER3_VIC, IRQ_TIMER4_VIC };
-	struct irq_chip_generic *s3c_tgc;
-	struct irq_chip_type *ct;
-	unsigned int i;
-
-#ifdef CONFIG_ARCH_EXYNOS
-	if (soc_is_exynos5250()) {
-		pirq[0] = EXYNOS5_IRQ_TIMER0_VIC;
-		pirq[1] = EXYNOS5_IRQ_TIMER1_VIC;
-		pirq[2] = EXYNOS5_IRQ_TIMER2_VIC;
-		pirq[3] = EXYNOS5_IRQ_TIMER3_VIC;
-		pirq[4] = EXYNOS5_IRQ_TIMER4_VIC;
-	} else {
-		pirq[0] = EXYNOS4_IRQ_TIMER0_VIC;
-		pirq[1] = EXYNOS4_IRQ_TIMER1_VIC;
-		pirq[2] = EXYNOS4_IRQ_TIMER2_VIC;
-		pirq[3] = EXYNOS4_IRQ_TIMER3_VIC;
-		pirq[4] = EXYNOS4_IRQ_TIMER4_VIC;
-	}
-#endif
-	s3c_tgc = irq_alloc_generic_chip("s3c-timer", 1, timer_irq,
-					 S3C64XX_TINT_CSTAT, handle_level_irq);
-
-	if (!s3c_tgc) {
-		pr_err("%s: irq_alloc_generic_chip for IRQ %d failed\n",
-		       __func__, timer_irq);
-		return;
-	}
-
-	ct = s3c_tgc->chip_types;
-	ct->chip.irq_mask = irq_gc_mask_clr_bit;
-	ct->chip.irq_unmask = irq_gc_mask_set_bit;
-	ct->chip.irq_ack = s3c_irq_timer_ack;
-	irq_setup_generic_chip(s3c_tgc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
-			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
-	/* Clear the upper bits of the mask_cache*/
-	s3c_tgc->mask_cache &= 0x1f;
-
-	for (i = 0; i < num; i++, timer_irq++) {
-		irq_set_chained_handler(pirq[i], s3c_irq_demux_vic_timer);
-		irq_set_handler_data(pirq[i], (void *)timer_irq);
-	}
-}
diff --git a/arch/arm/plat-samsung/s5p-irq.c b/arch/arm/plat-samsung/s5p-irq.c
index ce8564d..b1e2a82 100644
--- a/arch/arm/plat-samsung/s5p-irq.c
+++ b/arch/arm/plat-samsung/s5p-irq.c
@@ -18,7 +18,6 @@
 #include <mach/map.h>
 #include <plat/regs-timer.h>
 #include <plat/cpu.h>
-#include <plat/irq-vic-timer.h>
 
 void __init s5p_init_irq(u32 *vic, u32 num_vic)
 {
-- 
1.8.1.5

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

* [PATCH v4 14/14] ARM: SAMSUNG: Remove unused PWM timer IRQ chip code
@ 2013-04-04 16:37   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-04 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

As the need for an IRQ chip handling PWM timer interrupt chaining is
gone now, this patch removes all the code made unnecessary.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/Kconfig                                   |  1 -
 arch/arm/mach-s3c64xx/common.c                     |  1 -
 arch/arm/plat-samsung/Kconfig                      |  6 --
 arch/arm/plat-samsung/Makefile                     |  1 -
 arch/arm/plat-samsung/include/plat/irq-vic-timer.h | 13 ---
 arch/arm/plat-samsung/irq-vic-timer.c              | 98 ----------------------
 arch/arm/plat-samsung/s5p-irq.c                    |  1 -
 7 files changed, 121 deletions(-)
 delete mode 100644 arch/arm/plat-samsung/include/plat/irq-vic-timer.h
 delete mode 100644 arch/arm/plat-samsung/irq-vic-timer.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index dd68dec..ed584d4 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -806,7 +806,6 @@ config ARCH_S3C64XX
 	select S3C_GPIO_TRACK
 	select SAMSUNG_CLKSRC
 	select SAMSUNG_GPIOLIB_4BIT
-	select SAMSUNG_IRQ_VIC_TIMER
 	select USB_ARCH_HAS_OHCI
 	help
 	  Samsung S3C64XX series based systems
diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c
index 5dca83a..e2134b0 100644
--- a/arch/arm/mach-s3c64xx/common.c
+++ b/arch/arm/mach-s3c64xx/common.c
@@ -42,7 +42,6 @@
 #include <plat/pm.h>
 #include <plat/gpio-cfg.h>
 #include <plat/irq-uart.h>
-#include <plat/irq-vic-timer.h>
 #include <plat/regs-irqtype.h>
 #include <plat/regs-serial.h>
 #include <plat/watchdog-reset.h>
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 6f632ba..9951879 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -27,7 +27,6 @@ config PLAT_S5P
 	select S5P_GPIO_DRVSTR
 	select SAMSUNG_CLKSRC if !COMMON_CLK
 	select SAMSUNG_GPIOLIB_4BIT
-	select SAMSUNG_IRQ_VIC_TIMER
 	help
 	  Base platform code for Samsung's S5P series SoC.
 
@@ -79,11 +78,6 @@ config S5P_CLOCK
 
 # options for IRQ support
 
-config SAMSUNG_IRQ_VIC_TIMER
-       bool
-       help
-         Internal configuration to build the VIC timer interrupt code.
-
 config S5P_IRQ
 	def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
 	help
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 87494e1..ae2a0fd 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -19,7 +19,6 @@ obj-$(CONFIG_SAMSUNG_CLOCK)	+= pwm-clock.o
 obj-$(CONFIG_SAMSUNG_CLKSRC)	+= clock-clksrc.o
 obj-$(CONFIG_S5P_CLOCK)		+= s5p-clock.o
 
-obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o
 obj-$(CONFIG_S5P_IRQ)		+= s5p-irq.o
 obj-$(CONFIG_S5P_EXT_INT)	+= s5p-irq-eint.o
 obj-$(CONFIG_S5P_GPIO_INT)	+= s5p-irq-gpioint.o
diff --git a/arch/arm/plat-samsung/include/plat/irq-vic-timer.h b/arch/arm/plat-samsung/include/plat/irq-vic-timer.h
deleted file mode 100644
index 5b9c42f..0000000
--- a/arch/arm/plat-samsung/include/plat/irq-vic-timer.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/irq-vic-timer.h
- *
- * Copyright (c) 2010 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for Samsung SoC IRQ VIC timer
- *
- * 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.
-*/
-
-extern void s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq);
diff --git a/arch/arm/plat-samsung/irq-vic-timer.c b/arch/arm/plat-samsung/irq-vic-timer.c
deleted file mode 100644
index f980cf3..0000000
--- a/arch/arm/plat-samsung/irq-vic-timer.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/* arch/arm/plat-samsung/irq-vic-timer.c
- *	originally part of arch/arm/plat-s3c64xx/irq.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64XX - Interrupt handling
- *
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <mach/map.h>
-#include <plat/cpu.h>
-#include <plat/irq-vic-timer.h>
-#include <plat/regs-timer.h>
-
-#include <asm/mach/irq.h>
-
-static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc)
-{
-	struct irq_chip *chip = irq_get_chip(irq);
-	chained_irq_enter(chip, desc);
-	generic_handle_irq((int)desc->irq_data.handler_data);
-	chained_irq_exit(chip, desc);
-}
-
-/* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */
-static void s3c_irq_timer_ack(struct irq_data *d)
-{
-	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-	u32 mask = (1 << 5) << (d->irq - gc->irq_base);
-
-	irq_reg_writel(mask | gc->mask_cache, gc->reg_base);
-}
-
-/**
- * s3c_init_vic_timer_irq() - initialise timer irq chanined off VIC.\
- * @num: Number of timers to initialize
- * @timer_irq: Base IRQ number to be used for the timers.
- *
- * Register the necessary IRQ chaining and support for the timer IRQs
- * chained of the VIC.
- */
-void __init s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq)
-{
-	unsigned int pirq[5] = { IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC,
-				 IRQ_TIMER3_VIC, IRQ_TIMER4_VIC };
-	struct irq_chip_generic *s3c_tgc;
-	struct irq_chip_type *ct;
-	unsigned int i;
-
-#ifdef CONFIG_ARCH_EXYNOS
-	if (soc_is_exynos5250()) {
-		pirq[0] = EXYNOS5_IRQ_TIMER0_VIC;
-		pirq[1] = EXYNOS5_IRQ_TIMER1_VIC;
-		pirq[2] = EXYNOS5_IRQ_TIMER2_VIC;
-		pirq[3] = EXYNOS5_IRQ_TIMER3_VIC;
-		pirq[4] = EXYNOS5_IRQ_TIMER4_VIC;
-	} else {
-		pirq[0] = EXYNOS4_IRQ_TIMER0_VIC;
-		pirq[1] = EXYNOS4_IRQ_TIMER1_VIC;
-		pirq[2] = EXYNOS4_IRQ_TIMER2_VIC;
-		pirq[3] = EXYNOS4_IRQ_TIMER3_VIC;
-		pirq[4] = EXYNOS4_IRQ_TIMER4_VIC;
-	}
-#endif
-	s3c_tgc = irq_alloc_generic_chip("s3c-timer", 1, timer_irq,
-					 S3C64XX_TINT_CSTAT, handle_level_irq);
-
-	if (!s3c_tgc) {
-		pr_err("%s: irq_alloc_generic_chip for IRQ %d failed\n",
-		       __func__, timer_irq);
-		return;
-	}
-
-	ct = s3c_tgc->chip_types;
-	ct->chip.irq_mask = irq_gc_mask_clr_bit;
-	ct->chip.irq_unmask = irq_gc_mask_set_bit;
-	ct->chip.irq_ack = s3c_irq_timer_ack;
-	irq_setup_generic_chip(s3c_tgc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
-			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
-	/* Clear the upper bits of the mask_cache*/
-	s3c_tgc->mask_cache &= 0x1f;
-
-	for (i = 0; i < num; i++, timer_irq++) {
-		irq_set_chained_handler(pirq[i], s3c_irq_demux_vic_timer);
-		irq_set_handler_data(pirq[i], (void *)timer_irq);
-	}
-}
diff --git a/arch/arm/plat-samsung/s5p-irq.c b/arch/arm/plat-samsung/s5p-irq.c
index ce8564d..b1e2a82 100644
--- a/arch/arm/plat-samsung/s5p-irq.c
+++ b/arch/arm/plat-samsung/s5p-irq.c
@@ -18,7 +18,6 @@
 #include <mach/map.h>
 #include <plat/regs-timer.h>
 #include <plat/cpu.h>
-#include <plat/irq-vic-timer.h>
 
 void __init s5p_init_irq(u32 *vic, u32 num_vic)
 {
-- 
1.8.1.5

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

* Re: [PATCH v4 00/14] ARM: samsung-time: Prepare for multiplatform support
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-04 23:15   ` Heiko Stübner
  -1 siblings, 0 replies; 58+ messages in thread
From: Heiko Stübner @ 2013-04-04 23:15 UTC (permalink / raw)
  To: Tomasz Figa
  Cc: linux-arm-kernel, devicetree-discuss, linux-samsung-soc, sameo,
	kgene.kim, kyungmin.park, linux, broonie, kwangwoo.lee, jacmet,
	augulis.darius, mcuelenaere, linux, sylvester.nawrocki, buserror,
	christer, jekhor, ghcstop, mark.rutland, tomasz.figa,
	robherring2, m.szyprowski, arnd, john.stultz, tglx

Am Donnerstag, 4. April 2013, 18:36:57 schrieb Tomasz Figa:
> This series is an attempt to make the samsung-time clocksource driver ready
> for multiplatform kernels. It moves the driver to drivers/clocksource,
> cleans it up from uses of static platform-specific definitions, simplifies
> timer interrupt handling and adds Device Tree support.
> 
> Only samsung-time driver is reworked to use the master driver at this time,
> since the PWM driver can be already considered broken at the moment and
> needs separate series of several patches to fix and clean it up, which
> I am already working on.
> 
> Tested on Universal C210 board with Device Tree. Not tested without
> Device Tree, since it has been already broken before this series.
> Compile tested for other related SoCs.

Looks nice.

On a non-DT S3C2416 board:
Tested-by: Heiko Stuebner <heiko@sntech.de>


And just so I don't search myself silly, am I right in thinking that the 
driver does not use the generic clocksource registration yet and dt machines 
must still use samsung_timer_init at this point?


Heiko

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

* [PATCH v4 00/14] ARM: samsung-time: Prepare for multiplatform support
@ 2013-04-04 23:15   ` Heiko Stübner
  0 siblings, 0 replies; 58+ messages in thread
From: Heiko Stübner @ 2013-04-04 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

Am Donnerstag, 4. April 2013, 18:36:57 schrieb Tomasz Figa:
> This series is an attempt to make the samsung-time clocksource driver ready
> for multiplatform kernels. It moves the driver to drivers/clocksource,
> cleans it up from uses of static platform-specific definitions, simplifies
> timer interrupt handling and adds Device Tree support.
> 
> Only samsung-time driver is reworked to use the master driver at this time,
> since the PWM driver can be already considered broken at the moment and
> needs separate series of several patches to fix and clean it up, which
> I am already working on.
> 
> Tested on Universal C210 board with Device Tree. Not tested without
> Device Tree, since it has been already broken before this series.
> Compile tested for other related SoCs.

Looks nice.

On a non-DT S3C2416 board:
Tested-by: Heiko Stuebner <heiko@sntech.de>


And just so I don't search myself silly, am I right in thinking that the 
driver does not use the generic clocksource registration yet and dt machines 
must still use samsung_timer_init at this point?


Heiko

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

* Re: [PATCH v4 00/14] ARM: samsung-time: Prepare for multiplatform support
  2013-04-04 23:15   ` Heiko Stübner
@ 2013-04-05 10:33     ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-05 10:33 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: mark.rutland, tomasz.figa, buserror, jacmet, augulis.darius,
	christer, sylvester.nawrocki, m.szyprowski, kgene.kim, linux,
	sameo, kwangwoo.lee, mcuelenaere, arnd, devicetree-discuss,
	linux-samsung-soc, john.stultz, ghcstop, linux, linux-arm-kernel,
	broonie, jekhor, kyungmin.park, tglx

Hi Heiko,

On Friday 05 of April 2013 01:15:02 Heiko Stübner wrote:
> Am Donnerstag, 4. April 2013, 18:36:57 schrieb Tomasz Figa:
> > This series is an attempt to make the samsung-time clocksource driver
> > ready
> > for multiplatform kernels. It moves the driver to drivers/clocksource,
> > cleans it up from uses of static platform-specific definitions, simplifies
> > timer interrupt handling and adds Device Tree support.
> > 
> > Only samsung-time driver is reworked to use the master driver at this
> > time,
> > since the PWM driver can be already considered broken at the moment and
> > needs separate series of several patches to fix and clean it up, which
> > I am already working on.
> > 
> > Tested on Universal C210 board with Device Tree. Not tested without
> > Device Tree, since it has been already broken before this series.
> > Compile tested for other related SoCs.
> 
> Looks nice.
> 
> On a non-DT S3C2416 board:
> Tested-by: Heiko Stuebner <heiko@sntech.de>

Thanks for testing.

> And just so I don't search myself silly, am I right in thinking that the
> driver does not use the generic clocksource registration yet and dt machines
> must still use samsung_timer_init at this point?

Yes. Because of the build failures it caused recently I have decided not to 
use it yet. It can be added with a small patch later, though.

Best regards,
-- 
Tomasz Figa
Samsung Poland R&D Center
SW Solution Development, Kernel and System Framework

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

* [PATCH v4 00/14] ARM: samsung-time: Prepare for multiplatform support
@ 2013-04-05 10:33     ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-05 10:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Heiko,

On Friday 05 of April 2013 01:15:02 Heiko St?bner wrote:
> Am Donnerstag, 4. April 2013, 18:36:57 schrieb Tomasz Figa:
> > This series is an attempt to make the samsung-time clocksource driver
> > ready
> > for multiplatform kernels. It moves the driver to drivers/clocksource,
> > cleans it up from uses of static platform-specific definitions, simplifies
> > timer interrupt handling and adds Device Tree support.
> > 
> > Only samsung-time driver is reworked to use the master driver at this
> > time,
> > since the PWM driver can be already considered broken at the moment and
> > needs separate series of several patches to fix and clean it up, which
> > I am already working on.
> > 
> > Tested on Universal C210 board with Device Tree. Not tested without
> > Device Tree, since it has been already broken before this series.
> > Compile tested for other related SoCs.
> 
> Looks nice.
> 
> On a non-DT S3C2416 board:
> Tested-by: Heiko Stuebner <heiko@sntech.de>

Thanks for testing.

> And just so I don't search myself silly, am I right in thinking that the
> driver does not use the generic clocksource registration yet and dt machines
> must still use samsung_timer_init at this point?

Yes. Because of the build failures it caused recently I have decided not to 
use it yet. It can be added with a small patch later, though.

Best regards,
-- 
Tomasz Figa
Samsung Poland R&D Center
SW Solution Development, Kernel and System Framework

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

* Re: [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
  2013-04-04 16:37   ` Tomasz Figa
@ 2013-04-05 16:39     ` Samuel Ortiz
  -1 siblings, 0 replies; 58+ messages in thread
From: Samuel Ortiz @ 2013-04-05 16:39 UTC (permalink / raw)
  To: Tomasz Figa
  Cc: mark.rutland, heiko, tomasz.figa, buserror, jacmet,
	augulis.darius, christer, sylvester.nawrocki, m.szyprowski,
	kgene.kim, linux, kwangwoo.lee, mcuelenaere, arnd,
	devicetree-discuss, linux-samsung-soc, john.stultz, ghcstop,
	linux, linux-arm-kernel, broonie, jekhor, kyungmin.park, tglx

Hi Tomasz,

On Thu, Apr 04, 2013 at 06:37:01PM +0200, Tomasz Figa wrote:
> This patch adds master driver for PWM/timer block available on many
> Samsung SoCs providing clocksource and PWM output capabilities.
> 
> Signed-off-by: Tomasz Figa <t.figa@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  .../devicetree/bindings/pwm/pwm-samsung.txt        |  37 ++
>  drivers/clocksource/Kconfig                        |   1 +
>  drivers/mfd/Kconfig                                |   3 +
>  drivers/mfd/Makefile                               |   1 +
>  drivers/mfd/samsung-pwm.c                          | 439 +++++++++++++++++++++
>  drivers/pwm/Kconfig                                |   1 +
>  include/linux/mfd/samsung-pwm.h                    |  49 +++
>  include/linux/platform_data/samsung-pwm.h          |  28 ++
>  8 files changed, 559 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pwm/pwm-samsung.txt
>  create mode 100644 drivers/mfd/samsung-pwm.c
>  create mode 100644 include/linux/mfd/samsung-pwm.h
>  create mode 100644 include/linux/platform_data/samsung-pwm.h
Why is that an MFD driver, and why aren't you using the PWM APIs for it ?
Also, you probably want to look at using the regmap APIs for your IO.

Cheers,
Samuel.

-- 
Intel Open Source Technology Centre
http://oss.intel.com/

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

* [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
@ 2013-04-05 16:39     ` Samuel Ortiz
  0 siblings, 0 replies; 58+ messages in thread
From: Samuel Ortiz @ 2013-04-05 16:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tomasz,

On Thu, Apr 04, 2013 at 06:37:01PM +0200, Tomasz Figa wrote:
> This patch adds master driver for PWM/timer block available on many
> Samsung SoCs providing clocksource and PWM output capabilities.
> 
> Signed-off-by: Tomasz Figa <t.figa@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  .../devicetree/bindings/pwm/pwm-samsung.txt        |  37 ++
>  drivers/clocksource/Kconfig                        |   1 +
>  drivers/mfd/Kconfig                                |   3 +
>  drivers/mfd/Makefile                               |   1 +
>  drivers/mfd/samsung-pwm.c                          | 439 +++++++++++++++++++++
>  drivers/pwm/Kconfig                                |   1 +
>  include/linux/mfd/samsung-pwm.h                    |  49 +++
>  include/linux/platform_data/samsung-pwm.h          |  28 ++
>  8 files changed, 559 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pwm/pwm-samsung.txt
>  create mode 100644 drivers/mfd/samsung-pwm.c
>  create mode 100644 include/linux/mfd/samsung-pwm.h
>  create mode 100644 include/linux/platform_data/samsung-pwm.h
Why is that an MFD driver, and why aren't you using the PWM APIs for it ?
Also, you probably want to look at using the regmap APIs for your IO.

Cheers,
Samuel.

-- 
Intel Open Source Technology Centre
http://oss.intel.com/

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

* Re: [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
  2013-04-05 16:39     ` Samuel Ortiz
@ 2013-04-05 16:53       ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-05 16:53 UTC (permalink / raw)
  To: Samuel Ortiz
  Cc: mark.rutland, heiko, tomasz.figa, buserror, jacmet,
	augulis.darius, christer, sylvester.nawrocki, m.szyprowski,
	kgene.kim, linux, kwangwoo.lee, mcuelenaere, arnd,
	devicetree-discuss, linux-samsung-soc, john.stultz, ghcstop,
	linux, linux-arm-kernel, broonie, jekhor, kyungmin.park, tglx

Hi Samuel,

On Friday 05 of April 2013 18:39:58 Samuel Ortiz wrote:
> Hi Tomasz,
> 
> On Thu, Apr 04, 2013 at 06:37:01PM +0200, Tomasz Figa wrote:
> > This patch adds master driver for PWM/timer block available on many
> > Samsung SoCs providing clocksource and PWM output capabilities.
> > 
> > Signed-off-by: Tomasz Figa <t.figa@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > ---
> > 
> >  .../devicetree/bindings/pwm/pwm-samsung.txt        |  37 ++
> >  drivers/clocksource/Kconfig                        |   1 +
> >  drivers/mfd/Kconfig                                |   3 +
> >  drivers/mfd/Makefile                               |   1 +
> >  drivers/mfd/samsung-pwm.c                          | 439
> >  +++++++++++++++++++++ drivers/pwm/Kconfig                               
> >  |   1 +
> >  include/linux/mfd/samsung-pwm.h                    |  49 +++
> >  include/linux/platform_data/samsung-pwm.h          |  28 ++
> >  8 files changed, 559 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/pwm/pwm-samsung.txt
> >  create mode 100644 drivers/mfd/samsung-pwm.c
> >  create mode 100644 include/linux/mfd/samsung-pwm.h
> >  create mode 100644 include/linux/platform_data/samsung-pwm.h
> 
> Why is that an MFD driver, and why aren't you using the PWM APIs for it ?
> Also, you probably want to look at using the regmap APIs for your IO.

The case of Samsung PWM timers is rather complicated. It is a hardware block 
that can be used at the same time to generate PWM signal and as a system 
clocksource.

There was a discussion on how to solve the problem of sharing the hardware:
http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16480/focus=16500
(see the linked post and replies to it).

Best regards,
-- 
Tomasz Figa
Samsung Poland R&D Center
SW Solution Development, Kernel and System Framework

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

* [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
@ 2013-04-05 16:53       ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-05 16:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Samuel,

On Friday 05 of April 2013 18:39:58 Samuel Ortiz wrote:
> Hi Tomasz,
> 
> On Thu, Apr 04, 2013 at 06:37:01PM +0200, Tomasz Figa wrote:
> > This patch adds master driver for PWM/timer block available on many
> > Samsung SoCs providing clocksource and PWM output capabilities.
> > 
> > Signed-off-by: Tomasz Figa <t.figa@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > ---
> > 
> >  .../devicetree/bindings/pwm/pwm-samsung.txt        |  37 ++
> >  drivers/clocksource/Kconfig                        |   1 +
> >  drivers/mfd/Kconfig                                |   3 +
> >  drivers/mfd/Makefile                               |   1 +
> >  drivers/mfd/samsung-pwm.c                          | 439
> >  +++++++++++++++++++++ drivers/pwm/Kconfig                               
> >  |   1 +
> >  include/linux/mfd/samsung-pwm.h                    |  49 +++
> >  include/linux/platform_data/samsung-pwm.h          |  28 ++
> >  8 files changed, 559 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/pwm/pwm-samsung.txt
> >  create mode 100644 drivers/mfd/samsung-pwm.c
> >  create mode 100644 include/linux/mfd/samsung-pwm.h
> >  create mode 100644 include/linux/platform_data/samsung-pwm.h
> 
> Why is that an MFD driver, and why aren't you using the PWM APIs for it ?
> Also, you probably want to look at using the regmap APIs for your IO.

The case of Samsung PWM timers is rather complicated. It is a hardware block 
that can be used at the same time to generate PWM signal and as a system 
clocksource.

There was a discussion on how to solve the problem of sharing the hardware:
http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16480/focus=16500
(see the linked post and replies to it).

Best regards,
-- 
Tomasz Figa
Samsung Poland R&D Center
SW Solution Development, Kernel and System Framework

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

* Re: [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
  2013-04-05 16:53       ` Tomasz Figa
@ 2013-04-05 17:05         ` Arnd Bergmann
  -1 siblings, 0 replies; 58+ messages in thread
From: Arnd Bergmann @ 2013-04-05 17:05 UTC (permalink / raw)
  To: Tomasz Figa
  Cc: mark.rutland, heiko, tomasz.figa, buserror, jacmet,
	augulis.darius, christer, sylvester.nawrocki, m.szyprowski,
	kgene.kim, linux, Samuel Ortiz, kwangwoo.lee, mcuelenaere,
	devicetree-discuss, linux-samsung-soc, john.stultz, ghcstop,
	linux, linux-arm-kernel, broonie, jekhor, kyungmin.park, tglx

On Friday 05 April 2013, Tomasz Figa wrote:
> On Friday 05 of April 2013 18:39:58 Samuel Ortiz wrote:
> > Hi Tomasz,
> > 
> > On Thu, Apr 04, 2013 at 06:37:01PM +0200, Tomasz Figa wrote:
> > > This patch adds master driver for PWM/timer block available on many
> > > Samsung SoCs providing clocksource and PWM output capabilities.
>
> > Why is that an MFD driver, and why aren't you using the PWM APIs for it ?
> > Also, you probably want to look at using the regmap APIs for your IO.
> 
> The case of Samsung PWM timers is rather complicated. It is a hardware block 
> that can be used at the same time to generate PWM signal and as a system 
> clocksource.
> 
> There was a discussion on how to solve the problem of sharing the hardware:
> http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16480/focus=16500
> (see the linked post and replies to it).
> 

I don't think anyone ever suggested using a private API though. I think
it's ok if the driver lives in drivers/mfd when it doesn't fit anywhere
else easily, but you should really register it to the pwm subsystem to
expose that functionality, not export functions that can be used by
a pwm shim driver, which even seems to be missing from the series.

	Arnd

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

* [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
@ 2013-04-05 17:05         ` Arnd Bergmann
  0 siblings, 0 replies; 58+ messages in thread
From: Arnd Bergmann @ 2013-04-05 17:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 05 April 2013, Tomasz Figa wrote:
> On Friday 05 of April 2013 18:39:58 Samuel Ortiz wrote:
> > Hi Tomasz,
> > 
> > On Thu, Apr 04, 2013 at 06:37:01PM +0200, Tomasz Figa wrote:
> > > This patch adds master driver for PWM/timer block available on many
> > > Samsung SoCs providing clocksource and PWM output capabilities.
>
> > Why is that an MFD driver, and why aren't you using the PWM APIs for it ?
> > Also, you probably want to look at using the regmap APIs for your IO.
> 
> The case of Samsung PWM timers is rather complicated. It is a hardware block 
> that can be used at the same time to generate PWM signal and as a system 
> clocksource.
> 
> There was a discussion on how to solve the problem of sharing the hardware:
> http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16480/focus=16500
> (see the linked post and replies to it).
> 

I don't think anyone ever suggested using a private API though. I think
it's ok if the driver lives in drivers/mfd when it doesn't fit anywhere
else easily, but you should really register it to the pwm subsystem to
expose that functionality, not export functions that can be used by
a pwm shim driver, which even seems to be missing from the series.

	Arnd

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

* Re: [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
  2013-04-05 17:05         ` Arnd Bergmann
@ 2013-04-05 17:35           ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-05 17:35 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: mark.rutland, heiko, tomasz.figa, buserror, jacmet,
	augulis.darius, christer, sylvester.nawrocki, m.szyprowski,
	kgene.kim, linux, Samuel Ortiz, kwangwoo.lee, mcuelenaere,
	devicetree-discuss, linux-samsung-soc, john.stultz, ghcstop,
	linux, linux-arm-kernel, broonie, jekhor, kyungmin.park, tglx

On Friday 05 of April 2013 19:05:24 Arnd Bergmann wrote:
> On Friday 05 April 2013, Tomasz Figa wrote:
> > On Friday 05 of April 2013 18:39:58 Samuel Ortiz wrote:
> > > Hi Tomasz,
> > > 
> > > On Thu, Apr 04, 2013 at 06:37:01PM +0200, Tomasz Figa wrote:
> > > > This patch adds master driver for PWM/timer block available on many
> > > > Samsung SoCs providing clocksource and PWM output capabilities.
> > > 
> > > Why is that an MFD driver, and why aren't you using the PWM APIs for it
> > > ?
> > > Also, you probably want to look at using the regmap APIs for your IO.
> > 
> > The case of Samsung PWM timers is rather complicated. It is a hardware
> > block that can be used at the same time to generate PWM signal and as a
> > system clocksource.
> > 
> > There was a discussion on how to solve the problem of sharing the
> > hardware:
> > http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16480/focus=16500
> > (see the linked post and replies to it).
> 
> I don't think anyone ever suggested using a private API though.

I must have gotten the last paragraph of
http://article.gmane.org/gmane.linux.kernel.samsung-soc/16638
wrong then. For me it seemed like the timer driver would expose a private API 
to the PWM driver.

> I think
> it's ok if the driver lives in drivers/mfd when it doesn't fit anywhere
> else easily, but you should really register it to the pwm subsystem to
> expose that functionality, not export functions that can be used by
> a pwm shim driver, which even seems to be missing from the series.

Anyway, using PWM API in a clocksource driver that needs to be running very 
early (before any initcalls get called) seems a bit weird for me, especially 
when PWM API doesn't provide such fine grained control over PWM timers that is 
required in the clocksource drivers.

Best regards,
-- 
Tomasz Figa
Samsung Poland R&D Center
SW Solution Development, Kernel and System Framework

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

* [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
@ 2013-04-05 17:35           ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-05 17:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 05 of April 2013 19:05:24 Arnd Bergmann wrote:
> On Friday 05 April 2013, Tomasz Figa wrote:
> > On Friday 05 of April 2013 18:39:58 Samuel Ortiz wrote:
> > > Hi Tomasz,
> > > 
> > > On Thu, Apr 04, 2013 at 06:37:01PM +0200, Tomasz Figa wrote:
> > > > This patch adds master driver for PWM/timer block available on many
> > > > Samsung SoCs providing clocksource and PWM output capabilities.
> > > 
> > > Why is that an MFD driver, and why aren't you using the PWM APIs for it
> > > ?
> > > Also, you probably want to look at using the regmap APIs for your IO.
> > 
> > The case of Samsung PWM timers is rather complicated. It is a hardware
> > block that can be used at the same time to generate PWM signal and as a
> > system clocksource.
> > 
> > There was a discussion on how to solve the problem of sharing the
> > hardware:
> > http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16480/focus=16500
> > (see the linked post and replies to it).
> 
> I don't think anyone ever suggested using a private API though.

I must have gotten the last paragraph of
http://article.gmane.org/gmane.linux.kernel.samsung-soc/16638
wrong then. For me it seemed like the timer driver would expose a private API 
to the PWM driver.

> I think
> it's ok if the driver lives in drivers/mfd when it doesn't fit anywhere
> else easily, but you should really register it to the pwm subsystem to
> expose that functionality, not export functions that can be used by
> a pwm shim driver, which even seems to be missing from the series.

Anyway, using PWM API in a clocksource driver that needs to be running very 
early (before any initcalls get called) seems a bit weird for me, especially 
when PWM API doesn't provide such fine grained control over PWM timers that is 
required in the clocksource drivers.

Best regards,
-- 
Tomasz Figa
Samsung Poland R&D Center
SW Solution Development, Kernel and System Framework

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

* Re: [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
  2013-04-05 17:35           ` Tomasz Figa
@ 2013-04-05 19:54             ` Arnd Bergmann
  -1 siblings, 0 replies; 58+ messages in thread
From: Arnd Bergmann @ 2013-04-05 19:54 UTC (permalink / raw)
  To: Tomasz Figa
  Cc: mark.rutland, heiko, tomasz.figa, buserror, jacmet,
	augulis.darius, christer, sylvester.nawrocki, m.szyprowski,
	kgene.kim, linux, Samuel Ortiz, kwangwoo.lee, mcuelenaere,
	devicetree-discuss, linux-samsung-soc, john.stultz, ghcstop,
	linux, linux-arm-kernel, broonie, jekhor, kyungmin.park, tglx

On Friday 05 April 2013, Tomasz Figa wrote:
> > I don't think anyone ever suggested using a private API though.
> 
> I must have gotten the last paragraph of
> http://article.gmane.org/gmane.linux.kernel.samsung-soc/16638
> wrong then. For me it seemed like the timer driver would expose a private API 
> to the PWM driver.

Yes, sorry I wasn't clear enough. I meant a register-level interface
exposed from the base driver, not a high-level interface like you
did.

> > I think
> > it's ok if the driver lives in drivers/mfd when it doesn't fit anywhere
> > else easily, but you should really register it to the pwm subsystem to
> > expose that functionality, not export functions that can be used by
> > a pwm shim driver, which even seems to be missing from the series.
> 
> Anyway, using PWM API in a clocksource driver that needs to be running very 
> early (before any initcalls get called) seems a bit weird for me, especially 
> when PWM API doesn't provide such fine grained control over PWM timers that is 
> required in the clocksource drivers.

Exactly, that's why you should have a regular PWM driver that gets loaded
at a convenient time and just uses an interface exported by the base driver
to access the common registers.

	Arnd

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

* [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
@ 2013-04-05 19:54             ` Arnd Bergmann
  0 siblings, 0 replies; 58+ messages in thread
From: Arnd Bergmann @ 2013-04-05 19:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 05 April 2013, Tomasz Figa wrote:
> > I don't think anyone ever suggested using a private API though.
> 
> I must have gotten the last paragraph of
> http://article.gmane.org/gmane.linux.kernel.samsung-soc/16638
> wrong then. For me it seemed like the timer driver would expose a private API 
> to the PWM driver.

Yes, sorry I wasn't clear enough. I meant a register-level interface
exposed from the base driver, not a high-level interface like you
did.

> > I think
> > it's ok if the driver lives in drivers/mfd when it doesn't fit anywhere
> > else easily, but you should really register it to the pwm subsystem to
> > expose that functionality, not export functions that can be used by
> > a pwm shim driver, which even seems to be missing from the series.
> 
> Anyway, using PWM API in a clocksource driver that needs to be running very 
> early (before any initcalls get called) seems a bit weird for me, especially 
> when PWM API doesn't provide such fine grained control over PWM timers that is 
> required in the clocksource drivers.

Exactly, that's why you should have a regular PWM driver that gets loaded
at a convenient time and just uses an interface exported by the base driver
to access the common registers.

	Arnd

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

* Re: [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
  2013-04-05 19:54             ` Arnd Bergmann
@ 2013-04-05 22:24               ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-05 22:24 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: mark.rutland, heiko, Tomasz Figa, buserror, jacmet,
	augulis.darius, christer, sylvester.nawrocki, m.szyprowski,
	kgene.kim, linux, Samuel Ortiz, kwangwoo.lee, mcuelenaere,
	devicetree-discuss, linux-samsung-soc, john.stultz, ghcstop,
	linux, linux-arm-kernel, broonie, jekhor, kyungmin.park, tglx

On Friday 05 of April 2013 21:54:21 Arnd Bergmann wrote:
> On Friday 05 April 2013, Tomasz Figa wrote:
> > > I don't think anyone ever suggested using a private API though.
> > 
> > I must have gotten the last paragraph of
> > http://article.gmane.org/gmane.linux.kernel.samsung-soc/16638
> > wrong then. For me it seemed like the timer driver would expose a
> > private API to the PWM driver.
> 
> Yes, sorry I wasn't clear enough. I meant a register-level interface
> exposed from the base driver, not a high-level interface like you
> did.

I'm not sure what you mean by a register-level interface. Something like 
samsung_pwm_update_reg(reg, mask, val), which modifies bitfields according 
to the mask and value with appropriate synchronization? If yes, this 
solves only the problem of access to shared registers.

The other problems that remain:

- negotiation of PWM channels to use for clock source and clock events,
  because each board can use different channels for PWM outputs,

- code duplication caused by both of the drivers doing mostly the same
  things and or having to parse the same data from device tree,

- both non-DT and DT platforms must be supported,

- how to keep the ability to load PWM driver as a module (or not load it
  at all when PWM is not used on particular board), while retaining
  everything that is needed for the clocksource driver in kernel,

- some platforms can't use PWM timers as system clocksources, while on
  others this is the only timekeeping hardware available.

> > > I think
> > > it's ok if the driver lives in drivers/mfd when it doesn't fit
> > > anywhere
> > > else easily, but you should really register it to the pwm subsystem
> > > to
> > > expose that functionality, not export functions that can be used by
> > > a pwm shim driver, which even seems to be missing from the series.
> > 
> > Anyway, using PWM API in a clocksource driver that needs to be running
> > very early (before any initcalls get called) seems a bit weird for
> > me, especially when PWM API doesn't provide such fine grained control
> > over PWM timers that is required in the clocksource drivers.
> 
> Exactly, that's why you should have a regular PWM driver that gets
> loaded at a convenient time and just uses an interface exported by the
> base driver to access the common registers.

Well, this is basically what my patches do, except that the PWM driver 
isn't reworked to use the base driver yet.

The private API exported to the samsung-time and pwm-samsung drivers isn't 
maybe the most fortunate one, but it clearly has the advantage of solving 
all the problems I mentioned before.

Same goes for calling this an MFD driver. It doesn't even use the MFD 
core, but there seems to be no better place to put it. Maybe 
drivers/platform/arm would be better, if it existed, just as currently 
available drivers/platform/x86?

Best regards,
Tomasz

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

* [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
@ 2013-04-05 22:24               ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-05 22:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 05 of April 2013 21:54:21 Arnd Bergmann wrote:
> On Friday 05 April 2013, Tomasz Figa wrote:
> > > I don't think anyone ever suggested using a private API though.
> > 
> > I must have gotten the last paragraph of
> > http://article.gmane.org/gmane.linux.kernel.samsung-soc/16638
> > wrong then. For me it seemed like the timer driver would expose a
> > private API to the PWM driver.
> 
> Yes, sorry I wasn't clear enough. I meant a register-level interface
> exposed from the base driver, not a high-level interface like you
> did.

I'm not sure what you mean by a register-level interface. Something like 
samsung_pwm_update_reg(reg, mask, val), which modifies bitfields according 
to the mask and value with appropriate synchronization? If yes, this 
solves only the problem of access to shared registers.

The other problems that remain:

- negotiation of PWM channels to use for clock source and clock events,
  because each board can use different channels for PWM outputs,

- code duplication caused by both of the drivers doing mostly the same
  things and or having to parse the same data from device tree,

- both non-DT and DT platforms must be supported,

- how to keep the ability to load PWM driver as a module (or not load it
  at all when PWM is not used on particular board), while retaining
  everything that is needed for the clocksource driver in kernel,

- some platforms can't use PWM timers as system clocksources, while on
  others this is the only timekeeping hardware available.

> > > I think
> > > it's ok if the driver lives in drivers/mfd when it doesn't fit
> > > anywhere
> > > else easily, but you should really register it to the pwm subsystem
> > > to
> > > expose that functionality, not export functions that can be used by
> > > a pwm shim driver, which even seems to be missing from the series.
> > 
> > Anyway, using PWM API in a clocksource driver that needs to be running
> > very early (before any initcalls get called) seems a bit weird for
> > me, especially when PWM API doesn't provide such fine grained control
> > over PWM timers that is required in the clocksource drivers.
> 
> Exactly, that's why you should have a regular PWM driver that gets
> loaded at a convenient time and just uses an interface exported by the
> base driver to access the common registers.

Well, this is basically what my patches do, except that the PWM driver 
isn't reworked to use the base driver yet.

The private API exported to the samsung-time and pwm-samsung drivers isn't 
maybe the most fortunate one, but it clearly has the advantage of solving 
all the problems I mentioned before.

Same goes for calling this an MFD driver. It doesn't even use the MFD 
core, but there seems to be no better place to put it. Maybe 
drivers/platform/arm would be better, if it existed, just as currently 
available drivers/platform/x86?

Best regards,
Tomasz

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

* Re: [PATCH v4 00/14] ARM: samsung-time: Prepare for multiplatform support
  2013-04-04 16:36 ` Tomasz Figa
@ 2013-04-05 22:57   ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-05 22:57 UTC (permalink / raw)
  To: Tomasz Figa
  Cc: mark.rutland, heiko, buserror, jacmet, augulis.darius, christer,
	sylvester.nawrocki, m.szyprowski, kgene.kim, linux, sameo,
	kwangwoo.lee, mcuelenaere, arnd, devicetree-discuss,
	linux-samsung-soc, john.stultz, ghcstop, linux, linux-arm-kernel,
	broonie, jekhor, kyungmin.park, tglx

On Thursday 04 of April 2013 18:36:57 Tomasz Figa wrote:
> This series is an attempt to make the samsung-time clocksource driver
> ready for multiplatform kernels. It moves the driver to
> drivers/clocksource, cleans it up from uses of static platform-specific
> definitions, simplifies timer interrupt handling and adds Device Tree
> support.
> 
> Only samsung-time driver is reworked to use the master driver at this
> time, since the PWM driver can be already considered broken at the
> moment and needs separate series of several patches to fix and clean it
> up, which I am already working on.
> 
> Tested on Universal C210 board with Device Tree. Not tested without
> Device Tree, since it has been already broken before this series.
> Compile tested for other related SoCs.
> 
> Changes since v3:
> (http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16664/)
>  - Changed the design to use common (master) driver for operations that
>    can be done from both clocksource and PWM drivers (as suggested by
>    Arnd Bergmann) - needed to properly synchronize access to PWM
> registers - Moved handling of PWM prescaler and divider to master
> driver
> 
> Changes since v2:
> (http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16158)
>  - Addressed comments from Rob Herring and Mark Rutland
>  - Removed unused register definitions
>  - Replaced samsung,source-timer and samsung,event-timer properties
>    with samsung,pwm-outputs property that defines which PWM channels
>    are reserved for PWM outputs on particular platform
>  - Split non-DT and DT initialization into two functions
>  - Fixed a copy paste error
> 
> Changes since v1:
> (http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16005)
>  - Addressed comments from Mark Rutland
>  - Documented struct samsung_timer_variant
>  - Dropped inactive mail addresses from CC
> 
> Tomasz Figa (14):
>   ARM: SAMSUNG: Move samsung-time to drivers/clocksource
>   clocksource: samsung-time: Drop useless defines from public header
>   clocksource: samsung-time: Use local register definitions
>   mfd: Add Samsung PWM/timer master driver
>   ARM: SAMSUNG: Unify base address definitions of timer block
>   ARM: SAMSUNG: Add new PWM platform device
>   ARM: SAMSUNG: Set PWM platform data
>   clocksource: samsung-time: Use Samsung PWM/timer master driver
>   clocksource: samsung-time: Use variant data to get SoC-specific bits
>   clocksource: samsung-time: Use master driver to configure dividers
>   clocksource: samsung-time: Use clk_prepare_enable
>   clocksource: samsung-time: Use master driver to control PWM channels
>   clocksource: samsung-time: Move IRQ mask/ack handling to the driver
>   ARM: SAMSUNG: Remove unused PWM timer IRQ chip code

On FriendlyARM's Tiny6410 board (Mini6410-compatible), both with (using my 
patches adding S3C64xx Device Tree and pinctrl support) and without Device 
Tree:

Tested-by: Tomasz Figa <tomasz.figa@gmail.com>

Best regards,
Tomasz

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

* [PATCH v4 00/14] ARM: samsung-time: Prepare for multiplatform support
@ 2013-04-05 22:57   ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-05 22:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 04 of April 2013 18:36:57 Tomasz Figa wrote:
> This series is an attempt to make the samsung-time clocksource driver
> ready for multiplatform kernels. It moves the driver to
> drivers/clocksource, cleans it up from uses of static platform-specific
> definitions, simplifies timer interrupt handling and adds Device Tree
> support.
> 
> Only samsung-time driver is reworked to use the master driver at this
> time, since the PWM driver can be already considered broken at the
> moment and needs separate series of several patches to fix and clean it
> up, which I am already working on.
> 
> Tested on Universal C210 board with Device Tree. Not tested without
> Device Tree, since it has been already broken before this series.
> Compile tested for other related SoCs.
> 
> Changes since v3:
> (http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16664/)
>  - Changed the design to use common (master) driver for operations that
>    can be done from both clocksource and PWM drivers (as suggested by
>    Arnd Bergmann) - needed to properly synchronize access to PWM
> registers - Moved handling of PWM prescaler and divider to master
> driver
> 
> Changes since v2:
> (http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16158)
>  - Addressed comments from Rob Herring and Mark Rutland
>  - Removed unused register definitions
>  - Replaced samsung,source-timer and samsung,event-timer properties
>    with samsung,pwm-outputs property that defines which PWM channels
>    are reserved for PWM outputs on particular platform
>  - Split non-DT and DT initialization into two functions
>  - Fixed a copy paste error
> 
> Changes since v1:
> (http://thread.gmane.org/gmane.linux.kernel.samsung-soc/16005)
>  - Addressed comments from Mark Rutland
>  - Documented struct samsung_timer_variant
>  - Dropped inactive mail addresses from CC
> 
> Tomasz Figa (14):
>   ARM: SAMSUNG: Move samsung-time to drivers/clocksource
>   clocksource: samsung-time: Drop useless defines from public header
>   clocksource: samsung-time: Use local register definitions
>   mfd: Add Samsung PWM/timer master driver
>   ARM: SAMSUNG: Unify base address definitions of timer block
>   ARM: SAMSUNG: Add new PWM platform device
>   ARM: SAMSUNG: Set PWM platform data
>   clocksource: samsung-time: Use Samsung PWM/timer master driver
>   clocksource: samsung-time: Use variant data to get SoC-specific bits
>   clocksource: samsung-time: Use master driver to configure dividers
>   clocksource: samsung-time: Use clk_prepare_enable
>   clocksource: samsung-time: Use master driver to control PWM channels
>   clocksource: samsung-time: Move IRQ mask/ack handling to the driver
>   ARM: SAMSUNG: Remove unused PWM timer IRQ chip code

On FriendlyARM's Tiny6410 board (Mini6410-compatible), both with (using my 
patches adding S3C64xx Device Tree and pinctrl support) and without Device 
Tree:

Tested-by: Tomasz Figa <tomasz.figa@gmail.com>

Best regards,
Tomasz

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

* Re: [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
  2013-04-05 22:24               ` Tomasz Figa
@ 2013-04-08 16:53                 ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-08 16:53 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Tomasz Figa, Samuel Ortiz, linux-arm-kernel, devicetree-discuss,
	linux-samsung-soc, kgene.kim, kyungmin.park, linux, broonie,
	kwangwoo.lee, jacmet, augulis.darius, mcuelenaere, linux,
	sylvester.nawrocki, buserror, christer, jekhor, ghcstop,
	mark.rutland, heiko, robherring2, m.szyprowski, john.stultz,
	tglx

On Saturday 06 of April 2013 00:24:18 Tomasz Figa wrote:
> On Friday 05 of April 2013 21:54:21 Arnd Bergmann wrote:
> > On Friday 05 April 2013, Tomasz Figa wrote:
> > > > I don't think anyone ever suggested using a private API though.
> > > 
> > > I must have gotten the last paragraph of
> > > http://article.gmane.org/gmane.linux.kernel.samsung-soc/16638
> > > wrong then. For me it seemed like the timer driver would expose a
> > > private API to the PWM driver.
> > 
> > Yes, sorry I wasn't clear enough. I meant a register-level interface
> > exposed from the base driver, not a high-level interface like you
> > did.
> 
> I'm not sure what you mean by a register-level interface. Something like
> samsung_pwm_update_reg(reg, mask, val), which modifies bitfields
> according to the mask and value with appropriate synchronization? If
> yes, this solves only the problem of access to shared registers.
> 
> The other problems that remain:
> 
> - negotiation of PWM channels to use for clock source and clock events,
>   because each board can use different channels for PWM outputs,
> 
> - code duplication caused by both of the drivers doing mostly the same
>   things and or having to parse the same data from device tree,
> 
> - both non-DT and DT platforms must be supported,
> 
> - how to keep the ability to load PWM driver as a module (or not load it
> at all when PWM is not used on particular board), while retaining
> everything that is needed for the clocksource driver in kernel,
> 
> - some platforms can't use PWM timers as system clocksources, while on
>   others this is the only timekeeping hardware available.
> 

Hmm. Does anybody have an idea of a better way of implementing this PWM 
timer support, which solves the above problems?

This series is a dependency for moving Universal C210 board to DT-based 
description and it's already almost out of time to get this included for 
3.10...

Best regards,
Tomasz

> > > > I think
> > > > it's ok if the driver lives in drivers/mfd when it doesn't fit
> > > > anywhere
> > > > else easily, but you should really register it to the pwm
> > > > subsystem
> > > > to
> > > > expose that functionality, not export functions that can be used
> > > > by
> > > > a pwm shim driver, which even seems to be missing from the series.
> > > 
> > > Anyway, using PWM API in a clocksource driver that needs to be
> > > running
> > > very early (before any initcalls get called) seems a bit weird for
> > > me, especially when PWM API doesn't provide such fine grained
> > > control
> > > over PWM timers that is required in the clocksource drivers.
> > 
> > Exactly, that's why you should have a regular PWM driver that gets
> > loaded at a convenient time and just uses an interface exported by the
> > base driver to access the common registers.
> 
> Well, this is basically what my patches do, except that the PWM driver
> isn't reworked to use the base driver yet.
> 
> The private API exported to the samsung-time and pwm-samsung drivers
> isn't maybe the most fortunate one, but it clearly has the advantage of
> solving all the problems I mentioned before.
> 
> Same goes for calling this an MFD driver. It doesn't even use the MFD
> core, but there seems to be no better place to put it. Maybe
> drivers/platform/arm would be better, if it existed, just as currently
> available drivers/platform/x86?
> 
> Best regards,
> Tomasz

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

* [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
@ 2013-04-08 16:53                 ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-08 16:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 06 of April 2013 00:24:18 Tomasz Figa wrote:
> On Friday 05 of April 2013 21:54:21 Arnd Bergmann wrote:
> > On Friday 05 April 2013, Tomasz Figa wrote:
> > > > I don't think anyone ever suggested using a private API though.
> > > 
> > > I must have gotten the last paragraph of
> > > http://article.gmane.org/gmane.linux.kernel.samsung-soc/16638
> > > wrong then. For me it seemed like the timer driver would expose a
> > > private API to the PWM driver.
> > 
> > Yes, sorry I wasn't clear enough. I meant a register-level interface
> > exposed from the base driver, not a high-level interface like you
> > did.
> 
> I'm not sure what you mean by a register-level interface. Something like
> samsung_pwm_update_reg(reg, mask, val), which modifies bitfields
> according to the mask and value with appropriate synchronization? If
> yes, this solves only the problem of access to shared registers.
> 
> The other problems that remain:
> 
> - negotiation of PWM channels to use for clock source and clock events,
>   because each board can use different channels for PWM outputs,
> 
> - code duplication caused by both of the drivers doing mostly the same
>   things and or having to parse the same data from device tree,
> 
> - both non-DT and DT platforms must be supported,
> 
> - how to keep the ability to load PWM driver as a module (or not load it
> at all when PWM is not used on particular board), while retaining
> everything that is needed for the clocksource driver in kernel,
> 
> - some platforms can't use PWM timers as system clocksources, while on
>   others this is the only timekeeping hardware available.
> 

Hmm. Does anybody have an idea of a better way of implementing this PWM 
timer support, which solves the above problems?

This series is a dependency for moving Universal C210 board to DT-based 
description and it's already almost out of time to get this included for 
3.10...

Best regards,
Tomasz

> > > > I think
> > > > it's ok if the driver lives in drivers/mfd when it doesn't fit
> > > > anywhere
> > > > else easily, but you should really register it to the pwm
> > > > subsystem
> > > > to
> > > > expose that functionality, not export functions that can be used
> > > > by
> > > > a pwm shim driver, which even seems to be missing from the series.
> > > 
> > > Anyway, using PWM API in a clocksource driver that needs to be
> > > running
> > > very early (before any initcalls get called) seems a bit weird for
> > > me, especially when PWM API doesn't provide such fine grained
> > > control
> > > over PWM timers that is required in the clocksource drivers.
> > 
> > Exactly, that's why you should have a regular PWM driver that gets
> > loaded at a convenient time and just uses an interface exported by the
> > base driver to access the common registers.
> 
> Well, this is basically what my patches do, except that the PWM driver
> isn't reworked to use the base driver yet.
> 
> The private API exported to the samsung-time and pwm-samsung drivers
> isn't maybe the most fortunate one, but it clearly has the advantage of
> solving all the problems I mentioned before.
> 
> Same goes for calling this an MFD driver. It doesn't even use the MFD
> core, but there seems to be no better place to put it. Maybe
> drivers/platform/arm would be better, if it existed, just as currently
> available drivers/platform/x86?
> 
> Best regards,
> Tomasz

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

* Re: [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
  2013-04-08 16:53                 ` Tomasz Figa
@ 2013-04-10 22:35                   ` Arnd Bergmann
  -1 siblings, 0 replies; 58+ messages in thread
From: Arnd Bergmann @ 2013-04-10 22:35 UTC (permalink / raw)
  To: Tomasz Figa
  Cc: buserror-Re5JQEeQqe8AvxtiuMwx3w,
	augulis.darius-Re5JQEeQqe8AvxtiuMwx3w,
	christer-rKHMIqA5R6gwFerOooGFRg,
	sylvester.nawrocki-Re5JQEeQqe8AvxtiuMwx3w,
	m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ,
	kgene.kim-Sze3O3UU22JBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	Samuel Ortiz, kwangwoo.lee-Re5JQEeQqe8AvxtiuMwx3w,
	mcuelenaere-Re5JQEeQqe8AvxtiuMwx3w,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
	john.stultz-QSEj5FYQhm4dnm+yROfE0A,
	ghcstop-Re5JQEeQqe8AvxtiuMwx3w, linux-Y5A6D6n0/KfQXOPxS62xeg,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	broonie-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
	jekhor-Re5JQEeQqe8AvxtiuMwx3w,
	kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
	tglx-hfZtesqFncYOwBW4kG4KsQ

On Monday 08 April 2013, Tomasz Figa wrote:
> On Saturday 06 of April 2013 00:24:18 Tomasz Figa wrote:
> > On Friday 05 of April 2013 21:54:21 Arnd Bergmann wrote:
> > > On Friday 05 April 2013, Tomasz Figa wrote:
> > 
> > I'm not sure what you mean by a register-level interface. Something like
> > samsung_pwm_update_reg(reg, mask, val), which modifies bitfields
> > according to the mask and value with appropriate synchronization? If
> > yes, this solves only the problem of access to shared registers.
> > 
> > The other problems that remain:
> > 
> > - negotiation of PWM channels to use for clock source and clock events,
> >   because each board can use different channels for PWM outputs,
> > 
> > - code duplication caused by both of the drivers doing mostly the same
> >   things and or having to parse the same data from device tree,
> > 
> > - both non-DT and DT platforms must be supported,
> > 
> > - how to keep the ability to load PWM driver as a module (or not load it
> > at all when PWM is not used on particular board), while retaining
> > everything that is needed for the clocksource driver in kernel,
> > 
> > - some platforms can't use PWM timers as system clocksources, while on
> >   others this is the only timekeeping hardware available.
> > 
> 
> Hmm. Does anybody have an idea of a better way of implementing this PWM 
> timer support, which solves the above problems?
> 
> This series is a dependency for moving Universal C210 board to DT-based 
> description and it's already almost out of time to get this included for 
> 3.10...
> 

Sorry for not replying earlier. My idea for the register level interface
was to create a platform_device for each PWM, e.g. using the mfd_cell
infrastructure. You can then pass a "struct regmap" as the platform
data for each child of the timer node, and all the DT handling code
can stay in the parent driver.

	Arnd

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

* [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
@ 2013-04-10 22:35                   ` Arnd Bergmann
  0 siblings, 0 replies; 58+ messages in thread
From: Arnd Bergmann @ 2013-04-10 22:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Monday 08 April 2013, Tomasz Figa wrote:
> On Saturday 06 of April 2013 00:24:18 Tomasz Figa wrote:
> > On Friday 05 of April 2013 21:54:21 Arnd Bergmann wrote:
> > > On Friday 05 April 2013, Tomasz Figa wrote:
> > 
> > I'm not sure what you mean by a register-level interface. Something like
> > samsung_pwm_update_reg(reg, mask, val), which modifies bitfields
> > according to the mask and value with appropriate synchronization? If
> > yes, this solves only the problem of access to shared registers.
> > 
> > The other problems that remain:
> > 
> > - negotiation of PWM channels to use for clock source and clock events,
> >   because each board can use different channels for PWM outputs,
> > 
> > - code duplication caused by both of the drivers doing mostly the same
> >   things and or having to parse the same data from device tree,
> > 
> > - both non-DT and DT platforms must be supported,
> > 
> > - how to keep the ability to load PWM driver as a module (or not load it
> > at all when PWM is not used on particular board), while retaining
> > everything that is needed for the clocksource driver in kernel,
> > 
> > - some platforms can't use PWM timers as system clocksources, while on
> >   others this is the only timekeeping hardware available.
> > 
> 
> Hmm. Does anybody have an idea of a better way of implementing this PWM 
> timer support, which solves the above problems?
> 
> This series is a dependency for moving Universal C210 board to DT-based 
> description and it's already almost out of time to get this included for 
> 3.10...
> 

Sorry for not replying earlier. My idea for the register level interface
was to create a platform_device for each PWM, e.g. using the mfd_cell
infrastructure. You can then pass a "struct regmap" as the platform
data for each child of the timer node, and all the DT handling code
can stay in the parent driver.

	Arnd

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

* Re: [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
  2013-04-10 22:35                   ` Arnd Bergmann
@ 2013-04-11 16:28                     ` Mark Brown
  -1 siblings, 0 replies; 58+ messages in thread
From: Mark Brown @ 2013-04-11 16:28 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Tomasz Figa, Tomasz Figa, Samuel Ortiz, linux-arm-kernel,
	devicetree-discuss, linux-samsung-soc, kgene.kim, kyungmin.park,
	linux, kwangwoo.lee, jacmet, augulis.darius, mcuelenaere, linux,
	sylvester.nawrocki, buserror, christer, jekhor, ghcstop,
	mark.rutland, heiko, robherring2, m.szyprowski, john.stultz,
	tglx

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

On Thu, Apr 11, 2013 at 12:35:47AM +0200, Arnd Bergmann wrote:

> Sorry for not replying earlier. My idea for the register level interface
> was to create a platform_device for each PWM, e.g. using the mfd_cell
> infrastructure. You can then pass a "struct regmap" as the platform
> data for each child of the timer node, and all the DT handling code
> can stay in the parent driver.

Dunno if it helps or not but there's also dev_get_regmap() if you're
passing the struct device around or can fish one out of thhe parent.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
@ 2013-04-11 16:28                     ` Mark Brown
  0 siblings, 0 replies; 58+ messages in thread
From: Mark Brown @ 2013-04-11 16:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 11, 2013 at 12:35:47AM +0200, Arnd Bergmann wrote:

> Sorry for not replying earlier. My idea for the register level interface
> was to create a platform_device for each PWM, e.g. using the mfd_cell
> infrastructure. You can then pass a "struct regmap" as the platform
> data for each child of the timer node, and all the DT handling code
> can stay in the parent driver.

Dunno if it helps or not but there's also dev_get_regmap() if you're
passing the struct device around or can fish one out of thhe parent.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130411/f538ba40/attachment.sig>

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

* Re: [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
  2013-04-10 22:35                   ` Arnd Bergmann
@ 2013-04-11 16:44                     ` Tomasz Figa
  -1 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-11 16:44 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Tomasz Figa, Samuel Ortiz, linux-arm-kernel, devicetree-discuss,
	linux-samsung-soc, kgene.kim, kyungmin.park, linux, broonie,
	kwangwoo.lee, jacmet, augulis.darius, mcuelenaere, linux,
	sylvester.nawrocki, buserror, christer, jekhor, ghcstop,
	mark.rutland, heiko, robherring2, m.szyprowski, john.stultz,
	tglx

On Thursday 11 of April 2013 00:35:47 Arnd Bergmann wrote:
> On Monday 08 April 2013, Tomasz Figa wrote:
> > On Saturday 06 of April 2013 00:24:18 Tomasz Figa wrote:
> > > On Friday 05 of April 2013 21:54:21 Arnd Bergmann wrote:
> > > > On Friday 05 April 2013, Tomasz Figa wrote:
> > > I'm not sure what you mean by a register-level interface. Something like
> > > samsung_pwm_update_reg(reg, mask, val), which modifies bitfields
> > > according to the mask and value with appropriate synchronization? If
> > > yes, this solves only the problem of access to shared registers.
> > > 
> > > The other problems that remain:
> > > 
> > > - negotiation of PWM channels to use for clock source and clock events,
> > > 
> > >   because each board can use different channels for PWM outputs,
> > > 
> > > - code duplication caused by both of the drivers doing mostly the same
> > > 
> > >   things and or having to parse the same data from device tree,
> > > 
> > > - both non-DT and DT platforms must be supported,
> > > 
> > > - how to keep the ability to load PWM driver as a module (or not load it
> > > at all when PWM is not used on particular board), while retaining
> > > everything that is needed for the clocksource driver in kernel,
> > > 
> > > - some platforms can't use PWM timers as system clocksources, while on
> > > 
> > >   others this is the only timekeeping hardware available.
> > 
> > Hmm. Does anybody have an idea of a better way of implementing this PWM
> > timer support, which solves the above problems?
> > 
> > This series is a dependency for moving Universal C210 board to DT-based
> > description and it's already almost out of time to get this included for
> > 3.10...
> 
> Sorry for not replying earlier. My idea for the register level interface
> was to create a platform_device for each PWM, e.g. using the mfd_cell
> infrastructure. You can then pass a "struct regmap" as the platform
> data for each child of the timer node, and all the DT handling code
> can stay in the parent driver.

Hmm. As I said, I'm completely fine with using a regmap for sharing registers 
between subdrivers. However the clocksource can not be registered as an MFD 
cell, because it's needed very early.

I can imagine a solution alternative to my original one, where the MFD cells 
would be registered from the clocksource driver. This would mean that 
platforms that don't need (and can't use) the PWM clocksource would have to 
enable the driver anyway.

Another thing is that I don't see a need to create one cell per PWM channel. 
The PWM core is designed in a way that supports multiple channels per PWM 
controller and so is the generic PWM DT specifier (<&controller channel period 
flags>), so I'd rather see a single cell for all PWM channels.

So, to summarize this alternative concept:
 - two drivers:
   1) clocksource driver - registering clocksource and PWM MFD cell
   2) PWM driver - handling the PWM MFD cell
 - both drivers would share registers using a regmap with custom lock/unlock 
   callbacks (using spin_lock_irqsave/spin_unlock_irqrestore, because the 
   clocksource needs to access PWM registers in IRQ context)
 - the clocksource/master driver would have a samsung_time_init function which 
   would set up the driver early and initialize the clocksource
 - a platform driver would be registered by the clocksource/master driver
   which would register the PWM MFD cell in its probe
 - MFD cell platform data would contain struct regmap * and variant data
   (parsed from DT or received from platform code - as in my original version)

This should indeed work, assuming that I find a solution to make 
clocksource_of_init not initialize the PWM clocksource (from PWM DT node) on 
platforms that can't use it.

Best regards,
-- 
Tomasz Figa
Samsung Poland R&D Center
SW Solution Development, Kernel and System Framework

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

* [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
@ 2013-04-11 16:44                     ` Tomasz Figa
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Figa @ 2013-04-11 16:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 11 of April 2013 00:35:47 Arnd Bergmann wrote:
> On Monday 08 April 2013, Tomasz Figa wrote:
> > On Saturday 06 of April 2013 00:24:18 Tomasz Figa wrote:
> > > On Friday 05 of April 2013 21:54:21 Arnd Bergmann wrote:
> > > > On Friday 05 April 2013, Tomasz Figa wrote:
> > > I'm not sure what you mean by a register-level interface. Something like
> > > samsung_pwm_update_reg(reg, mask, val), which modifies bitfields
> > > according to the mask and value with appropriate synchronization? If
> > > yes, this solves only the problem of access to shared registers.
> > > 
> > > The other problems that remain:
> > > 
> > > - negotiation of PWM channels to use for clock source and clock events,
> > > 
> > >   because each board can use different channels for PWM outputs,
> > > 
> > > - code duplication caused by both of the drivers doing mostly the same
> > > 
> > >   things and or having to parse the same data from device tree,
> > > 
> > > - both non-DT and DT platforms must be supported,
> > > 
> > > - how to keep the ability to load PWM driver as a module (or not load it
> > > at all when PWM is not used on particular board), while retaining
> > > everything that is needed for the clocksource driver in kernel,
> > > 
> > > - some platforms can't use PWM timers as system clocksources, while on
> > > 
> > >   others this is the only timekeeping hardware available.
> > 
> > Hmm. Does anybody have an idea of a better way of implementing this PWM
> > timer support, which solves the above problems?
> > 
> > This series is a dependency for moving Universal C210 board to DT-based
> > description and it's already almost out of time to get this included for
> > 3.10...
> 
> Sorry for not replying earlier. My idea for the register level interface
> was to create a platform_device for each PWM, e.g. using the mfd_cell
> infrastructure. You can then pass a "struct regmap" as the platform
> data for each child of the timer node, and all the DT handling code
> can stay in the parent driver.

Hmm. As I said, I'm completely fine with using a regmap for sharing registers 
between subdrivers. However the clocksource can not be registered as an MFD 
cell, because it's needed very early.

I can imagine a solution alternative to my original one, where the MFD cells 
would be registered from the clocksource driver. This would mean that 
platforms that don't need (and can't use) the PWM clocksource would have to 
enable the driver anyway.

Another thing is that I don't see a need to create one cell per PWM channel. 
The PWM core is designed in a way that supports multiple channels per PWM 
controller and so is the generic PWM DT specifier (<&controller channel period 
flags>), so I'd rather see a single cell for all PWM channels.

So, to summarize this alternative concept:
 - two drivers:
   1) clocksource driver - registering clocksource and PWM MFD cell
   2) PWM driver - handling the PWM MFD cell
 - both drivers would share registers using a regmap with custom lock/unlock 
   callbacks (using spin_lock_irqsave/spin_unlock_irqrestore, because the 
   clocksource needs to access PWM registers in IRQ context)
 - the clocksource/master driver would have a samsung_time_init function which 
   would set up the driver early and initialize the clocksource
 - a platform driver would be registered by the clocksource/master driver
   which would register the PWM MFD cell in its probe
 - MFD cell platform data would contain struct regmap * and variant data
   (parsed from DT or received from platform code - as in my original version)

This should indeed work, assuming that I find a solution to make 
clocksource_of_init not initialize the PWM clocksource (from PWM DT node) on 
platforms that can't use it.

Best regards,
-- 
Tomasz Figa
Samsung Poland R&D Center
SW Solution Development, Kernel and System Framework

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

* Re: [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
  2013-04-11 16:44                     ` Tomasz Figa
@ 2013-04-11 21:08                       ` Arnd Bergmann
  -1 siblings, 0 replies; 58+ messages in thread
From: Arnd Bergmann @ 2013-04-11 21:08 UTC (permalink / raw)
  To: Tomasz Figa
  Cc: mark.rutland, heiko, Tomasz Figa, buserror, jacmet,
	augulis.darius, christer, sylvester.nawrocki, m.szyprowski,
	kgene.kim, linux, Samuel Ortiz, kwangwoo.lee, mcuelenaere,
	devicetree-discuss, linux-samsung-soc, john.stultz, ghcstop,
	linux, linux-arm-kernel, broonie, jekhor, kyungmin.park, tglx

On Thursday 11 April 2013, Tomasz Figa wrote:
> On Thursday 11 of April 2013 00:35:47 Arnd Bergmann wrote:
> > On Monday 08 April 2013, Tomasz Figa wrote:
> > > On Saturday 06 of April 2013 00:24:18 Tomasz Figa wrote:
> > > > On Friday 05 of April 2013 21:54:21 Arnd Bergmann wrote:
> > > > > On Friday 05 April 2013, Tomasz Figa wrote:
> > 
> > Sorry for not replying earlier. My idea for the register level interface
> > was to create a platform_device for each PWM, e.g. using the mfd_cell
> > infrastructure. You can then pass a "struct regmap" as the platform
> > data for each child of the timer node, and all the DT handling code
> > can stay in the parent driver.
> 
> Hmm. As I said, I'm completely fine with using a regmap for sharing registers 
> between subdrivers. However the clocksource can not be registered as an MFD 
> cell, because it's needed very early.
> 
> I can imagine a solution alternative to my original one, where the MFD cells 
> would be registered from the clocksource driver. This would mean that 
> platforms that don't need (and can't use) the PWM clocksource would have to 
> enable the driver anyway.

Sounds ok to me. The main part I want to avoid is having two separate device
nodes in the DT for one physical device, but there are multiple ways to get
there.

> Another thing is that I don't see a need to create one cell per PWM channel. 
> The PWM core is designed in a way that supports multiple channels per PWM 
> controller and so is the generic PWM DT specifier (<&controller channel period 
> flags>), so I'd rather see a single cell for all PWM channels.

Sure, no problem with that.

> So, to summarize this alternative concept:
>  - two drivers:
>    1) clocksource driver - registering clocksource and PWM MFD cell
>    2) PWM driver - handling the PWM MFD cell

Ok. Don't be too tied to the MFD concept though if it causes problems.
In many cases calling platform_device_register_resndata or similar is
actually easier than MFD, especially if you only want a single child
device. Either way is fine though.

>  - both drivers would share registers using a regmap with custom lock/unlock 
>    callbacks (using spin_lock_irqsave/spin_unlock_irqrestore, because the 
>    clocksource needs to access PWM registers in IRQ context)

Ok.

>  - the clocksource/master driver would have a samsung_time_init function which 
>    would set up the driver early and initialize the clocksource

Right. If you want to use the clocksource_of_init() infratstructure for this
(which is probably a good idea), please base your series on top of the
clksrc/cleanup branch in arm-soc.

>  - a platform driver would be registered by the clocksource/master driver
>    which would register the PWM MFD cell in its probe.

This seems unnecessary, if the only purpose of the platform driver is to
export the MFD cell. In that case, I would actually suggest a simpler model
where the PWM driver registers the main platform driver directly and
calls a function exported by the clocksource driver to get the regmap
structure and anything else it may need (possibly initializing the driver
in the case where it is not used as the clocksource but only provides
the registers for PWM).

>  - MFD cell platform data would contain struct regmap * and variant data
>    (parsed from DT or received from platform code - as in my original version)

Yes, either the MFD cell, or the exported symbol, whichever ends up easier.

> This should indeed work, assuming that I find a solution to make 
> clocksource_of_init not initialize the PWM clocksource (from PWM DT node) on 
> platforms that can't use it.

Right. If anything else comes up, I'd suggest we discuss it on IRC (#armlinux
on irc.freenode.net) tomorrow for faster round-trip, or I can call you on
the phone if you like. I'm available all day tomorrow, just send me your
(landline) phone number by private email.

	Arnd.

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

* [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver
@ 2013-04-11 21:08                       ` Arnd Bergmann
  0 siblings, 0 replies; 58+ messages in thread
From: Arnd Bergmann @ 2013-04-11 21:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 11 April 2013, Tomasz Figa wrote:
> On Thursday 11 of April 2013 00:35:47 Arnd Bergmann wrote:
> > On Monday 08 April 2013, Tomasz Figa wrote:
> > > On Saturday 06 of April 2013 00:24:18 Tomasz Figa wrote:
> > > > On Friday 05 of April 2013 21:54:21 Arnd Bergmann wrote:
> > > > > On Friday 05 April 2013, Tomasz Figa wrote:
> > 
> > Sorry for not replying earlier. My idea for the register level interface
> > was to create a platform_device for each PWM, e.g. using the mfd_cell
> > infrastructure. You can then pass a "struct regmap" as the platform
> > data for each child of the timer node, and all the DT handling code
> > can stay in the parent driver.
> 
> Hmm. As I said, I'm completely fine with using a regmap for sharing registers 
> between subdrivers. However the clocksource can not be registered as an MFD 
> cell, because it's needed very early.
> 
> I can imagine a solution alternative to my original one, where the MFD cells 
> would be registered from the clocksource driver. This would mean that 
> platforms that don't need (and can't use) the PWM clocksource would have to 
> enable the driver anyway.

Sounds ok to me. The main part I want to avoid is having two separate device
nodes in the DT for one physical device, but there are multiple ways to get
there.

> Another thing is that I don't see a need to create one cell per PWM channel. 
> The PWM core is designed in a way that supports multiple channels per PWM 
> controller and so is the generic PWM DT specifier (<&controller channel period 
> flags>), so I'd rather see a single cell for all PWM channels.

Sure, no problem with that.

> So, to summarize this alternative concept:
>  - two drivers:
>    1) clocksource driver - registering clocksource and PWM MFD cell
>    2) PWM driver - handling the PWM MFD cell

Ok. Don't be too tied to the MFD concept though if it causes problems.
In many cases calling platform_device_register_resndata or similar is
actually easier than MFD, especially if you only want a single child
device. Either way is fine though.

>  - both drivers would share registers using a regmap with custom lock/unlock 
>    callbacks (using spin_lock_irqsave/spin_unlock_irqrestore, because the 
>    clocksource needs to access PWM registers in IRQ context)

Ok.

>  - the clocksource/master driver would have a samsung_time_init function which 
>    would set up the driver early and initialize the clocksource

Right. If you want to use the clocksource_of_init() infratstructure for this
(which is probably a good idea), please base your series on top of the
clksrc/cleanup branch in arm-soc.

>  - a platform driver would be registered by the clocksource/master driver
>    which would register the PWM MFD cell in its probe.

This seems unnecessary, if the only purpose of the platform driver is to
export the MFD cell. In that case, I would actually suggest a simpler model
where the PWM driver registers the main platform driver directly and
calls a function exported by the clocksource driver to get the regmap
structure and anything else it may need (possibly initializing the driver
in the case where it is not used as the clocksource but only provides
the registers for PWM).

>  - MFD cell platform data would contain struct regmap * and variant data
>    (parsed from DT or received from platform code - as in my original version)

Yes, either the MFD cell, or the exported symbol, whichever ends up easier.

> This should indeed work, assuming that I find a solution to make 
> clocksource_of_init not initialize the PWM clocksource (from PWM DT node) on 
> platforms that can't use it.

Right. If anything else comes up, I'd suggest we discuss it on IRC (#armlinux
on irc.freenode.net) tomorrow for faster round-trip, or I can call you on
the phone if you like. I'm available all day tomorrow, just send me your
(landline) phone number by private email.

	Arnd.

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

end of thread, other threads:[~2013-04-11 21:08 UTC | newest]

Thread overview: 58+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-04-04 16:36 [PATCH v4 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
2013-04-04 16:36 ` Tomasz Figa
2013-04-04 16:36 ` [PATCH v4 01/14] ARM: SAMSUNG: Move samsung-time to drivers/clocksource Tomasz Figa
2013-04-04 16:36   ` Tomasz Figa
2013-04-04 16:36 ` [PATCH v4 02/14] clocksource: samsung-time: Drop useless defines from public header Tomasz Figa
2013-04-04 16:36   ` Tomasz Figa
2013-04-04 16:37 ` [PATCH v4 03/14] clocksource: samsung-time: Use local register definitions Tomasz Figa
2013-04-04 16:37   ` Tomasz Figa
2013-04-04 16:37 ` [PATCH v4 04/14] mfd: Add Samsung PWM/timer master driver Tomasz Figa
2013-04-04 16:37   ` Tomasz Figa
2013-04-05 16:39   ` Samuel Ortiz
2013-04-05 16:39     ` Samuel Ortiz
2013-04-05 16:53     ` Tomasz Figa
2013-04-05 16:53       ` Tomasz Figa
2013-04-05 17:05       ` Arnd Bergmann
2013-04-05 17:05         ` Arnd Bergmann
2013-04-05 17:35         ` Tomasz Figa
2013-04-05 17:35           ` Tomasz Figa
2013-04-05 19:54           ` Arnd Bergmann
2013-04-05 19:54             ` Arnd Bergmann
2013-04-05 22:24             ` Tomasz Figa
2013-04-05 22:24               ` Tomasz Figa
2013-04-08 16:53               ` Tomasz Figa
2013-04-08 16:53                 ` Tomasz Figa
2013-04-10 22:35                 ` Arnd Bergmann
2013-04-10 22:35                   ` Arnd Bergmann
2013-04-11 16:28                   ` Mark Brown
2013-04-11 16:28                     ` Mark Brown
2013-04-11 16:44                   ` Tomasz Figa
2013-04-11 16:44                     ` Tomasz Figa
2013-04-11 21:08                     ` Arnd Bergmann
2013-04-11 21:08                       ` Arnd Bergmann
2013-04-04 16:37 ` [PATCH v4 05/14] ARM: SAMSUNG: Unify base address definitions of timer block Tomasz Figa
2013-04-04 16:37   ` Tomasz Figa
2013-04-04 16:37 ` [PATCH v4 06/14] ARM: SAMSUNG: Add new PWM platform device Tomasz Figa
2013-04-04 16:37   ` Tomasz Figa
2013-04-04 16:37 ` [PATCH v4 07/14] ARM: SAMSUNG: Set PWM platform data Tomasz Figa
2013-04-04 16:37   ` Tomasz Figa
2013-04-04 16:37 ` [PATCH v4 08/14] clocksource: samsung-time: Use Samsung PWM/timer master driver Tomasz Figa
2013-04-04 16:37   ` Tomasz Figa
2013-04-04 16:37 ` [PATCH v4 09/14] clocksource: samsung-time: Use variant data to get SoC-specific bits Tomasz Figa
2013-04-04 16:37   ` Tomasz Figa
2013-04-04 16:37 ` [PATCH v4 10/14] clocksource: samsung-time: Use master driver to configure dividers Tomasz Figa
2013-04-04 16:37   ` Tomasz Figa
2013-04-04 16:37 ` [PATCH v4 11/14] clocksource: samsung-time: Use clk_prepare_enable Tomasz Figa
2013-04-04 16:37   ` Tomasz Figa
2013-04-04 16:37 ` [PATCH v4 12/14] clocksource: samsung-time: Use master driver to control PWM channels Tomasz Figa
2013-04-04 16:37   ` Tomasz Figa
2013-04-04 16:37 ` [PATCH v4 13/14] clocksource: samsung-time: Move IRQ mask/ack handling to the driver Tomasz Figa
2013-04-04 16:37   ` Tomasz Figa
2013-04-04 16:37 ` [PATCH v4 14/14] ARM: SAMSUNG: Remove unused PWM timer IRQ chip code Tomasz Figa
2013-04-04 16:37   ` Tomasz Figa
2013-04-04 23:15 ` [PATCH v4 00/14] ARM: samsung-time: Prepare for multiplatform support Heiko Stübner
2013-04-04 23:15   ` Heiko Stübner
2013-04-05 10:33   ` Tomasz Figa
2013-04-05 10:33     ` Tomasz Figa
2013-04-05 22:57 ` Tomasz Figa
2013-04-05 22:57   ` Tomasz Figa

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.