diff mbox

[v2,5/5] external: Update xscom utils for type 1 indirect accesses

Message ID 20170323061509.4231-5-mikey@neuling.org
State Accepted
Headers show

Commit Message

Michael Neuling March 23, 2017, 6:15 a.m. UTC
Update get/putscom utils to support type 1 indirect access.

Currently we do some (ugly) bit mangling so that we can fit a 64 bit
scom address into the debugfs interface. The current code only shifts
down the top bit (indirect bit). This patch changes it to shift down
the whole top nibble so that the form of the indirection is also
shifted.

Also currently putscom always reads back the value. This causes a
problem for form 1 which can only be written.  This patch marks the
form 1 as not readable and hence doesn't attempt the read back.

The kernel debugfs scom driver doesn't do the bit mangling correctly.
So for form1 to work correctly, the kernel debugfs scom driver needs
updating. Existing scoms are forwards and backwards compatible with
the kernel.

(FWIW the kernel PRD scom interface doesn't need to be updated as it
passes the whole 64 bit scom address without any bit mangling)

Signed-off-by: Michael Neuling <mikey@neuling.org>
---
 external/xscom-utils/putscom.c | 10 ++++++----
 external/xscom-utils/xscom.c   | 21 +++++++++++++++++++--
 external/xscom-utils/xscom.h   |  2 ++
 3 files changed, 27 insertions(+), 6 deletions(-)

Comments

Cédric Le Goater March 23, 2017, 2:37 p.m. UTC | #1
On 03/23/2017 07:15 AM, Michael Neuling wrote:
> Update get/putscom utils to support type 1 indirect access.
> 
> Currently we do some (ugly) bit mangling so that we can fit a 64 bit
> scom address into the debugfs interface. The current code only shifts
> down the top bit (indirect bit). This patch changes it to shift down
> the whole top nibble so that the form of the indirection is also
> shifted.
> 
> Also currently putscom always reads back the value. This causes a
> problem for form 1 which can only be written.  This patch marks the
> form 1 as not readable and hence doesn't attempt the read back.
>
> The kernel debugfs scom driver doesn't do the bit mangling correctly.
> So for form1 to work correctly, the kernel debugfs scom driver needs
> updating. Existing scoms are forwards and backwards compatible with
> the kernel.
> 
> (FWIW the kernel PRD scom interface doesn't need to be updated as it
> passes the whole 64 bit scom address without any bit mangling)
>
> Signed-off-by: Michael Neuling <mikey@neuling.org>

Reviewed-by: Cédric Le Goater <clg@kaod.org>

Thanks,

C.

> ---
>  external/xscom-utils/putscom.c | 10 ++++++----
>  external/xscom-utils/xscom.c   | 21 +++++++++++++++++++--
>  external/xscom-utils/xscom.h   |  2 ++
>  3 files changed, 27 insertions(+), 6 deletions(-)
> 
> diff --git a/external/xscom-utils/putscom.c b/external/xscom-utils/putscom.c
> index 7eaa59e8d1..ca8c0da305 100644
> --- a/external/xscom-utils/putscom.c
> +++ b/external/xscom-utils/putscom.c
> @@ -92,10 +92,12 @@ int main(int argc, char *argv[])
>  		fprintf(stderr,"Error %d writing XSCOM\n", rc);
>  		exit(1);
>  	}
> -	rc = xscom_read(chip_id, addr, &val);
> -	if (rc) {
> -		fprintf(stderr,"Error %d reading XSCOM\n", rc);
> -		exit(1);
> +	if (xscom_readable(addr)) {
> +		rc = xscom_read(chip_id, addr, &val);
> +		if (rc) {
> +			fprintf(stderr,"Error %d reading XSCOM\n", rc);
> +			exit(1);
> +		}
>  	}
>  	printf("%016" PRIx64 "\n", val);
>  	return 0;
> diff --git a/external/xscom-utils/xscom.c b/external/xscom-utils/xscom.c
> index 3338542b10..2425730334 100644
> --- a/external/xscom-utils/xscom.c
> +++ b/external/xscom-utils/xscom.c
> @@ -131,8 +131,17 @@ static struct xscom_chip *xscom_find_chip(uint32_t chip_id)
>  
>  static uint64_t xscom_mangle_addr(uint64_t addr)
>  {
> -	if (addr & (1ull << 63))
> -		addr |= (1ull << 59);
> +	uint64_t tmp;
> +
> +	/*
> +	 * Shift the top 4 bits (indirect mode) down by 4 bits so we
> +	 * don't lose going through the debugfs interfaces.
> +	 */
> +	tmp = (addr & 0xf000000000000000) >> 4;
> +	addr &= 0x00ffffffffffffff;
> +	addr |= tmp;
> +
> +	/* Shift up by 3 for debugfs */
>  	return addr << 3;
>  }
>  
> @@ -192,6 +201,14 @@ int xscom_write_ex(uint32_t ex_target_id, uint64_t addr, uint64_t val)
>  	return xscom_write(chip_id, addr, val);
>  }
>  
> +bool xscom_readable(uint64_t addr)
> +{
> +	/* Top nibble 9 indicates form 1 indirect, which is write only */
> +	if (((addr >> 60) & 0xf) == 9)
> +		return false;
> +	return true;
> +}
> +
>  uint32_t xscom_init(void)
>  {
>  	return xscom_scan_chips(XSCOM_BASE_PATH);
> diff --git a/external/xscom-utils/xscom.h b/external/xscom-utils/xscom.h
> index 52ba119bf3..5f9edbc9b3 100644
> --- a/external/xscom-utils/xscom.h
> +++ b/external/xscom-utils/xscom.h
> @@ -27,6 +27,8 @@ extern int xscom_write_ex(uint32_t ex_target_id, uint64_t addr, uint64_t val);
>  
>  extern void xscom_for_each_chip(void (*cb)(uint32_t chip_id));
>  
> +extern bool xscom_readable(uint64_t addr);
> +
>  extern uint32_t xscom_init(void);
>  
>  #endif /* __XSCOM_H */
>
diff mbox

Patch

diff --git a/external/xscom-utils/putscom.c b/external/xscom-utils/putscom.c
index 7eaa59e8d1..ca8c0da305 100644
--- a/external/xscom-utils/putscom.c
+++ b/external/xscom-utils/putscom.c
@@ -92,10 +92,12 @@  int main(int argc, char *argv[])
 		fprintf(stderr,"Error %d writing XSCOM\n", rc);
 		exit(1);
 	}
