From: Arnd Bergmann <arnd@arndb.de>
To: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org, Kukjin Kim <kgene.kim@samsung.com>,
linux-samsung-soc@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>,
Tomasz Figa <t.figa@samsung.com>,
Thierry Reding <thierry.reding@avionic-design.de>
Subject: [PATCH 17/30] pwm: samsung: repair the worst MMIO abuses
Date: Thu, 11 Apr 2013 02:04:59 +0200 [thread overview]
Message-ID: <1365638712-1028578-18-git-send-email-arnd@arndb.de> (raw)
In-Reply-To: <1365638712-1028578-1-git-send-email-arnd@arndb.de>
The Samsung PWM driver uses "magic" pointers that are mapped
at boot time to point its MMIO registers. This fails horribly
with a multiplatform kernel, which can not rely on platform
specific header files to contain the right values, aside from
this being a really bad idea in general.
This changes the driver to at least pass an __iomem token
around in the device structure to dereference that. Fixing
the platform code is much harder, so we'll leave that
until we have a DT binding for pwm-samsung, which may require
other changes in this area. Since we are already touching
every MMIO accessor in this driver, let's also use the
proper readl_relaxed variant rather than __raw_readl.
Tomasz Figa has a set of patches to clean this up in a proper
way, but that might be too late for 3.10.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Tomasz Figa <t.figa@samsung.com>
Cc: Thierry Reding <thierry.reding@avionic-design.de>
---
drivers/pwm/pwm-samsung.c | 60 +++++++++++++++++++++++++++++++++--------------
1 file changed, 42 insertions(+), 18 deletions(-)
diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
index 5207e6c..9d7234d 100644
--- a/drivers/pwm/pwm-samsung.c
+++ b/drivers/pwm/pwm-samsung.c
@@ -22,9 +22,25 @@
#include <linux/io.h>
#include <linux/pwm.h>
-#include <mach/map.h>
+#ifndef CONFIG_ARCH_MULTIPLATFORM
+/*
+ * This is gross: the platform maps the timer at a fixed
+ * virtual address and expects us to use that address
+ * rather than a proper resource. This should get done properly
+ * when we get a DT binding for this driver.
+ */
+#include <plat/map-base.h>
+static inline void dummy(void)
+{
+ BUILD_BUG_ON(S3C_VA_TIMER != IOMEM(0xf6300000));
+}
+#else
+#define S3C_VA_TIMER IOMEM(0xf6300000);
+#endif
-#include <plat/regs-timer.h>
+#define S3C2410_TCON 8
+#define S3C2410_TCNTB(tmr) (0x0c + (tmr)*0x0c + 0x00)
+#define S3C2410_TCMPB(tmr) (0x0c + (tmr)*0x0c + 0x04)
struct s3c_chip {
struct platform_device *pdev;
@@ -38,6 +54,7 @@ struct s3c_chip {
unsigned char tcon_base;
unsigned char pwm_id;
+ void __iomem *base;
struct pwm_chip chip;
};
@@ -65,9 +82,9 @@ static int s3c_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
local_irq_save(flags);
- tcon = __raw_readl(S3C2410_TCON);
+ tcon = readl_relaxed(s3c->base + S3C2410_TCON);
tcon |= pwm_tcon_start(s3c);
- __raw_writel(tcon, S3C2410_TCON);
+ writel_relaxed(tcon, s3c->base + S3C2410_TCON);
local_irq_restore(flags);
@@ -82,9 +99,9 @@ static void s3c_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
local_irq_save(flags);
- tcon = __raw_readl(S3C2410_TCON);
+ tcon = readl_relaxed(s3c->base + S3C2410_TCON);
tcon &= ~pwm_tcon_start(s3c);
- __raw_writel(tcon, S3C2410_TCON);
+ writel_relaxed(tcon, s3c->base + S3C2410_TCON);
local_irq_restore(flags);
}
@@ -133,8 +150,8 @@ static int s3c_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
/* The TCMP and TCNT can be read without a lock, they're not
* shared between the timers. */
- tcmp = __raw_readl(S3C2410_TCMPB(s3c->pwm_id));
- tcnt = __raw_readl(S3C2410_TCNTB(s3c->pwm_id));
+ tcmp = readl_relaxed(s3c->base + S3C2410_TCMPB(s3c->pwm_id));
+ tcnt = readl_relaxed(s3c->base + S3C2410_TCNTB(s3c->pwm_id));
period = NS_IN_HZ / period_ns;
@@ -177,16 +194,16 @@ static int s3c_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
local_irq_save(flags);
- __raw_writel(tcmp, S3C2410_TCMPB(s3c->pwm_id));
- __raw_writel(tcnt, S3C2410_TCNTB(s3c->pwm_id));
+ writel_relaxed(tcmp, s3c->base + S3C2410_TCMPB(s3c->pwm_id));
+ writel_relaxed(tcnt, s3c->base + S3C2410_TCNTB(s3c->pwm_id));
- tcon = __raw_readl(S3C2410_TCON);
+ tcon = readl_relaxed(s3c->base + S3C2410_TCON);
tcon |= pwm_tcon_manulupdate(s3c);
tcon |= pwm_tcon_autoreload(s3c);
- __raw_writel(tcon, S3C2410_TCON);
+ writel_relaxed(tcon, s3c->base + S3C2410_TCON);
tcon &= ~pwm_tcon_manulupdate(s3c);
- __raw_writel(tcon, S3C2410_TCON);
+ writel_relaxed(tcon, s3c->base + S3C2410_TCON);
local_irq_restore(flags);
@@ -207,6 +224,7 @@ static int s3c_pwm_probe(struct platform_device *pdev)
unsigned long flags;
unsigned long tcon;
unsigned int id = pdev->id;
+ struct resource *res;
int ret;
if (id == 4) {
@@ -220,6 +238,12 @@ static int s3c_pwm_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ /* try to get a proper base address, fall back to S3C_VA_TIMER */
+ s3c->base = S3C_VA_TIMER;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res)
+ s3c->base = devm_ioremap(dev, res->start, resource_size(res));
+
/* calculate base of control bits in TCON */
s3c->tcon_base = id == 0 ? 0 : (id * 4) + 4;
s3c->pwm_id = id;
@@ -245,9 +269,9 @@ static int s3c_pwm_probe(struct platform_device *pdev)
local_irq_save(flags);
- tcon = __raw_readl(S3C2410_TCON);
+ tcon = readl_relaxed(s3c->base + S3C2410_TCON);
tcon |= pwm_tcon_invert(s3c);
- __raw_writel(tcon, S3C2410_TCON);
+ writel_relaxed(tcon, s3c->base + S3C2410_TCON);
local_irq_restore(flags);
@@ -258,7 +282,7 @@ static int s3c_pwm_probe(struct platform_device *pdev)
}
pwm_dbg(s3c, "config bits %02x\n",
- (__raw_readl(S3C2410_TCON) >> s3c->tcon_base) & 0x0f);
+ (readl_relaxed(s3c->base + S3C2410_TCON) >> s3c->tcon_base) & 0x0f);
dev_info(dev, "tin at %lu, tdiv at %lu, tin=%sclk, base %d\n",
clk_get_rate(s3c->clk),
@@ -310,9 +334,9 @@ static int s3c_pwm_resume(struct platform_device *pdev)
unsigned long tcon;
/* Restore invertion */
- tcon = __raw_readl(S3C2410_TCON);
+ tcon = readl_relaxed(s3c->base + S3C2410_TCON);
tcon |= pwm_tcon_invert(s3c);
- __raw_writel(tcon, S3C2410_TCON);
+ writel_relaxed(tcon, s3c->base + S3C2410_TCON);
return 0;
}
--
1.8.1.2
next prev parent reply other threads:[~2013-04-11 0:13 UTC|newest]
Thread overview: 71+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-11 0:04 [PATCH 00/30] ARM: exynos multiplatform support Arnd Bergmann
2013-04-11 0:04 ` [PATCH 01/30] ARM: exynos: introduce EXYNOS_ATAGS symbol Arnd Bergmann
2013-04-11 0:04 ` [PATCH 02/30] ARM: exynos: prepare for sparse IRQ Arnd Bergmann
2013-04-11 0:17 ` Kyungmin Park
2013-04-11 0:04 ` [PATCH 03/30] ARM: exynos: move debug-macro.S to include/debug/ Arnd Bergmann
2013-04-11 0:04 ` [PATCH 04/30] ARM: samsung: move mfc device definition to s5p-dev-mfc.c Arnd Bergmann
2013-04-11 0:04 ` [PATCH 05/30] tty: serial/samsung: prepare for common clock API Arnd Bergmann
2013-04-11 0:04 ` [PATCH 06/30] tty: serial/samsung: make register definitions global Arnd Bergmann
2013-04-11 0:04 ` [PATCH 07/30] tty: serial/samsung: fix modular build Arnd Bergmann
2013-04-11 0:04 ` [PATCH 08/30] i2c: s3c2410: make header file local Arnd Bergmann
2013-04-14 12:20 ` Wolfram Sang
2013-04-14 17:01 ` Heiko Stübner
2013-04-11 0:04 ` [PATCH 09/30] mmc: sdhci-s3c: remove platform dependencies Arnd Bergmann
2013-04-11 1:06 ` Chris Ball
2013-04-11 0:04 ` [PATCH 10/30] usb: exynos: do not include plat/usb-phy.h Arnd Bergmann
2013-04-11 20:25 ` Greg Kroah-Hartman
2013-04-11 20:49 ` [PATCH v3] " Arnd Bergmann
2013-04-11 0:04 ` [PATCH 11/30] [media] exynos: remove unnecessary header inclusions Arnd Bergmann
2013-04-11 0:13 ` Mauro Carvalho Chehab
2013-04-11 9:07 ` Sylwester Nawrocki
2013-04-11 10:52 ` Arnd Bergmann
2013-04-11 0:04 ` [PATCH 12/30] video/exynos: " Arnd Bergmann
2013-04-11 5:07 ` Jingoo Han
2013-04-11 11:51 ` Tomi Valkeinen
2013-04-11 12:08 ` Arnd Bergmann
2013-04-11 0:04 ` [PATCH 13/30] video/s3c: move platform_data out of arch/arm Arnd Bergmann
2013-04-11 4:34 ` Jingoo Han
2013-04-11 5:12 ` Jingoo Han
2013-04-11 0:04 ` [PATCH 14/30] thermal/exynos: remove unnecessary header inclusions Arnd Bergmann
2013-04-11 1:19 ` Eduardo Valentin
2013-04-11 23:26 ` Zhang Rui
2013-04-11 0:04 ` [PATCH 15/30] mtd: onenand/samsung: make regs-onenand.h file local Arnd Bergmann
2013-04-11 0:18 ` Kyungmin Park
2013-04-11 0:04 ` [PATCH 16/30] rtc: s3c: make header " Arnd Bergmann
2013-04-11 0:04 ` Arnd Bergmann [this message]
2013-04-12 7:06 ` [PATCH 17/30] pwm: samsung: repair the worst MMIO abuses Thierry Reding
2013-04-12 7:46 ` Tomasz Figa
2013-04-11 0:05 ` [PATCH 18/30] ASoC: samsung: move plat/ headers to local directory Arnd Bergmann
2013-04-11 16:47 ` Mark Brown
2013-04-11 17:08 ` Arnd Bergmann
2013-04-11 17:19 ` Mark Brown
2013-04-11 19:02 ` [PATCH] ASoC: samsung: fix neo1973-wm8753 compilation Heiko Stübner
2013-04-12 12:13 ` Mark Brown
2013-04-12 11:04 ` [alsa-devel] [PATCH 18/30] ASoC: samsung: move plat/ headers to local directory Lars-Peter Clausen
2013-04-12 11:26 ` Mark Brown
2013-04-11 0:05 ` [PATCH 19/30] ASoC: samsung: use irq resource for idma Arnd Bergmann
2013-04-11 16:48 ` Mark Brown
2013-04-11 0:05 ` [PATCH 20/30] ASoC: samsung: convert to dmaengine API Arnd Bergmann
2013-04-11 14:27 ` Mark Brown
2013-04-11 14:47 ` Arnd Bergmann
2013-04-11 15:42 ` Mark Brown
2013-04-12 19:27 ` [alsa-devel] " Lars-Peter Clausen
2013-04-15 11:04 ` Mark Brown
2013-04-11 0:05 ` [PATCH 21/30] ASoC: samsung/i2s: fix module_device_table Arnd Bergmann
2013-04-11 16:48 ` Mark Brown
2013-04-11 0:05 ` [PATCH 22/30] ASoC: samsung/idma: export idma_reg_addr_init Arnd Bergmann
2013-04-11 16:48 ` Mark Brown
2013-04-11 0:05 ` [PATCH 23/30] clk: exynos: prepare for multiplatform Arnd Bergmann
2013-04-11 0:05 ` [PATCH 24/30] clocksource: exynos_mct: remove platform header dependency Arnd Bergmann
2013-04-11 0:05 ` [PATCH 25/30] irqchip: exynos: pass max combiner number to combiner_init Arnd Bergmann
2013-04-11 0:05 ` [PATCH 26/30] irqchip: exynos: allocate combiner_data dynamically Arnd Bergmann
2013-04-11 0:05 ` [PATCH 27/30] irqchip: exynos: localize irq lookup for ATAGS Arnd Bergmann
2013-04-11 0:05 ` [PATCH 28/30] irqchip: exynos: pass irq_base from platform Arnd Bergmann
2013-04-11 0:05 ` [PATCH 29/30] spi: s3c64xx: move to generic dmaengine API Arnd Bergmann
2013-04-11 16:55 ` Mark Brown
2013-04-11 20:42 ` [PATCH v2] " Arnd Bergmann
2013-04-12 12:55 ` Mark Brown
2013-04-17 14:46 ` Mark Brown
2013-04-17 20:05 ` [PATCH 29/30] " Arnd Bergmann
2013-04-18 16:46 ` Mark Brown
2013-04-11 0:05 ` [PATCH 30/30] ARM: exynos: enable multiplatform support Arnd Bergmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1365638712-1028578-18-git-send-email-arnd@arndb.de \
--to=arnd@arndb.de \
--cc=kgene.kim@samsung.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-samsung-soc@vger.kernel.org \
--cc=t.figa@samsung.com \
--cc=thierry.reding@avionic-design.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).