@@ -85,13 +85,14 @@ static int sunxi_sid_read(void *context, unsigned int offset,
85
85
}
86
86
87
87
static int sun8i_sid_register_readout (const struct sunxi_sid * sid ,
88
- const unsigned int word )
88
+ const unsigned int offset ,
89
+ u32 * out )
89
90
{
90
91
u32 reg_val ;
91
92
int ret ;
92
93
93
94
/* Set word, lock access, and set read command */
94
- reg_val = (word & SUN8I_SID_OFFSET_MASK )
95
+ reg_val = (offset & SUN8I_SID_OFFSET_MASK )
95
96
<< SUN8I_SID_OFFSET_SHIFT ;
96
97
reg_val |= SUN8I_SID_OP_LOCK | SUN8I_SID_READ ;
97
98
writel (reg_val , sid -> base + SUN8I_SID_PRCTL );
@@ -101,7 +102,49 @@ static int sun8i_sid_register_readout(const struct sunxi_sid *sid,
101
102
if (ret )
102
103
return ret ;
103
104
105
+ if (out )
106
+ * out = readl (sid -> base + SUN8I_SID_RDKEY );
107
+
104
108
writel (0 , sid -> base + SUN8I_SID_PRCTL );
109
+
110
+ return 0 ;
111
+ }
112
+
113
+ /*
114
+ * On Allwinner H3, the value on the 0x200 offset of the SID controller seems
115
+ * to be not reliable at all.
116
+ * Read by the registers instead.
117
+ */
118
+ static int sun8i_sid_read_byte_by_reg (const struct sunxi_sid * sid ,
119
+ const unsigned int offset ,
120
+ u8 * out )
121
+ {
122
+ u32 word ;
123
+ int ret ;
124
+
125
+ ret = sun8i_sid_register_readout (sid , offset & ~0x03 , & word );
126
+
127
+ if (ret )
128
+ return ret ;
129
+
130
+ * out = (word >> ((offset & 0x3 ) * 8 )) & 0xff ;
131
+
132
+ return 0 ;
133
+ }
134
+
135
+ static int sun8i_sid_read_by_reg (void * context , unsigned int offset ,
136
+ void * val , size_t bytes )
137
+ {
138
+ struct sunxi_sid * sid = context ;
139
+ u8 * buf = val ;
140
+ int ret ;
141
+
142
+ while (bytes -- ) {
143
+ ret = sun8i_sid_read_byte_by_reg (sid , offset ++ , buf ++ );
144
+ if (ret )
145
+ return ret ;
146
+ }
147
+
105
148
return 0 ;
106
149
}
107
150
@@ -131,26 +174,12 @@ static int sunxi_sid_probe(struct platform_device *pdev)
131
174
132
175
size = cfg -> size ;
133
176
134
- if (cfg -> need_register_readout ) {
135
- /*
136
- * H3's SID controller have a bug that the value at 0x200
137
- * offset is not the correct value when the hardware is reseted.
138
- * However, after doing a register-based read operation, the
139
- * value become right.
140
- * Do a full read operation here, but ignore its value
141
- * (as it's more fast to read by direct MMIO value than
142
- * with registers)
143
- */
144
- for (i = 0 ; i < (size >> 2 ); i ++ ) {
145
- ret = sun8i_sid_register_readout (sid , i );
146
- if (ret )
147
- return ret ;
148
- }
149
- }
150
-
151
177
econfig .size = size ;
152
178
econfig .dev = dev ;
153
- econfig .reg_read = sunxi_sid_read ;
179
+ if (cfg -> need_register_readout )
180
+ econfig .reg_read = sun8i_sid_read_by_reg ;
181
+ else
182
+ econfig .reg_read = sunxi_sid_read ;
154
183
econfig .priv = sid ;
155
184
nvmem = nvmem_register (& econfig );
156
185
if (IS_ERR (nvmem ))
@@ -163,7 +192,7 @@ static int sunxi_sid_probe(struct platform_device *pdev)
163
192
}
164
193
165
194
for (i = 0 ; i < size ; i ++ )
166
- randomness [i ] = sunxi_sid_read_byte ( sid , i );
195
+ econfig . reg_read ( sid , i , & randomness [i ], 1 );
167
196
168
197
add_device_randomness (randomness , size );
169
198
kfree (randomness );
0 commit comments