diff options
author | Arnd Bergmann <[email protected]> | 2023-01-24 21:55:46 +0100 |
---|---|---|
committer | Arnd Bergmann <[email protected]> | 2023-01-24 21:55:47 +0100 |
commit | 0d01e09022c558c54fa2d5fb7fe7e32b7a9a8554 (patch) | |
tree | 214ead654745ec4d50874736698c51382d8a8f9e | |
parent | f938b29d277a506dd6a22007b9417b2eef6e331d (diff) | |
parent | bbaf6624f23d6e538401382be97ba3d4bcba963e (diff) |
Merge tag 'memory-controller-drv-6.3-2' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl into soc/drivers
Memory controller drivers for v6.3
1. TI Emif: simplify device_get_match_data().
2. Renesas RPC IF:
- Few fixes (decouple driver's private data structure from other
drivers; unbind and rebind due to triggering managed resources
allocation from other drivers);
- Bigger rework around improved runtime Power Management.
* tag 'memory-controller-drv-6.3-2' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl:
memory: ti-emif-pm: Use device_get_match_data() to simplify the code
memory: renesas-rpc-if: Remove Runtime PM wrappers
memory: renesas-rpc-if: Pass device instead of rpcif to rpcif_*()
memory: renesas-rpc-if: Improve Runtime PM handling
memory: renesas-rpc-if: Always use dev in rpcif_probe()
memory: renesas-rpc-if: Move resource acquisition to .probe()
memory: renesas-rpc-if: Split-off private data from struct rpcif
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Arnd Bergmann <[email protected]>
-rw-r--r-- | drivers/memory/renesas-rpc-if.c | 152 | ||||
-rw-r--r-- | drivers/memory/ti-emif-pm.c | 7 | ||||
-rw-r--r-- | drivers/mtd/hyperbus/rpc-if.c | 18 | ||||
-rw-r--r-- | drivers/spi/spi-rpc-if.c | 14 | ||||
-rw-r--r-- | include/memory/renesas-rpc-if.h | 34 |
5 files changed, 119 insertions, 106 deletions
diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c index 09cd4318a83d..62b06041d758 100644 --- a/drivers/memory/renesas-rpc-if.c +++ b/drivers/memory/renesas-rpc-if.c @@ -163,14 +163,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: @@ -206,7 +228,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: @@ -253,39 +275,18 @@ 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 resource *res; + struct rpcif_priv *rpc = dev_get_drvdata(dev); - rpc->dev = dev; - - rpc->base = devm_platform_ioremap_resource_byname(pdev, "regs"); - if (IS_ERR(rpc->base)) - return PTR_ERR(rpc->base); - - rpc->regmap = devm_regmap_init(&pdev->dev, NULL, rpc, &rpcif_regmap_config); - if (IS_ERR(rpc->regmap)) { - dev_err(&pdev->dev, - "failed to init regmap for rpcif, error %ld\n", - PTR_ERR(rpc->regmap)); - return PTR_ERR(rpc->regmap); - } - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap"); - rpc->dirmap = devm_ioremap_resource(&pdev->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->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); - - 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); @@ -299,15 +300,17 @@ 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 device *dev, bool hyperflash) { + struct rpcif_priv *rpc = dev_get_drvdata(dev); u32 dummy; + int ret; - pm_runtime_get_sync(rpc->dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) + return ret; if (rpc->type == RPCIF_RZ_G2L) { - int ret; - ret = reset_control_reset(rpc->rstc); if (ret) return ret; @@ -356,7 +359,7 @@ int rpcif_hw_init(struct rpcif *rpc, bool hyperflash) regmap_write(rpc->regmap, RPCIF_SSLDR, RPCIF_SSLDR_SPNDL(7) | RPCIF_SSLDR_SLNDL(7) | RPCIF_SSLDR_SCKDL(7)); - pm_runtime_put(rpc->dev); + pm_runtime_put(dev); rpc->bus_size = hyperflash ? 2 : 1; @@ -364,7 +367,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; @@ -373,7 +376,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; @@ -386,9 +389,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 device *dev, const struct rpcif_op *op, u64 *offs, size_t *len) { + struct rpcif_priv *rpc = dev_get_drvdata(dev); + rpc->smcr = 0; rpc->smadr = 0; rpc->enable = 0; @@ -472,12 +477,15 @@ 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 device *dev) { + struct rpcif_priv *rpc = dev_get_drvdata(dev); u32 smenr, smcr, pos = 0, max = rpc->bus_size == 2 ? 8 : 4; int ret = 0; - pm_runtime_get_sync(rpc->dev); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + return ret; regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_CAL, RPCIF_PHYCNT_CAL); @@ -587,13 +595,13 @@ int rpcif_manual_xfer(struct rpcif *rpc) } exit: - pm_runtime_put(rpc->dev); + pm_runtime_put(dev); return ret; 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); + dev_err(dev, "Failed to reset HW\n"); + rpcif_hw_init(dev, rpc->bus_size == 2); goto exit; } EXPORT_SYMBOL(rpcif_manual_xfer); @@ -640,15 +648,19 @@ 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 device *dev, u64 offs, size_t len, void *buf) { + struct rpcif_priv *rpc = dev_get_drvdata(dev); loff_t from = offs & (rpc->size - 1); size_t size = rpc->size - from; + int ret; if (len > size) len = size; - pm_runtime_get_sync(rpc->dev); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + return ret; regmap_update_bits(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_MD, 0); regmap_write(rpc->regmap, RPCIF_DRCR, 0); @@ -666,7 +678,7 @@ ssize_t rpcif_dirmap_read(struct rpcif *rpc, u64 offs, size_t len, void *buf) else memcpy_fromio(buf, rpc->dirmap + from, len); - pm_runtime_put(rpc->dev); + pm_runtime_put(dev); return len; } @@ -674,14 +686,17 @@ EXPORT_SYMBOL(rpcif_dirmap_read); static int rpcif_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct platform_device *vdev; struct device_node *flash; + struct rpcif_priv *rpc; + struct resource *res; const char *name; int ret; - flash = of_get_next_child(pdev->dev.of_node, NULL); + flash = of_get_next_child(dev->of_node, NULL); if (!flash) { - dev_warn(&pdev->dev, "no flash node found\n"); + dev_warn(dev, "no flash node found\n"); return -ENODEV; } @@ -691,16 +706,45 @@ static int rpcif_probe(struct platform_device *pdev) name = "rpc-if-hyperflash"; } else { of_node_put(flash); - dev_warn(&pdev->dev, "unknown flash type\n"); + dev_warn(dev, "unknown flash type\n"); return -ENODEV; } of_node_put(flash); + rpc = devm_kzalloc(dev, sizeof(*rpc), GFP_KERNEL); + if (!rpc) + return -ENOMEM; + + rpc->base = devm_platform_ioremap_resource_byname(pdev, "regs"); + if (IS_ERR(rpc->base)) + return PTR_ERR(rpc->base); + + rpc->regmap = devm_regmap_init(dev, NULL, rpc, &rpcif_regmap_config); + if (IS_ERR(rpc->regmap)) { + dev_err(dev, "failed to init regmap for rpcif, error %ld\n", + PTR_ERR(rpc->regmap)); + return PTR_ERR(rpc->regmap); + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap"); + 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->rstc = devm_reset_control_get_exclusive(dev, NULL); + if (IS_ERR(rpc->rstc)) + return PTR_ERR(rpc->rstc); + vdev = platform_device_alloc(name, pdev->id); if (!vdev) return -ENOMEM; - vdev->dev.parent = &pdev->dev; - platform_set_drvdata(pdev, vdev); + vdev->dev.parent = dev; + + rpc->dev = dev; + rpc->vdev = vdev; + platform_set_drvdata(pdev, rpc); ret = platform_device_add(vdev); if (ret) { @@ -713,9 +757,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; } diff --git a/drivers/memory/ti-emif-pm.c b/drivers/memory/ti-emif-pm.c index 31d6266f008c..cef0d3beb63b 100644 --- a/drivers/memory/ti-emif-pm.c +++ b/drivers/memory/ti-emif-pm.c @@ -277,18 +277,13 @@ static int ti_emif_probe(struct platform_device *pdev) int ret; struct resource *res; struct device *dev = &pdev->dev; - const struct of_device_id *match; struct ti_emif_data *emif_data; emif_data = devm_kzalloc(dev, sizeof(*emif_data), GFP_KERNEL); if (!emif_data) return -ENOMEM; - match = of_match_device(ti_emif_of_match, &pdev->dev); - if (!match) - return -ENODEV; - - emif_data->pm_data.ti_emif_sram_config = (unsigned long)match->data; + emif_data->pm_data.ti_emif_sram_config = (unsigned long) device_get_match_data(&pdev->dev); emif_data->pm_data.ti_emif_base_addr_virt = devm_platform_get_and_ioremap_resource(pdev, 0, diff --git a/drivers/mtd/hyperbus/rpc-if.c b/drivers/mtd/hyperbus/rpc-if.c index d00d30243403..ef32fca5f785 100644 --- a/drivers/mtd/hyperbus/rpc-if.c +++ b/drivers/mtd/hyperbus/rpc-if.c @@ -56,7 +56,7 @@ static void rpcif_hb_prepare_read(struct rpcif *rpc, void *to, op.data.nbytes = len; op.data.buf.in = to; - rpcif_prepare(rpc, &op, NULL, NULL); + rpcif_prepare(rpc->dev, &op, NULL, NULL); } static void rpcif_hb_prepare_write(struct rpcif *rpc, unsigned long to, @@ -70,7 +70,7 @@ static void rpcif_hb_prepare_write(struct rpcif *rpc, unsigned long to, op.data.nbytes = len; op.data.buf.out = from; - rpcif_prepare(rpc, &op, NULL, NULL); + rpcif_prepare(rpc->dev, &op, NULL, NULL); } static u16 rpcif_hb_read16(struct hyperbus_device *hbdev, unsigned long addr) @@ -81,7 +81,7 @@ static u16 rpcif_hb_read16(struct hyperbus_device *hbdev, unsigned long addr) rpcif_hb_prepare_read(&hyperbus->rpc, &data, addr, 2); - rpcif_manual_xfer(&hyperbus->rpc); + rpcif_manual_xfer(hyperbus->rpc.dev); return data.x[0]; } @@ -94,7 +94,7 @@ static void rpcif_hb_write16(struct hyperbus_device *hbdev, unsigned long addr, rpcif_hb_prepare_write(&hyperbus->rpc, addr, &data, 2); - rpcif_manual_xfer(&hyperbus->rpc); + rpcif_manual_xfer(hyperbus->rpc.dev); } static void rpcif_hb_copy_from(struct hyperbus_device *hbdev, void *to, @@ -105,7 +105,7 @@ static void rpcif_hb_copy_from(struct hyperbus_device *hbdev, void *to, rpcif_hb_prepare_read(&hyperbus->rpc, to, from, len); - rpcif_dirmap_read(&hyperbus->rpc, from, len, to); + rpcif_dirmap_read(hyperbus->rpc.dev, from, len, to); } static const struct hyperbus_ops rpcif_hb_ops = { @@ -130,9 +130,9 @@ static int rpcif_hb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, hyperbus); - rpcif_enable_rpm(&hyperbus->rpc); + pm_runtime_enable(hyperbus->rpc.dev); - error = rpcif_hw_init(&hyperbus->rpc, true); + error = rpcif_hw_init(hyperbus->rpc.dev, true); if (error) goto out_disable_rpm; @@ -150,7 +150,7 @@ static int rpcif_hb_probe(struct platform_device *pdev) return 0; out_disable_rpm: - rpcif_disable_rpm(&hyperbus->rpc); + pm_runtime_disable(hyperbus->rpc.dev); return error; } @@ -160,7 +160,7 @@ static int rpcif_hb_remove(struct platform_device *pdev) hyperbus_unregister_device(&hyperbus->hbdev); - rpcif_disable_rpm(&hyperbus->rpc); + pm_runtime_disable(hyperbus->rpc.dev); return 0; } diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c index 24ec1c83f379..ec0904faf3a1 100644 --- a/drivers/spi/spi-rpc-if.c +++ b/drivers/spi/spi-rpc-if.c @@ -58,7 +58,7 @@ static void rpcif_spi_mem_prepare(struct spi_device *spi_dev, rpc_op.data.dir = RPCIF_NO_DATA; } - rpcif_prepare(rpc, &rpc_op, offs, len); + rpcif_prepare(rpc->dev, &rpc_op, offs, len); } static bool rpcif_spi_mem_supports_op(struct spi_mem *mem, @@ -86,7 +86,7 @@ static ssize_t rpcif_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc, rpcif_spi_mem_prepare(desc->mem->spi, &desc->info.op_tmpl, &offs, &len); - return rpcif_dirmap_read(rpc, offs, len, buf); + return rpcif_dirmap_read(rpc->dev, offs, len, buf); } static int rpcif_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc) @@ -117,7 +117,7 @@ static int rpcif_spi_mem_exec_op(struct spi_mem *mem, rpcif_spi_mem_prepare(mem->spi, op, NULL, NULL); - return rpcif_manual_xfer(rpc); + return rpcif_manual_xfer(rpc->dev); } static const struct spi_controller_mem_ops rpcif_spi_mem_ops = { @@ -147,7 +147,7 @@ static int rpcif_spi_probe(struct platform_device *pdev) ctlr->dev.of_node = parent->of_node; - rpcif_enable_rpm(rpc); + pm_runtime_enable(rpc->dev); ctlr->num_chipselect = 1; ctlr->mem_ops = &rpcif_spi_mem_ops; @@ -156,7 +156,7 @@ static int rpcif_spi_probe(struct platform_device *pdev) ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_QUAD | SPI_RX_QUAD; ctlr->flags = SPI_CONTROLLER_HALF_DUPLEX; - error = rpcif_hw_init(rpc, false); + error = rpcif_hw_init(rpc->dev, false); if (error) goto out_disable_rpm; @@ -169,7 +169,7 @@ static int rpcif_spi_probe(struct platform_device *pdev) return 0; out_disable_rpm: - rpcif_disable_rpm(rpc); + pm_runtime_disable(rpc->dev); return error; } @@ -179,7 +179,7 @@ static int rpcif_spi_remove(struct platform_device *pdev) struct rpcif *rpc = spi_controller_get_devdata(ctlr); spi_unregister_controller(ctlr); - rpcif_disable_rpm(rpc); + pm_runtime_disable(rpc->dev); return 0; } diff --git a/include/memory/renesas-rpc-if.h b/include/memory/renesas-rpc-if.h index 862eff613dc7..b8fa30fd6b50 100644 --- a/include/memory/renesas-rpc-if.h +++ b/include/memory/renesas-rpc-if.h @@ -65,41 +65,15 @@ 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); -int rpcif_hw_init(struct rpcif *rpc, bool hyperflash); -void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs, +int rpcif_hw_init(struct device *dev, bool hyperflash); +void rpcif_prepare(struct device *dev, const struct rpcif_op *op, u64 *offs, size_t *len); -int rpcif_manual_xfer(struct rpcif *rpc); -ssize_t rpcif_dirmap_read(struct rpcif *rpc, u64 offs, size_t len, void *buf); - -static inline void rpcif_enable_rpm(struct rpcif *rpc) -{ - pm_runtime_enable(rpc->dev); -} - -static inline void rpcif_disable_rpm(struct rpcif *rpc) -{ - pm_runtime_disable(rpc->dev); -} +int rpcif_manual_xfer(struct device *dev); +ssize_t rpcif_dirmap_read(struct device *dev, u64 offs, size_t len, void *buf); #endif // __RENESAS_RPC_IF_H |