Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: pse-pd: tps23881: Add support for PSE events and interrupts

Add support for PSE event reporting through interrupts. Set up the newly
introduced devm_pse_irq_helper helper to register the interrupt. Events are
reported for over-current and over-temperature conditions.

Signed-off-by: Kory Maincent (Dent Project) <kory.maincent@bootlin.com>
Reviewed-by: Oleksij Rempel <o.rempel@pengutronix.de>
Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-3-78a1a645e2ee@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Kory Maincent (Dent Project) and committed by
Jakub Kicinski
f5e7aeca fc0e6db3

+186 -1
+186 -1
drivers/net/pse-pd/tps23881.c
··· 16 16 #include <linux/pse-pd/pse.h> 17 17 18 18 #define TPS23881_MAX_CHANS 8 19 + #define TPS23881_MAX_IRQ_RETRIES 10 19 20 21 + #define TPS23881_REG_IT 0x0 22 + #define TPS23881_REG_IT_MASK 0x1 23 + #define TPS23881_REG_IT_IFAULT BIT(5) 24 + #define TPS23881_REG_IT_SUPF BIT(7) 25 + #define TPS23881_REG_FAULT 0x7 26 + #define TPS23881_REG_SUPF_EVENT 0xb 27 + #define TPS23881_REG_TSD BIT(7) 20 28 #define TPS23881_REG_PW_STATUS 0x10 21 29 #define TPS23881_REG_OP_MODE 0x12 22 30 #define TPS23881_OP_MODE_SEMIAUTO 0xaaaa ··· 32 24 #define TPS23881_REG_DET_CLA_EN 0x14 33 25 #define TPS23881_REG_GEN_MASK 0x17 34 26 #define TPS23881_REG_NBITACC BIT(5) 27 + #define TPS23881_REG_INTEN BIT(7) 35 28 #define TPS23881_REG_PW_EN 0x19 36 29 #define TPS23881_REG_2PAIR_POL1 0x1e 37 30 #define TPS23881_REG_PORT_MAP 0x26 ··· 60 51 u8 chan[2]; 61 52 bool is_4p; 62 53 int pw_pol; 54 + bool exist; 63 55 }; 64 56 65 57 struct tps23881_priv { ··· 792 782 hw_chan = port_matrix[i].hw_chan[0] % 4; 793 783 794 784 /* Set software port matrix for existing ports */ 795 - if (port_matrix[i].exist) 785 + if (port_matrix[i].exist) { 796 786 priv->port[pi_id].chan[0] = lgcl_chan; 787 + priv->port[pi_id].exist = true; 788 + } 797 789 798 790 /* Initialize power policy internal value */ 799 791 priv->port[pi_id].pw_pol = -1; ··· 1029 1017 return 0; 1030 1018 } 1031 1019 1020 + /* Convert interrupt events to 0xff to be aligned with the chan 1021 + * number. 1022 + */ 1023 + static u8 tps23881_irq_export_chans_helper(u16 reg_val, u8 field_offset) 1024 + { 1025 + u8 val; 1026 + 1027 + val = (reg_val >> (4 + field_offset) & 0xf0) | 1028 + (reg_val >> field_offset & 0x0f); 1029 + 1030 + return val; 1031 + } 1032 + 1033 + /* Convert chan number to port number */ 1034 + static void tps23881_set_notifs_helper(struct tps23881_priv *priv, 1035 + u8 chans, 1036 + unsigned long *notifs, 1037 + unsigned long *notifs_mask, 1038 + enum ethtool_pse_event event) 1039 + { 1040 + u8 chan; 1041 + int i; 1042 + 1043 + if (!chans) 1044 + return; 1045 + 1046 + for (i = 0; i < TPS23881_MAX_CHANS; i++) { 1047 + if (!priv->port[i].exist) 1048 + continue; 1049 + /* No need to look at the 2nd channel in case of PoE4 as 1050 + * both registers are set. 1051 + */ 1052 + chan = priv->port[i].chan[0]; 1053 + 1054 + if (BIT(chan) & chans) { 1055 + *notifs_mask |= BIT(i); 1056 + notifs[i] |= event; 1057 + } 1058 + } 1059 + } 1060 + 1061 + static void tps23881_irq_event_over_temp(struct tps23881_priv *priv, 1062 + u16 reg_val, 1063 + unsigned long *notifs, 1064 + unsigned long *notifs_mask) 1065 + { 1066 + int i; 1067 + 1068 + if (reg_val & TPS23881_REG_TSD) { 1069 + for (i = 0; i < TPS23881_MAX_CHANS; i++) { 1070 + if (!priv->port[i].exist) 1071 + continue; 1072 + 1073 + *notifs_mask |= BIT(i); 1074 + notifs[i] |= ETHTOOL_PSE_EVENT_OVER_TEMP; 1075 + } 1076 + } 1077 + } 1078 + 1079 + static void tps23881_irq_event_over_current(struct tps23881_priv *priv, 1080 + u16 reg_val, 1081 + unsigned long *notifs, 1082 + unsigned long *notifs_mask) 1083 + { 1084 + u8 chans; 1085 + 1086 + chans = tps23881_irq_export_chans_helper(reg_val, 0); 1087 + if (chans) 1088 + tps23881_set_notifs_helper(priv, chans, notifs, notifs_mask, 1089 + ETHTOOL_PSE_EVENT_OVER_CURRENT); 1090 + } 1091 + 1092 + static int tps23881_irq_event_handler(struct tps23881_priv *priv, u16 reg, 1093 + unsigned long *notifs, 1094 + unsigned long *notifs_mask) 1095 + { 1096 + struct i2c_client *client = priv->client; 1097 + int ret; 1098 + 1099 + /* The Supply event bit is repeated twice so we only need to read 1100 + * the one from the first byte. 1101 + */ 1102 + if (reg & TPS23881_REG_IT_SUPF) { 1103 + ret = i2c_smbus_read_word_data(client, TPS23881_REG_SUPF_EVENT); 1104 + if (ret < 0) 1105 + return ret; 1106 + tps23881_irq_event_over_temp(priv, ret, notifs, notifs_mask); 1107 + } 1108 + 1109 + if (reg & (TPS23881_REG_IT_IFAULT | TPS23881_REG_IT_IFAULT << 8)) { 1110 + ret = i2c_smbus_read_word_data(client, TPS23881_REG_FAULT); 1111 + if (ret < 0) 1112 + return ret; 1113 + tps23881_irq_event_over_current(priv, ret, notifs, notifs_mask); 1114 + } 1115 + 1116 + return 0; 1117 + } 1118 + 1119 + static int tps23881_irq_handler(int irq, struct pse_controller_dev *pcdev, 1120 + unsigned long *notifs, 1121 + unsigned long *notifs_mask) 1122 + { 1123 + struct tps23881_priv *priv = to_tps23881_priv(pcdev); 1124 + struct i2c_client *client = priv->client; 1125 + int ret, it_mask, retry; 1126 + 1127 + /* Get interruption mask */ 1128 + ret = i2c_smbus_read_word_data(client, TPS23881_REG_IT_MASK); 1129 + if (ret < 0) 1130 + return ret; 1131 + it_mask = ret; 1132 + 1133 + /* Read interrupt register until it frees the interruption pin. */ 1134 + retry = 0; 1135 + while (true) { 1136 + if (retry > TPS23881_MAX_IRQ_RETRIES) { 1137 + dev_err(&client->dev, "interrupt never freed"); 1138 + return -ETIMEDOUT; 1139 + } 1140 + 1141 + ret = i2c_smbus_read_word_data(client, TPS23881_REG_IT); 1142 + if (ret < 0) 1143 + return ret; 1144 + 1145 + /* No more relevant interruption */ 1146 + if (!(ret & it_mask)) 1147 + return 0; 1148 + 1149 + ret = tps23881_irq_event_handler(priv, (u16)ret, notifs, 1150 + notifs_mask); 1151 + if (ret) 1152 + return ret; 1153 + 1154 + retry++; 1155 + } 1156 + return 0; 1157 + } 1158 + 1159 + static int tps23881_setup_irq(struct tps23881_priv *priv, int irq) 1160 + { 1161 + struct i2c_client *client = priv->client; 1162 + struct pse_irq_desc irq_desc = { 1163 + .name = "tps23881-irq", 1164 + .map_event = tps23881_irq_handler, 1165 + }; 1166 + int ret; 1167 + u16 val; 1168 + 1169 + val = TPS23881_REG_IT_IFAULT | TPS23881_REG_IT_SUPF; 1170 + val |= val << 8; 1171 + ret = i2c_smbus_write_word_data(client, TPS23881_REG_IT_MASK, val); 1172 + if (ret) 1173 + return ret; 1174 + 1175 + ret = i2c_smbus_read_word_data(client, TPS23881_REG_GEN_MASK); 1176 + if (ret < 0) 1177 + return ret; 1178 + 1179 + val = (u16)(ret | TPS23881_REG_INTEN | TPS23881_REG_INTEN << 8); 1180 + ret = i2c_smbus_write_word_data(client, TPS23881_REG_GEN_MASK, val); 1181 + if (ret < 0) 1182 + return ret; 1183 + 1184 + return devm_pse_irq_helper(&priv->pcdev, irq, 0, &irq_desc); 1185 + } 1186 + 1032 1187 static int tps23881_i2c_probe(struct i2c_client *client) 1033 1188 { 1034 1189 struct device *dev = &client->dev; ··· 1274 1095 if (ret) { 1275 1096 return dev_err_probe(dev, ret, 1276 1097 "failed to register PSE controller\n"); 1098 + } 1099 + 1100 + if (client->irq) { 1101 + ret = tps23881_setup_irq(priv, client->irq); 1102 + if (ret) 1103 + return ret; 1277 1104 } 1278 1105 1279 1106 return ret;