diff options
Diffstat (limited to 'drivers/staging/nvec')
| -rw-r--r-- | drivers/staging/nvec/Kconfig | 13 | ||||
| -rw-r--r-- | drivers/staging/nvec/TODO | 4 | ||||
| -rw-r--r-- | drivers/staging/nvec/nvec.c | 200 | ||||
| -rw-r--r-- | drivers/staging/nvec/nvec.h | 40 | ||||
| -rw-r--r-- | drivers/staging/nvec/nvec_kbd.c | 66 | ||||
| -rw-r--r-- | drivers/staging/nvec/nvec_paz00.c | 6 | ||||
| -rw-r--r-- | drivers/staging/nvec/nvec_power.c | 15 | ||||
| -rw-r--r-- | drivers/staging/nvec/nvec_ps2.c | 49 |
8 files changed, 228 insertions, 165 deletions
diff --git a/drivers/staging/nvec/Kconfig b/drivers/staging/nvec/Kconfig index 1235a7897d0..9475e20c3d6 100644 --- a/drivers/staging/nvec/Kconfig +++ b/drivers/staging/nvec/Kconfig @@ -1,33 +1,34 @@ config MFD_NVEC - bool "NV Tegra Embedded Controller SMBus Interface" + tristate "NV Tegra Embedded Controller SMBus Interface" depends on I2C && GPIOLIB && ARCH_TEGRA + select MFD_CORE help Say Y here to enable support for a nVidia compliant embedded controller. config KEYBOARD_NVEC - bool "Keyboard on nVidia compliant EC" + tristate "Keyboard on nVidia compliant EC" depends on MFD_NVEC && INPUT help - Say Y here to enable support for a keyboard connected to + Say Y here to enable support for a keyboard connected to a nVidia compliant embedded controller. config SERIO_NVEC_PS2 - bool "PS2 on nVidia EC" + tristate "PS2 on nVidia EC" depends on MFD_NVEC && SERIO help Say Y here to enable support for a Touchpad / Mouse connected to a nVidia compliant embedded controller. config NVEC_POWER - bool "NVEC charger and battery" + tristate "NVEC charger and battery" depends on MFD_NVEC && POWER_SUPPLY help Say Y to enable support for battery and charger interface for nVidia compliant embedded controllers. config NVEC_PAZ00 - bool "Support for OEM specific functions on Compal PAZ00 based devices" + tristate "Support for OEM specific functions on Compal PAZ00 based devices" depends on MFD_NVEC && LEDS_CLASS help Say Y to enable control of the yellow side leds on Compal PAZ00 based diff --git a/drivers/staging/nvec/TODO b/drivers/staging/nvec/TODO index f950ab890e2..e5ae42a0b44 100644 --- a/drivers/staging/nvec/TODO +++ b/drivers/staging/nvec/TODO @@ -1,9 +1,5 @@ ToDo list (incomplete, unordered) - add compile as module support - - fix clk usage - 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 - the device specific name if it has multiple clocks. - move half of the nvec init stuff to i2c-tegra.c - move event handling to nvec_events - finish suspend/resume support diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 094fdc366f3..90f1c4d7fa8 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -33,14 +33,10 @@ #include <linux/mfd/core.h> #include <linux/mutex.h> #include <linux/notifier.h> -#include <linux/platform_device.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/workqueue.h> -#include <mach/clk.h> -#include <mach/iomap.h> - #include "nvec.h" #define I2C_CNFG 0x00 @@ -73,13 +69,20 @@ enum nvec_msg_category { NVEC_MSG_TX, }; -static const unsigned char EC_DISABLE_EVENT_REPORTING[3] = "\x04\x00\x00"; -static const unsigned char EC_ENABLE_EVENT_REPORTING[3] = "\x04\x00\x01"; -static const unsigned char EC_GET_FIRMWARE_VERSION[2] = "\x07\x15"; +enum nvec_sleep_subcmds { + GLOBAL_EVENTS, + AP_PWR_DOWN, + AP_SUSPEND, +}; + +#define CNF_EVENT_REPORTING 0x01 +#define GET_FIRMWARE_VERSION 0x15 +#define LID_SWITCH BIT(1) +#define PWR_BUTTON BIT(15) static struct nvec_chip *nvec_power_handle; -static struct mfd_cell nvec_devices[] = { +static const struct mfd_cell nvec_devices[] = { { .name = "nvec-kbd", .id = 1, @@ -119,6 +122,20 @@ int nvec_register_notifier(struct nvec_chip *nvec, struct notifier_block *nb, EXPORT_SYMBOL_GPL(nvec_register_notifier); /** + * nvec_unregister_notifier - Unregister a notifier with nvec + * @nvec: A &struct nvec_chip + * @nb: The notifier block to unregister + * + * Unregisters a notifier with @nvec. The notifier will be removed from the + * atomic notifier chain. + */ +int nvec_unregister_notifier(struct nvec_chip *nvec, struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&nvec->notifier_list, nb); +} +EXPORT_SYMBOL_GPL(nvec_unregister_notifier); + +/** * nvec_status_notifier - The final notifier * * Prints a message about control events not handled in the notifier @@ -180,7 +197,7 @@ static struct nvec_msg *nvec_msg_alloc(struct nvec_chip *nvec, * * Free the given message */ -inline void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg) +void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg) { if (msg != &nvec->tx_scratch) dev_vdbg(nvec->dev, "INFO: Free %ti\n", msg - nvec->msg_pool); @@ -319,6 +336,41 @@ struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec, EXPORT_SYMBOL(nvec_write_sync); /** + * nvec_toggle_global_events - enables or disables global event reporting + * @nvec: nvec handle + * @state: true for enable, false for disable + * + * This switches on/off global event reports by the embedded controller. + */ +static void nvec_toggle_global_events(struct nvec_chip *nvec, bool state) +{ + unsigned char global_events[] = { NVEC_SLEEP, GLOBAL_EVENTS, state }; + + nvec_write_async(nvec, global_events, 3); +} + +/** + * nvec_event_mask - fill the command string with event bitfield + * ev: points to event command string + * mask: bit to insert into the event mask + * + * Configure event command expects a 32 bit bitfield which describes + * which events to enable. The bitfield has the following structure + * (from highest byte to lowest): + * system state bits 7-0 + * system state bits 15-8 + * oem system state bits 7-0 + * oem system state bits 15-8 + */ +static void nvec_event_mask(char *ev, u32 mask) +{ + ev[3] = mask >> 16 & 0xff; + ev[4] = mask >> 24 & 0xff; + ev[5] = mask >> 0 & 0xff; + ev[6] = mask >> 8 & 0xff; +} + +/** * nvec_request_master - Process outgoing messages * @work: A &struct work_struct (the tx_worker member of &struct nvec_chip) * @@ -626,9 +678,9 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) nvec->rx->data[nvec->rx->pos++] = received; else dev_err(nvec->dev, - "RX buffer overflow on %p: " - "Trying to write byte %u of %u\n", - nvec->rx, nvec->rx->pos, NVEC_MSG_SIZE); + "RX buffer overflow on %p: Trying to write byte %u of %u\n", + nvec->rx, nvec->rx ? nvec->rx->pos : 0, + NVEC_MSG_SIZE); break; default: nvec->state = 0; @@ -680,9 +732,9 @@ static void tegra_init_i2c_slave(struct nvec_chip *nvec) clk_prepare_enable(nvec->i2c_clk); - tegra_periph_reset_assert(nvec->i2c_clk); + reset_control_assert(nvec->rst); udelay(2); - tegra_periph_reset_deassert(nvec->i2c_clk); + reset_control_deassert(nvec->rst); val = I2C_CNFG_NEW_MASTER_SFM | I2C_CNFG_PACKET_MODE_EN | (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT); @@ -697,8 +749,6 @@ static void tegra_init_i2c_slave(struct nvec_chip *nvec) writel(0, nvec->base + I2C_SL_ADDR2); enable_irq(nvec->irq); - - clk_disable_unprepare(nvec->i2c_clk); } #ifdef CONFIG_PM_SLEEP @@ -712,19 +762,49 @@ static void nvec_disable_i2c_slave(struct nvec_chip *nvec) static void nvec_power_off(void) { - nvec_write_async(nvec_power_handle, EC_DISABLE_EVENT_REPORTING, 3); - nvec_write_async(nvec_power_handle, "\x04\x01", 2); + char ap_pwr_down[] = { NVEC_SLEEP, AP_PWR_DOWN }; + + nvec_toggle_global_events(nvec_power_handle, false); + nvec_write_async(nvec_power_handle, ap_pwr_down, 2); } -static int __devinit tegra_nvec_probe(struct platform_device *pdev) +/* + * Parse common device tree data + */ +static int nvec_i2c_parse_dt_pdata(struct nvec_chip *nvec) +{ + nvec->gpio = of_get_named_gpio(nvec->dev->of_node, "request-gpios", 0); + + if (nvec->gpio < 0) { + dev_err(nvec->dev, "no gpio specified"); + return -ENODEV; + } + + if (of_property_read_u32(nvec->dev->of_node, "slave-addr", + &nvec->i2c_addr)) { + dev_err(nvec->dev, "no i2c address specified"); + return -ENODEV; + } + + return 0; +} + +static int tegra_nvec_probe(struct platform_device *pdev) { int err, ret; struct clk *i2c_clk; - struct nvec_platform_data *pdata = pdev->dev.platform_data; struct nvec_chip *nvec; struct nvec_msg *msg; struct resource *res; void __iomem *base; + char get_firmware_version[] = { NVEC_CNTL, GET_FIRMWARE_VERSION }, + unmute_speakers[] = { NVEC_OEM0, 0x10, 0x59, 0x95 }, + enable_event[7] = { NVEC_SYS, CNF_EVENT_REPORTING, true }; + + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, "must be instantiated using device tree\n"); + return -ENODEV; + } nvec = devm_kzalloc(&pdev->dev, sizeof(struct nvec_chip), GFP_KERNEL); if (nvec == NULL) { @@ -734,37 +814,14 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) platform_set_drvdata(pdev, nvec); nvec->dev = &pdev->dev; - if (pdata) { - nvec->gpio = pdata->gpio; - nvec->i2c_addr = pdata->i2c_addr; - } else if (nvec->dev->of_node) { - nvec->gpio = of_get_named_gpio(nvec->dev->of_node, - "request-gpios", 0); - if (nvec->gpio < 0) { - dev_err(&pdev->dev, "no gpio specified"); - return -ENODEV; - } - if (of_property_read_u32(nvec->dev->of_node, - "slave-addr", &nvec->i2c_addr)) { - dev_err(&pdev->dev, "no i2c address specified"); - return -ENODEV; - } - } else { - dev_err(&pdev->dev, "no platform data\n"); - return -ENODEV; - } + err = nvec_i2c_parse_dt_pdata(nvec); + if (err < 0) + return err; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no mem resource?\n"); - return -ENODEV; - } - - base = devm_request_and_ioremap(&pdev->dev, res); - if (!base) { - dev_err(&pdev->dev, "Can't ioremap I2C region\n"); - return -ENOMEM; - } + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { @@ -772,12 +829,18 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) return -ENODEV; } - i2c_clk = clk_get_sys("tegra-i2c.2", "div-clk"); + i2c_clk = devm_clk_get(&pdev->dev, "div-clk"); if (IS_ERR(i2c_clk)) { dev_err(nvec->dev, "failed to get controller clock\n"); return -ENODEV; } + nvec->rst = devm_reset_control_get(&pdev->dev, "i2c"); + if (IS_ERR(nvec->rst)) { + dev_err(nvec->dev, "failed to get controller reset\n"); + return PTR_ERR(nvec->rst); + } + nvec->base = base; nvec->irq = res->start; nvec->i2c_clk = i2c_clk; @@ -812,12 +875,8 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) tegra_init_i2c_slave(nvec); - clk_prepare_enable(i2c_clk); - - /* enable event reporting */ - nvec_write_async(nvec, EC_ENABLE_EVENT_REPORTING, - sizeof(EC_ENABLE_EVENT_REPORTING)); + nvec_toggle_global_events(nvec, true); nvec->nvec_status_notifier.notifier_call = nvec_status_notifier; nvec_register_notifier(nvec, &nvec->nvec_status_notifier, 0); @@ -826,8 +885,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) pm_power_off = nvec_power_off; /* Get Firmware Version */ - msg = nvec_write_sync(nvec, EC_GET_FIRMWARE_VERSION, - sizeof(EC_GET_FIRMWARE_VERSION)); + msg = nvec_write_sync(nvec, get_firmware_version, 2); if (msg) { dev_warn(nvec->dev, "ec firmware version %02x.%02x.%02x / %02x\n", @@ -842,25 +900,30 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) dev_err(nvec->dev, "error adding subdevices\n"); /* unmute speakers? */ - nvec_write_async(nvec, "\x0d\x10\x59\x95", 4); + nvec_write_async(nvec, unmute_speakers, 4); /* enable lid switch event */ - nvec_write_async(nvec, "\x01\x01\x01\x00\x00\x02\x00", 7); + nvec_event_mask(enable_event, LID_SWITCH); + nvec_write_async(nvec, enable_event, 7); /* enable power button event */ - nvec_write_async(nvec, "\x01\x01\x01\x00\x00\x80\x00", 7); + nvec_event_mask(enable_event, PWR_BUTTON); + nvec_write_async(nvec, enable_event, 7); return 0; } -static int __devexit tegra_nvec_remove(struct platform_device *pdev) +static int tegra_nvec_remove(struct platform_device *pdev) { struct nvec_chip *nvec = platform_get_drvdata(pdev); - nvec_write_async(nvec, EC_DISABLE_EVENT_REPORTING, 3); + nvec_toggle_global_events(nvec, false); mfd_remove_devices(nvec->dev); + nvec_unregister_notifier(nvec, &nvec->nvec_status_notifier); cancel_work_sync(&nvec->rx_work); cancel_work_sync(&nvec->tx_work); + /* FIXME: needs check wether nvec is responsible for power off */ + pm_power_off = NULL; return 0; } @@ -871,13 +934,14 @@ static int nvec_suspend(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct nvec_chip *nvec = platform_get_drvdata(pdev); struct nvec_msg *msg; + char ap_suspend[] = { NVEC_SLEEP, AP_SUSPEND }; dev_dbg(nvec->dev, "suspending\n"); /* keep these sync or you'll break suspend */ - msg = nvec_write_sync(nvec, EC_DISABLE_EVENT_REPORTING, 3); - nvec_msg_free(nvec, msg); - msg = nvec_write_sync(nvec, "\x04\x02", 2); + nvec_toggle_global_events(nvec, false); + + msg = nvec_write_sync(nvec, ap_suspend, sizeof(ap_suspend)); nvec_msg_free(nvec, msg); nvec_disable_i2c_slave(nvec); @@ -892,7 +956,7 @@ static int nvec_resume(struct device *dev) dev_dbg(nvec->dev, "resuming\n"); tegra_init_i2c_slave(nvec); - nvec_write_async(nvec, EC_ENABLE_EVENT_REPORTING, 3); + nvec_toggle_global_events(nvec, true); return 0; } @@ -901,7 +965,7 @@ static int nvec_resume(struct device *dev) static const SIMPLE_DEV_PM_OPS(nvec_pm_ops, nvec_suspend, nvec_resume); /* Match table for of_platform binding */ -static const struct of_device_id nvidia_nvec_of_match[] __devinitconst = { +static const struct of_device_id nvidia_nvec_of_match[] = { { .compatible = "nvidia,nvec", }, {}, }; @@ -909,7 +973,7 @@ MODULE_DEVICE_TABLE(of, nvidia_nvec_of_match); static struct platform_driver nvec_device_driver = { .probe = tegra_nvec_probe, - .remove = __devexit_p(tegra_nvec_remove), + .remove = tegra_nvec_remove, .driver = { .name = "nvec", .owner = THIS_MODULE, diff --git a/drivers/staging/nvec/nvec.h b/drivers/staging/nvec/nvec.h index ba6ed8f4e8a..e271375053f 100644 --- a/drivers/staging/nvec/nvec.h +++ b/drivers/staging/nvec/nvec.h @@ -23,6 +23,7 @@ #include <linux/list.h> #include <linux/mutex.h> #include <linux/notifier.h> +#include <linux/reset.h> #include <linux/spinlock.h> #include <linux/workqueue.h> @@ -71,9 +72,12 @@ enum nvec_event_size { enum nvec_msg_type { NVEC_SYS = 1, NVEC_BAT, - NVEC_KBD = 5, + NVEC_GPIO, + NVEC_SLEEP, + NVEC_KBD, NVEC_PS2, NVEC_CNTL, + NVEC_OEM0 = 0x0d, NVEC_KB_EVT = 0x80, NVEC_PS2_EVT, }; @@ -100,38 +104,14 @@ struct nvec_msg { }; /** - * struct nvec_subdev - A subdevice of nvec, such as nvec_kbd - * @name: The name of the sub device - * @platform_data: Platform data - * @id: Identifier of the sub device - */ -struct nvec_subdev { - const char *name; - void *platform_data; - int id; -}; - -/** - * struct nvec_platform_data - platform data for a tegra slave controller - * @i2c_addr: number of i2c slave adapter the ec is connected to - * @gpio: gpio number for the ec request line - * - * Platform data, to be used in board definitions. For an example, take a - * look at the paz00 board in arch/arm/mach-tegra/board-paz00.c - */ -struct nvec_platform_data { - int i2c_addr; - int gpio; -}; - -/** * struct nvec_chip - A single connection to an NVIDIA Embedded controller * @dev: The device * @gpio: The same as for &struct nvec_platform_data * @irq: The IRQ of the I2C device * @i2c_addr: The address of the I2C slave * @base: The base of the memory mapped region of the I2C device - * @clk: The clock of the I2C device + * @i2c_clk: The clock of the I2C device + * @rst: The reset of the I2C device * @notifier_list: Notifiers to be called on received messages, see * nvec_register_notifier() * @rx_data: Received messages that have to be processed @@ -161,6 +141,7 @@ struct nvec_chip { int i2c_addr; void __iomem *base; struct clk *i2c_clk; + struct reset_control *rst; struct atomic_notifier_head notifier_list; struct list_head rx_data, tx_data; struct notifier_block nvec_status_notifier; @@ -194,9 +175,8 @@ extern int nvec_register_notifier(struct nvec_chip *nvec, struct notifier_block *nb, unsigned int events); -extern int nvec_unregister_notifier(struct device *dev, - struct notifier_block *nb, - unsigned int events); +extern int nvec_unregister_notifier(struct nvec_chip *dev, + struct notifier_block *nb); extern void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg); diff --git a/drivers/staging/nvec/nvec_kbd.c b/drivers/staging/nvec/nvec_kbd.c index 6cc30dcd830..c17a1c3eb3c 100644 --- a/drivers/staging/nvec/nvec_kbd.c +++ b/drivers/staging/nvec/nvec_kbd.c @@ -21,10 +21,14 @@ #include "nvec-keytable.h" #include "nvec.h" -#define ACK_KBD_EVENT {'\x05', '\xed', '\x01'} +enum kbd_subcmds { + CNFG_WAKE = 3, + CNFG_WAKE_KEY_REPORTING, + SET_LEDS = 0xed, + ENABLE_KBD = 0xf4, + DISABLE_KBD, +}; -static const char led_on[3] = "\x05\xed\x07"; -static const char led_off[3] = "\x05\xed\x00"; static unsigned char keycodes[ARRAY_SIZE(code_tab_102us) + ARRAY_SIZE(extcode_tab_us102)]; @@ -39,12 +43,15 @@ static struct nvec_keys keys_dev; static void nvec_kbd_toggle_led(void) { + char buf[] = { NVEC_KBD, SET_LEDS, 0 }; + keys_dev.caps_lock = !keys_dev.caps_lock; if (keys_dev.caps_lock) - nvec_write_async(keys_dev.nvec, led_on, sizeof(led_on)); - else - nvec_write_async(keys_dev.nvec, led_off, sizeof(led_off)); + /* should be BIT(0) only, firmware bug? */ + buf[2] = BIT(0) | BIT(1) | BIT(2); + + nvec_write_async(keys_dev.nvec, buf, sizeof(buf)); } static int nvec_keys_notifier(struct notifier_block *nb, @@ -82,8 +89,8 @@ static int nvec_keys_notifier(struct notifier_block *nb, static int nvec_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - unsigned char buf[] = ACK_KBD_EVENT; struct nvec_chip *nvec = keys_dev.nvec; + char buf[] = { NVEC_KBD, SET_LEDS, 0 }; if (type == EV_REP) return 0; @@ -100,11 +107,16 @@ static int nvec_kbd_event(struct input_dev *dev, unsigned int type, return 0; } -static int __devinit nvec_kbd_probe(struct platform_device *pdev) +static int nvec_kbd_probe(struct platform_device *pdev) { struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); int i, j, err; struct input_dev *idev; + char clear_leds[] = { NVEC_KBD, SET_LEDS, 0 }, + enable_kbd[] = { NVEC_KBD, ENABLE_KBD }, + cnfg_wake[] = { NVEC_KBD, CNFG_WAKE, true, true }, + cnfg_wake_key_reporting[] = { NVEC_KBD, CNFG_WAKE_KEY_REPORTING, + true }; j = 0; @@ -114,7 +126,7 @@ static int __devinit nvec_kbd_probe(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(extcode_tab_us102); ++i) keycodes[j++] = extcode_tab_us102[i]; - idev = input_allocate_device(); + idev = devm_input_allocate_device(&pdev->dev); idev->name = "nvec keyboard"; idev->phys = "nvec"; idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_LED); @@ -130,7 +142,7 @@ static int __devinit nvec_kbd_probe(struct platform_device *pdev) clear_bit(0, idev->keybit); err = input_register_device(idev); if (err) - goto fail; + return err; keys_dev.input = idev; keys_dev.notifier.notifier_call = nvec_keys_notifier; @@ -138,38 +150,35 @@ static int __devinit nvec_kbd_probe(struct platform_device *pdev) nvec_register_notifier(nvec, &keys_dev.notifier, 0); /* Enable keyboard */ - nvec_write_async(nvec, "\x05\xf4", 2); + nvec_write_async(nvec, enable_kbd, 2); - /* keyboard reset? */ - nvec_write_async(nvec, "\x05\x03\x01\x01", 4); - nvec_write_async(nvec, "\x05\x04\x01", 3); - nvec_write_async(nvec, "\x06\x01\xff\x03", 4); -/* FIXME - wait until keyboard reset is finished - or until we have a sync write */ - mdelay(1000); + /* configures wake on special keys */ + nvec_write_async(nvec, cnfg_wake, 4); + /* enable wake key reporting */ + nvec_write_async(nvec, cnfg_wake_key_reporting, 3); /* Disable caps lock LED */ - nvec_write_async(nvec, led_off, sizeof(led_off)); + nvec_write_async(nvec, clear_leds, sizeof(clear_leds)); return 0; - -fail: - input_free_device(idev); - return err; } -static int __devexit nvec_kbd_remove(struct platform_device *pdev) +static int nvec_kbd_remove(struct platform_device *pdev) { - input_unregister_device(keys_dev.input); - input_free_device(keys_dev.input); + struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); + char disable_kbd[] = { NVEC_KBD, DISABLE_KBD }, + uncnfg_wake_key_reporting[] = { NVEC_KBD, CNFG_WAKE_KEY_REPORTING, + false }; + nvec_write_async(nvec, uncnfg_wake_key_reporting, 3); + nvec_write_async(nvec, disable_kbd, 2); + nvec_unregister_notifier(nvec, &keys_dev.notifier); return 0; } static struct platform_driver nvec_kbd_driver = { .probe = nvec_kbd_probe, - .remove = __devexit_p(nvec_kbd_remove), + .remove = nvec_kbd_remove, .driver = { .name = "nvec-kbd", .owner = THIS_MODULE, @@ -180,4 +189,5 @@ module_platform_driver(nvec_kbd_driver); MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>"); MODULE_DESCRIPTION("NVEC keyboard driver"); +MODULE_ALIAS("platform:nvec-kbd"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/nvec/nvec_paz00.c b/drivers/staging/nvec/nvec_paz00.c index b747e39ff94..934b796222a 100644 --- a/drivers/staging/nvec/nvec_paz00.c +++ b/drivers/staging/nvec/nvec_paz00.c @@ -43,7 +43,7 @@ static void nvec_led_brightness_set(struct led_classdev *led_cdev, } -static int __devinit nvec_paz00_probe(struct platform_device *pdev) +static int nvec_paz00_probe(struct platform_device *pdev) { struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); struct nvec_led *led; @@ -72,7 +72,7 @@ static int __devinit nvec_paz00_probe(struct platform_device *pdev) return 0; } -static int __devexit nvec_paz00_remove(struct platform_device *pdev) +static int nvec_paz00_remove(struct platform_device *pdev) { struct nvec_led *led = platform_get_drvdata(pdev); @@ -83,7 +83,7 @@ static int __devexit nvec_paz00_remove(struct platform_device *pdev) static struct platform_driver nvec_paz00_driver = { .probe = nvec_paz00_probe, - .remove = __devexit_p(nvec_paz00_remove), + .remove = nvec_paz00_remove, .driver = { .name = "nvec-paz00", .owner = THIS_MODULE, diff --git a/drivers/staging/nvec/nvec_power.c b/drivers/staging/nvec/nvec_power.c index cc8ccd75e7f..aacfcd6954a 100644 --- a/drivers/staging/nvec/nvec_power.c +++ b/drivers/staging/nvec/nvec_power.c @@ -22,6 +22,8 @@ #include "nvec.h" +#define GET_SYSTEM_STATUS 0x00 + struct nvec_power { struct notifier_block notifier; struct delayed_work poller; @@ -111,7 +113,7 @@ static const int bat_init[] = { static void get_bat_mfg_data(struct nvec_power *power) { int i; - char buf[] = { '\x02', '\x00' }; + char buf[] = { NVEC_BAT, SLOT_STATUS }; for (i = 0; i < ARRAY_SIZE(bat_init); i++) { buf[1] = bat_init[i]; @@ -348,7 +350,7 @@ static int const bat_iter[] = { static void nvec_power_poll(struct work_struct *work) { - char buf[] = { '\x01', '\x00' }; + char buf[] = { NVEC_SYS, GET_SYSTEM_STATUS }; struct nvec_power *power = container_of(work, struct nvec_power, poller.work); @@ -361,14 +363,14 @@ static void nvec_power_poll(struct work_struct *work) /* select a battery request function via round robin doing it all at once seems to overload the power supply */ - buf[0] = '\x02'; /* battery */ + buf[0] = NVEC_BAT; buf[1] = bat_iter[counter++]; nvec_write_async(power->nvec, buf, 2); schedule_delayed_work(to_delayed_work(work), msecs_to_jiffies(5000)); }; -static int __devinit nvec_power_probe(struct platform_device *pdev) +static int nvec_power_probe(struct platform_device *pdev) { struct power_supply *psy; struct nvec_power *power; @@ -407,11 +409,12 @@ static int __devinit nvec_power_probe(struct platform_device *pdev) return power_supply_register(&pdev->dev, psy); } -static int __devexit nvec_power_remove(struct platform_device *pdev) +static int nvec_power_remove(struct platform_device *pdev) { struct nvec_power *power = platform_get_drvdata(pdev); cancel_delayed_work_sync(&power->poller); + nvec_unregister_notifier(power->nvec, &power->notifier); switch (pdev->id) { case AC: power_supply_unregister(&nvec_psy); @@ -425,7 +428,7 @@ static int __devexit nvec_power_remove(struct platform_device *pdev) static struct platform_driver nvec_power_driver = { .probe = nvec_power_probe, - .remove = __devexit_p(nvec_power_remove), + .remove = nvec_power_remove, .driver = { .name = "nvec-power", .owner = THIS_MODULE, diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c index d7c65110213..45b2f1308e0 100644 --- a/drivers/staging/nvec/nvec_ps2.c +++ b/drivers/staging/nvec/nvec_ps2.c @@ -21,9 +21,11 @@ #include "nvec.h" -#define START_STREAMING {'\x06', '\x03', '\x06'} -#define STOP_STREAMING {'\x06', '\x04'} -#define SEND_COMMAND {'\x06', '\x01', '\xf4', '\x01'} +#define PACKET_SIZE 6 + +#define ENABLE_MOUSE 0xf4 +#define DISABLE_MOUSE 0xf5 +#define PSMOUSE_RST 0xff #ifdef NVEC_PS2_DEBUG #define NVEC_PHD(str, buf, len) \ @@ -33,7 +35,12 @@ #define NVEC_PHD(str, buf, len) #endif -static const unsigned char MOUSE_RESET[] = {'\x06', '\x01', '\xff', '\x03'}; +enum ps2_subcmds { + SEND_COMMAND = 1, + RECEIVE_N, + AUTO_RECEIVE_N, + CANCEL_AUTO_RECEIVE, +}; struct nvec_ps2 { struct serio *ser_dev; @@ -45,19 +52,19 @@ static struct nvec_ps2 ps2_dev; static int ps2_startstreaming(struct serio *ser_dev) { - unsigned char buf[] = START_STREAMING; + unsigned char buf[] = { NVEC_PS2, AUTO_RECEIVE_N, PACKET_SIZE }; return nvec_write_async(ps2_dev.nvec, buf, sizeof(buf)); } static void ps2_stopstreaming(struct serio *ser_dev) { - unsigned char buf[] = STOP_STREAMING; + unsigned char buf[] = { NVEC_PS2, CANCEL_AUTO_RECEIVE }; nvec_write_async(ps2_dev.nvec, buf, sizeof(buf)); } static int ps2_sendcommand(struct serio *ser_dev, unsigned char cmd) { - unsigned char buf[] = SEND_COMMAND; + unsigned char buf[] = { NVEC_PS2, SEND_COMMAND, ENABLE_MOUSE, 1 }; buf[2] = cmd & 0xff; @@ -93,10 +100,11 @@ static int nvec_ps2_notifier(struct notifier_block *nb, return NOTIFY_DONE; } -static int __devinit nvec_mouse_probe(struct platform_device *pdev) +static int nvec_mouse_probe(struct platform_device *pdev) { struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); struct serio *ser_dev; + char mouse_reset[] = { NVEC_PS2, SEND_COMMAND, PSMOUSE_RST, 3 }; ser_dev = devm_kzalloc(&pdev->dev, sizeof(struct serio), GFP_KERNEL); if (ser_dev == NULL) @@ -118,13 +126,18 @@ static int __devinit nvec_mouse_probe(struct platform_device *pdev) serio_register_port(ser_dev); /* mouse reset */ - nvec_write_async(nvec, MOUSE_RESET, 4); + nvec_write_async(nvec, mouse_reset, sizeof(mouse_reset)); return 0; } -static int __devexit nvec_mouse_remove(struct platform_device *pdev) +static int nvec_mouse_remove(struct platform_device *pdev) { + struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); + + ps2_sendcommand(ps2_dev.ser_dev, DISABLE_MOUSE); + ps2_stopstreaming(ps2_dev.ser_dev); + nvec_unregister_notifier(nvec, &ps2_dev.notifier); serio_unregister_port(ps2_dev.ser_dev); return 0; @@ -133,27 +146,22 @@ static int __devexit nvec_mouse_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int nvec_mouse_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); - /* disable mouse */ - nvec_write_async(nvec, "\x06\xf4", 2); + ps2_sendcommand(ps2_dev.ser_dev, DISABLE_MOUSE); /* send cancel autoreceive */ - nvec_write_async(nvec, "\x06\x04", 2); + ps2_stopstreaming(ps2_dev.ser_dev); return 0; } static int nvec_mouse_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); - + /* start streaming */ ps2_startstreaming(ps2_dev.ser_dev); /* enable mouse */ - nvec_write_async(nvec, "\x06\xf5", 2); + ps2_sendcommand(ps2_dev.ser_dev, ENABLE_MOUSE); return 0; } @@ -164,7 +172,7 @@ static const SIMPLE_DEV_PM_OPS(nvec_mouse_pm_ops, nvec_mouse_suspend, static struct platform_driver nvec_mouse_driver = { .probe = nvec_mouse_probe, - .remove = __devexit_p(nvec_mouse_remove), + .remove = nvec_mouse_remove, .driver = { .name = "nvec-mouse", .owner = THIS_MODULE, @@ -176,4 +184,5 @@ module_platform_driver(nvec_mouse_driver); MODULE_DESCRIPTION("NVEC mouse driver"); MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>"); +MODULE_ALIAS("platform:nvec-mouse"); MODULE_LICENSE("GPL"); |
