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 | \
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
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. */
217283static 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. */
312378static 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
402484static bool mlxsw_i2c_skb_transmit_busy (void * bus_priv ,
0 commit comments