1539 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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>9#include <linux/firmware.h>10#include <linux/i2c.h>11#include <linux/module.h>12#include <linux/of.h>13#include <linux/platform_device.h>14#include <linux/pse-pd/pse.h>15 16#define PD692X0_PSE_NAME "pd692x0_pse"17 18#define PD692X0_MAX_PIS 4819#define PD692X0_MAX_MANAGERS 1220#define PD692X0_MAX_MANAGER_PORTS 821#define PD692X0_MAX_HW_PORTS (PD692X0_MAX_MANAGERS * PD692X0_MAX_MANAGER_PORTS)22 23#define PD69200_BT_PROD_VER 2424#define PD69210_BT_PROD_VER 2625#define PD69220_BT_PROD_VER 2926 27#define PD692X0_FW_MAJ_VER 328#define PD692X0_FW_MIN_VER 529#define PD692X0_FW_PATCH_VER 530 31enum pd692x0_fw_state {32 PD692X0_FW_UNKNOWN,33 PD692X0_FW_OK,34 PD692X0_FW_BROKEN,35 PD692X0_FW_NEED_UPDATE,36 PD692X0_FW_PREPARE,37 PD692X0_FW_WRITE,38 PD692X0_FW_COMPLETE,39};40 41struct pd692x0_msg {42 u8 key;43 u8 echo;44 u8 sub[3];45 u8 data[8];46 __be16 chksum;47} __packed;48 49struct pd692x0_msg_ver {50 u8 prod;51 u8 maj_sw_ver;52 u8 min_sw_ver;53 u8 pa_sw_ver;54 u8 param;55 u8 build;56};57 58enum {59 PD692X0_KEY_CMD,60 PD692X0_KEY_PRG,61 PD692X0_KEY_REQ,62 PD692X0_KEY_TLM,63 PD692X0_KEY_TEST,64 PD692X0_KEY_REPORT = 0x5265};66 67enum {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,77 PD692X0_MSG_GET_PORT_MEAS,78 PD692X0_MSG_GET_PORT_PARAM,79 80 /* add new message above here */81 PD692X0_MSG_CNT82};83 84struct pd692x0_priv {85 struct i2c_client *client;86 struct pse_controller_dev pcdev;87 struct device_node *np;88 89 enum pd692x0_fw_state fw_state;90 struct fw_upload *fwl;91 bool cancel_request;92 93 u8 msg_id;94 bool last_cmd_key;95 unsigned long last_cmd_key_time;96 97 enum ethtool_c33_pse_admin_state admin_state[PD692X0_MAX_PIS];98};99 100/* Template list of communication messages. The non-null bytes defined here101 * constitute the fixed portion of the messages. The remaining bytes will102 * be configured later within the functions. Refer to the "PD692x0 BT Serial103 * Communication Protocol User Guide" for comprehensive details on messages104 * content.105 */106static const struct pd692x0_msg pd692x0_msg_template_list[PD692X0_MSG_CNT] = {107 [PD692X0_MSG_RESET] = {108 .key = PD692X0_KEY_CMD,109 .sub = {0x07, 0x55, 0x00},110 .data = {0x55, 0x00, 0x55, 0x4e,111 0x4e, 0x4e, 0x4e, 0x4e},112 },113 [PD692X0_MSG_GET_SYS_STATUS] = {114 .key = PD692X0_KEY_REQ,115 .sub = {0x07, 0xd0, 0x4e},116 .data = {0x4e, 0x4e, 0x4e, 0x4e,117 0x4e, 0x4e, 0x4e, 0x4e},118 },119 [PD692X0_MSG_GET_SW_VER] = {120 .key = PD692X0_KEY_REQ,121 .sub = {0x07, 0x1e, 0x21},122 .data = {0x4e, 0x4e, 0x4e, 0x4e,123 0x4e, 0x4e, 0x4e, 0x4e},124 },125 [PD692X0_MSG_SET_TMP_PORT_MATRIX] = {126 .key = PD692X0_KEY_CMD,127 .sub = {0x05, 0x43},128 .data = { 0, 0x4e, 0x4e, 0x4e,129 0x4e, 0x4e, 0x4e, 0x4e},130 },131 [PD692X0_MSG_PRG_PORT_MATRIX] = {132 .key = PD692X0_KEY_CMD,133 .sub = {0x07, 0x43, 0x4e},134 .data = {0x4e, 0x4e, 0x4e, 0x4e,135 0x4e, 0x4e, 0x4e, 0x4e},136 },137 [PD692X0_MSG_SET_PORT_PARAM] = {138 .key = PD692X0_KEY_CMD,139 .sub = {0x05, 0xc0},140 .data = { 0xf, 0xff, 0xff, 0xff,141 0x4e, 0x4e, 0x4e, 0x4e},142 },143 [PD692X0_MSG_GET_PORT_STATUS] = {144 .key = PD692X0_KEY_REQ,145 .sub = {0x05, 0xc1},146 .data = {0x4e, 0x4e, 0x4e, 0x4e,147 0x4e, 0x4e, 0x4e, 0x4e},148 },149 [PD692X0_MSG_DOWNLOAD_CMD] = {150 .key = PD692X0_KEY_PRG,151 .sub = {0xff, 0x99, 0x15},152 .data = {0x16, 0x16, 0x99, 0x4e,153 0x4e, 0x4e, 0x4e, 0x4e},154 },155 [PD692X0_MSG_GET_PORT_CLASS] = {156 .key = PD692X0_KEY_REQ,157 .sub = {0x05, 0xc4},158 .data = {0x4e, 0x4e, 0x4e, 0x4e,159 0x4e, 0x4e, 0x4e, 0x4e},160 },161 [PD692X0_MSG_GET_PORT_MEAS] = {162 .key = PD692X0_KEY_REQ,163 .sub = {0x05, 0xc5},164 .data = {0x4e, 0x4e, 0x4e, 0x4e,165 0x4e, 0x4e, 0x4e, 0x4e},166 },167 [PD692X0_MSG_GET_PORT_PARAM] = {168 .key = PD692X0_KEY_REQ,169 .sub = {0x05, 0xc0},170 .data = {0x4e, 0x4e, 0x4e, 0x4e,171 0x4e, 0x4e, 0x4e, 0x4e},172 },173};174 175static u8 pd692x0_build_msg(struct pd692x0_msg *msg, u8 echo)176{177 u8 *data = (u8 *)msg;178 u16 chksum = 0;179 int i;180 181 msg->echo = echo++;182 if (echo == 0xff)183 echo = 0;184 185 for (i = 0; i < sizeof(*msg) - sizeof(msg->chksum); i++)186 chksum += data[i];187 188 msg->chksum = cpu_to_be16(chksum);189 190 return echo;191}192 193static int pd692x0_send_msg(struct pd692x0_priv *priv, struct pd692x0_msg *msg)194{195 const struct i2c_client *client = priv->client;196 int ret;197 198 if (msg->key == PD692X0_KEY_CMD && priv->last_cmd_key) {199 int cmd_msleep;200 201 cmd_msleep = 30 - jiffies_to_msecs(jiffies - priv->last_cmd_key_time);202 if (cmd_msleep > 0)203 msleep(cmd_msleep);204 }205 206 /* Add echo and checksum bytes to the message */207 priv->msg_id = pd692x0_build_msg(msg, priv->msg_id);208 209 ret = i2c_master_send(client, (u8 *)msg, sizeof(*msg));210 if (ret != sizeof(*msg))211 return -EIO;212 213 return 0;214}215 216static int pd692x0_reset(struct pd692x0_priv *priv)217{218 const struct i2c_client *client = priv->client;219 struct pd692x0_msg msg, buf = {0};220 int ret;221 222 msg = pd692x0_msg_template_list[PD692X0_MSG_RESET];223 ret = pd692x0_send_msg(priv, &msg);224 if (ret) {225 dev_err(&client->dev,226 "Failed to reset the controller (%pe)\n", ERR_PTR(ret));227 return ret;228 }229 230 msleep(30);231 232 ret = i2c_master_recv(client, (u8 *)&buf, sizeof(buf));233 if (ret != sizeof(buf))234 return ret < 0 ? ret : -EIO;235 236 /* Is the reply a successful report message */237 if (buf.key != PD692X0_KEY_REPORT || buf.sub[0] || buf.sub[1])238 return -EIO;239 240 msleep(300);241 242 ret = i2c_master_recv(client, (u8 *)&buf, sizeof(buf));243 if (ret != sizeof(buf))244 return ret < 0 ? ret : -EIO;245 246 /* Is the boot status without error */247 if (buf.key != 0x03 || buf.echo != 0xff || buf.sub[0] & 0x1) {248 dev_err(&client->dev, "PSE controller error\n");249 return -EIO;250 }251 252 return 0;253}254 255static bool pd692x0_try_recv_msg(const struct i2c_client *client,256 struct pd692x0_msg *msg,257 struct pd692x0_msg *buf)258{259 /* Wait 30ms before readback as mandated by the protocol */260 msleep(30);261 262 memset(buf, 0, sizeof(*buf));263 i2c_master_recv(client, (u8 *)buf, sizeof(*buf));264 if (buf->key)265 return 0;266 267 msleep(100);268 269 memset(buf, 0, sizeof(*buf));270 i2c_master_recv(client, (u8 *)buf, sizeof(*buf));271 if (buf->key)272 return 0;273 274 return 1;275}276 277/* Implementation of I2C communication, specifically addressing scenarios278 * involving communication loss. Refer to the "Synchronization During279 * Communication Loss" section in the Communication Protocol document for280 * further details.281 */282static int pd692x0_recv_msg(struct pd692x0_priv *priv,283 struct pd692x0_msg *msg,284 struct pd692x0_msg *buf)285{286 const struct i2c_client *client = priv->client;287 int ret;288 289 ret = pd692x0_try_recv_msg(client, msg, buf);290 if (!ret)291 goto out_success;292 293 dev_warn(&client->dev,294 "Communication lost, rtnl is locked until communication is back!");295 296 ret = pd692x0_send_msg(priv, msg);297 if (ret)298 return ret;299 300 ret = pd692x0_try_recv_msg(client, msg, buf);301 if (!ret)302 goto out_success2;303 304 msleep(10000);305 306 ret = pd692x0_send_msg(priv, msg);307 if (ret)308 return ret;309 310 ret = pd692x0_try_recv_msg(client, msg, buf);311 if (!ret)312 goto out_success2;313 314 return pd692x0_reset(priv);315 316out_success2:317 dev_warn(&client->dev, "Communication is back, rtnl is unlocked!");318out_success:319 if (msg->key == PD692X0_KEY_CMD) {320 priv->last_cmd_key = true;321 priv->last_cmd_key_time = jiffies;322 } else {323 priv->last_cmd_key = false;324 }325 326 return 0;327}328 329static int pd692x0_sendrecv_msg(struct pd692x0_priv *priv,330 struct pd692x0_msg *msg,331 struct pd692x0_msg *buf)332{333 struct device *dev = &priv->client->dev;334 int ret;335 336 ret = pd692x0_send_msg(priv, msg);337 if (ret)338 return ret;339 340 ret = pd692x0_recv_msg(priv, msg, buf);341 if (ret)342 return ret;343 344 if (msg->echo != buf->echo) {345 dev_err(dev,346 "Wrong match in message ID, expect %d received %d.\n",347 msg->echo, buf->echo);348 return -EIO;349 }350 351 /* If the reply is a report message is it successful */352 if (buf->key == PD692X0_KEY_REPORT &&353 (buf->sub[0] || buf->sub[1])) {354 return -EIO;355 }356 357 return 0;358}359 360static struct pd692x0_priv *to_pd692x0_priv(struct pse_controller_dev *pcdev)361{362 return container_of(pcdev, struct pd692x0_priv, pcdev);363}364 365static int pd692x0_fw_unavailable(struct pd692x0_priv *priv)366{367 switch (priv->fw_state) {368 case PD692X0_FW_OK:369 return 0;370 case PD692X0_FW_PREPARE:371 case PD692X0_FW_WRITE:372 case PD692X0_FW_COMPLETE:373 dev_err(&priv->client->dev, "Firmware update in progress!\n");374 return -EBUSY;375 case PD692X0_FW_BROKEN:376 case PD692X0_FW_NEED_UPDATE:377 default:378 dev_err(&priv->client->dev,379 "Firmware issue. Please update it!\n");380 return -EOPNOTSUPP;381 }382}383 384static int pd692x0_pi_enable(struct pse_controller_dev *pcdev, int id)385{386 struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);387 struct pd692x0_msg msg, buf = {0};388 int ret;389 390 ret = pd692x0_fw_unavailable(priv);391 if (ret)392 return ret;393 394 if (priv->admin_state[id] == ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED)395 return 0;396 397 msg = pd692x0_msg_template_list[PD692X0_MSG_SET_PORT_PARAM];398 msg.data[0] = 0x1;399 msg.sub[2] = id;400 ret = pd692x0_sendrecv_msg(priv, &msg, &buf);401 if (ret < 0)402 return ret;403 404 priv->admin_state[id] = ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED;405 406 return 0;407}408 409static int pd692x0_pi_disable(struct pse_controller_dev *pcdev, int id)410{411 struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);412 struct pd692x0_msg msg, buf = {0};413 int ret;414 415 ret = pd692x0_fw_unavailable(priv);416 if (ret)417 return ret;418 419 if (priv->admin_state[id] == ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED)420 return 0;421 422 msg = pd692x0_msg_template_list[PD692X0_MSG_SET_PORT_PARAM];423 msg.data[0] = 0x0;424 msg.sub[2] = id;425 ret = pd692x0_sendrecv_msg(priv, &msg, &buf);426 if (ret < 0)427 return ret;428 429 priv->admin_state[id] = ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED;430 431 return 0;432}433 434static int pd692x0_pi_is_enabled(struct pse_controller_dev *pcdev, int id)435{436 struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);437 struct pd692x0_msg msg, buf = {0};438 int ret;439 440 ret = pd692x0_fw_unavailable(priv);441 if (ret)442 return ret;443 444 msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_STATUS];445 msg.sub[2] = id;446 ret = pd692x0_sendrecv_msg(priv, &msg, &buf);447 if (ret < 0)448 return ret;449 450 if (buf.sub[1]) {451 priv->admin_state[id] = ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED;452 return 1;453 } else {454 priv->admin_state[id] = ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED;455 return 0;456 }457}458 459struct pd692x0_pse_ext_state_mapping {460 u32 status_code;461 enum ethtool_c33_pse_ext_state pse_ext_state;462 u32 pse_ext_substate;463};464 465static const struct pd692x0_pse_ext_state_mapping466pd692x0_pse_ext_state_map[] = {467 {0x06, ETHTOOL_C33_PSE_EXT_STATE_OPTION_VPORT_LIM,468 ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_HIGH_VOLTAGE},469 {0x07, ETHTOOL_C33_PSE_EXT_STATE_OPTION_VPORT_LIM,470 ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_LOW_VOLTAGE},471 {0x08, ETHTOOL_C33_PSE_EXT_STATE_MR_PSE_ENABLE,472 ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_PSE_ENABLE_DISABLE_PIN_ACTIVE},473 {0x0C, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,474 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_NON_EXISTING_PORT},475 {0x11, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,476 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNDEFINED_PORT},477 {0x12, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,478 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_INTERNAL_HW_FAULT},479 {0x1B, ETHTOOL_C33_PSE_EXT_STATE_OPTION_DETECT_TED,480 ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_DETECT_TED_DET_IN_PROCESS},481 {0x1C, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,482 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS},483 {0x1E, ETHTOOL_C33_PSE_EXT_STATE_MR_MPS_VALID,484 ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_MPS_VALID_DETECTED_UNDERLOAD},485 {0x1F, ETHTOOL_C33_PSE_EXT_STATE_OVLD_DETECTED,486 ETHTOOL_C33_PSE_EXT_SUBSTATE_OVLD_DETECTED_OVERLOAD},487 {0x20, ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE,488 ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_BUDGET_EXCEEDED},489 {0x21, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,490 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_INTERNAL_HW_FAULT},491 {0x22, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,492 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_CONFIG_CHANGE},493 {0x24, ETHTOOL_C33_PSE_EXT_STATE_OPTION_VPORT_LIM,494 ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_VOLTAGE_INJECTION},495 {0x25, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,496 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS},497 {0x34, ETHTOOL_C33_PSE_EXT_STATE_SHORT_DETECTED,498 ETHTOOL_C33_PSE_EXT_SUBSTATE_SHORT_DETECTED_SHORT_CONDITION},499 {0x35, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,500 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_DETECTED_OVER_TEMP},501 {0x36, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,502 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_DETECTED_OVER_TEMP},503 {0x37, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,504 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS},505 {0x3C, ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE,506 ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_PORT_PW_LIMIT_EXCEEDS_CONTROLLER_BUDGET},507 {0x3D, ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE,508 ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_PD_REQUEST_EXCEEDS_PORT_LIMIT},509 {0x41, ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE,510 ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_HW_PW_LIMIT},511 {0x43, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,512 ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS},513 {0xA7, ETHTOOL_C33_PSE_EXT_STATE_OPTION_DETECT_TED,514 ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_DETECT_TED_CONNECTION_CHECK_ERROR},515 {0xA8, ETHTOOL_C33_PSE_EXT_STATE_MR_MPS_VALID,516 ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_MPS_VALID_CONNECTION_OPEN},517 { /* sentinel */ }518};519 520static void521pd692x0_get_ext_state(struct ethtool_c33_pse_ext_state_info *c33_ext_state_info,522 u32 status_code)523{524 const struct pd692x0_pse_ext_state_mapping *ext_state_map;525 526 ext_state_map = pd692x0_pse_ext_state_map;527 while (ext_state_map->status_code) {528 if (ext_state_map->status_code == status_code) {529 c33_ext_state_info->c33_pse_ext_state = ext_state_map->pse_ext_state;530 c33_ext_state_info->__c33_pse_ext_substate = ext_state_map->pse_ext_substate;531 return;532 }533 ext_state_map++;534 }535}536 537struct pd692x0_class_pw {538 int class;539 int class_cfg_value;540 int class_pw;541 int max_added_class_pw;542};543 544#define PD692X0_CLASS_PW_TABLE_SIZE 4545/* 4/2 pairs class configuration power table in compliance mode.546 * Need to be arranged in ascending order of power support.547 */548static const struct pd692x0_class_pw549pd692x0_class_pw_table[PD692X0_CLASS_PW_TABLE_SIZE] = {550 {.class = 3, .class_cfg_value = 0x3, .class_pw = 15000, .max_added_class_pw = 3100},551 {.class = 4, .class_cfg_value = 0x2, .class_pw = 30000, .max_added_class_pw = 8000},552 {.class = 6, .class_cfg_value = 0x1, .class_pw = 60000, .max_added_class_pw = 5000},553 {.class = 8, .class_cfg_value = 0x0, .class_pw = 90000, .max_added_class_pw = 7500},554};555 556static int pd692x0_pi_get_pw_from_table(int op_mode, int added_pw)557{558 const struct pd692x0_class_pw *pw_table;559 int i;560 561 pw_table = pd692x0_class_pw_table;562 for (i = 0; i < PD692X0_CLASS_PW_TABLE_SIZE; i++, pw_table++) {563 if (pw_table->class_cfg_value == op_mode)564 return pw_table->class_pw + added_pw * 100;565 }566 567 return -ERANGE;568}569 570static int pd692x0_pi_set_pw_from_table(struct device *dev,571 struct pd692x0_msg *msg, int pw)572{573 const struct pd692x0_class_pw *pw_table;574 int i;575 576 pw_table = pd692x0_class_pw_table;577 if (pw < pw_table->class_pw) {578 dev_err(dev,579 "Power limit %dmW not supported. Ranges minimal available: [%d-%d]\n",580 pw,581 pw_table->class_pw,582 pw_table->class_pw + pw_table->max_added_class_pw);583 return -ERANGE;584 }585 586 for (i = 0; i < PD692X0_CLASS_PW_TABLE_SIZE; i++, pw_table++) {587 if (pw > (pw_table->class_pw + pw_table->max_added_class_pw))588 continue;589 590 if (pw < pw_table->class_pw) {591 dev_err(dev,592 "Power limit %dmW not supported. Ranges available: [%d-%d] or [%d-%d]\n",593 pw,594 (pw_table - 1)->class_pw,595 (pw_table - 1)->class_pw + (pw_table - 1)->max_added_class_pw,596 pw_table->class_pw,597 pw_table->class_pw + pw_table->max_added_class_pw);598 return -ERANGE;599 }600 601 msg->data[2] = pw_table->class_cfg_value;602 msg->data[3] = (pw - pw_table->class_pw) / 100;603 return 0;604 }605 606 pw_table--;607 dev_warn(dev,608 "Power limit %dmW not supported. Set to highest power limit %dmW\n",609 pw, pw_table->class_pw + pw_table->max_added_class_pw);610 msg->data[2] = pw_table->class_cfg_value;611 msg->data[3] = pw_table->max_added_class_pw / 100;612 return 0;613}614 615static int616pd692x0_pi_get_pw_ranges(struct pse_control_status *st)617{618 const struct pd692x0_class_pw *pw_table;619 int i;620 621 pw_table = pd692x0_class_pw_table;622 st->c33_pw_limit_ranges = kcalloc(PD692X0_CLASS_PW_TABLE_SIZE,623 sizeof(struct ethtool_c33_pse_pw_limit_range),624 GFP_KERNEL);625 if (!st->c33_pw_limit_ranges)626 return -ENOMEM;627 628 for (i = 0; i < PD692X0_CLASS_PW_TABLE_SIZE; i++, pw_table++) {629 st->c33_pw_limit_ranges[i].min = pw_table->class_pw;630 st->c33_pw_limit_ranges[i].max = pw_table->class_pw + pw_table->max_added_class_pw;631 }632 633 st->c33_pw_limit_nb_ranges = i;634 return 0;635}636 637static int pd692x0_ethtool_get_status(struct pse_controller_dev *pcdev,638 unsigned long id,639 struct netlink_ext_ack *extack,640 struct pse_control_status *status)641{642 struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);643 struct pd692x0_msg msg, buf = {0};644 u32 class;645 int ret;646 647 ret = pd692x0_fw_unavailable(priv);648 if (ret)649 return ret;650 651 msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_STATUS];652 msg.sub[2] = id;653 ret = pd692x0_sendrecv_msg(priv, &msg, &buf);654 if (ret < 0)655 return ret;656 657 /* Compare Port Status (Communication Protocol Document par. 7.1) */658 if ((buf.sub[0] & 0xf0) == 0x80 || (buf.sub[0] & 0xf0) == 0x90)659 status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING;660 else if (buf.sub[0] == 0x1b || buf.sub[0] == 0x22)661 status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_SEARCHING;662 else if (buf.sub[0] == 0x12)663 status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_FAULT;664 else665 status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED;666 667 if (buf.sub[1])668 status->c33_admin_state = ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED;669 else670 status->c33_admin_state = ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED;671 672 priv->admin_state[id] = status->c33_admin_state;673 674 pd692x0_get_ext_state(&status->c33_ext_state_info, buf.sub[0]);675 status->c33_actual_pw = (buf.data[0] << 4 | buf.data[1]) * 100;676 677 msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_PARAM];678 msg.sub[2] = id;679 memset(&buf, 0, sizeof(buf));680 ret = pd692x0_sendrecv_msg(priv, &msg, &buf);681 if (ret < 0)682 return ret;683 684 ret = pd692x0_pi_get_pw_from_table(buf.data[0], buf.data[1]);685 if (ret < 0)686 return ret;687 status->c33_avail_pw_limit = ret;688 689 memset(&buf, 0, sizeof(buf));690 msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_CLASS];691 msg.sub[2] = id;692 ret = pd692x0_sendrecv_msg(priv, &msg, &buf);693 if (ret < 0)694 return ret;695 696 class = buf.data[3] >> 4;697 if (class <= 8)698 status->c33_pw_class = class;699 700 ret = pd692x0_pi_get_pw_ranges(status);701 if (ret < 0)702 return ret;703 704 return 0;705}706 707static struct pd692x0_msg_ver pd692x0_get_sw_version(struct pd692x0_priv *priv)708{709 struct device *dev = &priv->client->dev;710 struct pd692x0_msg msg, buf = {0};711 struct pd692x0_msg_ver ver = {0};712 int ret;713 714 msg = pd692x0_msg_template_list[PD692X0_MSG_GET_SW_VER];715 ret = pd692x0_sendrecv_msg(priv, &msg, &buf);716 if (ret < 0) {717 dev_err(dev, "Failed to get PSE version (%pe)\n", ERR_PTR(ret));718 return ver;719 }720 721 /* Extract version from the message */722 ver.prod = buf.sub[2];723 ver.maj_sw_ver = (buf.data[0] << 8 | buf.data[1]) / 100;724 ver.min_sw_ver = ((buf.data[0] << 8 | buf.data[1]) / 10) % 10;725 ver.pa_sw_ver = (buf.data[0] << 8 | buf.data[1]) % 10;726 ver.param = buf.data[2];727 ver.build = buf.data[3];728 729 return ver;730}731 732struct pd692x0_manager {733 struct device_node *port_node[PD692X0_MAX_MANAGER_PORTS];734 int nports;735};736 737struct pd692x0_matrix {738 u8 hw_port_a;739 u8 hw_port_b;740};741 742static int743pd692x0_of_get_ports_manager(struct pd692x0_priv *priv,744 struct pd692x0_manager *manager,745 struct device_node *np)746{747 struct device_node *node;748 int ret, nports, i;749 750 nports = 0;751 for_each_child_of_node(np, node) {752 u32 port;753 754 if (!of_node_name_eq(node, "port"))755 continue;756 757 ret = of_property_read_u32(node, "reg", &port);758 if (ret)759 goto out;760 761 if (port >= PD692X0_MAX_MANAGER_PORTS || port != nports) {762 dev_err(&priv->client->dev,763 "wrong number or order of manager ports (%d)\n",764 port);765 ret = -EINVAL;766 goto out;767 }768 769 of_node_get(node);770 manager->port_node[port] = node;771 nports++;772 }773 774 manager->nports = nports;775 return 0;776 777out:778 for (i = 0; i < nports; i++) {779 of_node_put(manager->port_node[i]);780 manager->port_node[i] = NULL;781 }782 of_node_put(node);783 return ret;784}785 786static int787pd692x0_of_get_managers(struct pd692x0_priv *priv,788 struct pd692x0_manager manager[PD692X0_MAX_MANAGERS])789{790 struct device_node *managers_node, *node;791 int ret, nmanagers, i, j;792 793 if (!priv->np)794 return -EINVAL;795 796 nmanagers = 0;797 managers_node = of_get_child_by_name(priv->np, "managers");798 if (!managers_node)799 return -EINVAL;800 801 for_each_child_of_node(managers_node, node) {802 u32 manager_id;803 804 if (!of_node_name_eq(node, "manager"))805 continue;806 807 ret = of_property_read_u32(node, "reg", &manager_id);808 if (ret)809 goto out;810 811 if (manager_id >= PD692X0_MAX_MANAGERS ||812 manager_id != nmanagers) {813 dev_err(&priv->client->dev,814 "wrong number or order of managers (%d)\n",815 manager_id);816 ret = -EINVAL;817 goto out;818 }819 820 ret = pd692x0_of_get_ports_manager(priv, &manager[manager_id],821 node);822 if (ret)823 goto out;824 825 nmanagers++;826 }827 828 of_node_put(managers_node);829 return nmanagers;830 831out:832 for (i = 0; i < nmanagers; i++) {833 for (j = 0; j < manager[i].nports; j++) {834 of_node_put(manager[i].port_node[j]);835 manager[i].port_node[j] = NULL;836 }837 }838 839 of_node_put(node);840 of_node_put(managers_node);841 return ret;842}843 844static int845pd692x0_set_port_matrix(const struct pse_pi_pairset *pairset,846 const struct pd692x0_manager *manager,847 int nmanagers, struct pd692x0_matrix *port_matrix)848{849 int i, j, port_cnt;850 bool found = false;851 852 if (!pairset->np)853 return 0;854 855 /* Look on every managers */856 port_cnt = 0;857 for (i = 0; i < nmanagers; i++) {858 /* Look on every ports of the manager */859 for (j = 0; j < manager[i].nports; j++) {860 if (pairset->np == manager[i].port_node[j]) {861 found = true;862 break;863 }864 }865 port_cnt += j;866 867 if (found)868 break;869 }870 871 if (!found)872 return -ENODEV;873 874 if (pairset->pinout == ALTERNATIVE_A)875 port_matrix->hw_port_a = port_cnt;876 else if (pairset->pinout == ALTERNATIVE_B)877 port_matrix->hw_port_b = port_cnt;878 879 return 0;880}881 882static int883pd692x0_set_ports_matrix(struct pd692x0_priv *priv,884 const struct pd692x0_manager *manager,885 int nmanagers,886 struct pd692x0_matrix port_matrix[PD692X0_MAX_PIS])887{888 struct pse_controller_dev *pcdev = &priv->pcdev;889 int i, ret;890 891 /* Init Matrix */892 for (i = 0; i < PD692X0_MAX_PIS; i++) {893 port_matrix[i].hw_port_a = 0xff;894 port_matrix[i].hw_port_b = 0xff;895 }896 897 /* Update with values for every PSE PIs */898 for (i = 0; i < pcdev->nr_lines; i++) {899 ret = pd692x0_set_port_matrix(&pcdev->pi[i].pairset[0],900 manager, nmanagers,901 &port_matrix[i]);902 if (ret) {903 dev_err(&priv->client->dev,904 "unable to configure pi %d pairset 0", i);905 return ret;906 }907 908 ret = pd692x0_set_port_matrix(&pcdev->pi[i].pairset[1],909 manager, nmanagers,910 &port_matrix[i]);911 if (ret) {912 dev_err(&priv->client->dev,913 "unable to configure pi %d pairset 1", i);914 return ret;915 }916 }917 918 return 0;919}920 921static int922pd692x0_write_ports_matrix(struct pd692x0_priv *priv,923 const struct pd692x0_matrix port_matrix[PD692X0_MAX_PIS])924{925 struct pd692x0_msg msg, buf;926 int ret, i;927 928 /* Write temporary Matrix */929 msg = pd692x0_msg_template_list[PD692X0_MSG_SET_TMP_PORT_MATRIX];930 for (i = 0; i < PD692X0_MAX_PIS; i++) {931 msg.sub[2] = i;932 msg.data[0] = port_matrix[i].hw_port_b;933 msg.data[1] = port_matrix[i].hw_port_a;934 935 ret = pd692x0_sendrecv_msg(priv, &msg, &buf);936 if (ret < 0)937 return ret;938 }939 940 /* Program Matrix */941 msg = pd692x0_msg_template_list[PD692X0_MSG_PRG_PORT_MATRIX];942 ret = pd692x0_sendrecv_msg(priv, &msg, &buf);943 if (ret < 0)944 return ret;945 946 return 0;947}948 949static int pd692x0_setup_pi_matrix(struct pse_controller_dev *pcdev)950{951 struct pd692x0_manager manager[PD692X0_MAX_MANAGERS] = {0};952 struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);953 struct pd692x0_matrix port_matrix[PD692X0_MAX_PIS];954 int ret, i, j, nmanagers;955 956 /* Should we flash the port matrix */957 if (priv->fw_state != PD692X0_FW_OK &&958 priv->fw_state != PD692X0_FW_COMPLETE)959 return 0;960 961 ret = pd692x0_of_get_managers(priv, manager);962 if (ret < 0)963 return ret;964 965 nmanagers = ret;966 ret = pd692x0_set_ports_matrix(priv, manager, nmanagers, port_matrix);967 if (ret)968 goto out;969 970 ret = pd692x0_write_ports_matrix(priv, port_matrix);971 if (ret)972 goto out;973 974out:975 for (i = 0; i < nmanagers; i++) {976 for (j = 0; j < manager[i].nports; j++)977 of_node_put(manager[i].port_node[j]);978 }979 return ret;980}981 982static int pd692x0_pi_get_voltage(struct pse_controller_dev *pcdev, int id)983{984 struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);985 struct pd692x0_msg msg, buf = {0};986 int ret;987 988 ret = pd692x0_fw_unavailable(priv);989 if (ret)990 return ret;991 992 msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_MEAS];993 msg.sub[2] = id;994 ret = pd692x0_sendrecv_msg(priv, &msg, &buf);995 if (ret < 0)996 return ret;997 998 /* Convert 0.1V unit to uV */999 return (buf.sub[0] << 8 | buf.sub[1]) * 100000;1000}1001 1002static int pd692x0_pi_get_current_limit(struct pse_controller_dev *pcdev,1003 int id)1004{1005 struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);1006 struct pd692x0_msg msg, buf = {0};1007 int mW, uV, uA, ret;1008 s64 tmp_64;1009 1010 msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_PARAM];1011 msg.sub[2] = id;1012 ret = pd692x0_sendrecv_msg(priv, &msg, &buf);1013 if (ret < 0)1014 return ret;1015 1016 ret = pd692x0_pi_get_pw_from_table(buf.data[2], buf.data[3]);1017 if (ret < 0)1018 return ret;1019 mW = ret;1020 1021 ret = pd692x0_pi_get_voltage(pcdev, id);1022 if (ret < 0)1023 return ret;1024 uV = ret;1025 1026 tmp_64 = mW;1027 tmp_64 *= 1000000000ull;1028 /* uA = mW * 1000000000 / uV */1029 uA = DIV_ROUND_CLOSEST_ULL(tmp_64, uV);1030 return uA;1031}1032 1033static int pd692x0_pi_set_current_limit(struct pse_controller_dev *pcdev,1034 int id, int max_uA)1035{1036 struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);1037 struct device *dev = &priv->client->dev;1038 struct pd692x0_msg msg, buf = {0};1039 int uV, ret, mW;1040 s64 tmp_64;1041 1042 ret = pd692x0_fw_unavailable(priv);1043 if (ret)1044 return ret;1045 1046 ret = pd692x0_pi_get_voltage(pcdev, id);1047 if (ret < 0)1048 return ret;1049 uV = ret;1050 1051 msg = pd692x0_msg_template_list[PD692X0_MSG_SET_PORT_PARAM];1052 msg.sub[2] = id;1053 tmp_64 = uV;1054 tmp_64 *= max_uA;1055 /* mW = uV * uA / 1000000000 */1056 mW = DIV_ROUND_CLOSEST_ULL(tmp_64, 1000000000);1057 ret = pd692x0_pi_set_pw_from_table(dev, &msg, mW);1058 if (ret)1059 return ret;1060 1061 return pd692x0_sendrecv_msg(priv, &msg, &buf);1062}1063 1064static const struct pse_controller_ops pd692x0_ops = {1065 .setup_pi_matrix = pd692x0_setup_pi_matrix,1066 .ethtool_get_status = pd692x0_ethtool_get_status,1067 .pi_enable = pd692x0_pi_enable,1068 .pi_disable = pd692x0_pi_disable,1069 .pi_is_enabled = pd692x0_pi_is_enabled,1070 .pi_get_voltage = pd692x0_pi_get_voltage,1071 .pi_get_current_limit = pd692x0_pi_get_current_limit,1072 .pi_set_current_limit = pd692x0_pi_set_current_limit,1073};1074 1075#define PD692X0_FW_LINE_MAX_SZ 0xff1076static int pd692x0_fw_get_next_line(const u8 *data,1077 char *line, size_t size)1078{1079 size_t line_size;1080 int i;1081 1082 line_size = min_t(size_t, size, PD692X0_FW_LINE_MAX_SZ);1083 1084 memset(line, 0, PD692X0_FW_LINE_MAX_SZ);1085 for (i = 0; i < line_size - 1; i++) {1086 if (*data == '\r' && *(data + 1) == '\n') {1087 line[i] = '\r';1088 line[i + 1] = '\n';1089 return i + 2;1090 }1091 line[i] = *data;1092 data++;1093 }1094 1095 return -EIO;1096}1097 1098static enum fw_upload_err1099pd692x0_fw_recv_resp(const struct i2c_client *client, unsigned long ms_timeout,1100 const char *msg_ok, unsigned int msg_size)1101{1102 /* Maximum controller response size */1103 char fw_msg_buf[5] = {0};1104 unsigned long timeout;1105 int ret;1106 1107 if (msg_size > sizeof(fw_msg_buf))1108 return FW_UPLOAD_ERR_RW_ERROR;1109 1110 /* Read until we get something */1111 timeout = msecs_to_jiffies(ms_timeout) + jiffies;1112 while (true) {1113 if (time_is_before_jiffies(timeout))1114 return FW_UPLOAD_ERR_TIMEOUT;1115 1116 ret = i2c_master_recv(client, fw_msg_buf, 1);1117 if (ret < 0 || *fw_msg_buf == 0) {1118 usleep_range(1000, 2000);1119 continue;1120 } else {1121 break;1122 }1123 }1124 1125 /* Read remaining characters */1126 ret = i2c_master_recv(client, fw_msg_buf + 1, msg_size - 1);1127 if (strncmp(fw_msg_buf, msg_ok, msg_size)) {1128 dev_err(&client->dev,1129 "Wrong FW download process answer (%*pE)\n",1130 msg_size, fw_msg_buf);1131 return FW_UPLOAD_ERR_HW_ERROR;1132 }1133 1134 return FW_UPLOAD_ERR_NONE;1135}1136 1137static int pd692x0_fw_write_line(const struct i2c_client *client,1138 const char line[PD692X0_FW_LINE_MAX_SZ],1139 const bool last_line)1140{1141 int ret;1142 1143 while (*line != 0) {1144 ret = i2c_master_send(client, line, 1);1145 if (ret < 0)1146 return FW_UPLOAD_ERR_RW_ERROR;1147 line++;1148 }1149 1150 if (last_line) {1151 ret = pd692x0_fw_recv_resp(client, 100, "TP\r\n",1152 sizeof("TP\r\n") - 1);1153 if (ret)1154 return ret;1155 } else {1156 ret = pd692x0_fw_recv_resp(client, 100, "T*\r\n",1157 sizeof("T*\r\n") - 1);1158 if (ret)1159 return ret;1160 }1161 1162 return FW_UPLOAD_ERR_NONE;1163}1164 1165static enum fw_upload_err pd692x0_fw_reset(const struct i2c_client *client)1166{1167 const struct pd692x0_msg zero = {0};1168 struct pd692x0_msg buf = {0};1169 unsigned long timeout;1170 char cmd[] = "RST";1171 int ret;1172 1173 ret = i2c_master_send(client, cmd, strlen(cmd));1174 if (ret < 0) {1175 dev_err(&client->dev,1176 "Failed to reset the controller (%pe)\n",1177 ERR_PTR(ret));1178 return ret;1179 }1180 1181 timeout = msecs_to_jiffies(10000) + jiffies;1182 while (true) {1183 if (time_is_before_jiffies(timeout))1184 return FW_UPLOAD_ERR_TIMEOUT;1185 1186 ret = i2c_master_recv(client, (u8 *)&buf, sizeof(buf));1187 if (ret < 0 ||1188 !memcmp(&buf, &zero, sizeof(buf)))1189 usleep_range(1000, 2000);1190 else1191 break;1192 }1193 1194 /* Is the reply a successful report message */1195 if (buf.key != PD692X0_KEY_TLM || buf.echo != 0xff ||1196 buf.sub[0] & 0x01) {1197 dev_err(&client->dev, "PSE controller error\n");1198 return FW_UPLOAD_ERR_HW_ERROR;1199 }1200 1201 /* Is the firmware operational */1202 if (buf.sub[0] & 0x02) {1203 dev_err(&client->dev,1204 "PSE firmware error. Please update it.\n");1205 return FW_UPLOAD_ERR_HW_ERROR;1206 }1207 1208 return FW_UPLOAD_ERR_NONE;1209}1210 1211static enum fw_upload_err pd692x0_fw_prepare(struct fw_upload *fwl,1212 const u8 *data, u32 size)1213{1214 struct pd692x0_priv *priv = fwl->dd_handle;1215 const struct i2c_client *client = priv->client;1216 enum pd692x0_fw_state last_fw_state;1217 int ret;1218 1219 priv->cancel_request = false;1220 last_fw_state = priv->fw_state;1221 1222 priv->fw_state = PD692X0_FW_PREPARE;1223 1224 /* Enter program mode */1225 if (last_fw_state == PD692X0_FW_BROKEN) {1226 const char *msg = "ENTR";1227 const char *c;1228 1229 c = msg;1230 do {1231 ret = i2c_master_send(client, c, 1);1232 if (ret < 0)1233 return FW_UPLOAD_ERR_RW_ERROR;1234 if (*(c + 1))1235 usleep_range(10000, 20000);1236 } while (*(++c));1237 } else {1238 struct pd692x0_msg msg, buf;1239 1240 msg = pd692x0_msg_template_list[PD692X0_MSG_DOWNLOAD_CMD];1241 ret = pd692x0_sendrecv_msg(priv, &msg, &buf);1242 if (ret < 0) {1243 dev_err(&client->dev,1244 "Failed to enter programming mode (%pe)\n",1245 ERR_PTR(ret));1246 return FW_UPLOAD_ERR_RW_ERROR;1247 }1248 }1249 1250 ret = pd692x0_fw_recv_resp(client, 100, "TPE\r\n", sizeof("TPE\r\n") - 1);1251 if (ret)1252 goto err_out;1253 1254 if (priv->cancel_request) {1255 ret = FW_UPLOAD_ERR_CANCELED;1256 goto err_out;1257 }1258 1259 return FW_UPLOAD_ERR_NONE;1260 1261err_out:1262 pd692x0_fw_reset(priv->client);1263 priv->fw_state = last_fw_state;1264 return ret;1265}1266 1267static enum fw_upload_err pd692x0_fw_write(struct fw_upload *fwl,1268 const u8 *data, u32 offset,1269 u32 size, u32 *written)1270{1271 struct pd692x0_priv *priv = fwl->dd_handle;1272 char line[PD692X0_FW_LINE_MAX_SZ];1273 const struct i2c_client *client;1274 int ret, i;1275 char cmd;1276 1277 client = priv->client;1278 priv->fw_state = PD692X0_FW_WRITE;1279 1280 /* Erase */1281 cmd = 'E';1282 ret = i2c_master_send(client, &cmd, 1);1283 if (ret < 0) {1284 dev_err(&client->dev,1285 "Failed to boot programming mode (%pe)\n",1286 ERR_PTR(ret));1287 return FW_UPLOAD_ERR_RW_ERROR;1288 }1289 1290 ret = pd692x0_fw_recv_resp(client, 100, "TOE\r\n", sizeof("TOE\r\n") - 1);1291 if (ret)1292 return ret;1293 1294 ret = pd692x0_fw_recv_resp(client, 5000, "TE\r\n", sizeof("TE\r\n") - 1);1295 if (ret)1296 dev_warn(&client->dev,1297 "Failed to erase internal memory, however still try to write Firmware\n");1298 1299 ret = pd692x0_fw_recv_resp(client, 100, "TPE\r\n", sizeof("TPE\r\n") - 1);1300 if (ret)1301 dev_warn(&client->dev,1302 "Failed to erase internal memory, however still try to write Firmware\n");1303 1304 if (priv->cancel_request)1305 return FW_UPLOAD_ERR_CANCELED;1306 1307 /* Program */1308 cmd = 'P';1309 ret = i2c_master_send(client, &cmd, sizeof(char));1310 if (ret < 0) {1311 dev_err(&client->dev,1312 "Failed to boot programming mode (%pe)\n",1313 ERR_PTR(ret));1314 return ret;1315 }1316 1317 ret = pd692x0_fw_recv_resp(client, 100, "TOP\r\n", sizeof("TOP\r\n") - 1);1318 if (ret)1319 return ret;1320 1321 i = 0;1322 while (i < size) {1323 ret = pd692x0_fw_get_next_line(data, line, size - i);1324 if (ret < 0) {1325 ret = FW_UPLOAD_ERR_FW_INVALID;1326 goto err;1327 }1328 1329 i += ret;1330 data += ret;1331 if (line[0] == 'S' && line[1] == '0') {1332 continue;1333 } else if (line[0] == 'S' && line[1] == '7') {1334 ret = pd692x0_fw_write_line(client, line, true);1335 if (ret)1336 goto err;1337 } else {1338 ret = pd692x0_fw_write_line(client, line, false);1339 if (ret)1340 goto err;1341 }1342 1343 if (priv->cancel_request) {1344 ret = FW_UPLOAD_ERR_CANCELED;1345 goto err;1346 }1347 }1348 *written = i;1349 1350 msleep(400);1351 1352 return FW_UPLOAD_ERR_NONE;1353 1354err:1355 strscpy_pad(line, "S7\r\n", sizeof(line));1356 pd692x0_fw_write_line(client, line, true);1357 return ret;1358}1359 1360static enum fw_upload_err pd692x0_fw_poll_complete(struct fw_upload *fwl)1361{1362 struct pd692x0_priv *priv = fwl->dd_handle;1363 const struct i2c_client *client = priv->client;1364 struct pd692x0_msg_ver ver;1365 int ret;1366 1367 priv->fw_state = PD692X0_FW_COMPLETE;1368 1369 ret = pd692x0_fw_reset(client);1370 if (ret)1371 return ret;1372 1373 ver = pd692x0_get_sw_version(priv);1374 if (ver.maj_sw_ver < PD692X0_FW_MAJ_VER) {1375 dev_err(&client->dev,1376 "Too old firmware version. Please update it\n");1377 priv->fw_state = PD692X0_FW_NEED_UPDATE;1378 return FW_UPLOAD_ERR_FW_INVALID;1379 }1380 1381 ret = pd692x0_setup_pi_matrix(&priv->pcdev);1382 if (ret < 0) {1383 dev_err(&client->dev, "Error configuring ports matrix (%pe)\n",1384 ERR_PTR(ret));1385 priv->fw_state = PD692X0_FW_NEED_UPDATE;1386 return FW_UPLOAD_ERR_HW_ERROR;1387 }1388 1389 priv->fw_state = PD692X0_FW_OK;1390 return FW_UPLOAD_ERR_NONE;1391}1392 1393static void pd692x0_fw_cancel(struct fw_upload *fwl)1394{1395 struct pd692x0_priv *priv = fwl->dd_handle;1396 1397 priv->cancel_request = true;1398}1399 1400static void pd692x0_fw_cleanup(struct fw_upload *fwl)1401{1402 struct pd692x0_priv *priv = fwl->dd_handle;1403 1404 switch (priv->fw_state) {1405 case PD692X0_FW_WRITE:1406 pd692x0_fw_reset(priv->client);1407 fallthrough;1408 case PD692X0_FW_COMPLETE:1409 priv->fw_state = PD692X0_FW_BROKEN;1410 break;1411 default:1412 break;1413 }1414}1415 1416static const struct fw_upload_ops pd692x0_fw_ops = {1417 .prepare = pd692x0_fw_prepare,1418 .write = pd692x0_fw_write,1419 .poll_complete = pd692x0_fw_poll_complete,1420 .cancel = pd692x0_fw_cancel,1421 .cleanup = pd692x0_fw_cleanup,1422};1423 1424static int pd692x0_i2c_probe(struct i2c_client *client)1425{1426 struct pd692x0_msg msg, buf = {0}, zero = {0};1427 struct device *dev = &client->dev;1428 struct pd692x0_msg_ver ver;1429 struct pd692x0_priv *priv;1430 struct fw_upload *fwl;1431 int ret;1432 1433 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {1434 dev_err(dev, "i2c check functionality failed\n");1435 return -ENXIO;1436 }1437 1438 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);1439 if (!priv)1440 return -ENOMEM;1441 1442 priv->client = client;1443 i2c_set_clientdata(client, priv);1444 1445 ret = i2c_master_recv(client, (u8 *)&buf, sizeof(buf));1446 if (ret != sizeof(buf)) {1447 dev_err(dev, "Failed to get device status\n");1448 return -EIO;1449 }1450 1451 /* Probe has been already run and the status dumped */1452 if (!memcmp(&buf, &zero, sizeof(buf))) {1453 /* Ask again the controller status */1454 msg = pd692x0_msg_template_list[PD692X0_MSG_GET_SYS_STATUS];1455 ret = pd692x0_sendrecv_msg(priv, &msg, &buf);1456 if (ret < 0) {1457 dev_err(dev, "Failed to get device status\n");1458 return ret;1459 }1460 }1461 1462 if (buf.key != 0x03 || buf.sub[0] & 0x01) {1463 dev_err(dev, "PSE controller error\n");1464 return -EIO;1465 }1466 if (buf.sub[0] & 0x02) {1467 dev_err(dev, "PSE firmware error. Please update it.\n");1468 priv->fw_state = PD692X0_FW_BROKEN;1469 } else {1470 ver = pd692x0_get_sw_version(priv);1471 dev_info(&client->dev, "Software version %d.%02d.%d.%d\n",1472 ver.prod, ver.maj_sw_ver, ver.min_sw_ver,1473 ver.pa_sw_ver);1474 1475 if (ver.maj_sw_ver < PD692X0_FW_MAJ_VER) {1476 dev_err(dev, "Too old firmware version. Please update it\n");1477 priv->fw_state = PD692X0_FW_NEED_UPDATE;1478 } else {1479 priv->fw_state = PD692X0_FW_OK;1480 }1481 }1482 1483 priv->np = dev->of_node;1484 priv->pcdev.nr_lines = PD692X0_MAX_PIS;1485 priv->pcdev.owner = THIS_MODULE;1486 priv->pcdev.ops = &pd692x0_ops;1487 priv->pcdev.dev = dev;1488 priv->pcdev.types = ETHTOOL_PSE_C33;1489 ret = devm_pse_controller_register(dev, &priv->pcdev);1490 if (ret)1491 return dev_err_probe(dev, ret,1492 "failed to register PSE controller\n");1493 1494 fwl = firmware_upload_register(THIS_MODULE, dev, dev_name(dev),1495 &pd692x0_fw_ops, priv);1496 if (IS_ERR(fwl))1497 return dev_err_probe(dev, PTR_ERR(fwl),1498 "failed to register to the Firmware Upload API\n");1499 priv->fwl = fwl;1500 1501 return 0;1502}1503 1504static void pd692x0_i2c_remove(struct i2c_client *client)1505{1506 struct pd692x0_priv *priv = i2c_get_clientdata(client);1507 1508 firmware_upload_unregister(priv->fwl);1509}1510 1511static const struct i2c_device_id pd692x0_id[] = {1512 { PD692X0_PSE_NAME },1513 { }1514};1515MODULE_DEVICE_TABLE(i2c, pd692x0_id);1516 1517static const struct of_device_id pd692x0_of_match[] = {1518 { .compatible = "microchip,pd69200", },1519 { .compatible = "microchip,pd69210", },1520 { .compatible = "microchip,pd69220", },1521 { },1522};1523MODULE_DEVICE_TABLE(of, pd692x0_of_match);1524 1525static struct i2c_driver pd692x0_driver = {1526 .probe = pd692x0_i2c_probe,1527 .remove = pd692x0_i2c_remove,1528 .id_table = pd692x0_id,1529 .driver = {1530 .name = PD692X0_PSE_NAME,1531 .of_match_table = pd692x0_of_match,1532 },1533};1534module_i2c_driver(pd692x0_driver);1535 1536MODULE_AUTHOR("Kory Maincent <kory.maincent@bootlin.com>");1537MODULE_DESCRIPTION("Microchip PD692x0 PoE PSE Controller driver");1538MODULE_LICENSE("GPL");1539