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/platform_device.h>
27 static unsigned char EC_DISABLE_EVENT_REPORTING
[] = {'\x04','\x00','\x00'};
28 static unsigned char EC_ENABLE_EVENT_REPORTING
[] = {'\x04','\x00','\x01'};
29 static unsigned char EC_GET_FIRMWARE_VERSION
[] = {'\x07','\x15'};
31 static struct nvec_chip
*nvec_power_handle
;
33 int nvec_register_notifier(struct nvec_chip
*nvec
, struct notifier_block
*nb
,
36 return atomic_notifier_chain_register(&nvec
->notifier_list
, nb
);
38 EXPORT_SYMBOL_GPL(nvec_register_notifier
);
40 static int nvec_status_notifier(struct notifier_block
*nb
, unsigned long event_type
,
43 unsigned char *msg
= (unsigned char *)data
;
46 if(event_type
!= NVEC_CNTL
)
49 printk("unhandled msg type %ld, payload: ", event_type
);
50 for (i
= 0; i
< msg
[1]; i
++)
51 printk("%0x ", msg
[i
+2]);
57 void nvec_write_async(struct nvec_chip
*nvec
, unsigned char *data
, short size
)
59 struct nvec_msg
*msg
= kzalloc(sizeof(struct nvec_msg
), GFP_NOWAIT
);
61 msg
->data
= kzalloc(size
, GFP_NOWAIT
);
63 memcpy(msg
->data
+ 1, data
, size
);
66 INIT_LIST_HEAD(&msg
->node
);
68 list_add_tail(&msg
->node
, &nvec
->tx_data
);
70 gpio_set_value(nvec
->gpio
, 0);
72 EXPORT_SYMBOL(nvec_write_async
);
74 static void nvec_request_master(struct work_struct
*work
)
76 struct nvec_chip
*nvec
= container_of(work
, struct nvec_chip
, tx_work
);
78 if(!list_empty(&nvec
->tx_data
)) {
79 gpio_set_value(nvec
->gpio
, 0);
83 static int parse_msg(struct nvec_chip
*nvec
, struct nvec_msg
*msg
)
87 if((msg
->data
[0] & 1<<7) == 0 && msg
->data
[3]) {
88 dev_err(nvec
->dev
, "ec responded %02x %02x %02x %02x\n", msg
->data
[0],
89 msg
->data
[1], msg
->data
[2], msg
->data
[3]);
93 if ((msg
->data
[0] >> 7 ) == 1 && (msg
->data
[0] & 0x0f) == 5)
95 dev_warn(nvec
->dev
, "ec system event ");
96 for (i
=0; i
< msg
->data
[1]; i
++)
97 dev_warn(nvec
->dev
, "%02x ", msg
->data
[2+i
]);
98 dev_warn(nvec
->dev
, "\n");
101 atomic_notifier_call_chain(&nvec
->notifier_list
, msg
->data
[0] & 0x8f, msg
->data
);
106 static struct nvec_msg
*nvec_write_sync(struct nvec_chip
*nvec
, unsigned char *data
, short size
)
108 down(&nvec
->sync_write_mutex
);
110 nvec
->sync_write_pending
= (data
[1] << 8) + data
[0];
111 nvec_write_async(nvec
, data
, size
);
113 dev_dbg(nvec
->dev
, "nvec_sync_write: 0x%04x\n", nvec
->sync_write_pending
);
114 wait_for_completion(&nvec
->sync_write
);
115 dev_dbg(nvec
->dev
, "nvec_sync_write: pong!\n");
117 up(&nvec
->sync_write_mutex
);
119 return nvec
->last_sync_msg
;
123 static void nvec_dispatch(struct work_struct
*work
)
125 struct nvec_chip
*nvec
= container_of(work
, struct nvec_chip
, rx_work
);
126 struct nvec_msg
*msg
;
128 while(!list_empty(&nvec
->rx_data
))
130 msg
= list_first_entry(&nvec
->rx_data
, struct nvec_msg
, node
);
131 list_del_init(&msg
->node
);
133 if(nvec
->sync_write_pending
== (msg
->data
[2] << 8) + msg
->data
[0])
135 dev_dbg(nvec
->dev
, "sync write completed!\n");
136 nvec
->sync_write_pending
= 0;
137 nvec
->last_sync_msg
= msg
;
138 complete(&nvec
->sync_write
);
140 parse_msg(nvec
, msg
);
141 if((!msg
) || (!msg
->data
))
142 dev_warn(nvec
->dev
, "attempt access zero pointer");
151 static irqreturn_t
i2c_interrupt(int irq
, void *dev
)
153 unsigned long status
;
154 unsigned long received
;
155 unsigned char to_send
;
156 struct nvec_msg
*msg
;
157 struct nvec_chip
*nvec
= (struct nvec_chip
*)dev
;
158 unsigned char *i2c_regs
= nvec
->i2c_regs
;
160 status
= readl(i2c_regs
+ I2C_SL_STATUS
);
162 if(!(status
& I2C_SL_IRQ
))
164 dev_warn(nvec
->dev
, "nvec Spurious IRQ\n");
165 //Yup, handled. ahum.
168 if(status
& END_TRANS
&& !(status
& RCVD
))
170 //Reenable IRQ only when even has been sent
171 //printk("Write sequence ended !\n");
173 nvec
->state
= NVEC_WAIT
;
174 if(nvec
->rx
->size
> 1)
176 list_add_tail(&nvec
->rx
->node
, &nvec
->rx_data
);
177 schedule_work(&nvec
->rx_work
);
179 kfree(nvec
->rx
->data
);
183 } else if(status
& RNW
)
185 // Work around for AP20 New Slave Hw Bug. Give 1us extra.
186 // nvec/smbus/nvec_i2c_transport.c in NV`s crap for reference
192 nvec
->state
= NVEC_WRITE
;
193 //Master wants something from us. New communication
194 // dev_dbg(nvec->dev, "New read comm!\n");
196 //Master wants something from us from a communication we've already started
197 // dev_dbg(nvec->dev, "Read comm cont !\n");
199 //if(msg_pos<msg_size) {
200 if(list_empty(&nvec
->tx_data
))
202 dev_err(nvec
->dev
, "nvec empty tx - sending no-op\n");
204 nvec_write_async(nvec
, "\x07\x02", 2);
207 msg
= list_first_entry(&nvec
->tx_data
, struct nvec_msg
, node
);
208 if(msg
->pos
< msg
->size
) {
209 to_send
= msg
->data
[msg
->pos
];
212 dev_err(nvec
->dev
, "nvec crap! %d\n", msg
->size
);
216 if(msg
->pos
>= msg
->size
)
218 list_del_init(&msg
->node
);
221 schedule_work(&nvec
->tx_work
);
222 nvec
->state
= NVEC_WAIT
;
225 writel(to_send
, i2c_regs
+ I2C_SL_RCVD
);
227 gpio_set_value(nvec
->gpio
, 1);
229 dev_dbg(nvec
->dev
, "nvec sent %x\n", to_send
);
233 received
= readl(i2c_regs
+ I2C_SL_RCVD
);
236 writel(0, i2c_regs
+ I2C_SL_RCVD
);
240 if (nvec
->state
== NVEC_WAIT
)
242 nvec
->state
= NVEC_READ
;
243 msg
= kzalloc(sizeof(struct nvec_msg
), GFP_NOWAIT
);
244 msg
->data
= kzalloc(32, GFP_NOWAIT
);
245 INIT_LIST_HEAD(&msg
->node
);
250 BUG_ON(msg
->pos
> 32);
252 msg
->data
[msg
->pos
] = received
;
254 msg
->size
= msg
->pos
;
255 dev_dbg(nvec
->dev
, "Got %02lx from Master (pos: %d)!\n", received
, msg
->pos
);
261 static int __devinit
nvec_add_subdev(struct nvec_chip
*nvec
, struct nvec_subdev
*subdev
)
263 struct platform_device
*pdev
;
265 pdev
= platform_device_alloc(subdev
->name
, subdev
->id
);
266 pdev
->dev
.parent
= nvec
->dev
;
267 pdev
->dev
.platform_data
= subdev
->platform_data
;
269 return platform_device_add(pdev
);
272 static void tegra_init_i2c_slave(struct nvec_platform_data
*pdata
, unsigned char *i2c_regs
,
278 tegra_periph_reset_assert(i2c_clk
);
280 tegra_periph_reset_deassert(i2c_clk
);
282 writel(pdata
->i2c_addr
>>1, i2c_regs
+ I2C_SL_ADDR1
);
283 writel(0, i2c_regs
+ I2C_SL_ADDR2
);
285 writel(0x1E, i2c_regs
+ I2C_SL_DELAY_COUNT
);
286 val
= I2C_CNFG_NEW_MASTER_SFM
| I2C_CNFG_PACKET_MODE_EN
|
287 (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT
);
288 writel(val
, i2c_regs
+ I2C_CNFG
);
289 writel(I2C_SL_NEWL
, i2c_regs
+ I2C_SL_CNFG
);
291 clk_disable(i2c_clk
);
294 static void nvec_power_off(void)
296 nvec_write_async(nvec_power_handle
, EC_DISABLE_EVENT_REPORTING
, 3);
297 nvec_write_async(nvec_power_handle
, "\x04\x01", 2);
300 static int __devinit
tegra_nvec_probe(struct platform_device
*pdev
)
304 struct nvec_platform_data
*pdata
= pdev
->dev
.platform_data
;
305 struct nvec_chip
*nvec
;
306 struct nvec_msg
*msg
;
307 unsigned char *i2c_regs
;
309 nvec
= kzalloc(sizeof(struct nvec_chip
), GFP_KERNEL
);
311 dev_err(&pdev
->dev
, "failed to reserve memory\n");
314 platform_set_drvdata(pdev
, nvec
);
315 nvec
->dev
= &pdev
->dev
;
316 nvec
->gpio
= pdata
->gpio
;
317 nvec
->irq
= pdata
->irq
;
320 i2c_clk=clk_get_sys(NULL, "i2c");
321 if(IS_ERR_OR_NULL(i2c_clk))
322 printk(KERN_ERR"No such clock tegra-i2c.2\n");
326 i2c_regs
= ioremap(pdata
->base
, pdata
->size
);
328 dev_err(nvec
->dev
, "failed to ioremap registers\n");
332 nvec
->i2c_regs
= i2c_regs
;
334 i2c_clk
= clk_get_sys(pdata
->clock
, NULL
);
335 if(IS_ERR_OR_NULL(i2c_clk
)) {
336 dev_err(nvec
->dev
, "failed to get clock tegra-i2c.2\n");
340 tegra_init_i2c_slave(pdata
, i2c_regs
, i2c_clk
);
342 err
= request_irq(nvec
->irq
, i2c_interrupt
, IRQF_DISABLED
, "nvec", nvec
);
344 dev_err(nvec
->dev
, "couldn't request irq");
349 clk_set_rate(i2c_clk
, 8*80000);
351 /* Set the gpio to low when we've got something to say */
352 err
= gpio_request(nvec
->gpio
, "nvec gpio");
354 dev_err(nvec
->dev
, "couldn't request gpio\n");
356 tegra_gpio_enable(nvec
->gpio
);
357 gpio_direction_output(nvec
->gpio
, 1);
358 gpio_set_value(nvec
->gpio
, 1);
360 ATOMIC_INIT_NOTIFIER_HEAD(&nvec
->notifier_list
);
362 init_completion(&nvec
->sync_write
);
363 sema_init(&nvec
->sync_write_mutex
, 1);
364 INIT_LIST_HEAD(&nvec
->tx_data
);
365 INIT_LIST_HEAD(&nvec
->rx_data
);
366 INIT_WORK(&nvec
->rx_work
, nvec_dispatch
);
367 INIT_WORK(&nvec
->tx_work
, nvec_request_master
);
369 /* enable event reporting */
370 nvec_write_async(nvec
, EC_ENABLE_EVENT_REPORTING
,
371 sizeof(EC_ENABLE_EVENT_REPORTING
));
374 #ifdef CONFIG_SERIO_NVEC_PS2
379 for (i
= 0; i
< pdata
->num_subdevs
; i
++) {
380 ret
= nvec_add_subdev(nvec
, &pdata
->subdevs
[i
]);
383 nvec
->nvec_status_notifier
.notifier_call
= nvec_status_notifier
;
384 nvec_register_notifier(nvec
, &nvec
->nvec_status_notifier
, 0);
386 nvec_power_handle
= nvec
;
387 pm_power_off
= nvec_power_off
;
389 /* Get Firmware Version */
390 msg
= nvec_write_sync(nvec
, EC_GET_FIRMWARE_VERSION
,
391 sizeof(EC_GET_FIRMWARE_VERSION
));
393 dev_warn(nvec
->dev
, "ec firmware version %02x.%02x.%02x / %02x\n",
394 msg
->data
[4], msg
->data
[5], msg
->data
[6], msg
->data
[7]);
399 /* unmute speakers? */
400 nvec_write_async(nvec
, "\x0d\x10\x59\x94", 4);
402 /* enable lid switch event */
403 nvec_write_async(nvec
, "\x01\x01\x01\x00\x00\x02\x00", 7);
405 /* enable power button event */
406 nvec_write_async(nvec
, "\x01\x01\x01\x00\x00\x80\x00", 7);
415 static int __devexit
tegra_nvec_remove(struct platform_device
*pdev
)
423 static int tegra_nvec_suspend(struct platform_device
*pdev
, pm_message_t state
)
425 struct nvec_chip
*nvec
= platform_get_drvdata(pdev
);
427 dev_dbg(nvec
->dev
, "suspending\n");
428 nvec_write_async(nvec
, EC_DISABLE_EVENT_REPORTING
, 3);
429 nvec_write_async(nvec
, "\x04\x02", 2);
434 static int tegra_nvec_resume(struct platform_device
*pdev
) {
436 struct nvec_chip
*nvec
= platform_get_drvdata(pdev
);
438 dev_dbg(nvec
->dev
, "resuming\n");
439 nvec_write_async(nvec
, EC_ENABLE_EVENT_REPORTING
, 3);
445 #define tegra_nvec_suspend NULL
446 #define tegra_nvec_resume NULL
449 static struct platform_driver nvec_device_driver
=
451 .probe
= tegra_nvec_probe
,
452 .remove
= __devexit_p(tegra_nvec_remove
),
453 .suspend
= tegra_nvec_suspend
,
454 .resume
= tegra_nvec_resume
,
457 .owner
= THIS_MODULE
,
461 static int __init
tegra_nvec_init(void)
463 return platform_driver_register(&nvec_device_driver
);
466 module_init(tegra_nvec_init
);
467 MODULE_ALIAS("platform:nvec");