Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Driver for the Skyworks Si3474 PoE PSE Controller
4 *
5 * Chip Architecture & Terminology:
6 *
7 * The Si3474 is a single-chip PoE PSE controller managing 8 physical power
8 * delivery channels. Internally, it's structured into two logical "Quads".
9 *
10 * Quad 0: Manages physical channels ('ports' in datasheet) 0, 1, 2, 3
11 * Quad 1: Manages physical channels ('ports' in datasheet) 4, 5, 6, 7
12 *
13 * Each Quad is accessed via a separate I2C address. The base address range is
14 * set by hardware pins A1-A4, and the specific address selects Quad 0 (usually
15 * the lower/even address) or Quad 1 (usually the higher/odd address).
16 * See datasheet Table 2.2 for the address mapping.
17 *
18 * While the Quads manage channel-specific operations, the Si3474 package has
19 * several resources shared across the entire chip:
20 * - Single RESETb input pin.
21 * - Single INTb output pin (signals interrupts from *either* Quad).
22 * - Single OSS input pin (Emergency Shutdown).
23 * - Global I2C Address (0x7F) used for firmware updates.
24 * - Global status monitoring (Temperature, VDD/VPWR Undervoltage Lockout).
25 *
26 * Driver Architecture:
27 *
28 * To handle the mix of per-Quad access and shared resources correctly, this
29 * driver treats the entire Si3474 package as one logical device. The driver
30 * instance associated with the primary I2C address (Quad 0) takes ownership.
31 * It discovers and manages the I2C client for the secondary address (Quad 1).
32 * This primary instance handles shared resources like IRQ management and
33 * registers a single PSE controller device representing all logical PIs.
34 * Internal functions route I2C commands to the appropriate Quad's i2c_client
35 * based on the target channel or PI.
36 *
37 * Terminology Mapping:
38 *
39 * - "PI" (Power Interface): Refers to the logical PSE port as defined by
40 * IEEE 802.3 (typically corresponds to an RJ45 connector). This is the
41 * `id` (0-7) used in the pse_controller_ops.
42 * - "Channel": Refers to one of the 8 physical power control paths within
43 * the Si3474 chip itself (hardware channels 0-7). This terminology is
44 * used internally within the driver to avoid confusion with 'ports'.
45 * - "Quad": One of the two internal 4-channel management units within the
46 * Si3474, each accessed via its own I2C address.
47 *
48 * Relationship:
49 * - A 2-Pair PoE PI uses 1 Channel.
50 * - A 4-Pair PoE PI uses 2 Channels.
51 *
52 * ASCII Schematic:
53 *
54 * +-----------------------------------------------------+
55 * | Si3474 Chip |
56 * | |
57 * | +---------------------+ +---------------------+ |
58 * | | Quad 0 | | Quad 1 | |
59 * | | Channels 0, 1, 2, 3 | | Channels 4, 5, 6, 7 | |
60 * | +----------^----------+ +-------^-------------+ |
61 * | I2C Addr 0 | | I2C Addr 1 |
62 * | +------------------------+ |
63 * | (Primary Driver Instance) (Managed by Primary) |
64 * | |
65 * | Shared Resources (affect whole chip): |
66 * | - Single INTb Output -> Handled by Primary |
67 * | - Single RESETb Input |
68 * | - Single OSS Input -> Handled by Primary |
69 * | - Global I2C Addr (0x7F) for Firmware Update |
70 * | - Global Status (Temp, VDD/VPWR UVLO) |
71 * +-----------------------------------------------------+
72 * | | | | | | | |
73 * Ch0 Ch1 Ch2 Ch3 Ch4 Ch5 Ch6 Ch7 (Physical Channels)
74 *
75 * Example Mapping (Logical PI to Physical Channel(s)):
76 * * 2-Pair Mode (8 PIs):
77 * PI 0 -> Ch 0
78 * PI 1 -> Ch 1
79 * ...
80 * PI 7 -> Ch 7
81 * * 4-Pair Mode (4 PIs):
82 * PI 0 -> Ch 0 + Ch 1 (Managed via Quad 0 Addr)
83 * PI 1 -> Ch 2 + Ch 3 (Managed via Quad 0 Addr)
84 * PI 2 -> Ch 4 + Ch 5 (Managed via Quad 1 Addr)
85 * PI 3 -> Ch 6 + Ch 7 (Managed via Quad 1 Addr)
86 * (Note: Actual mapping depends on Device Tree and PORT_REMAP config)
87 */
88
89#include <linux/i2c.h>
90#include <linux/module.h>
91#include <linux/of.h>
92#include <linux/platform_device.h>
93#include <linux/pse-pd/pse.h>
94
95#define SI3474_MAX_CHANS 8
96
97#define MANUFACTURER_ID 0x08
98#define IC_ID 0x05
99#define SI3474_DEVICE_ID (MANUFACTURER_ID << 3 | IC_ID)
100
101/* Misc registers */
102#define VENDOR_IC_ID_REG 0x1B
103#define TEMPERATURE_REG 0x2C
104#define FIRMWARE_REVISION_REG 0x41
105#define CHIP_REVISION_REG 0x43
106
107/* Main status registers */
108#define POWER_STATUS_REG 0x10
109#define PORT_MODE_REG 0x12
110#define DETECT_CLASS_ENABLE_REG 0x14
111
112/* PORTn Current */
113#define PORT1_CURRENT_LSB_REG 0x30
114
115/* PORTn Current [mA], return in [nA] */
116/* 1000 * ((PORTn_CURRENT_MSB << 8) + PORTn_CURRENT_LSB) / 16384 */
117#define SI3474_NA_STEP (1000 * 1000 * 1000 / 16384)
118
119/* VPWR Voltage */
120#define VPWR_LSB_REG 0x2E
121#define VPWR_MSB_REG 0x2F
122
123/* PORTn Voltage */
124#define PORT1_VOLTAGE_LSB_REG 0x32
125
126/* VPWR Voltage [V], return in [uV] */
127/* 60 * (( VPWR_MSB << 8) + VPWR_LSB) / 16384 */
128#define SI3474_UV_STEP (1000 * 1000 * 60 / 16384)
129
130/* Helper macros */
131#define CHAN_IDX(chan) ((chan) % 4)
132#define CHAN_BIT(chan) BIT(CHAN_IDX(chan))
133#define CHAN_UPPER_BIT(chan) BIT(CHAN_IDX(chan) + 4)
134
135#define CHAN_MASK(chan) (0x03U << (2 * CHAN_IDX(chan)))
136#define CHAN_REG(base, chan) ((base) + (CHAN_IDX(chan) * 4))
137
138struct si3474_pi_desc {
139 u8 chan[2];
140 bool is_4p;
141};
142
143struct si3474_priv {
144 struct i2c_client *client[2];
145 struct pse_controller_dev pcdev;
146 struct device_node *np;
147 struct si3474_pi_desc pi[SI3474_MAX_CHANS];
148};
149
150static struct si3474_priv *to_si3474_priv(struct pse_controller_dev *pcdev)
151{
152 return container_of(pcdev, struct si3474_priv, pcdev);
153}
154
155static void si3474_get_channels(struct si3474_priv *priv, int id,
156 u8 *chan0, u8 *chan1)
157{
158 *chan0 = priv->pi[id].chan[0];
159 *chan1 = priv->pi[id].chan[1];
160}
161
162static struct i2c_client *si3474_get_chan_client(struct si3474_priv *priv,
163 u8 chan)
164{
165 return (chan < 4) ? priv->client[0] : priv->client[1];
166}
167
168static int si3474_pi_get_admin_state(struct pse_controller_dev *pcdev, int id,
169 struct pse_admin_state *admin_state)
170{
171 struct si3474_priv *priv = to_si3474_priv(pcdev);
172 struct i2c_client *client;
173 bool is_enabled;
174 u8 chan0, chan1;
175 s32 ret;
176
177 si3474_get_channels(priv, id, &chan0, &chan1);
178 client = si3474_get_chan_client(priv, chan0);
179
180 ret = i2c_smbus_read_byte_data(client, PORT_MODE_REG);
181 if (ret < 0) {
182 admin_state->c33_admin_state =
183 ETHTOOL_C33_PSE_ADMIN_STATE_UNKNOWN;
184 return ret;
185 }
186
187 is_enabled = ret & (CHAN_MASK(chan0) | CHAN_MASK(chan1));
188
189 if (is_enabled)
190 admin_state->c33_admin_state =
191 ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED;
192 else
193 admin_state->c33_admin_state =
194 ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED;
195
196 return 0;
197}
198
199static int si3474_pi_get_pw_status(struct pse_controller_dev *pcdev, int id,
200 struct pse_pw_status *pw_status)
201{
202 struct si3474_priv *priv = to_si3474_priv(pcdev);
203 struct i2c_client *client;
204 bool delivering;
205 u8 chan0, chan1;
206 s32 ret;
207
208 si3474_get_channels(priv, id, &chan0, &chan1);
209 client = si3474_get_chan_client(priv, chan0);
210
211 ret = i2c_smbus_read_byte_data(client, POWER_STATUS_REG);
212 if (ret < 0) {
213 pw_status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_UNKNOWN;
214 return ret;
215 }
216
217 delivering = ret & (CHAN_UPPER_BIT(chan0) | CHAN_UPPER_BIT(chan1));
218
219 if (delivering)
220 pw_status->c33_pw_status =
221 ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING;
222 else
223 pw_status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED;
224
225 return 0;
226}
227
228static int si3474_get_of_channels(struct si3474_priv *priv)
229{
230 struct pse_pi *pi;
231 u32 chan_id;
232 u8 pi_no;
233 s32 ret;
234
235 for (pi_no = 0; pi_no < SI3474_MAX_CHANS; pi_no++) {
236 pi = &priv->pcdev.pi[pi_no];
237 bool pairset_found = false;
238 u8 pairset_no;
239
240 for (pairset_no = 0; pairset_no < 2; pairset_no++) {
241 if (!pi->pairset[pairset_no].np)
242 continue;
243
244 pairset_found = true;
245
246 ret = of_property_read_u32(pi->pairset[pairset_no].np,
247 "reg", &chan_id);
248 if (ret) {
249 dev_err(&priv->client[0]->dev,
250 "Failed to read channel reg property\n");
251 return ret;
252 }
253 if (chan_id > SI3474_MAX_CHANS) {
254 dev_err(&priv->client[0]->dev,
255 "Incorrect channel number: %d\n", chan_id);
256 return -EINVAL;
257 }
258
259 priv->pi[pi_no].chan[pairset_no] = chan_id;
260 /* Mark as 4-pair if second pairset is present */
261 priv->pi[pi_no].is_4p = (pairset_no == 1);
262 }
263
264 if (pairset_found && !priv->pi[pi_no].is_4p) {
265 dev_err(&priv->client[0]->dev,
266 "Second pairset is missing for PI %pOF, only 4p configs are supported\n",
267 pi->np);
268 return -EINVAL;
269 }
270 }
271
272 return 0;
273}
274
275static int si3474_setup_pi_matrix(struct pse_controller_dev *pcdev)
276{
277 struct si3474_priv *priv = to_si3474_priv(pcdev);
278 s32 ret;
279
280 ret = si3474_get_of_channels(priv);
281 if (ret < 0)
282 dev_warn(&priv->client[0]->dev,
283 "Unable to parse DT PSE power interface matrix\n");
284
285 return ret;
286}
287
288static int si3474_pi_enable(struct pse_controller_dev *pcdev, int id)
289{
290 struct si3474_priv *priv = to_si3474_priv(pcdev);
291 struct i2c_client *client;
292 u8 chan0, chan1;
293 s32 ret;
294 u8 val;
295
296 si3474_get_channels(priv, id, &chan0, &chan1);
297 client = si3474_get_chan_client(priv, chan0);
298
299 /* Release PI from shutdown */
300 ret = i2c_smbus_read_byte_data(client, PORT_MODE_REG);
301 if (ret < 0)
302 return ret;
303
304 val = (u8)ret;
305 val |= CHAN_MASK(chan0);
306 val |= CHAN_MASK(chan1);
307
308 ret = i2c_smbus_write_byte_data(client, PORT_MODE_REG, val);
309 if (ret)
310 return ret;
311
312 /* DETECT_CLASS_ENABLE must be set when using AUTO mode,
313 * otherwise PI does not power up - datasheet section 2.10.2
314 */
315 val = CHAN_BIT(chan0) | CHAN_UPPER_BIT(chan0) |
316 CHAN_BIT(chan1) | CHAN_UPPER_BIT(chan1);
317
318 ret = i2c_smbus_write_byte_data(client, DETECT_CLASS_ENABLE_REG, val);
319 if (ret)
320 return ret;
321
322 return 0;
323}
324
325static int si3474_pi_disable(struct pse_controller_dev *pcdev, int id)
326{
327 struct si3474_priv *priv = to_si3474_priv(pcdev);
328 struct i2c_client *client;
329 u8 chan0, chan1;
330 s32 ret;
331 u8 val;
332
333 si3474_get_channels(priv, id, &chan0, &chan1);
334 client = si3474_get_chan_client(priv, chan0);
335
336 /* Set PI in shutdown mode */
337 ret = i2c_smbus_read_byte_data(client, PORT_MODE_REG);
338 if (ret < 0)
339 return ret;
340
341 val = (u8)ret;
342 val &= ~CHAN_MASK(chan0);
343 val &= ~CHAN_MASK(chan1);
344
345 ret = i2c_smbus_write_byte_data(client, PORT_MODE_REG, val);
346 if (ret)
347 return ret;
348
349 return 0;
350}
351
352static int si3474_pi_get_chan_current(struct si3474_priv *priv, u8 chan)
353{
354 struct i2c_client *client;
355 u64 tmp_64;
356 s32 ret;
357 u8 reg;
358
359 client = si3474_get_chan_client(priv, chan);
360
361 /* Registers 0x30 to 0x3d */
362 reg = CHAN_REG(PORT1_CURRENT_LSB_REG, chan);
363
364 ret = i2c_smbus_read_word_data(client, reg);
365 if (ret < 0)
366 return ret;
367
368 tmp_64 = ret * SI3474_NA_STEP;
369
370 /* uA = nA / 1000 */
371 tmp_64 = DIV_ROUND_CLOSEST_ULL(tmp_64, 1000);
372 return (int)tmp_64;
373}
374
375static int si3474_pi_get_chan_voltage(struct si3474_priv *priv, u8 chan)
376{
377 struct i2c_client *client;
378 s32 ret;
379 u32 val;
380 u8 reg;
381
382 client = si3474_get_chan_client(priv, chan);
383
384 /* Registers 0x32 to 0x3f */
385 reg = CHAN_REG(PORT1_VOLTAGE_LSB_REG, chan);
386
387 ret = i2c_smbus_read_word_data(client, reg);
388 if (ret < 0)
389 return ret;
390
391 val = ret * SI3474_UV_STEP;
392
393 return (int)val;
394}
395
396static int si3474_pi_get_voltage(struct pse_controller_dev *pcdev, int id)
397{
398 struct si3474_priv *priv = to_si3474_priv(pcdev);
399 struct i2c_client *client;
400 u8 chan0, chan1;
401 s32 ret;
402
403 si3474_get_channels(priv, id, &chan0, &chan1);
404 client = si3474_get_chan_client(priv, chan0);
405
406 /* Check which channels are enabled*/
407 ret = i2c_smbus_read_byte_data(client, POWER_STATUS_REG);
408 if (ret < 0)
409 return ret;
410
411 /* Take voltage from the first enabled channel */
412 if (ret & CHAN_BIT(chan0))
413 ret = si3474_pi_get_chan_voltage(priv, chan0);
414 else if (ret & CHAN_BIT(chan1))
415 ret = si3474_pi_get_chan_voltage(priv, chan1);
416 else
417 /* 'should' be no voltage in this case */
418 return 0;
419
420 return ret;
421}
422
423static int si3474_pi_get_actual_pw(struct pse_controller_dev *pcdev, int id)
424{
425 struct si3474_priv *priv = to_si3474_priv(pcdev);
426 u8 chan0, chan1;
427 u32 uV, uA;
428 u64 tmp_64;
429 s32 ret;
430
431 ret = si3474_pi_get_voltage(&priv->pcdev, id);
432
433 /* Do not read currents if voltage is 0 */
434 if (ret <= 0)
435 return ret;
436 uV = ret;
437
438 si3474_get_channels(priv, id, &chan0, &chan1);
439
440 ret = si3474_pi_get_chan_current(priv, chan0);
441 if (ret < 0)
442 return ret;
443 uA = ret;
444
445 ret = si3474_pi_get_chan_current(priv, chan1);
446 if (ret < 0)
447 return ret;
448 uA += ret;
449
450 tmp_64 = uV;
451 tmp_64 *= uA;
452 /* mW = uV * uA / 1000000000 */
453 return DIV_ROUND_CLOSEST_ULL(tmp_64, 1000000000);
454}
455
456static const struct pse_controller_ops si3474_ops = {
457 .setup_pi_matrix = si3474_setup_pi_matrix,
458 .pi_enable = si3474_pi_enable,
459 .pi_disable = si3474_pi_disable,
460 .pi_get_actual_pw = si3474_pi_get_actual_pw,
461 .pi_get_voltage = si3474_pi_get_voltage,
462 .pi_get_admin_state = si3474_pi_get_admin_state,
463 .pi_get_pw_status = si3474_pi_get_pw_status,
464};
465
466static void si3474_ancillary_i2c_remove(void *data)
467{
468 struct i2c_client *client = data;
469
470 i2c_unregister_device(client);
471}
472
473static int si3474_i2c_probe(struct i2c_client *client)
474{
475 struct device *dev = &client->dev;
476 struct si3474_priv *priv;
477 u8 fw_version;
478 s32 ret;
479
480 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
481 dev_err(dev, "i2c check functionality failed\n");
482 return -ENXIO;
483 }
484
485 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
486 if (!priv)
487 return -ENOMEM;
488
489 ret = i2c_smbus_read_byte_data(client, VENDOR_IC_ID_REG);
490 if (ret < 0)
491 return ret;
492
493 if (ret != SI3474_DEVICE_ID) {
494 dev_err(dev, "Wrong device ID: 0x%x\n", ret);
495 return -ENXIO;
496 }
497
498 ret = i2c_smbus_read_byte_data(client, FIRMWARE_REVISION_REG);
499 if (ret < 0)
500 return ret;
501 fw_version = ret;
502
503 ret = i2c_smbus_read_byte_data(client, CHIP_REVISION_REG);
504 if (ret < 0)
505 return ret;
506
507 dev_dbg(dev, "Chip revision: 0x%x, firmware version: 0x%x\n",
508 ret, fw_version);
509
510 priv->client[0] = client;
511 i2c_set_clientdata(client, priv);
512
513 priv->client[1] = i2c_new_ancillary_device(priv->client[0], "secondary",
514 priv->client[0]->addr + 1);
515 if (IS_ERR(priv->client[1]))
516 return PTR_ERR(priv->client[1]);
517
518 ret = devm_add_action_or_reset(dev, si3474_ancillary_i2c_remove, priv->client[1]);
519 if (ret < 0) {
520 dev_err(&priv->client[1]->dev, "Cannot register remove callback\n");
521 return ret;
522 }
523
524 ret = i2c_smbus_read_byte_data(priv->client[1], VENDOR_IC_ID_REG);
525 if (ret < 0) {
526 dev_err(&priv->client[1]->dev, "Cannot access secondary PSE controller\n");
527 return ret;
528 }
529
530 if (ret != SI3474_DEVICE_ID) {
531 dev_err(&priv->client[1]->dev,
532 "Wrong device ID for secondary PSE controller: 0x%x\n", ret);
533 return -ENXIO;
534 }
535
536 priv->np = dev->of_node;
537 priv->pcdev.owner = THIS_MODULE;
538 priv->pcdev.ops = &si3474_ops;
539 priv->pcdev.dev = dev;
540 priv->pcdev.types = ETHTOOL_PSE_C33;
541 priv->pcdev.nr_lines = SI3474_MAX_CHANS;
542
543 ret = devm_pse_controller_register(dev, &priv->pcdev);
544 if (ret) {
545 dev_err(dev, "Failed to register PSE controller: 0x%x\n", ret);
546 return ret;
547 }
548
549 return 0;
550}
551
552static const struct i2c_device_id si3474_id[] = {
553 { "si3474" },
554 {}
555};
556MODULE_DEVICE_TABLE(i2c, si3474_id);
557
558static const struct of_device_id si3474_of_match[] = {
559 {
560 .compatible = "skyworks,si3474",
561 },
562 {},
563};
564MODULE_DEVICE_TABLE(of, si3474_of_match);
565
566static struct i2c_driver si3474_driver = {
567 .probe = si3474_i2c_probe,
568 .id_table = si3474_id,
569 .driver = {
570 .name = "si3474",
571 .of_match_table = si3474_of_match,
572 },
573};
574module_i2c_driver(si3474_driver);
575
576MODULE_AUTHOR("Piotr Kubik <piotr.kubik@adtran.com>");
577MODULE_DESCRIPTION("Skyworks Si3474 PoE PSE Controller driver");
578MODULE_LICENSE("GPL");