pd692x0.c (a6a6a98094116b60e5523a571d9443c53325f5b1) pd692x0.c (ae37dc574259f2750e9e2666591b752678fcd7cc)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Driver for the Microchip PD692X0 PoE PSE Controller driver (I2C bus)
4 *
5 * Copyright (c) 2023 Bootlin, Kory Maincent <kory.maincent@bootlin.com>
6 */
7
8#include <linux/delay.h>

--- 59 unchanged lines hidden (view full) ---

68 PD692X0_MSG_RESET,
69 PD692X0_MSG_GET_SYS_STATUS,
70 PD692X0_MSG_GET_SW_VER,
71 PD692X0_MSG_SET_TMP_PORT_MATRIX,
72 PD692X0_MSG_PRG_PORT_MATRIX,
73 PD692X0_MSG_SET_PORT_PARAM,
74 PD692X0_MSG_GET_PORT_STATUS,
75 PD692X0_MSG_DOWNLOAD_CMD,
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Driver for the Microchip PD692X0 PoE PSE Controller driver (I2C bus)
4 *
5 * Copyright (c) 2023 Bootlin, Kory Maincent <kory.maincent@bootlin.com>
6 */
7
8#include <linux/delay.h>

--- 59 unchanged lines hidden (view full) ---

68 PD692X0_MSG_RESET,
69 PD692X0_MSG_GET_SYS_STATUS,
70 PD692X0_MSG_GET_SW_VER,
71 PD692X0_MSG_SET_TMP_PORT_MATRIX,
72 PD692X0_MSG_PRG_PORT_MATRIX,
73 PD692X0_MSG_SET_PORT_PARAM,
74 PD692X0_MSG_GET_PORT_STATUS,
75 PD692X0_MSG_DOWNLOAD_CMD,
76 PD692X0_MSG_GET_PORT_CLASS,
76
77 /* add new message above here */
78 PD692X0_MSG_CNT
79};
80
81struct pd692x0_priv {
82 struct i2c_client *client;
83 struct pse_controller_dev pcdev;

--- 60 unchanged lines hidden (view full) ---

144 0x4e, 0x4e, 0x4e, 0x4e},
145 },
146 [PD692X0_MSG_DOWNLOAD_CMD] = {
147 .key = PD692X0_KEY_PRG,
148 .sub = {0xff, 0x99, 0x15},
149 .data = {0x16, 0x16, 0x99, 0x4e,
150 0x4e, 0x4e, 0x4e, 0x4e},
151 },
77
78 /* add new message above here */
79 PD692X0_MSG_CNT
80};
81
82struct pd692x0_priv {
83 struct i2c_client *client;
84 struct pse_controller_dev pcdev;

--- 60 unchanged lines hidden (view full) ---

145 0x4e, 0x4e, 0x4e, 0x4e},
146 },
147 [PD692X0_MSG_DOWNLOAD_CMD] = {
148 .key = PD692X0_KEY_PRG,
149 .sub = {0xff, 0x99, 0x15},
150 .data = {0x16, 0x16, 0x99, 0x4e,
151 0x4e, 0x4e, 0x4e, 0x4e},
152 },
153 [PD692X0_MSG_GET_PORT_CLASS] = {
154 .key = PD692X0_KEY_REQ,
155 .sub = {0x05, 0xc4},
156 .data = {0x4e, 0x4e, 0x4e, 0x4e,
157 0x4e, 0x4e, 0x4e, 0x4e},
158 },
152};
153
154static u8 pd692x0_build_msg(struct pd692x0_msg *msg, u8 echo)
155{
156 u8 *data = (u8 *)msg;
157 u16 chksum = 0;
158 int i;
159

--- 270 unchanged lines hidden (view full) ---

430 priv->admin_state[id] = ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED;
431 return 1;
432 } else {
433 priv->admin_state[id] = ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED;
434 return 0;
435 }
436}
437
159};
160
161static u8 pd692x0_build_msg(struct pd692x0_msg *msg, u8 echo)
162{
163 u8 *data = (u8 *)msg;
164 u16 chksum = 0;
165 int i;
166

--- 270 unchanged lines hidden (view full) ---

437 priv->admin_state[id] = ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED;
438 return 1;
439 } else {
440 priv->admin_state[id] = ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED;
441 return 0;
442 }
443}
444
445struct pd692x0_pse_ext_state_mapping {
446 u32 status_code;
447 enum ethtool_c33_pse_ext_state pse_ext_state;
448 u32 pse_ext_substate;
449};
450
451static const struct pd692x0_pse_ext_state_mapping
452pd692x0_pse_ext_state_map[] = {
453 {0x06, ETHTOOL_C33_PSE_EXT_STATE_OPTION_VPORT_LIM,
454 ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_HIGH_VOLTAGE},
455 {0x07, ETHTOOL_C33_PSE_EXT_STATE_OPTION_VPORT_LIM,
456 ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_LOW_VOLTAGE},
457 {0x08, ETHTOOL_C33_PSE_EXT_STATE_MR_PSE_ENABLE,
458 ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_PSE_ENABLE_DISABLE_PIN_ACTIVE},
459 {0x0C, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
460 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_NON_EXISTING_PORT},
461 {0x11, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
462 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNDEFINED_PORT},
463 {0x12, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
464 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_INTERNAL_HW_FAULT},
465 {0x1B, ETHTOOL_C33_PSE_EXT_STATE_OPTION_DETECT_TED,
466 ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_DETECT_TED_DET_IN_PROCESS},
467 {0x1C, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
468 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS},
469 {0x1E, ETHTOOL_C33_PSE_EXT_STATE_MR_MPS_VALID,
470 ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_MPS_VALID_DETECTED_UNDERLOAD},
471 {0x1F, ETHTOOL_C33_PSE_EXT_STATE_OVLD_DETECTED,
472 ETHTOOL_C33_PSE_EXT_SUBSTATE_OVLD_DETECTED_OVERLOAD},
473 {0x20, ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE,
474 ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_BUDGET_EXCEEDED},
475 {0x21, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
476 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_INTERNAL_HW_FAULT},
477 {0x22, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
478 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_CONFIG_CHANGE},
479 {0x24, ETHTOOL_C33_PSE_EXT_STATE_OPTION_VPORT_LIM,
480 ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_VOLTAGE_INJECTION},
481 {0x25, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
482 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS},
483 {0x34, ETHTOOL_C33_PSE_EXT_STATE_SHORT_DETECTED,
484 ETHTOOL_C33_PSE_EXT_SUBSTATE_SHORT_DETECTED_SHORT_CONDITION},
485 {0x35, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
486 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_DETECTED_OVER_TEMP},
487 {0x36, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
488 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_DETECTED_OVER_TEMP},
489 {0x37, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
490 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS},
491 {0x3C, ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE,
492 ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_PORT_PW_LIMIT_EXCEEDS_CONTROLLER_BUDGET},
493 {0x3D, ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE,
494 ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_PD_REQUEST_EXCEEDS_PORT_LIMIT},
495 {0x41, ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE,
496 ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_HW_PW_LIMIT},
497 {0x43, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
498 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS},
499 {0xA7, ETHTOOL_C33_PSE_EXT_STATE_OPTION_DETECT_TED,
500 ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_DETECT_TED_CONNECTION_CHECK_ERROR},
501 {0xA8, ETHTOOL_C33_PSE_EXT_STATE_MR_MPS_VALID,
502 ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_MPS_VALID_CONNECTION_OPEN},
503 { /* sentinel */ }
504};
505
506static void
507pd692x0_get_ext_state(struct ethtool_c33_pse_ext_state_info *c33_ext_state_info,
508 u32 status_code)
509{
510 const struct pd692x0_pse_ext_state_mapping *ext_state_map;
511
512 ext_state_map = pd692x0_pse_ext_state_map;
513 while (ext_state_map->status_code) {
514 if (ext_state_map->status_code == status_code) {
515 c33_ext_state_info->c33_pse_ext_state = ext_state_map->pse_ext_state;
516 c33_ext_state_info->__c33_pse_ext_substate = ext_state_map->pse_ext_substate;
517 return;
518 }
519 ext_state_map++;
520 }
521}
522
438static int pd692x0_ethtool_get_status(struct pse_controller_dev *pcdev,
439 unsigned long id,
440 struct netlink_ext_ack *extack,
441 struct pse_control_status *status)
442{
443 struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);
444 struct pd692x0_msg msg, buf = {0};
523static int pd692x0_ethtool_get_status(struct pse_controller_dev *pcdev,
524 unsigned long id,
525 struct netlink_ext_ack *extack,
526 struct pse_control_status *status)
527{
528 struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);
529 struct pd692x0_msg msg, buf = {0};
530 u32 class;
445 int ret;
446
447 ret = pd692x0_fw_unavailable(priv);
448 if (ret)
449 return ret;
450
451 msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_STATUS];
452 msg.sub[2] = id;

