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>
25 #include <linux/mfd/core.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 static struct mfd_cell nvec_devices
[] = {
53 int nvec_register_notifier(struct nvec_chip
*nvec
, struct notifier_block
*nb
,
56 return atomic_notifier_chain_register(&nvec
->notifier_list
, nb
);
58 EXPORT_SYMBOL_GPL(nvec_register_notifier
);
60 static int nvec_status_notifier(struct notifier_block
*nb
, unsigned long event_type
,
63 unsigned char *msg
= (unsigned char *)data
;
66 if(event_type
!= NVEC_CNTL
)
69 printk("unhandled msg type %ld, payload: ", event_type
);
70 for (i
= 0; i
< msg
[1]; i
++)
71 printk("%0x ", msg
[i
+2]);
77 void nvec_write_async(struct nvec_chip
*nvec
, unsigned char *data
, short size
)
79 struct nvec_msg
*msg
= kzalloc(sizeof(struct nvec_msg
), GFP_NOWAIT
);
81 msg
->data
= kzalloc(size
, GFP_NOWAIT
);
83 memcpy(msg
->data
+ 1, data
, size
);
86 INIT_LIST_HEAD(&msg
->node
);
88 list_add_tail(&msg
->node
, &nvec
->tx_data
);
90 gpio_set_value(nvec
->gpio
, 0);
92 EXPORT_SYMBOL(nvec_write_async
);
94 static void nvec_request_master(struct work_struct
*work
)
96 struct nvec_chip
*nvec
= container_of(work
, struct nvec_chip
, tx_work
);
98 if(!list_empty(&nvec
->tx_data
)) {
99 gpio_set_value(nvec
->gpio
, 0);
103 static int parse_msg(struct nvec_chip
*nvec
, struct nvec_msg
*msg
)
107 if((msg
->data
[0] & 1<<7) == 0 && msg
->data
[3]) {
108 dev_err(nvec
->dev
, "ec responded %02x %02x %02x %02x\n", msg
->data
[0],
109 msg
->data
[1], msg
->data
[2], msg
->data
[3]);
113 if ((msg
->data
[0] >> 7 ) == 1 && (msg
->data
[0] & 0x0f) == 5)
115 dev_warn(nvec
->dev
, "ec system event ");
116 for (i
=0; i
< msg
->data
[1]; i
++)
117 dev_warn(nvec
->dev
, "%02x ", msg
->data
[2+i
]);
118 dev_warn(nvec
->dev
, "\n");
121 atomic_notifier_call_chain(&nvec
->notifier_list
, msg
->data
[0] & 0x8f, msg
->data
);
126 static struct nvec_msg
*nvec_write_sync(struct nvec_chip
*nvec
, unsigned char *data
, short size
)
128 down(&nvec
->sync_write_mutex
);
130 nvec
->sync_write_pending
= (data
[1] << 8) + data
[0];
131 nvec_write_async(nvec
, data
, size
);
133 dev_dbg(nvec
->dev
, "nvec_sync_write: 0x%04x\n", nvec
->sync_write_pending
);
134 wait_for_completion(&nvec
->sync_write
);
135 dev_dbg(nvec
->dev
, "nvec_sync_write: pong!\n");
137 up(&nvec
->sync_write_mutex
);
139 return nvec
->last_sync_msg
;
143 static void nvec_dispatch(struct work_struct
*work
)
145 struct nvec_chip
*nvec
= container_of(work
, struct nvec_chip
, rx_work
);
146 struct nvec_msg
*msg
;
148 while(!list_empty(&nvec
->rx_data
))
150 msg
= list_first_entry(&nvec
->rx_data
, struct nvec_msg
, node
);
151 list_del_init(&msg
->node
);
153 if(nvec
->sync_write_pending
== (msg
->data
[2] << 8) + msg
->data
[0])
155 dev_dbg(nvec
->dev
, "sync write completed!\n");
156 nvec
->sync_write_pending
= 0;
157 nvec
->last_sync_msg
= msg
;
158 complete(&nvec
->sync_write
);
160 parse_msg(nvec
, msg
);
161 if((!msg
) || (!msg
->data
))
162 dev_warn(nvec
->dev
, "attempt access zero pointer\n");
171 static irqreturn_t
nvec_interrupt(int irq
, void *dev
)
173 unsigned long status
;
174 unsigned long received
;
175 unsigned char to_send
;
176 struct nvec_msg
*msg
;
177 struct nvec_chip
*nvec
= (struct nvec_chip
*)dev
;
178 void __iomem
*base
= nvec
->base
;
180 status
= readl(base
+ I2C_SL_STATUS
);
182 if(!(status
& I2C_SL_IRQ
))
184 dev_warn(nvec
->dev
, "nvec Spurious IRQ\n");
185 //Yup, handled. ahum.
188 if(status
& END_TRANS
&& !(status
& RCVD
))
190 //Reenable IRQ only when even has been sent
191 //printk("Write sequence ended !\n");
193 nvec
->state
= NVEC_WAIT
;
194 if(nvec
->rx
->size
> 1)
196 list_add_tail(&nvec
->rx
->node
, &nvec
->rx_data
);
197 schedule_work(&nvec
->rx_work
);
199 kfree(nvec
->rx
->data
);
203 } else if(status
& RNW
)
205 // Work around for AP20 New Slave Hw Bug. Give 1us extra.
206 // nvec/smbus/nvec_i2c_transport.c in NV`s crap for reference
212 nvec
->state
= NVEC_WRITE
;
213 //Master wants something from us. New communication
214 // dev_dbg(nvec->dev, "New read comm!\n");
216 //Master wants something from us from a communication we've already started
217 // dev_dbg(nvec->dev, "Read comm cont !\n");
219 //if(msg_pos<msg_size) {
220 if(list_empty(&nvec
->tx_data
))
222 dev_err(nvec
->dev
, "nvec empty tx - sending no-op\n");
224 nvec_write_async(nvec
, "\x07\x02", 2);
227 msg
= list_first_entry(&nvec
->tx_data
, struct nvec_msg
, node
);
228 if(msg
->pos
< msg
->size
) {
229 to_send
= msg
->data
[msg
->pos
];
232 dev_err(nvec
->dev
, "nvec crap! %d\n", msg
->size
);
236 if(msg
->pos
>= msg
->size
)
238 list_del_init(&msg
->node
);
241 schedule_work(&nvec
->tx_work
);
242 nvec
->state
= NVEC_WAIT
;
245 writel(to_send
, base
+ I2C_SL_RCVD
);
247 gpio_set_value(nvec
->gpio
, 1);
249 dev_dbg(nvec
->dev
, "nvec sent %x\n", to_send
);
253 received
= readl(base
+ I2C_SL_RCVD
);
256 writel(0, base
+ I2C_SL_RCVD
);
260 if (nvec
->state
== NVEC_WAIT
)
262 nvec
->state
= NVEC_READ
;
263 msg
= kzalloc(sizeof(struct nvec_msg
), GFP_NOWAIT
);
264 msg
->data
= kzalloc(32, GFP_NOWAIT
);
265 INIT_LIST_HEAD(&msg
->node
);
270 BUG_ON(msg
->pos
> 32);
272 msg
->data
[msg
->pos
] = received
;
274 msg
->size
= msg
->pos
;
275 dev_dbg(nvec
->dev
, "Got %02lx from Master (pos: %d)!\n", received
, msg
->pos
);
281 static void tegra_init_i2c_slave(struct nvec_chip
*nvec
)
285 clk_enable(nvec
->i2c_clk
);
287 tegra_periph_reset_assert(nvec
->i2c_clk
);
289 tegra_periph_reset_deassert(nvec
->i2c_clk
);
291 writel(nvec
->i2c_addr
>>1, nvec
->base
+ I2C_SL_ADDR1
);
292 writel(0, nvec
->base
+ I2C_SL_ADDR2
);
294 writel(0x1E, nvec
->base
+ I2C_SL_DELAY_COUNT
);
295 val
= I2C_CNFG_NEW_MASTER_SFM
| I2C_CNFG_PACKET_MODE_EN
|
296 (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT
);
297 writel(val
, nvec
->base
+ I2C_CNFG
);
298 writel(I2C_SL_NEWL
, nvec
->base
+ I2C_SL_CNFG
);
300 clk_disable(nvec
->i2c_clk
);
303 static void nvec_power_off(void)
305 nvec_write_async(nvec_power_handle
, EC_DISABLE_EVENT_REPORTING
, 3);
306 nvec_write_async(nvec_power_handle
, "\x04\x01", 2);
309 static int __devinit
tegra_nvec_probe(struct platform_device
*pdev
)
313 struct nvec_platform_data
*pdata
= pdev
->dev
.platform_data
;
314 struct nvec_chip
*nvec
;
315 struct nvec_msg
*msg
;
316 struct resource
*res
;
317 struct resource
*iomem
;
320 nvec
= kzalloc(sizeof(struct nvec_chip
), GFP_KERNEL
);
322 dev_err(&pdev
->dev
, "failed to reserve memory\n");
325 platform_set_drvdata(pdev
, nvec
);
326 nvec
->dev
= &pdev
->dev
;
327 nvec
->gpio
= pdata
->gpio
;
328 nvec
->i2c_addr
= pdata
->i2c_addr
;
330 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
332 dev_err(&pdev
->dev
, "no mem resource?\n");
336 iomem
= request_mem_region(res
->start
, resource_size(res
), pdev
->name
);
338 dev_err(&pdev
->dev
, "I2C region already claimed\n");
342 base
= ioremap(iomem
->start
, resource_size(iomem
));
344 dev_err(&pdev
->dev
, "Can't ioremap I2C region\n");
348 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
350 dev_err(&pdev
->dev
, "no irq resource?\n");
355 i2c_clk
= clk_get_sys("tegra-i2c.2", NULL
);
356 if (IS_ERR(i2c_clk
)) {
357 dev_err(nvec
->dev
, "failed to get controller clock\n");
362 clk_set_rate(i2c_clk
, 8*80000);
365 nvec
->irq
= res
->start
;
366 nvec
->i2c_clk
= i2c_clk
;
368 /* Set the gpio to low when we've got something to say */
369 err
= gpio_request(nvec
->gpio
, "nvec gpio");
371 dev_err(nvec
->dev
, "couldn't request gpio\n");
373 ATOMIC_INIT_NOTIFIER_HEAD(&nvec
->notifier_list
);
375 init_completion(&nvec
->sync_write
);
376 sema_init(&nvec
->sync_write_mutex
, 1);
377 INIT_LIST_HEAD(&nvec
->tx_data
);
378 INIT_LIST_HEAD(&nvec
->rx_data
);
379 INIT_WORK(&nvec
->rx_work
, nvec_dispatch
);
380 INIT_WORK(&nvec
->tx_work
, nvec_request_master
);
382 err
= request_irq(nvec
->irq
, nvec_interrupt
, 0, "nvec", nvec
);
384 dev_err(nvec
->dev
, "couldn't request irq\n");
388 tegra_init_i2c_slave(nvec
);
390 gpio_direction_output(nvec
->gpio
, 1);
391 gpio_set_value(nvec
->gpio
, 1);
393 /* enable event reporting */
394 nvec_write_async(nvec
, EC_ENABLE_EVENT_REPORTING
,
395 sizeof(EC_ENABLE_EVENT_REPORTING
));
397 nvec
->nvec_status_notifier
.notifier_call
= nvec_status_notifier
;
398 nvec_register_notifier(nvec
, &nvec
->nvec_status_notifier
, 0);
400 nvec_power_handle
= nvec
;
401 pm_power_off
= nvec_power_off
;
403 /* Get Firmware Version */
404 msg
= nvec_write_sync(nvec
, EC_GET_FIRMWARE_VERSION
,
405 sizeof(EC_GET_FIRMWARE_VERSION
));
407 dev_warn(nvec
->dev
, "ec firmware version %02x.%02x.%02x / %02x\n",
408 msg
->data
[4], msg
->data
[5], msg
->data
[6], msg
->data
[7]);
413 ret
= mfd_add_devices(nvec
->dev
, -1, nvec_devices
,
414 ARRAY_SIZE(nvec_devices
), base
, 0);
416 dev_err(nvec
->dev
, "error adding subdevices\n");
418 /* unmute speakers? */
419 nvec_write_async(nvec
, "\x0d\x10\x59\x94", 4);
421 /* enable lid switch event */
422 nvec_write_async(nvec
, "\x01\x01\x01\x00\x00\x02\x00", 7);
424 /* enable power button event */
425 nvec_write_async(nvec
, "\x01\x01\x01\x00\x00\x80\x00", 7);
436 static int __devexit
tegra_nvec_remove(struct platform_device
*pdev
)
438 struct nvec_chip
*nvec
= platform_get_drvdata(pdev
);
440 nvec_write_async(nvec
, EC_DISABLE_EVENT_REPORTING
, 3);
441 mfd_remove_devices(nvec
->dev
);
442 free_irq(nvec
->irq
, &nvec_interrupt
);
444 gpio_free(nvec
->gpio
);
452 static int tegra_nvec_suspend(struct platform_device
*pdev
, pm_message_t state
)
454 struct nvec_chip
*nvec
= platform_get_drvdata(pdev
);
456 dev_dbg(nvec
->dev
, "suspending\n");
457 nvec_write_async(nvec
, EC_DISABLE_EVENT_REPORTING
, 3);
458 nvec_write_async(nvec
, "\x04\x02", 2);
463 static int tegra_nvec_resume(struct platform_device
*pdev
) {
465 struct nvec_chip
*nvec
= platform_get_drvdata(pdev
);
467 dev_dbg(nvec
->dev
, "resuming\n");
468 tegra_init_i2c_slave(nvec
);
469 nvec_write_async(nvec
, EC_ENABLE_EVENT_REPORTING
, 3);
475 #define tegra_nvec_suspend NULL
476 #define tegra_nvec_resume NULL
479 static struct platform_driver nvec_device_driver
=
481 .probe
= tegra_nvec_probe
,
482 .remove
= __devexit_p(tegra_nvec_remove
),
483 .suspend
= tegra_nvec_suspend
,
484 .resume
= tegra_nvec_resume
,
487 .owner
= THIS_MODULE
,
491 static int __init
tegra_nvec_init(void)
493 return platform_driver_register(&nvec_device_driver
);
496 module_init(tegra_nvec_init
);
497 MODULE_ALIAS("platform:nvec");