diff mbox

mtd: maps: lantiq-flash: Check if the EBU endianness swap is enabled

Message ID 1484904834-14980-1-git-send-email-sebtx452@gmail.com
State Changes Requested
Delegated to: Brian Norris
Headers show

Commit Message

Sebastien Decourriere Jan. 20, 2017, 9:33 a.m. UTC
The purpose of this patch is to enable the software address endianness
swapping only when the in SoC EBU endianness swapping is disabled.
To perform this check, I look at Bit 30 of the EBU_CON_0 register.
Actually, the driver expects that the in SoC swapping is disabled.
This is the case with current bootloaders shuch as U-boot.

This applies only to vr9 (xrx200) rev 1.2 and ar10 (xrx300).

I have a router which uses a proprietary bootloader which keeps
the in SoC swapping enabled. The SoC in this router is a vrx200 v1.2.
In this SoC version, I can keep the in SoC swapping without any problem.

This patch replaces my previous broken patch.

Signed-off-by: Sebastien Decourriere <sebtx452@gmail.com>
---
 .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |  1 +
 drivers/mtd/maps/lantiq-flash.c                    | 29 +++++++++++++++++++---
 2 files changed, 27 insertions(+), 3 deletions(-)

Comments

Ralf Baechle Jan. 24, 2017, 5:03 p.m. UTC | #1
On Fri, Jan 20, 2017 at 10:33:54AM +0100, Sebastien Decourriere wrote:

> The purpose of this patch is to enable the software address endianness
> swapping only when the in SoC EBU endianness swapping is disabled.
> To perform this check, I look at Bit 30 of the EBU_CON_0 register.
> Actually, the driver expects that the in SoC swapping is disabled.
> This is the case with current bootloaders shuch as U-boot.
> 
> This applies only to vr9 (xrx200) rev 1.2 and ar10 (xrx300).
> 
> I have a router which uses a proprietary bootloader which keeps
> the in SoC swapping enabled. The SoC in this router is a vrx200 v1.2.
> In this SoC version, I can keep the in SoC swapping without any problem.
> 
> This patch replaces my previous broken patch.
> 
> Signed-off-by: Sebastien Decourriere <sebtx452@gmail.com>
>  .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |  1 +
>  drivers/mtd/maps/lantiq-flash.c                    | 29 +++++++++++++++++++---

Acked-by: Ralf Baechle <ralf@linux-mips.org>

for the trivial MIPS bit.

  Ralf
