3 /* ToDo list (incomplete, unorderd)
4 - convert mouse, keyboard, and power to platform devices
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>
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>
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'};
32 static struct nvec_chip
*nvec_power_handle
;
34 int nvec_register_notifier(struct nvec_chip
*nvec
, struct notifier_block
*nb
,
37 return atomic_notifier_chain_register(&nvec
->notifier_list
, nb
);
39 EXPORT_SYMBOL_GPL(nvec_register_notifier
);
41 static int nvec_status_notifier(struct notifier_block
*nb
, unsigned long event_type
,
44 unsigned char *msg
= (unsigned char *)data
;
47 if(event_type
!= NVEC_CNTL
)
50 printk("unhandled msg type %ld, payload: ", event_type
);
51 for (i
= 0; i
< msg
[1]; i
++)
52 printk("%0x ", msg
[i
+2]);
58 void nvec_write_async(struct nvec_chip
*nvec
, unsigned char *data
, short size
)
60 struct nvec_msg
*msg
= kzalloc(sizeof(struct nvec_msg
), GFP_NOWAIT
);
62 msg
->data
= kzalloc(size
, GFP_NOWAIT
);
64 memcpy(msg
->data
+ 1, data
, size
);
67 INIT_LIST_HEAD(&msg
->node
);
69 list_add_tail(&msg
->node
, &nvec
->tx_data
);
71 gpio_set_value(nvec
->gpio
, 0);
73 EXPORT_SYMBOL(nvec_write_async
);
75 static void nvec_request_master(struct work_struct
*work
)
77 struct nvec_chip
*nvec
= container_of(work
, struct nvec_chip
, tx_work
);
79 if(!list_empty(&nvec
->tx_data
)) {
80 gpio_set_value(nvec
->gpio
, 0);
84 static int parse_msg(struct nvec_chip
*nvec
, struct nvec_msg
*msg
)
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]);
94 if ((msg
->data
[0] >> 7 ) == 1 && (msg
->data
[0] & 0x0f) == 5)
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");
102 atomic_notifier_call_chain(&nvec
->notifier_list
, msg
->data
[0] & 0x8f, msg
->data
);
107 static struct nvec_msg
*nvec_write_sync(struct nvec_chip
*nvec
, unsigned char *data
, short size
)
109 down(&nvec
->sync_write_mutex
);
111 nvec
->sync_write_pending
= (data
[1] << 8) + data
[0];
112 nvec_write_async(nvec
, data
, size
);
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");
118 up(&nvec
->sync_write_mutex
);
120 return nvec
->last_sync_msg
;
124 static void nvec_dispatch(struct work_struct
*work
)
126 struct nvec_chip
*nvec
= container_of(work
, struct nvec_chip
, rx_work
);
127 struct nvec_msg
*msg
;
129 while(!list_empty(&nvec
->rx_data
))
131 msg
= list_first_entry(&nvec
->rx_data
, struct nvec_msg
, node
);
132 list_del_init(&msg
->node
);
134 if(nvec
->sync_write_pending
== (msg
->data
[2] << 8) + msg
->data
[0])
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
);
141 parse_msg(nvec
, msg
);
142 if((!msg
) || (!msg
->data
))
143 dev_warn(nvec
->dev
, "attempt access zero pointer");
152 static irqreturn_t
i2c_interrupt(int irq
, void *dev
)
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
;
161 status
= readl(i2c_regs
+ I2C_SL_STATUS
);
163 if(!(status
& I2C_SL_IRQ
))
165 dev_warn(nvec
->dev
, "nvec Spurious IRQ\n");
166 //Yup, handled. ahum.
169 if(status
& END_TRANS
&& !(status
& RCVD
))
171 //Reenable IRQ only when even has been sent
172 //printk("Write sequence ended !\n");
174 nvec
->state
= NVEC_WAIT
;
175 if(nvec
->rx
->size
> 1)
177 list_add_tail(&nvec
->rx
->node
, &nvec
->rx_data
);
178 schedule_work(&nvec
->rx_work
);
180 kfree(nvec
->rx
->data
);
184 } else if(status
& RNW
)
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
193 nvec
->state
= NVEC_WRITE
;
194 //Master wants something from us. New communication
195 // dev_dbg(nvec->dev, "New read comm!\n");
197 //Master wants something from us from a communication we've already started
198 // dev_dbg(nvec->dev, "Read comm cont !\n");
200 //if(msg_pos<msg_size) {
201 if(list_empty(&nvec
->tx_data
))
203 dev_err(nvec
->dev
, "nvec empty tx - sending no-op\n");
205 nvec_write_async(nvec
, "\x07\x02", 2);
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
];
213 dev_err(nvec
->dev
, "nvec crap! %d\n", msg
->size
);
217 if(msg
->pos
>= msg
->size
)
219 list_del_init(&msg
->node
);
222 schedule_work(&nvec
->tx_work
);
223 nvec
->state
= NVEC_WAIT
;
226 writel(to_send
, i2c_regs
+ I2C_SL_RCVD
);
228 gpio_set_value(nvec
->gpio
, 1);
230 dev_dbg(nvec
->dev
, "nvec sent %x\n", to_send
);
234 received
= readl(i2c_regs
+ I2C_SL_RCVD
);
237 writel(0, i2c_regs
+ I2C_SL_RCVD
);
241 if (nvec
->state
== NVEC_WAIT
)
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
);
251 BUG_ON(msg
->pos
> 32);
253 msg
->data
[msg
->pos
] = received
;
255 msg
->size
= msg
->pos
;
256 dev_dbg(nvec
->dev
, "Got %02lx from Master (pos: %d)!\n", received
, msg
->pos
);
262 static int __devinit
nvec_add_subdev(struct nvec_chip
*nvec
, struct nvec_subdev
*subdev
)
264 struct platform_device
*pdev
;
266 pdev
= platform_device_alloc(subdev
->name
, subdev
->id
);
267 pdev
->dev
.parent
= nvec
->dev
;
268 pdev
->dev
.platform_data
= subdev
->platform_data
;
270 return platform_device_add(pdev
);
273 static void tegra_init_i2c_slave(struct nvec_platform_data
*pdata
, unsigned char *i2c_regs
,
279 tegra_periph_reset_assert(i2c_clk
);
281 tegra_periph_reset_deassert(i2c_clk
);
283 writel(pdata
->i2c_addr
>>1, i2c_regs
+ I2C_SL_ADDR1
);
284 writel(0, i2c_regs
+ I2C_SL_ADDR2
);
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
);
292 clk_disable(i2c_clk
);
295 static void nvec_power_off(void)
297 nvec_write_async(nvec_power_handle
, EC_DISABLE_EVENT_REPORTING
, 3);
298 nvec_write_async(nvec_power_handle
, "\x04\x01", 2);
301 static int __devinit
tegra_nvec_probe(struct platform_device
*pdev
)
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
;
310 nvec
= kzalloc(sizeof(struct nvec_chip
), GFP_KERNEL
);
312 dev_err(&pdev
->dev
, "failed to reserve memory\n");
315 platform_set_drvdata(pdev
, nvec
);
316 nvec
->dev
= &pdev
->dev
;
317 nvec
->gpio
= pdata
->gpio
;
318 nvec
->irq
= pdata
->irq
;
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");
327 i2c_regs
= ioremap(pdata
->base
, pdata
->size
);
329 dev_err(nvec
->dev
, "failed to ioremap registers\n");
333 nvec
->i2c_regs
= i2c_regs
;
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");
341 tegra_init_i2c_slave(pdata
, i2c_regs
, i2c_clk
);
343 err
= request_irq(nvec
->irq
, i2c_interrupt
, IRQF_DISABLED
, "nvec", nvec
);
345 dev_err(nvec
->dev
, "couldn't request irq");
350 clk_set_rate(i2c_clk
, 8*80000);
352 /* Set the gpio to low when we've got something to say */
353 err
= gpio_request(nvec
->gpio
, "nvec gpio");
355 dev_err(nvec
->dev
, "couldn't request gpio\n");
357 tegra_gpio_enable(nvec
->gpio
);
358 gpio_direction_output(nvec
->gpio
, 1);
359 gpio_set_value(nvec
->gpio
, 1);
361 ATOMIC_INIT_NOTIFIER_HEAD(&nvec
->notifier_list
);
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
);
370 /* enable event reporting */
371 nvec_write_async(nvec
, EC_ENABLE_EVENT_REPORTING
,
372 sizeof(EC_ENABLE_EVENT_REPORTING
));
375 #ifdef CONFIG_SERIO_NVEC_PS2
380 for (i
= 0; i
< pdata
->num_subdevs
; i
++) {
381 ret
= nvec_add_subdev(nvec
, &pdata
->subdevs
[i
]);
384 nvec
->nvec_status_notifier
.notifier_call
= nvec_status_notifier
;
385 nvec_register_notifier(nvec
, &nvec
->nvec_status_notifier
, 0);
387 nvec_power_handle
= nvec
;
388 pm_power_off
= nvec_power_off
;
390 /* Get Firmware Version */
391 msg
= nvec_write_sync(nvec
, EC_GET_FIRMWARE_VERSION
,
392 sizeof(EC_GET_FIRMWARE_VERSION
));
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]);
400 /* unmute speakers? */
401 nvec_write_async(nvec
, "\x0d\x10\x59\x94", 4);
403 /* enable lid switch event */
404 nvec_write_async(nvec
, "\x01\x01\x01\x00\x00\x02\x00", 7);
406 /* enable power button event */
407 nvec_write_async(nvec
, "\x01\x01\x01\x00\x00\x80\x00", 7);
416 static int __devexit
tegra_nvec_remove(struct platform_device
*pdev
)
424 static int tegra_nvec_suspend(struct platform_device
*pdev
, pm_message_t state
)
426 struct nvec_chip
*nvec
= platform_get_drvdata(pdev
);
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);
435 static int tegra_nvec_resume(struct platform_device
*pdev
) {
437 struct nvec_chip
*nvec
= platform_get_drvdata(pdev
);
439 dev_dbg(nvec
->dev
, "resuming\n");
440 nvec_write_async(nvec
, EC_ENABLE_EVENT_REPORTING
, 3);
446 #define tegra_nvec_suspend NULL
447 #define tegra_nvec_resume NULL
450 static struct platform_driver nvec_device_driver
=
452 .probe
= tegra_nvec_probe
,
453 .remove
= __devexit_p(tegra_nvec_remove
),
454 .suspend
= tegra_nvec_suspend
,
455 .resume
= tegra_nvec_resume
,
458 .owner
= THIS_MODULE
,
462 static int __init
tegra_nvec_init(void)
464 return platform_driver_register(&nvec_device_driver
);
467 module_init(tegra_nvec_init
);
468 MODULE_ALIAS("platform:nvec");