File Index
Files and directories
Sign in
FILE

si3474.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/pse-pd/si3474.c C
  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");
~/ Read-only file preview.