144 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * i.MX IIM driver4 *5 * Copyright (c) 2017 Pengutronix, Michael Grzeschik <m.grzeschik@pengutronix.de>6 *7 * Based on the barebox iim driver,8 * Copyright (c) 2010 Baruch Siach <baruch@tkos.co.il>,9 * Orex Computed Radiography10 */11 12#include <linux/device.h>13#include <linux/io.h>14#include <linux/module.h>15#include <linux/nvmem-provider.h>16#include <linux/of.h>17#include <linux/platform_device.h>18#include <linux/slab.h>19#include <linux/clk.h>20 21#define IIM_BANK_BASE(n) (0x800 + 0x400 * (n))22 23struct imx_iim_drvdata {24 unsigned int nregs;25};26 27struct iim_priv {28 void __iomem *base;29 struct clk *clk;30};31 32static int imx_iim_read(void *context, unsigned int offset,33 void *buf, size_t bytes)34{35 struct iim_priv *iim = context;36 int i, ret;37 u8 *buf8 = buf;38 39 ret = clk_prepare_enable(iim->clk);40 if (ret)41 return ret;42 43 for (i = offset; i < offset + bytes; i++) {44 int bank = i >> 5;45 int reg = i & 0x1f;46 47 *buf8++ = readl(iim->base + IIM_BANK_BASE(bank) + reg * 4);48 }49 50 clk_disable_unprepare(iim->clk);51 52 return 0;53}54 55static struct imx_iim_drvdata imx27_drvdata = {56 .nregs = 2 * 32,57};58 59static struct imx_iim_drvdata imx25_imx31_imx35_drvdata = {60 .nregs = 3 * 32,61};62 63static struct imx_iim_drvdata imx51_drvdata = {64 .nregs = 4 * 32,65};66 67static struct imx_iim_drvdata imx53_drvdata = {68 .nregs = 4 * 32 + 16,69};70 71static const struct of_device_id imx_iim_dt_ids[] = {72 {73 .compatible = "fsl,imx25-iim",74 .data = &imx25_imx31_imx35_drvdata,75 }, {76 .compatible = "fsl,imx27-iim",77 .data = &imx27_drvdata,78 }, {79 .compatible = "fsl,imx31-iim",80 .data = &imx25_imx31_imx35_drvdata,81 }, {82 .compatible = "fsl,imx35-iim",83 .data = &imx25_imx31_imx35_drvdata,84 }, {85 .compatible = "fsl,imx51-iim",86 .data = &imx51_drvdata,87 }, {88 .compatible = "fsl,imx53-iim",89 .data = &imx53_drvdata,90 }, {91 /* sentinel */92 },93};94MODULE_DEVICE_TABLE(of, imx_iim_dt_ids);95 96static int imx_iim_probe(struct platform_device *pdev)97{98 struct device *dev = &pdev->dev;99 struct iim_priv *iim;100 struct nvmem_device *nvmem;101 struct nvmem_config cfg = {};102 const struct imx_iim_drvdata *drvdata = NULL;103 104 iim = devm_kzalloc(dev, sizeof(*iim), GFP_KERNEL);105 if (!iim)106 return -ENOMEM;107 108 iim->base = devm_platform_ioremap_resource(pdev, 0);109 if (IS_ERR(iim->base))110 return PTR_ERR(iim->base);111 112 drvdata = of_device_get_match_data(&pdev->dev);113 114 iim->clk = devm_clk_get(dev, NULL);115 if (IS_ERR(iim->clk))116 return PTR_ERR(iim->clk);117 118 cfg.name = "imx-iim",119 cfg.read_only = true,120 cfg.word_size = 1,121 cfg.stride = 1,122 cfg.reg_read = imx_iim_read,123 cfg.dev = dev;124 cfg.size = drvdata->nregs;125 cfg.priv = iim;126 127 nvmem = devm_nvmem_register(dev, &cfg);128 129 return PTR_ERR_OR_ZERO(nvmem);130}131 132static struct platform_driver imx_iim_driver = {133 .probe = imx_iim_probe,134 .driver = {135 .name = "imx-iim",136 .of_match_table = imx_iim_dt_ids,137 },138};139module_platform_driver(imx_iim_driver);140 141MODULE_AUTHOR("Michael Grzeschik <m.grzeschik@pengutronix.de>");142MODULE_DESCRIPTION("i.MX IIM driver");143MODULE_LICENSE("GPL v2");144