xref: /openbmc/linux/drivers/staging/nvec/nvec.c (revision 97cc2657)
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