Commit 162c7d8c authored by Marc Dietrich's avatar Marc Dietrich Committed by Greg Kroah-Hartman

staging: nvec: coding style fixes / add copyright notice

This patch fixes coding style and adds copyright notices.
Signed-off-by: default avatarMarc Dietrich <marvin24@gmx.de>
[jak@jak-linux.org: Merge later cleanup into that patch]
Signed-off-by: default avatarJulian Andres Klode <jak@jak-linux.org>
Acked-by: default avatarMarc Dietrich <marvin24@gmx.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 7974035c
ToDo list (incomplete, unordered) ToDo list (incomplete, unordered)
- convert mouse, keyboard, and power to platform devices
- add copyright / driver author / license
- add compile as module support - add compile as module support
- move nvec devices to mfd cells?
- adjust to kernel style
- fix clk usage - fix clk usage
should not be using clk_get_sys(), but clk_get(&pdev->dev, conn) should not be using clk_get_sys(), but clk_get(&pdev->dev, conn)
where conn is either NULL if the device only has one clock, or where conn is either NULL if the device only has one clock, or
the device specific name if it has multiple clocks. the device specific name if it has multiple clocks.
- move half of the nvec init stuff to i2c-tegra.c
...@@ -22,7 +22,8 @@ ...@@ -22,7 +22,8 @@
*/ */
static unsigned short code_tab_102us[] = { static unsigned short code_tab_102us[] = {
KEY_GRAVE, // 0x00 /* 0x00 */
KEY_GRAVE,
KEY_ESC, KEY_ESC,
KEY_1, KEY_1,
KEY_2, KEY_2,
...@@ -38,7 +39,8 @@ static unsigned short code_tab_102us[] = { ...@@ -38,7 +39,8 @@ static unsigned short code_tab_102us[] = {
KEY_EQUAL, KEY_EQUAL,
KEY_BACKSPACE, KEY_BACKSPACE,
KEY_TAB, KEY_TAB,
KEY_Q, // 0x10 /* 0x10 */
KEY_Q,
KEY_W, KEY_W,
KEY_E, KEY_E,
KEY_R, KEY_R,
...@@ -54,7 +56,8 @@ static unsigned short code_tab_102us[] = { ...@@ -54,7 +56,8 @@ static unsigned short code_tab_102us[] = {
KEY_LEFTCTRL, KEY_LEFTCTRL,
KEY_A, KEY_A,
KEY_S, KEY_S,
KEY_D, // 0x20 /* 0x20 */
KEY_D,
KEY_F, KEY_F,
KEY_G, KEY_G,
KEY_H, KEY_H,
...@@ -70,7 +73,8 @@ static unsigned short code_tab_102us[] = { ...@@ -70,7 +73,8 @@ static unsigned short code_tab_102us[] = {
KEY_X, KEY_X,
KEY_C, KEY_C,
KEY_V, KEY_V,
KEY_B, // 0x30 /* 0x30 */
KEY_B,
KEY_N, KEY_N,
KEY_M, KEY_M,
KEY_COMMA, KEY_COMMA,
...@@ -86,13 +90,15 @@ static unsigned short code_tab_102us[] = { ...@@ -86,13 +90,15 @@ static unsigned short code_tab_102us[] = {
KEY_F3, KEY_F3,
KEY_F4, KEY_F4,
KEY_F5, KEY_F5,
KEY_F6, // 0x40 /* 0x40 */
KEY_F6,
KEY_F7, KEY_F7,
KEY_F8, KEY_F8,
KEY_F9, KEY_F9,
KEY_F10, KEY_F10,
KEY_FN, KEY_FN,
0, //VK_SCROLL /* VK_SCROLL */
0,
KEY_KP7, KEY_KP7,
KEY_KP8, KEY_KP8,
KEY_KP9, KEY_KP9,
...@@ -102,52 +108,57 @@ static unsigned short code_tab_102us[] = { ...@@ -102,52 +108,57 @@ static unsigned short code_tab_102us[] = {
KEY_KP6, KEY_KP6,
KEY_KPPLUS, KEY_KPPLUS,
KEY_KP1, KEY_KP1,
KEY_KP2, // 0x50 /* 0x50 */
KEY_KP2,
KEY_KP3, KEY_KP3,
KEY_KP0, KEY_KP0,
KEY_KPDOT, KEY_KPDOT,
KEY_MENU, //VK_SNAPSHOT /* VK_SNAPSHOT */
KEY_MENU,
KEY_POWER, KEY_POWER,
KEY_102ND, //VK_OEM_102 henry+ 0x2B (43) BACKSLASH have been used,change to use 0X56 (86) /* VK_OEM_102 */
KEY_F11, //VK_F11 KEY_102ND,
KEY_F12, //VK_F12 KEY_F11,
0, KEY_F12,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, // 60 0,
0, /* 0x60 */
0, 0,
KEY_SEARCH, // add search key map 0,
0, 0,
0, KEY_SEARCH,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, // 70 0,
0, 0,
0, /* 0x70 */
KEY_KP5, //73 for JP keyboard '\' key, report 0x4c 0,
0, 0,
0, 0,
0, KEY_KP5,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
KEY_KP9, //7d for JP keyboard '|' key, report 0x49 0,
0,
0,
KEY_KP9,
}; };
static unsigned short extcode_tab_us102[] = { static unsigned short extcode_tab_us102[] = {
...@@ -167,27 +178,35 @@ static unsigned short extcode_tab_us102[] = { ...@@ -167,27 +178,35 @@ static unsigned short extcode_tab_us102[] = {
0, 0,
0, 0,
0, 0,
0, // 0xE0 0x10 /* 0x10 */
0,
0,
0,
0,
0,
0,
0,
0, 0,
0, 0,
/* VK_MEDIA_NEXT_TRACK */
0, 0,
0, 0,
0, 0,
/* VK_RETURN */
0, 0,
KEY_RIGHTCTRL,
0, 0,
0, 0,
0, //VK_MEDIA_NEXT_TRACK, /* 0x20 */
KEY_MUTE,
/* VK_LAUNCH_APP1 */
0, 0,
/* VK_MEDIA_PLAY_PAUSE */
0, 0,
0, //VK_RETURN,
KEY_RIGHTCTRL, //VK_RCONTROL,
0, 0,
/* VK_MEDIA_STOP */
0, 0,
KEY_MUTE, // 0xE0 0x20
0, //VK_LAUNCH_APP1
0, //VK_MEDIA_PLAY_PAUSE
0, 0,
0, //VK_MEDIA_STOP
0, 0,
0, 0,
0, 0,
...@@ -198,41 +217,54 @@ static unsigned short extcode_tab_us102[] = { ...@@ -198,41 +217,54 @@ static unsigned short extcode_tab_us102[] = {
0, 0,
0, 0,
0, 0,
/* 0x30 */
KEY_VOLUMEUP,
0, 0,
KEY_VOLUMEUP, // 0xE0 0x30 /* VK_BROWSER_HOME */
0,
0,
0,
/* VK_DIVIDE */
KEY_KPSLASH,
0,
/* VK_SNAPSHOT */
KEY_SYSRQ,
/* VK_RMENU */
KEY_RIGHTALT,
/* VK_OEM_NV_BACKLIGHT_UP */
0,
/* VK_OEM_NV_BACKLIGHT_DN */
0,
/* VK_OEM_NV_BACKLIGHT_AUTOTOGGLE */
0,
/* VK_OEM_NV_POWER_INFO */
0,
/* VK_OEM_NV_WIFI_TOGGLE */
0,
/* VK_OEM_NV_DISPLAY_SELECT */
0,
/* VK_OEM_NV_AIRPLANE_TOGGLE */
0,
/* 0x40 */
0,
KEY_LEFT,
0, 0,
0, //VK_BROWSER_HOME
0, 0,
0, 0,
KEY_KPSLASH, //VK_DIVIDE
0, 0,
KEY_SYSRQ, //VK_SNAPSHOT
KEY_RIGHTALT, //VK_RMENU
0, //VK_OEM_NV_BACKLIGHT_UP
0, //VK_OEM_NV_BACKLIGHT_DN
0, //VK_OEM_NV_BACKLIGHT_AUTOTOGGLE
0, //VK_OEM_NV_POWER_INFO
0, //VK_OEM_NV_WIFI_TOGGLE
0, //VK_OEM_NV_DISPLAY_SELECT
0, //VK_OEM_NV_AIRPLANE_TOGGLE
0, //0xE0 0x40
KEY_LEFT, //VK_OEM_NV_RESERVED henry+ for JP keyboard
0, //VK_OEM_NV_RESERVED
0, //VK_OEM_NV_RESERVED
0, //VK_OEM_NV_RESERVED
0, //VK_OEM_NV_RESERVED
KEY_CANCEL, KEY_CANCEL,
KEY_HOME, KEY_HOME,
KEY_UP, KEY_UP,
KEY_PAGEUP, //VK_PRIOR KEY_PAGEUP,
0, 0,
KEY_LEFT, KEY_LEFT,
0, 0,
KEY_RIGHT, KEY_RIGHT,
0, 0,
KEY_END, KEY_END,
KEY_DOWN, // 0xE0 0x50 /* 0x50 */
KEY_PAGEDOWN, //VK_NEXT KEY_DOWN,
KEY_PAGEDOWN,
KEY_INSERT, KEY_INSERT,
KEY_DELETE, KEY_DELETE,
0, 0,
...@@ -242,25 +274,34 @@ static unsigned short extcode_tab_us102[] = { ...@@ -242,25 +274,34 @@ static unsigned short extcode_tab_us102[] = {
0, 0,
0, 0,
0, 0,
KEY_LEFTMETA, //VK_LWIN KEY_LEFTMETA,
0, //VK_RWIN 0,
KEY_ESC, //VK_APPS KEY_ESC,
KEY_KPMINUS, //for power button workaround KEY_KPMINUS,
0, 0,
0,
0,
0,
0,
0,
/* VK_BROWSER_SEARCH */
0,
/* VK_BROWSER_FAVORITES */
0,
/* VK_BROWSER_REFRESH */
0,
/* VK_BROWSER_STOP */
0,
/* VK_BROWSER_FORWARD */
0, 0,
/* VK_BROWSER_BACK */
0, 0,
/* VK_LAUNCH_APP2 */
0, 0,
/* VK_LAUNCH_MAIL */
0, 0,
/* VK_LAUNCH_MEDIA_SELECT */
0, 0,
0, //VK_BROWSER_SEARCH
0, //VK_BROWSER_FAVORITES
0, //VK_BROWSER_REFRESH
0, //VK_BROWSER_STOP
0, //VK_BROWSER_FORWARD
0, //VK_BROWSER_BACK
0, //VK_LAUNCH_APP2
0, //VK_LAUNCH_MAIL
0, //VK_LAUNCH_MEDIA_SELECT
}; };
static unsigned short* code_tabs[] = {code_tab_102us, extcode_tab_us102 }; static unsigned short *code_tabs[] = { code_tab_102us, extcode_tab_us102 };
// #define DEBUG /*
* NVEC: NVIDIA compliant embedded controller interface
*
* Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
*
* Authors: Pierre-Hugues Husson <phhusson@free.fr>
* Ilya Petrov <ilya.muromec@gmail.com>
* Marc Dietrich <marvin24@gmx.de>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
*/
/* #define DEBUG */
/* ToDo list (incomplete, unorderd)
- convert mouse, keyboard, and power to platform devices
*/
#include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/gpio.h> #include <linux/gpio.h>
...@@ -16,57 +28,60 @@ ...@@ -16,57 +28,60 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <mach/iomap.h>
#include <mach/clk.h>
#include <linux/semaphore.h> #include <linux/semaphore.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <mach/iomap.h>
#include <mach/clk.h>
#include "nvec.h" #include "nvec.h"
static unsigned char EC_DISABLE_EVENT_REPORTING[] = {'\x04','\x00','\x00'}; static const unsigned char EC_DISABLE_EVENT_REPORTING[3] = "\x04\x00\x00";
static unsigned char EC_ENABLE_EVENT_REPORTING[] = {'\x04','\x00','\x01'}; static const unsigned char EC_ENABLE_EVENT_REPORTING[3] = "\x04\x00\x01";
static unsigned char EC_GET_FIRMWARE_VERSION[] = {'\x07','\x15'}; static const unsigned char EC_GET_FIRMWARE_VERSION[2] = "\x07\x15";
static struct nvec_chip *nvec_power_handle; static struct nvec_chip *nvec_power_handle;
static struct mfd_cell nvec_devices[] = { static struct mfd_cell nvec_devices[] = {
{ {
.name = "nvec-kbd", .name = "nvec-kbd",
.id = 1, .id = 1,
}, },
{ {
.name = "nvec-mouse", .name = "nvec-mouse",
.id = 1, .id = 1,
}, },
{ {
.name = "nvec-power", .name = "nvec-power",
.id = 1, .id = 1,
}, },
{ {
.name = "nvec-power", .name = "nvec-power",
.id = 2, .id = 2,
}, },
}; };
int nvec_register_notifier(struct nvec_chip *nvec, struct notifier_block *nb, int nvec_register_notifier(struct nvec_chip *nvec, struct notifier_block *nb,
unsigned int events) unsigned int events)
{ {
return atomic_notifier_chain_register(&nvec->notifier_list, nb); return atomic_notifier_chain_register(&nvec->notifier_list, nb);
} }
EXPORT_SYMBOL_GPL(nvec_register_notifier); EXPORT_SYMBOL_GPL(nvec_register_notifier);
static int nvec_status_notifier(struct notifier_block *nb, unsigned long event_type, static int nvec_status_notifier(struct notifier_block *nb,
void *data) unsigned long event_type, void *data)
{ {
unsigned char *msg = (unsigned char *)data; unsigned char *msg = (unsigned char *)data;
int i; int i;
if(event_type != NVEC_CNTL) if (event_type != NVEC_CNTL)
return NOTIFY_DONE; return NOTIFY_DONE;
printk("unhandled msg type %ld, payload: ", event_type); printk(KERN_WARNING "unhandled msg type %ld, payload: ", event_type);
for (i = 0; i < msg[1]; i++) for (i = 0; i < msg[1]; i++)
printk("%0x ", msg[i+2]); printk("%0x ", msg[i+2]);
printk("\n"); printk("\n");
...@@ -74,7 +89,8 @@ static int nvec_status_notifier(struct notifier_block *nb, unsigned long event_t ...@@ -74,7 +89,8 @@ static int nvec_status_notifier(struct notifier_block *nb, unsigned long event_t
return NOTIFY_OK; return NOTIFY_OK;
} }
void nvec_write_async(struct nvec_chip *nvec, unsigned char *data, short size) void nvec_write_async(struct nvec_chip *nvec, const unsigned char *data,
short size)
{ {
struct nvec_msg *msg = kzalloc(sizeof(struct nvec_msg), GFP_NOWAIT); struct nvec_msg *msg = kzalloc(sizeof(struct nvec_msg), GFP_NOWAIT);
...@@ -95,42 +111,43 @@ static void nvec_request_master(struct work_struct *work) ...@@ -95,42 +111,43 @@ static void nvec_request_master(struct work_struct *work)
{ {
struct nvec_chip *nvec = container_of(work, struct nvec_chip, tx_work); struct nvec_chip *nvec = container_of(work, struct nvec_chip, tx_work);
if(!list_empty(&nvec->tx_data)) { if (!list_empty(&nvec->tx_data))
gpio_set_value(nvec->gpio, 0); gpio_set_value(nvec->gpio, 0);
}
} }
static int parse_msg(struct nvec_chip *nvec, struct nvec_msg *msg) static int parse_msg(struct nvec_chip *nvec, struct nvec_msg *msg)
{ {
int i; int i;
if((msg->data[0] & 1<<7) == 0 && msg->data[3]) { if ((msg->data[0] & 1 << 7) == 0 && msg->data[3]) {
dev_err(nvec->dev, "ec responded %02x %02x %02x %02x\n", msg->data[0], dev_err(nvec->dev, "ec responded %02x %02x %02x %02x\n",
msg->data[1], msg->data[2], msg->data[3]); msg->data[0], msg->data[1], msg->data[2], msg->data[3]);
return -EINVAL; return -EINVAL;
} }
if ((msg->data[0] >> 7 ) == 1 && (msg->data[0] & 0x0f) == 5) if ((msg->data[0] >> 7) == 1 && (msg->data[0] & 0x0f) == 5) {
{
dev_warn(nvec->dev, "ec system event "); dev_warn(nvec->dev, "ec system event ");
for (i=0; i < msg->data[1]; i++) for (i = 0; i < msg->data[1]; i++)
dev_warn(nvec->dev, "%02x ", msg->data[2+i]); dev_warn(nvec->dev, "%02x ", msg->data[2+i]);
dev_warn(nvec->dev, "\n"); dev_warn(nvec->dev, "\n");
} }
atomic_notifier_call_chain(&nvec->notifier_list, msg->data[0] & 0x8f, msg->data); atomic_notifier_call_chain(&nvec->notifier_list, msg->data[0] & 0x8f,
msg->data);
return 0; return 0;
} }
static struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec, unsigned char *data, short size) static struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec,
const unsigned char *data, short size)
{ {
down(&nvec->sync_write_mutex); down(&nvec->sync_write_mutex);
nvec->sync_write_pending = (data[1] << 8) + data[0]; nvec->sync_write_pending = (data[1] << 8) + data[0];
nvec_write_async(nvec, data, size); nvec_write_async(nvec, data, size);
dev_dbg(nvec->dev, "nvec_sync_write: 0x%04x\n", nvec->sync_write_pending); dev_dbg(nvec->dev, "nvec_sync_write: 0x%04x\n",
nvec->sync_write_pending);
wait_for_completion(&nvec->sync_write); wait_for_completion(&nvec->sync_write);
dev_dbg(nvec->dev, "nvec_sync_write: pong!\n"); dev_dbg(nvec->dev, "nvec_sync_write: pong!\n");
...@@ -145,21 +162,21 @@ static void nvec_dispatch(struct work_struct *work) ...@@ -145,21 +162,21 @@ static void nvec_dispatch(struct work_struct *work)
struct nvec_chip *nvec = container_of(work, struct nvec_chip, rx_work); struct nvec_chip *nvec = container_of(work, struct nvec_chip, rx_work);
struct nvec_msg *msg; struct nvec_msg *msg;
while(!list_empty(&nvec->rx_data)) while (!list_empty(&nvec->rx_data)) {
{
msg = list_first_entry(&nvec->rx_data, struct nvec_msg, node); msg = list_first_entry(&nvec->rx_data, struct nvec_msg, node);
list_del_init(&msg->node); list_del_init(&msg->node);
if(nvec->sync_write_pending == (msg->data[2] << 8) + msg->data[0]) if (nvec->sync_write_pending ==
{ (msg->data[2] << 8) + msg->data[0]) {
dev_dbg(nvec->dev, "sync write completed!\n"); dev_dbg(nvec->dev, "sync write completed!\n");
nvec->sync_write_pending = 0; nvec->sync_write_pending = 0;
nvec->last_sync_msg = msg; nvec->last_sync_msg = msg;
complete(&nvec->sync_write); complete(&nvec->sync_write);
} else { } else {
parse_msg(nvec, msg); parse_msg(nvec, msg);
if((!msg) || (!msg->data)) if ((!msg) || (!msg->data))
dev_warn(nvec->dev, "attempt access zero pointer\n"); dev_warn(nvec->dev,
"attempt access zero pointer\n");
else { else {
kfree(msg->data); kfree(msg->data);
kfree(msg); kfree(msg);
...@@ -179,20 +196,13 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) ...@@ -179,20 +196,13 @@ static irqreturn_t nvec_interrupt(int irq, void *dev)
status = readl(base + I2C_SL_STATUS); status = readl(base + I2C_SL_STATUS);
if(!(status & I2C_SL_IRQ)) if (!(status & I2C_SL_IRQ)) {
{
dev_warn(nvec->dev, "nvec Spurious IRQ\n"); dev_warn(nvec->dev, "nvec Spurious IRQ\n");
//Yup, handled. ahum.
goto handled; goto handled;
} }
if(status & END_TRANS && !(status & RCVD)) if (status & END_TRANS && !(status & RCVD)) {
{
//Reenable IRQ only when even has been sent
//printk("Write sequence ended !\n");
//parse_msg(nvec);
nvec->state = NVEC_WAIT; nvec->state = NVEC_WAIT;
if(nvec->rx->size > 1) if (nvec->rx->size > 1) {
{
list_add_tail(&nvec->rx->node, &nvec->rx_data); list_add_tail(&nvec->rx->node, &nvec->rx_data);
schedule_work(&nvec->rx_work); schedule_work(&nvec->rx_work);
} else { } else {
...@@ -200,41 +210,31 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) ...@@ -200,41 +210,31 @@ static irqreturn_t nvec_interrupt(int irq, void *dev)
kfree(nvec->rx); kfree(nvec->rx);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
} else if(status & RNW) } else if (status & RNW) {
{ if (status & RCVD)
// Work around for AP20 New Slave Hw Bug. Give 1us extra.
// nvec/smbus/nvec_i2c_transport.c in NV`s crap for reference
if(status & RCVD)
udelay(3); udelay(3);
if(status & RCVD) if (status & RCVD)
{
nvec->state = NVEC_WRITE; nvec->state = NVEC_WRITE;
//Master wants something from us. New communication
// dev_dbg(nvec->dev, "New read comm!\n"); if (list_empty(&nvec->tx_data)) {
} else {
//Master wants something from us from a communication we've already started
// dev_dbg(nvec->dev, "Read comm cont !\n");
}
//if(msg_pos<msg_size) {
if(list_empty(&nvec->tx_data))
{
dev_err(nvec->dev, "nvec empty tx - sending no-op\n"); dev_err(nvec->dev, "nvec empty tx - sending no-op\n");
to_send = 0x8a; to_send = 0x8a;
nvec_write_async(nvec, "\x07\x02", 2); nvec_write_async(nvec, "\x07\x02", 2);
// to_send = 0x01;
} else { } else {
msg = list_first_entry(&nvec->tx_data, struct nvec_msg, node); msg =
if(msg->pos < msg->size) { list_first_entry(&nvec->tx_data, struct nvec_msg,
node);
if (msg->pos < msg->size) {
to_send = msg->data[msg->pos]; to_send = msg->data[msg->pos];
msg->pos++; msg->pos++;
} else { } else {
dev_err(nvec->dev, "nvec crap! %d\n", msg->size); dev_err(nvec->dev, "nvec crap! %d\n",
msg->size);
to_send = 0x01; to_send = 0x01;
} }
if(msg->pos >= msg->size) if (msg->pos >= msg->size) {
{
list_del_init(&msg->node); list_del_init(&msg->node);
kfree(msg->data); kfree(msg->data);
kfree(msg); kfree(msg);
...@@ -251,14 +251,13 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) ...@@ -251,14 +251,13 @@ static irqreturn_t nvec_interrupt(int irq, void *dev)
goto handled; goto handled;
} else { } else {
received = readl(base + I2C_SL_RCVD); received = readl(base + I2C_SL_RCVD);
//Workaround?
if(status & RCVD) { if (status & RCVD) {
writel(0, base + I2C_SL_RCVD); writel(0, base + I2C_SL_RCVD);
goto handled; goto handled;
} }
if (nvec->state == NVEC_WAIT) if (nvec->state == NVEC_WAIT) {
{
nvec->state = NVEC_READ; nvec->state = NVEC_READ;
msg = kzalloc(sizeof(struct nvec_msg), GFP_NOWAIT); msg = kzalloc(sizeof(struct nvec_msg), GFP_NOWAIT);
msg->data = kzalloc(32, GFP_NOWAIT); msg->data = kzalloc(32, GFP_NOWAIT);
...@@ -272,7 +271,8 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) ...@@ -272,7 +271,8 @@ static irqreturn_t nvec_interrupt(int irq, void *dev)
msg->data[msg->pos] = received; msg->data[msg->pos] = received;
msg->pos++; msg->pos++;
msg->size = msg->pos; msg->size = msg->pos;
dev_dbg(nvec->dev, "Got %02lx from Master (pos: %d)!\n", received, msg->pos); dev_dbg(nvec->dev, "Got %02lx from Master (pos: %d)!\n",
received, msg->pos);
} }
handled: handled:
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -318,7 +318,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) ...@@ -318,7 +318,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev)
void __iomem *base; void __iomem *base;
nvec = kzalloc(sizeof(struct nvec_chip), GFP_KERNEL); nvec = kzalloc(sizeof(struct nvec_chip), GFP_KERNEL);
if(nvec == NULL) { if (nvec == NULL) {
dev_err(&pdev->dev, "failed to reserve memory\n"); dev_err(&pdev->dev, "failed to reserve memory\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -367,7 +367,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) ...@@ -367,7 +367,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev)
/* Set the gpio to low when we've got something to say */ /* Set the gpio to low when we've got something to say */
err = gpio_request(nvec->gpio, "nvec gpio"); err = gpio_request(nvec->gpio, "nvec gpio");
if(err < 0) if (err < 0)
dev_err(nvec->dev, "couldn't request gpio\n"); dev_err(nvec->dev, "couldn't request gpio\n");
ATOMIC_INIT_NOTIFIER_HEAD(&nvec->notifier_list); ATOMIC_INIT_NOTIFIER_HEAD(&nvec->notifier_list);
...@@ -392,7 +392,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) ...@@ -392,7 +392,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev)
/* enable event reporting */ /* enable event reporting */
nvec_write_async(nvec, EC_ENABLE_EVENT_REPORTING, nvec_write_async(nvec, EC_ENABLE_EVENT_REPORTING,
sizeof(EC_ENABLE_EVENT_REPORTING)); sizeof(EC_ENABLE_EVENT_REPORTING));
nvec->nvec_status_notifier.notifier_call = nvec_status_notifier; nvec->nvec_status_notifier.notifier_call = nvec_status_notifier;
nvec_register_notifier(nvec, &nvec->nvec_status_notifier, 0); nvec_register_notifier(nvec, &nvec->nvec_status_notifier, 0);
...@@ -402,17 +402,17 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) ...@@ -402,17 +402,17 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev)
/* Get Firmware Version */ /* Get Firmware Version */
msg = nvec_write_sync(nvec, EC_GET_FIRMWARE_VERSION, msg = nvec_write_sync(nvec, EC_GET_FIRMWARE_VERSION,
sizeof(EC_GET_FIRMWARE_VERSION)); sizeof(EC_GET_FIRMWARE_VERSION));
dev_warn(nvec->dev, "ec firmware version %02x.%02x.%02x / %02x\n", dev_warn(nvec->dev, "ec firmware version %02x.%02x.%02x / %02x\n",
msg->data[4], msg->data[5], msg->data[6], msg->data[7]); msg->data[4], msg->data[5], msg->data[6], msg->data[7]);
kfree(msg->data); kfree(msg->data);
kfree(msg); kfree(msg);
ret = mfd_add_devices(nvec->dev, -1, nvec_devices, ret = mfd_add_devices(nvec->dev, -1, nvec_devices,
ARRAY_SIZE(nvec_devices), base, 0); ARRAY_SIZE(nvec_devices), base, 0);
if(ret) if (ret)
dev_err(nvec->dev, "error adding subdevices\n"); dev_err(nvec->dev, "error adding subdevices\n");
/* unmute speakers? */ /* unmute speakers? */
...@@ -460,8 +460,8 @@ static int tegra_nvec_suspend(struct platform_device *pdev, pm_message_t state) ...@@ -460,8 +460,8 @@ static int tegra_nvec_suspend(struct platform_device *pdev, pm_message_t state)
return 0; return 0;
} }
static int tegra_nvec_resume(struct platform_device *pdev) { static int tegra_nvec_resume(struct platform_device *pdev)
{
struct nvec_chip *nvec = platform_get_drvdata(pdev); struct nvec_chip *nvec = platform_get_drvdata(pdev);
dev_dbg(nvec->dev, "resuming\n"); dev_dbg(nvec->dev, "resuming\n");
...@@ -476,13 +476,12 @@ static int tegra_nvec_resume(struct platform_device *pdev) { ...@@ -476,13 +476,12 @@ static int tegra_nvec_resume(struct platform_device *pdev) {
#define tegra_nvec_resume NULL #define tegra_nvec_resume NULL
#endif #endif
static struct platform_driver nvec_device_driver = static struct platform_driver nvec_device_driver = {
{ .probe = tegra_nvec_probe,
.probe = tegra_nvec_probe, .remove = __devexit_p(tegra_nvec_remove),
.remove = __devexit_p(tegra_nvec_remove),
.suspend = tegra_nvec_suspend, .suspend = tegra_nvec_suspend,
.resume = tegra_nvec_resume, .resume = tegra_nvec_resume,
.driver = { .driver = {
.name = "nvec", .name = "nvec",
.owner = THIS_MODULE, .owner = THIS_MODULE,
} }
...@@ -494,4 +493,8 @@ static int __init tegra_nvec_init(void) ...@@ -494,4 +493,8 @@ static int __init tegra_nvec_init(void)
} }
module_init(tegra_nvec_init); module_init(tegra_nvec_init);
MODULE_ALIAS("platform:nvec"); MODULE_ALIAS("platform:nvec");
MODULE_DESCRIPTION("NVIDIA compliant embedded controller interface");
MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>");
MODULE_LICENSE("GPL");
/*
* NVEC: NVIDIA compliant embedded controller interface
*
* Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.launchpad.net>
*
* Authors: Pierre-Hugues Husson <phhusson@free.fr>
* Ilya Petrov <ilya.muromec@gmail.com>
* Marc Dietrich <marvin24@gmx.de>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
*/
#ifndef __LINUX_MFD_NVEC #ifndef __LINUX_MFD_NVEC
#define __LINUX_MFD_NVEC #define __LINUX_MFD_NVEC
...@@ -17,7 +32,7 @@ typedef enum { ...@@ -17,7 +32,7 @@ typedef enum {
} how_care; } how_care;
typedef enum { typedef enum {
NVEC_SYS=1, NVEC_SYS = 1,
NVEC_BAT, NVEC_BAT,
NVEC_KBD = 5, NVEC_KBD = 5,
NVEC_PS2, NVEC_PS2,
...@@ -27,9 +42,9 @@ typedef enum { ...@@ -27,9 +42,9 @@ typedef enum {
} nvec_event; } nvec_event;
typedef enum { typedef enum {
NVEC_WAIT, NVEC_WAIT,
NVEC_READ, NVEC_READ,
NVEC_WRITE NVEC_WRITE
} nvec_state; } nvec_state;
struct nvec_msg { struct nvec_msg {
...@@ -64,22 +79,27 @@ struct nvec_chip { ...@@ -64,22 +79,27 @@ struct nvec_chip {
struct work_struct rx_work, tx_work; struct work_struct rx_work, tx_work;
struct nvec_msg *rx, *tx; struct nvec_msg *rx, *tx;
/* sync write stuff */ /* sync write stuff */
struct semaphore sync_write_mutex; struct semaphore sync_write_mutex;
struct completion sync_write; struct completion sync_write;
u16 sync_write_pending; u16 sync_write_pending;
struct nvec_msg *last_sync_msg; struct nvec_msg *last_sync_msg;
}; };
extern void nvec_write_async(struct nvec_chip *nvec, unsigned char *data, short size); extern void nvec_write_async(struct nvec_chip *nvec, const unsigned char *data,
short size);
extern int nvec_register_notifier(struct nvec_chip *nvec, extern int nvec_register_notifier(struct nvec_chip *nvec,
struct notifier_block *nb, unsigned int events); struct notifier_block *nb,
unsigned int events);
extern int nvec_unregister_notifier(struct device *dev, extern int nvec_unregister_notifier(struct device *dev,
struct notifier_block *nb, unsigned int events); struct notifier_block *nb,
unsigned int events);
const char *nvec_send_msg(unsigned char *src, unsigned char *dst_size, how_care care_resp, void (*rt_handler)(unsigned char *data)); const char *nvec_send_msg(unsigned char *src, unsigned char *dst_size,
how_care care_resp,
void (*rt_handler) (unsigned char *data));
#define I2C_CNFG 0x00 #define I2C_CNFG 0x00
#define I2C_CNFG_PACKET_MODE_EN (1<<10) #define I2C_CNFG_PACKET_MODE_EN (1<<10)
......
/*
* nvec_kbd: keyboard driver for a NVIDIA compliant embedded controller
*
* Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.launchpad.net>
*
* Authors: Pierre-Hugues Husson <phhusson@free.fr>
* Marc Dietrich <marvin24@gmx.de>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
*/
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "nvec-keytable.h" #include "nvec-keytable.h"
#include "nvec.h" #include "nvec.h"
#define ACK_KBD_EVENT {'\x05', '\xed', '\x01'} #define ACK_KBD_EVENT {'\x05', '\xed', '\x01'}
static unsigned char keycodes[ARRAY_SIZE(code_tab_102us) static unsigned char keycodes[ARRAY_SIZE(code_tab_102us)
+ ARRAY_SIZE(extcode_tab_us102)]; + ARRAY_SIZE(extcode_tab_us102)];
struct nvec_keys { struct nvec_keys {
struct input_dev *input; struct input_dev *input;
...@@ -20,7 +35,7 @@ struct nvec_keys { ...@@ -20,7 +35,7 @@ struct nvec_keys {
static struct nvec_keys keys_dev; static struct nvec_keys keys_dev;
static int nvec_keys_notifier(struct notifier_block *nb, static int nvec_keys_notifier(struct notifier_block *nb,
unsigned long event_type, void *data) unsigned long event_type, void *data)
{ {
int code, state; int code, state;
unsigned char *msg = (unsigned char *)data; unsigned char *msg = (unsigned char *)data;
...@@ -38,7 +53,8 @@ static int nvec_keys_notifier(struct notifier_block *nb, ...@@ -38,7 +53,8 @@ static int nvec_keys_notifier(struct notifier_block *nb,
code = msg[1] & 0x7f; code = msg[1] & 0x7f;
state = msg[1] & 0x80; state = msg[1] & 0x80;
input_report_key(keys_dev.input, code_tabs[_size][code], !state); input_report_key(keys_dev.input, code_tabs[_size][code],
!state);
input_sync(keys_dev.input); input_sync(keys_dev.input);
return NOTIFY_STOP; return NOTIFY_STOP;
...@@ -48,7 +64,7 @@ static int nvec_keys_notifier(struct notifier_block *nb, ...@@ -48,7 +64,7 @@ static int nvec_keys_notifier(struct notifier_block *nb,
} }
static int nvec_kbd_event(struct input_dev *dev, unsigned int type, static int nvec_kbd_event(struct input_dev *dev, unsigned int type,
unsigned int code, int value) unsigned int code, int value)
{ {
unsigned char buf[] = ACK_KBD_EVENT; unsigned char buf[] = ACK_KBD_EVENT;
struct nvec_chip *nvec = keys_dev.nvec; struct nvec_chip *nvec = keys_dev.nvec;
...@@ -125,10 +141,10 @@ static int __devinit nvec_kbd_probe(struct platform_device *pdev) ...@@ -125,10 +141,10 @@ static int __devinit nvec_kbd_probe(struct platform_device *pdev)
} }
static struct platform_driver nvec_kbd_driver = { static struct platform_driver nvec_kbd_driver = {
.probe = nvec_kbd_probe, .probe = nvec_kbd_probe,
.driver = { .driver = {
.name = "nvec-kbd", .name = "nvec-kbd",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
}; };
...@@ -138,3 +154,7 @@ static int __init nvec_kbd_init(void) ...@@ -138,3 +154,7 @@ static int __init nvec_kbd_init(void)
} }
module_init(nvec_kbd_init); module_init(nvec_kbd_init);
MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>");
MODULE_DESCRIPTION("NVEC keyboard driver");
MODULE_LICENSE("GPL");
/*
* nvec_power: power supply driver for a NVIDIA compliant embedded controller
*
* Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.launchpad.net>
*
* Authors: Ilya Petrov <ilya.muromec@gmail.com>
* Marc Dietrich <marvin24@gmx.de>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
*/
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/err.h> #include <linux/err.h>
...@@ -5,10 +19,10 @@ ...@@ -5,10 +19,10 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/delay.h> #include <linux/delay.h>
#include "nvec.h" #include "nvec.h"
struct nvec_power struct nvec_power {
{
struct notifier_block notifier; struct notifier_block notifier;
struct delayed_work poller; struct delayed_work poller;
struct nvec_chip *nvec; struct nvec_chip *nvec;
...@@ -58,7 +72,8 @@ struct bat_response { ...@@ -58,7 +72,8 @@ struct bat_response {
u8 length; u8 length;
u8 sub_type; u8 sub_type;
u8 status; u8 status;
union { /* payload */ /* payload */
union {
char plc[30]; char plc[30];
u16 plu; u16 plu;
s16 pls; s16 pls;
...@@ -69,18 +84,17 @@ static struct power_supply nvec_bat_psy; ...@@ -69,18 +84,17 @@ static struct power_supply nvec_bat_psy;
static struct power_supply nvec_psy; static struct power_supply nvec_psy;
static int nvec_power_notifier(struct notifier_block *nb, static int nvec_power_notifier(struct notifier_block *nb,
unsigned long event_type, void *data) unsigned long event_type, void *data)
{ {
struct nvec_power *power = container_of(nb, struct nvec_power, notifier); struct nvec_power *power =
container_of(nb, struct nvec_power, notifier);
struct bat_response *res = (struct bat_response *)data; struct bat_response *res = (struct bat_response *)data;
if (event_type != NVEC_SYS) if (event_type != NVEC_SYS)
return NOTIFY_DONE; return NOTIFY_DONE;
if(res->sub_type == 0) if (res->sub_type == 0) {
{ if (power->on != res->plu) {
if (power->on != res->plu)
{
power->on = res->plu; power->on = res->plu;
power_supply_changed(&nvec_psy); power_supply_changed(&nvec_psy);
} }
...@@ -89,8 +103,7 @@ static int nvec_power_notifier(struct notifier_block *nb, ...@@ -89,8 +103,7 @@ static int nvec_power_notifier(struct notifier_block *nb,
return NOTIFY_OK; return NOTIFY_OK;
} }
static const int bat_init[] = static const int bat_init[] = {
{
LAST_FULL_CHARGE_CAPACITY, DESIGN_CAPACITY, CRITICAL_CAPACITY, LAST_FULL_CHARGE_CAPACITY, DESIGN_CAPACITY, CRITICAL_CAPACITY,
MANUFACTURER, MODEL, TYPE, MANUFACTURER, MODEL, TYPE,
}; };
...@@ -100,116 +113,115 @@ static void get_bat_mfg_data(struct nvec_power *power) ...@@ -100,116 +113,115 @@ static void get_bat_mfg_data(struct nvec_power *power)
int i; int i;
char buf[] = { '\x02', '\x00' }; char buf[] = { '\x02', '\x00' };
for (i = 0; i < ARRAY_SIZE(bat_init); i++) for (i = 0; i < ARRAY_SIZE(bat_init); i++) {
{
buf[1] = bat_init[i]; buf[1] = bat_init[i];
nvec_write_async(power->nvec, buf, 2); nvec_write_async(power->nvec, buf, 2);
} }
} }
static int nvec_power_bat_notifier(struct notifier_block *nb, static int nvec_power_bat_notifier(struct notifier_block *nb,
unsigned long event_type, void *data) unsigned long event_type, void *data)
{ {
struct nvec_power *power = container_of(nb, struct nvec_power, notifier); struct nvec_power *power =
container_of(nb, struct nvec_power, notifier);
struct bat_response *res = (struct bat_response *)data; struct bat_response *res = (struct bat_response *)data;
int status_changed = 0; int status_changed = 0;
if (event_type != NVEC_BAT) if (event_type != NVEC_BAT)
return NOTIFY_DONE; return NOTIFY_DONE;
switch(res->sub_type) switch (res->sub_type) {
{ case SLOT_STATUS:
case SLOT_STATUS: if (res->plc[0] & 1) {
if (res->plc[0] & 1) if (power->bat_present == 0) {
{ status_changed = 1;
if (power->bat_present == 0) get_bat_mfg_data(power);
{ }
status_changed = 1;
get_bat_mfg_data(power); power->bat_present = 1;
}
switch ((res->plc[0] >> 1) & 3) {
power->bat_present = 1; case 0:
power->bat_status =
switch ((res->plc[0] >> 1) & 3) POWER_SUPPLY_STATUS_NOT_CHARGING;
{ break;
case 0: case 1:
power->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING; power->bat_status =
break; POWER_SUPPLY_STATUS_CHARGING;
case 1: break;
power->bat_status = POWER_SUPPLY_STATUS_CHARGING; case 2:
break; power->bat_status =
case 2: POWER_SUPPLY_STATUS_DISCHARGING;
power->bat_status = POWER_SUPPLY_STATUS_DISCHARGING; break;
break; default:
default:
power->bat_status = POWER_SUPPLY_STATUS_UNKNOWN;
}
} else {
if (power->bat_present == 1)
status_changed = 1;
power->bat_present = 0;
power->bat_status = POWER_SUPPLY_STATUS_UNKNOWN; power->bat_status = POWER_SUPPLY_STATUS_UNKNOWN;
} }
power->bat_cap = res->plc[1]; } else {
if (status_changed) if (power->bat_present == 1)
power_supply_changed(&nvec_bat_psy); status_changed = 1;
break;
case VOLTAGE: power->bat_present = 0;
power->bat_voltage_now = res->plu * 1000; power->bat_status = POWER_SUPPLY_STATUS_UNKNOWN;
break; }
case TIME_REMAINING: power->bat_cap = res->plc[1];
power->time_remain = res->plu * 3600; if (status_changed)
break; power_supply_changed(&nvec_bat_psy);
case CURRENT: break;
power->bat_current_now = res->pls * 1000; case VOLTAGE:
break; power->bat_voltage_now = res->plu * 1000;
case AVERAGE_CURRENT: break;
power->bat_current_avg = res->pls * 1000; case TIME_REMAINING:
break; power->time_remain = res->plu * 3600;
case CAPACITY_REMAINING: break;
power->capacity_remain = res->plu * 1000; case CURRENT:
break; power->bat_current_now = res->pls * 1000;
case LAST_FULL_CHARGE_CAPACITY: break;
power->charge_last_full = res->plu * 1000; case AVERAGE_CURRENT:
break; power->bat_current_avg = res->pls * 1000;
case DESIGN_CAPACITY: break;
power->charge_full_design = res->plu * 1000; case CAPACITY_REMAINING:
break; power->capacity_remain = res->plu * 1000;
case CRITICAL_CAPACITY: break;
power->critical_capacity = res->plu * 1000; case LAST_FULL_CHARGE_CAPACITY:
break; power->charge_last_full = res->plu * 1000;
case TEMPERATURE: break;
power->bat_temperature = res->plu - 2732; case DESIGN_CAPACITY:
break; power->charge_full_design = res->plu * 1000;
case MANUFACTURER: break;
memcpy(power->bat_manu, &res->plc, res->length-2); case CRITICAL_CAPACITY:
power->bat_model[res->length-2] = '\0'; power->critical_capacity = res->plu * 1000;
break; break;
case MODEL: case TEMPERATURE:
memcpy(power->bat_model, &res->plc, res->length-2); power->bat_temperature = res->plu - 2732;
power->bat_model[res->length-2] = '\0'; break;
break; case MANUFACTURER:
case TYPE: memcpy(power->bat_manu, &res->plc, res->length - 2);
memcpy(power->bat_type, &res->plc, res->length-2); power->bat_model[res->length - 2] = '\0';
power->bat_type[res->length-2] = '\0'; break;
/* this differs a little from the spec case MODEL:
fill in more if you find some */ memcpy(power->bat_model, &res->plc, res->length - 2);
if (!strncmp(power->bat_type, "Li", 30)) power->bat_model[res->length - 2] = '\0';
power->bat_type_enum = POWER_SUPPLY_TECHNOLOGY_LION; break;
else case TYPE:
power->bat_type_enum = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; memcpy(power->bat_type, &res->plc, res->length - 2);
break; power->bat_type[res->length - 2] = '\0';
default: /* this differs a little from the spec
return NOTIFY_STOP; fill in more if you find some */
if (!strncmp(power->bat_type, "Li", 30))
power->bat_type_enum = POWER_SUPPLY_TECHNOLOGY_LION;
else
power->bat_type_enum = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
break;
default:
return NOTIFY_STOP;
} }
return NOTIFY_STOP; return NOTIFY_STOP;
} }
static int nvec_power_get_property(struct power_supply *psy, static int nvec_power_get_property(struct power_supply *psy,
enum power_supply_property psp, enum power_supply_property psp,
union power_supply_propval *val) union power_supply_propval *val)
{ {
struct nvec_power *power = dev_get_drvdata(psy->dev->parent); struct nvec_power *power = dev_get_drvdata(psy->dev->parent);
switch (psp) { switch (psp) {
...@@ -223,61 +235,60 @@ static int nvec_power_get_property(struct power_supply *psy, ...@@ -223,61 +235,60 @@ static int nvec_power_get_property(struct power_supply *psy,
} }
static int nvec_battery_get_property(struct power_supply *psy, static int nvec_battery_get_property(struct power_supply *psy,
enum power_supply_property psp, enum power_supply_property psp,
union power_supply_propval *val) union power_supply_propval *val)
{ {
struct nvec_power *power = dev_get_drvdata(psy->dev->parent); struct nvec_power *power = dev_get_drvdata(psy->dev->parent);
switch(psp) switch (psp) {
{ case POWER_SUPPLY_PROP_STATUS:
case POWER_SUPPLY_PROP_STATUS: val->intval = power->bat_status;
val->intval = power->bat_status; break;
break; case POWER_SUPPLY_PROP_CAPACITY:
case POWER_SUPPLY_PROP_CAPACITY: val->intval = power->bat_cap;
val->intval = power->bat_cap; break;
break; case POWER_SUPPLY_PROP_PRESENT:
case POWER_SUPPLY_PROP_PRESENT: val->intval = power->bat_present;
val->intval = power->bat_present; break;
break; case POWER_SUPPLY_PROP_VOLTAGE_NOW:
case POWER_SUPPLY_PROP_VOLTAGE_NOW: val->intval = power->bat_voltage_now;
val->intval = power->bat_voltage_now; break;
break; case POWER_SUPPLY_PROP_CURRENT_NOW:
case POWER_SUPPLY_PROP_CURRENT_NOW: val->intval = power->bat_current_now;
val->intval = power->bat_current_now; break;
break; case POWER_SUPPLY_PROP_CURRENT_AVG:
case POWER_SUPPLY_PROP_CURRENT_AVG: val->intval = power->bat_current_avg;
val->intval = power->bat_current_avg; break;
break; case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: val->intval = power->time_remain;
val->intval = power->time_remain; break;
break; case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: val->intval = power->charge_full_design;
val->intval = power->charge_full_design; break;
break; case POWER_SUPPLY_PROP_CHARGE_FULL:
case POWER_SUPPLY_PROP_CHARGE_FULL: val->intval = power->charge_last_full;
val->intval = power->charge_last_full; break;
break; case POWER_SUPPLY_PROP_CHARGE_EMPTY:
case POWER_SUPPLY_PROP_CHARGE_EMPTY: val->intval = power->critical_capacity;
val->intval = power->critical_capacity; break;
break; case POWER_SUPPLY_PROP_CHARGE_NOW:
case POWER_SUPPLY_PROP_CHARGE_NOW: val->intval = power->capacity_remain;
val->intval = power->capacity_remain; break;
break; case POWER_SUPPLY_PROP_TEMP:
case POWER_SUPPLY_PROP_TEMP: val->intval = power->bat_temperature;
val->intval = power->bat_temperature; break;
break; case POWER_SUPPLY_PROP_MANUFACTURER:
case POWER_SUPPLY_PROP_MANUFACTURER: val->strval = power->bat_manu;
val->strval = power->bat_manu; break;
break; case POWER_SUPPLY_PROP_MODEL_NAME:
case POWER_SUPPLY_PROP_MODEL_NAME: val->strval = power->bat_model;
val->strval = power->bat_model; break;
break; case POWER_SUPPLY_PROP_TECHNOLOGY:
case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = power->bat_type_enum;
val->intval = power->bat_type_enum; break;
break; default:
default: return -EINVAL;
return -EINVAL; }
}
return 0; return 0;
} }
...@@ -310,11 +321,11 @@ static char *nvec_power_supplied_to[] = { ...@@ -310,11 +321,11 @@ static char *nvec_power_supplied_to[] = {
}; };
static struct power_supply nvec_bat_psy = { static struct power_supply nvec_bat_psy = {
.name = "battery", .name = "battery",
.type = POWER_SUPPLY_TYPE_BATTERY, .type = POWER_SUPPLY_TYPE_BATTERY,
.properties = nvec_battery_props, .properties = nvec_battery_props,
.num_properties = ARRAY_SIZE(nvec_battery_props), .num_properties = ARRAY_SIZE(nvec_battery_props),
.get_property = nvec_battery_get_property, .get_property = nvec_battery_get_property,
}; };
static struct power_supply nvec_psy = { static struct power_supply nvec_psy = {
...@@ -327,9 +338,8 @@ static struct power_supply nvec_psy = { ...@@ -327,9 +338,8 @@ static struct power_supply nvec_psy = {
.get_property = nvec_power_get_property, .get_property = nvec_power_get_property,
}; };
static int counter = 0; static int counter;
static int const bat_iter[] = static int const bat_iter[] = {
{
SLOT_STATUS, VOLTAGE, CURRENT, CAPACITY_REMAINING, SLOT_STATUS, VOLTAGE, CURRENT, CAPACITY_REMAINING,
#ifdef EC_FULL_DIAG #ifdef EC_FULL_DIAG
AVERAGE_CURRENT, TEMPERATURE, TIME_REMAINING, AVERAGE_CURRENT, TEMPERATURE, TIME_REMAINING,
...@@ -340,7 +350,7 @@ static void nvec_power_poll(struct work_struct *work) ...@@ -340,7 +350,7 @@ static void nvec_power_poll(struct work_struct *work)
{ {
char buf[] = { '\x01', '\x00' }; char buf[] = { '\x01', '\x00' };
struct nvec_power *power = container_of(work, struct nvec_power, struct nvec_power *power = container_of(work, struct nvec_power,
poller.work); poller.work);
if (counter >= ARRAY_SIZE(bat_iter)) if (counter >= ARRAY_SIZE(bat_iter))
counter = 0; counter = 0;
...@@ -351,19 +361,18 @@ static void nvec_power_poll(struct work_struct *work) ...@@ -351,19 +361,18 @@ static void nvec_power_poll(struct work_struct *work)
/* select a battery request function via round robin /* select a battery request function via round robin
doing it all at once seems to overload the power supply */ doing it all at once seems to overload the power supply */
buf[0] = '\x02'; /* battery */ buf[0] = '\x02'; /* battery */
buf[1] = bat_iter[counter++]; buf[1] = bat_iter[counter++];
nvec_write_async(power->nvec, buf, 2); nvec_write_async(power->nvec, buf, 2);
// printk("%02x %02x\n", buf[0], buf[1]);
schedule_delayed_work(to_delayed_work(work), msecs_to_jiffies(5000)); schedule_delayed_work(to_delayed_work(work), msecs_to_jiffies(5000));
}; };
static int __devinit nvec_power_probe(struct platform_device *pdev) static int __devinit nvec_power_probe(struct platform_device *pdev)
{ {
struct power_supply *psy; struct power_supply *psy;
struct nvec_power *power = kzalloc(sizeof(struct nvec_power), GFP_NOWAIT); struct nvec_power *power =
kzalloc(sizeof(struct nvec_power), GFP_NOWAIT);
struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
dev_set_drvdata(&pdev->dev, power); dev_set_drvdata(&pdev->dev, power);
...@@ -381,7 +390,7 @@ static int __devinit nvec_power_probe(struct platform_device *pdev) ...@@ -381,7 +390,7 @@ static int __devinit nvec_power_probe(struct platform_device *pdev)
case BAT: case BAT:
psy = &nvec_bat_psy; psy = &nvec_bat_psy;
power->notifier.notifier_call = nvec_power_bat_notifier; power->notifier.notifier_call = nvec_power_bat_notifier;
break; break;
default: default:
kfree(power); kfree(power);
...@@ -398,14 +407,13 @@ static int __devinit nvec_power_probe(struct platform_device *pdev) ...@@ -398,14 +407,13 @@ static int __devinit nvec_power_probe(struct platform_device *pdev)
static struct platform_driver nvec_power_driver = { static struct platform_driver nvec_power_driver = {
.probe = nvec_power_probe, .probe = nvec_power_probe,
// .remove = __devexit_p(nvec_power_remove),
.driver = { .driver = {
.name = "nvec-power", .name = "nvec-power",
.owner = THIS_MODULE, .owner = THIS_MODULE,
} }
}; };
static int __init nvec_power_init(void) static int __init nvec_power_init(void)
{ {
return platform_driver_register(&nvec_power_driver); return platform_driver_register(&nvec_power_driver);
} }
......
/*
* nvec_ps2: mouse driver for a NVIDIA compliant embedded controller
*
* Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.launchpad.net>
*
* Authors: Pierre-Hugues Husson <phhusson@free.fr>
* Ilya Petrov <ilya.muromec@gmail.com>
* Marc Dietrich <marvin24@gmx.de>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
*/
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "nvec.h" #include "nvec.h"
#define START_STREAMING {'\x06','\x03','\x01'} #define START_STREAMING {'\x06', '\x03', '\x01'}
#define STOP_STREAMING {'\x06','\x04'} #define STOP_STREAMING {'\x06', '\x04'}
#define SEND_COMMAND {'\x06','\x01','\xf4','\x01'} #define SEND_COMMAND {'\x06', '\x01', '\xf4', '\x01'}
struct nvec_ps2 static const unsigned char MOUSE_RESET[] = {'\x06', '\x01', '\xff', '\x03'};
{
struct nvec_ps2 {
struct serio *ser_dev; struct serio *ser_dev;
struct notifier_block notifier; struct notifier_block notifier;
struct nvec_chip *nvec; struct nvec_chip *nvec;
...@@ -31,12 +48,6 @@ static void ps2_stopstreaming(struct serio *ser_dev) ...@@ -31,12 +48,6 @@ static void ps2_stopstreaming(struct serio *ser_dev)
nvec_write_async(ps2_dev.nvec, buf, sizeof(buf)); nvec_write_async(ps2_dev.nvec, buf, sizeof(buf));
} }
/* is this really needed?
static void nvec_resp_handler(unsigned char *data) {
serio_interrupt(ser_dev, data[4], 0);
}
*/
static int ps2_sendcommand(struct serio *ser_dev, unsigned char cmd) static int ps2_sendcommand(struct serio *ser_dev, unsigned char cmd)
{ {
unsigned char buf[] = SEND_COMMAND; unsigned char buf[] = SEND_COMMAND;
...@@ -50,47 +61,44 @@ static int ps2_sendcommand(struct serio *ser_dev, unsigned char cmd) ...@@ -50,47 +61,44 @@ static int ps2_sendcommand(struct serio *ser_dev, unsigned char cmd)
} }
static int nvec_ps2_notifier(struct notifier_block *nb, static int nvec_ps2_notifier(struct notifier_block *nb,
unsigned long event_type, void *data) unsigned long event_type, void *data)
{ {
int i; int i;
unsigned char *msg = (unsigned char *)data; unsigned char *msg = (unsigned char *)data;
switch (event_type) { switch (event_type) {
case NVEC_PS2_EVT: case NVEC_PS2_EVT:
serio_interrupt(ps2_dev.ser_dev, msg[2], 0); serio_interrupt(ps2_dev.ser_dev, msg[2], 0);
return NOTIFY_STOP; return NOTIFY_STOP;
case NVEC_PS2: case NVEC_PS2:
if (msg[2] == 1) if (msg[2] == 1)
for(i = 0; i < (msg[1] - 2); i++) for (i = 0; i < (msg[1] - 2); i++)
serio_interrupt(ps2_dev.ser_dev, msg[i+4], 0); serio_interrupt(ps2_dev.ser_dev, msg[i + 4], 0);
else if (msg[1] != 2) /* !ack */ else if (msg[1] != 2) { /* !ack */
{ print_hex_dump(KERN_WARNING, "unhandled mouse event: ",
printk("nvec_ps2: unhandled mouse event "); DUMP_PREFIX_NONE, 16, 1,
for(i = 0; i <= (msg[1]+1); i++) msg, msg[1] + 2, true);
printk("%02x ", msg[i]); }
printk(".\n");
} return NOTIFY_STOP;
return NOTIFY_STOP;
} }
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static int __devinit nvec_mouse_probe(struct platform_device *pdev) static int __devinit nvec_mouse_probe(struct platform_device *pdev)
{ {
struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
struct serio *ser_dev = kzalloc(sizeof(struct serio), GFP_KERNEL); struct serio *ser_dev = kzalloc(sizeof(struct serio), GFP_KERNEL);
ser_dev->id.type=SERIO_8042; ser_dev->id.type = SERIO_8042;
ser_dev->write=ps2_sendcommand; ser_dev->write = ps2_sendcommand;
ser_dev->open=ps2_startstreaming; ser_dev->open = ps2_startstreaming;
ser_dev->close=ps2_stopstreaming; ser_dev->close = ps2_stopstreaming;
strlcpy(ser_dev->name, "NVEC PS2", sizeof(ser_dev->name)); strlcpy(ser_dev->name, "nvec mouse", sizeof(ser_dev->name));
strlcpy(ser_dev->phys, "NVEC I2C slave", sizeof(ser_dev->phys)); strlcpy(ser_dev->phys, "nvec", sizeof(ser_dev->phys));
ps2_dev.ser_dev = ser_dev; ps2_dev.ser_dev = ser_dev;
ps2_dev.notifier.notifier_call = nvec_ps2_notifier; ps2_dev.notifier.notifier_call = nvec_ps2_notifier;
...@@ -100,16 +108,16 @@ static int __devinit nvec_mouse_probe(struct platform_device *pdev) ...@@ -100,16 +108,16 @@ static int __devinit nvec_mouse_probe(struct platform_device *pdev)
serio_register_port(ser_dev); serio_register_port(ser_dev);
/* mouse reset */ /* mouse reset */
nvec_write_async(nvec, "\x06\x01\xff\x03", 4); nvec_write_async(nvec, MOUSE_RESET, 4);
return 0; return 0;
} }
static struct platform_driver nvec_mouse_driver = { static struct platform_driver nvec_mouse_driver = {
.probe = nvec_mouse_probe, .probe = nvec_mouse_probe,
.driver = { .driver = {
.name = "nvec-mouse", .name = "nvec-mouse",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
}; };
...@@ -119,3 +127,7 @@ static int __init nvec_mouse_init(void) ...@@ -119,3 +127,7 @@ static int __init nvec_mouse_init(void)
} }
module_init(nvec_mouse_init); module_init(nvec_mouse_init);
MODULE_DESCRIPTION("NVEC mouse driver");
MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>");
MODULE_LICENSE("GPL");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment