pci: Make Rockchip PCIe voltage regulators optional
[oweals/u-boot.git] / drivers / misc / rockchip-otp.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4  */
5
6 #include <common.h>
7 #include <asm/io.h>
8 #include <command.h>
9 #include <dm.h>
10 #include <linux/bitops.h>
11 #include <linux/delay.h>
12 #include <misc.h>
13
14 /* OTP Register Offsets */
15 #define OTPC_SBPI_CTRL                  0x0020
16 #define OTPC_SBPI_CMD_VALID_PRE         0x0024
17 #define OTPC_SBPI_CS_VALID_PRE          0x0028
18 #define OTPC_SBPI_STATUS                0x002C
19 #define OTPC_USER_CTRL                  0x0100
20 #define OTPC_USER_ADDR                  0x0104
21 #define OTPC_USER_ENABLE                0x0108
22 #define OTPC_USER_QP                    0x0120
23 #define OTPC_USER_Q                     0x0124
24 #define OTPC_INT_STATUS                 0x0304
25 #define OTPC_SBPI_CMD0_OFFSET           0x1000
26 #define OTPC_SBPI_CMD1_OFFSET           0x1004
27
28 /* OTP Register bits and masks */
29 #define OTPC_USER_ADDR_MASK             GENMASK(31, 16)
30 #define OTPC_USE_USER                   BIT(0)
31 #define OTPC_USE_USER_MASK              GENMASK(16, 16)
32 #define OTPC_USER_FSM_ENABLE            BIT(0)
33 #define OTPC_USER_FSM_ENABLE_MASK       GENMASK(16, 16)
34 #define OTPC_SBPI_DONE                  BIT(1)
35 #define OTPC_USER_DONE                  BIT(2)
36
37 #define SBPI_DAP_ADDR                   0x02
38 #define SBPI_DAP_ADDR_SHIFT             8
39 #define SBPI_DAP_ADDR_MASK              GENMASK(31, 24)
40 #define SBPI_CMD_VALID_MASK             GENMASK(31, 16)
41 #define SBPI_DAP_CMD_WRF                0xC0
42 #define SBPI_DAP_REG_ECC                0x3A
43 #define SBPI_ECC_ENABLE                 0x00
44 #define SBPI_ECC_DISABLE                0x09
45 #define SBPI_ENABLE                     BIT(0)
46 #define SBPI_ENABLE_MASK                GENMASK(16, 16)
47
48 #define OTPC_TIMEOUT                    10000
49
50 struct rockchip_otp_platdata {
51         void __iomem *base;
52         unsigned long secure_conf_base;
53         unsigned long otp_mask_base;
54 };
55
56 static int rockchip_otp_wait_status(struct rockchip_otp_platdata *otp,
57                                     u32 flag)
58 {
59         int delay = OTPC_TIMEOUT;
60
61         while (!(readl(otp->base + OTPC_INT_STATUS) & flag)) {
62                 udelay(1);
63                 delay--;
64                 if (delay <= 0) {
65                         printf("%s: wait init status timeout\n", __func__);
66                         return -ETIMEDOUT;
67                 }
68         }
69
70         /* clean int status */
71         writel(flag, otp->base + OTPC_INT_STATUS);
72
73         return 0;
74 }
75
76 static int rockchip_otp_ecc_enable(struct rockchip_otp_platdata *otp,
77                                    bool enable)
78 {
79         int ret = 0;
80
81         writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT),
82                otp->base + OTPC_SBPI_CTRL);
83
84         writel(SBPI_CMD_VALID_MASK | 0x1, otp->base + OTPC_SBPI_CMD_VALID_PRE);
85         writel(SBPI_DAP_CMD_WRF | SBPI_DAP_REG_ECC,
86                otp->base + OTPC_SBPI_CMD0_OFFSET);
87
88         if (enable)
89                 writel(SBPI_ECC_ENABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
90         else
91                 writel(SBPI_ECC_DISABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
92
93         writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
94
95         ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE);
96         if (ret < 0)
97                 printf("%s timeout during ecc_enable\n", __func__);
98
99         return ret;
100 }
101
102 static int rockchip_px30_otp_read(struct udevice *dev, int offset,
103                                   void *buf, int size)
104 {
105         struct rockchip_otp_platdata *otp = dev_get_platdata(dev);
106         u8 *buffer = buf;
107         int ret = 0;
108
109         ret = rockchip_otp_ecc_enable(otp, false);
110         if (ret < 0) {
111                 printf("%s rockchip_otp_ecc_enable err\n", __func__);
112                 return ret;
113         }
114
115         writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
116         udelay(5);
117         while (size--) {
118                 writel(offset++ | OTPC_USER_ADDR_MASK,
119                        otp->base + OTPC_USER_ADDR);
120                 writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
121                        otp->base + OTPC_USER_ENABLE);
122
123                 ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE);
124                 if (ret < 0) {
125                         printf("%s timeout during read setup\n", __func__);
126                         goto read_end;
127                 }
128
129                 *buffer++ = readb(otp->base + OTPC_USER_Q);
130         }
131
132 read_end:
133         writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
134
135         return ret;
136 }
137
138 static int rockchip_otp_read(struct udevice *dev, int offset,
139                              void *buf, int size)
140 {
141         return rockchip_px30_otp_read(dev, offset, buf, size);
142 }
143
144 static const struct misc_ops rockchip_otp_ops = {
145         .read = rockchip_otp_read,
146 };
147
148 static int rockchip_otp_ofdata_to_platdata(struct udevice *dev)
149 {
150         struct rockchip_otp_platdata *otp = dev_get_platdata(dev);
151
152         otp->base = dev_read_addr_ptr(dev);
153
154         return 0;
155 }
156
157 static const struct udevice_id rockchip_otp_ids[] = {
158         {
159                 .compatible = "rockchip,px30-otp",
160                 .data = (ulong)&rockchip_px30_otp_read,
161         },
162         {
163                 .compatible = "rockchip,rk3308-otp",
164                 .data = (ulong)&rockchip_px30_otp_read,
165         },
166         {}
167 };
168
169 U_BOOT_DRIVER(rockchip_otp) = {
170         .name = "rockchip_otp",
171         .id = UCLASS_MISC,
172         .of_match = rockchip_otp_ids,
173         .ops = &rockchip_otp_ops,
174         .ofdata_to_platdata = rockchip_otp_ofdata_to_platdata,
175         .platdata_auto_alloc_size = sizeof(struct rockchip_otp_platdata),
176 };