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