1/* 2 * X-Gene SLIMpro I2C Driver 3 * 4 * Copyright (c) 2014, Applied Micro Circuits Corporation 5 * Author: Feng Kan <fkan@apm.com> 6 * Author: Hieu Le <hnle@apm.com> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, see <http://www.gnu.org/licenses/>. 20 * 21 * This driver provides support for X-Gene SLIMpro I2C device access 22 * using the APM X-Gene SLIMpro mailbox driver. 23 * 24 */ 25#include <linux/acpi.h> 26#include <linux/dma-mapping.h> 27#include <linux/i2c.h> 28#include <linux/interrupt.h> 29#include <linux/mailbox_client.h> 30#include <linux/module.h> 31#include <linux/of.h> 32#include <linux/platform_device.h> 33#include <linux/version.h> 34 35#define MAILBOX_OP_TIMEOUT 1000 /* Operation time out in ms */ 36#define MAILBOX_I2C_INDEX 0 37#define SLIMPRO_IIC_BUS 1 /* Use I2C bus 1 only */ 38 39#define SMBUS_CMD_LEN 1 40#define BYTE_DATA 1 41#define WORD_DATA 2 42#define BLOCK_DATA 3 43 44#define SLIMPRO_IIC_I2C_PROTOCOL 0 45#define SLIMPRO_IIC_SMB_PROTOCOL 1 46 47#define SLIMPRO_IIC_READ 0 48#define SLIMPRO_IIC_WRITE 1 49 50#define IIC_SMB_WITHOUT_DATA_LEN 0 51#define IIC_SMB_WITH_DATA_LEN 1 52 53#define SLIMPRO_DEBUG_MSG 0 54#define SLIMPRO_MSG_TYPE_SHIFT 28 55#define SLIMPRO_DBG_SUBTYPE_I2C1READ 4 56#define SLIMPRO_DBGMSG_TYPE_SHIFT 24 57#define SLIMPRO_DBGMSG_TYPE_MASK 0x0F000000U 58#define SLIMPRO_IIC_DEV_SHIFT 23 59#define SLIMPRO_IIC_DEV_MASK 0x00800000U 60#define SLIMPRO_IIC_DEVID_SHIFT 13 61#define SLIMPRO_IIC_DEVID_MASK 0x007FE000U 62#define SLIMPRO_IIC_RW_SHIFT 12 63#define SLIMPRO_IIC_RW_MASK 0x00001000U 64#define SLIMPRO_IIC_PROTO_SHIFT 11 65#define SLIMPRO_IIC_PROTO_MASK 0x00000800U 66#define SLIMPRO_IIC_ADDRLEN_SHIFT 8 67#define SLIMPRO_IIC_ADDRLEN_MASK 0x00000700U 68#define SLIMPRO_IIC_DATALEN_SHIFT 0 69#define SLIMPRO_IIC_DATALEN_MASK 0x000000FFU 70 71/* 72 * SLIMpro I2C message encode 73 * 74 * dev - Controller number (0-based) 75 * chip - I2C chip address 76 * op - SLIMPRO_IIC_READ or SLIMPRO_IIC_WRITE 77 * proto - SLIMPRO_IIC_SMB_PROTOCOL or SLIMPRO_IIC_I2C_PROTOCOL 78 * addrlen - Length of the address field 79 * datalen - Length of the data field 80 */ 81#define SLIMPRO_IIC_ENCODE_MSG(dev, chip, op, proto, addrlen, datalen) \ 82 ((SLIMPRO_DEBUG_MSG << SLIMPRO_MSG_TYPE_SHIFT) | \ 83 ((SLIMPRO_DBG_SUBTYPE_I2C1READ << SLIMPRO_DBGMSG_TYPE_SHIFT) & \ 84 SLIMPRO_DBGMSG_TYPE_MASK) | \ 85 ((dev << SLIMPRO_IIC_DEV_SHIFT) & SLIMPRO_IIC_DEV_MASK) | \ 86 ((chip << SLIMPRO_IIC_DEVID_SHIFT) & SLIMPRO_IIC_DEVID_MASK) | \ 87 ((op << SLIMPRO_IIC_RW_SHIFT) & SLIMPRO_IIC_RW_MASK) | \ 88 ((proto << SLIMPRO_IIC_PROTO_SHIFT) & SLIMPRO_IIC_PROTO_MASK) | \ 89 ((addrlen << SLIMPRO_IIC_ADDRLEN_SHIFT) & SLIMPRO_IIC_ADDRLEN_MASK) | \ 90 ((datalen << SLIMPRO_IIC_DATALEN_SHIFT) & SLIMPRO_IIC_DATALEN_MASK)) 91 92/* 93 * Encode for upper address for block data 94 */ 95#define SLIMPRO_IIC_ENCODE_FLAG_BUFADDR 0x80000000 96#define SLIMPRO_IIC_ENCODE_FLAG_WITH_DATA_LEN(a) ((u32) (((a) << 30) \ 97 & 0x40000000)) 98#define SLIMPRO_IIC_ENCODE_UPPER_BUFADDR(a) ((u32) (((a) >> 12) \ 99 & 0x3FF00000)) 100#define SLIMPRO_IIC_ENCODE_ADDR(a) ((a) & 0x000FFFFF) 101 102struct slimpro_i2c_dev { 103 struct i2c_adapter adapter; 104 struct device *dev; 105 struct mbox_chan *mbox_chan; 106 struct mbox_client mbox_client; 107 struct completion rd_complete; 108 u8 dma_buffer[I2C_SMBUS_BLOCK_MAX]; 109 u32 *resp_msg; 110}; 111 112#define to_slimpro_i2c_dev(cl) \ 113 container_of(cl, struct slimpro_i2c_dev, mbox_client) 114 115static void slimpro_i2c_rx_cb(struct mbox_client *cl, void *mssg) 116{ 117 struct slimpro_i2c_dev *ctx = to_slimpro_i2c_dev(cl); 118 119 /* 120 * Response message format: 121 * mssg[0] is the return code of the operation 122 * mssg[1] is the first data word 123 * mssg[2] is NOT used 124 */ 125 if (ctx->resp_msg) 126 *ctx->resp_msg = ((u32 *)mssg)[1]; 127 128 if (ctx->mbox_client.tx_block) 129 complete(&ctx->rd_complete); 130} 131 132static int start_i2c_msg_xfer(struct slimpro_i2c_dev *ctx) 133{ 134 if (ctx->mbox_client.tx_block) { 135 if (!wait_for_completion_timeout(&ctx->rd_complete, 136 msecs_to_jiffies(MAILBOX_OP_TIMEOUT))) 137 return -ETIMEDOUT; 138 } 139 140 /* Check of invalid data or no device */ 141 if (*ctx->resp_msg == 0xffffffff) 142 return -ENODEV; 143 144 return 0; 145} 146 147static int slimpro_i2c_rd(struct slimpro_i2c_dev *ctx, u32 chip, 148 u32 addr, u32 addrlen, u32 protocol, 149 u32 readlen, u32 *data) 150{ 151 u32 msg[3]; 152 int rc; 153 154 msg[0] = SLIMPRO_IIC_ENCODE_MSG(SLIMPRO_IIC_BUS, chip, 155 SLIMPRO_IIC_READ, protocol, addrlen, readlen); 156 msg[1] = SLIMPRO_IIC_ENCODE_ADDR(addr); 157 msg[2] = 0; 158 ctx->resp_msg = data; 159 rc = mbox_send_message(ctx->mbox_chan, &msg); 160 if (rc < 0) 161 goto err; 162 163 rc = start_i2c_msg_xfer(ctx); 164err: 165 ctx->resp_msg = NULL; 166 return rc; 167} 168 169static int slimpro_i2c_wr(struct slimpro_i2c_dev *ctx, u32 chip, 170 u32 addr, u32 addrlen, u32 protocol, u32 writelen, 171 u32 data) 172{ 173 u32 msg[3]; 174 int rc; 175 176 msg[0] = SLIMPRO_IIC_ENCODE_MSG(SLIMPRO_IIC_BUS, chip, 177 SLIMPRO_IIC_WRITE, protocol, addrlen, writelen); 178 msg[1] = SLIMPRO_IIC_ENCODE_ADDR(addr); 179 msg[2] = data; 180 ctx->resp_msg = msg; 181 182 rc = mbox_send_message(ctx->mbox_chan, &msg); 183 if (rc < 0) 184 goto err; 185 186 rc = start_i2c_msg_xfer(ctx); 187err: 188 ctx->resp_msg = NULL; 189 return rc; 190} 191 192static int slimpro_i2c_blkrd(struct slimpro_i2c_dev *ctx, u32 chip, u32 addr, 193 u32 addrlen, u32 protocol, u32 readlen, 194 u32 with_data_len, void *data) 195{ 196 dma_addr_t paddr; 197 u32 msg[3]; 198 int rc; 199 200 paddr = dma_map_single(ctx->dev, ctx->dma_buffer, readlen, DMA_FROM_DEVICE); 201 if (dma_mapping_error(ctx->dev, paddr)) { 202 dev_err(&ctx->adapter.dev, "Error in mapping dma buffer %p\n", 203 ctx->dma_buffer); 204 rc = -ENOMEM; 205 goto err; 206 } 207 208 msg[0] = SLIMPRO_IIC_ENCODE_MSG(SLIMPRO_IIC_BUS, chip, SLIMPRO_IIC_READ, 209 protocol, addrlen, readlen); 210 msg[1] = SLIMPRO_IIC_ENCODE_FLAG_BUFADDR | 211 SLIMPRO_IIC_ENCODE_FLAG_WITH_DATA_LEN(with_data_len) | 212 SLIMPRO_IIC_ENCODE_UPPER_BUFADDR(paddr) | 213 SLIMPRO_IIC_ENCODE_ADDR(addr); 214 msg[2] = (u32)paddr; 215 ctx->resp_msg = msg; 216 217 rc = mbox_send_message(ctx->mbox_chan, &msg); 218 if (rc < 0) 219 goto err_unmap; 220 221 rc = start_i2c_msg_xfer(ctx); 222 223 /* Copy to destination */ 224 memcpy(data, ctx->dma_buffer, readlen); 225 226err_unmap: 227 dma_unmap_single(ctx->dev, paddr, readlen, DMA_FROM_DEVICE); 228err: 229 ctx->resp_msg = NULL; 230 return rc; 231} 232 233static int slimpro_i2c_blkwr(struct slimpro_i2c_dev *ctx, u32 chip, 234 u32 addr, u32 addrlen, u32 protocol, u32 writelen, 235 void *data) 236{ 237 dma_addr_t paddr; 238 u32 msg[3]; 239 int rc; 240 241 memcpy(ctx->dma_buffer, data, writelen); 242 paddr = dma_map_single(ctx->dev, ctx->dma_buffer, writelen, 243 DMA_TO_DEVICE); 244 if (dma_mapping_error(ctx->dev, paddr)) { 245 dev_err(&ctx->adapter.dev, "Error in mapping dma buffer %p\n", 246 ctx->dma_buffer); 247 rc = -ENOMEM; 248 goto err; 249 } 250 251 msg[0] = SLIMPRO_IIC_ENCODE_MSG(SLIMPRO_IIC_BUS, chip, SLIMPRO_IIC_WRITE, 252 protocol, addrlen, writelen); 253 msg[1] = SLIMPRO_IIC_ENCODE_FLAG_BUFADDR | 254 SLIMPRO_IIC_ENCODE_UPPER_BUFADDR(paddr) | 255 SLIMPRO_IIC_ENCODE_ADDR(addr); 256 msg[2] = (u32)paddr; 257 ctx->resp_msg = msg; 258 259 if (ctx->mbox_client.tx_block) 260 reinit_completion(&ctx->rd_complete); 261 262 rc = mbox_send_message(ctx->mbox_chan, &msg); 263 if (rc < 0) 264 goto err_unmap; 265 266 rc = start_i2c_msg_xfer(ctx); 267 268err_unmap: 269 dma_unmap_single(ctx->dev, paddr, writelen, DMA_TO_DEVICE); 270err: 271 ctx->resp_msg = NULL; 272 return rc; 273} 274 275static int xgene_slimpro_i2c_xfer(struct i2c_adapter *adap, u16 addr, 276 unsigned short flags, char read_write, 277 u8 command, int size, 278 union i2c_smbus_data *data) 279{ 280 struct slimpro_i2c_dev *ctx = i2c_get_adapdata(adap); 281 int ret = -EOPNOTSUPP; 282 u32 val; 283 284 switch (size) { 285 case I2C_SMBUS_BYTE: 286 if (read_write == I2C_SMBUS_READ) { 287 ret = slimpro_i2c_rd(ctx, addr, 0, 0, 288 SLIMPRO_IIC_SMB_PROTOCOL, 289 BYTE_DATA, &val); 290 data->byte = val; 291 } else { 292 ret = slimpro_i2c_wr(ctx, addr, command, SMBUS_CMD_LEN, 293 SLIMPRO_IIC_SMB_PROTOCOL, 294 0, 0); 295 } 296 break; 297 case I2C_SMBUS_BYTE_DATA: 298 if (read_write == I2C_SMBUS_READ) { 299 ret = slimpro_i2c_rd(ctx, addr, command, SMBUS_CMD_LEN, 300 SLIMPRO_IIC_SMB_PROTOCOL, 301 BYTE_DATA, &val); 302 data->byte = val; 303 } else { 304 val = data->byte; 305 ret = slimpro_i2c_wr(ctx, addr, command, SMBUS_CMD_LEN, 306 SLIMPRO_IIC_SMB_PROTOCOL, 307 BYTE_DATA, val); 308 } 309 break; 310 case I2C_SMBUS_WORD_DATA: 311 if (read_write == I2C_SMBUS_READ) { 312 ret = slimpro_i2c_rd(ctx, addr, command, SMBUS_CMD_LEN, 313 SLIMPRO_IIC_SMB_PROTOCOL, 314 WORD_DATA, &val); 315 data->word = val; 316 } else { 317 val = data->word; 318 ret = slimpro_i2c_wr(ctx, addr, command, SMBUS_CMD_LEN, 319 SLIMPRO_IIC_SMB_PROTOCOL, 320 WORD_DATA, val); 321 } 322 break; 323 case I2C_SMBUS_BLOCK_DATA: 324 if (read_write == I2C_SMBUS_READ) { 325 ret = slimpro_i2c_blkrd(ctx, addr, command, 326 SMBUS_CMD_LEN, 327 SLIMPRO_IIC_SMB_PROTOCOL, 328 I2C_SMBUS_BLOCK_MAX + 1, 329 IIC_SMB_WITH_DATA_LEN, 330 &data->block[0]); 331 332 } else { 333 ret = slimpro_i2c_blkwr(ctx, addr, command, 334 SMBUS_CMD_LEN, 335 SLIMPRO_IIC_SMB_PROTOCOL, 336 data->block[0] + 1, 337 &data->block[0]); 338 } 339 break; 340 case I2C_SMBUS_I2C_BLOCK_DATA: 341 if (read_write == I2C_SMBUS_READ) { 342 ret = slimpro_i2c_blkrd(ctx, addr, 343 command, 344 SMBUS_CMD_LEN, 345 SLIMPRO_IIC_I2C_PROTOCOL, 346 I2C_SMBUS_BLOCK_MAX, 347 IIC_SMB_WITHOUT_DATA_LEN, 348 &data->block[1]); 349 } else { 350 ret = slimpro_i2c_blkwr(ctx, addr, command, 351 SMBUS_CMD_LEN, 352 SLIMPRO_IIC_I2C_PROTOCOL, 353 data->block[0], 354 &data->block[1]); 355 } 356 break; 357 default: 358 break; 359 } 360 return ret; 361} 362 363/* 364* Return list of supported functionality. 365*/ 366static u32 xgene_slimpro_i2c_func(struct i2c_adapter *adapter) 367{ 368 return I2C_FUNC_SMBUS_BYTE | 369 I2C_FUNC_SMBUS_BYTE_DATA | 370 I2C_FUNC_SMBUS_WORD_DATA | 371 I2C_FUNC_SMBUS_BLOCK_DATA | 372 I2C_FUNC_SMBUS_I2C_BLOCK; 373} 374 375static struct i2c_algorithm xgene_slimpro_i2c_algorithm = { 376 .smbus_xfer = xgene_slimpro_i2c_xfer, 377 .functionality = xgene_slimpro_i2c_func, 378}; 379 380static int xgene_slimpro_i2c_probe(struct platform_device *pdev) 381{ 382 struct slimpro_i2c_dev *ctx; 383 struct i2c_adapter *adapter; 384 struct mbox_client *cl; 385 int rc; 386 387 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 388 if (!ctx) 389 return -ENOMEM; 390 391 ctx->dev = &pdev->dev; 392 platform_set_drvdata(pdev, ctx); 393 cl = &ctx->mbox_client; 394 395 /* Request mailbox channel */ 396 cl->dev = &pdev->dev; 397 cl->rx_callback = slimpro_i2c_rx_cb; 398 cl->tx_block = true; 399 init_completion(&ctx->rd_complete); 400 cl->tx_tout = MAILBOX_OP_TIMEOUT; 401 cl->knows_txdone = false; 402 ctx->mbox_chan = mbox_request_channel(cl, MAILBOX_I2C_INDEX); 403 if (IS_ERR(ctx->mbox_chan)) { 404 dev_err(&pdev->dev, "i2c mailbox channel request failed\n"); 405 return PTR_ERR(ctx->mbox_chan); 406 } 407 408 rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 409 if (rc) 410 dev_warn(&pdev->dev, "Unable to set dma mask\n"); 411 412 /* Setup I2C adapter */ 413 adapter = &ctx->adapter; 414 snprintf(adapter->name, sizeof(adapter->name), "MAILBOX I2C"); 415 adapter->algo = &xgene_slimpro_i2c_algorithm; 416 adapter->class = I2C_CLASS_HWMON; 417 adapter->dev.parent = &pdev->dev; 418 i2c_set_adapdata(adapter, ctx); 419 rc = i2c_add_adapter(adapter); 420 if (rc) { 421 dev_err(&pdev->dev, "Adapter registeration failed\n"); 422 mbox_free_channel(ctx->mbox_chan); 423 return rc; 424 } 425 426 dev_info(&pdev->dev, "Mailbox I2C Adapter registered\n"); 427 return 0; 428} 429 430static int xgene_slimpro_i2c_remove(struct platform_device *pdev) 431{ 432 struct slimpro_i2c_dev *ctx = platform_get_drvdata(pdev); 433 434 i2c_del_adapter(&ctx->adapter); 435 436 mbox_free_channel(ctx->mbox_chan); 437 438 return 0; 439} 440 441static const struct of_device_id xgene_slimpro_i2c_dt_ids[] = { 442 {.compatible = "apm,xgene-slimpro-i2c" }, 443 {}, 444}; 445MODULE_DEVICE_TABLE(of, xgene_slimpro_i2c_dt_ids); 446 447#ifdef CONFIG_ACPI 448static const struct acpi_device_id xgene_slimpro_i2c_acpi_ids[] = { 449 {"APMC0D40", 0}, 450 {} 451}; 452MODULE_DEVICE_TABLE(acpi, xgene_slimpro_i2c_acpi_ids); 453#endif 454 455static struct platform_driver xgene_slimpro_i2c_driver = { 456 .probe = xgene_slimpro_i2c_probe, 457 .remove = xgene_slimpro_i2c_remove, 458 .driver = { 459 .name = "xgene-slimpro-i2c", 460 .of_match_table = of_match_ptr(xgene_slimpro_i2c_dt_ids), 461 .acpi_match_table = ACPI_PTR(xgene_slimpro_i2c_acpi_ids) 462 }, 463}; 464 465module_platform_driver(xgene_slimpro_i2c_driver); 466 467MODULE_DESCRIPTION("APM X-Gene SLIMpro I2C driver"); 468MODULE_AUTHOR("Feng Kan <fkan@apm.com>"); 469MODULE_AUTHOR("Hieu Le <hnle@apm.com>"); 470MODULE_LICENSE("GPL"); 471