Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * i.MX8 OCOTP fusebox driver
0004  *
0005  * Copyright 2019 NXP
0006  *
0007  * Peng Fan <peng.fan@nxp.com>
0008  */
0009 
0010 #include <linux/arm-smccc.h>
0011 #include <linux/firmware/imx/sci.h>
0012 #include <linux/module.h>
0013 #include <linux/nvmem-provider.h>
0014 #include <linux/of_device.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/slab.h>
0017 
0018 #define IMX_SIP_OTP_WRITE       0xc200000B
0019 
0020 enum ocotp_devtype {
0021     IMX8QXP,
0022     IMX8QM,
0023 };
0024 
0025 #define ECC_REGION  BIT(0)
0026 #define HOLE_REGION BIT(1)
0027 
0028 struct ocotp_region {
0029     u32 start;
0030     u32 end;
0031     u32 flag;
0032 };
0033 
0034 struct ocotp_devtype_data {
0035     int devtype;
0036     int nregs;
0037     u32 num_region;
0038     struct ocotp_region region[];
0039 };
0040 
0041 struct ocotp_priv {
0042     struct device *dev;
0043     const struct ocotp_devtype_data *data;
0044     struct imx_sc_ipc *nvmem_ipc;
0045 };
0046 
0047 struct imx_sc_msg_misc_fuse_read {
0048     struct imx_sc_rpc_msg hdr;
0049     u32 word;
0050 } __packed;
0051 
0052 static DEFINE_MUTEX(scu_ocotp_mutex);
0053 
0054 static struct ocotp_devtype_data imx8qxp_data = {
0055     .devtype = IMX8QXP,
0056     .nregs = 800,
0057     .num_region = 3,
0058     .region = {
0059         {0x10, 0x10f, ECC_REGION},
0060         {0x110, 0x21F, HOLE_REGION},
0061         {0x220, 0x31F, ECC_REGION},
0062     },
0063 };
0064 
0065 static struct ocotp_devtype_data imx8qm_data = {
0066     .devtype = IMX8QM,
0067     .nregs = 800,
0068     .num_region = 2,
0069     .region = {
0070         {0x10, 0x10f, ECC_REGION},
0071         {0x1a0, 0x1ff, ECC_REGION},
0072     },
0073 };
0074 
0075 static bool in_hole(void *context, u32 index)
0076 {
0077     struct ocotp_priv *priv = context;
0078     const struct ocotp_devtype_data *data = priv->data;
0079     int i;
0080 
0081     for (i = 0; i < data->num_region; i++) {
0082         if (data->region[i].flag & HOLE_REGION) {
0083             if ((index >= data->region[i].start) &&
0084                 (index <= data->region[i].end))
0085                 return true;
0086         }
0087     }
0088 
0089     return false;
0090 }
0091 
0092 static bool in_ecc(void *context, u32 index)
0093 {
0094     struct ocotp_priv *priv = context;
0095     const struct ocotp_devtype_data *data = priv->data;
0096     int i;
0097 
0098     for (i = 0; i < data->num_region; i++) {
0099         if (data->region[i].flag & ECC_REGION) {
0100             if ((index >= data->region[i].start) &&
0101                 (index <= data->region[i].end))
0102                 return true;
0103         }
0104     }
0105 
0106     return false;
0107 }
0108 
0109 static int imx_sc_misc_otp_fuse_read(struct imx_sc_ipc *ipc, u32 word,
0110                      u32 *val)
0111 {
0112     struct imx_sc_msg_misc_fuse_read msg;
0113     struct imx_sc_rpc_msg *hdr = &msg.hdr;
0114     int ret;
0115 
0116     hdr->ver = IMX_SC_RPC_VERSION;
0117     hdr->svc = IMX_SC_RPC_SVC_MISC;
0118     hdr->func = IMX_SC_MISC_FUNC_OTP_FUSE_READ;
0119     hdr->size = 2;
0120 
0121     msg.word = word;
0122 
0123     ret = imx_scu_call_rpc(ipc, &msg, true);
0124     if (ret)
0125         return ret;
0126 
0127     *val = msg.word;
0128 
0129     return 0;
0130 }
0131 
0132 static int imx_scu_ocotp_read(void *context, unsigned int offset,
0133                   void *val, size_t bytes)
0134 {
0135     struct ocotp_priv *priv = context;
0136     u32 count, index, num_bytes;
0137     u32 *buf;
0138     void *p;
0139     int i, ret;
0140 
0141     index = offset;
0142     num_bytes = round_up(bytes, 4);
0143     count = num_bytes >> 2;
0144 
0145     if (count > (priv->data->nregs - index))
0146         count = priv->data->nregs - index;
0147 
0148     p = kzalloc(num_bytes, GFP_KERNEL);
0149     if (!p)
0150         return -ENOMEM;
0151 
0152     mutex_lock(&scu_ocotp_mutex);
0153 
0154     buf = p;
0155 
0156     for (i = index; i < (index + count); i++) {
0157         if (in_hole(context, i)) {
0158             *buf++ = 0;
0159             continue;
0160         }
0161 
0162         ret = imx_sc_misc_otp_fuse_read(priv->nvmem_ipc, i, buf);
0163         if (ret) {
0164             mutex_unlock(&scu_ocotp_mutex);
0165             kfree(p);
0166             return ret;
0167         }
0168         buf++;
0169     }
0170 
0171     memcpy(val, (u8 *)p, bytes);
0172 
0173     mutex_unlock(&scu_ocotp_mutex);
0174 
0175     kfree(p);
0176 
0177     return 0;
0178 }
0179 
0180 static int imx_scu_ocotp_write(void *context, unsigned int offset,
0181                    void *val, size_t bytes)
0182 {
0183     struct ocotp_priv *priv = context;
0184     struct arm_smccc_res res;
0185     u32 *buf = val;
0186     u32 tmp;
0187     u32 index;
0188     int ret;
0189 
0190     /* allow only writing one complete OTP word at a time */
0191     if (bytes != 4)
0192         return -EINVAL;
0193 
0194     index = offset;
0195 
0196     if (in_hole(context, index))
0197         return -EINVAL;
0198 
0199     if (in_ecc(context, index)) {
0200         pr_warn("ECC region, only program once\n");
0201         mutex_lock(&scu_ocotp_mutex);
0202         ret = imx_sc_misc_otp_fuse_read(priv->nvmem_ipc, index, &tmp);
0203         mutex_unlock(&scu_ocotp_mutex);
0204         if (ret)
0205             return ret;
0206         if (tmp) {
0207             pr_warn("ECC region, already has value: %x\n", tmp);
0208             return -EIO;
0209         }
0210     }
0211 
0212     mutex_lock(&scu_ocotp_mutex);
0213 
0214     arm_smccc_smc(IMX_SIP_OTP_WRITE, index, *buf, 0, 0, 0, 0, 0, &res);
0215 
0216     mutex_unlock(&scu_ocotp_mutex);
0217 
0218     return res.a0;
0219 }
0220 
0221 static struct nvmem_config imx_scu_ocotp_nvmem_config = {
0222     .name = "imx-scu-ocotp",
0223     .read_only = false,
0224     .word_size = 4,
0225     .stride = 1,
0226     .owner = THIS_MODULE,
0227     .reg_read = imx_scu_ocotp_read,
0228     .reg_write = imx_scu_ocotp_write,
0229 };
0230 
0231 static const struct of_device_id imx_scu_ocotp_dt_ids[] = {
0232     { .compatible = "fsl,imx8qxp-scu-ocotp", (void *)&imx8qxp_data },
0233     { .compatible = "fsl,imx8qm-scu-ocotp", (void *)&imx8qm_data },
0234     { },
0235 };
0236 MODULE_DEVICE_TABLE(of, imx_scu_ocotp_dt_ids);
0237 
0238 static int imx_scu_ocotp_probe(struct platform_device *pdev)
0239 {
0240     struct device *dev = &pdev->dev;
0241     struct ocotp_priv *priv;
0242     struct nvmem_device *nvmem;
0243     int ret;
0244 
0245     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0246     if (!priv)
0247         return -ENOMEM;
0248 
0249     ret = imx_scu_get_handle(&priv->nvmem_ipc);
0250     if (ret)
0251         return ret;
0252 
0253     priv->data = of_device_get_match_data(dev);
0254     priv->dev = dev;
0255     imx_scu_ocotp_nvmem_config.size = 4 * priv->data->nregs;
0256     imx_scu_ocotp_nvmem_config.dev = dev;
0257     imx_scu_ocotp_nvmem_config.priv = priv;
0258     nvmem = devm_nvmem_register(dev, &imx_scu_ocotp_nvmem_config);
0259 
0260     return PTR_ERR_OR_ZERO(nvmem);
0261 }
0262 
0263 static struct platform_driver imx_scu_ocotp_driver = {
0264     .probe  = imx_scu_ocotp_probe,
0265     .driver = {
0266         .name   = "imx_scu_ocotp",
0267         .of_match_table = imx_scu_ocotp_dt_ids,
0268     },
0269 };
0270 module_platform_driver(imx_scu_ocotp_driver);
0271 
0272 MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
0273 MODULE_DESCRIPTION("i.MX8 SCU OCOTP fuse box driver");
0274 MODULE_LICENSE("GPL v2");