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