1 /* 2 * drivers/net/ethernet/mellanox/mlxsw/i2c.c 3 * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 4 * Copyright (c) 2016 Vadim Pasternak <vadimp@mellanox.com> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the names of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * Alternatively, this software may be distributed under the terms of the 19 * GNU General Public License ("GPL") version 2 as published by the Free 20 * Software Foundation. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <linux/err.h> 36 #include <linux/i2c.h> 37 #include <linux/init.h> 38 #include <linux/jiffies.h> 39 #include <linux/kernel.h> 40 #include <linux/mutex.h> 41 #include <linux/module.h> 42 #include <linux/mod_devicetable.h> 43 #include <linux/slab.h> 44 45 #include "cmd.h" 46 #include "core.h" 47 #include "i2c.h" 48 49 static const char mlxsw_i2c_driver_name[] = "mlxsw_i2c"; 50 51 #define MLXSW_I2C_CIR2_BASE 0x72000 52 #define MLXSW_I2C_CIR_STATUS_OFF 0x18 53 #define MLXSW_I2C_CIR2_OFF_STATUS (MLXSW_I2C_CIR2_BASE + \ 54 MLXSW_I2C_CIR_STATUS_OFF) 55 #define MLXSW_I2C_OPMOD_SHIFT 12 56 #define MLXSW_I2C_GO_BIT_SHIFT 23 57 #define MLXSW_I2C_CIR_CTRL_STATUS_SHIFT 24 58 #define MLXSW_I2C_GO_BIT BIT(MLXSW_I2C_GO_BIT_SHIFT) 59 #define MLXSW_I2C_GO_OPMODE BIT(MLXSW_I2C_OPMOD_SHIFT) 60 #define MLXSW_I2C_SET_IMM_CMD (MLXSW_I2C_GO_OPMODE | \ 61 MLXSW_CMD_OPCODE_QUERY_FW) 62 #define MLXSW_I2C_PUSH_IMM_CMD (MLXSW_I2C_GO_BIT | \ 63 MLXSW_I2C_SET_IMM_CMD) 64 #define MLXSW_I2C_SET_CMD (MLXSW_CMD_OPCODE_ACCESS_REG) 65 #define MLXSW_I2C_PUSH_CMD (MLXSW_I2C_GO_BIT | MLXSW_I2C_SET_CMD) 66 #define MLXSW_I2C_TLV_HDR_SIZE 0x10 67 #define MLXSW_I2C_ADDR_WIDTH 4 68 #define MLXSW_I2C_PUSH_CMD_SIZE (MLXSW_I2C_ADDR_WIDTH + 4) 69 #define MLXSW_I2C_READ_SEMA_SIZE 4 70 #define MLXSW_I2C_PREP_SIZE (MLXSW_I2C_ADDR_WIDTH + 28) 71 #define MLXSW_I2C_MBOX_SIZE 20 72 #define MLXSW_I2C_MBOX_OUT_PARAM_OFF 12 73 #define MLXSW_I2C_MAX_BUFF_SIZE 32 74 #define MLXSW_I2C_MBOX_OFFSET_BITS 20 75 #define MLXSW_I2C_MBOX_SIZE_BITS 12 76 #define MLXSW_I2C_ADDR_BUF_SIZE 4 77 #define MLXSW_I2C_BLK_MAX 32 78 #define MLXSW_I2C_RETRY 5 79 #define MLXSW_I2C_TIMEOUT_MSECS 5000 80 81 /** 82 * struct mlxsw_i2c - device private data: 83 * @cmd.mb_size_in: input mailbox size; 84 * @cmd.mb_off_in: input mailbox offset in register space; 85 * @cmd.mb_size_out: output mailbox size; 86 * @cmd.mb_off_out: output mailbox offset in register space; 87 * @cmd.lock: command execution lock; 88 * @dev: I2C device; 89 * @core: switch core pointer; 90 * @bus_info: bus info block; 91 */ 92 struct mlxsw_i2c { 93 struct { 94 u32 mb_size_in; 95 u32 mb_off_in; 96 u32 mb_size_out; 97 u32 mb_off_out; 98 struct mutex lock; 99 } cmd; 100 struct device *dev; 101 struct mlxsw_core *core; 102 struct mlxsw_bus_info bus_info; 103 }; 104 105 #define MLXSW_I2C_READ_MSG(_client, _addr_buf, _buf, _len) { \ 106 { .addr = (_client)->addr, \ 107 .buf = (_addr_buf), \ 108 .len = MLXSW_I2C_ADDR_BUF_SIZE, \ 109 .flags = 0 }, \ 110 { .addr = (_client)->addr, \ 111 .buf = (_buf), \ 112 .len = (_len), \ 113 .flags = I2C_M_RD } } 114 115 #define MLXSW_I2C_WRITE_MSG(_client, _buf, _len) \ 116 { .addr = (_client)->addr, \ 117 .buf = (u8 *)(_buf), \ 118 .len = (_len), \ 119 .flags = 0 } 120 121 /* Routine converts in and out mail boxes offset and size. */ 122 static inline void 123 mlxsw_i2c_convert_mbox(struct mlxsw_i2c *mlxsw_i2c, u8 *buf) 124 { 125 u32 tmp; 126 127 /* Local in/out mailboxes: 20 bits for offset, 12 for size */ 128 tmp = be32_to_cpup((__be32 *) buf); 129 mlxsw_i2c->cmd.mb_off_in = tmp & 130 GENMASK(MLXSW_I2C_MBOX_OFFSET_BITS - 1, 0); 131 mlxsw_i2c->cmd.mb_size_in = (tmp & GENMASK(31, 132 MLXSW_I2C_MBOX_OFFSET_BITS)) >> 133 MLXSW_I2C_MBOX_OFFSET_BITS; 134 135 tmp = be32_to_cpup((__be32 *) (buf + MLXSW_I2C_ADDR_WIDTH)); 136 mlxsw_i2c->cmd.mb_off_out = tmp & 137 GENMASK(MLXSW_I2C_MBOX_OFFSET_BITS - 1, 0); 138 mlxsw_i2c->cmd.mb_size_out = (tmp & GENMASK(31, 139 MLXSW_I2C_MBOX_OFFSET_BITS)) >> 140 MLXSW_I2C_MBOX_OFFSET_BITS; 141 } 142 143 /* Routine obtains register size from mail box buffer. */ 144 static inline int mlxsw_i2c_get_reg_size(u8 *in_mbox) 145 { 146 u16 tmp = be16_to_cpup((__be16 *) (in_mbox + MLXSW_I2C_TLV_HDR_SIZE)); 147 148 return (tmp & 0x7ff) * 4 + MLXSW_I2C_TLV_HDR_SIZE; 149 } 150 151 /* Routine sets I2C device internal offset in the transaction buffer. */ 152 static inline void mlxsw_i2c_set_slave_addr(u8 *buf, u32 off) 153 { 154 __be32 *val = (__be32 *) buf; 155 156 *val = htonl(off); 157 } 158 159 /* Routine waits until go bit is cleared. */ 160 static int mlxsw_i2c_wait_go_bit(struct i2c_client *client, 161 struct mlxsw_i2c *mlxsw_i2c, u8 *p_status) 162 { 163 u8 addr_buf[MLXSW_I2C_ADDR_BUF_SIZE]; 164 u8 buf[MLXSW_I2C_READ_SEMA_SIZE]; 165 int len = MLXSW_I2C_READ_SEMA_SIZE; 166 struct i2c_msg read_sema[] = 167 MLXSW_I2C_READ_MSG(client, addr_buf, buf, len); 168 bool wait_done = false; 169 unsigned long end; 170 int i = 0, err; 171 172 mlxsw_i2c_set_slave_addr(addr_buf, MLXSW_I2C_CIR2_OFF_STATUS); 173 174 end = jiffies + msecs_to_jiffies(MLXSW_I2C_TIMEOUT_MSECS); 175 do { 176 u32 ctrl; 177 178 err = i2c_transfer(client->adapter, read_sema, 179 ARRAY_SIZE(read_sema)); 180 181 ctrl = be32_to_cpu(*(__be32 *) buf); 182 if (err == ARRAY_SIZE(read_sema)) { 183 if (!(ctrl & MLXSW_I2C_GO_BIT)) { 184 wait_done = true; 185 *p_status = ctrl >> 186 MLXSW_I2C_CIR_CTRL_STATUS_SHIFT; 187 break; 188 } 189 } 190 cond_resched(); 191 } while ((time_before(jiffies, end)) || (i++ < MLXSW_I2C_RETRY)); 192 193 if (wait_done) { 194 if (*p_status) 195 err = -EIO; 196 } else { 197 return -ETIMEDOUT; 198 } 199 200 return err > 0 ? 0 : err; 201 } 202 203 /* Routine posts a command to ASIC though mail box. */ 204 static int mlxsw_i2c_write_cmd(struct i2c_client *client, 205 struct mlxsw_i2c *mlxsw_i2c, 206 int immediate) 207 { 208 __be32 push_cmd_buf[MLXSW_I2C_PUSH_CMD_SIZE / 4] = { 209 0, cpu_to_be32(MLXSW_I2C_PUSH_IMM_CMD) 210 }; 211 __be32 prep_cmd_buf[MLXSW_I2C_PREP_SIZE / 4] = { 212 0, 0, 0, 0, 0, 0, 213 cpu_to_be32(client->adapter->nr & 0xffff), 214 cpu_to_be32(MLXSW_I2C_SET_IMM_CMD) 215 }; 216 struct i2c_msg push_cmd = 217 MLXSW_I2C_WRITE_MSG(client, push_cmd_buf, 218 MLXSW_I2C_PUSH_CMD_SIZE); 219 struct i2c_msg prep_cmd = 220 MLXSW_I2C_WRITE_MSG(client, prep_cmd_buf, MLXSW_I2C_PREP_SIZE); 221 int err; 222 223 if (!immediate) { 224 push_cmd_buf[1] = cpu_to_be32(MLXSW_I2C_PUSH_CMD); 225 prep_cmd_buf[7] = cpu_to_be32(MLXSW_I2C_SET_CMD); 226 } 227 mlxsw_i2c_set_slave_addr((u8 *)prep_cmd_buf, 228 MLXSW_I2C_CIR2_BASE); 229 mlxsw_i2c_set_slave_addr((u8 *)push_cmd_buf, 230 MLXSW_I2C_CIR2_OFF_STATUS); 231 232 /* Prepare Command Interface Register for transaction */ 233 err = i2c_transfer(client->adapter, &prep_cmd, 1); 234 if (err < 0) 235 return err; 236 else if (err != 1) 237 return -EIO; 238 239 /* Write out Command Interface Register GO bit to push transaction */ 240 err = i2c_transfer(client->adapter, &push_cmd, 1); 241 if (err < 0) 242 return err; 243 else if (err != 1) 244 return -EIO; 245 246 return 0; 247 } 248 249 /* Routine obtains mail box offsets from ASIC register space. */ 250 static int mlxsw_i2c_get_mbox(struct i2c_client *client, 251 struct mlxsw_i2c *mlxsw_i2c) 252 { 253 u8 addr_buf[MLXSW_I2C_ADDR_BUF_SIZE]; 254 u8 buf[MLXSW_I2C_MBOX_SIZE]; 255 struct i2c_msg mbox_cmd[] = 256 MLXSW_I2C_READ_MSG(client, addr_buf, buf, MLXSW_I2C_MBOX_SIZE); 257 int err; 258 259 /* Read mail boxes offsets. */ 260 mlxsw_i2c_set_slave_addr(addr_buf, MLXSW_I2C_CIR2_BASE); 261 err = i2c_transfer(client->adapter, mbox_cmd, 2); 262 if (err != 2) { 263 dev_err(&client->dev, "Could not obtain mail boxes\n"); 264 if (!err) 265 return -EIO; 266 else 267 return err; 268 } 269 270 /* Convert mail boxes. */ 271 mlxsw_i2c_convert_mbox(mlxsw_i2c, &buf[MLXSW_I2C_MBOX_OUT_PARAM_OFF]); 272 273 return err; 274 } 275 276 /* Routine sends I2C write transaction to ASIC device. */ 277 static int 278 mlxsw_i2c_write(struct device *dev, size_t in_mbox_size, u8 *in_mbox, int num, 279 u8 *p_status) 280 { 281 struct i2c_client *client = to_i2c_client(dev); 282 struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client); 283 unsigned long timeout = msecs_to_jiffies(MLXSW_I2C_TIMEOUT_MSECS); 284 u8 tran_buf[MLXSW_I2C_MAX_BUFF_SIZE + MLXSW_I2C_ADDR_BUF_SIZE]; 285 int off = mlxsw_i2c->cmd.mb_off_in, chunk_size, i, j; 286 unsigned long end; 287 struct i2c_msg write_tran = 288 MLXSW_I2C_WRITE_MSG(client, tran_buf, MLXSW_I2C_PUSH_CMD_SIZE); 289 int err; 290 291 for (i = 0; i < num; i++) { 292 chunk_size = (in_mbox_size > MLXSW_I2C_BLK_MAX) ? 293 MLXSW_I2C_BLK_MAX : in_mbox_size; 294 write_tran.len = MLXSW_I2C_ADDR_WIDTH + chunk_size; 295 mlxsw_i2c_set_slave_addr(tran_buf, off); 296 memcpy(&tran_buf[MLXSW_I2C_ADDR_BUF_SIZE], in_mbox + 297 MLXSW_I2C_BLK_MAX * i, chunk_size); 298 299 j = 0; 300 end = jiffies + timeout; 301 do { 302 err = i2c_transfer(client->adapter, &write_tran, 1); 303 if (err == 1) 304 break; 305 306 cond_resched(); 307 } while ((time_before(jiffies, end)) || 308 (j++ < MLXSW_I2C_RETRY)); 309 310 if (err != 1) { 311 if (!err) 312 err = -EIO; 313 return err; 314 } 315 316 off += chunk_size; 317 in_mbox_size -= chunk_size; 318 } 319 320 /* Prepare and write out Command Interface Register for transaction. */ 321 err = mlxsw_i2c_write_cmd(client, mlxsw_i2c, 0); 322 if (err) { 323 dev_err(&client->dev, "Could not start transaction"); 324 return -EIO; 325 } 326 327 /* Wait until go bit is cleared. */ 328 err = mlxsw_i2c_wait_go_bit(client, mlxsw_i2c, p_status); 329 if (err) { 330 dev_err(&client->dev, "HW semaphore is not released"); 331 return err; 332 } 333 334 /* Validate transaction completion status. */ 335 if (*p_status) { 336 dev_err(&client->dev, "Bad transaction completion status %x\n", 337 *p_status); 338 return -EIO; 339 } 340 341 return 0; 342 } 343 344 /* Routine executes I2C command. */ 345 static int 346 mlxsw_i2c_cmd(struct device *dev, size_t in_mbox_size, u8 *in_mbox, 347 size_t out_mbox_size, u8 *out_mbox, u8 *status) 348 { 349 struct i2c_client *client = to_i2c_client(dev); 350 struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client); 351 unsigned long timeout = msecs_to_jiffies(MLXSW_I2C_TIMEOUT_MSECS); 352 u8 tran_buf[MLXSW_I2C_ADDR_BUF_SIZE]; 353 int num, chunk_size, reg_size, i, j; 354 int off = mlxsw_i2c->cmd.mb_off_out; 355 unsigned long end; 356 struct i2c_msg read_tran[] = 357 MLXSW_I2C_READ_MSG(client, tran_buf, NULL, 0); 358 int err; 359 360 WARN_ON(in_mbox_size % sizeof(u32) || out_mbox_size % sizeof(u32)); 361 362 reg_size = mlxsw_i2c_get_reg_size(in_mbox); 363 num = reg_size / MLXSW_I2C_BLK_MAX; 364 if (reg_size % MLXSW_I2C_BLK_MAX) 365 num++; 366 367 if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) { 368 dev_err(&client->dev, "Could not acquire lock"); 369 return -EINVAL; 370 } 371 372 err = mlxsw_i2c_write(dev, reg_size, in_mbox, num, status); 373 if (err) 374 goto cmd_fail; 375 376 /* No out mailbox is case of write transaction. */ 377 if (!out_mbox) { 378 mutex_unlock(&mlxsw_i2c->cmd.lock); 379 return 0; 380 } 381 382 /* Send read transaction to get output mailbox content. */ 383 read_tran[1].buf = out_mbox; 384 for (i = 0; i < num; i++) { 385 chunk_size = (reg_size > MLXSW_I2C_BLK_MAX) ? 386 MLXSW_I2C_BLK_MAX : reg_size; 387 read_tran[1].len = chunk_size; 388 mlxsw_i2c_set_slave_addr(tran_buf, off); 389 390 j = 0; 391 end = jiffies + timeout; 392 do { 393 err = i2c_transfer(client->adapter, read_tran, 394 ARRAY_SIZE(read_tran)); 395 if (err == ARRAY_SIZE(read_tran)) 396 break; 397 398 cond_resched(); 399 } while ((time_before(jiffies, end)) || 400 (j++ < MLXSW_I2C_RETRY)); 401 402 if (err != ARRAY_SIZE(read_tran)) { 403 if (!err) 404 err = -EIO; 405 406 goto cmd_fail; 407 } 408 409 off += chunk_size; 410 reg_size -= chunk_size; 411 read_tran[1].buf += chunk_size; 412 } 413 414 mutex_unlock(&mlxsw_i2c->cmd.lock); 415 416 return 0; 417 418 cmd_fail: 419 mutex_unlock(&mlxsw_i2c->cmd.lock); 420 return err; 421 } 422 423 static int mlxsw_i2c_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod, 424 u32 in_mod, bool out_mbox_direct, 425 char *in_mbox, size_t in_mbox_size, 426 char *out_mbox, size_t out_mbox_size, 427 u8 *status) 428 { 429 struct mlxsw_i2c *mlxsw_i2c = bus_priv; 430 431 return mlxsw_i2c_cmd(mlxsw_i2c->dev, in_mbox_size, in_mbox, 432 out_mbox_size, out_mbox, status); 433 } 434 435 static bool mlxsw_i2c_skb_transmit_busy(void *bus_priv, 436 const struct mlxsw_tx_info *tx_info) 437 { 438 return false; 439 } 440 441 static int mlxsw_i2c_skb_transmit(void *bus_priv, struct sk_buff *skb, 442 const struct mlxsw_tx_info *tx_info) 443 { 444 return 0; 445 } 446 447 static int 448 mlxsw_i2c_init(void *bus_priv, struct mlxsw_core *mlxsw_core, 449 const struct mlxsw_config_profile *profile, 450 struct mlxsw_res *resources) 451 { 452 struct mlxsw_i2c *mlxsw_i2c = bus_priv; 453 454 mlxsw_i2c->core = mlxsw_core; 455 456 return 0; 457 } 458 459 static void mlxsw_i2c_fini(void *bus_priv) 460 { 461 struct mlxsw_i2c *mlxsw_i2c = bus_priv; 462 463 mlxsw_i2c->core = NULL; 464 } 465 466 static const struct mlxsw_bus mlxsw_i2c_bus = { 467 .kind = "i2c", 468 .init = mlxsw_i2c_init, 469 .fini = mlxsw_i2c_fini, 470 .skb_transmit_busy = mlxsw_i2c_skb_transmit_busy, 471 .skb_transmit = mlxsw_i2c_skb_transmit, 472 .cmd_exec = mlxsw_i2c_cmd_exec, 473 }; 474 475 static int mlxsw_i2c_probe(struct i2c_client *client, 476 const struct i2c_device_id *id) 477 { 478 struct mlxsw_i2c *mlxsw_i2c; 479 u8 status; 480 int err; 481 482 mlxsw_i2c = devm_kzalloc(&client->dev, sizeof(*mlxsw_i2c), GFP_KERNEL); 483 if (!mlxsw_i2c) 484 return -ENOMEM; 485 486 i2c_set_clientdata(client, mlxsw_i2c); 487 mutex_init(&mlxsw_i2c->cmd.lock); 488 489 /* In order to use mailboxes through the i2c, special area is reserved 490 * on the i2c address space that can be used for input and output 491 * mailboxes. Such mailboxes are called local mailboxes. When using a 492 * local mailbox, software should specify 0 as the Input/Output 493 * parameters. The location of the Local Mailbox addresses on the i2c 494 * space can be retrieved through the QUERY_FW command. 495 * For this purpose QUERY_FW is to be issued with opcode modifier equal 496 * 0x01. For such command the output parameter is an immediate value. 497 * Here QUERY_FW command is invoked for ASIC probing and for getting 498 * local mailboxes addresses from immedate output parameters. 499 */ 500 501 /* Prepare and write out Command Interface Register for transaction */ 502 err = mlxsw_i2c_write_cmd(client, mlxsw_i2c, 1); 503 if (err) { 504 dev_err(&client->dev, "Could not start transaction"); 505 goto errout; 506 } 507 508 /* Wait until go bit is cleared. */ 509 err = mlxsw_i2c_wait_go_bit(client, mlxsw_i2c, &status); 510 if (err) { 511 dev_err(&client->dev, "HW semaphore is not released"); 512 goto errout; 513 } 514 515 /* Validate transaction completion status. */ 516 if (status) { 517 dev_err(&client->dev, "Bad transaction completion status %x\n", 518 status); 519 err = -EIO; 520 goto errout; 521 } 522 523 /* Get mailbox offsets. */ 524 err = mlxsw_i2c_get_mbox(client, mlxsw_i2c); 525 if (err < 0) { 526 dev_err(&client->dev, "Fail to get mailboxes\n"); 527 goto errout; 528 } 529 530 dev_info(&client->dev, "%s mb size=%x off=0x%08x out mb size=%x off=0x%08x\n", 531 id->name, mlxsw_i2c->cmd.mb_size_in, 532 mlxsw_i2c->cmd.mb_off_in, mlxsw_i2c->cmd.mb_size_out, 533 mlxsw_i2c->cmd.mb_off_out); 534 535 /* Register device bus. */ 536 mlxsw_i2c->bus_info.device_kind = id->name; 537 mlxsw_i2c->bus_info.device_name = client->name; 538 mlxsw_i2c->bus_info.dev = &client->dev; 539 mlxsw_i2c->dev = &client->dev; 540 541 err = mlxsw_core_bus_device_register(&mlxsw_i2c->bus_info, 542 &mlxsw_i2c_bus, mlxsw_i2c, false, 543 NULL); 544 if (err) { 545 dev_err(&client->dev, "Fail to register core bus\n"); 546 return err; 547 } 548 549 return 0; 550 551 errout: 552 i2c_set_clientdata(client, NULL); 553 554 return err; 555 } 556 557 static int mlxsw_i2c_remove(struct i2c_client *client) 558 { 559 struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client); 560 561 mlxsw_core_bus_device_unregister(mlxsw_i2c->core, false); 562 mutex_destroy(&mlxsw_i2c->cmd.lock); 563 564 return 0; 565 } 566 567 int mlxsw_i2c_driver_register(struct i2c_driver *i2c_driver) 568 { 569 i2c_driver->probe = mlxsw_i2c_probe; 570 i2c_driver->remove = mlxsw_i2c_remove; 571 return i2c_add_driver(i2c_driver); 572 } 573 EXPORT_SYMBOL(mlxsw_i2c_driver_register); 574 575 void mlxsw_i2c_driver_unregister(struct i2c_driver *i2c_driver) 576 { 577 i2c_del_driver(i2c_driver); 578 } 579 EXPORT_SYMBOL(mlxsw_i2c_driver_unregister); 580 581 MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>"); 582 MODULE_DESCRIPTION("Mellanox switch I2C interface driver"); 583 MODULE_LICENSE("Dual BSD/GPL"); 584