summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorNinad Malwade <nmalwade@nvidia.com>2010-02-26 13:54:32 +0530
committerNinad Malwade <nmalwade@nvidia.com>2010-02-26 14:19:05 +0530
commit92891e2ab3df0eafc3f064c410d8ac47187ccb07 (patch)
treeaf90e4b0c5db5d2d6a461987f7b301a42871b935 /drivers
parent18af2d21101948f32922b18cb9057c9708b288b9 (diff)
tegra NVEC: Bus driver architecture for nvec drivers
- nvec_user is the bus driver - tegra-nvec [keyboard], nvec_mouse [touchpad], nvec_battery are the client drivers for nvec. - verified: suspend-resume ordering: This is synchronous now. - Issues: after few suspend-resume EC is failed to suspend. [working on this issue] - Bug 648447 - Adding device_unregister for nvec bus driver. Change-Id: I3c30ceb50a89f67d71050089766897bd7691848d
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/keyboard/tegra-nvec.c76
-rw-r--r--drivers/input/mouse/nvec_mouse.c986
-rw-r--r--drivers/power/nvec_battery.c61
3 files changed, 546 insertions, 577 deletions
diff --git a/drivers/input/keyboard/tegra-nvec.c b/drivers/input/keyboard/tegra-nvec.c
index 266a3a29cacf..5f0cdbb6793f 100644
--- a/drivers/input/keyboard/tegra-nvec.c
+++ b/drivers/input/keyboard/tegra-nvec.c
@@ -23,7 +23,7 @@
#include <linux/module.h>
#include <linux/input.h>
-#include <linux/platform_device.h>
+#include <linux/device.h>
#include <linux/kthread.h>
#include <linux/tegra_devices.h>
#include <linux/freezer.h>
@@ -32,6 +32,7 @@
#include "nvec.h"
#include "nvodm_services.h"
#include "nvodm_keyboard.h"
+#include "nvec_device.h"
#define DRIVER_DESC "NvEc keyboard driver"
#define DRIVER_LICENSE "GPL"
@@ -262,8 +263,6 @@ struct nvec_keyboard
NvEcEventRegistrationHandle hEvent;
};
-static struct platform_device *nvec_keyboard_device;
-
static int nvec_keyboard_recv(void *arg)
{
struct input_dev *input_dev = (struct input_dev *)arg;
@@ -317,7 +316,7 @@ static void nvec_keyboard_close(struct input_dev *dev)
return;
}
-static int __devinit nvec_keyboard_probe(struct platform_device *pdev)
+static int __devinit nvec_keyboard_probe(struct nvec_device *pdev)
{
int error;
NvError nverr;
@@ -334,7 +333,7 @@ static int __devinit nvec_keyboard_probe(struct platform_device *pdev)
keyboard->input_dev = input_dev;
input_set_drvdata(input_dev, keyboard);
- platform_set_drvdata(pdev, input_dev);
+ nvec_set_drvdata(pdev, input_dev);
if (!NvOdmKeyboardInit()) {
error = -ENODEV;
@@ -393,9 +392,9 @@ fail:
return error;
}
-static int __devexit nvec_keyboard_remove(struct platform_device *dev)
+static int nvec_keyboard_remove(struct nvec_device *dev)
{
- struct input_dev *input_dev = platform_get_drvdata(dev);
+ struct input_dev *input_dev = nvec_get_drvdata(dev);
struct nvec_keyboard *keyboard = input_get_drvdata(input_dev);
(void)kthread_stop(keyboard->task);
@@ -409,12 +408,11 @@ static int __devexit nvec_keyboard_remove(struct platform_device *dev)
return 0;
}
-#ifdef ENABLE_NVEC_KBD_SUSPEND
-static int nvec_keyboard_suspend(struct platform_device *pdev, pm_message_t state)
+static int nvec_keyboard_suspend(struct nvec_device *pdev, pm_message_t state)
{
NvEcRequest Request = {0};
NvEcResponse Response = {0};
- struct input_dev *input_dev = platform_get_drvdata(pdev);
+ struct input_dev *input_dev = nvec_get_drvdata(pdev);
struct nvec_keyboard *keyboard = input_get_drvdata(input_dev);
NvError err = NvError_Success;
@@ -455,11 +453,11 @@ static int nvec_keyboard_suspend(struct platform_device *pdev, pm_message_t stat
return 0;
}
-static int nvec_keyboard_resume(struct platform_device *pdev)
+static int nvec_keyboard_resume(struct nvec_device *pdev)
{
NvEcRequest Request = {0};
NvEcResponse Response = {0};
- struct input_dev *input_dev = platform_get_drvdata(pdev);
+ struct input_dev *input_dev = nvec_get_drvdata(pdev);
struct nvec_keyboard *keyboard = input_get_drvdata(input_dev);
NvError err = NvError_Success;
@@ -499,54 +497,46 @@ static int nvec_keyboard_resume(struct platform_device *pdev)
return 0;
}
-#endif /* ENABLE_NVEC_KBD_SUSPEND */
-
-static struct platform_driver nvec_keyboard_driver = {
- .driver = {
- .name = "nvec_keyboard",
- .owner = THIS_MODULE,
- },
- .probe = nvec_keyboard_probe,
- .remove = __devexit_p(nvec_keyboard_remove),
-#ifdef ENABLE_NVEC_KBD_SUSPEND
+
+static struct nvec_driver nvec_keyboard_driver = {
+ .name = "nvec_keyboard",
+ .probe = nvec_keyboard_probe,
+ .remove = nvec_keyboard_remove,
.suspend = nvec_keyboard_suspend,
.resume = nvec_keyboard_resume,
-#endif
+};
+
+static struct nvec_device nvec_keyboard_device = {
+ .name = "nvec_keyboard",
+ .driver = &nvec_keyboard_driver,
};
static int __init nvec_keyboard_init(void)
{
int err;
- err = platform_driver_register(&nvec_keyboard_driver);
- if (err) {
- goto error;
- }
-
- nvec_keyboard_device = platform_device_alloc("nvec_keyboard", -1);
- if (!nvec_keyboard_device) {
- err = -ENOMEM;
- goto error_unregister_driver;
+ err = nvec_register_driver(&nvec_keyboard_driver);
+ if (err)
+ {
+ pr_err("**nvec_keyboard_init: nvec_register_driver: fail\n");
+ return err;
}
- err = platform_device_add(nvec_keyboard_device);
+ err = nvec_register_device(&nvec_keyboard_device);
if (err)
- goto error_free_device;
+ {
+ pr_err("**nvec_keyboard_init: nvec_device_add: fail\n");
+ nvec_unregister_driver(&nvec_keyboard_driver);
+ return err;
+ }
return 0;
-
-error_free_device:
- platform_device_put(nvec_keyboard_device);
-error_unregister_driver:
- platform_driver_unregister(&nvec_keyboard_driver);
-error:
- return err;
}
static void __exit nvec_keyboard_exit(void)
{
- platform_device_unregister(nvec_keyboard_device);
- platform_driver_unregister(&nvec_keyboard_driver);
+ nvec_unregister_device(&nvec_keyboard_device);
+ nvec_unregister_driver(&nvec_keyboard_driver);
}
module_init(nvec_keyboard_init);
diff --git a/drivers/input/mouse/nvec_mouse.c b/drivers/input/mouse/nvec_mouse.c
index daebda669d9c..06014b92dd17 100644
--- a/drivers/input/mouse/nvec_mouse.c
+++ b/drivers/input/mouse/nvec_mouse.c
@@ -1,514 +1,472 @@
-/*
- * drivers/input/mouse/nvec_mouse.c
- *
- * Mouse class input driver for mice and touchpads connected to an NvEc
- * compliant embedded controller
- *
- * Copyright (c) 2009, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/input.h>
-#include <linux/platform_device.h>
-#include <linux/kthread.h>
-#include <linux/tegra_devices.h>
-#include <linux/earlysuspend.h>
-#include <linux/freezer.h>
-
-#include "nvos.h"
-#include "nvec.h"
-#include "nvodm_services.h"
-#include "nvodm_mouse.h"
-
-#define DRIVER_DESC "NvEc mouse driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-
-enum nvec_mouse_type {
- nvec_mouse_type_none,
- nvec_mouse_type_standard,
- nvec_mouse_type_intellimouse,
- nvec_mouse_type_intelli5buttonmouse,
-};
-
-#define NVEC_PAYLOAD 32
-
-struct nvec_mouse
-{
- struct input_dev *input_dev;
- struct task_struct *task;
- NvOdmOsSemaphoreHandle semaphore;
- char name[128];
- NvOdmMouseDeviceHandle hDevice;
- enum nvec_mouse_type type;
- unsigned char data[NVEC_PAYLOAD];
- int valid_data_size;
- int enableWake;
- int packetSize;
- unsigned char previousState;
- int shutdown;
- struct early_suspend early_suspend;
-};
-
-static struct platform_device *nvec_mouse_device;
-
-// Commands sent to the mouse.
-//
-static const NvU8 cmdReadId = 0xF2;
-static const NvU8 cmdSetSampleRate = 0xF3;
-static const NvU8 cmdEnable = 0xF4;
-static const NvU8 cmdReset = 0xFF;
-static const NvU8 cmdSetResolution = 0xE8;
-static const NvU8 cmdSetScaling1_1 = 0xE6;
-static const NvU8 cmdSetResolution2_1 = 0xE7;
-static const NvU8 cmdSetStreamMode = 0xEA;
-
-//
-// Mouse Responses
-//
-static const NvU8 responseAck = 0xFA;
-static const NvU8 responseResend = 0xFE;
-static const NvU8 responseStandardMouseId = 0x00;
-static const NvU8 responseIntelliMouseId = 0x03;
-static const NvU8 responseIntelli5buttonMouseId = 0x04;
-static const NvU8 responseBatSuccess = 0xAA;
-static const NvU8 responseBatError = 0xFC;
-
-
-int nvec_mouse_cmd(struct nvec_mouse *mouse, unsigned int cmd,
- int resp_size)
-{
- volatile int cnt = 3;
-
- while (cnt--) {
- if (!NvOdmMouseSendRequest(mouse->hDevice, cmd, resp_size,
- &mouse->valid_data_size, mouse->data)) {
- pr_err("**nvec_mouse_cmd: SendRequest: fail\n");
- return -1;
- } if (mouse->valid_data_size != resp_size) {
- pr_err("**nvec_mouse_cmd: not valid data size\n");
- continue;
- }
- if (mouse->valid_data_size == 0 ||
- mouse->data[0] == responseAck) {
- return 0;
- }
- }
- pr_err("**nvec_mouse_cmd error\n");
-
- return -1;
-}
-
-int nvec_IsStandardMouse(struct nvec_mouse *mouse)
-{
- if (!nvec_mouse_cmd(mouse, cmdReset, 3) &&
- (mouse->data[1] == responseBatSuccess) &&
- (mouse->data[2] == responseStandardMouseId)) {
- return 0;
- }
- return -ENODEV;
-}
-
-static int nvec_setSampleRate(struct nvec_mouse *mouse,
- unsigned int SamplesPerSecond)
-{
- if (!nvec_mouse_cmd(mouse, cmdSetSampleRate, 1) &&
- !nvec_mouse_cmd(mouse, SamplesPerSecond, 1)) {
- return 0;
- }
- return -EINVAL;
-}
-
-int nvec_IsIntellimouse(struct nvec_mouse *mouse)
-{
- if (((!nvec_setSampleRate(mouse, 0xC8)) &&
- (!nvec_setSampleRate(mouse, 0x64)) &&
- (!nvec_setSampleRate(mouse, 0x50)))
- && ((!nvec_mouse_cmd(mouse, cmdReadId, 1)) &&
- (mouse->data[1] == responseIntelliMouseId))) {
-
- printk("mouse->data[1]=0x%x\n", mouse->data[1]);
- return 0;
- }
- return -ENODEV;
-}
-
-int nvec_IsIntelli5buttonmouse(struct nvec_mouse *mouse)
-{
- if (((!nvec_setSampleRate(mouse, 0xC8)) &&
- (!nvec_setSampleRate(mouse, 0xC8)) &&
- (!nvec_setSampleRate(mouse, 0x50)))
- && ((!nvec_mouse_cmd(mouse, cmdReadId, 1)) &&
- mouse->data[1] == responseIntelli5buttonMouseId)) {
- printk("mouse->data[1]=0x%x\n", mouse->data[1]);
- return 0;
- }
- return -ENODEV;
-}
-
-static int nvec_mouse_receive_thread(void *arg)
-{
- struct input_dev *input_dev = (struct input_dev *)arg;
- struct nvec_mouse *mouse = input_get_drvdata(input_dev);
- NvU8 buttonState;
- NvU8 updatedState;
- NvS8 dataBuffer[4] = {0};
- NvU32 x,y;
-
- /* mouse event thread should be frozen before suspending the
- * mouse and NVEC drivers */
- set_freezable_with_signal();
-
- if (!NvOdmMouseEnableInterrupt(mouse->hDevice, mouse->semaphore)) {
- pr_err("**nvec_mouse_receive_thread: EnableInterrupt: fail\n");
- return -1;
- }
-
- while (!mouse->shutdown) {
- unsigned char data[4];
- int size;
-
- NvOdmOsSemaphoreWait(mouse->semaphore);
- if (mouse->shutdown)
- break;
-
- if (!NvOdmMouseGetEventInfo(mouse->hDevice, &size, data))
- continue;
-
- /* Short packets are not valid? */
- if (size < 3) continue;
-
- NvOsMemcpy(&dataBuffer, data, 4);
-
- updatedState = dataBuffer[0] ^ mouse->previousState;
- if (updatedState) {
- buttonState = dataBuffer[0];
-
- if (updatedState & 0x01)
- input_report_key(input_dev, BTN_LEFT,
- buttonState & 0x01);
- if (updatedState & 0x02)
- input_report_key(input_dev, BTN_RIGHT,
- (buttonState>>1) & 0x01);
- if (updatedState & 0x04)
- input_report_key(input_dev, BTN_MIDDLE,
- (buttonState>>2) & 0x01);
-
- mouse->previousState = dataBuffer[0];
- } else {
- x = dataBuffer[1];
- y = -dataBuffer[2];
-
- input_report_rel(input_dev, REL_X, x);
- input_report_rel(input_dev, REL_Y, y);
-
- input_sync(input_dev);
- }
-
- if (mouse->packetSize == 4 && dataBuffer[3])
- input_report_rel(input_dev, REL_WHEEL, dataBuffer[3]);
-
- input_sync(input_dev);
- }
- return 0;
-}
-
-static int nvec_mouse_open(struct input_dev *dev)
-{
- struct nvec_mouse *mouse = input_get_drvdata(dev);
-
- /* Set the resolution */
- /*
- * Factor Resolution
- * ------ ----------
- * 0x00 1 count/mm
- * 0x01 2 count/mm
- * 0x02 4 count/mm
- * 0x03 8 count/mm
- */
- if (nvec_mouse_cmd(mouse, cmdSetResolution, 1) ||
- nvec_mouse_cmd(mouse, 2, 1)) {
- pr_err("**nvec_mouse_open: cmd fail\n");
- return -EINVAL;
- }
-
- /* Set scaling */
- if (nvec_mouse_cmd(mouse, cmdSetScaling1_1, 1)) {
- pr_err("**nvec_mouse_open: cmdsetscaling fail\n");
- return -EINVAL;
- }
-
- if (nvec_setSampleRate(mouse, 0x64)) {
- pr_err("**nvec_mouse_open: setsamplerate fail\n");
- return -EINVAL;
- }
-
- if (nvec_mouse_cmd(mouse, cmdEnable, 1)) {
- pr_err("**nvec_mouse_open: mouse cmd fail\n");
- return -EINVAL;
- }
-
- if (!NvOdmMouseStartStreaming(mouse->hDevice, mouse->packetSize)) {
- pr_err("**nvec_mouse_open: streaming fail\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void nvec_mouse_close(struct input_dev *dev)
-{
- return;
-}
-
-static int mouse_resume(struct nvec_mouse *m)
-{
- if (!m || !m->hDevice || !NvOdmMousePowerResume(m->hDevice))
- return -1;
-
- return 0;
-}
-
-static int mouse_suspend(struct nvec_mouse *m)
-{
- if (!m || !m->hDevice || !NvOdmMousePowerSuspend(m->hDevice))
- return -1;
-
- return 0;
-}
-
-#ifndef CONFIG_HAS_EARLYSUSPEND
-
-static int nvec_mouse_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct input_dev *input_dev = platform_get_drvdata(pdev);
- struct nvec_mouse *mouse = input_get_drvdata(input_dev);
-
- return mouse_suspend(mouse);
-}
-
-static int nvec_mouse_resume(struct platform_device *pdev)
-{
- struct input_dev *input_dev = platform_get_drvdata(pdev);
- struct nvec_mouse *mouse = input_get_drvdata(input_dev);
-
- return mouse_resume(mouse);
-}
-
-#else
-
-static void nvec_mouse_early_suspend(struct early_suspend *es)
-{
- struct nvec_mouse *mouse;
- mouse = container_of(es, struct nvec_mouse, early_suspend);
-
- mouse_suspend(mouse);
-}
-
-static void nvec_mouse_late_resume(struct early_suspend *es)
-{
- struct nvec_mouse *mouse;
- mouse = container_of(es, struct nvec_mouse, early_suspend);
-
- mouse_resume(mouse);
-}
-#endif
-
-static int __devinit nvec_mouse_probe(struct platform_device *pdev)
-{
- int error;
- struct nvec_mouse *mouse;
- struct input_dev *input_dev;
-
- mouse = kzalloc(sizeof(struct nvec_mouse), GFP_KERNEL);
- input_dev = input_allocate_device();
- if (!mouse || !input_dev) {
- pr_err("**nvec_mouse_probe: input_allocate_device: fail\n");
- error = -ENOMEM;
- goto fail;
- }
-
- if (!NvOdmMouseDeviceOpen(&mouse->hDevice)) {
- pr_err("NvOdmMouseDeviceOpen failed\n");
- error = -ENODEV;
- goto fail;
- }
-
- mouse->input_dev = input_dev;
- input_set_drvdata(input_dev, mouse);
-
- mouse->type = nvec_mouse_type_none;
- mouse->enableWake = 0;
-
- /* Probe for the type of the mouse */
- if (!nvec_IsStandardMouse(mouse)) {
- if (!nvec_IsIntellimouse(mouse)) {
- mouse->packetSize = 4;
- if (!nvec_IsIntelli5buttonmouse(mouse))
- mouse->type = nvec_mouse_type_intelli5buttonmouse;
- else
- mouse->type = nvec_mouse_type_intellimouse;
- } else {
- mouse->packetSize = 3;
- mouse->type = nvec_mouse_type_standard;
- }
- } else {
- error = -ENODEV;
- goto fail_no_mouse_found;
- }
-
- platform_set_drvdata(pdev, input_dev);
-
- mouse->semaphore = NvOdmOsSemaphoreCreate(0);
- if (mouse->semaphore == NULL) {
- error = -1;
- pr_err("nvec_mouse: Semaphore creation failed\n");
- goto fail_semaphore_create;
- }
-
- mouse->task = kthread_create(nvec_mouse_receive_thread,
- input_dev, "nvec_mouse");
-
- if (!mouse->task) {
- pr_err("**nvec_mouse_probe: kthread_create: fail\n");
- error = -ENOMEM;
- goto fail_thread_create;
- }
- wake_up_process(mouse->task);
-
- if (!strlen(mouse->name))
- snprintf(mouse->name, sizeof(mouse->name), "nvec mouse");
-
- input_dev->name = mouse->name;
- input_dev->open = nvec_mouse_open;
- input_dev->close = nvec_mouse_close;
-
- input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
-
- input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
- BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
- input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
- input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);
-
- error = input_register_device(mouse->input_dev);
- if (error) {
- pr_err("**nvec_mouse_probe: input_register_device: fail\n");
- goto fail_input_register;
- }
-
- mouse->previousState = 0;
-#ifdef CONFIG_HAS_EARLYSUSPEND
- mouse->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
- mouse->early_suspend.suspend = nvec_mouse_early_suspend;
- mouse->early_suspend.resume = nvec_mouse_late_resume;
- register_early_suspend(&mouse->early_suspend);
-#endif
-
- printk(KERN_INFO DRIVER_DESC ": registered NVEC mouse driver\n");
- return 0;
-
-fail_input_register:
- (void)kthread_stop(mouse->task);
-fail_thread_create:
- NvOdmOsSemaphoreDestroy(mouse->semaphore);
- mouse->semaphore = NULL;
-fail_semaphore_create:
-fail_no_mouse_found:
- NvOdmMouseDeviceClose(mouse->hDevice);
- mouse->hDevice = NULL;
-fail:
- input_free_device(input_dev);
- kfree(mouse);
- mouse = NULL;
-
- return error;
-}
-
-static int __devexit nvec_mouse_remove(struct platform_device *dev)
-{
- struct input_dev *input_dev = platform_get_drvdata(dev);
- struct nvec_mouse *mouse = platform_get_drvdata(dev);
-
- unregister_early_suspend(&mouse->early_suspend);
- mouse->shutdown = 1;
- NvOdmOsSemaphoreSignal(mouse->semaphore);
- (void)kthread_stop(mouse->task);
- NvOdmOsSemaphoreDestroy(mouse->semaphore);
- NvOdmMouseDeviceClose(mouse->hDevice);
- input_free_device(input_dev);
- kfree(mouse);
- mouse = NULL;
- return 0;
-}
-
-static struct platform_driver nvec_mouse_driver = {
- .driver = {
- .name = "nvec_mouse",
- .owner = THIS_MODULE,
- },
- .probe = nvec_mouse_probe,
- .remove = __devexit_p(nvec_mouse_remove),
-#ifndef CONFIG_HAS_EARLYSUSPEND
- .suspend = nvec_mouse_suspend,
- .resume = nvec_mouse_resume,
-#endif
-};
-
-static int __init nvec_mouse_init(void)
-{
- int err;
-
- err = platform_driver_register(&nvec_mouse_driver);
- if (err) {
- pr_err("**nvec_mouse_init: platform_driver_register: fail\n");
- goto error;
- }
-
- nvec_mouse_device = platform_device_alloc("nvec_mouse", -1);
- if (!nvec_mouse_device) {
- pr_err("**nvec_mouse_init: platform_device_alloc: fail\n");
- err = -ENOMEM;
- goto error_unregister_driver;
- }
-
- err = platform_device_add(nvec_mouse_device);
- if (err)
- {
- pr_err("**nvec_mouse_init: platform_device_add: fail\n");
- goto error_free_device;
- }
- return 0;
-
-error_free_device:
- platform_device_put(nvec_mouse_device);
-error_unregister_driver:
- platform_driver_unregister(&nvec_mouse_driver);
-error:
- return err;
-}
-
-static void __exit nvec_mouse_exit(void)
-{
- platform_device_unregister(nvec_mouse_device);
- platform_driver_unregister(&nvec_mouse_driver);
-}
-
-module_init(nvec_mouse_init);
-module_exit(nvec_mouse_exit);
-
+/*
+ * drivers/input/mouse/nvec_mouse.c
+ *
+ * Mouse class input driver for mice and touchpads connected to an NvEc
+ * compliant embedded controller
+ *
+ * Copyright (c) 2009, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/device.h>
+#include <linux/kthread.h>
+#include <linux/tegra_devices.h>
+#include <linux/earlysuspend.h>
+#include <linux/freezer.h>
+
+#include "nvos.h"
+#include "nvec.h"
+#include "nvodm_services.h"
+#include "nvodm_mouse.h"
+#include "nvec_device.h"
+
+#define DRIVER_DESC "NvEc mouse driver"
+#define DRIVER_LICENSE "GPL"
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+enum nvec_mouse_type {
+ nvec_mouse_type_none,
+ nvec_mouse_type_standard,
+ nvec_mouse_type_intellimouse,
+ nvec_mouse_type_intelli5buttonmouse,
+};
+
+#define NVEC_PAYLOAD 32
+
+struct nvec_mouse
+{
+ struct input_dev *input_dev;
+ struct task_struct *task;
+ NvOdmOsSemaphoreHandle semaphore;
+ char name[128];
+ NvOdmMouseDeviceHandle hDevice;
+ enum nvec_mouse_type type;
+ unsigned char data[NVEC_PAYLOAD];
+ int valid_data_size;
+ int enableWake;
+ int packetSize;
+ unsigned char previousState;
+ int shutdown;
+};
+
+// Commands sent to the mouse.
+//
+static const NvU8 cmdReadId = 0xF2;
+static const NvU8 cmdSetSampleRate = 0xF3;
+static const NvU8 cmdEnable = 0xF4;
+static const NvU8 cmdReset = 0xFF;
+static const NvU8 cmdSetResolution = 0xE8;
+static const NvU8 cmdSetScaling1_1 = 0xE6;
+static const NvU8 cmdSetResolution2_1 = 0xE7;
+static const NvU8 cmdSetStreamMode = 0xEA;
+
+//
+// Mouse Responses
+//
+static const NvU8 responseAck = 0xFA;
+static const NvU8 responseResend = 0xFE;
+static const NvU8 responseStandardMouseId = 0x00;
+static const NvU8 responseIntelliMouseId = 0x03;
+static const NvU8 responseIntelli5buttonMouseId = 0x04;
+static const NvU8 responseBatSuccess = 0xAA;
+static const NvU8 responseBatError = 0xFC;
+
+
+int nvec_mouse_cmd(struct nvec_mouse *mouse, unsigned int cmd,
+ int resp_size)
+{
+ volatile int cnt = 3;
+
+ while (cnt--) {
+ if (!NvOdmMouseSendRequest(mouse->hDevice, cmd, resp_size,
+ &mouse->valid_data_size, mouse->data)) {
+ pr_err("**nvec_mouse_cmd: SendRequest: fail\n");
+ return -1;
+ } if (mouse->valid_data_size != resp_size) {
+ pr_err("**nvec_mouse_cmd: not valid data size\n");
+ continue;
+ }
+ if (mouse->valid_data_size == 0 ||
+ mouse->data[0] == responseAck) {
+ return 0;
+ }
+ }
+ pr_err("**nvec_mouse_cmd error\n");
+
+ return -1;
+}
+
+int nvec_IsStandardMouse(struct nvec_mouse *mouse)
+{
+ if (!nvec_mouse_cmd(mouse, cmdReset, 3) &&
+ (mouse->data[1] == responseBatSuccess) &&
+ (mouse->data[2] == responseStandardMouseId)) {
+ return 0;
+ }
+ return -ENODEV;
+}
+
+static int nvec_setSampleRate(struct nvec_mouse *mouse,
+ unsigned int SamplesPerSecond)
+{
+ if (!nvec_mouse_cmd(mouse, cmdSetSampleRate, 1) &&
+ !nvec_mouse_cmd(mouse, SamplesPerSecond, 1)) {
+ return 0;
+ }
+ return -EINVAL;
+}
+
+int nvec_IsIntellimouse(struct nvec_mouse *mouse)
+{
+ if (((!nvec_setSampleRate(mouse, 0xC8)) &&
+ (!nvec_setSampleRate(mouse, 0x64)) &&
+ (!nvec_setSampleRate(mouse, 0x50)))
+ && ((!nvec_mouse_cmd(mouse, cmdReadId, 1)) &&
+ (mouse->data[1] == responseIntelliMouseId))) {
+
+ printk("mouse->data[1]=0x%x\n", mouse->data[1]);
+ return 0;
+ }
+ return -ENODEV;
+}
+
+int nvec_IsIntelli5buttonmouse(struct nvec_mouse *mouse)
+{
+ if (((!nvec_setSampleRate(mouse, 0xC8)) &&
+ (!nvec_setSampleRate(mouse, 0xC8)) &&
+ (!nvec_setSampleRate(mouse, 0x50)))
+ && ((!nvec_mouse_cmd(mouse, cmdReadId, 1)) &&
+ mouse->data[1] == responseIntelli5buttonMouseId)) {
+ printk("mouse->data[1]=0x%x\n", mouse->data[1]);
+ return 0;
+ }
+ return -ENODEV;
+}
+
+static int nvec_mouse_receive_thread(void *arg)
+{
+ struct input_dev *input_dev = (struct input_dev *)arg;
+ struct nvec_mouse *mouse = input_get_drvdata(input_dev);
+ NvU8 buttonState;
+ NvU8 updatedState;
+ NvS8 dataBuffer[4] = {0};
+ NvU32 x,y;
+
+ /* mouse event thread should be frozen before suspending the
+ * mouse and NVEC drivers */
+ set_freezable_with_signal();
+
+ if (!NvOdmMouseEnableInterrupt(mouse->hDevice, mouse->semaphore)) {
+ pr_err("**nvec_mouse_receive_thread: EnableInterrupt: fail\n");
+ return -1;
+ }
+
+ while (!mouse->shutdown) {
+ unsigned char data[4];
+ int size;
+
+ NvOdmOsSemaphoreWait(mouse->semaphore);
+ if (mouse->shutdown)
+ break;
+
+ if (!NvOdmMouseGetEventInfo(mouse->hDevice, &size, data))
+ continue;
+
+ /* Short packets are not valid? */
+ if (size < 3) continue;
+
+ NvOsMemcpy(&dataBuffer, data, 4);
+
+ updatedState = dataBuffer[0] ^ mouse->previousState;
+ if (updatedState) {
+ buttonState = dataBuffer[0];
+
+ if (updatedState & 0x01)
+ input_report_key(input_dev, BTN_LEFT,
+ buttonState & 0x01);
+ if (updatedState & 0x02)
+ input_report_key(input_dev, BTN_RIGHT,
+ (buttonState>>1) & 0x01);
+ if (updatedState & 0x04)
+ input_report_key(input_dev, BTN_MIDDLE,
+ (buttonState>>2) & 0x01);
+
+ mouse->previousState = dataBuffer[0];
+ } else {
+ x = dataBuffer[1];
+ y = -dataBuffer[2];
+
+ input_report_rel(input_dev, REL_X, x);
+ input_report_rel(input_dev, REL_Y, y);
+
+ input_sync(input_dev);
+ }
+
+ if (mouse->packetSize == 4 && dataBuffer[3])
+ input_report_rel(input_dev, REL_WHEEL, dataBuffer[3]);
+
+ input_sync(input_dev);
+ }
+ return 0;
+}
+
+static int nvec_mouse_open(struct input_dev *dev)
+{
+ struct nvec_mouse *mouse = input_get_drvdata(dev);
+
+ /* Set the resolution */
+ /*
+ * Factor Resolution
+ * ------ ----------
+ * 0x00 1 count/mm
+ * 0x01 2 count/mm
+ * 0x02 4 count/mm
+ * 0x03 8 count/mm
+ */
+ if (nvec_mouse_cmd(mouse, cmdSetResolution, 1) ||
+ nvec_mouse_cmd(mouse, 2, 1)) {
+ pr_err("**nvec_mouse_open: cmd fail\n");
+ return -EINVAL;
+ }
+
+ /* Set scaling */
+ if (nvec_mouse_cmd(mouse, cmdSetScaling1_1, 1)) {
+ pr_err("**nvec_mouse_open: cmdsetscaling fail\n");
+ return -EINVAL;
+ }
+
+ if (nvec_setSampleRate(mouse, 0x64)) {
+ pr_err("**nvec_mouse_open: setsamplerate fail\n");
+ return -EINVAL;
+ }
+
+ if (nvec_mouse_cmd(mouse, cmdEnable, 1)) {
+ pr_err("**nvec_mouse_open: mouse cmd fail\n");
+ return -EINVAL;
+ }
+
+ if (!NvOdmMouseStartStreaming(mouse->hDevice, mouse->packetSize)) {
+ pr_err("**nvec_mouse_open: streaming fail\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void nvec_mouse_close(struct input_dev *dev)
+{
+ return;
+}
+
+static int mouse_resume(struct nvec_mouse *m)
+{
+ if (!m || !m->hDevice || !NvOdmMousePowerResume(m->hDevice))
+ return -1;
+
+ return 0;
+}
+
+static int mouse_suspend(struct nvec_mouse *m)
+{
+ if (!m || !m->hDevice || !NvOdmMousePowerSuspend(m->hDevice))
+ return -1;
+
+ return 0;
+}
+
+static int nvec_mouse_suspend(struct nvec_device *pdev, pm_message_t state)
+{
+ struct input_dev *input_dev = nvec_get_drvdata(pdev);
+ struct nvec_mouse *mouse = input_get_drvdata(input_dev);
+
+ return mouse_suspend(mouse);
+}
+
+static int nvec_mouse_resume(struct nvec_device *pdev)
+{
+ struct input_dev *input_dev = nvec_get_drvdata(pdev);
+ struct nvec_mouse *mouse = input_get_drvdata(input_dev);
+
+ return mouse_resume(mouse);
+}
+
+static int __devinit nvec_mouse_probe(struct nvec_device *pdev)
+{
+ int error;
+ struct nvec_mouse *mouse;
+ struct input_dev *input_dev;
+
+ mouse = kzalloc(sizeof(struct nvec_mouse), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!mouse || !input_dev) {
+ pr_err("**nvec_mouse_probe: input_allocate_device: fail\n");
+ error = -ENOMEM;
+ goto fail;
+ }
+
+ if (!NvOdmMouseDeviceOpen(&mouse->hDevice)) {
+ pr_err("NvOdmMouseDeviceOpen failed\n");
+ error = -ENODEV;
+ goto fail;
+ }
+
+ mouse->input_dev = input_dev;
+ input_set_drvdata(input_dev, mouse);
+
+ mouse->type = nvec_mouse_type_none;
+ mouse->enableWake = 0;
+
+ /* Probe for the type of the mouse */
+ if (!nvec_IsStandardMouse(mouse)) {
+ if (!nvec_IsIntellimouse(mouse)) {
+ mouse->packetSize = 4;
+ if (!nvec_IsIntelli5buttonmouse(mouse))
+ mouse->type = nvec_mouse_type_intelli5buttonmouse;
+ else
+ mouse->type = nvec_mouse_type_intellimouse;
+ } else {
+ mouse->packetSize = 3;
+ mouse->type = nvec_mouse_type_standard;
+ }
+ } else {
+ error = -ENODEV;
+ goto fail_no_mouse_found;
+ }
+
+ nvec_set_drvdata(pdev, input_dev);
+
+ mouse->semaphore = NvOdmOsSemaphoreCreate(0);
+ if (mouse->semaphore == NULL) {
+ error = -1;
+ pr_err("nvec_mouse: Semaphore creation failed\n");
+ goto fail_semaphore_create;
+ }
+
+ mouse->task = kthread_create(nvec_mouse_receive_thread,
+ input_dev, "nvec_mouse");
+
+ if (!mouse->task) {
+ pr_err("**nvec_mouse_probe: kthread_create: fail\n");
+ error = -ENOMEM;
+ goto fail_thread_create;
+ }
+ wake_up_process(mouse->task);
+
+ if (!strlen(mouse->name))
+ snprintf(mouse->name, sizeof(mouse->name), "nvec mouse");
+
+ input_dev->name = mouse->name;
+ input_dev->open = nvec_mouse_open;
+ input_dev->close = nvec_mouse_close;
+
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+
+ input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
+ input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+ input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);
+
+ error = input_register_device(mouse->input_dev);
+ if (error) {
+ pr_err("**nvec_mouse_probe: input_register_device: fail\n");
+ goto fail_input_register;
+ }
+
+ mouse->previousState = 0;
+
+ printk(KERN_INFO DRIVER_DESC ": registered NVEC mouse driver\n");
+ return 0;
+
+fail_input_register:
+ (void)kthread_stop(mouse->task);
+fail_thread_create:
+ NvOdmOsSemaphoreDestroy(mouse->semaphore);
+ mouse->semaphore = NULL;
+fail_semaphore_create:
+fail_no_mouse_found:
+ NvOdmMouseDeviceClose(mouse->hDevice);
+ mouse->hDevice = NULL;
+fail:
+ input_free_device(input_dev);
+ kfree(mouse);
+ mouse = NULL;
+
+ return error;
+}
+
+static void nvec_mouse_remove(struct nvec_device *dev)
+{
+ struct input_dev *input_dev = nvec_get_drvdata(dev);
+ struct nvec_mouse *mouse = input_get_drvdata(input_dev);
+
+ mouse->shutdown = 1;
+ NvOdmOsSemaphoreSignal(mouse->semaphore);
+ (void)kthread_stop(mouse->task);
+ NvOdmOsSemaphoreDestroy(mouse->semaphore);
+ NvOdmMouseDeviceClose(mouse->hDevice);
+ input_free_device(input_dev);
+ kfree(mouse);
+ mouse = NULL;
+}
+
+static struct nvec_driver nvec_mouse = {
+ .name = "nvec_mouse",
+ .probe = nvec_mouse_probe,
+ .remove = nvec_mouse_remove,
+ .suspend = nvec_mouse_suspend,
+ .resume = nvec_mouse_resume,
+};
+
+static struct nvec_device nvec_mouse_device = {
+ .name = "nvec_mouse",
+ .driver = &nvec_mouse,
+};
+
+static int __init nvec_mouse_init(void)
+{
+ int err;
+
+ err = nvec_register_driver(&nvec_mouse);
+ if (err)
+ {
+ pr_err("**nvec_mouse_init: nvec_register_driver: fail\n");
+ return err;
+ }
+
+ err = nvec_register_device(&nvec_mouse_device);
+ if (err)
+ {
+ pr_err("**nvec_mouse_init: nvec_device_add: fail\n");
+ nvec_unregister_driver(&nvec_mouse);
+ return err;
+ }
+
+ return 0;
+}
+
+static void __exit nvec_mouse_exit(void)
+{
+ nvec_unregister_device(&nvec_mouse_device);
+ nvec_unregister_driver(&nvec_mouse);
+}
+
+module_init(nvec_mouse_init);
+module_exit(nvec_mouse_exit);
+
diff --git a/drivers/power/nvec_battery.c b/drivers/power/nvec_battery.c
index d0b2a06410d4..5db17a6a10be 100644
--- a/drivers/power/nvec_battery.c
+++ b/drivers/power/nvec_battery.c
@@ -25,7 +25,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/device.h>
#include <linux/debugfs.h>
#include <linux/power_supply.h>
#include <linux/wakelock.h>
@@ -34,6 +34,8 @@
#include "nvcommon.h"
#include "nvos.h"
#include "nvodm_battery.h"
+#include "nvec_device.h"
+
/* This defines the manufacturer name and model name length */
#define BATTERY_INFO_NAME_LEN 30
@@ -416,7 +418,7 @@ static void tegra_battery_poll_timer_func(unsigned long unused)
jiffies + msecs_to_jiffies(NVBATTERY_POLLING_INTERVAL));
}
-static int tegra_battery_probe(struct platform_device *pdev)
+static int nvec_battery_probe(struct nvec_device *pdev)
{
int i;
NvBool result = NV_FALSE;
@@ -445,7 +447,7 @@ static int tegra_battery_probe(struct platform_device *pdev)
return 0;
}
-static int tegra_battery_remove(struct platform_device *pdev)
+static int nvec_battery_remove(struct nvec_device *pdev)
{
unsigned int i = 0;
@@ -469,7 +471,7 @@ static int tegra_battery_remove(struct platform_device *pdev)
return 0;
}
-static int tegra_battery_suspend(struct platform_device *dev,
+static int nvec_battery_suspend(struct nvec_device *dev,
pm_message_t state)
{
/* Kill the Battery Polling timer */
@@ -477,7 +479,7 @@ static int tegra_battery_suspend(struct platform_device *dev,
return 0;
}
-static int tegra_battery_resume(struct platform_device *dev)
+static int nvec_battery_resume(struct nvec_device *dev)
{
/*Create Battery Polling timer */
setup_timer(&battery_poll_timer, tegra_battery_poll_timer_func, 0);
@@ -486,29 +488,48 @@ static int tegra_battery_resume(struct platform_device *dev)
return 0;
}
-static struct platform_driver tegra_battery_driver = {
- .probe = tegra_battery_probe,
- .remove = tegra_battery_remove,
- .suspend= tegra_battery_suspend,
- .resume = tegra_battery_resume,
- .driver = {
- .name = "tegra_battery",
- .owner = THIS_MODULE,
- },
+static struct nvec_driver nvec_battery_driver = {
+ .name = "nvec_battery",
+ .probe = nvec_battery_probe,
+ .remove = nvec_battery_remove,
+ .suspend = nvec_battery_suspend,
+ .resume = nvec_battery_resume,
+};
+
+static struct nvec_device nvec_battery_device = {
+ .name = "nvec_battery",
+ .driver = &nvec_battery_driver,
};
-static int __init tegra_battery_init(void)
+static int __init nvec_battery_init(void)
{
- platform_driver_register(&tegra_battery_driver);
+ int err;
+
+ err = nvec_register_driver(&nvec_battery_driver);
+ if (err)
+ {
+ pr_err("**nvec_battery_init: nvec_register_driver: fail\n");
+ return err;
+ }
+
+ err = nvec_register_device(&nvec_battery_device);
+ if (err)
+ {
+ pr_err("**nvec_battery_init: nvec_device_add: fail\n");
+ nvec_unregister_driver(&nvec_battery_driver);
+ return err;
+ }
+
return 0;
}
-static void __exit tegra_battery_exit(void)
+static void __exit nvec_battery_exit(void)
{
- platform_driver_unregister(&tegra_battery_driver);
+ nvec_unregister_device(&nvec_battery_device);
+ nvec_unregister_driver(&nvec_battery_driver);
}
-module_init(tegra_battery_init);
-module_exit(tegra_battery_exit);
+module_init(nvec_battery_init);
+module_exit(nvec_battery_exit);
MODULE_DESCRIPTION("TEGRA EC based Battery Driver");