Skip to content

Commit

Permalink
io: endian conversions for io accessors
Browse files Browse the repository at this point in the history
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>
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
  • Loading branch information
npiggin authored and oohal committed Dec 16, 2019
1 parent 0d12f0c commit bb9aebc
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 29 deletions.
79 changes: 64 additions & 15 deletions include/io.h
Expand Up @@ -9,6 +9,7 @@
#include <compiler.h>
#include <stdint.h>
#include <processor.h>
#include <types.h>
#include <ccan/endian/endian.h>

/*
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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 */
Expand Down
20 changes: 14 additions & 6 deletions libflash/ipmi-hiomap.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
20 changes: 14 additions & 6 deletions libflash/mbox-flash.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
31 changes: 29 additions & 2 deletions libflash/test/mbox-server.c
Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down

0 comments on commit bb9aebc

Please sign in to comment.