10
10
#include <linux/kernel.h>
11
11
#include <linux/module.h>
12
12
#include <linux/platform_device.h>
13
+ #include <linux/regmap.h>
13
14
#include <linux/seq_file.h>
14
15
#include <linux/slab.h>
15
16
#include <linux/err.h>
@@ -76,15 +77,15 @@ enum {
76
77
* @dev_id: ALE version/SoC id
77
78
* @features: features supported by ALE
78
79
* @tbl_entries: number of ALE entries
79
- * @major_ver_mask: mask of ALE Major Version Value in ALE_IDVER reg.
80
+ * @reg_fields: pointer to array of register field configuration
80
81
* @nu_switch_ale: NU Switch ALE
81
82
* @vlan_entry_tbl: ALE vlan entry fields description tbl
82
83
*/
83
84
struct cpsw_ale_dev_id {
84
85
const char * dev_id ;
85
86
u32 features ;
86
87
u32 tbl_entries ;
87
- u32 major_ver_mask ;
88
+ const struct reg_field * reg_fields ;
88
89
bool nu_switch_ale ;
89
90
const struct ale_entry_fld * vlan_entry_tbl ;
90
91
};
@@ -1292,54 +1293,66 @@ void cpsw_ale_stop(struct cpsw_ale *ale)
1292
1293
cpsw_ale_control_set (ale , 0 , ALE_ENABLE , 0 );
1293
1294
}
1294
1295
1296
+ static const struct reg_field ale_fields_cpsw [] = {
1297
+ /* CPSW_ALE_IDVER_REG */
1298
+ [MINOR_VER ] = REG_FIELD (ALE_IDVER , 0 , 7 ),
1299
+ [MAJOR_VER ] = REG_FIELD (ALE_IDVER , 8 , 15 ),
1300
+ };
1301
+
1302
+ static const struct reg_field ale_fields_cpsw_nu [] = {
1303
+ /* CPSW_ALE_IDVER_REG */
1304
+ [MINOR_VER ] = REG_FIELD (ALE_IDVER , 0 , 7 ),
1305
+ [MAJOR_VER ] = REG_FIELD (ALE_IDVER , 8 , 10 ),
1306
+ };
1307
+
1295
1308
static const struct cpsw_ale_dev_id cpsw_ale_id_match [] = {
1296
1309
{
1297
1310
/* am3/4/5, dra7. dm814x, 66ak2hk-gbe */
1298
1311
.dev_id = "cpsw" ,
1299
1312
.tbl_entries = 1024 ,
1300
- .major_ver_mask = 0xff ,
1313
+ .reg_fields = ale_fields_cpsw ,
1301
1314
.vlan_entry_tbl = vlan_entry_cpsw ,
1302
1315
},
1303
1316
{
1304
1317
/* 66ak2h_xgbe */
1305
1318
.dev_id = "66ak2h-xgbe" ,
1306
1319
.tbl_entries = 2048 ,
1307
- .major_ver_mask = 0xff ,
1320
+ .reg_fields = ale_fields_cpsw ,
1308
1321
.vlan_entry_tbl = vlan_entry_cpsw ,
1309
1322
},
1310
1323
{
1311
1324
.dev_id = "66ak2el" ,
1312
1325
.features = CPSW_ALE_F_STATUS_REG ,
1313
- .major_ver_mask = 0x7 ,
1326
+ .reg_fields = ale_fields_cpsw_nu ,
1314
1327
.nu_switch_ale = true,
1315
1328
.vlan_entry_tbl = vlan_entry_nu ,
1316
1329
},
1317
1330
{
1318
1331
.dev_id = "66ak2g" ,
1319
1332
.features = CPSW_ALE_F_STATUS_REG ,
1320
1333
.tbl_entries = 64 ,
1321
- .major_ver_mask = 0x7 ,
1334
+ .reg_fields = ale_fields_cpsw_nu ,
1322
1335
.nu_switch_ale = true,
1323
1336
.vlan_entry_tbl = vlan_entry_nu ,
1324
1337
},
1325
1338
{
1326
1339
.dev_id = "am65x-cpsw2g" ,
1327
1340
.features = CPSW_ALE_F_STATUS_REG | CPSW_ALE_F_HW_AUTOAGING ,
1328
1341
.tbl_entries = 64 ,
1329
- .major_ver_mask = 0x7 ,
1342
+ .reg_fields = ale_fields_cpsw_nu ,
1330
1343
.nu_switch_ale = true,
1331
1344
.vlan_entry_tbl = vlan_entry_nu ,
1332
1345
},
1333
1346
{
1334
1347
.dev_id = "j721e-cpswxg" ,
1335
1348
.features = CPSW_ALE_F_STATUS_REG | CPSW_ALE_F_HW_AUTOAGING ,
1336
- .major_ver_mask = 0x7 ,
1349
+ .reg_fields = ale_fields_cpsw_nu ,
1337
1350
.vlan_entry_tbl = vlan_entry_k3_cpswxg ,
1338
1351
},
1339
1352
{
1340
1353
.dev_id = "am64-cpswxg" ,
1341
1354
.features = CPSW_ALE_F_STATUS_REG | CPSW_ALE_F_HW_AUTOAGING ,
1342
- .major_ver_mask = 0x7 ,
1355
+ .reg_fields = ale_fields_cpsw_nu ,
1343
1356
.vlan_entry_tbl = vlan_entry_k3_cpswxg ,
1344
1357
.tbl_entries = 512 ,
1345
1358
},
@@ -1361,41 +1374,76 @@ cpsw_ale_dev_id *cpsw_ale_match_id(const struct cpsw_ale_dev_id *id,
1361
1374
return NULL ;
1362
1375
}
1363
1376
1377
+ static const struct regmap_config ale_regmap_cfg = {
1378
+ .reg_bits = 32 ,
1379
+ .val_bits = 32 ,
1380
+ .reg_stride = 4 ,
1381
+ .name = "cpsw-ale" ,
1382
+ };
1383
+
1384
+ static int cpsw_ale_regfield_init (struct cpsw_ale * ale )
1385
+ {
1386
+ const struct reg_field * reg_fields = ale -> params .reg_fields ;
1387
+ struct device * dev = ale -> params .dev ;
1388
+ struct regmap * regmap = ale -> regmap ;
1389
+ int i ;
1390
+
1391
+ for (i = 0 ; i < ALE_FIELDS_MAX ; i ++ ) {
1392
+ ale -> fields [i ] = devm_regmap_field_alloc (dev , regmap ,
1393
+ reg_fields [i ]);
1394
+ if (IS_ERR (ale -> fields [i ])) {
1395
+ dev_err (dev , "Unable to allocate regmap field %d\n" , i );
1396
+ return PTR_ERR (ale -> fields [i ]);
1397
+ }
1398
+ }
1399
+
1400
+ return 0 ;
1401
+ }
1402
+
1364
1403
struct cpsw_ale * cpsw_ale_create (struct cpsw_ale_params * params )
1365
1404
{
1366
1405
const struct cpsw_ale_dev_id * ale_dev_id ;
1406
+ u32 ale_entries , rev_major , rev_minor ;
1367
1407
struct cpsw_ale * ale ;
1368
- u32 rev , ale_entries ;
1408
+ int ret ;
1369
1409
1370
1410
ale_dev_id = cpsw_ale_match_id (cpsw_ale_id_match , params -> dev_id );
1371
1411
if (!ale_dev_id )
1372
1412
return ERR_PTR (- EINVAL );
1373
1413
1374
1414
params -> ale_entries = ale_dev_id -> tbl_entries ;
1375
- params -> major_ver_mask = ale_dev_id -> major_ver_mask ;
1376
1415
params -> nu_switch_ale = ale_dev_id -> nu_switch_ale ;
1416
+ params -> reg_fields = ale_dev_id -> reg_fields ;
1377
1417
1378
1418
ale = devm_kzalloc (params -> dev , sizeof (* ale ), GFP_KERNEL );
1379
1419
if (!ale )
1380
1420
return ERR_PTR (- ENOMEM );
1421
+ ale -> regmap = devm_regmap_init_mmio (params -> dev , params -> ale_regs ,
1422
+ & ale_regmap_cfg );
1423
+ if (IS_ERR (ale -> regmap )) {
1424
+ dev_err (params -> dev , "Couldn't create CPSW ALE regmap\n" );
1425
+ return ERR_PTR (- ENOMEM );
1426
+ }
1427
+
1428
+ ale -> params = * params ;
1429
+ ret = cpsw_ale_regfield_init (ale );
1430
+ if (ret )
1431
+ return ERR_PTR (ret );
1381
1432
1382
1433
ale -> p0_untag_vid_mask = devm_bitmap_zalloc (params -> dev , VLAN_N_VID ,
1383
1434
GFP_KERNEL );
1384
1435
if (!ale -> p0_untag_vid_mask )
1385
1436
return ERR_PTR (- ENOMEM );
1386
1437
1387
- ale -> params = * params ;
1388
1438
ale -> ageout = ale -> params .ale_ageout * HZ ;
1389
1439
ale -> features = ale_dev_id -> features ;
1390
1440
ale -> vlan_entry_tbl = ale_dev_id -> vlan_entry_tbl ;
1391
1441
1392
- rev = readl_relaxed (ale -> params .ale_regs + ALE_IDVER );
1393
- ale -> version =
1394
- (ALE_VERSION_MAJOR (rev , ale -> params .major_ver_mask ) << 8 ) |
1395
- ALE_VERSION_MINOR (rev );
1442
+ regmap_field_read (ale -> fields [MINOR_VER ], & rev_minor );
1443
+ regmap_field_read (ale -> fields [MAJOR_VER ], & rev_major );
1444
+ ale -> version = rev_major << 8 | rev_minor ;
1396
1445
dev_info (ale -> params .dev , "initialized cpsw ale version %d.%d\n" ,
1397
- ALE_VERSION_MAJOR (rev , ale -> params .major_ver_mask ),
1398
- ALE_VERSION_MINOR (rev ));
1446
+ rev_major , rev_minor );
1399
1447
1400
1448
if (ale -> features & CPSW_ALE_F_STATUS_REG &&
1401
1449
!ale -> params .ale_entries ) {
0 commit comments