@@ -9,6 +9,7 @@
#include <compiler.h>
#include <stdint.h>
#include <processor.h>
+#include <types.h>
#include <ccan/endian/endian.h>
/*
@@ -35,10 +36,10 @@ static inline uint8_t in_8(const volatile uint8_t *addr)
static inline uint16_t __in_be16(const volatile uint16_t *addr)
{
- uint16_t val;
+ __be16 val;
asm volatile("lhzcix %0,0,%1" :
"=r"(val) : "r"(addr), "m"(*addr) : "memory");
- return val;
+ return be16_to_cpu(val);
}
static inline uint16_t in_be16(const volatile uint16_t *addr)
@@ -47,17 +48,26 @@ static inline uint16_t in_be16(const volatile uint16_t *addr)
return __in_be16(addr);
}
+static inline uint16_t __in_le16(const volatile uint16_t *addr)
+{
+ __le16 val;
+ asm volatile("lhzcix %0,0,%1" :
+ "=r"(val) : "r"(addr), "m"(*addr) : "memory");
+ return le16_to_cpu(val);
+}
+
static inline uint16_t in_le16(const volatile uint16_t *addr)
{
- return bswap_16(in_be16(addr));
+ sync();
+ return __in_le16(addr);
}
static inline uint32_t __in_be32(const volatile uint32_t *addr)
{
- uint32_t val;
+ __be32 val;
asm volatile("lwzcix %0,0,%1" :
"=r"(val) : "r"(addr), "m"(*addr) : "memory");
- return val;
+ return be32_to_cpu(val);
}
static inline uint32_t in_be32(const volatile uint32_t *addr)
@@ -66,17 +76,26 @@ static inline uint32_t in_be32(const volatile uint32_t *addr)
return __in_be32(addr);
}
+static inline uint32_t __in_le32(const volatile uint32_t *addr)
+{
+ __le32 val;
+ asm volatile("lwzcix %0,0,%1" :
+ "=r"(val) : "r"(addr), "m"(*addr) : "memory");
+ return le32_to_cpu(val);
+}
+
static inline uint32_t in_le32(const volatile uint32_t *addr)
{
- return bswap_32(in_be32(addr));
+ sync();
+ return __in_le32(addr);
}
static inline uint64_t __in_be64(const volatile uint64_t *addr)
{
- uint64_t val;
+ __be64 val;
asm volatile("ldcix %0,0,%1" :
"=r"(val) : "r"(addr), "m"(*addr) : "memory");
- return val;
+ return be64_to_cpu(val);
}
static inline uint64_t in_be64(const volatile uint64_t *addr)
@@ -85,9 +104,18 @@ static inline uint64_t in_be64(const volatile uint64_t *addr)
return __in_be64(addr);
}
+static inline uint64_t __in_le64(const volatile uint64_t *addr)
+{
+ __le64 val;
+ asm volatile("ldcix %0,0,%1" :
+ "=r"(val) : "r"(addr), "m"(*addr) : "memory");
+ return le64_to_cpu(val);
+}
+
static inline uint64_t in_le64(const volatile uint64_t *addr)
{
- return bswap_64(in_be64(addr));
+ sync();
+ return __in_le64(addr);
}
static inline void __out_8(volatile uint8_t *addr, uint8_t val)
@@ -105,7 +133,7 @@ static inline void out_8(volatile uint8_t *addr, uint8_t val)
static inline void __out_be16(volatile uint16_t *addr, uint16_t val)
{
asm volatile("sthcix %0,0,%1"
- : : "r"(val), "r"(addr), "m"(*addr) : "memory");
+ : : "r"(cpu_to_be16(val)), "r"(addr), "m"(*addr) : "memory");
}
static inline void out_be16(volatile uint16_t *addr, uint16_t val)
@@ -114,15 +142,22 @@ static inline void out_be16(volatile uint16_t *addr, uint16_t val)
return __out_be16(addr, val);
}
+static inline void __out_le16(volatile uint16_t *addr, uint16_t val)
+{
+ asm volatile("sthcix %0,0,%1"
+ : : "r"(cpu_to_le16(val)), "r"(addr), "m"(*addr) : "memory");
+}
+
static inline void out_le16(volatile uint16_t *addr, uint16_t val)
{
- out_be16(addr, bswap_16(val));
+ sync();
+ return __out_le16(addr, val);
}
static inline void __out_be32(volatile uint32_t *addr, uint32_t val)
{
asm volatile("stwcix %0,0,%1"
- : : "r"(val), "r"(addr), "m"(*addr) : "memory");
+ : : "r"(cpu_to_be32(val)), "r"(addr), "m"(*addr) : "memory");
}
static inline void out_be32(volatile uint32_t *addr, uint32_t val)
@@ -131,15 +166,22 @@ static inline void out_be32(volatile uint32_t *addr, uint32_t val)
return __out_be32(addr, val);
}
+static inline void __out_le32(volatile uint32_t *addr, uint32_t val)
+{
+ asm volatile("stwcix %0,0,%1"
+ : : "r"(cpu_to_le32(val)), "r"(addr), "m"(*addr) : "memory");
+}
+
static inline void out_le32(volatile uint32_t *addr, uint32_t val)
{
- out_be32(addr, bswap_32(val));
+ sync();
+ return __out_le32(addr, val);
}
static inline void __out_be64(volatile uint64_t *addr, uint64_t val)
{
asm volatile("stdcix %0,0,%1"
- : : "r"(val), "r"(addr), "m"(*addr) : "memory");
+ : : "r"(cpu_to_be64(val)), "r"(addr), "m"(*addr) : "memory");
}
static inline void out_be64(volatile uint64_t *addr, uint64_t val)
@@ -148,9 +190,16 @@ static inline void out_be64(volatile uint64_t *addr, uint64_t val)
return __out_be64(addr, val);
}
+static inline void __out_le64(volatile uint64_t *addr, uint64_t val)
+{
+ asm volatile("stdcix %0,0,%1"
+ : : "r"(cpu_to_le64(val)), "r"(addr), "m"(*addr) : "memory");
+}
+
static inline void out_le64(volatile uint64_t *addr, uint64_t val)
{
- out_be64(addr, bswap_64(val));
+ sync();
+ return __out_le64(addr, val);
}
/* Assistant to macros used to access PCI config space */
@@ -570,8 +570,13 @@ static int lpc_window_read(struct ipmi_hiomap *ctx, uint32_t pos,
/* XXX: make this read until it's aligned */
if (len > 3 && !(off & 3)) {
rc = lpc_read(OPAL_LPC_FW, off, &dat, 4);
- if (!rc)
- *(uint32_t *)buf = dat;
+ if (!rc) {
+ /*
+ * lpc_read swaps to CPU endian but it's not
+ * really a 32-bit value, so convert back.
+ */
+ *(__be32 *)buf = cpu_to_be32(dat);
+ }
chunk = 4;
} else {
rc = lpc_read(OPAL_LPC_FW, off, &dat, 1);
@@ -615,12 +620,15 @@ static int lpc_window_write(struct ipmi_hiomap *ctx, uint32_t pos,
uint32_t chunk;
if (len > 3 && !(off & 3)) {
- rc = lpc_write(OPAL_LPC_FW, off,
- *(uint32_t *)buf, 4);
+ /* endian swap: see lpc_window_write */
+ uint32_t dat = be32_to_cpu(*(__be32 *)buf);
+
+ rc = lpc_write(OPAL_LPC_FW, off, dat, 4);
chunk = 4;
} else {
- rc = lpc_write(OPAL_LPC_FW, off,
- *(uint8_t *)buf, 1);
+ uint8_t dat = *(uint8_t *)buf;
+
+ rc = lpc_write(OPAL_LPC_FW, off, dat, 1);
chunk = 1;
}
if (rc) {
@@ -159,8 +159,13 @@ static int lpc_window_read(struct mbox_flash_data *mbox_flash, uint32_t pos,
/* XXX: make this read until it's aligned */
if (len > 3 && !(off & 3)) {
rc = lpc_read(OPAL_LPC_FW, off, &dat, 4);
- if (!rc)
- *(uint32_t *)buf = dat;
+ if (!rc) {
+ /*
+ * lpc_read swaps to CPU endian but it's not
+ * really a 32-bit value, so convert back.
+ */
+ *(__be32 *)buf = cpu_to_be32(dat);
+ }
chunk = 4;
} else {
rc = lpc_read(OPAL_LPC_FW, off, &dat, 1);
@@ -194,12 +199,15 @@ static int lpc_window_write(struct mbox_flash_data *mbox_flash, uint32_t pos,
uint32_t chunk;
if (len > 3 && !(off & 3)) {
- rc = lpc_write(OPAL_LPC_FW, off,
- *(uint32_t *)buf, 4);
+ /* endian swap: see lpc_window_write */
+ uint32_t dat = be32_to_cpu(*(__be32 *)buf);
+
+ rc = lpc_write(OPAL_LPC_FW, off, dat, 4);
chunk = 4;
} else {
- rc = lpc_write(OPAL_LPC_FW, off,
- *(uint8_t *)buf, 1);
+ uint8_t dat = *(uint8_t *)buf;
+
+ rc = lpc_write(OPAL_LPC_FW, off, dat, 1);
chunk = 1;
}
if (rc) {
@@ -100,7 +100,21 @@ int64_t lpc_read(enum OpalLPCAddressType __unused addr_type, uint32_t addr,
/* Let it read from a write window... Spec says it ok! */
if (!check_window(addr, sz) || server_state.win_type == WIN_CLOSED)
return 1;
- memcpy(data, server_state.lpc_base + addr, sz);
+
+ switch (sz) {
+ case 1:
+ *(uint8_t *)data = *(uint8_t *)(server_state.lpc_base + addr);
+ break;
+ case 2:
+ *(uint16_t *)data = be16_to_cpu(*(uint16_t *)(server_state.lpc_base + addr));
+ break;
+ case 4:
+ *(uint32_t *)data = be32_to_cpu(*(uint32_t *)(server_state.lpc_base + addr));
+ break;
+ default:
+ prerror("Invalid data size %d\n", sz);
+ return 1;
+ }
return 0;
}
@@ -111,7 +125,20 @@ int64_t lpc_write(enum OpalLPCAddressType __unused addr_type, uint32_t addr,
{
if (!check_window(addr, sz) || server_state.win_type != WIN_WRITE)
return 1;
- memcpy(server_state.lpc_base + addr, &data, sz);
+ switch (sz) {
+ case 1:
+ *(uint8_t *)(server_state.lpc_base + addr) = data;
+ break;
+ case 2:
+ *(uint16_t *)(server_state.lpc_base + addr) = cpu_to_be16(data);
+ break;
+ case 4:
+ *(uint32_t *)(server_state.lpc_base + addr) = cpu_to_be32(data);
+ break;
+ default:
+ prerror("Invalid data size %d\n", sz);
+ return 1;
+ }
return 0;
}
This requires a small change to flash drivers which assumed 4-byte LPC reads would not change endian. _raw accessors could be added if this becomes a signifcant pattern, but for now this hack works. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> --- include/io.h | 79 ++++++++++++++++++++++++++++++------- libflash/ipmi-hiomap.c | 20 +++++++--- libflash/mbox-flash.c | 20 +++++++--- libflash/test/mbox-server.c | 31 ++++++++++++++- 4 files changed, 121 insertions(+), 29 deletions(-)