Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Oct 2012 17:13:46 +0000 (UTC)
From:      Navdeep Parhar <np@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r241399 - in head/sys/dev/cxgbe: . common
Message-ID:  <201210101713.q9AHDkDV068141@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: np
Date: Wed Oct 10 17:13:46 2012
New Revision: 241399
URL: http://svn.freebsd.org/changeset/base/241399

Log:
  Add a driver ioctl to read a byte from any device on a port's i2c bus.
  This lets userspace read arbitrary information from the SFP+ modules
  etc. on this bus.
  
  Reading multiple bytes in the same transaction isn't possible right now.
  I'll update the driver once the chip's firmware supports this.
  
  MFC after:	3 days

Modified:
  head/sys/dev/cxgbe/common/common.h
  head/sys/dev/cxgbe/common/t4_hw.c
  head/sys/dev/cxgbe/t4_ioctl.h
  head/sys/dev/cxgbe/t4_main.c

Modified: head/sys/dev/cxgbe/common/common.h
==============================================================================
--- head/sys/dev/cxgbe/common/common.h	Wed Oct 10 16:54:14 2012	(r241398)
+++ head/sys/dev/cxgbe/common/common.h	Wed Oct 10 17:13:46 2012	(r241399)
@@ -521,6 +521,8 @@ int t4_enable_vi(struct adapter *adap, u
 		 bool rx_en, bool tx_en);
 int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
 		     unsigned int nblinks);
+int t4_i2c_rd(struct adapter *adap, unsigned int mbox, unsigned int port_id,
+	      u8 dev_addr, u8 offset, u8 *valp);
 int t4_mdio_rd(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
 	       unsigned int mmd, unsigned int reg, unsigned int *valp);
 int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,

Modified: head/sys/dev/cxgbe/common/t4_hw.c
==============================================================================
--- head/sys/dev/cxgbe/common/t4_hw.c	Wed Oct 10 16:54:14 2012	(r241398)
+++ head/sys/dev/cxgbe/common/t4_hw.c	Wed Oct 10 17:13:46 2012	(r241399)
@@ -3885,6 +3885,36 @@ int t4_fwaddrspace_write(struct adapter 
 }
 
 /**
+ *	t4_i2c_rd - read a byte from an i2c addressable device
+ *	@adap: the adapter
+ *	@mbox: mailbox to use for the FW command
+ *	@port_id: the port id
+ *	@dev_addr: the i2c device address
+ *	@offset: the byte offset to read from
+ *	@valp: where to store the value
+ */
+int t4_i2c_rd(struct adapter *adap, unsigned int mbox, unsigned int port_id,
+	       u8 dev_addr, u8 offset, u8 *valp)
+{
+	int ret;
+	struct fw_ldst_cmd c;
+
+	memset(&c, 0, sizeof(c));
+	c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST |
+		F_FW_CMD_READ |
+		V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_I2C));
+	c.cycles_to_len16 = htonl(FW_LEN16(c));
+	c.u.i2c.pid_pkd = V_FW_LDST_CMD_PID(port_id);
+	c.u.i2c.base = dev_addr;
+	c.u.i2c.boffset = offset;
+
+	ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
+	if (ret == 0)
+		*valp = c.u.i2c.data;
+	return ret;
+}
+
+/**
  *	t4_mdio_rd - read a PHY register through MDIO
  *	@adap: the adapter
  *	@mbox: mailbox to use for the FW command

Modified: head/sys/dev/cxgbe/t4_ioctl.h
==============================================================================
--- head/sys/dev/cxgbe/t4_ioctl.h	Wed Oct 10 16:54:14 2012	(r241398)
+++ head/sys/dev/cxgbe/t4_ioctl.h	Wed Oct 10 17:13:46 2012	(r241399)
@@ -49,6 +49,7 @@ enum {
 	T4_GET_SGE_CONTEXT,		/* get SGE context for a queue */
 	T4_LOAD_FW,			/* flash firmware */
 	T4_GET_MEM,			/* read memory */
+	T4_GET_I2C,			/* read from i2c addressible device */
 };
 
 struct t4_reg {
@@ -69,6 +70,14 @@ struct t4_data {
 	uint8_t *data;
 };
 
+struct t4_i2c_data {
+	uint8_t port_id;
+	uint8_t dev_addr;
+	uint8_t offset;
+	uint8_t len;
+	uint8_t data[8];
+};
+
 /*
  * A hardware filter is some valid combination of these.
  */
@@ -224,4 +233,5 @@ struct t4_mem_range {
     struct t4_sge_context)
 #define CHELSIO_T4_LOAD_FW	_IOW('f', T4_LOAD_FW, struct t4_data)
 #define CHELSIO_T4_GET_MEM	_IOW('f', T4_GET_MEM, struct t4_mem_range)
+#define CHELSIO_T4_GET_I2C	_IOWR('f', T4_GET_I2C, struct t4_i2c_data)
 #endif

Modified: head/sys/dev/cxgbe/t4_main.c
==============================================================================
--- head/sys/dev/cxgbe/t4_main.c	Wed Oct 10 16:54:14 2012	(r241398)
+++ head/sys/dev/cxgbe/t4_main.c	Wed Oct 10 17:13:46 2012	(r241399)
@@ -349,6 +349,7 @@ static int set_filter_wr(struct adapter 
 static int del_filter_wr(struct adapter *, int);
 static int get_sge_context(struct adapter *, struct t4_sge_context *);
 static int read_card_mem(struct adapter *, struct t4_mem_range *);
+static int read_i2c(struct adapter *, struct t4_i2c_data *);
 #ifdef TCP_OFFLOAD
 static int toe_capability(struct port_info *, int);
 #endif
@@ -5170,6 +5171,27 @@ proceed:
 	return (rc);
 }
 
+static int
+read_i2c(struct adapter *sc, struct t4_i2c_data *i2cd)
+{
+	int rc;
+
+	ADAPTER_LOCK_ASSERT_OWNED(sc);	/* for mbox */
+
+	if (i2cd->len == 0 || i2cd->port_id >= sc->params.nports)
+		return (EINVAL);
+
+	if (i2cd->len > 1) {
+		/* XXX: need fw support for longer reads in one go */
+		return (ENOTSUP);
+	}
+
+	rc = -t4_i2c_rd(sc, sc->mbox, i2cd->port_id, i2cd->dev_addr,
+	    i2cd->offset, &i2cd->data[0]);
+
+	return (rc);
+}
+
 int
 t4_os_find_pci_capability(struct adapter *sc, int cap)
 {
@@ -5373,6 +5395,11 @@ t4_ioctl(struct cdev *dev, unsigned long
 	case CHELSIO_T4_GET_MEM:
 		rc = read_card_mem(sc, (struct t4_mem_range *)data);
 		break;
+	case CHELSIO_T4_GET_I2C:
+		ADAPTER_LOCK(sc);
+		rc = read_i2c(sc, (struct t4_i2c_data *)data);
+		ADAPTER_UNLOCK(sc);
+		break;
 	default:
 		rc = EINVAL;
 	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201210101713.q9AHDkDV068141>