1 /* 2 * I2C driver for Marvell 88PM860x 3 * 4 * Copyright (C) 2009 Marvell International Ltd. 5 * Haojian Zhuang <haojian.zhuang@marvell.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/platform_device.h> 14 #include <linux/i2c.h> 15 #include <linux/err.h> 16 #include <linux/regmap.h> 17 #include <linux/mfd/88pm860x.h> 18 #include <linux/slab.h> 19 20 int pm860x_reg_read(struct i2c_client *i2c, int reg) 21 { 22 struct pm860x_chip *chip = i2c_get_clientdata(i2c); 23 struct regmap *map = (i2c == chip->client) ? chip->regmap 24 : chip->regmap_companion; 25 unsigned int data; 26 int ret; 27 28 ret = regmap_read(map, reg, &data); 29 if (ret < 0) 30 return ret; 31 else 32 return (int)data; 33 } 34 EXPORT_SYMBOL(pm860x_reg_read); 35 36 int pm860x_reg_write(struct i2c_client *i2c, int reg, 37 unsigned char data) 38 { 39 struct pm860x_chip *chip = i2c_get_clientdata(i2c); 40 struct regmap *map = (i2c == chip->client) ? chip->regmap 41 : chip->regmap_companion; 42 int ret; 43 44 ret = regmap_write(map, reg, data); 45 return ret; 46 } 47 EXPORT_SYMBOL(pm860x_reg_write); 48 49 int pm860x_bulk_read(struct i2c_client *i2c, int reg, 50 int count, unsigned char *buf) 51 { 52 struct pm860x_chip *chip = i2c_get_clientdata(i2c); 53 struct regmap *map = (i2c == chip->client) ? chip->regmap 54 : chip->regmap_companion; 55 int ret; 56 57 ret = regmap_raw_read(map, reg, buf, count); 58 return ret; 59 } 60 EXPORT_SYMBOL(pm860x_bulk_read); 61 62 int pm860x_bulk_write(struct i2c_client *i2c, int reg, 63 int count, unsigned char *buf) 64 { 65 struct pm860x_chip *chip = i2c_get_clientdata(i2c); 66 struct regmap *map = (i2c == chip->client) ? chip->regmap 67 : chip->regmap_companion; 68 int ret; 69 70 ret = regmap_raw_write(map, reg, buf, count); 71 return ret; 72 } 73 EXPORT_SYMBOL(pm860x_bulk_write); 74 75 int pm860x_set_bits(struct i2c_client *i2c, int reg, 76 unsigned char mask, unsigned char data) 77 { 78 struct pm860x_chip *chip = i2c_get_clientdata(i2c); 79 struct regmap *map = (i2c == chip->client) ? chip->regmap 80 : chip->regmap_companion; 81 int ret; 82 83 ret = regmap_update_bits(map, reg, mask, data); 84 return ret; 85 } 86 EXPORT_SYMBOL(pm860x_set_bits); 87 88 static int read_device(struct i2c_client *i2c, int reg, 89 int bytes, void *dest) 90 { 91 unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX + 3]; 92 unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX + 2]; 93 struct i2c_adapter *adap = i2c->adapter; 94 struct i2c_msg msg[2] = {{i2c->addr, 0, 1, msgbuf0}, 95 {i2c->addr, I2C_M_RD, 0, msgbuf1}, 96 }; 97 int num = 1, ret = 0; 98 99 if (dest == NULL) 100 return -EINVAL; 101 msgbuf0[0] = (unsigned char)reg; /* command */ 102 msg[1].len = bytes; 103 104 /* if data needs to read back, num should be 2 */ 105 if (bytes > 0) 106 num = 2; 107 ret = adap->algo->master_xfer(adap, msg, num); 108 memcpy(dest, msgbuf1, bytes); 109 if (ret < 0) 110 return ret; 111 return 0; 112 } 113 114 static int write_device(struct i2c_client *i2c, int reg, 115 int bytes, void *src) 116 { 117 unsigned char buf[bytes + 1]; 118 struct i2c_adapter *adap = i2c->adapter; 119 struct i2c_msg msg; 120 int ret; 121 122 buf[0] = (unsigned char)reg; 123 memcpy(&buf[1], src, bytes); 124 msg.addr = i2c->addr; 125 msg.flags = 0; 126 msg.len = bytes + 1; 127 msg.buf = buf; 128 129 ret = adap->algo->master_xfer(adap, &msg, 1); 130 if (ret < 0) 131 return ret; 132 return 0; 133 } 134 135 int pm860x_page_reg_read(struct i2c_client *i2c, int reg) 136 { 137 unsigned char zero = 0; 138 unsigned char data; 139 int ret; 140 141 i2c_lock_adapter(i2c->adapter); 142 read_device(i2c, 0xFA, 0, &zero); 143 read_device(i2c, 0xFB, 0, &zero); 144 read_device(i2c, 0xFF, 0, &zero); 145 ret = read_device(i2c, reg, 1, &data); 146 if (ret >= 0) 147 ret = (int)data; 148 read_device(i2c, 0xFE, 0, &zero); 149 read_device(i2c, 0xFC, 0, &zero); 150 i2c_unlock_adapter(i2c->adapter); 151 return ret; 152 } 153 EXPORT_SYMBOL(pm860x_page_reg_read); 154 155 int pm860x_page_reg_write(struct i2c_client *i2c, int reg, 156 unsigned char data) 157 { 158 unsigned char zero; 159 int ret; 160 161 i2c_lock_adapter(i2c->adapter); 162 read_device(i2c, 0xFA, 0, &zero); 163 read_device(i2c, 0xFB, 0, &zero); 164 read_device(i2c, 0xFF, 0, &zero); 165 ret = write_device(i2c, reg, 1, &data); 166 read_device(i2c, 0xFE, 0, &zero); 167 read_device(i2c, 0xFC, 0, &zero); 168 i2c_unlock_adapter(i2c->adapter); 169 return ret; 170 } 171 EXPORT_SYMBOL(pm860x_page_reg_write); 172 173 int pm860x_page_bulk_read(struct i2c_client *i2c, int reg, 174 int count, unsigned char *buf) 175 { 176 unsigned char zero = 0; 177 int ret; 178 179 i2c_lock_adapter(i2c->adapter); 180 read_device(i2c, 0xfa, 0, &zero); 181 read_device(i2c, 0xfb, 0, &zero); 182 read_device(i2c, 0xff, 0, &zero); 183 ret = read_device(i2c, reg, count, buf); 184 read_device(i2c, 0xFE, 0, &zero); 185 read_device(i2c, 0xFC, 0, &zero); 186 i2c_unlock_adapter(i2c->adapter); 187 return ret; 188 } 189 EXPORT_SYMBOL(pm860x_page_bulk_read); 190 191 int pm860x_page_bulk_write(struct i2c_client *i2c, int reg, 192 int count, unsigned char *buf) 193 { 194 unsigned char zero = 0; 195 int ret; 196 197 i2c_lock_adapter(i2c->adapter); 198 read_device(i2c, 0xFA, 0, &zero); 199 read_device(i2c, 0xFB, 0, &zero); 200 read_device(i2c, 0xFF, 0, &zero); 201 ret = write_device(i2c, reg, count, buf); 202 read_device(i2c, 0xFE, 0, &zero); 203 read_device(i2c, 0xFC, 0, &zero); 204 i2c_unlock_adapter(i2c->adapter); 205 i2c_unlock_adapter(i2c->adapter); 206 return ret; 207 } 208 EXPORT_SYMBOL(pm860x_page_bulk_write); 209 210 int pm860x_page_set_bits(struct i2c_client *i2c, int reg, 211 unsigned char mask, unsigned char data) 212 { 213 unsigned char zero; 214 unsigned char value; 215 int ret; 216 217 i2c_lock_adapter(i2c->adapter); 218 read_device(i2c, 0xFA, 0, &zero); 219 read_device(i2c, 0xFB, 0, &zero); 220 read_device(i2c, 0xFF, 0, &zero); 221 ret = read_device(i2c, reg, 1, &value); 222 if (ret < 0) 223 goto out; 224 value &= ~mask; 225 value |= data; 226 ret = write_device(i2c, reg, 1, &value); 227 out: 228 read_device(i2c, 0xFE, 0, &zero); 229 read_device(i2c, 0xFC, 0, &zero); 230 i2c_unlock_adapter(i2c->adapter); 231 return ret; 232 } 233 EXPORT_SYMBOL(pm860x_page_set_bits); 234 235 static const struct i2c_device_id pm860x_id_table[] = { 236 { "88PM860x", 0 }, 237 {} 238 }; 239 MODULE_DEVICE_TABLE(i2c, pm860x_id_table); 240 241 static int verify_addr(struct i2c_client *i2c) 242 { 243 unsigned short addr_8607[] = {0x30, 0x34}; 244 unsigned short addr_8606[] = {0x10, 0x11}; 245 int size, i; 246 247 if (i2c == NULL) 248 return 0; 249 size = ARRAY_SIZE(addr_8606); 250 for (i = 0; i < size; i++) { 251 if (i2c->addr == *(addr_8606 + i)) 252 return CHIP_PM8606; 253 } 254 size = ARRAY_SIZE(addr_8607); 255 for (i = 0; i < size; i++) { 256 if (i2c->addr == *(addr_8607 + i)) 257 return CHIP_PM8607; 258 } 259 return 0; 260 } 261 262 static struct regmap_config pm860x_regmap_config = { 263 .reg_bits = 8, 264 .val_bits = 8, 265 }; 266 267 static int __devinit pm860x_probe(struct i2c_client *client, 268 const struct i2c_device_id *id) 269 { 270 struct pm860x_platform_data *pdata = client->dev.platform_data; 271 struct pm860x_chip *chip; 272 int ret; 273 274 if (!pdata) { 275 pr_info("No platform data in %s!\n", __func__); 276 return -EINVAL; 277 } 278 279 chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL); 280 if (chip == NULL) 281 return -ENOMEM; 282 283 chip->id = verify_addr(client); 284 chip->regmap = regmap_init_i2c(client, &pm860x_regmap_config); 285 if (IS_ERR(chip->regmap)) { 286 ret = PTR_ERR(chip->regmap); 287 dev_err(&client->dev, "Failed to allocate register map: %d\n", 288 ret); 289 kfree(chip); 290 return ret; 291 } 292 chip->client = client; 293 i2c_set_clientdata(client, chip); 294 chip->dev = &client->dev; 295 dev_set_drvdata(chip->dev, chip); 296 297 /* 298 * Both client and companion client shares same platform driver. 299 * Driver distinguishes them by pdata->companion_addr. 300 * pdata->companion_addr is only assigned if companion chip exists. 301 * At the same time, the companion_addr shouldn't equal to client 302 * address. 303 */ 304 if (pdata->companion_addr && (pdata->companion_addr != client->addr)) { 305 chip->companion_addr = pdata->companion_addr; 306 chip->companion = i2c_new_dummy(chip->client->adapter, 307 chip->companion_addr); 308 chip->regmap_companion = regmap_init_i2c(chip->companion, 309 &pm860x_regmap_config); 310 if (IS_ERR(chip->regmap_companion)) { 311 ret = PTR_ERR(chip->regmap_companion); 312 dev_err(&chip->companion->dev, 313 "Failed to allocate register map: %d\n", ret); 314 return ret; 315 } 316 i2c_set_clientdata(chip->companion, chip); 317 } 318 319 pm860x_device_init(chip, pdata); 320 return 0; 321 } 322 323 static int __devexit pm860x_remove(struct i2c_client *client) 324 { 325 struct pm860x_chip *chip = i2c_get_clientdata(client); 326 327 pm860x_device_exit(chip); 328 if (chip->companion) { 329 regmap_exit(chip->regmap_companion); 330 i2c_unregister_device(chip->companion); 331 } 332 regmap_exit(chip->regmap); 333 kfree(chip); 334 return 0; 335 } 336 337 #ifdef CONFIG_PM_SLEEP 338 static int pm860x_suspend(struct device *dev) 339 { 340 struct i2c_client *client = container_of(dev, struct i2c_client, dev); 341 struct pm860x_chip *chip = i2c_get_clientdata(client); 342 343 if (device_may_wakeup(dev) && chip->wakeup_flag) 344 enable_irq_wake(chip->core_irq); 345 return 0; 346 } 347 348 static int pm860x_resume(struct device *dev) 349 { 350 struct i2c_client *client = container_of(dev, struct i2c_client, dev); 351 struct pm860x_chip *chip = i2c_get_clientdata(client); 352 353 if (device_may_wakeup(dev) && chip->wakeup_flag) 354 disable_irq_wake(chip->core_irq); 355 return 0; 356 } 357 #endif 358 359 static SIMPLE_DEV_PM_OPS(pm860x_pm_ops, pm860x_suspend, pm860x_resume); 360 361 static struct i2c_driver pm860x_driver = { 362 .driver = { 363 .name = "88PM860x", 364 .owner = THIS_MODULE, 365 .pm = &pm860x_pm_ops, 366 }, 367 .probe = pm860x_probe, 368 .remove = __devexit_p(pm860x_remove), 369 .id_table = pm860x_id_table, 370 }; 371 372 static int __init pm860x_i2c_init(void) 373 { 374 int ret; 375 ret = i2c_add_driver(&pm860x_driver); 376 if (ret != 0) 377 pr_err("Failed to register 88PM860x I2C driver: %d\n", ret); 378 return ret; 379 } 380 subsys_initcall(pm860x_i2c_init); 381 382 static void __exit pm860x_i2c_exit(void) 383 { 384 i2c_del_driver(&pm860x_driver); 385 } 386 module_exit(pm860x_i2c_exit); 387 388 MODULE_DESCRIPTION("I2C Driver for Marvell 88PM860x"); 389 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 390 MODULE_LICENSE("GPL"); 391