Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * i.MX IIM driver
0004  *
0005  * Copyright (c) 2017 Pengutronix, Michael Grzeschik <m.grzeschik@pengutronix.de>
0006  *
0007  * Based on the barebox iim driver,
0008  * Copyright (c) 2010 Baruch Siach <baruch@tkos.co.il>,
0009  *  Orex Computed Radiography
0010  */
0011 
0012 #include <linux/device.h>
0013 #include <linux/io.h>
0014 #include <linux/module.h>
0015 #include <linux/nvmem-provider.h>
0016 #include <linux/of.h>
0017 #include <linux/of_device.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/slab.h>
0020 #include <linux/clk.h>
0021 
0022 #define IIM_BANK_BASE(n)    (0x800 + 0x400 * (n))
0023 
0024 struct imx_iim_drvdata {
0025     unsigned int nregs;
0026 };
0027 
0028 struct iim_priv {
0029     void __iomem *base;
0030     struct clk *clk;
0031 };
0032 
0033 static int imx_iim_read(void *context, unsigned int offset,
0034               void *buf, size_t bytes)
0035 {
0036     struct iim_priv *iim = context;
0037     int i, ret;
0038     u8 *buf8 = buf;
0039 
0040     ret = clk_prepare_enable(iim->clk);
0041     if (ret)
0042         return ret;
0043 
0044     for (i = offset; i < offset + bytes; i++) {
0045         int bank = i >> 5;
0046         int reg = i & 0x1f;
0047 
0048         *buf8++ = readl(iim->base + IIM_BANK_BASE(bank) + reg * 4);
0049     }
0050 
0051     clk_disable_unprepare(iim->clk);
0052 
0053     return 0;
0054 }
0055 
0056 static struct imx_iim_drvdata imx27_drvdata = {
0057     .nregs = 2 * 32,
0058 };
0059 
0060 static struct imx_iim_drvdata imx25_imx31_imx35_drvdata = {
0061     .nregs = 3 * 32,
0062 };
0063 
0064 static struct imx_iim_drvdata imx51_drvdata = {
0065     .nregs = 4 * 32,
0066 };
0067 
0068 static struct imx_iim_drvdata imx53_drvdata = {
0069     .nregs = 4 * 32 + 16,
0070 };
0071 
0072 static const struct of_device_id imx_iim_dt_ids[] = {
0073     {
0074         .compatible = "fsl,imx25-iim",
0075         .data = &imx25_imx31_imx35_drvdata,
0076     }, {
0077         .compatible = "fsl,imx27-iim",
0078         .data = &imx27_drvdata,
0079     }, {
0080         .compatible = "fsl,imx31-iim",
0081         .data = &imx25_imx31_imx35_drvdata,
0082     }, {
0083         .compatible = "fsl,imx35-iim",
0084         .data = &imx25_imx31_imx35_drvdata,
0085     }, {
0086         .compatible = "fsl,imx51-iim",
0087         .data = &imx51_drvdata,
0088     }, {
0089         .compatible = "fsl,imx53-iim",
0090         .data = &imx53_drvdata,
0091     }, {
0092         /* sentinel */
0093     },
0094 };
0095 MODULE_DEVICE_TABLE(of, imx_iim_dt_ids);
0096 
0097 static int imx_iim_probe(struct platform_device *pdev)
0098 {
0099     struct device *dev = &pdev->dev;
0100     struct iim_priv *iim;
0101     struct nvmem_device *nvmem;
0102     struct nvmem_config cfg = {};
0103     const struct imx_iim_drvdata *drvdata = NULL;
0104 
0105     iim = devm_kzalloc(dev, sizeof(*iim), GFP_KERNEL);
0106     if (!iim)
0107         return -ENOMEM;
0108 
0109     iim->base = devm_platform_ioremap_resource(pdev, 0);
0110     if (IS_ERR(iim->base))
0111         return PTR_ERR(iim->base);
0112 
0113     drvdata = of_device_get_match_data(&pdev->dev);
0114 
0115     iim->clk = devm_clk_get(dev, NULL);
0116     if (IS_ERR(iim->clk))
0117         return PTR_ERR(iim->clk);
0118 
0119     cfg.name = "imx-iim",
0120     cfg.read_only = true,
0121     cfg.word_size = 1,
0122     cfg.stride = 1,
0123     cfg.reg_read = imx_iim_read,
0124     cfg.dev = dev;
0125     cfg.size = drvdata->nregs;
0126     cfg.priv = iim;
0127 
0128     nvmem = devm_nvmem_register(dev, &cfg);
0129 
0130     return PTR_ERR_OR_ZERO(nvmem);
0131 }
0132 
0133 static struct platform_driver imx_iim_driver = {
0134     .probe  = imx_iim_probe,
0135     .driver = {
0136         .name   = "imx-iim",
0137         .of_match_table = imx_iim_dt_ids,
0138     },
0139 };
0140 module_platform_driver(imx_iim_driver);
0141 
0142 MODULE_AUTHOR("Michael Grzeschik <m.grzeschik@pengutronix.de>");
0143 MODULE_DESCRIPTION("i.MX IIM driver");
0144 MODULE_LICENSE("GPL v2");