Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Rockchip OTP Driver
0004  *
0005  * Copyright (c) 2018 Rockchip Electronics Co. Ltd.
0006  * Author: Finley Xiao <finley.xiao@rock-chips.com>
0007  */
0008 
0009 #include <linux/clk.h>
0010 #include <linux/delay.h>
0011 #include <linux/device.h>
0012 #include <linux/io.h>
0013 #include <linux/iopoll.h>
0014 #include <linux/module.h>
0015 #include <linux/nvmem-provider.h>
0016 #include <linux/reset.h>
0017 #include <linux/slab.h>
0018 #include <linux/of.h>
0019 #include <linux/of_platform.h>
0020 #include <linux/platform_device.h>
0021 
0022 /* OTP Register Offsets */
0023 #define OTPC_SBPI_CTRL          0x0020
0024 #define OTPC_SBPI_CMD_VALID_PRE     0x0024
0025 #define OTPC_SBPI_CS_VALID_PRE      0x0028
0026 #define OTPC_SBPI_STATUS        0x002C
0027 #define OTPC_USER_CTRL          0x0100
0028 #define OTPC_USER_ADDR          0x0104
0029 #define OTPC_USER_ENABLE        0x0108
0030 #define OTPC_USER_Q         0x0124
0031 #define OTPC_INT_STATUS         0x0304
0032 #define OTPC_SBPI_CMD0_OFFSET       0x1000
0033 #define OTPC_SBPI_CMD1_OFFSET       0x1004
0034 
0035 /* OTP Register bits and masks */
0036 #define OTPC_USER_ADDR_MASK     GENMASK(31, 16)
0037 #define OTPC_USE_USER           BIT(0)
0038 #define OTPC_USE_USER_MASK      GENMASK(16, 16)
0039 #define OTPC_USER_FSM_ENABLE        BIT(0)
0040 #define OTPC_USER_FSM_ENABLE_MASK   GENMASK(16, 16)
0041 #define OTPC_SBPI_DONE          BIT(1)
0042 #define OTPC_USER_DONE          BIT(2)
0043 
0044 #define SBPI_DAP_ADDR           0x02
0045 #define SBPI_DAP_ADDR_SHIFT     8
0046 #define SBPI_DAP_ADDR_MASK      GENMASK(31, 24)
0047 #define SBPI_CMD_VALID_MASK     GENMASK(31, 16)
0048 #define SBPI_DAP_CMD_WRF        0xC0
0049 #define SBPI_DAP_REG_ECC        0x3A
0050 #define SBPI_ECC_ENABLE         0x00
0051 #define SBPI_ECC_DISABLE        0x09
0052 #define SBPI_ENABLE         BIT(0)
0053 #define SBPI_ENABLE_MASK        GENMASK(16, 16)
0054 
0055 #define OTPC_TIMEOUT            10000
0056 
0057 struct rockchip_otp {
0058     struct device *dev;
0059     void __iomem *base;
0060     struct clk_bulk_data    *clks;
0061     int num_clks;
0062     struct reset_control *rst;
0063 };
0064 
0065 /* list of required clocks */
0066 static const char * const rockchip_otp_clocks[] = {
0067     "otp", "apb_pclk", "phy",
0068 };
0069 
0070 struct rockchip_data {
0071     int size;
0072 };
0073 
0074 static int rockchip_otp_reset(struct rockchip_otp *otp)
0075 {
0076     int ret;
0077 
0078     ret = reset_control_assert(otp->rst);
0079     if (ret) {
0080         dev_err(otp->dev, "failed to assert otp phy %d\n", ret);
0081         return ret;
0082     }
0083 
0084     udelay(2);
0085 
0086     ret = reset_control_deassert(otp->rst);
0087     if (ret) {
0088         dev_err(otp->dev, "failed to deassert otp phy %d\n", ret);
0089         return ret;
0090     }
0091 
0092     return 0;
0093 }
0094 
0095 static int rockchip_otp_wait_status(struct rockchip_otp *otp, u32 flag)
0096 {
0097     u32 status = 0;
0098     int ret;
0099 
0100     ret = readl_poll_timeout_atomic(otp->base + OTPC_INT_STATUS, status,
0101                     (status & flag), 1, OTPC_TIMEOUT);
0102     if (ret)
0103         return ret;
0104 
0105     /* clean int status */
0106     writel(flag, otp->base + OTPC_INT_STATUS);
0107 
0108     return 0;
0109 }
0110 
0111 static int rockchip_otp_ecc_enable(struct rockchip_otp *otp, bool enable)
0112 {
0113     int ret = 0;
0114 
0115     writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT),
0116            otp->base + OTPC_SBPI_CTRL);
0117 
0118     writel(SBPI_CMD_VALID_MASK | 0x1, otp->base + OTPC_SBPI_CMD_VALID_PRE);
0119     writel(SBPI_DAP_CMD_WRF | SBPI_DAP_REG_ECC,
0120            otp->base + OTPC_SBPI_CMD0_OFFSET);
0121     if (enable)
0122         writel(SBPI_ECC_ENABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
0123     else
0124         writel(SBPI_ECC_DISABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
0125 
0126     writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
0127 
0128     ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE);
0129     if (ret < 0)
0130         dev_err(otp->dev, "timeout during ecc_enable\n");
0131 
0132     return ret;
0133 }
0134 
0135 static int rockchip_otp_read(void *context, unsigned int offset,
0136                  void *val, size_t bytes)
0137 {
0138     struct rockchip_otp *otp = context;
0139     u8 *buf = val;
0140     int ret = 0;
0141 
0142     ret = clk_bulk_prepare_enable(otp->num_clks, otp->clks);
0143     if (ret < 0) {
0144         dev_err(otp->dev, "failed to prepare/enable clks\n");
0145         return ret;
0146     }
0147 
0148     ret = rockchip_otp_reset(otp);
0149     if (ret) {
0150         dev_err(otp->dev, "failed to reset otp phy\n");
0151         goto disable_clks;
0152     }
0153 
0154     ret = rockchip_otp_ecc_enable(otp, false);
0155     if (ret < 0) {
0156         dev_err(otp->dev, "rockchip_otp_ecc_enable err\n");
0157         goto disable_clks;
0158     }
0159 
0160     writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
0161     udelay(5);
0162     while (bytes--) {
0163         writel(offset++ | OTPC_USER_ADDR_MASK,
0164                otp->base + OTPC_USER_ADDR);
0165         writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
0166                otp->base + OTPC_USER_ENABLE);
0167         ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE);
0168         if (ret < 0) {
0169             dev_err(otp->dev, "timeout during read setup\n");
0170             goto read_end;
0171         }
0172         *buf++ = readb(otp->base + OTPC_USER_Q);
0173     }
0174 
0175 read_end:
0176     writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
0177 disable_clks:
0178     clk_bulk_disable_unprepare(otp->num_clks, otp->clks);
0179 
0180     return ret;
0181 }
0182 
0183 static struct nvmem_config otp_config = {
0184     .name = "rockchip-otp",
0185     .owner = THIS_MODULE,
0186     .read_only = true,
0187     .stride = 1,
0188     .word_size = 1,
0189     .reg_read = rockchip_otp_read,
0190 };
0191 
0192 static const struct rockchip_data px30_data = {
0193     .size = 0x40,
0194 };
0195 
0196 static const struct of_device_id rockchip_otp_match[] = {
0197     {
0198         .compatible = "rockchip,px30-otp",
0199         .data = (void *)&px30_data,
0200     },
0201     {
0202         .compatible = "rockchip,rk3308-otp",
0203         .data = (void *)&px30_data,
0204     },
0205     { /* sentinel */ },
0206 };
0207 MODULE_DEVICE_TABLE(of, rockchip_otp_match);
0208 
0209 static int rockchip_otp_probe(struct platform_device *pdev)
0210 {
0211     struct device *dev = &pdev->dev;
0212     struct rockchip_otp *otp;
0213     const struct rockchip_data *data;
0214     struct nvmem_device *nvmem;
0215     int ret, i;
0216 
0217     data = of_device_get_match_data(dev);
0218     if (!data) {
0219         dev_err(dev, "failed to get match data\n");
0220         return -EINVAL;
0221     }
0222 
0223     otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp),
0224                GFP_KERNEL);
0225     if (!otp)
0226         return -ENOMEM;
0227 
0228     otp->dev = dev;
0229     otp->base = devm_platform_ioremap_resource(pdev, 0);
0230     if (IS_ERR(otp->base))
0231         return PTR_ERR(otp->base);
0232 
0233     otp->num_clks = ARRAY_SIZE(rockchip_otp_clocks);
0234     otp->clks = devm_kcalloc(dev, otp->num_clks,
0235                      sizeof(*otp->clks), GFP_KERNEL);
0236     if (!otp->clks)
0237         return -ENOMEM;
0238 
0239     for (i = 0; i < otp->num_clks; ++i)
0240         otp->clks[i].id = rockchip_otp_clocks[i];
0241 
0242     ret = devm_clk_bulk_get(dev, otp->num_clks, otp->clks);
0243     if (ret)
0244         return ret;
0245 
0246     otp->rst = devm_reset_control_get(dev, "phy");
0247     if (IS_ERR(otp->rst))
0248         return PTR_ERR(otp->rst);
0249 
0250     otp_config.size = data->size;
0251     otp_config.priv = otp;
0252     otp_config.dev = dev;
0253     nvmem = devm_nvmem_register(dev, &otp_config);
0254 
0255     return PTR_ERR_OR_ZERO(nvmem);
0256 }
0257 
0258 static struct platform_driver rockchip_otp_driver = {
0259     .probe = rockchip_otp_probe,
0260     .driver = {
0261         .name = "rockchip-otp",
0262         .of_match_table = rockchip_otp_match,
0263     },
0264 };
0265 
0266 module_platform_driver(rockchip_otp_driver);
0267 MODULE_DESCRIPTION("Rockchip OTP driver");
0268 MODULE_LICENSE("GPL v2");