Hauke Mehrtens Jan. 24, 2017, 9:32 p.m. UTC | #2
On 01/20/2017 10:33 AM, Sebastien Decourriere wrote:
> The purpose of this patch is to enable the software address endianness
> swapping only when the in SoC EBU endianness swapping is disabled.
> To perform this check, I look at Bit 30 of the EBU_CON_0 register.
> Actually, the driver expects that the in SoC swapping is disabled.
> This is the case with current bootloaders shuch as U-boot.
> 
> This applies only to vr9 (xrx200) rev 1.2 and ar10 (xrx300).
> 
> I have a router which uses a proprietary bootloader which keeps
> the in SoC swapping enabled. The SoC in this router is a vrx200 v1.2.
> In this SoC version, I can keep the in SoC swapping without any problem.
> 
> This patch replaces my previous broken patch.
> 
> Signed-off-by: Sebastien Decourriere <sebtx452@gmail.com>
> ---
>  .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |  1 +
>  drivers/mtd/maps/lantiq-flash.c                    | 29 +++++++++++++++++++---
>  2 files changed, 27 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
> index 17b41bb..0ed0896 100644
> --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
> +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
> @@ -87,6 +87,7 @@ extern __iomem void *ltq_cgu_membase;
>  #define LTQ_EBU_PCC_ISTAT	0x00A0
>  #define LTQ_EBU_BUSCON1		0x0064
>  #define LTQ_EBU_ADDRSEL1	0x0024
> +#define EBU_FLASH_ENDIAN_SWAP	0x40000000
>  #define EBU_WRDIS		0x80000000
>  
>  /* WDT */
> diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
> index c8febb3..8d628d2 100644
> --- a/drivers/mtd/maps/lantiq-flash.c
> +++ b/drivers/mtd/maps/lantiq-flash.c
> @@ -113,6 +113,24 @@ ltq_mtd_probe(struct platform_device *pdev)
>  	struct ltq_mtd *ltq_mtd;
>  	struct cfi_private *cfi;
>  	int err;
> +	bool mtd_addr_swap = true;
> +
> +#ifdef CONFIG_SOC_TYPE_XWAY
> +	/* If SoC is vr9 rev 1.2 or ar10 and EBU endian swap
> +	 *  is enabled, we don't need to do software address swap
> +	 */
> +	if (ltq_ebu_r32(LTQ_EBU_BUSCON0) & EBU_FLASH_ENDIAN_SWAP) {
> +		switch (ltq_soc_type()) {

I would like to get rid of the calls to ltq_soc_type(). This list also
has to get extended for more recent SoCs which are not yet supported by
mainline kernel like xrx500 (GRX350/550), grx300/330.

This EBU register also does not exits on falcon, this SoC uses a
different EBU.

I would prefer to use a device tree option to activate this check and
only access LTQ_EBU_BUSCON0 when this property is set.

> +		case SOC_TYPE_VR9_2:
> +		case SOC_TYPE_AR10:
> +			mtd_addr_swap = false;
> +			break;
> +		default:
> +			mtd_addr_swap = true;
> +			break;
> +		}
> +	}
> +#endif
>  
>  	if (of_machine_is_compatible("lantiq,falcon") &&
>  			(ltq_boot_select() != BS_FLASH)) {
> @@ -150,7 +168,10 @@ ltq_mtd_probe(struct platform_device *pdev)
>  	ltq_mtd->map->copy_from = ltq_copy_from;
>  	ltq_mtd->map->copy_to = ltq_copy_to;
>  
> -	ltq_mtd->map->map_priv_1 = LTQ_NOR_PROBING;
> +	if (mtd_addr_swap)
> +		ltq_mtd->map->map_priv_1 = LTQ_NOR_PROBING;
> +	else
> +		ltq_mtd->map->map_priv_1 = LTQ_NOR_NORMAL;
>  	ltq_mtd->mtd = do_map_probe("cfi_probe", ltq_mtd->map);
>  	ltq_mtd->map->map_priv_1 = LTQ_NOR_NORMAL;
>  
> @@ -163,8 +184,10 @@ ltq_mtd_probe(struct platform_device *pdev)
>  	mtd_set_of_node(ltq_mtd->mtd, pdev->dev.of_node);
>  
>  	cfi = ltq_mtd->map->fldrv_priv;
> -	cfi->addr_unlock1 ^= 1;
> -	cfi->addr_unlock2 ^= 1;
> +	if (mtd_addr_swap) {
> +		cfi->addr_unlock1 ^= 1;
> +		cfi->addr_unlock2 ^= 1;
> +	}
>  
>  	err = mtd_device_register(ltq_mtd->mtd, NULL, 0);
>  	if (err) {
>
Sebastien Decourriere Jan. 25, 2017, 9:04 a.m. UTC | #3
Hello,


> I would prefer to use a device tree option to activate this check and
> only access LTQ_EBU_BUSCON0 when this property is set.

If I understand correctly, I have to make something like this :

---

bool mtd_addr_swap=true;

        if (!of_machine_is_compatible("lantiq,falcon") &&
                of_find_property(pdev->dev.of_node,
"lantiq,ebu_swap_check", NULL))
                if (ltq_ebu_r32(LTQ_EBU_BUSCON0) & EBU_FLASH_ENDIAN_SWAP)
                        mtd_addr_swap = false;

---

And then set this property directly on my device-specific dts file ?
Langer, Thomas Jan. 25, 2017, 4:58 p.m. UTC | #4
> Hello,

Hi Sebastian

> 
> 
> > I would prefer to use a device tree option to activate this check and
> > only access LTQ_EBU_BUSCON0 when this property is set.
> 
> If I understand correctly, I have to make something like this :
> 
> ---
> 
> bool mtd_addr_swap=true;
> 
>         if (!of_machine_is_compatible("lantiq,falcon") &&
>                 of_find_property(pdev->dev.of_node,
> "lantiq,ebu_swap_check", NULL))
>                 if (ltq_ebu_r32(LTQ_EBU_BUSCON0) & EBU_FLASH_ENDIAN_SWAP)
>                         mtd_addr_swap = false;
> 

No, please avoid "of_machine_is_compatible" in drivers.

> ---
> 
> And then set this property directly on my device-specific dts file ?

We should introduce specific compatible strings for this driver, which trigger this,
e.g. "lantiq,nor-vr9" or "lantiq,nor-ar10" (or better using family names "xrx200" and "xrx300")

Regards,
Thomas
Sebastien Decourriere Jan. 26, 2017, 11:02 a.m. UTC | #5
Hi Thomas


> No, please avoid "of_machine_is_compatible" in drivers.

OK


> We should introduce specific compatible strings for this driver, which trigger this,
> e.g. "lantiq,nor-vr9" or "lantiq,nor-ar10" (or better using family names "xrx200" and "xrx300")

You mean we can use the same way as other drivers, for example in the
physmap_of_versatile.c file :

static const struct of_device_id syscon_match[] = {
        {
                .compatible = "arm,integrator-ap-syscon",
                .data = (void *)INTEGRATOR_AP_FLASHPROT,
        },
        {
                .compatible = "arm,integrator-cp-syscon",
                .data = (void *)INTEGRATOR_CP_FLASHPROT,
        },

etc...


We can't filter on xrx200 or vr9, but we have to know the VR9 version
(as the VR9 < 1.2 is not compatible with this patch).

Regards,

Sebastien
Langer, Thomas Jan. 26, 2017, 4:01 p.m. UTC | #6
Hi Sebastian,

> 
> > We should introduce specific compatible strings for this driver, which
> trigger this,
> > e.g. "lantiq,nor-vr9" or "lantiq,nor-ar10" (or better using family names
> "xrx200" and "xrx300")
> 
> You mean we can use the same way as other drivers, for example in the
> physmap_of_versatile.c file :
> 
> static const struct of_device_id syscon_match[] = {
>         {
>                 .compatible = "arm,integrator-ap-syscon",
>                 .data = (void *)INTEGRATOR_AP_FLASHPROT,
>         },
>         {
>                 .compatible = "arm,integrator-cp-syscon",
>                 .data = (void *)INTEGRATOR_CP_FLASHPROT,
>         },
> 
> etc...
> 
> 
> We can't filter on xrx200 or vr9, but we have to know the VR9 version
> (as the VR9 < 1.2 is not compatible with this patch).

Then extend the compatible strings with versions (where necessary).
This requires to know the SoC version for each board, but it should be 
okay and is done for other system already this way.

> 
> Regards,
> 
> Sebastien

Regards,
Thomas
diff mbox

Patch

diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 17b41bb..0ed0896 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -87,6 +87,7 @@  extern __iomem void *ltq_cgu_membase;
 #define LTQ_EBU_PCC_ISTAT	0x00A0
 #define LTQ_EBU_BUSCON1		0x0064
 #define LTQ_EBU_ADDRSEL1	0x0024
+#define EBU_FLASH_ENDIAN_SWAP	0x40000000
 #define EBU_WRDIS		0x80000000
 
 /* WDT */
diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
index c8febb3..8d628d2 100644
--- a/drivers/mtd/maps/lantiq-flash.c
+++ b/drivers/mtd/maps/lantiq-flash.c
@@ -113,6 +113,24 @@  ltq_mtd_probe(struct platform_device *pdev)
 	struct ltq_mtd *ltq_mtd;
 	struct cfi_private *cfi;
 	int err;
+	bool mtd_addr_swap = true;
+
+#ifdef CONFIG_SOC_TYPE_XWAY
+	/* If SoC is vr9 rev 1.2 or ar10 and EBU endian swap
+	 *  is enabled, we don't need to do software address swap
+	 */
+	if (ltq_ebu_r32(LTQ_EBU_BUSCON0) & EBU_FLASH_ENDIAN_SWAP) {
+		switch (ltq_soc_type()) {
+		case SOC_TYPE_VR9_2:
+		case SOC_TYPE_AR10:
+			mtd_addr_swap = false;
+			break;
+		default:
+			mtd_addr_swap = true;
+			break;
+		}
+	}
+#endif
 
 	if (of_machine_is_compatible("lantiq,falcon") &&
 			(ltq_boot_select() != BS_FLASH)) {
@@ -150,7 +168,10 @@  ltq_mtd_probe(struct platform_device *pdev)
 	ltq_mtd->map->copy_from = ltq_copy_from;
 	ltq_mtd->map->copy_to = ltq_copy_to;
 
-	ltq_mtd->map->map_priv_1 = LTQ_NOR_PROBING;
+	if (mtd_addr_swap)
+		ltq_mtd->map->map_priv_1 = LTQ_NOR_PROBING;
+	else
+		ltq_mtd->map->map_priv_1 = LTQ_NOR_NORMAL;
 	ltq_mtd->mtd = do_map_probe("cfi_probe", ltq_mtd->map);
 	ltq_mtd->map->map_priv_1 = LTQ_NOR_NORMAL;
 
@@ -163,8 +184,10 @@  ltq_mtd_probe(struct platform_device *pdev)
 	mtd_set_of_node(ltq_mtd->mtd, pdev->dev.of_node);
 
 	cfi = ltq_mtd->map->fldrv_priv;
-	cfi->addr_unlock1 ^= 1;
-	cfi->addr_unlock2 ^= 1;
+	if (mtd_addr_swap) {
+		cfi->addr_unlock1 ^= 1;
+		cfi->addr_unlock2 ^= 1;
+	}
 
 	err = mtd_device_register(ltq_mtd->mtd, NULL, 0);
 	if (err) {