Changeset 39338
- Timestamp:
- 2014-01-20T11:22:56+01:00 (4 years ago)
- Location:
- trunk/target/linux/generic/files
- Files:
-
- 3 edited
-
drivers/net/phy/ar8216.c (modified) (7 diffs)
-
drivers/net/phy/ar8216.h (modified) (2 diffs)
-
include/linux/ar8216_platform.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/target/linux/generic/files/drivers/net/phy/ar8216.c
r39337 r39338 35 35 #include <linux/workqueue.h> 36 36 #include <linux/of_device.h> 37 #include <linux/leds.h> 38 #include <linux/gpio.h> 37 39 38 40 #include "ar8216.h" … … 83 85 }; 84 86 87 enum ar8327_led_pattern { 88 AR8327_LED_PATTERN_OFF = 0, 89 AR8327_LED_PATTERN_BLINK, 90 AR8327_LED_PATTERN_ON, 91 AR8327_LED_PATTERN_RULE, 92 }; 93 94 struct ar8327_led_entry { 95 unsigned reg; 96 unsigned shift; 97 }; 98 99 struct ar8327_led { 100 struct led_classdev cdev; 101 struct ar8xxx_priv *sw_priv; 102 103 char *name; 104 bool active_low; 105 u8 led_num; 106 enum ar8327_led_mode mode; 107 108 struct mutex mutex; 109 spinlock_t lock; 110 struct work_struct led_work; 111 bool enable_hw_mode; 112 enum ar8327_led_pattern pattern; 113 }; 114 85 115 struct ar8327_data { 86 116 u32 port0_status; 87 117 u32 port6_status; 118 119 struct ar8327_led **leds; 120 unsigned int num_leds; 88 121 }; 89 122 … … 1091 1124 } 1092 1125 1126 #define AR8327_LED_ENTRY(_num, _reg, _shift) \ 1127 [_num] = { .reg = (_reg), .shift = (_shift) } 1128 1129 static const struct ar8327_led_entry 1130 ar8327_led_map[AR8327_NUM_LEDS] = { 1131 AR8327_LED_ENTRY(AR8327_LED_PHY0_0, 0, 14), 1132 AR8327_LED_ENTRY(AR8327_LED_PHY0_1, 1, 14), 1133 AR8327_LED_ENTRY(AR8327_LED_PHY0_2, 2, 14), 1134 1135 AR8327_LED_ENTRY(AR8327_LED_PHY1_0, 3, 8), 1136 AR8327_LED_ENTRY(AR8327_LED_PHY1_1, 3, 10), 1137 AR8327_LED_ENTRY(AR8327_LED_PHY1_2, 3, 12), 1138 1139 AR8327_LED_ENTRY(AR8327_LED_PHY2_0, 3, 14), 1140 AR8327_LED_ENTRY(AR8327_LED_PHY2_1, 3, 16), 1141 AR8327_LED_ENTRY(AR8327_LED_PHY2_2, 3, 18), 1142 1143 AR8327_LED_ENTRY(AR8327_LED_PHY3_0, 3, 20), 1144 AR8327_LED_ENTRY(AR8327_LED_PHY3_1, 3, 22), 1145 AR8327_LED_ENTRY(AR8327_LED_PHY3_2, 3, 24), 1146 1147 AR8327_LED_ENTRY(AR8327_LED_PHY4_0, 0, 30), 1148 AR8327_LED_ENTRY(AR8327_LED_PHY4_1, 1, 30), 1149 AR8327_LED_ENTRY(AR8327_LED_PHY4_2, 2, 30), 1150 }; 1151 1152 static void 1153 ar8327_set_led_pattern(struct ar8xxx_priv *priv, unsigned int led_num, 1154 enum ar8327_led_pattern pattern) 1155 { 1156 const struct ar8327_led_entry *entry; 1157 1158 entry = &ar8327_led_map[led_num]; 1159 ar8xxx_rmw(priv, AR8327_REG_LED_CTRL(entry->reg), 1160 (3 << entry->shift), pattern << entry->shift); 1161 } 1162 1163 static void 1164 ar8327_led_work_func(struct work_struct *work) 1165 { 1166 struct ar8327_led *aled; 1167 u8 pattern; 1168 1169 aled = container_of(work, struct ar8327_led, led_work); 1170 1171 spin_lock(&aled->lock); 1172 pattern = aled->pattern; 1173 spin_unlock(&aled->lock); 1174 1175 ar8327_set_led_pattern(aled->sw_priv, aled->led_num, 1176 pattern); 1177 } 1178 1179 static void 1180 ar8327_led_schedule_change(struct ar8327_led *aled, u8 pattern) 1181 { 1182 if (aled->pattern == pattern) 1183 return; 1184 1185 aled->pattern = pattern; 1186 schedule_work(&aled->led_work); 1187 } 1188 1189 static inline struct ar8327_led * 1190 led_cdev_to_ar8327_led(struct led_classdev *led_cdev) 1191 { 1192 return container_of(led_cdev, struct ar8327_led, cdev); 1193 } 1194 1195 static int 1196 ar8327_led_blink_set(struct led_classdev *led_cdev, 1197 unsigned long *delay_on, 1198 unsigned long *delay_off) 1199 { 1200 struct ar8327_led *aled = led_cdev_to_ar8327_led(led_cdev); 1201 1202 if (*delay_on == 0 && *delay_off == 0) { 1203 *delay_on = 125; 1204 *delay_off = 125; 1205 } 1206 1207 if (*delay_on != 125 || *delay_off != 125) { 1208 /* 1209 * The hardware only supports blinking at 4Hz. Fall back 1210 * to software implementation in other cases. 1211 */ 1212 return -EINVAL; 1213 } 1214 1215 spin_lock(&aled->lock); 1216 1217 aled->enable_hw_mode = false; 1218 ar8327_led_schedule_change(aled, AR8327_LED_PATTERN_BLINK); 1219 1220 spin_unlock(&aled->lock); 1221 1222 return 0; 1223 } 1224 1225 static void 1226 ar8327_led_set_brightness(struct led_classdev *led_cdev, 1227 enum led_brightness brightness) 1228 { 1229 struct ar8327_led *aled = led_cdev_to_ar8327_led(led_cdev); 1230 u8 pattern; 1231 bool active; 1232 1233 active = (brightness != LED_OFF); 1234 active ^= aled->active_low; 1235 1236 pattern = (active) ? AR8327_LED_PATTERN_ON : 1237 AR8327_LED_PATTERN_OFF; 1238 1239 spin_lock(&aled->lock); 1240 1241 aled->enable_hw_mode = false; 1242 ar8327_led_schedule_change(aled, pattern); 1243 1244 spin_unlock(&aled->lock); 1245 } 1246 1247 static ssize_t 1248 ar8327_led_enable_hw_mode_show(struct device *dev, 1249 struct device_attribute *attr, 1250 char *buf) 1251 { 1252 struct led_classdev *led_cdev = dev_get_drvdata(dev); 1253 struct ar8327_led *aled = led_cdev_to_ar8327_led(led_cdev); 1254 ssize_t ret = 0; 1255 1256 spin_lock(&aled->lock); 1257 ret += sprintf(buf, "%d\n", aled->enable_hw_mode); 1258 spin_unlock(&aled->lock); 1259 1260 return ret; 1261 } 1262 1263 static ssize_t 1264 ar8327_led_enable_hw_mode_store(struct device *dev, 1265 struct device_attribute *attr, 1266 const char *buf, 1267 size_t size) 1268 { 1269 struct led_classdev *led_cdev = dev_get_drvdata(dev); 1270 struct ar8327_led *aled = led_cdev_to_ar8327_led(led_cdev); 1271 u8 pattern; 1272 u8 value; 1273 int ret; 1274 1275 ret = kstrtou8(buf, 10, &value); 1276 if (ret < 0) 1277 return -EINVAL; 1278 1279 spin_lock(&aled->lock); 1280 1281 aled->enable_hw_mode = !!value; 1282 if (aled->enable_hw_mode) 1283 pattern = AR8327_LED_PATTERN_RULE; 1284 else 1285 pattern = AR8327_LED_PATTERN_OFF; 1286 1287 ar8327_led_schedule_change(aled, pattern); 1288 1289 spin_unlock(&aled->lock); 1290 1291 return size; 1292 } 1293 1294 static DEVICE_ATTR(enable_hw_mode, S_IRUGO | S_IWUSR, 1295 ar8327_led_enable_hw_mode_show, 1296 ar8327_led_enable_hw_mode_store); 1297 1298 static int 1299 ar8327_led_register(struct ar8xxx_priv *priv, struct ar8327_led *aled) 1300 { 1301 int ret; 1302 1303 ret = led_classdev_register(NULL, &aled->cdev); 1304 if (ret < 0) 1305 return ret; 1306 1307 if (aled->mode == AR8327_LED_MODE_HW) { 1308 ret = device_create_file(aled->cdev.dev, 1309 &dev_attr_enable_hw_mode); 1310 if (ret) 1311 goto err_unregister; 1312 } 1313 1314 return 0; 1315 1316 err_unregister: 1317 led_classdev_unregister(&aled->cdev); 1318 return ret; 1319 } 1320 1321 static void 1322 ar8327_led_unregister(struct ar8327_led *aled) 1323 { 1324 if (aled->mode == AR8327_LED_MODE_HW) 1325 device_remove_file(aled->cdev.dev, &dev_attr_enable_hw_mode); 1326 1327 led_classdev_unregister(&aled->cdev); 1328 cancel_work_sync(&aled->led_work); 1329 } 1330 1331 static int 1332 ar8327_led_create(struct ar8xxx_priv *priv, 1333 const struct ar8327_led_info *led_info) 1334 { 1335 struct ar8327_data *data = &priv->chip_data.ar8327; 1336 struct ar8327_led *aled; 1337 int ret; 1338 1339 if (!IS_ENABLED(CONFIG_AR8216_PHY_LEDS)) 1340 return 0; 1341 1342 if (!led_info->name) 1343 return -EINVAL; 1344 1345 if (led_info->led_num >= AR8327_NUM_LEDS) 1346 return -EINVAL; 1347 1348 aled = kzalloc(sizeof(*aled) + strlen(led_info->name) + 1, 1349 GFP_KERNEL); 1350 if (!aled) 1351 return -ENOMEM; 1352 1353 aled->sw_priv = priv; 1354 aled->led_num = led_info->led_num; 1355 aled->active_low = led_info->active_low; 1356 aled->mode = led_info->mode; 1357 1358 if (aled->mode == AR8327_LED_MODE_HW) 1359 aled->enable_hw_mode = true; 1360 1361 aled->name = (char *)(aled + 1); 1362 strcpy(aled->name, led_info->name); 1363 1364 aled->cdev.name = aled->name; 1365 aled->cdev.brightness_set = ar8327_led_set_brightness; 1366 aled->cdev.blink_set = ar8327_led_blink_set; 1367 aled->cdev.default_trigger = led_info->default_trigger; 1368 1369 spin_lock_init(&aled->lock); 1370 mutex_init(&aled->mutex); 1371 INIT_WORK(&aled->led_work, ar8327_led_work_func); 1372 1373 ret = ar8327_led_register(priv, aled); 1374 if (ret) 1375 goto err_free; 1376 1377 data->leds[data->num_leds++] = aled; 1378 1379 return 0; 1380 1381 err_free: 1382 kfree(aled); 1383 return ret; 1384 } 1385 1386 static void 1387 ar8327_led_destroy(struct ar8327_led *aled) 1388 { 1389 ar8327_led_unregister(aled); 1390 kfree(aled); 1391 } 1392 1393 static void 1394 ar8327_leds_init(struct ar8xxx_priv *priv) 1395 { 1396 struct ar8327_data *data; 1397 unsigned i; 1398 1399 if (!IS_ENABLED(CONFIG_AR8216_PHY_LEDS)) 1400 return; 1401 1402 data = &priv->chip_data.ar8327; 1403 1404 for (i = 0; i < data->num_leds; i++) { 1405 struct ar8327_led *aled; 1406 1407 aled = data->leds[i]; 1408 1409 if (aled->enable_hw_mode) 1410 aled->pattern = AR8327_LED_PATTERN_RULE; 1411 else 1412 aled->pattern = AR8327_LED_PATTERN_OFF; 1413 1414 ar8327_set_led_pattern(priv, aled->led_num, aled->pattern); 1415 } 1416 } 1417 1418 static void 1419 ar8327_leds_cleanup(struct ar8xxx_priv *priv) 1420 { 1421 struct ar8327_data *data = &priv->chip_data.ar8327; 1422 unsigned i; 1423 1424 if (!IS_ENABLED(CONFIG_AR8216_PHY_LEDS)) 1425 return; 1426 1427 for (i = 0; i < data->num_leds; i++) { 1428 struct ar8327_led *aled; 1429 1430 aled = data->leds[i]; 1431 ar8327_led_destroy(aled); 1432 } 1433 1434 kfree(data->leds); 1435 } 1436 1093 1437 static int 1094 1438 ar8327_hw_config_pdata(struct ar8xxx_priv *priv, … … 1159 1503 1160 1504 priv->write(priv, AR8327_REG_POWER_ON_STRIP, new_pos); 1505 1506 if (pdata->leds && pdata->num_leds) { 1507 int i; 1508 1509 data->leds = kzalloc(pdata->num_leds * sizeof(void *), 1510 GFP_KERNEL); 1511 if (!data->leds) 1512 return -ENOMEM; 1513 1514 for (i = 0; i < pdata->num_leds; i++) 1515 ar8327_led_create(priv, &pdata->leds[i]); 1516 } 1161 1517 1162 1518 return 0; … … 1223 1579 return ret; 1224 1580 1581 ar8327_leds_init(priv); 1582 1225 1583 bus = priv->mii_bus; 1226 1584 for (i = 0; i < AR8327_NUM_PHYS; i++) { … … 1238 1596 1239 1597 return 0; 1598 } 1599 1600 static void 1601 ar8327_cleanup(struct ar8xxx_priv *priv) 1602 { 1603 ar8327_leds_cleanup(priv); 1240 1604 } 1241 1605 … … 1396 1760 .caps = AR8XXX_CAP_GIGE | AR8XXX_CAP_MIB_COUNTERS, 1397 1761 .hw_init = ar8327_hw_init, 1762 .cleanup = ar8327_cleanup, 1398 1763 .init_globals = ar8327_init_globals, 1399 1764 .init_port = ar8327_init_port, -
trunk/target/linux/generic/files/drivers/net/phy/ar8216.h
r38952 r39338 291 291 292 292 #define AR8327_NUM_PORTS 7 293 #define AR8327_NUM_LEDS 15 293 294 #define AR8327_NUM_PHYS 5 294 295 #define AR8327_PORTS_ALL 0x7f 296 #define AR8327_NUM_LED_CTRL_REGS 4 295 297 296 298 #define AR8327_REG_MASK 0x000 … … 344 346 345 347 #define AR8327_REG_SERVICE_TAG 0x048 348 #define AR8327_REG_LED_CTRL(_i) (0x050 + (_i) * 4) 346 349 #define AR8327_REG_LED_CTRL0 0x050 347 350 #define AR8327_REG_LED_CTRL1 0x054 -
trunk/target/linux/generic/files/include/linux/ar8216_platform.h
r36798 r39338 77 77 }; 78 78 79 enum ar8327_led_num { 80 AR8327_LED_PHY0_0 = 0, 81 AR8327_LED_PHY0_1, 82 AR8327_LED_PHY0_2, 83 AR8327_LED_PHY1_0, 84 AR8327_LED_PHY1_1, 85 AR8327_LED_PHY1_2, 86 AR8327_LED_PHY2_0, 87 AR8327_LED_PHY2_1, 88 AR8327_LED_PHY2_2, 89 AR8327_LED_PHY3_0, 90 AR8327_LED_PHY3_1, 91 AR8327_LED_PHY3_2, 92 AR8327_LED_PHY4_0, 93 AR8327_LED_PHY4_1, 94 AR8327_LED_PHY4_2, 95 }; 96 97 enum ar8327_led_mode { 98 AR8327_LED_MODE_HW = 0, 99 AR8327_LED_MODE_SW, 100 }; 101 102 struct ar8327_led_info { 103 const char *name; 104 const char *default_trigger; 105 bool active_low; 106 enum ar8327_led_num led_num; 107 enum ar8327_led_mode mode; 108 }; 109 110 #define AR8327_LED_INFO(_led, _mode, _name) { \ 111 .name = (_name), \ 112 .led_num = AR8327_LED_ ## _led, \ 113 .mode = AR8327_LED_MODE_ ## _mode \ 114 } 115 79 116 struct ar8327_platform_data { 80 117 struct ar8327_pad_cfg *pad0_cfg; … … 87 124 88 125 int (*get_port_link)(unsigned port); 126 127 unsigned num_leds; 128 const struct ar8327_led_info *leds; 89 129 }; 90 130
Note: See TracChangeset
for help on using the changeset viewer.
