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 "fifo_icap.h"
0034
0035
0036 #define XHI_GIER_OFFSET 0x1C
0037 #define XHI_IPISR_OFFSET 0x20
0038 #define XHI_IPIER_OFFSET 0x28
0039 #define XHI_WF_OFFSET 0x100
0040 #define XHI_RF_OFFSET 0x104
0041 #define XHI_SZ_OFFSET 0x108
0042 #define XHI_CR_OFFSET 0x10C
0043 #define XHI_SR_OFFSET 0x110
0044 #define XHI_WFV_OFFSET 0x114
0045 #define XHI_RFO_OFFSET 0x118
0046
0047
0048
0049 #define XHI_GIER_GIE_MASK 0x80000000
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 #define XHI_IPIXR_RFULL_MASK 0x00000008
0067 #define XHI_IPIXR_WEMPTY_MASK 0x00000004
0068 #define XHI_IPIXR_RDP_MASK 0x00000002
0069 #define XHI_IPIXR_WRP_MASK 0x00000001
0070 #define XHI_IPIXR_ALL_MASK 0x0000000F
0071
0072
0073 #define XHI_CR_SW_RESET_MASK 0x00000008
0074 #define XHI_CR_FIFO_CLR_MASK 0x00000004
0075 #define XHI_CR_READ_MASK 0x00000002
0076 #define XHI_CR_WRITE_MASK 0x00000001
0077
0078
0079 #define XHI_WFO_MAX_VACANCY 1024
0080 #define XHI_RFO_MAX_OCCUPANCY 256
0081
0082
0083 #define XHI_MAX_READ_TRANSACTION_WORDS 0xFFF
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 static inline void fifo_icap_fifo_write(struct hwicap_drvdata *drvdata,
0094 u32 data)
0095 {
0096 dev_dbg(drvdata->dev, "fifo_write: %x\n", data);
0097 out_be32(drvdata->base_address + XHI_WF_OFFSET, data);
0098 }
0099
0100
0101
0102
0103
0104
0105
0106 static inline u32 fifo_icap_fifo_read(struct hwicap_drvdata *drvdata)
0107 {
0108 u32 data = in_be32(drvdata->base_address + XHI_RF_OFFSET);
0109 dev_dbg(drvdata->dev, "fifo_read: %x\n", data);
0110 return data;
0111 }
0112
0113
0114
0115
0116
0117
0118 static inline void fifo_icap_set_read_size(struct hwicap_drvdata *drvdata,
0119 u32 data)
0120 {
0121 out_be32(drvdata->base_address + XHI_SZ_OFFSET, data);
0122 }
0123
0124
0125
0126
0127
0128 static inline void fifo_icap_start_config(struct hwicap_drvdata *drvdata)
0129 {
0130 out_be32(drvdata->base_address + XHI_CR_OFFSET, XHI_CR_WRITE_MASK);
0131 dev_dbg(drvdata->dev, "configuration started\n");
0132 }
0133
0134
0135
0136
0137
0138 static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata)
0139 {
0140 out_be32(drvdata->base_address + XHI_CR_OFFSET, XHI_CR_READ_MASK);
0141 dev_dbg(drvdata->dev, "readback started\n");
0142 }
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160 u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata)
0161 {
0162 u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET);
0163 dev_dbg(drvdata->dev, "Getting status = %x\n", status);
0164 return status;
0165 }
0166
0167
0168
0169
0170
0171 static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata)
0172 {
0173 u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET);
0174 return (status & XHI_SR_DONE_MASK) ? 0 : 1;
0175 }
0176
0177
0178
0179
0180
0181
0182
0183 static inline u32 fifo_icap_write_fifo_vacancy(
0184 struct hwicap_drvdata *drvdata)
0185 {
0186 return in_be32(drvdata->base_address + XHI_WFV_OFFSET);
0187 }
0188
0189
0190
0191
0192
0193
0194
0195 static inline u32 fifo_icap_read_fifo_occupancy(
0196 struct hwicap_drvdata *drvdata)
0197 {
0198 return in_be32(drvdata->base_address + XHI_RFO_OFFSET);
0199 }
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213 int fifo_icap_set_configuration(struct hwicap_drvdata *drvdata,
0214 u32 *frame_buffer, u32 num_words)
0215 {
0216
0217 u32 write_fifo_vacancy = 0;
0218 u32 retries = 0;
0219 u32 remaining_words;
0220
0221 dev_dbg(drvdata->dev, "fifo_set_configuration\n");
0222
0223
0224
0225
0226 if (fifo_icap_busy(drvdata))
0227 return -EBUSY;
0228
0229
0230
0231
0232 remaining_words = num_words;
0233
0234 while (remaining_words > 0) {
0235
0236
0237
0238 while (write_fifo_vacancy == 0) {
0239 write_fifo_vacancy =
0240 fifo_icap_write_fifo_vacancy(drvdata);
0241 retries++;
0242 if (retries > XHI_MAX_RETRIES)
0243 return -EIO;
0244 }
0245
0246
0247
0248
0249 while ((write_fifo_vacancy != 0) &&
0250 (remaining_words > 0)) {
0251 fifo_icap_fifo_write(drvdata, *frame_buffer);
0252
0253 remaining_words--;
0254 write_fifo_vacancy--;
0255 frame_buffer++;
0256 }
0257
0258 fifo_icap_start_config(drvdata);
0259 }
0260
0261
0262 while (fifo_icap_busy(drvdata)) {
0263 retries++;
0264 if (retries > XHI_MAX_RETRIES)
0265 break;
0266 }
0267
0268 dev_dbg(drvdata->dev, "done fifo_set_configuration\n");
0269
0270
0271
0272
0273
0274 if (remaining_words != 0)
0275 return -EIO;
0276
0277 return 0;
0278 }
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289 int fifo_icap_get_configuration(struct hwicap_drvdata *drvdata,
0290 u32 *frame_buffer, u32 num_words)
0291 {
0292
0293 u32 read_fifo_occupancy = 0;
0294 u32 retries = 0;
0295 u32 *data = frame_buffer;
0296 u32 remaining_words;
0297 u32 words_to_read;
0298
0299 dev_dbg(drvdata->dev, "fifo_get_configuration\n");
0300
0301
0302
0303
0304 if (fifo_icap_busy(drvdata))
0305 return -EBUSY;
0306
0307 remaining_words = num_words;
0308
0309 while (remaining_words > 0) {
0310 words_to_read = remaining_words;
0311
0312
0313 if (words_to_read > XHI_MAX_READ_TRANSACTION_WORDS)
0314 words_to_read = XHI_MAX_READ_TRANSACTION_WORDS;
0315
0316 remaining_words -= words_to_read;
0317
0318 fifo_icap_set_read_size(drvdata, words_to_read);
0319 fifo_icap_start_readback(drvdata);
0320
0321 while (words_to_read > 0) {
0322
0323 while (read_fifo_occupancy == 0) {
0324 read_fifo_occupancy =
0325 fifo_icap_read_fifo_occupancy(drvdata);
0326 retries++;
0327 if (retries > XHI_MAX_RETRIES)
0328 return -EIO;
0329 }
0330
0331 if (read_fifo_occupancy > words_to_read)
0332 read_fifo_occupancy = words_to_read;
0333
0334 words_to_read -= read_fifo_occupancy;
0335
0336
0337 while (read_fifo_occupancy != 0) {
0338 *data++ = fifo_icap_fifo_read(drvdata);
0339 read_fifo_occupancy--;
0340 }
0341 }
0342 }
0343
0344 dev_dbg(drvdata->dev, "done fifo_get_configuration\n");
0345
0346 return 0;
0347 }
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357 void fifo_icap_reset(struct hwicap_drvdata *drvdata)
0358 {
0359 u32 reg_data;
0360
0361
0362
0363
0364 reg_data = in_be32(drvdata->base_address + XHI_CR_OFFSET);
0365
0366 out_be32(drvdata->base_address + XHI_CR_OFFSET,
0367 reg_data | XHI_CR_SW_RESET_MASK);
0368
0369 out_be32(drvdata->base_address + XHI_CR_OFFSET,
0370 reg_data & (~XHI_CR_SW_RESET_MASK));
0371
0372 }
0373
0374
0375
0376
0377
0378 void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata)
0379 {
0380 u32 reg_data;
0381
0382
0383
0384
0385 reg_data = in_be32(drvdata->base_address + XHI_CR_OFFSET);
0386
0387 out_be32(drvdata->base_address + XHI_CR_OFFSET,
0388 reg_data | XHI_CR_FIFO_CLR_MASK);
0389
0390 out_be32(drvdata->base_address + XHI_CR_OFFSET,
0391 reg_data & (~XHI_CR_FIFO_CLR_MASK));
0392 }
0393