--- 13 unchanged lines hidden (view full) ---

466
467 if (buf.sub[1])
468 status->c33_admin_state = ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED;
469 else
470 status->c33_admin_state = ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED;
471
472 priv->admin_state[id] = status->c33_admin_state;
473
531 int ret;
532
533 ret = pd692x0_fw_unavailable(priv);
534 if (ret)
535 return ret;
536
537 msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_STATUS];
538 msg.sub[2] = id;

--- 13 unchanged lines hidden (view full) ---

552
553 if (buf.sub[1])
554 status->c33_admin_state = ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED;
555 else
556 status->c33_admin_state = ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED;
557
558 priv->admin_state[id] = status->c33_admin_state;
559
560 pd692x0_get_ext_state(&status->c33_ext_state_info, buf.sub[0]);
561
562 status->c33_actual_pw = (buf.data[0] << 4 | buf.data[1]) * 100;
563
564 memset(&buf, 0, sizeof(buf));
565 msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_CLASS];
566 msg.sub[2] = id;
567 ret = pd692x0_sendrecv_msg(priv, &msg, &buf);
568 if (ret < 0)
569 return ret;
570
571 class = buf.data[3] >> 4;
572 if (class <= 8)
573 status->c33_pw_class = class;
574
474 return 0;
475}
476
477static struct pd692x0_msg_ver pd692x0_get_sw_version(struct pd692x0_priv *priv)
478{
479 struct device *dev = &priv->client->dev;
480 struct pd692x0_msg msg, buf = {0};
481 struct pd692x0_msg_ver ver = {0};

--- 742 unchanged lines hidden ---
575 return 0;
576}
577
578static struct pd692x0_msg_ver pd692x0_get_sw_version(struct pd692x0_priv *priv)
579{
580 struct device *dev = &priv->client->dev;
581 struct pd692x0_msg msg, buf = {0};
582 struct pd692x0_msg_ver ver = {0};

--- 742 unchanged lines hidden ---