* [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support
@ 2013-04-12 19:17 Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 01/14] ARM: SAMSUNG: Move samsung-time to drivers/clocksource Tomasz Figa
` (18 more replies)
0 siblings, 19 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 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.
The samsung_pwm clocksource driver is made the master driver, which
exposes a single function to the PWM driver to get required data. 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 v4:
(http://thread.gmane.org/gmane.linux.kernel.samsung-soc/17464)
- Changed the design again - now clocksource driver is considered the master
and exports a single function to get access to things like base address,
hardware variant information, shared spinlock for register access
synchronization and interrupt numbers
- Renamed the clocksource driver to samsung_pwm
- Cleaned up the code a bit more
- Added clocksource_of_init support
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-pwm: Clean up platform header
clocksource: samsung-pwm: Add infrastructure to share PWM hardware
ARM: SAMSUNG: Unify base address definitions of timer block
ARM: SAMSUNG: Add new PWM platform device
ARM: SAMSUNG: Set PWM platform data
clocksource: samsung-pwm: Use platform data to setup the clocksource
clocksource: samsung-pwm: Synchronize register accesses
clocksource: samsung-pwm: Move IRQ mask/ack handling to the driver
ARM: SAMSUNG: Remove unused PWM timer IRQ chip code
clocksource: samsung-pwm: Configure dividers directly
clocksource: samsung-pwm: Do not use static mapping of registers
clocksource: samsung-pwm: Drop unnecessary includes
clocksource: samsung-pwm: Prepare for clocksource_of_init
.../devicetree/bindings/pwm/pwm-samsung.txt | 43 ++
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 | 7 +
drivers/clocksource/Makefile | 1 +
drivers/clocksource/samsung_pwm.c | 636 +++++++++++++++++++++
include/clocksource/samsung_pwm.h | 45 ++
34 files changed, 849 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_pwm.c
create mode 100644 include/clocksource/samsung_pwm.h
--
1.8.1.5
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v5 01/14] ARM: SAMSUNG: Move samsung-time to drivers/clocksource
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
@ 2013-04-12 19:17 ` Tomasz Figa
2013-04-12 20:44 ` Arnd Bergmann
2013-04-12 19:17 ` [PATCH v5 02/14] clocksource: samsung-pwm: Clean up platform header Tomasz Figa
` (17 subsequent siblings)
18 siblings, 1 reply; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 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.
In addition, the driver is renamed to samsung_pwm, since it uses PWM
timers available on Samsung SoCs for timekeeping purposes.
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_pwm.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_pwm.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..c0a1945 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_pwm.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_pwm.c b/drivers/clocksource/samsung_pwm.c
new file mode 100644
index 0000000..f899cbc
--- /dev/null
+++ b/drivers/clocksource/samsung_pwm.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] 29+ messages in thread
* [PATCH v5 02/14] clocksource: samsung-pwm: Clean up platform header
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 01/14] ARM: SAMSUNG: Move samsung-time to drivers/clocksource Tomasz Figa
@ 2013-04-12 19:17 ` Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 03/14] clocksource: samsung-pwm: Add infrastructure to share PWM hardware Tomasz Figa
` (16 subsequent siblings)
18 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 UTC (permalink / raw)
To: linux-arm-kernel
This patch moves private definitions out of the public platform header
and also cleans it up from unused and/or unnecessary ones.
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 | 11 -----------
drivers/clocksource/samsung_pwm.c | 15 ++++++++++-----
2 files changed, 10 insertions(+), 16 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..ecc423c 100644
--- a/arch/arm/plat-samsung/include/plat/samsung-time.h
+++ b/arch/arm/plat-samsung/include/plat/samsung-time.h
@@ -22,14 +22,6 @@ enum samsung_timer_mode {
SAMSUNG_PWM4,
};
-struct samsung_timer_source {
- unsigned int event_id;
- 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 +34,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_pwm.c b/drivers/clocksource/samsung_pwm.c
index f899cbc..974675b 100644
--- a/drivers/clocksource/samsung_pwm.c
+++ b/drivers/clocksource/samsung_pwm.c
@@ -27,6 +27,11 @@
#include <plat/regs-timer.h>
#include <plat/samsung-time.h>
+struct samsung_timer_source {
+ unsigned int event_id;
+ unsigned int source_id;
+};
+
static struct clk *tin_event;
static struct clk *tin_source;
static struct clk *tdiv_event;
@@ -182,7 +187,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 +200,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 +220,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 +340,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] 29+ messages in thread
* [PATCH v5 03/14] clocksource: samsung-pwm: Add infrastructure to share PWM hardware
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 01/14] ARM: SAMSUNG: Move samsung-time to drivers/clocksource Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 02/14] clocksource: samsung-pwm: Clean up platform header Tomasz Figa
@ 2013-04-12 19:17 ` Tomasz Figa
2013-04-12 20:42 ` Arnd Bergmann
2013-04-12 19:17 ` [PATCH v5 04/14] ARM: SAMSUNG: Unify base address definitions of timer block Tomasz Figa
` (15 subsequent siblings)
18 siblings, 1 reply; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 UTC (permalink / raw)
To: linux-arm-kernel
This patch extends samsung PWM clocksource driver with infrastructure
that allows sharing of PWM hardware between clocksource and PWM drivers.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
.../devicetree/bindings/pwm/pwm-samsung.txt | 43 ++++
drivers/clocksource/samsung_pwm.c | 250 +++++++++++++++++++++
include/clocksource/samsung_pwm.h | 44 ++++
3 files changed, 337 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pwm/pwm-samsung.txt
create mode 100644 include/clocksource/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..cc17c4c
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-samsung.txt
@@ -0,0 +1,43 @@
+* 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 the clocksource driver supports only uniprocessor systems.
+
+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 rev0 SoCs
+ samsung,exynos4210-pwm - for 32-bit timers present on 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 4
+ the specifier format is as follows:
+ - phandle to PWM controller node
+ - index of PWM channel (from 0 to 4)
+ - PWM signal period in nanoseconds
+ - bitmask of PWM flags:
+ 0x1 - invert PWM signal
+
+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/samsung_pwm.c b/drivers/clocksource/samsung_pwm.c
index 974675b..7bbd55c 100644
--- a/drivers/clocksource/samsung_pwm.c
+++ b/drivers/clocksource/samsung_pwm.c
@@ -14,7 +14,15 @@
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/clockchips.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <clocksource/samsung_pwm.h>
#include <asm/smp_twd.h>
#include <asm/mach/time.h>
@@ -27,6 +35,248 @@
#include <plat/regs-timer.h>
#include <plat/samsung-time.h>
+/*
+ * PWM master driver
+ */
+
+struct samsung_pwm_drvdata {
+ struct samsung_pwm pwm;
+ struct platform_device *pdev;
+ struct device_node *of_node;
+ struct resource resource;
+ struct list_head list;
+};
+
+static LIST_HEAD(pwm_list);
+
+#ifdef CONFIG_OF
+static int samsung_pwm_parse_dt(struct samsung_pwm_drvdata *drvdata)
+{
+ struct samsung_pwm *pwm = &drvdata->pwm;
+ struct samsung_pwm_variant *variant = &pwm->variant;
+ struct device_node *np = drvdata->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, },
+ { .compatible = "samsung,exynos4210-pwm", .data = &s5p_variant, },
+ {},
+};
+
+static struct samsung_pwm_drvdata *samsung_pwm_alloc(
+ struct platform_device *pdev, struct device_node *of_node,
+ const struct samsung_pwm_variant *variant)
+{
+ struct samsung_pwm_drvdata *drvdata;
+
+ drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return NULL;
+
+ memcpy(&drvdata->pwm.variant, variant, sizeof(drvdata->pwm.variant));
+
+ spin_lock_init(&drvdata->pwm.slock);
+
+ drvdata->pdev = pdev;
+ drvdata->of_node = of_node;
+
+ return drvdata;
+}
+
+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 = samsung_pwm_alloc(NULL, np, variant);
+ if (!pwm) {
+ pr_err("%s: could not allocate PWM device struct\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ 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);
+ 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 = samsung_pwm_alloc(pdev, pdev->dev.of_node, variant);
+ if (!pwm) {
+ pr_err("%s: could not allocate PWM device struct\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ 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 device_node *np)
+{
+ struct samsung_pwm_drvdata *pwm;
+
+ if (pdev)
+ np = pdev->dev.of_node;
+
+ list_for_each_entry(pwm, &pwm_list, list)
+ if ((np && pwm->of_node == np) || !pdev || pwm->pdev == pdev)
+ return pwm;
+
+ if (pdev && !np)
+ return samsung_pwm_add(pdev);
+
+ return samsung_pwm_of_add(np);
+}
+
+struct samsung_pwm *samsung_pwm_get(struct platform_device *pdev,
+ struct device_node *of_node)
+{
+ struct samsung_pwm_drvdata *pwm;
+ struct resource *res;
+
+ pwm = samsung_pwm_find(pdev, of_node);
+ 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);
+
+/*
+ * Clocksource driver
+ */
+
struct samsung_timer_source {
unsigned int event_id;
unsigned int source_id;
diff --git a/include/clocksource/samsung_pwm.h b/include/clocksource/samsung_pwm.h
new file mode 100644
index 0000000..d16415f
--- /dev/null
+++ b/include/clocksource/samsung_pwm.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __CLOCKSOURCE_SAMSUNG_PWM_H
+#define __CLOCKSOURCE_SAMSUNG_PWM_H
+
+#include <linux/spinlock.h>
+
+#define SAMSUNG_PWM_NUM 5
+
+struct platform_device;
+struct device_node;
+
+struct samsung_pwm_variant {
+ u8 bits;
+ u8 div_base;
+ u8 tclk_mask;
+ u8 output_mask;
+ bool has_tint_cstat;
+};
+
+struct samsung_pwm {
+ struct samsung_pwm_variant variant;
+ spinlock_t slock;
+ void __iomem *base;
+ int irq[SAMSUNG_PWM_NUM];
+};
+
+extern struct samsung_pwm *samsung_pwm_get(struct platform_device *,
+ struct device_node *);
+
+#endif /* __CLOCKSOURCE_SAMSUNG_PWM_H */
--
1.8.1.5
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 04/14] ARM: SAMSUNG: Unify base address definitions of timer block
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (2 preceding siblings ...)
2013-04-12 19:17 ` [PATCH v5 03/14] clocksource: samsung-pwm: Add infrastructure to share PWM hardware Tomasz Figa
@ 2013-04-12 19:17 ` Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 05/14] ARM: SAMSUNG: Add new PWM platform device Tomasz Figa
` (14 subsequent siblings)
18 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 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] 29+ messages in thread
* [PATCH v5 05/14] ARM: SAMSUNG: Add new PWM platform device
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (3 preceding siblings ...)
2013-04-12 19:17 ` [PATCH v5 04/14] ARM: SAMSUNG: Unify base address definitions of timer block Tomasz Figa
@ 2013-04-12 19:17 ` Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 06/14] ARM: SAMSUNG: Set PWM platform data Tomasz Figa
` (13 subsequent siblings)
18 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 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] 29+ messages in thread
* [PATCH v5 06/14] ARM: SAMSUNG: Set PWM platform data
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (4 preceding siblings ...)
2013-04-12 19:17 ` [PATCH v5 05/14] ARM: SAMSUNG: Add new PWM platform device Tomasz Figa
@ 2013-04-12 19:17 ` Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 07/14] clocksource: samsung-pwm: Use platform data to setup the clocksource Tomasz Figa
` (12 subsequent siblings)
18 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 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 a8570bf..b65229d 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 <clocksource/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..a01cccb 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 <clocksource/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..89d2823 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 <clocksource/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..cef1d3a 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 <clocksource/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..3ccbd43 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 <clocksource/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..bfd918f 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 <clocksource/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] 29+ messages in thread
* [PATCH v5 07/14] clocksource: samsung-pwm: Use platform data to setup the clocksource
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (5 preceding siblings ...)
2013-04-12 19:17 ` [PATCH v5 06/14] ARM: SAMSUNG: Set PWM platform data Tomasz Figa
@ 2013-04-12 19:17 ` Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 08/14] clocksource: samsung-pwm: Synchronize register accesses Tomasz Figa
` (11 subsequent siblings)
18 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 UTC (permalink / raw)
To: linux-arm-kernel
This patch modifies the clocksource registration code to use data taken
from platform data instead of statically hardcoded defines.
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 | 29 +++++-----
drivers/clocksource/samsung_pwm.c | 70 ++++++++++++++++-------
include/clocksource/samsung_pwm.h | 1 +
4 files changed, 73 insertions(+), 34 deletions(-)
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index bfae4dd..fbfabd2 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -32,6 +32,8 @@
#include <linux/platform_data/s3c-hsudc.h>
#include <linux/platform_data/s3c-hsotg.h>
+#include <clocksource/samsung_pwm.h>
+
#include <media/s5p_hdmi.h>
#include <asm/irq.h>
@@ -1184,6 +1186,11 @@ struct platform_device samsung_device_pwm = {
.resource = samsung_pwm_resource,
};
+void samsung_timer_init(void)
+{
+ samsung_pwm_clocksource_init(&samsung_device_pwm);
+}
+
/* 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 ecc423c..633c151 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 <clocksource/samsung_pwm.h>
+
+#include <plat/devs.h>
+
/* SAMSUNG HR-Timer Clock mode */
enum samsung_timer_mode {
SAMSUNG_PWM0,
@@ -22,20 +26,17 @@ enum samsung_timer_mode {
SAMSUNG_PWM4,
};
-#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
-
-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_pwm.c b/drivers/clocksource/samsung_pwm.c
index 7bbd55c..841d03c 100644
--- a/drivers/clocksource/samsung_pwm.c
+++ b/drivers/clocksource/samsung_pwm.c
@@ -280,8 +280,13 @@ EXPORT_SYMBOL(samsung_pwm_get);
struct samsung_timer_source {
unsigned int event_id;
unsigned int source_id;
+ unsigned int tcnt_max;
+ unsigned int tscaler_div;
+ unsigned int tdiv;
};
+static struct samsung_pwm *pwm;
+
static struct clk *tin_event;
static struct clk *tin_source;
static struct clk *tdiv_event;
@@ -473,20 +478,10 @@ 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);
}
-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,
@@ -522,8 +517,9 @@ 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.tdiv * timer_source.tscaler_div));
clk_set_parent(tin_event, tdiv_event);
clock_rate = clk_get_rate(tin_event);
@@ -532,7 +528,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);
}
@@ -579,23 +575,29 @@ static u32 notrace samsung_read_sched_clock(void)
static void __init samsung_clocksource_init(void)
{
+ void __iomem *reg = samsung_timer_reg();
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.tdiv * timer_source.tscaler_div));
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(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");
}
@@ -639,10 +641,38 @@ 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_timer_init(void)
+void __init samsung_pwm_clocksource_init(struct platform_device *pdev)
{
+ u8 mask;
+ int channel;
+
+ pwm = samsung_pwm_get(pdev, 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;
+
+ 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_timer_resources();
samsung_clockevent_init();
samsung_clocksource_init();
diff --git a/include/clocksource/samsung_pwm.h b/include/clocksource/samsung_pwm.h
index d16415f..a0449d5 100644
--- a/include/clocksource/samsung_pwm.h
+++ b/include/clocksource/samsung_pwm.h
@@ -38,6 +38,7 @@ struct samsung_pwm {
int irq[SAMSUNG_PWM_NUM];
};
+extern void samsung_pwm_clocksource_init(struct platform_device *);
extern struct samsung_pwm *samsung_pwm_get(struct platform_device *,
struct device_node *);
--
1.8.1.5
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 08/14] clocksource: samsung-pwm: Synchronize register accesses
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (6 preceding siblings ...)
2013-04-12 19:17 ` [PATCH v5 07/14] clocksource: samsung-pwm: Use platform data to setup the clocksource Tomasz Figa
@ 2013-04-12 19:17 ` Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 09/14] clocksource: samsung-pwm: Move IRQ mask/ack handling to the driver Tomasz Figa
` (10 subsequent siblings)
18 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 UTC (permalink / raw)
To: linux-arm-kernel
Since the registers of PWM block are shared between two drivers, it is
required to synchronize accesses to them. This patch introduces
necessary synchronization using spin_{un,}lock_irq{save,restore} and
a shared spinlock.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/clocksource/samsung_pwm.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/clocksource/samsung_pwm.c b/drivers/clocksource/samsung_pwm.c
index 841d03c..bddf9aa 100644
--- a/drivers/clocksource/samsung_pwm.c
+++ b/drivers/clocksource/samsung_pwm.c
@@ -299,6 +299,9 @@ static void samsung_timer_resume(void);
static void samsung_time_stop(enum samsung_timer_mode mode)
{
unsigned long tcon;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pwm->slock, flags);
tcon = __raw_readl(S3C2410_TCON);
@@ -328,11 +331,16 @@ static void samsung_time_stop(enum samsung_timer_mode mode)
break;
}
__raw_writel(tcon, S3C2410_TCON);
+
+ spin_unlock_irqrestore(&pwm->slock, flags);
}
static void samsung_time_setup(enum samsung_timer_mode mode, unsigned long tcnt)
{
unsigned long tcon;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pwm->slock, flags);
tcon = __raw_readl(S3C2410_TCON);
@@ -372,11 +380,16 @@ static void samsung_time_setup(enum samsung_timer_mode mode, unsigned long tcnt)
__raw_writel(tcnt, S3C2410_TCNTB(mode));
__raw_writel(tcnt, S3C2410_TCMPB(mode));
__raw_writel(tcon, S3C2410_TCON);
+
+ spin_unlock_irqrestore(&pwm->slock, flags);
}
static void samsung_time_start(enum samsung_timer_mode mode, bool periodic)
{
unsigned long tcon;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pwm->slock, flags);
tcon = __raw_readl(S3C2410_TCON);
@@ -436,6 +449,8 @@ static void samsung_time_start(enum samsung_timer_mode mode, bool periodic)
break;
}
__raw_writel(tcon, S3C2410_TCON);
+
+ spin_unlock_irqrestore(&pwm->slock, flags);
}
static int samsung_set_next_event(unsigned long cycles,
--
1.8.1.5
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 09/14] clocksource: samsung-pwm: Move IRQ mask/ack handling to the driver
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (7 preceding siblings ...)
2013-04-12 19:17 ` [PATCH v5 08/14] clocksource: samsung-pwm: Synchronize register accesses Tomasz Figa
@ 2013-04-12 19:17 ` Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 10/14] ARM: SAMSUNG: Remove unused PWM timer IRQ chip code Tomasz Figa
` (9 subsequent siblings)
18 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 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 changes the way of PWM timer interrupt handling to use
real VIC/GIC interrupt requests and handle PWM mask/ack register
internally in samsung-pwm clocksource 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_pwm.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 b6dd4cb..287545f 100644
--- a/arch/arm/mach-s3c24xx/include/mach/irqs.h
+++ b/arch/arm/mach-s3c24xx/include/mach/irqs.h
@@ -205,6 +205,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 89d2823..4cb9afe6 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 fbfabd2..68b163a 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -1162,20 +1162,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_pwm.c b/drivers/clocksource/samsung_pwm.c
index bddf9aa..3219ecc 100644
--- a/drivers/clocksource/samsung_pwm.c
+++ b/drivers/clocksource/samsung_pwm.c
@@ -509,6 +509,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;
@@ -545,6 +550,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] 29+ messages in thread
* [PATCH v5 10/14] ARM: SAMSUNG: Remove unused PWM timer IRQ chip code
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (8 preceding siblings ...)
2013-04-12 19:17 ` [PATCH v5 09/14] clocksource: samsung-pwm: Move IRQ mask/ack handling to the driver Tomasz Figa
@ 2013-04-12 19:17 ` Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 11/14] clocksource: samsung-pwm: Configure dividers directly Tomasz Figa
` (8 subsequent siblings)
18 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 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 a957aa0..648eda3 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 4cb9afe6..e79ca92 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] 29+ messages in thread
* [PATCH v5 11/14] clocksource: samsung-pwm: Configure dividers directly
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (9 preceding siblings ...)
2013-04-12 19:17 ` [PATCH v5 10/14] ARM: SAMSUNG: Remove unused PWM timer IRQ chip code Tomasz Figa
@ 2013-04-12 19:17 ` Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 12/14] clocksource: samsung-pwm: Do not use static mapping of registers Tomasz Figa
` (7 subsequent siblings)
18 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 UTC (permalink / raw)
To: linux-arm-kernel
Clock dividers present in the PWM blocks are used to generate signal for
PWM timers internally, so there is no need to export them using clock
API.
This patch moves handling of those dividers to the clocksource driver to
not use the clock API anymore.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/clocksource/samsung_pwm.c | 111 ++++++++++++++++++++------------------
1 file changed, 60 insertions(+), 51 deletions(-)
diff --git a/drivers/clocksource/samsung_pwm.c b/drivers/clocksource/samsung_pwm.c
index 3219ecc..29b480a 100644
--- a/drivers/clocksource/samsung_pwm.c
+++ b/drivers/clocksource/samsung_pwm.c
@@ -277,6 +277,15 @@ EXPORT_SYMBOL(samsung_pwm_get);
* Clocksource driver
*/
+#define REG_TCFG0 0x00
+#define REG_TCFG1 0x04
+
+#define TCFG0_PRESCALER_MASK 0xff
+#define TCFG0_PRESCALER1_SHIFT 8
+
+#define TCFG1_SHIFT(x) ((x) * 4)
+#define TCFG1_MUX_MASK 0xf
+
struct samsung_timer_source {
unsigned int event_id;
unsigned int source_id;
@@ -286,16 +295,51 @@ 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;
static void samsung_timer_resume(void);
+static void samsung_timer_set_prescale(struct samsung_pwm *pwm,
+ unsigned int channel, u16 prescale)
+{
+ unsigned long flags;
+ u8 shift = 0;
+ u32 reg;
+
+ if (channel >= 2)
+ shift = TCFG0_PRESCALER1_SHIFT;
+
+ spin_lock_irqsave(&pwm->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(&pwm->slock, flags);
+}
+
+static void samsung_timer_set_divisor(struct samsung_pwm *pwm,
+ unsigned int channel, u8 divisor)
+{
+ u8 shift = TCFG1_SHIFT(channel);
+ unsigned long flags;
+ u32 reg;
+ u8 bits;
+
+ bits = (fls(divisor) - 1) - pwm->variant.div_base;
+
+ spin_lock_irqsave(&pwm->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(&pwm->slock, flags);
+}
+
static void samsung_time_stop(enum samsung_timer_mode mode)
{
unsigned long tcon;
@@ -531,18 +575,15 @@ 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.tdiv * timer_source.tscaler_div));
- clk_set_parent(tin_event, tdiv_event);
+ samsung_timer_set_prescale(pwm, timer_source.event_id,
+ timer_source.tscaler_div);
+ samsung_timer_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);
@@ -607,11 +648,12 @@ static void __init samsung_clocksource_init(void)
pclk = clk_get_rate(timerclk);
- clk_set_rate(tdiv_source,
- pclk / (timer_source.tdiv * timer_source.tscaler_div));
- clk_set_parent(tin_source, tdiv_source);
+ samsung_timer_set_prescale(pwm, timer_source.source_id,
+ timer_source.tscaler_div);
+ samsung_timer_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);
@@ -628,44 +670,11 @@ 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);
+ 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] 29+ messages in thread
* [PATCH v5 12/14] clocksource: samsung-pwm: Do not use static mapping of registers
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (10 preceding siblings ...)
2013-04-12 19:17 ` [PATCH v5 11/14] clocksource: samsung-pwm: Configure dividers directly Tomasz Figa
@ 2013-04-12 19:17 ` Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 13/14] clocksource: samsung-pwm: Drop unnecessary includes Tomasz Figa
` (6 subsequent siblings)
18 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 UTC (permalink / raw)
To: linux-arm-kernel
This patch modifies the samsung-pwm clocksource driver to use registers
through the dynamic mapping created by the master driver, instead of
static, hardcoded mapping.
By the way, register definitions and accesses are cleaned up.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/clocksource/samsung_pwm.c | 190 ++++++++++----------------------------
1 file changed, 50 insertions(+), 140 deletions(-)
diff --git a/drivers/clocksource/samsung_pwm.c b/drivers/clocksource/samsung_pwm.c
index 29b480a..99c376d 100644
--- a/drivers/clocksource/samsung_pwm.c
+++ b/drivers/clocksource/samsung_pwm.c
@@ -27,12 +27,9 @@
#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>
/*
@@ -279,6 +276,11 @@ EXPORT_SYMBOL(samsung_pwm_get);
#define REG_TCFG0 0x00
#define REG_TCFG1 0x04
+#define REG_TCON 0x08
+#define REG_TINT_CSTAT 0x44
+
+#define REG_TCNTB(chan) (0x0c + 12 * (chan))
+#define REG_TCMPB(chan) (0x10 + 12 * (chan))
#define TCFG0_PRESCALER_MASK 0xff
#define TCFG0_PRESCALER1_SHIFT 8
@@ -286,6 +288,11 @@ EXPORT_SYMBOL(samsung_pwm_get);
#define TCFG1_SHIFT(x) ((x) * 4)
#define TCFG1_MUX_MASK 0xf
+#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))
+
struct samsung_timer_source {
unsigned int event_id;
unsigned int source_id;
@@ -340,159 +347,69 @@ static void samsung_timer_set_divisor(struct samsung_pwm *pwm,
spin_unlock_irqrestore(&pwm->slock, flags);
}
-static void samsung_time_stop(enum samsung_timer_mode mode)
+static void samsung_time_stop(unsigned int channel)
{
unsigned long tcon;
unsigned long flags;
- spin_lock_irqsave(&pwm->slock, flags);
-
- 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;
+ if (channel > 0)
+ ++channel;
- case SAMSUNG_PWM3:
- tcon &= ~S3C2410_TCON_T3START;
- break;
-
- case SAMSUNG_PWM4:
- tcon &= ~S3C2410_TCON_T4START;
- break;
+ spin_lock_irqsave(&pwm->slock, flags);
- default:
- printk(KERN_ERR "Invalid Timer %d\n", mode);
- break;
- }
- __raw_writel(tcon, S3C2410_TCON);
+ tcon = __raw_readl(pwm->base + REG_TCON);
+ tcon &= ~TCON_START(channel);
+ __raw_writel(tcon, pwm->base + REG_TCON);
spin_unlock_irqrestore(&pwm->slock, flags);
}
-static void samsung_time_setup(enum samsung_timer_mode mode, unsigned long tcnt)
+static void samsung_time_setup(unsigned int channel, unsigned long tcnt)
{
unsigned long tcon;
unsigned long flags;
+ unsigned int tcon_chan = channel;
+
+ if (tcon_chan > 0)
+ ++tcon_chan;
spin_lock_irqsave(&pwm->slock, flags);
- tcon = __raw_readl(S3C2410_TCON);
+ tcon = __raw_readl(pwm->base + REG_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;
+ tcon &= ~(TCON_START(tcon_chan) | TCON_AUTORELOAD(tcon_chan));
+ tcon |= TCON_MANUALUPDATE(tcon_chan);
- 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);
+ __raw_writel(tcnt, pwm->base + REG_TCNTB(channel));
+ __raw_writel(tcnt, pwm->base + REG_TCMPB(channel));
+ __raw_writel(tcon, pwm->base + REG_TCON);
spin_unlock_irqrestore(&pwm->slock, flags);
}
-static void samsung_time_start(enum samsung_timer_mode mode, bool periodic)
+static void samsung_time_start(unsigned int channel, bool periodic)
{
unsigned long tcon;
unsigned long flags;
- spin_lock_irqsave(&pwm->slock, flags);
-
- 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 (channel > 0)
+ ++channel;
- if (periodic)
- tcon |= S3C2410_TCON_T2RELOAD;
- else
- tcon &= ~S3C2410_TCON_T2RELOAD;
- break;
+ spin_lock_irqsave(&pwm->slock, flags);
- case SAMSUNG_PWM3:
- tcon |= S3C2410_TCON_T3START;
- tcon &= ~S3C2410_TCON_T3MANUALUPD;
+ tcon = __raw_readl(pwm->base + REG_TCON);
- if (periodic)
- tcon |= S3C2410_TCON_T3RELOAD;
- else
- tcon &= ~S3C2410_TCON_T3RELOAD;
- break;
+ tcon &= ~TCON_MANUALUPDATE(channel);
+ tcon |= TCON_START(channel);
- case SAMSUNG_PWM4:
- tcon |= S3C2410_TCON_T4START;
- tcon &= ~S3C2410_TCON_T4MANUALUPD;
+ if (periodic)
+ tcon |= TCON_AUTORELOAD(channel);
+ else
+ tcon &= ~TCON_AUTORELOAD(channel);
- 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);
+ __raw_writel(tcon, pwm->base + REG_TCON);
spin_unlock_irqrestore(&pwm->slock, flags);
}
@@ -555,7 +472,7 @@ static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id)
if (pwm->variant.has_tint_cstat) {
u32 mask = (1 << timer_source.event_id);
- writel(mask | (mask << 5), S3C64XX_TINT_CSTAT);
+ writel(mask | (mask << 5), pwm->base + REG_TINT_CSTAT);
}
evt->event_handler(evt);
@@ -594,32 +511,25 @@ static void __init samsung_clockevent_init(void)
if (pwm->variant.has_tint_cstat) {
u32 mask = (1 << timer_source.event_id);
- writel(mask | (mask << 5), S3C64XX_TINT_CSTAT);
+ writel(mask | (mask << 5), pwm->base + REG_TINT_CSTAT);
}
}
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 0:
+ case 1:
+ case 2:
+ case 3:
+ return pwm->base + timer_source.source_id * 0x0c + 0x14;
- case SAMSUNG_PWM4:
- offset = 0x40;
- break;
+ case 4:
+ return pwm->base + 0x40;
default:
- printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
- return NULL;
+ BUG();
}
-
- return S3C_TIMERREG(offset);
}
/*
--
1.8.1.5
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 13/14] clocksource: samsung-pwm: Drop unnecessary includes
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (11 preceding siblings ...)
2013-04-12 19:17 ` [PATCH v5 12/14] clocksource: samsung-pwm: Do not use static mapping of registers Tomasz Figa
@ 2013-04-12 19:17 ` Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 14/14] clocksource: samsung-pwm: Prepare for clocksource_of_init Tomasz Figa
` (5 subsequent siblings)
18 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 UTC (permalink / raw)
To: linux-arm-kernel
This patch removes unneccessary header inclusions from the samsung-pwm
clocksource driver.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/clocksource/samsung_pwm.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/drivers/clocksource/samsung_pwm.c b/drivers/clocksource/samsung_pwm.c
index 99c376d..b816b65 100644
--- a/drivers/clocksource/samsung_pwm.c
+++ b/drivers/clocksource/samsung_pwm.c
@@ -24,14 +24,8 @@
#include <clocksource/samsung_pwm.h>
-#include <asm/smp_twd.h>
-#include <asm/mach/time.h>
-#include <asm/mach/arch.h>
#include <asm/sched_clock.h>
-#include <plat/devs.h>
-#include <plat/samsung-time.h>
-
/*
* PWM master driver
*/
--
1.8.1.5
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 14/14] clocksource: samsung-pwm: Prepare for clocksource_of_init
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (12 preceding siblings ...)
2013-04-12 19:17 ` [PATCH v5 13/14] clocksource: samsung-pwm: Drop unnecessary includes Tomasz Figa
@ 2013-04-12 19:17 ` Tomasz Figa
2013-04-12 20:51 ` [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Arnd Bergmann
` (4 subsequent siblings)
18 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 19:17 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds support for clocksource instantiation using
clocksource_of_init, by declaring OF clocksources with
CLOCKSOURCE_OF_DECLARE() macro.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/clocksource/samsung_pwm.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/clocksource/samsung_pwm.c b/drivers/clocksource/samsung_pwm.c
index b816b65..a12ee08 100644
--- a/drivers/clocksource/samsung_pwm.c
+++ b/drivers/clocksource/samsung_pwm.c
@@ -590,12 +590,13 @@ static void __init samsung_timer_resources(void)
}
}
-void __init samsung_pwm_clocksource_init(struct platform_device *pdev)
+static void __init __samsung_pwm_clocksource_init(
+ struct platform_device *pdev, struct device_node *np)
{
u8 mask;
int channel;
- pwm = samsung_pwm_get(pdev, NULL);
+ pwm = samsung_pwm_get(pdev, np);
if (IS_ERR(pwm))
panic("failed to get PWM device");
@@ -615,3 +616,21 @@ void __init samsung_pwm_clocksource_init(struct platform_device *pdev)
samsung_clockevent_init();
samsung_clocksource_init();
}
+
+static void __init samsung_pwm_clocksource_init_of(struct device_node *np)
+{
+ __samsung_pwm_clocksource_init(NULL, np);
+}
+CLOCKSOURCE_OF_DECLARE(s3c2410_pwm, "samsung,s3c2410-pwm",
+ samsung_pwm_clocksource_init_of);
+CLOCKSOURCE_OF_DECLARE(s3c6400_pwm, "samsung,s3c6400-pwm",
+ samsung_pwm_clocksource_init_of);
+CLOCKSOURCE_OF_DECLARE(s5p6440_pwm, "samsung,s5p6440-pwm",
+ samsung_pwm_clocksource_init_of);
+CLOCKSOURCE_OF_DECLARE(s5pc100_pwm, "samsung,s5pc100-pwm",
+ samsung_pwm_clocksource_init_of);
+
+void __init samsung_pwm_clocksource_init(struct platform_device *pdev)
+{
+ __samsung_pwm_clocksource_init(pdev, NULL);
+}
--
1.8.1.5
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 03/14] clocksource: samsung-pwm: Add infrastructure to share PWM hardware
2013-04-12 19:17 ` [PATCH v5 03/14] clocksource: samsung-pwm: Add infrastructure to share PWM hardware Tomasz Figa
@ 2013-04-12 20:42 ` Arnd Bergmann
2013-04-12 20:47 ` Tomasz Figa
0 siblings, 1 reply; 29+ messages in thread
From: Arnd Bergmann @ 2013-04-12 20:42 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 12 April 2013, Tomasz Figa wrote:
> +
> +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).
> +
...
> +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.
> +
There is probably a good reason, but can you explain why this is actually required
to be a property? Wouldn't it be enough to just not refer to the PWM outputs from
other devices when they are not used?
Arnd
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v5 01/14] ARM: SAMSUNG: Move samsung-time to drivers/clocksource
2013-04-12 19:17 ` [PATCH v5 01/14] ARM: SAMSUNG: Move samsung-time to drivers/clocksource Tomasz Figa
@ 2013-04-12 20:44 ` Arnd Bergmann
2013-04-12 20:52 ` Tomasz Figa
0 siblings, 1 reply; 29+ messages in thread
From: Arnd Bergmann @ 2013-04-12 20:44 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 12 April 2013, Tomasz Figa wrote:
> ---
> 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_pwm.c | 394 +++++++++++++++++++++++++++++++++++
In general, please send patches generated with 'git format-patch -M'. You can
set that as a default using 'git config diff.renames true'.
Arnd
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v5 03/14] clocksource: samsung-pwm: Add infrastructure to share PWM hardware
2013-04-12 20:42 ` Arnd Bergmann
@ 2013-04-12 20:47 ` Tomasz Figa
0 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 20:47 UTC (permalink / raw)
To: linux-arm-kernel
Hi Arnd,
On Friday 12 of April 2013 22:42:36 Arnd Bergmann wrote:
> On Friday 12 April 2013, Tomasz Figa wrote:
> > +
> > +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).
> > +
>
> ...
>
> > +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.
> > +
>
> There is probably a good reason, but can you explain why this is
> actually required to be a property? Wouldn't it be enough to just not
> refer to the PWM outputs from other devices when they are not used?
It is needed for the clocksource driver, to select unused channels for
clocksource and clock event purposes.
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (13 preceding siblings ...)
2013-04-12 19:17 ` [PATCH v5 14/14] clocksource: samsung-pwm: Prepare for clocksource_of_init Tomasz Figa
@ 2013-04-12 20:51 ` Arnd Bergmann
2013-04-22 17:37 ` Kukjin Kim
2013-04-12 22:22 ` Heiko Stübner
` (3 subsequent siblings)
18 siblings, 1 reply; 29+ messages in thread
From: Arnd Bergmann @ 2013-04-12 20:51 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 12 April 2013, 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.
>
> The samsung_pwm clocksource driver is made the master driver, which
> exposes a single function to the PWM driver to get required data. 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.
Acked-by: Arnd Bergmann <arnd@arndb.de>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v5 01/14] ARM: SAMSUNG: Move samsung-time to drivers/clocksource
2013-04-12 20:44 ` Arnd Bergmann
@ 2013-04-12 20:52 ` Tomasz Figa
0 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 20:52 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 12 of April 2013 22:44:03 Arnd Bergmann wrote:
> On Friday 12 April 2013, Tomasz Figa wrote:
> > ---
> >
> > 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_pwm.c | 394
> > +++++++++++++++++++++++++++++++++++
> In general, please send patches generated with 'git format-patch -M'.
> You can set that as a default using 'git config diff.renames true'.
Oops, I forgot to add the switch, sorry. Setting it as default might be a
good idea indeed.
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (14 preceding siblings ...)
2013-04-12 20:51 ` [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Arnd Bergmann
@ 2013-04-12 22:22 ` Heiko Stübner
2013-04-12 22:26 ` Arnd Bergmann
2013-04-13 12:28 ` Tomasz Figa
` (2 subsequent siblings)
18 siblings, 1 reply; 29+ messages in thread
From: Heiko Stübner @ 2013-04-12 22:22 UTC (permalink / raw)
To: linux-arm-kernel
Hi Tomasz,
Am Freitag, 12. April 2013, 21:17:16 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.
>
> The samsung_pwm clocksource driver is made the master driver, which
> exposes a single function to the PWM driver to get required data. 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.
On a s3c2416 based board with both non-dt and preliminary-dt support
Tested-by: Heiko Stuebner <heiko@sntech.de>
One nitpick:
Without dt support, you get this:
CC drivers/clocksource/samsung_pwm.o
drivers/clocksource/samsung_pwm.c:620: warning: ?samsung_pwm_clocksource_init_of? defined but not used
So, something like the following might be necessary
-------------- 8< -------------------
diff --git a/drivers/clocksource/samsung_pwm.c b/drivers/clocksource/samsung_pwm.c
index a12ee08..2bf8303 100644
--- a/drivers/clocksource/samsung_pwm.c
+++ b/drivers/clocksource/samsung_pwm.c
@@ -617,6 +617,7 @@ static void __init __samsung_pwm_clocksource_init(
samsung_clocksource_init();
}
+#ifdef CONFIG_CLKSRC_OF
static void __init samsung_pwm_clocksource_init_of(struct device_node *np)
{
__samsung_pwm_clocksource_init(NULL, np);
@@ -629,6 +630,7 @@ CLOCKSOURCE_OF_DECLARE(s5p6440_pwm, "samsung,s5p6440-pwm",
samsung_pwm_clocksource_init_of);
CLOCKSOURCE_OF_DECLARE(s5pc100_pwm, "samsung,s5pc100-pwm",
samsung_pwm_clocksource_init_of);
+#endif
void __init samsung_pwm_clocksource_init(struct platform_device *pdev)
{
-------------- 8< -------------------
Heiko
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support
2013-04-12 22:22 ` Heiko Stübner
@ 2013-04-12 22:26 ` Arnd Bergmann
2013-04-12 22:39 ` Heiko Stübner
0 siblings, 1 reply; 29+ messages in thread
From: Arnd Bergmann @ 2013-04-12 22:26 UTC (permalink / raw)
To: linux-arm-kernel
On Saturday 13 April 2013 00:22:48 Heiko St?bner wrote:
>
> Without dt support, you get this:
>
> CC drivers/clocksource/samsung_pwm.o
> drivers/clocksource/samsung_pwm.c:620: warning: ?samsung_pwm_clocksource_init_of? defined but not used
>
> So, something like the following might be necessary
That patch should not be required any more with the definition
#ifdef CONFIG_CLKSRC_OF
extern void clocksource_of_init(void);
#define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \
static const struct of_device_id __clksrc_of_table_##name \
__used __section(__clksrc_of_table) \
= { .compatible = compat, \
.data = (fn == (clocksource_of_init_fn)NULL) ? fn : fn }
#else
static inline void clocksource_of_init(void) {}
#define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \
static const struct of_device_id __clksrc_of_table_##name \
__attribute__((unused)) \
= { .compatible = compat, \
.data = (fn == (clocksource_of_init_fn)NULL) ? fn : fn }
#endif
which turns the ?samsung_pwm_clocksource_init_of? function into an unused
symbol that gets silently dropped by gcc, at least in theory. Are you
using the latest clksrc/cleanup branch as a base?
Arnd
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support
2013-04-12 22:26 ` Arnd Bergmann
@ 2013-04-12 22:39 ` Heiko Stübner
2013-04-12 22:42 ` Tomasz Figa
0 siblings, 1 reply; 29+ messages in thread
From: Heiko Stübner @ 2013-04-12 22:39 UTC (permalink / raw)
To: linux-arm-kernel
Am Samstag, 13. April 2013, 00:26:43 schrieb Arnd Bergmann:
> On Saturday 13 April 2013 00:22:48 Heiko St?bner wrote:
> > Without dt support, you get this:
> > CC drivers/clocksource/samsung_pwm.o
> >
> > drivers/clocksource/samsung_pwm.c:620: warning:
> > ?samsung_pwm_clocksource_init_of? defined but not used
> >
> > So, something like the following might be necessary
>
> That patch should not be required any more with the definition
>
> #ifdef CONFIG_CLKSRC_OF
> extern void clocksource_of_init(void);
>
> #define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \
> static const struct of_device_id __clksrc_of_table_##name \
> __used __section(__clksrc_of_table) \
> = { .compatible = compat, \
> .data = (fn == (clocksource_of_init_fn)NULL) ? fn : fn
> } #else
> static inline void clocksource_of_init(void) {}
> #define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \
> static const struct of_device_id __clksrc_of_table_##name \
> __attribute__((unused)) \
> = { .compatible = compat, \
> .data = (fn == (clocksource_of_init_fn)NULL) ? fn : fn
> } #endif
>
> which turns the ?samsung_pwm_clocksource_init_of? function into an unused
> symbol that gets silently dropped by gcc, at least in theory. Are you
> using the latest clksrc/cleanup branch as a base?
Nope, I just put the stuff on top of all the other changes. So it seems
everything is fine and working ... very nice :-)
Heiko
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support
2013-04-12 22:39 ` Heiko Stübner
@ 2013-04-12 22:42 ` Tomasz Figa
0 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-12 22:42 UTC (permalink / raw)
To: linux-arm-kernel
On Saturday 13 of April 2013 00:39:24 Heiko St?bner wrote:
> Am Samstag, 13. April 2013, 00:26:43 schrieb Arnd Bergmann:
> > On Saturday 13 April 2013 00:22:48 Heiko St?bner wrote:
> > > Without dt support, you get this:
> > > CC drivers/clocksource/samsung_pwm.o
> > >
> > > drivers/clocksource/samsung_pwm.c:620: warning:
> > > ?samsung_pwm_clocksource_init_of? defined but not used
> > >
> > > So, something like the following might be necessary
> >
> > That patch should not be required any more with the definition
> >
> > #ifdef CONFIG_CLKSRC_OF
> > extern void clocksource_of_init(void);
> >
> > #define CLOCKSOURCE_OF_DECLARE(name, compat, fn)
> > \>
> > static const struct of_device_id __clksrc_of_table_##name
> > \
> >
> > __used __section(__clksrc_of_table)
> > \
> >
> > = { .compatible = compat,
> > \
> >
> > .data = (fn == (clocksource_of_init_fn)NULL) ? fn
> > : fn
> >
> > } #else
> > static inline void clocksource_of_init(void) {}
> > #define CLOCKSOURCE_OF_DECLARE(name, compat, fn)
> > \>
> > static const struct of_device_id __clksrc_of_table_##name
> > \
> >
> > __attribute__((unused))
> > \
> >
> > = { .compatible = compat,
> > \
> >
> > .data = (fn == (clocksource_of_init_fn)NULL) ? fn
> > : fn
> >
> > } #endif
> >
> > which turns the ?samsung_pwm_clocksource_init_of? function into an
> > unused symbol that gets silently dropped by gcc, at least in theory.
> > Are you using the latest clksrc/cleanup branch as a base?
>
> Nope, I just put the stuff on top of all the other changes. So it seems
> everything is fine and working ... very nice :-)
Great. Thanks for testing.
I will try to rebase my patches for s3c64xx on top of this and do some
testing as well.
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (15 preceding siblings ...)
2013-04-12 22:22 ` Heiko Stübner
@ 2013-04-13 12:28 ` Tomasz Figa
2013-04-16 16:22 ` Mark Brown
2013-04-16 20:51 ` Sylwester Nawrocki
18 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-13 12:28 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 12 of April 2013 21:17:16 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.
>
> The samsung_pwm clocksource driver is made the master driver, which
> exposes a single function to the PWM driver to get required data. 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 v4:
> (http://thread.gmane.org/gmane.linux.kernel.samsung-soc/17464)
> - Changed the design again - now clocksource driver is considered the
> master and exports a single function to get access to things like base
> address, hardware variant information, shared spinlock for register
> access synchronization and interrupt numbers
> - Renamed the clocksource driver to samsung_pwm
> - Cleaned up the code a bit more
> - Added clocksource_of_init support
>
> 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-pwm: Clean up platform header
> clocksource: samsung-pwm: Add infrastructure to share PWM hardware
> ARM: SAMSUNG: Unify base address definitions of timer block
> ARM: SAMSUNG: Add new PWM platform device
> ARM: SAMSUNG: Set PWM platform data
> clocksource: samsung-pwm: Use platform data to setup the clocksource
> clocksource: samsung-pwm: Synchronize register accesses
> clocksource: samsung-pwm: Move IRQ mask/ack handling to the driver
> ARM: SAMSUNG: Remove unused PWM timer IRQ chip code
> clocksource: samsung-pwm: Configure dividers directly
> clocksource: samsung-pwm: Do not use static mapping of registers
> clocksource: samsung-pwm: Drop unnecessary includes
> clocksource: samsung-pwm: Prepare for clocksource_of_init
On S3C6410-based Tiny6410 (Mini6410-compatible) board, both with and
without Device Tree:
Tested-by: Tomasz Figa <tomasz.figa@gmail.com>
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (16 preceding siblings ...)
2013-04-13 12:28 ` Tomasz Figa
@ 2013-04-16 16:22 ` Mark Brown
2013-04-16 20:51 ` Sylwester Nawrocki
18 siblings, 0 replies; 29+ messages in thread
From: Mark Brown @ 2013-04-16 16:22 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Apr 12, 2013 at 09:17:16PM +0200, 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.
Tested-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-------------- 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/20130416/4c95907a/attachment-0001.sig>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
` (17 preceding siblings ...)
2013-04-16 16:22 ` Mark Brown
@ 2013-04-16 20:51 ` Sylwester Nawrocki
18 siblings, 0 replies; 29+ messages in thread
From: Sylwester Nawrocki @ 2013-04-16 20:51 UTC (permalink / raw)
To: linux-arm-kernel
On 04/12/2013 09:17 PM, 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.
>
> The samsung_pwm clocksource driver is made the master driver, which
> exposes a single function to the PWM driver to get required data. 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.
On s3c2440 based board
Tested-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support
2013-04-12 20:51 ` [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Arnd Bergmann
@ 2013-04-22 17:37 ` Kukjin Kim
2013-04-22 19:21 ` Tomasz Figa
0 siblings, 1 reply; 29+ messages in thread
From: Kukjin Kim @ 2013-04-22 17:37 UTC (permalink / raw)
To: linux-arm-kernel
On 04/13/13 05:51, Arnd Bergmann wrote:
> On Friday 12 April 2013, 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.
>>
>> The samsung_pwm clocksource driver is made the master driver, which
>> exposes a single function to the PWM driver to get required data. 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.
>
> Acked-by: Arnd Bergmann<arnd@arndb.de>
Applied, this whole series.
Thanks.
- Kukjin
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support
2013-04-22 17:37 ` Kukjin Kim
@ 2013-04-22 19:21 ` Tomasz Figa
0 siblings, 0 replies; 29+ messages in thread
From: Tomasz Figa @ 2013-04-22 19:21 UTC (permalink / raw)
To: linux-arm-kernel
On Tuesday 23 of April 2013 02:37:33 Kukjin Kim wrote:
> On 04/13/13 05:51, Arnd Bergmann wrote:
> > On Friday 12 April 2013, 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.
> >>
> >> The samsung_pwm clocksource driver is made the master driver, which
> >> exposes a single function to the PWM driver to get required data.
> >> 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.
> >
> > Acked-by: Arnd Bergmann<arnd@arndb.de>
>
> Applied, this whole series.
It would be nice if we could still get this for 3.10, but AFAIK it is
already much too late.
I've discussed this matter with Arnd and the solution that can be accepted
by arm-soc maintainers is to send a subset of this series, like in the
patch sent by Arnd (clocksource: add samsung pwm timer driver; it needs
additional fixes, though.).
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2013-04-22 19:21 UTC | newest]
Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-12 19:17 [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 01/14] ARM: SAMSUNG: Move samsung-time to drivers/clocksource Tomasz Figa
2013-04-12 20:44 ` Arnd Bergmann
2013-04-12 20:52 ` Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 02/14] clocksource: samsung-pwm: Clean up platform header Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 03/14] clocksource: samsung-pwm: Add infrastructure to share PWM hardware Tomasz Figa
2013-04-12 20:42 ` Arnd Bergmann
2013-04-12 20:47 ` Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 04/14] ARM: SAMSUNG: Unify base address definitions of timer block Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 05/14] ARM: SAMSUNG: Add new PWM platform device Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 06/14] ARM: SAMSUNG: Set PWM platform data Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 07/14] clocksource: samsung-pwm: Use platform data to setup the clocksource Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 08/14] clocksource: samsung-pwm: Synchronize register accesses Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 09/14] clocksource: samsung-pwm: Move IRQ mask/ack handling to the driver Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 10/14] ARM: SAMSUNG: Remove unused PWM timer IRQ chip code Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 11/14] clocksource: samsung-pwm: Configure dividers directly Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 12/14] clocksource: samsung-pwm: Do not use static mapping of registers Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 13/14] clocksource: samsung-pwm: Drop unnecessary includes Tomasz Figa
2013-04-12 19:17 ` [PATCH v5 14/14] clocksource: samsung-pwm: Prepare for clocksource_of_init Tomasz Figa
2013-04-12 20:51 ` [PATCH v5 00/14] ARM: samsung-time: Prepare for multiplatform support Arnd Bergmann
2013-04-22 17:37 ` Kukjin Kim
2013-04-22 19:21 ` Tomasz Figa
2013-04-12 22:22 ` Heiko Stübner
2013-04-12 22:26 ` Arnd Bergmann
2013-04-12 22:39 ` Heiko Stübner
2013-04-12 22:42 ` Tomasz Figa
2013-04-13 12:28 ` Tomasz Figa
2013-04-16 16:22 ` Mark Brown
2013-04-16 20:51 ` Sylwester Nawrocki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).