From: Mark Brown <broonie@kernel.org>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Jiri Slaby <jslaby@suse.cz>
Cc: linux-serial@vger.kernel.org, linaro-kernel@lists.linaro.org,
Victor Kamensky <victor.kamensky@linaro.org>,
Mark Brown <broonie@linaro.org>
Subject: [PATCH] exynos: serial clear and set big endian fix
Date: Mon, 21 Jul 2014 16:50:32 +0100 [thread overview]
Message-ID: <1405957832-6444-1-git-send-email-broonie@kernel.org> (raw)
From: Victor Kamensky <victor.kamensky@linaro.org>
The Samsung serial driver uses __set_bit and __clear_bit functions
directly with h/w registers but these functions do not account for any
difference between the endianess of the CPU and the hardware so if
running in big endian mode we need to byte swap. Handle this by
wrapping these functions with open coded versions when configured for
big endian.
[Rewrote commit message -- broonie]
Signed-off-by: Victor Kamensky <victor.kamensky@linaro.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
drivers/tty/serial/samsung.c | 43 +++++++++++++++++++++++++++++++++++++++----
1 file changed, 39 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 8df6c173d6ed..7191adefe40e 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -78,6 +78,41 @@ static void dbg(const char *fmt, ...)
#define S3C24XX_SERIAL_MAJOR 204
#define S3C24XX_SERIAL_MINOR 64
+#ifndef CONFIG_CPU_BIG_ENDIAN /* little endian */
+static inline void __hw_set_bit(int nr, volatile unsigned long *addr)
+{
+ __set_bit(nr, addr);
+}
+
+static inline void __hw_clear_bit(int nr, volatile unsigned long *addr)
+{
+ __clear_bit(nr, addr);
+}
+#else
+static inline void __hw_set_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+ unsigned long val = le32_to_cpu(*p);
+
+ val |= mask;
+
+ *p = cpu_to_le32(val);
+}
+
+static inline void __hw_clear_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+
+ unsigned long val = le32_to_cpu(*p);
+
+ val &= ~mask;
+
+ *p = cpu_to_le32(val);
+}
+#endif
+
/* macros to change one thing to another */
#define tx_enabled(port) ((port)->unused[0])
@@ -157,7 +192,7 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port)
if (tx_enabled(port)) {
if (s3c24xx_serial_has_interrupt_mask(port))
- __set_bit(S3C64XX_UINTM_TXD,
+ __hw_set_bit(S3C64XX_UINTM_TXD,
portaddrl(port, S3C64XX_UINTM));
else
disable_irq_nosync(ourport->tx_irq);
@@ -176,7 +211,7 @@ static void s3c24xx_serial_start_tx(struct uart_port *port)
s3c24xx_serial_rx_disable(port);
if (s3c24xx_serial_has_interrupt_mask(port))
- __clear_bit(S3C64XX_UINTM_TXD,
+ __hw_clear_bit(S3C64XX_UINTM_TXD,
portaddrl(port, S3C64XX_UINTM));
else
enable_irq(ourport->tx_irq);
@@ -191,7 +226,7 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
if (rx_enabled(port)) {
dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
if (s3c24xx_serial_has_interrupt_mask(port))
- __set_bit(S3C64XX_UINTM_RXD,
+ __hw_set_bit(S3C64XX_UINTM_RXD,
portaddrl(port, S3C64XX_UINTM));
else
disable_irq_nosync(ourport->rx_irq);
@@ -548,7 +583,7 @@ static int s3c64xx_serial_startup(struct uart_port *port)
ourport->tx_claimed = 1;
/* Enable Rx Interrupt */
- __clear_bit(S3C64XX_UINTM_RXD, portaddrl(port, S3C64XX_UINTM));
+ __hw_clear_bit(S3C64XX_UINTM_RXD, portaddrl(port, S3C64XX_UINTM));
dbg("s3c64xx_serial_startup ok\n");
return ret;
}
--
2.0.1
next reply other threads:[~2014-07-21 15:50 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-21 15:50 Mark Brown [this message]
2014-07-21 16:01 ` [PATCH] exynos: serial clear and set big endian fix Arnd Bergmann
2014-07-21 16:10 ` Mark Brown
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=1405957832-6444-1-git-send-email-broonie@kernel.org \
--to=broonie@kernel.org \
--cc=broonie@linaro.org \
--cc=gregkh@linuxfoundation.org \
--cc=jslaby@suse.cz \
--cc=linaro-kernel@lists.linaro.org \
--cc=linux-serial@vger.kernel.org \
--cc=victor.kamensky@linaro.org \
/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