-	rc = xscom_read(chip_id, addr, &val);
-	if (rc) {
-		fprintf(stderr,"Error %d reading XSCOM\n", rc);
-		exit(1);
+	if (xscom_readable(addr)) {
+		rc = xscom_read(chip_id, addr, &val);
+		if (rc) {
+			fprintf(stderr,"Error %d reading XSCOM\n", rc);
+			exit(1);
+		}
 	}
 	printf("%016" PRIx64 "\n", val);
 	return 0;
diff --git a/external/xscom-utils/xscom.c b/external/xscom-utils/xscom.c
index 3338542b10..2425730334 100644
--- a/external/xscom-utils/xscom.c
+++ b/external/xscom-utils/xscom.c
@@ -131,8 +131,17 @@  static struct xscom_chip *xscom_find_chip(uint32_t chip_id)
 
 static uint64_t xscom_mangle_addr(uint64_t addr)
 {
-	if (addr & (1ull << 63))
-		addr |= (1ull << 59);
+	uint64_t tmp;
+
+	/*
+	 * Shift the top 4 bits (indirect mode) down by 4 bits so we
+	 * don't lose going through the debugfs interfaces.
+	 */
+	tmp = (addr & 0xf000000000000000) >> 4;
+	addr &= 0x00ffffffffffffff;
+	addr |= tmp;
+
+	/* Shift up by 3 for debugfs */
 	return addr << 3;
 }
 
@@ -192,6 +201,14 @@  int xscom_write_ex(uint32_t ex_target_id, uint64_t addr, uint64_t val)
 	return xscom_write(chip_id, addr, val);
 }
 
+bool xscom_readable(uint64_t addr)
+{
+	/* Top nibble 9 indicates form 1 indirect, which is write only */
+	if (((addr >> 60) & 0xf) == 9)
+		return false;
+	return true;
+}
+
 uint32_t xscom_init(void)
 {
 	return xscom_scan_chips(XSCOM_BASE_PATH);
diff --git a/external/xscom-utils/xscom.h b/external/xscom-utils/xscom.h
index 52ba119bf3..5f9edbc9b3 100644
--- a/external/xscom-utils/xscom.h
+++ b/external/xscom-utils/xscom.h
@@ -27,6 +27,8 @@  extern int xscom_write_ex(uint32_t ex_target_id, uint64_t addr, uint64_t val);
 
 extern void xscom_for_each_chip(void (*cb)(uint32_t chip_id));
 
+extern bool xscom_readable(uint64_t addr);
+
 extern uint32_t xscom_init(void);
 
 #endif /* __XSCOM_H */