0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include "buffer_icap.h"
0034
0035
0036 #define XHI_MAX_BUFFER_BYTES 2048
0037 #define XHI_MAX_BUFFER_INTS (XHI_MAX_BUFFER_BYTES >> 2)
0038
0039
0040 #define XHI_DEVICE_READ_ERROR -1
0041 #define XHI_DEVICE_WRITE_ERROR -2
0042 #define XHI_BUFFER_OVERFLOW_ERROR -3
0043
0044 #define XHI_DEVICE_READ 0x1
0045 #define XHI_DEVICE_WRITE 0x0
0046
0047
0048 #define XHI_CYCLE_DONE 0
0049 #define XHI_CYCLE_EXECUTING 1
0050
0051
0052
0053
0054 #define XHI_SIZE_REG_OFFSET 0x800L
0055
0056 #define XHI_BRAM_OFFSET_REG_OFFSET 0x804L
0057
0058 #define XHI_RNC_REG_OFFSET 0x808L
0059
0060 #define XHI_STATUS_REG_OFFSET 0x80CL
0061
0062
0063 #define XHI_CONFIGURE 0x0UL
0064 #define XHI_READBACK 0x1UL
0065
0066
0067 #define XHI_NOT_FINISHED 0x0UL
0068 #define XHI_FINISHED 0x1UL
0069
0070 #define XHI_BUFFER_START 0
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088 u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata)
0089 {
0090 return in_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET);
0091 }
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101 static inline u32 buffer_icap_get_bram(void __iomem *base_address,
0102 u32 offset)
0103 {
0104 return in_be32(base_address + (offset << 2));
0105 }
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 static inline bool buffer_icap_busy(void __iomem *base_address)
0116 {
0117 u32 status = in_be32(base_address + XHI_STATUS_REG_OFFSET);
0118 return (status & 1) == XHI_NOT_FINISHED;
0119 }
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 static inline void buffer_icap_set_size(void __iomem *base_address,
0130 u32 data)
0131 {
0132 out_be32(base_address + XHI_SIZE_REG_OFFSET, data);
0133 }
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143 static inline void buffer_icap_set_offset(void __iomem *base_address,
0144 u32 data)
0145 {
0146 out_be32(base_address + XHI_BRAM_OFFSET_REG_OFFSET, data);
0147 }
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159 static inline void buffer_icap_set_rnc(void __iomem *base_address,
0160 u32 data)
0161 {
0162 out_be32(base_address + XHI_RNC_REG_OFFSET, data);
0163 }
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174 static inline void buffer_icap_set_bram(void __iomem *base_address,
0175 u32 offset, u32 data)
0176 {
0177 out_be32(base_address + (offset << 2), data);
0178 }
0179
0180
0181
0182
0183
0184
0185
0186
0187 static int buffer_icap_device_read(struct hwicap_drvdata *drvdata,
0188 u32 offset, u32 count)
0189 {
0190
0191 s32 retries = 0;
0192 void __iomem *base_address = drvdata->base_address;
0193
0194 if (buffer_icap_busy(base_address))
0195 return -EBUSY;
0196
0197 if ((offset + count) > XHI_MAX_BUFFER_INTS)
0198 return -EINVAL;
0199
0200
0201 buffer_icap_set_size(base_address, (count << 2));
0202 buffer_icap_set_offset(base_address, offset);
0203 buffer_icap_set_rnc(base_address, XHI_READBACK);
0204
0205 while (buffer_icap_busy(base_address)) {
0206 retries++;
0207 if (retries > XHI_MAX_RETRIES)
0208 return -EBUSY;
0209 }
0210 return 0;
0211
0212 };
0213
0214
0215
0216
0217
0218
0219
0220
0221 static int buffer_icap_device_write(struct hwicap_drvdata *drvdata,
0222 u32 offset, u32 count)
0223 {
0224
0225 s32 retries = 0;
0226 void __iomem *base_address = drvdata->base_address;
0227
0228 if (buffer_icap_busy(base_address))
0229 return -EBUSY;
0230
0231 if ((offset + count) > XHI_MAX_BUFFER_INTS)
0232 return -EINVAL;
0233
0234
0235 buffer_icap_set_size(base_address, count << 2);
0236 buffer_icap_set_offset(base_address, offset);
0237 buffer_icap_set_rnc(base_address, XHI_CONFIGURE);
0238
0239 while (buffer_icap_busy(base_address)) {
0240 retries++;
0241 if (retries > XHI_MAX_RETRIES)
0242 return -EBUSY;
0243 }
0244 return 0;
0245
0246 };
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256 void buffer_icap_reset(struct hwicap_drvdata *drvdata)
0257 {
0258 out_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET, 0xFEFE);
0259 }
0260
0261
0262
0263
0264
0265
0266
0267 int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
0268 u32 size)
0269 {
0270 int status;
0271 s32 buffer_count = 0;
0272 bool dirty = false;
0273 u32 i;
0274 void __iomem *base_address = drvdata->base_address;
0275
0276
0277 for (i = 0, buffer_count = 0; i < size; i++) {
0278
0279
0280 buffer_icap_set_bram(base_address, buffer_count, data[i]);
0281 dirty = true;
0282
0283 if (buffer_count < XHI_MAX_BUFFER_INTS - 1) {
0284 buffer_count++;
0285 continue;
0286 }
0287
0288
0289 status = buffer_icap_device_write(
0290 drvdata,
0291 XHI_BUFFER_START,
0292 XHI_MAX_BUFFER_INTS);
0293 if (status != 0) {
0294
0295 buffer_icap_reset(drvdata);
0296 return status;
0297 }
0298
0299 buffer_count = 0;
0300 dirty = false;
0301 }
0302
0303
0304 if (dirty) {
0305
0306 status = buffer_icap_device_write(drvdata, XHI_BUFFER_START,
0307 buffer_count);
0308 if (status != 0) {
0309
0310 buffer_icap_reset(drvdata);
0311 }
0312 return status;
0313 }
0314
0315 return 0;
0316 };
0317
0318
0319
0320
0321
0322
0323
0324 int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,
0325 u32 size)
0326 {
0327 int status;
0328 s32 buffer_count = 0;
0329 u32 i;
0330 void __iomem *base_address = drvdata->base_address;
0331
0332
0333 for (i = 0, buffer_count = XHI_MAX_BUFFER_INTS; i < size; i++) {
0334 if (buffer_count == XHI_MAX_BUFFER_INTS) {
0335 u32 words_remaining = size - i;
0336 u32 words_to_read =
0337 words_remaining <
0338 XHI_MAX_BUFFER_INTS ? words_remaining :
0339 XHI_MAX_BUFFER_INTS;
0340
0341
0342 status = buffer_icap_device_read(
0343 drvdata,
0344 XHI_BUFFER_START,
0345 words_to_read);
0346 if (status != 0) {
0347
0348 buffer_icap_reset(drvdata);
0349 return status;
0350 }
0351
0352 buffer_count = 0;
0353 }
0354
0355
0356 data[i] = buffer_icap_get_bram(base_address, buffer_count);
0357 buffer_count++;
0358 }
0359
0360 return 0;
0361 };