1 /* 2 * NVEC: NVIDIA compliant embedded controller interface 3 * 4 * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net> 5 * 6 * Authors: Pierre-Hugues Husson <phhusson@free.fr> 7 * Ilya Petrov <ilya.muromec@gmail.com> 8 * Marc Dietrich <marvin24@gmx.de> 9 * 10 * This file is subject to the terms and conditions of the GNU General Public 11 * License. See the file "COPYING" in the main directory of this archive 12 * for more details. 13 * 14 */ 15 16 /* #define DEBUG */ 17 18 #include <asm/irq.h> 19 20 #include <linux/atomic.h> 21 #include <linux/completion.h> 22 #include <linux/interrupt.h> 23 #include <linux/io.h> 24 #include <linux/irq.h> 25 #include <linux/slab.h> 26 #include <linux/gpio.h> 27 #include <linux/serio.h> 28 #include <linux/delay.h> 29 #include <linux/input.h> 30 #include <linux/workqueue.h> 31 #include <linux/clk.h> 32 33 #include <linux/semaphore.h> 34 #include <linux/list.h> 35 #include <linux/notifier.h> 36 #include <linux/platform_device.h> 37 #include <linux/mfd/core.h> 38 39 #include <mach/iomap.h> 40 #include <mach/clk.h> 41 42 #include "nvec.h" 43 44 static const unsigned char EC_DISABLE_EVENT_REPORTING[3] = "\x04\x00\x00"; 45 static const unsigned char EC_ENABLE_EVENT_REPORTING[3] = "\x04\x00\x01"; 46 static const unsigned char EC_GET_FIRMWARE_VERSION[2] = "\x07\x15"; 47 48 static struct nvec_chip *nvec_power_handle; 49 50 static struct mfd_cell nvec_devices[] = { 51 { 52 .name = "nvec-kbd", 53 .id = 1, 54 }, 55 { 56 .name = "nvec-mouse", 57 .id = 1, 58 }, 59 { 60 .name = "nvec-power", 61 .id = 1, 62 }, 63 { 64 .name = "nvec-power", 65 .id = 2, 66 }, 67 { 68 .name = "nvec-leds", 69 .id = 1, 70 }, 71 }; 72 73 int nvec_register_notifier(struct nvec_chip *nvec, struct notifier_block *nb, 74 unsigned int events) 75 { 76 return atomic_notifier_chain_register(&nvec->notifier_list, nb); 77 } 78 EXPORT_SYMBOL_GPL(nvec_register_notifier); 79 80 static int nvec_status_notifier(struct notifier_block *nb, 81 unsigned long event_type, void *data) 82 { 83 unsigned char *msg = (unsigned char *)data; 84 85 if (event_type != NVEC_CNTL) 86 return NOTIFY_DONE; 87 88 printk(KERN_WARNING "unhandled msg type %ld\n", event_type); 89 print_hex_dump(KERN_WARNING, "payload: ", DUMP_PREFIX_NONE, 16, 1, 90 msg, msg[1] + 2, true); 91 92 return NOTIFY_OK; 93 } 94 95 static struct nvec_msg *nvec_msg_alloc(struct nvec_chip *nvec) 96 { 97 int i; 98 99 for (i = 0; i < NVEC_POOL_SIZE; i++) { 100 if (atomic_xchg(&nvec->msg_pool[i].used, 1) == 0) { 101 dev_vdbg(nvec->dev, "INFO: Allocate %i\n", i); 102 return &nvec->msg_pool[i]; 103 } 104 } 105 106 dev_err(nvec->dev, "could not allocate buffer\n"); 107 108 return NULL; 109 } 110 111 static void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg) 112 { 113 dev_vdbg(nvec->dev, "INFO: Free %ti\n", msg - nvec->msg_pool); 114 atomic_set(&msg->used, 0); 115 } 116 117 static void nvec_gpio_set_value(struct nvec_chip *nvec, int value) 118 { 119 dev_dbg(nvec->dev, "GPIO changed from %u to %u\n", 120 gpio_get_value(nvec->gpio), value); 121 gpio_set_value(nvec->gpio, value); 122 } 123 124 void nvec_write_async(struct nvec_chip *nvec, const unsigned char *data, 125 short size) 126 { 127 struct nvec_msg *msg = kzalloc(sizeof(struct nvec_msg), GFP_NOWAIT); 128 129 msg->data = kzalloc(size, GFP_NOWAIT); 130 msg->data[0] = size; 131 memcpy(msg->data + 1, data, size); 132 msg->size = size + 1; 133 msg->pos = 0; 134 INIT_LIST_HEAD(&msg->node); 135 136 list_add_tail(&msg->node, &nvec->tx_data); 137 138 gpio_set_value(nvec->gpio, 0); 139 } 140 EXPORT_SYMBOL(nvec_write_async); 141 142 static void nvec_request_master(struct work_struct *work) 143 { 144 struct nvec_chip *nvec = container_of(work, struct nvec_chip, tx_work); 145 146 if (!list_empty(&nvec->tx_data)) 147 gpio_set_value(nvec->gpio, 0); 148 } 149 150 static int parse_msg(struct nvec_chip *nvec, struct nvec_msg *msg) 151 { 152 if ((msg->data[0] & 1 << 7) == 0 && msg->data[3]) { 153 dev_err(nvec->dev, "ec responded %02x %02x %02x %02x\n", 154 msg->data[0], msg->data[1], msg->data[2], msg->data[3]); 155 return -EINVAL; 156 } 157 158 if ((msg->data[0] >> 7) == 1 && (msg->data[0] & 0x0f) == 5) 159 print_hex_dump(KERN_WARNING, "ec system event ", 160 DUMP_PREFIX_NONE, 16, 1, msg->data, 161 msg->data[1] + 2, true); 162 163 atomic_notifier_call_chain(&nvec->notifier_list, msg->data[0] & 0x8f, 164 msg->data); 165 166 return 0; 167 } 168 169 static struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec, 170 const unsigned char *data, short size) 171 { 172 down(&nvec->sync_write_mutex); 173 174 nvec->sync_write_pending = (data[1] << 8) + data[0]; 175 nvec_write_async(nvec, data, size); 176 177 dev_dbg(nvec->dev, "nvec_sync_write: 0x%04x\n", 178 nvec->sync_write_pending); 179 wait_for_completion(&nvec->sync_write); 180 dev_dbg(nvec->dev, "nvec_sync_write: pong!\n"); 181 182 up(&nvec->sync_write_mutex); 183 184 return nvec->last_sync_msg; 185 } 186 187 /* RX worker */ 188 static void nvec_dispatch(struct work_struct *work) 189 { 190 struct nvec_chip *nvec = container_of(work, struct nvec_chip, rx_work); 191 struct nvec_msg *msg; 192 193 while (!list_empty(&nvec->rx_data)) { 194 msg = list_first_entry(&nvec->rx_data, struct nvec_msg, node); 195 list_del_init(&msg->node); 196 197 if (nvec->sync_write_pending == 198 (msg->data[2] << 8) + msg->data[0]) { 199 dev_dbg(nvec->dev, "sync write completed!\n"); 200 nvec->sync_write_pending = 0; 201 nvec->last_sync_msg = msg; 202 complete(&nvec->sync_write); 203 } else { 204 parse_msg(nvec, msg); 205 if ((!msg) || (!msg->data)) 206 dev_warn(nvec->dev, 207 "attempt access zero pointer\n"); 208 else { 209 kfree(msg->data); 210 kfree(msg); 211 } 212 } 213 } 214 } 215 216 static irqreturn_t nvec_interrupt(int irq, void *dev) 217 { 218 unsigned long status; 219 unsigned long received; 220 unsigned char to_send; 221 struct nvec_msg *msg; 222 struct nvec_chip *nvec = (struct nvec_chip *)dev; 223 void __iomem *base = nvec->base; 224 225 status = readl(base + I2C_SL_STATUS); 226 227 if (!(status & I2C_SL_IRQ)) { 228 dev_warn(nvec->dev, "nvec Spurious IRQ\n"); 229 goto handled; 230 } 231 if (status & END_TRANS && !(status & RCVD)) { 232 nvec->state = NVEC_WAIT; 233 if (nvec->rx->size > 1) { 234 list_add_tail(&nvec->rx->node, &nvec->rx_data); 235 schedule_work(&nvec->rx_work); 236 } else { 237 kfree(nvec->rx->data); 238 kfree(nvec->rx); 239 } 240 return IRQ_HANDLED; 241 } else if (status & RNW) { 242 if (status & RCVD) 243 udelay(3); 244 245 if (status & RCVD) 246 nvec->state = NVEC_WRITE; 247 248 if (list_empty(&nvec->tx_data)) { 249 dev_err(nvec->dev, "nvec empty tx - sending no-op\n"); 250 to_send = 0x8a; 251 nvec_write_async(nvec, "\x07\x02", 2); 252 } else { 253 msg = 254 list_first_entry(&nvec->tx_data, struct nvec_msg, 255 node); 256 if (msg->pos < msg->size) { 257 to_send = msg->data[msg->pos]; 258 msg->pos++; 259 } else { 260 dev_err(nvec->dev, "nvec crap! %d\n", 261 msg->size); 262 to_send = 0x01; 263 } 264 265 if (msg->pos >= msg->size) { 266 list_del_init(&msg->node); 267 kfree(msg->data); 268 kfree(msg); 269 schedule_work(&nvec->tx_work); 270 nvec->state = NVEC_WAIT; 271 } 272 } 273 writel(to_send, base + I2C_SL_RCVD); 274 275 gpio_set_value(nvec->gpio, 1); 276 277 dev_dbg(nvec->dev, "nvec sent %x\n", to_send); 278 279 goto handled; 280 } else { 281 received = readl(base + I2C_SL_RCVD); 282 283 if (status & RCVD) { 284 writel(0, base + I2C_SL_RCVD); 285 goto handled; 286 } 287 288 if (nvec->state == NVEC_WAIT) { 289 nvec->state = NVEC_READ; 290 msg = kzalloc(sizeof(struct nvec_msg), GFP_NOWAIT); 291 msg->data = kzalloc(32, GFP_NOWAIT); 292 INIT_LIST_HEAD(&msg->node); 293 nvec->rx = msg; 294 } else 295 msg = nvec->rx; 296 297 BUG_ON(msg->pos > 32); 298 299 msg->data[msg->pos] = received; 300 msg->pos++; 301 msg->size = msg->pos; 302 dev_dbg(nvec->dev, "Got %02lx from Master (pos: %d)!\n", 303 received, msg->pos); 304 } 305 handled: 306 return IRQ_HANDLED; 307 } 308 309 static void tegra_init_i2c_slave(struct nvec_chip *nvec) 310 { 311 u32 val; 312 313 clk_enable(nvec->i2c_clk); 314 315 tegra_periph_reset_assert(nvec->i2c_clk); 316 udelay(2); 317 tegra_periph_reset_deassert(nvec->i2c_clk); 318 319 val = I2C_CNFG_NEW_MASTER_SFM | I2C_CNFG_PACKET_MODE_EN | 320 (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT); 321 writel(val, nvec->base + I2C_CNFG); 322 323 clk_set_rate(nvec->i2c_clk, 8 * 80000); 324 325 writel(I2C_SL_NEWL, nvec->base + I2C_SL_CNFG); 326 writel(0x1E, nvec->base + I2C_SL_DELAY_COUNT); 327 328 writel(nvec->i2c_addr>>1, nvec->base + I2C_SL_ADDR1); 329 writel(0, nvec->base + I2C_SL_ADDR2); 330 331 enable_irq(nvec->irq); 332 333 clk_disable(nvec->i2c_clk); 334 } 335 336 static void nvec_disable_i2c_slave(struct nvec_chip *nvec) 337 { 338 disable_irq(nvec->irq); 339 writel(I2C_SL_NEWL | I2C_SL_NACK, nvec->base + I2C_SL_CNFG); 340 clk_disable(nvec->i2c_clk); 341 } 342 343 static void nvec_power_off(void) 344 { 345 nvec_write_async(nvec_power_handle, EC_DISABLE_EVENT_REPORTING, 3); 346 nvec_write_async(nvec_power_handle, "\x04\x01", 2); 347 } 348 349 static int __devinit tegra_nvec_probe(struct platform_device *pdev) 350 { 351 int err, ret; 352 struct clk *i2c_clk; 353 struct nvec_platform_data *pdata = pdev->dev.platform_data; 354 struct nvec_chip *nvec; 355 struct nvec_msg *msg; 356 struct resource *res; 357 struct resource *iomem; 358 void __iomem *base; 359 360 nvec = kzalloc(sizeof(struct nvec_chip), GFP_KERNEL); 361 if (nvec == NULL) { 362 dev_err(&pdev->dev, "failed to reserve memory\n"); 363 return -ENOMEM; 364 } 365 platform_set_drvdata(pdev, nvec); 366 nvec->dev = &pdev->dev; 367 nvec->gpio = pdata->gpio; 368 nvec->i2c_addr = pdata->i2c_addr; 369 370 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 371 if (!res) { 372 dev_err(&pdev->dev, "no mem resource?\n"); 373 return -ENODEV; 374 } 375 376 iomem = request_mem_region(res->start, resource_size(res), pdev->name); 377 if (!iomem) { 378 dev_err(&pdev->dev, "I2C region already claimed\n"); 379 return -EBUSY; 380 } 381 382 base = ioremap(iomem->start, resource_size(iomem)); 383 if (!base) { 384 dev_err(&pdev->dev, "Can't ioremap I2C region\n"); 385 return -ENOMEM; 386 } 387 388 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 389 if (!res) { 390 dev_err(&pdev->dev, "no irq resource?\n"); 391 ret = -ENODEV; 392 goto err_iounmap; 393 } 394 395 i2c_clk = clk_get_sys("tegra-i2c.2", NULL); 396 if (IS_ERR(i2c_clk)) { 397 dev_err(nvec->dev, "failed to get controller clock\n"); 398 goto err_iounmap; 399 } 400 401 nvec->base = base; 402 nvec->irq = res->start; 403 nvec->i2c_clk = i2c_clk; 404 405 /* Set the gpio to low when we've got something to say */ 406 err = gpio_request(nvec->gpio, "nvec gpio"); 407 if (err < 0) 408 dev_err(nvec->dev, "couldn't request gpio\n"); 409 410 ATOMIC_INIT_NOTIFIER_HEAD(&nvec->notifier_list); 411 412 init_completion(&nvec->sync_write); 413 sema_init(&nvec->sync_write_mutex, 1); 414 INIT_LIST_HEAD(&nvec->tx_data); 415 INIT_LIST_HEAD(&nvec->rx_data); 416 INIT_WORK(&nvec->rx_work, nvec_dispatch); 417 INIT_WORK(&nvec->tx_work, nvec_request_master); 418 419 err = request_irq(nvec->irq, nvec_interrupt, 0, "nvec", nvec); 420 if (err) { 421 dev_err(nvec->dev, "couldn't request irq\n"); 422 goto failed; 423 } 424 disable_irq(nvec->irq); 425 426 tegra_init_i2c_slave(nvec); 427 428 clk_enable(i2c_clk); 429 430 gpio_direction_output(nvec->gpio, 1); 431 gpio_set_value(nvec->gpio, 1); 432 433 /* enable event reporting */ 434 nvec_write_async(nvec, EC_ENABLE_EVENT_REPORTING, 435 sizeof(EC_ENABLE_EVENT_REPORTING)); 436 437 nvec->nvec_status_notifier.notifier_call = nvec_status_notifier; 438 nvec_register_notifier(nvec, &nvec->nvec_status_notifier, 0); 439 440 nvec_power_handle = nvec; 441 pm_power_off = nvec_power_off; 442 443 /* Get Firmware Version */ 444 msg = nvec_write_sync(nvec, EC_GET_FIRMWARE_VERSION, 445 sizeof(EC_GET_FIRMWARE_VERSION)); 446 447 dev_warn(nvec->dev, "ec firmware version %02x.%02x.%02x / %02x\n", 448 msg->data[4], msg->data[5], msg->data[6], msg->data[7]); 449 450 kfree(msg->data); 451 kfree(msg); 452 453 ret = mfd_add_devices(nvec->dev, -1, nvec_devices, 454 ARRAY_SIZE(nvec_devices), base, 0); 455 if (ret) 456 dev_err(nvec->dev, "error adding subdevices\n"); 457 458 /* unmute speakers? */ 459 nvec_write_async(nvec, "\x0d\x10\x59\x95", 4); 460 461 /* enable lid switch event */ 462 nvec_write_async(nvec, "\x01\x01\x01\x00\x00\x02\x00", 7); 463 464 /* enable power button event */ 465 nvec_write_async(nvec, "\x01\x01\x01\x00\x00\x80\x00", 7); 466 467 return 0; 468 469 err_iounmap: 470 iounmap(base); 471 failed: 472 kfree(nvec); 473 return -ENOMEM; 474 } 475 476 static int __devexit tegra_nvec_remove(struct platform_device *pdev) 477 { 478 struct nvec_chip *nvec = platform_get_drvdata(pdev); 479 480 nvec_write_async(nvec, EC_DISABLE_EVENT_REPORTING, 3); 481 mfd_remove_devices(nvec->dev); 482 free_irq(nvec->irq, &nvec_interrupt); 483 iounmap(nvec->base); 484 gpio_free(nvec->gpio); 485 kfree(nvec); 486 487 return 0; 488 } 489 490 #ifdef CONFIG_PM 491 492 static int tegra_nvec_suspend(struct platform_device *pdev, pm_message_t state) 493 { 494 struct nvec_chip *nvec = platform_get_drvdata(pdev); 495 496 dev_dbg(nvec->dev, "suspending\n"); 497 nvec_write_async(nvec, EC_DISABLE_EVENT_REPORTING, 3); 498 nvec_write_async(nvec, "\x04\x02", 2); 499 nvec_disable_i2c_slave(nvec); 500 501 return 0; 502 } 503 504 static int tegra_nvec_resume(struct platform_device *pdev) 505 { 506 struct nvec_chip *nvec = platform_get_drvdata(pdev); 507 508 dev_dbg(nvec->dev, "resuming\n"); 509 tegra_init_i2c_slave(nvec); 510 nvec_write_async(nvec, EC_ENABLE_EVENT_REPORTING, 3); 511 512 return 0; 513 } 514 515 #else 516 #define tegra_nvec_suspend NULL 517 #define tegra_nvec_resume NULL 518 #endif 519 520 static struct platform_driver nvec_device_driver = { 521 .probe = tegra_nvec_probe, 522 .remove = __devexit_p(tegra_nvec_remove), 523 .suspend = tegra_nvec_suspend, 524 .resume = tegra_nvec_resume, 525 .driver = { 526 .name = "nvec", 527 .owner = THIS_MODULE, 528 } 529 }; 530 531 static int __init tegra_nvec_init(void) 532 { 533 return platform_driver_register(&nvec_device_driver); 534 } 535 536 module_init(tegra_nvec_init); 537 538 MODULE_ALIAS("platform:nvec"); 539 MODULE_DESCRIPTION("NVIDIA compliant embedded controller interface"); 540 MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>"); 541 MODULE_LICENSE("GPL"); 542