diff options
author | Ninad Malwade <nmalwade@nvidia.com> | 2010-02-26 13:54:32 +0530 |
---|---|---|
committer | Ninad Malwade <nmalwade@nvidia.com> | 2010-02-26 14:19:05 +0530 |
commit | 92891e2ab3df0eafc3f064c410d8ac47187ccb07 (patch) | |
tree | af90e4b0c5db5d2d6a461987f7b301a42871b935 | |
parent | 18af2d21101948f32922b18cb9057c9708b288b9 (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
-rw-r--r-- | arch/arm/mach-tegra/include/nvec_device.h | 81 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvec_user.c | 648 | ||||
-rw-r--r-- | drivers/input/keyboard/tegra-nvec.c | 76 | ||||
-rw-r--r-- | drivers/input/mouse/nvec_mouse.c | 986 | ||||
-rw-r--r-- | drivers/power/nvec_battery.c | 61 |
5 files changed, 1004 insertions, 848 deletions
diff --git a/arch/arm/mach-tegra/include/nvec_device.h b/arch/arm/mach-tegra/include/nvec_device.h new file mode 100644 index 000000000000..71c1f761906b --- /dev/null +++ b/arch/arm/mach-tegra/include/nvec_device.h @@ -0,0 +1,81 @@ +/*
+ * Copyright (c) 2010 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef INCLUDED_NVEC_DEVICE_H
+#define INCLUDED_NVEC_DEVICE_H
+
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+#define nvec_get_drvdata(f) dev_get_drvdata(&(f)->dev)
+#define nvec_set_drvdata(f,d) dev_set_drvdata(&(f)->dev, d)
+
+struct nvec_driver;
+
+struct nvec_device {
+ char *name;
+ struct device *parent;
+ struct device dev;
+ struct bus_type *bus; /* type of bus device is on */
+ struct nvec_driver *driver; /* which driver has allocated this
+ device */
+};
+
+extern int nvec_register_device(struct nvec_device *pdev);
+extern void nvec_unregister_device(struct nvec_device *pdev);
+
+/*
+ * NVEC function device driver
+ */
+struct nvec_driver {
+ char *name;
+ struct device_driver driver;
+ struct device dev;
+
+ int (*probe)(struct nvec_device *);
+ void (*remove)(struct nvec_device *);
+
+ int (*suspend)(struct nvec_device *dev, pm_message_t state);
+ int (*resume)(struct nvec_device *dev);
+};
+
+extern int nvec_register_driver(struct nvec_driver *);
+extern void nvec_unregister_driver(struct nvec_driver *);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // INCLUDED_NVEC_DEVICE_H
diff --git a/arch/arm/mach-tegra/nvec_user.c b/arch/arm/mach-tegra/nvec_user.c index b11c00e0c0c4..8ee0240b219a 100644 --- a/arch/arm/mach-tegra/nvec_user.c +++ b/arch/arm/mach-tegra/nvec_user.c @@ -1,271 +1,377 @@ -/* - * arch/arm/mach-tegra/nvec_user.c - * - * User-land access to NvEc embedded controller features - * - * Copyright (c) 2008-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/proc_fs.h> -#include <linux/platform_device.h> -#include <linux/miscdevice.h> -#include "linux/nvos_ioctl.h" -#include "nvec.h" -#include "linux/nvec_ioctls.h" -#include "nvreftrack.h" -#include "nvassert.h" - -static NvRtHandle s_RtHandle = NULL; - -NvError NvECPackage_Dispatch(void *InBuffer, NvU32 InSize, void *OutBuffer, - NvU32 OutSize, NvDispatchCtx* Ctx); - -static int nvec_open(struct inode *inode, struct file *file); -static int nvec_close(struct inode *inode, struct file *file); -static long nvec_unlocked_ioctl(struct file *file, - unsigned int cmd, unsigned long arg); - -int nvec_open(struct inode *inode, struct file *file) -{ - NvRtClientHandle Client; - - if (NvRtRegisterClient(s_RtHandle, &Client) != NvSuccess) - return -ENOMEM; - - file->private_data = (void*)Client; - return 0; -} - -int nvec_close(struct inode *inode, struct file *file) -{ - NvRtClientHandle client = (NvRtClientHandle)file->private_data; - - if (NvRtUnregisterClient(s_RtHandle, client)) { - NvDispatchCtx dctx; - - dctx.Rt = s_RtHandle; - dctx.Client = client; - dctx.PackageIdx = 0; - - // TODO: Enable this code for freeing up leaked handles - #if 0 - for (;;) - { - void* ptr = NvRtFreeObjRef(&dctx, - NvRtObjType_NvEc_NvEcHandle, NULL); - if (!ptr) break; - NVRT_LEAK("NvEc", "NvEcHandle", ptr); - NvEcClose(ptr); - } - #endif - - NvRtUnregisterClient(s_RtHandle, client); - } - return 0; -} - -long nvec_unlocked_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - NvError err; - NvOsIoctlParams p; - NvU32 size; - NvU32 small_buf[8]; - void *ptr = 0; - long e; - NvBool bAlloc = NV_FALSE; - - switch( cmd ) { - case NvECKernelIoctls_Generic: - { - NvDispatchCtx dctx; - - dctx.Rt = s_RtHandle; - dctx.Client = (NvRtClientHandle)file->private_data; - dctx.PackageIdx = 0; - - err = NvOsCopyIn(&p, (void *)arg, sizeof(p)); - if (err != NvSuccess) { - printk("NvECKernelIoctls_Generic: copy in failed\n"); - goto fail; - } - - size = p.InBufferSize + p.InOutBufferSize + p.OutBufferSize; - if (size <= sizeof(small_buf)) { - ptr = small_buf; - } else { - ptr = NvOsAlloc(size); - if (!ptr) { - printk("NvECKernelIoctls_Generic: alloc err\n"); - goto fail; - } - - bAlloc = NV_TRUE; - } - - err = NvOsCopyIn(ptr, p.pBuffer, p.InBufferSize + - p.InOutBufferSize); - if (err != NvSuccess) { - printk("NvECKernelIoctls_Generic: copy in failure\n"); - goto fail; - } - - err = NvECPackage_Dispatch(ptr, - p.InBufferSize + p.InOutBufferSize, - ((NvU8 *)ptr) + p.InBufferSize, p.InOutBufferSize + - p.OutBufferSize, &dctx); - if (err != NvSuccess) { - printk("NvECKernelIoctls_Generic: dispatch failure\n"); - goto fail; - } - - if (p.InOutBufferSize || p.OutBufferSize) { - err = NvOsCopyOut( - ((NvU8 *)((NvOsIoctlParams *)arg)->pBuffer) + - p.InBufferSize, - ((NvU8 *)ptr) + p.InBufferSize, - p.InOutBufferSize + p.OutBufferSize); - if (err != NvSuccess) { - printk("NvECKernelIoctls_Generic: copyout err\n"); - goto fail; - } - } - - break; - } - default: - printk("unknown ioctl code\n"); - goto fail; - } - e = 0; - goto clean; - -fail: - e = -EINVAL; - -clean: - if (bAlloc) - NvOsFree(ptr); - - return e; -} - -#define DEVICE_NAME "nvec" - -static const struct file_operations nvec_fops = -{ - .owner = THIS_MODULE, - .open = nvec_open, - .release = nvec_close, - .unlocked_ioctl = nvec_unlocked_ioctl, -}; - -static struct miscdevice nvec_dev = -{ - .name = DEVICE_NAME, - .fops = &nvec_fops, - .minor = MISC_DYNAMIC_MINOR, -}; - -static NvEcHandle s_NvEcHandle = NULL; - -static int __init nvec_probe(struct platform_device *pdev) -{ - int e = 0; - NvError status; - NvU32 NumTypes = 1; // TODO: must have NvRtObjType_NvEc_Num instead; - - NV_ASSERT(s_RtHandle == NULL); - - if (NvRtCreate(1, &NumTypes, &s_RtHandle) != NvSuccess) { - printk("nvec NvRtCreate returned error\n"); - return -ENOMEM; - } - - status = NvEcOpen(&s_NvEcHandle, 0); - if (status != NvError_Success) { - printk("nvec NvEcOpen returned 0x%x\n", status); - return -EINVAL; - } - - e = misc_register(&nvec_dev); - if (e < 0) { - if (s_RtHandle) { - NvRtDestroy(s_RtHandle); - s_RtHandle = NULL; - } - printk("nvec failed to open\n"); - } - return e; -} - -static int nvec_remove(struct platform_device *pdev) -{ - NvEcClose(s_NvEcHandle); - misc_deregister( &nvec_dev ); - NvRtDestroy(s_RtHandle); - s_RtHandle = NULL; - return 0; -} - -static int nvec_suspend(struct platform_device *pdev, pm_message_t state) -{ - NvError e = NvEcPowerSuspend(NvEcPowerState_Suspend); - if (e != NvSuccess) - return -1; - - return 0; -} - -static int nvec_resume(struct platform_device *pdev) -{ - NvError e = NvEcPowerResume(); - if (e != NvSuccess) - return -1; - - return 0; -} - -static void nvec_shutdown(struct platform_device *pdev) -{ - NvEcPowerSuspend(NvEcPowerState_PowerDown); -} - -static struct platform_driver tegra_nvec_driver = { - .probe = nvec_probe, - .remove = nvec_remove, - .suspend = nvec_suspend, - .resume = nvec_resume, - .shutdown = nvec_shutdown, - .driver = { - .name = "nvec", - }, -}; - -static int __devinit nvec_init( void ) -{ - return platform_driver_register(&tegra_nvec_driver); -} - -static void __exit nvec_deinit( void ) -{ - return platform_driver_unregister(&tegra_nvec_driver); -} - -module_init(nvec_init); -module_exit(nvec_deinit); +/*
+ * arch/arm/mach-tegra/nvec_user.c
+ *
+ * User-land access to NvEc embedded controller features
+ *
+ * Copyright (c) 2008-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/proc_fs.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+#include "linux/nvos_ioctl.h"
+#include "nvec.h"
+#include "linux/nvec_ioctls.h"
+#include "nvreftrack.h"
+#include "nvassert.h"
+#include "nvec_device.h"
+
+static NvRtHandle s_RtHandle = NULL;
+int device_count = 0;
+
+#define dev_to_nvec_driver(d) container_of(d, struct nvec_driver, driver)
+#define to_nvec_device(x) container_of((x), struct nvec_device, dev)
+
+NvError NvECPackage_Dispatch(void *InBuffer, NvU32 InSize, void *OutBuffer,
+ NvU32 OutSize, NvDispatchCtx* Ctx);
+
+static int nvec_open(struct inode *inode, struct file *file);
+static int nvec_close(struct inode *inode, struct file *file);
+static long nvec_unlocked_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg);
+
+int nvec_open(struct inode *inode, struct file *file)
+{
+ NvRtClientHandle Client;
+
+ if (NvRtRegisterClient(s_RtHandle, &Client) != NvSuccess)
+ return -ENOMEM;
+
+ file->private_data = (void*)Client;
+ return 0;
+}
+
+int nvec_close(struct inode *inode, struct file *file)
+{
+ NvRtClientHandle client = (NvRtClientHandle)file->private_data;
+
+ if (NvRtUnregisterClient(s_RtHandle, client)) {
+ NvDispatchCtx dctx;
+
+ dctx.Rt = s_RtHandle;
+ dctx.Client = client;
+ dctx.PackageIdx = 0;
+
+ // TODO: Enable this code for freeing up leaked handles
+ #if 0
+ for (;;)
+ {
+ void* ptr = NvRtFreeObjRef(&dctx,
+ NvRtObjType_NvEc_NvEcHandle, NULL);
+ if (!ptr) break;
+ NVRT_LEAK("NvEc", "NvEcHandle", ptr);
+ NvEcClose(ptr);
+ }
+ #endif
+
+ NvRtUnregisterClient(s_RtHandle, client);
+ }
+ return 0;
+}
+
+long nvec_unlocked_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ NvError err;
+ NvOsIoctlParams p;
+ NvU32 size;
+ NvU32 small_buf[8];
+ void *ptr = 0;
+ long e;
+ NvBool bAlloc = NV_FALSE;
+
+ switch( cmd ) {
+ case NvECKernelIoctls_Generic:
+ {
+ NvDispatchCtx dctx;
+
+ dctx.Rt = s_RtHandle;
+ dctx.Client = (NvRtClientHandle)file->private_data;
+ dctx.PackageIdx = 0;
+
+ err = NvOsCopyIn(&p, (void *)arg, sizeof(p));
+ if (err != NvSuccess) {
+ printk("NvECKernelIoctls_Generic: copy in failed\n");
+ goto fail;
+ }
+
+ size = p.InBufferSize + p.InOutBufferSize + p.OutBufferSize;
+ if (size <= sizeof(small_buf)) {
+ ptr = small_buf;
+ } else {
+ ptr = NvOsAlloc(size);
+ if (!ptr) {
+ printk("NvECKernelIoctls_Generic: alloc err\n");
+ goto fail;
+ }
+
+ bAlloc = NV_TRUE;
+ }
+
+ err = NvOsCopyIn(ptr, p.pBuffer, p.InBufferSize +
+ p.InOutBufferSize);
+ if (err != NvSuccess) {
+ printk("NvECKernelIoctls_Generic: copy in failure\n");
+ goto fail;
+ }
+
+ err = NvECPackage_Dispatch(ptr,
+ p.InBufferSize + p.InOutBufferSize,
+ ((NvU8 *)ptr) + p.InBufferSize, p.InOutBufferSize +
+ p.OutBufferSize, &dctx);
+ if (err != NvSuccess) {
+ printk("NvECKernelIoctls_Generic: dispatch failure\n");
+ goto fail;
+ }
+
+ if (p.InOutBufferSize || p.OutBufferSize) {
+ err = NvOsCopyOut(
+ ((NvU8 *)((NvOsIoctlParams *)arg)->pBuffer) +
+ p.InBufferSize,
+ ((NvU8 *)ptr) + p.InBufferSize,
+ p.InOutBufferSize + p.OutBufferSize);
+ if (err != NvSuccess) {
+ printk("NvECKernelIoctls_Generic: copyout err\n");
+ goto fail;
+ }
+ }
+
+ break;
+ }
+ default:
+ printk("unknown ioctl code\n");
+ goto fail;
+ }
+ e = 0;
+ goto clean;
+
+fail:
+ e = -EINVAL;
+
+clean:
+ if (bAlloc)
+ NvOsFree(ptr);
+
+ return e;
+}
+
+#define DEVICE_NAME "nvec"
+
+static const struct file_operations nvec_fops =
+{
+ .owner = THIS_MODULE,
+ .open = nvec_open,
+ .release = nvec_close,
+ .unlocked_ioctl = nvec_unlocked_ioctl,
+};
+
+static struct miscdevice nvec_dev =
+{
+ .name = DEVICE_NAME,
+ .fops = &nvec_fops,
+ .minor = MISC_DYNAMIC_MINOR,
+};
+
+static NvEcHandle s_NvEcHandle = NULL;
+
+static int nvec_bus_probe(struct device *_dev)
+{
+ struct nvec_driver *drv = dev_to_nvec_driver(_dev->driver);
+ struct nvec_device *dev = to_nvec_device(_dev);
+
+ return drv->probe(dev);
+}
+
+static int nvec_bus_remove(struct device *_dev)
+{
+ return 0;
+}
+
+int nvec_bus_match(struct device *_dev, struct device_driver *drv)
+{
+ struct nvec_device *dev = to_nvec_device(_dev);
+
+ return (strcmp(dev->name, drv->name) == 0);
+}
+
+static int nvec_bus_suspend(struct device *_dev, pm_message_t state)
+{
+ struct nvec_driver *drv = dev_to_nvec_driver(_dev->driver);
+ struct nvec_device *dev = to_nvec_device(_dev);
+ NvError e = NvError_Success;
+
+ device_count--;
+ drv->suspend(dev, state);
+
+ if (!device_count)
+ {
+ e = NvEcPowerSuspend(NvEcPowerState_Suspend);
+ if (e != NvSuccess) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int nvec_bus_resume(struct device *_dev)
+{
+ struct nvec_driver *drv = dev_to_nvec_driver(_dev->driver);
+ struct nvec_device *dev = to_nvec_device(_dev);
+
+ if (!device_count)
+ {
+ NvError e = NvEcPowerResume();
+ if (e != NvSuccess) {
+ return -1;
+ }
+ }
+
+ device_count++;
+ drv->resume(dev);
+ return 0;
+}
+
+static void nvec_bus_shutdown(struct device *pdev)
+{
+ NvEcPowerSuspend(NvEcPowerState_PowerDown);
+}
+
+static struct bus_type nvec_bus_type = {
+ .name = DEVICE_NAME,
+ .match = nvec_bus_match,
+ .probe = nvec_bus_probe,
+ .remove = nvec_bus_remove,
+ .suspend = nvec_bus_suspend,
+ .resume = nvec_bus_resume,
+ .shutdown = nvec_bus_shutdown,
+};
+
+static struct device nvec_bus_dev = {
+ .init_name = DEVICE_NAME
+};
+
+int nvec_register_driver(struct nvec_driver *drv)
+{
+ drv->driver.name = drv->name;
+ drv->driver.bus = &nvec_bus_type;
+ return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(nvec_register_driver);
+
+void nvec_unregister_driver(struct nvec_driver *drv)
+{
+ drv->driver.bus = &nvec_bus_type;
+ driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(nvec_unregister_driver);
+
+int nvec_register_device(struct nvec_device *pdev)
+{
+ if (!pdev)
+ return -EINVAL;
+
+ if (!pdev->dev.parent)
+ pdev->dev.parent = &nvec_bus_dev;
+
+ pdev->dev.bus = &nvec_bus_type;
+
+ dev_set_name(&pdev->dev, pdev->name);
+
+ device_count++;
+ return device_register(&pdev->dev);
+}
+EXPORT_SYMBOL_GPL(nvec_register_device);
+
+void nvec_unregister_device(struct nvec_device *pdev)
+{
+ if (pdev) {
+ device_count--;
+ device_unregister(&pdev->dev);
+ }
+}
+EXPORT_SYMBOL_GPL(nvec_unregister_device);
+
+static int __init nvec_init(void)
+{
+ int err = 0;
+ NvError status = NvSuccess;
+ NvU32 NumTypes = 1; // TODO: must have NvRtObjType_NvEc_Num instead;
+
+ err = device_register(&nvec_bus_dev);
+ if (err)
+ return err;
+
+ err = bus_register(&nvec_bus_type);
+ if (err){
+ device_unregister(&nvec_bus_dev);
+ return err;
+ }
+
+
+ NV_ASSERT(s_RtHandle == NULL);
+
+ if (NvRtCreate(1, &NumTypes, &s_RtHandle) != NvSuccess) {
+ printk("nvec NvRtCreate returned error\n");
+ bus_unregister(&nvec_bus_type);
+ device_unregister(&nvec_bus_dev);
+ return -ENOMEM;
+ }
+
+ status = NvEcOpen(&s_NvEcHandle, 0);
+ if (status != NvError_Success) {
+ printk("nvec NvEcOpen returned 0x%x\n", status);
+ NvRtDestroy(s_RtHandle);
+ s_RtHandle = NULL;
+ bus_unregister(&nvec_bus_type);
+ device_unregister(&nvec_bus_dev);
+ return -EINVAL;
+ }
+
+ err = misc_register(&nvec_dev);
+ if (err < 0) {
+ if (s_RtHandle) {
+ NvEcClose(s_NvEcHandle);
+ s_NvEcHandle = NULL;
+ NvRtDestroy(s_RtHandle);
+ s_RtHandle = NULL;
+ bus_unregister(&nvec_bus_type);
+ device_unregister(&nvec_bus_dev);
+ }
+ printk("nvec failed to open\n");
+ }
+
+ return err;
+}
+
+static void __exit nvec_exit(void)
+{
+ NvEcClose(s_NvEcHandle);
+ s_NvEcHandle = NULL;
+ misc_deregister( &nvec_dev );
+ NvRtDestroy(s_RtHandle);
+ s_RtHandle = NULL;
+
+ bus_unregister(&nvec_bus_type);
+ device_unregister(&nvec_bus_dev);
+}
+
+module_init(nvec_init);
+module_exit(nvec_exit);
+
+MODULE_LICENSE("GPL");
\ No newline at end of file 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"); |