Skip to content

Commit 95b75cb

Browse files
mellanoxbmcdavem330
authored andcommitted
mlxsw: i2c: Extend input parameters list of command API
Extend input parameters list of command API in mlxsw_i2c_cmd() in order to support initialization commands. Up until now, only access commands were supported by I2C driver. Signed-off-by: Vadim Pasternak <vadimp@mellanox.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent f43d9d9 commit 95b75cb

File tree

1 file changed

+101
-19
lines changed
  • drivers/net/ethernet/mellanox/mlxsw

1 file changed

+101
-19
lines changed

drivers/net/ethernet/mellanox/mlxsw/i2c.c

Lines changed: 101 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
#define MLXSW_I2C_CIR2_OFF_STATUS (MLXSW_I2C_CIR2_BASE + \
2121
MLXSW_I2C_CIR_STATUS_OFF)
2222
#define MLXSW_I2C_OPMOD_SHIFT 12
23+
#define MLXSW_I2C_EVENT_BIT_SHIFT 22
2324
#define MLXSW_I2C_GO_BIT_SHIFT 23
2425
#define MLXSW_I2C_CIR_CTRL_STATUS_SHIFT 24
26+
#define MLXSW_I2C_EVENT_BIT BIT(MLXSW_I2C_EVENT_BIT_SHIFT)
2527
#define MLXSW_I2C_GO_BIT BIT(MLXSW_I2C_GO_BIT_SHIFT)
2628
#define MLXSW_I2C_GO_OPMODE BIT(MLXSW_I2C_OPMOD_SHIFT)
2729
#define MLXSW_I2C_SET_IMM_CMD (MLXSW_I2C_GO_OPMODE | \
@@ -33,6 +35,9 @@
3335
#define MLXSW_I2C_TLV_HDR_SIZE 0x10
3436
#define MLXSW_I2C_ADDR_WIDTH 4
3537
#define MLXSW_I2C_PUSH_CMD_SIZE (MLXSW_I2C_ADDR_WIDTH + 4)
38+
#define MLXSW_I2C_SET_EVENT_CMD (MLXSW_I2C_EVENT_BIT)
39+
#define MLXSW_I2C_PUSH_EVENT_CMD (MLXSW_I2C_GO_BIT | \
40+
MLXSW_I2C_SET_EVENT_CMD)
3641
#define MLXSW_I2C_READ_SEMA_SIZE 4
3742
#define MLXSW_I2C_PREP_SIZE (MLXSW_I2C_ADDR_WIDTH + 28)
3843
#define MLXSW_I2C_MBOX_SIZE 20
@@ -44,6 +49,7 @@
4449
#define MLXSW_I2C_BLK_MAX 32
4550
#define MLXSW_I2C_RETRY 5
4651
#define MLXSW_I2C_TIMEOUT_MSECS 5000
52+
#define MLXSW_I2C_MAX_DATA_SIZE 256
4753

