mirror of
https://github.com/torvalds/linux.git
synced 2026-05-23 06:31:58 +02:00
soc: imx8m: Cleanup with adding imx8m_soc_[un]prepare
There is a common flow to i.MX8M family, map OCOTP register base and enable ocotp clk first before read Unique ID from OCOTP. So introduce imx8m_soc_prepare to do ioremap and enable the ocotp clk, and introduce imx8m_soc_unprepare to disable the clk and do iounmap. With this patch, no need to spread the ioremap and clk handling in each soc_revision hook. Signed-off-by: Peng Fan <peng.fan@nxp.com> Reviewed-by: Marco Felsch <m.felsch@pengutronix.de> Signed-off-by: Shawn Guo <shawnguo@kernel.org>
This commit is contained in:
parent
0af2f6be1b
commit
390c01073f
|
|
@ -30,7 +30,13 @@
|
|||
|
||||
struct imx8_soc_data {
|
||||
char *name;
|
||||
int (*soc_revision)(u32 *socrev, u64 *socuid);
|
||||
const char *ocotp_compatible;
|
||||
int (*soc_revision)(struct platform_device *pdev, u32 *socrev, u64 *socuid);
|
||||
};
|
||||
|
||||
struct imx8_soc_drvdata {
|
||||
void __iomem *ocotp_base;
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_HAVE_ARM_SMCCC
|
||||
|
|
@ -49,30 +55,12 @@ static u32 imx8mq_soc_revision_from_atf(void)
|
|||
static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; };
|
||||
#endif
|
||||
|
||||
static int imx8mq_soc_revision(u32 *socrev, u64 *socuid)
|
||||
static int imx8mq_soc_revision(struct platform_device *pdev, u32 *socrev, u64 *socuid)
|
||||
{
|
||||
struct device_node *np __free(device_node) =
|
||||
of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
|
||||
void __iomem *ocotp_base;
|
||||
struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev);
|
||||
void __iomem *ocotp_base = drvdata->ocotp_base;
|
||||
u32 magic;
|
||||
u32 rev;
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
|
||||
if (!np)
|
||||
return -EINVAL;
|
||||
|
||||
ocotp_base = of_iomap(np, 0);
|
||||
if (!ocotp_base)
|
||||
return -EINVAL;
|
||||
|
||||
clk = of_clk_get_by_name(np, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
ret = PTR_ERR(clk);
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
clk_prepare_enable(clk);
|
||||
|
||||
/*
|
||||
* SOC revision on older imx8mq is not available in fuses so query
|
||||
|
|
@ -91,55 +79,24 @@ static int imx8mq_soc_revision(u32 *socrev, u64 *socuid)
|
|||
|
||||
*socrev = rev;
|
||||
|
||||
clk_disable_unprepare(clk);
|
||||
clk_put(clk);
|
||||
iounmap(ocotp_base);
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk:
|
||||
iounmap(ocotp_base);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int imx8mm_soc_uid(u64 *socuid)
|
||||
static int imx8mm_soc_uid(struct platform_device *pdev, u64 *socuid)
|
||||
{
|
||||
struct device_node *np __free(device_node) =
|
||||
of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp");
|
||||
void __iomem *ocotp_base;
|
||||
struct clk *clk;
|
||||
int ret = 0;
|
||||
struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev);
|
||||
void __iomem *ocotp_base = drvdata->ocotp_base;
|
||||
u32 offset = of_machine_is_compatible("fsl,imx8mp") ?
|
||||
IMX8MP_OCOTP_UID_OFFSET : 0;
|
||||
|
||||
if (!np)
|
||||
return -EINVAL;
|
||||
|
||||
ocotp_base = of_iomap(np, 0);
|
||||
if (!ocotp_base)
|
||||
return -EINVAL;
|
||||
|
||||
clk = of_clk_get_by_name(np, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
ret = PTR_ERR(clk);
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
clk_prepare_enable(clk);
|
||||
|
||||
*socuid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + offset);
|
||||
*socuid <<= 32;
|
||||
*socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset);
|
||||
|
||||
clk_disable_unprepare(clk);
|
||||
clk_put(clk);
|
||||
|
||||
err_clk:
|
||||
iounmap(ocotp_base);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx8mm_soc_revision(u32 *socrev, u64 *socuid)
|
||||
static int imx8mm_soc_revision(struct platform_device *pdev, u32 *socrev, u64 *socuid)
|
||||
{
|
||||
struct device_node *np __free(device_node) =
|
||||
of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
|
||||
|
|
@ -156,26 +113,66 @@ static int imx8mm_soc_revision(u32 *socrev, u64 *socuid)
|
|||
|
||||
iounmap(anatop_base);
|
||||
|
||||
return imx8mm_soc_uid(socuid);
|
||||
return imx8mm_soc_uid(pdev, socuid);
|
||||
}
|
||||
|
||||
static int imx8m_soc_prepare(struct platform_device *pdev, const char *ocotp_compatible)
|
||||
{
|
||||
struct device_node *np __free(device_node) =
|
||||
of_find_compatible_node(NULL, NULL, ocotp_compatible);
|
||||
struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev);
|
||||
int ret = 0;
|
||||
|
||||
if (!np)
|
||||
return -EINVAL;
|
||||
|
||||
drvdata->ocotp_base = of_iomap(np, 0);
|
||||
if (!drvdata->ocotp_base)
|
||||
return -EINVAL;
|
||||
|
||||
drvdata->clk = of_clk_get_by_name(np, NULL);
|
||||
if (IS_ERR(drvdata->clk)) {
|
||||
ret = PTR_ERR(drvdata->clk);
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
return clk_prepare_enable(drvdata->clk);
|
||||
|
||||
err_clk:
|
||||
iounmap(drvdata->ocotp_base);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void imx8m_soc_unprepare(struct platform_device *pdev)
|
||||
{
|
||||
struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
clk_put(drvdata->clk);
|
||||
iounmap(drvdata->ocotp_base);
|
||||
}
|
||||
|
||||
static const struct imx8_soc_data imx8mq_soc_data = {
|
||||
.name = "i.MX8MQ",
|
||||
.ocotp_compatible = "fsl,imx8mq-ocotp",
|
||||
.soc_revision = imx8mq_soc_revision,
|
||||
};
|
||||
|
||||
static const struct imx8_soc_data imx8mm_soc_data = {
|
||||
.name = "i.MX8MM",
|
||||
.ocotp_compatible = "fsl,imx8mm-ocotp",
|
||||
.soc_revision = imx8mm_soc_revision,
|
||||
};
|
||||
|
||||
static const struct imx8_soc_data imx8mn_soc_data = {
|
||||
.name = "i.MX8MN",
|
||||
.ocotp_compatible = "fsl,imx8mm-ocotp",
|
||||
.soc_revision = imx8mm_soc_revision,
|
||||
};
|
||||
|
||||
static const struct imx8_soc_data imx8mp_soc_data = {
|
||||
.name = "i.MX8MP",
|
||||
.ocotp_compatible = "fsl,imx8mm-ocotp",
|
||||
.soc_revision = imx8mm_soc_revision,
|
||||
};
|
||||
|
||||
|
|
@ -207,6 +204,7 @@ static int imx8m_soc_probe(struct platform_device *pdev)
|
|||
struct soc_device_attribute *soc_dev_attr;
|
||||
struct platform_device *cpufreq_dev;
|
||||
const struct imx8_soc_data *data;
|
||||
struct imx8_soc_drvdata *drvdata;
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct of_device_id *id;
|
||||
struct soc_device *soc_dev;
|
||||
|
|
@ -218,6 +216,12 @@ static int imx8m_soc_probe(struct platform_device *pdev)
|
|||
if (!soc_dev_attr)
|
||||
return -ENOMEM;
|
||||
|
||||
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, drvdata);
|
||||
|
||||
soc_dev_attr->family = "Freescale i.MX";
|
||||
|
||||
ret = of_property_read_string(of_root, "model", &soc_dev_attr->machine);
|
||||
|
|
@ -231,11 +235,18 @@ static int imx8m_soc_probe(struct platform_device *pdev)
|
|||
data = id->data;
|
||||
if (data) {
|
||||
soc_dev_attr->soc_id = data->name;
|
||||
ret = imx8m_soc_prepare(pdev, data->ocotp_compatible);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (data->soc_revision) {
|
||||
ret = data->soc_revision(&soc_rev, &soc_uid);
|
||||
if (ret)
|
||||
ret = data->soc_revision(pdev, &soc_rev, &soc_uid);
|
||||
if (ret) {
|
||||
imx8m_soc_unprepare(pdev);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
imx8m_soc_unprepare(pdev);
|
||||
}
|
||||
|
||||
soc_dev_attr->revision = imx8_revision(dev, soc_rev);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user