aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnd Bergmann <[email protected]>2023-01-24 21:55:46 +0100
committerArnd Bergmann <[email protected]>2023-01-24 21:55:47 +0100
commit0d01e09022c558c54fa2d5fb7fe7e32b7a9a8554 (patch)
tree214ead654745ec4d50874736698c51382d8a8f9e
parentf938b29d277a506dd6a22007b9417b2eef6e331d (diff)
parentbbaf6624f23d6e538401382be97ba3d4bcba963e (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.c152
-rw-r--r--drivers/memory/ti-emif-pm.c7
-rw-r--r--drivers/mtd/hyperbus/rpc-if.c18
-rw-r--r--drivers/spi/spi-rpc-if.c14
-rw-r--r--include/memory/renesas-rpc-if.h34
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