]> git.baikalelectronics.ru Git - kernel.git/commitdiff
memory: renesas-rpc-if: Split-off private data from struct rpcif
authorGeert Uytterhoeven <geert+renesas@glider.be>
Wed, 23 Nov 2022 14:41:17 +0000 (15:41 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 11 Mar 2023 12:55:17 +0000 (13:55 +0100)
[ Upstream commit 8419f6cd77712d500bd1b94ded722359e5eab2a9 ]

The rpcif structure is used as a common data structure, shared by the
RPC-IF core driver and by the HyperBus and SPI child drivers.
This poses several problems:
  - Most structure members describe private core driver state, which
    should not be accessible by the child drivers,
  - The structure's lifetime is controlled by the child drivers,
    complicating use by the core driver.

Fix this by moving the private core driver state to its own structure,
managed by the RPC-IF core driver, and store it in the core driver's
private data field.  This requires absorbing the child's platform
device, as that was stored in the driver's private data field before.

Fixes: 29f245a42766 ("memory: add Renesas RPC-IF driver")
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Link: https://lore.kernel.org/r/09fbb6fa67d5a8cd48a08808c9afa2f6a499aa42.1669213027.git.geert+renesas@glider.be
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/memory/renesas-rpc-if.c
include/memory/renesas-rpc-if.h

index 61c288d403750b14046a1d96fd7d508a22c5132b..309c0b59f3a2f680806b786e0deeeb12c1813edf 100644 (file)
@@ -162,14 +162,36 @@ static const struct regmap_access_table rpcif_volatile_table = {
        .n_yes_ranges   = ARRAY_SIZE(rpcif_volatile_ranges),
 };
 
+struct rpcif_priv {
+       struct device *dev;
+       void __iomem *base;
+       void __iomem *dirmap;
+       struct regmap *regmap;
+       struct reset_control *rstc;
+       struct platform_device *vdev;
+       size_t size;
+       enum rpcif_type type;
+       enum rpcif_data_dir dir;
+       u8 bus_size;
+       u8 xfer_size;
+       void *buffer;
+       u32 xferlen;
+       u32 smcr;
+       u32 smadr;
+       u32 command;            /* DRCMR or SMCMR */
+       u32 option;             /* DROPR or SMOPR */
+       u32 enable;             /* DRENR or SMENR */
+       u32 dummy;              /* DRDMCR or SMDMCR */
+       u32 ddr;                /* DRDRENR or SMDRENR */
+};
 
 /*
  * Custom accessor functions to ensure SM[RW]DR[01] are always accessed with
- * proper width.  Requires rpcif.xfer_size to be correctly set before!
+ * proper width.  Requires rpcif_priv.xfer_size to be correctly set before!
  */
 static int rpcif_reg_read(void *context, unsigned int reg, unsigned int *val)
 {
-       struct rpcif *rpc = context;
+       struct rpcif_priv *rpc = context;
 
        switch (reg) {
        case RPCIF_SMRDR0:
@@ -205,7 +227,7 @@ static int rpcif_reg_read(void *context, unsigned int reg, unsigned int *val)
 
 static int rpcif_reg_write(void *context, unsigned int reg, unsigned int val)
 {
-       struct rpcif *rpc = context;
+       struct rpcif_priv *rpc = context;
 
        switch (reg) {
        case RPCIF_SMWDR0:
@@ -252,13 +274,12 @@ static const struct regmap_config rpcif_regmap_config = {
        .volatile_table = &rpcif_volatile_table,
 };
 
-int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
+int rpcif_sw_init(struct rpcif *rpcif, struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
+       struct rpcif_priv *rpc = dev_get_drvdata(dev);
        struct resource *res;
 
-       rpc->dev = dev;
-
        rpc->base = devm_platform_ioremap_resource_byname(pdev, "regs");
        if (IS_ERR(rpc->base))
                return PTR_ERR(rpc->base);
@@ -279,12 +300,17 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
 
        rpc->type = (uintptr_t)of_device_get_match_data(dev);
        rpc->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+       if (IS_ERR(rpc->rstc))
+               return PTR_ERR(rpc->rstc);
 
-       return PTR_ERR_OR_ZERO(rpc->rstc);
+       rpcif->dev = dev;
+       rpcif->dirmap = rpc->dirmap;
+       rpcif->size = rpc->size;
+       return 0;
 }
 EXPORT_SYMBOL(rpcif_sw_init);
 
-static void rpcif_rzg2l_timing_adjust_sdr(struct rpcif *rpc)
+static void rpcif_rzg2l_timing_adjust_sdr(struct rpcif_priv *rpc)
 {
        regmap_write(rpc->regmap, RPCIF_PHYWR, 0xa5390000);
        regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000000);
@@ -298,8 +324,9 @@ static void rpcif_rzg2l_timing_adjust_sdr(struct rpcif *rpc)
        regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000032);
 }
 
-int rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
+int rpcif_hw_init(struct rpcif *rpcif, bool hyperflash)
 {
+       struct rpcif_priv *rpc = dev_get_drvdata(rpcif->dev);
        u32 dummy;
 
        pm_runtime_get_sync(rpc->dev);
@@ -360,7 +387,7 @@ int rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
 }
 EXPORT_SYMBOL(rpcif_hw_init);
 
-static int wait_msg_xfer_end(struct rpcif *rpc)
+static int wait_msg_xfer_end(struct rpcif_priv *rpc)
 {
        u32 sts;
 
@@ -369,7 +396,7 @@ static int wait_msg_xfer_end(struct rpcif *rpc)
                                        USEC_PER_SEC);
 }
 
-static u8 rpcif_bits_set(struct rpcif *rpc, u32 nbytes)
+static u8 rpcif_bits_set(struct rpcif_priv *rpc, u32 nbytes)
 {
        if (rpc->bus_size == 2)
                nbytes /= 2;
@@ -382,9 +409,11 @@ static u8 rpcif_bit_size(u8 buswidth)
        return buswidth > 4 ? 2 : ilog2(buswidth);
 }
 
-void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs,
+void rpcif_prepare(struct rpcif *rpcif, const struct rpcif_op *op, u64 *offs,
                   size_t *len)
 {
+       struct rpcif_priv *rpc = dev_get_drvdata(rpcif->dev);
+
        rpc->smcr = 0;
        rpc->smadr = 0;
        rpc->enable = 0;
@@ -468,8 +497,9 @@ void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs,
 }
 EXPORT_SYMBOL(rpcif_prepare);
 
-int rpcif_manual_xfer(struct rpcif *rpc)
+int rpcif_manual_xfer(struct rpcif *rpcif)
 {
+       struct rpcif_priv *rpc = dev_get_drvdata(rpcif->dev);
        u32 smenr, smcr, pos = 0, max = rpc->bus_size == 2 ? 8 : 4;
        int ret = 0;
 
@@ -589,7 +619,7 @@ exit:
 err_out:
        if (reset_control_reset(rpc->rstc))
                dev_err(rpc->dev, "Failed to reset HW\n");
-       rpcif_hw_init(rpc, rpc->bus_size == 2);
+       rpcif_hw_init(rpcif, rpc->bus_size == 2);
        goto exit;
 }
 EXPORT_SYMBOL(rpcif_manual_xfer);
@@ -636,8 +666,9 @@ static void memcpy_fromio_readw(void *to,
        }
 }
 
-ssize_t rpcif_dirmap_read(struct rpcif *rpc, u64 offs, size_t len, void *buf)
+ssize_t rpcif_dirmap_read(struct rpcif *rpcif, u64 offs, size_t len, void *buf)
 {
+       struct rpcif_priv *rpc = dev_get_drvdata(rpcif->dev);
        loff_t from = offs & (rpc->size - 1);
        size_t size = rpc->size - from;
 
@@ -672,6 +703,7 @@ static int rpcif_probe(struct platform_device *pdev)
 {
        struct platform_device *vdev;
        struct device_node *flash;
+       struct rpcif_priv *rpc;
        const char *name;
        int ret;
 
@@ -692,11 +724,18 @@ static int rpcif_probe(struct platform_device *pdev)
        }
        of_node_put(flash);
 
+       rpc = devm_kzalloc(&pdev->dev, sizeof(*rpc), GFP_KERNEL);
+       if (!rpc)
+               return -ENOMEM;
+
        vdev = platform_device_alloc(name, pdev->id);
        if (!vdev)
                return -ENOMEM;
        vdev->dev.parent = &pdev->dev;
-       platform_set_drvdata(pdev, vdev);
+
+       rpc->dev = &pdev->dev;
+       rpc->vdev = vdev;
+       platform_set_drvdata(pdev, rpc);
 
        ret = platform_device_add(vdev);
        if (ret) {
@@ -709,9 +748,9 @@ static int rpcif_probe(struct platform_device *pdev)
 
 static int rpcif_remove(struct platform_device *pdev)
 {
-       struct platform_device *vdev = platform_get_drvdata(pdev);
+       struct rpcif_priv *rpc = platform_get_drvdata(pdev);
 
-       platform_device_unregister(vdev);
+       platform_device_unregister(rpc->vdev);
 
        return 0;
 }
index 9c0ad64b8d292d49746c542e0c1b6bb261475e32..ddf94356752d3315acc286af68a641d6daa1e1d0 100644 (file)
@@ -64,24 +64,8 @@ enum rpcif_type {
 
 struct rpcif {
        struct device *dev;
-       void __iomem *base;
        void __iomem *dirmap;
-       struct regmap *regmap;
-       struct reset_control *rstc;
        size_t size;
-       enum rpcif_type type;
-       enum rpcif_data_dir dir;
-       u8 bus_size;
-       u8 xfer_size;
-       void *buffer;
-       u32 xferlen;
-       u32 smcr;
-       u32 smadr;
-       u32 command;            /* DRCMR or SMCMR */
-       u32 option;             /* DROPR or SMOPR */
-       u32 enable;             /* DRENR or SMENR */
-       u32 dummy;              /* DRDMCR or SMDMCR */
-       u32 ddr;                /* DRDRENR or SMDRENR */
 };
 
 int rpcif_sw_init(struct rpcif *rpc, struct device *dev);