diff options
| -rw-r--r-- | arch/powerpc/platforms/powernv/opal-xscom.c | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/arch/powerpc/platforms/powernv/opal-xscom.c b/arch/powerpc/platforms/powernv/opal-xscom.c index 4fbf276ac99e..4cd2ea6c0dbe 100644 --- a/arch/powerpc/platforms/powernv/opal-xscom.c +++ b/arch/powerpc/platforms/powernv/opal-xscom.c | |||
| @@ -71,11 +71,11 @@ static int opal_xscom_err_xlate(int64_t rc) | |||
| 71 | } | 71 | } |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static u64 opal_scom_unmangle(u64 reg) | 74 | static u64 opal_scom_unmangle(u64 addr) |
| 75 | { | 75 | { |
| 76 | /* | 76 | /* |
| 77 | * XSCOM indirect addresses have the top bit set. Additionally | 77 | * XSCOM indirect addresses have the top bit set. Additionally |
| 78 | * the reset of the top 3 nibbles is always 0. | 78 | * the rest of the top 3 nibbles is always 0. |
| 79 | * | 79 | * |
| 80 | * Because the debugfs interface uses signed offsets and shifts | 80 | * Because the debugfs interface uses signed offsets and shifts |
| 81 | * the address left by 3, we basically cannot use the top 4 bits | 81 | * the address left by 3, we basically cannot use the top 4 bits |
| @@ -86,10 +86,13 @@ static u64 opal_scom_unmangle(u64 reg) | |||
| 86 | * conversion here. To leave room for further xscom address | 86 | * conversion here. To leave room for further xscom address |
| 87 | * expansion, we only clear out the top byte | 87 | * expansion, we only clear out the top byte |
| 88 | * | 88 | * |
| 89 | * For in-kernel use, we also support the real indirect bit, so | ||
| 90 | * we test for any of the top 5 bits | ||
| 91 | * | ||
| 89 | */ | 92 | */ |
| 90 | if (reg & (1ull << 59)) | 93 | if (addr & (0x1full << 59)) |
| 91 | reg = (reg & ~(0xffull << 56)) | (1ull << 63); | 94 | addr = (addr & ~(0xffull << 56)) | (1ull << 63); |
| 92 | return reg; | 95 | return addr; |
| 93 | } | 96 | } |
| 94 | 97 | ||
| 95 | static int opal_scom_read(scom_map_t map, u64 reg, u64 *value) | 98 | static int opal_scom_read(scom_map_t map, u64 reg, u64 *value) |
| @@ -98,8 +101,8 @@ static int opal_scom_read(scom_map_t map, u64 reg, u64 *value) | |||
| 98 | int64_t rc; | 101 | int64_t rc; |
| 99 | __be64 v; | 102 | __be64 v; |
| 100 | 103 | ||
| 101 | reg = opal_scom_unmangle(reg); | 104 | reg = opal_scom_unmangle(m->addr + reg); |
| 102 | rc = opal_xscom_read(m->chip, m->addr + reg, (__be64 *)__pa(&v)); | 105 | rc = opal_xscom_read(m->chip, reg, (__be64 *)__pa(&v)); |
| 103 | *value = be64_to_cpu(v); | 106 | *value = be64_to_cpu(v); |
| 104 | return opal_xscom_err_xlate(rc); | 107 | return opal_xscom_err_xlate(rc); |
| 105 | } | 108 | } |
| @@ -109,8 +112,8 @@ static int opal_scom_write(scom_map_t map, u64 reg, u64 value) | |||
| 109 | struct opal_scom_map *m = map; | 112 | struct opal_scom_map *m = map; |
| 110 | int64_t rc; | 113 | int64_t rc; |
| 111 | 114 | ||
| 112 | reg = opal_scom_unmangle(reg); | 115 | reg = opal_scom_unmangle(m->addr + reg); |
| 113 | rc = opal_xscom_write(m->chip, m->addr + reg, value); | 116 | rc = opal_xscom_write(m->chip, reg, value); |
| 114 | return opal_xscom_err_xlate(rc); | 117 | return opal_xscom_err_xlate(rc); |
| 115 | } | 118 | } |
| 116 | 119 | ||
