.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:
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:
.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);
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);
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);
}
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;
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;
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;
}
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;
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);
}
}
-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;
{
struct platform_device *vdev;
struct device_node *flash;
+ struct rpcif_priv *rpc;
const char *name;
int ret;
}
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) {
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;
}