memory: renesas-rpc-if: Fix PHYCNT.STRTIM setting
authorWolfram Sang <wsa+renesas@sang-engineering.com>
Wed, 19 Apr 2023 13:02:34 +0000 (15:02 +0200)
committerKrzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Mon, 8 May 2023 10:18:25 +0000 (12:18 +0200)
According to the datasheets, the Strobe Timing Adjustment bit (STRTIM)
setting is different on R-Car SoCs, i.e.

R-Car M3 ES1.*  : STRTIM[2:0] is set to 0x6
other R-Car Gen3: STRTIM[2:0] is set to 0x7
other R-Car Gen4: STRTIM[3:0] is set to 0xf

To fix this issue, a DT match data was added to specify the setting
for special use cases.

Signed-off-by: Cong Dang <cong.dang.xn@renesas.com>
Signed-off-by: Hai Pham <hai.pham.ud@renesas.com>
[wsa: rebased, restructured, added Gen4 support]
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/20230419130234.44321-1-wsa+renesas@sang-engineering.com
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
drivers/memory/renesas-rpc-if.c

index 025bb62..75fcba4 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright (C) 2019-2020 Cogent Embedded, Inc.
  */
 
+#include <linux/bitops.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/module.h>
@@ -163,6 +164,11 @@ static const struct regmap_access_table rpcif_volatile_table = {
        .n_yes_ranges   = ARRAY_SIZE(rpcif_volatile_ranges),
 };
 
+struct rpcif_info {
+       enum rpcif_type type;
+       u8 strtim;
+};
+
 struct rpcif_priv {
        struct device *dev;
        void __iomem *base;
@@ -171,7 +177,7 @@ struct rpcif_priv {
        struct reset_control *rstc;
        struct platform_device *vdev;
        size_t size;
-       enum rpcif_type type;
+       const struct rpcif_info *info;
        enum rpcif_data_dir dir;
        u8 bus_size;
        u8 xfer_size;
@@ -186,6 +192,26 @@ struct rpcif_priv {
        u32 ddr;                /* DRDRENR or SMDRENR */
 };
 
+static const struct rpcif_info rpcif_info_r8a7796 = {
+       .type = RPCIF_RCAR_GEN3,
+       .strtim = 6,
+};
+
+static const struct rpcif_info rpcif_info_gen3 = {
+       .type = RPCIF_RCAR_GEN3,
+       .strtim = 7,
+};
+
+static const struct rpcif_info rpcif_info_rz_g2l = {
+       .type = RPCIF_RZ_G2L,
+       .strtim = 7,
+};
+
+static const struct rpcif_info rpcif_info_gen4 = {
+       .type = RPCIF_RCAR_GEN4,
+       .strtim = 15,
+};
+
 /*
  * Custom accessor functions to ensure SM[RW]DR[01] are always accessed with
  * proper width.  Requires rpcif_priv.xfer_size to be correctly set before!
@@ -310,7 +336,7 @@ int rpcif_hw_init(struct device *dev, bool hyperflash)
        if (ret)
                return ret;
 
-       if (rpc->type == RPCIF_RZ_G2L) {
+       if (rpc->info->type == RPCIF_RZ_G2L) {
                ret = reset_control_reset(rpc->rstc);
                if (ret)
                        return ret;
@@ -324,12 +350,10 @@ int rpcif_hw_init(struct device *dev, bool hyperflash)
        /* DMA Transfer is not supported */
        regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_HS, 0);
 
-       if (rpc->type == RPCIF_RCAR_GEN3)
-               regmap_update_bits(rpc->regmap, RPCIF_PHYCNT,
-                                  RPCIF_PHYCNT_STRTIM(7), RPCIF_PHYCNT_STRTIM(7));
-       else if (rpc->type == RPCIF_RCAR_GEN4)
-               regmap_update_bits(rpc->regmap, RPCIF_PHYCNT,
-                                  RPCIF_PHYCNT_STRTIM(15), RPCIF_PHYCNT_STRTIM(15));
+       regmap_update_bits(rpc->regmap, RPCIF_PHYCNT,
+                          /* create mask with all affected bits set */
+                          RPCIF_PHYCNT_STRTIM(BIT(fls(rpc->info->strtim)) - 1),
+                          RPCIF_PHYCNT_STRTIM(rpc->info->strtim));
 
        regmap_update_bits(rpc->regmap, RPCIF_PHYOFFSET1, RPCIF_PHYOFFSET1_DDRTMG(3),
                           RPCIF_PHYOFFSET1_DDRTMG(3));
@@ -340,7 +364,7 @@ int rpcif_hw_init(struct device *dev, bool hyperflash)
                regmap_update_bits(rpc->regmap, RPCIF_PHYINT,
                                   RPCIF_PHYINT_WPVAL, 0);
 
-       if (rpc->type == RPCIF_RZ_G2L)
+       if (rpc->info->type == RPCIF_RZ_G2L)
                regmap_update_bits(rpc->regmap, RPCIF_CMNCR,
                                   RPCIF_CMNCR_MOIIO(3) | RPCIF_CMNCR_IOFV(3) |
                                   RPCIF_CMNCR_BSZ(3),
@@ -729,9 +753,9 @@ static int rpcif_probe(struct platform_device *pdev)
        rpc->dirmap = devm_ioremap_resource(dev, res);
        if (IS_ERR(rpc->dirmap))
                return PTR_ERR(rpc->dirmap);
-       rpc->size = resource_size(res);
 
-       rpc->type = (uintptr_t)of_device_get_match_data(dev);
+       rpc->size = resource_size(res);
+       rpc->info = of_device_get_match_data(dev);
        rpc->rstc = devm_reset_control_get_exclusive(dev, NULL);
        if (IS_ERR(rpc->rstc))
                return PTR_ERR(rpc->rstc);
@@ -764,9 +788,10 @@ static int rpcif_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id rpcif_of_match[] = {
-       { .compatible = "renesas,rcar-gen3-rpc-if", .data = (void *)RPCIF_RCAR_GEN3 },
-       { .compatible = "renesas,rcar-gen4-rpc-if", .data = (void *)RPCIF_RCAR_GEN4 },
-       { .compatible = "renesas,rzg2l-rpc-if", .data = (void *)RPCIF_RZ_G2L },
+       { .compatible = "renesas,r8a7796-rpc-if", .data = &rpcif_info_r8a7796 },
+       { .compatible = "renesas,rcar-gen3-rpc-if", .data = &rpcif_info_gen3 },
+       { .compatible = "renesas,rcar-gen4-rpc-if", .data = &rpcif_info_gen4 },
+       { .compatible = "renesas,rzg2l-rpc-if", .data = &rpcif_info_rz_g2l },
        {},
 };
 MODULE_DEVICE_TABLE(of, rpcif_of_match);