4854
/**
4955
* struct mlxsw_i2c - device private data:
@@ -213,6 +219,66 @@ static int mlxsw_i2c_write_cmd(struct i2c_client *client,
213219
return 0;
214220
}
215221

222+
/* Routine posts initialization command to ASIC through mail box. */
223+
static int
224+
mlxsw_i2c_write_init_cmd(struct i2c_client *client,
225+
struct mlxsw_i2c *mlxsw_i2c, u16 opcode, u32 in_mod)
226+
{
227+
__be32 push_cmd_buf[MLXSW_I2C_PUSH_CMD_SIZE / 4] = {
228+
0, cpu_to_be32(MLXSW_I2C_PUSH_EVENT_CMD)
229+
};
230+
__be32 prep_cmd_buf[MLXSW_I2C_PREP_SIZE / 4] = {
231+
0, 0, 0, 0, 0, 0,
232+
cpu_to_be32(client->adapter->nr & 0xffff),
233+
cpu_to_be32(MLXSW_I2C_SET_EVENT_CMD)
234+
};
235+
struct i2c_msg push_cmd =
236+
MLXSW_I2C_WRITE_MSG(client, push_cmd_buf,
237+
MLXSW_I2C_PUSH_CMD_SIZE);
238+
struct i2c_msg prep_cmd =
239+
MLXSW_I2C_WRITE_MSG(client, prep_cmd_buf, MLXSW_I2C_PREP_SIZE);
240+
u8 status;
241+
int err;
242+
243+
push_cmd_buf[1] = cpu_to_be32(MLXSW_I2C_PUSH_EVENT_CMD | opcode);
244+
prep_cmd_buf[3] = cpu_to_be32(in_mod);
245+
prep_cmd_buf[7] = cpu_to_be32(MLXSW_I2C_GO_BIT | opcode);
246+
mlxsw_i2c_set_slave_addr((u8 *)prep_cmd_buf,
247+
MLXSW_I2C_CIR2_BASE);
248+
mlxsw_i2c_set_slave_addr((u8 *)push_cmd_buf,
249+
MLXSW_I2C_CIR2_OFF_STATUS);
250+
251+
/* Prepare Command Interface Register for transaction */
252+
err = i2c_transfer(client->adapter, &prep_cmd, 1);
253+
if (err < 0)
254+
return err;
255+
else if (err != 1)
256+
return -EIO;
257+
258+
/* Write out Command Interface Register GO bit to push transaction */
259+
err = i2c_transfer(client->adapter, &push_cmd, 1);
260+
if (err < 0)
261+
return err;
262+
else if (err != 1)
263+
return -EIO;
264+
265+
/* Wait until go bit is cleared. */
266+
err = mlxsw_i2c_wait_go_bit(client, mlxsw_i2c, &status);
267+
if (err) {
268+
dev_err(&client->dev, "HW semaphore is not released");
269+
return err;
270+
}
271+
272+
/* Validate transaction completion status. */
273+
if (status) {
274+
dev_err(&client->dev, "Bad transaction completion status %x\n",
275+
status);
276+
return -EIO;
277+
}
278+
279+
return 0;
280+
}
281+
216282
/* Routine obtains mail box offsets from ASIC register space. */
217283
static int mlxsw_i2c_get_mbox(struct i2c_client *client,
218284
struct mlxsw_i2c *mlxsw_i2c)
@@ -310,8 +376,8 @@ mlxsw_i2c_write(struct device *dev, size_t in_mbox_size, u8 *in_mbox, int num,
310376

311377
/* Routine executes I2C command. */
312378
static int
313-
mlxsw_i2c_cmd(struct device *dev, size_t in_mbox_size, u8 *in_mbox,
314-
size_t out_mbox_size, u8 *out_mbox, u8 *status)
379+
mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size,
380+
u8 *in_mbox, size_t out_mbox_size, u8 *out_mbox, u8 *status)
315381
{
316382
struct i2c_client *client = to_i2c_client(dev);
317383
struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client);
@@ -326,24 +392,40 @@ mlxsw_i2c_cmd(struct device *dev, size_t in_mbox_size, u8 *in_mbox,
326392

327393
WARN_ON(in_mbox_size % sizeof(u32) || out_mbox_size % sizeof(u32));
328394

329-
reg_size = mlxsw_i2c_get_reg_size(in_mbox);
330-
num = reg_size / MLXSW_I2C_BLK_MAX;
331-
if (reg_size % MLXSW_I2C_BLK_MAX)
332-
num++;
395+
if (in_mbox) {
396+
reg_size = mlxsw_i2c_get_reg_size(in_mbox);
397+
num = reg_size / MLXSW_I2C_BLK_MAX;
398+
if (reg_size % MLXSW_I2C_BLK_MAX)
399+
num++;
333400

334-
if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
335-
dev_err(&client->dev, "Could not acquire lock");
336-
return -EINVAL;
337-
}
401+
if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
402+
dev_err(&client->dev, "Could not acquire lock");
403+
return -EINVAL;
404+
}
338405

339-
err = mlxsw_i2c_write(dev, reg_size, in_mbox, num, status);
340-
if (err)
341-
goto cmd_fail;
406+
err = mlxsw_i2c_write(dev, reg_size, in_mbox, num, status);
407+
if (err)
408+
goto cmd_fail;
409+
410+
/* No out mailbox is case of write transaction. */
411+
if (!out_mbox) {
412+
mutex_unlock(&mlxsw_i2c->cmd.lock);
413+
return 0;
414+
}
415+
} else {
416+
/* No input mailbox is case of initialization query command. */
417+
reg_size = MLXSW_I2C_MAX_DATA_SIZE;
418+
num = reg_size / MLXSW_I2C_BLK_MAX;
342419

343-
/* No out mailbox is case of write transaction. */
344-
if (!out_mbox) {
345-
mutex_unlock(&mlxsw_i2c->cmd.lock);
346-
return 0;
420+
if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
421+
dev_err(&client->dev, "Could not acquire lock");
422+
return -EINVAL;
423+
}
424+
425+
err = mlxsw_i2c_write_init_cmd(client, mlxsw_i2c, opcode,
426+
in_mod);
427+
if (err)
428+
goto cmd_fail;
347429
}
348430

349431
/* Send read transaction to get output mailbox content. */
@@ -395,8 +477,8 @@ static int mlxsw_i2c_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod,
395477
{
396478
struct mlxsw_i2c *mlxsw_i2c = bus_priv;
397479

398-
return mlxsw_i2c_cmd(mlxsw_i2c->dev, in_mbox_size, in_mbox,
399-
out_mbox_size, out_mbox, status);
480+
return mlxsw_i2c_cmd(mlxsw_i2c->dev, opcode, in_mod, in_mbox_size,
481+
in_mbox, out_mbox_size, out_mbox, status);
400482
}
401483

402484
static bool mlxsw_i2c_skb_transmit_busy(void *bus_priv,

0 commit comments

Comments
 (0)