From 8dee001d98813c4cfa0be92ae3da7cabdc954c63 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 7 Aug 2012 14:46:32 +0530 Subject: [PATCH 01/15] extcon: Remove duplicate inclusion of extcon.h header file extcon.h header file was included twice. Signed-off-by: Sachin Kamat Signed-off-by: Sachin Kamat Signed-off-by: MyungJoo Ham --- drivers/extcon/extcon-gpio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index 3cc152e690b0..71d3ab7b3d8d 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include From 3cafbd4e5005dbef78b32f2e0fe3ab00a955c6c1 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Fri, 31 Aug 2012 14:00:19 +0530 Subject: [PATCH 02/15] extcon-max8997: remove usage of ret in max8997_muic_handle_charger_type_detach actually we can do returns with error or success with out ret in this function, so remove the ret variable, and reduce a very little (4byte) space on stack of this function Signed-off-by: Devendra Naga Signed-off-by: MyungJoo Ham --- drivers/extcon/extcon-max8997.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index ef9090a4271d..77b66b0cc8f5 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c @@ -271,8 +271,6 @@ static int max8997_muic_handle_adc(struct max8997_muic_info *info, int adc) static int max8997_muic_handle_charger_type_detach( struct max8997_muic_info *info) { - int ret = 0; - switch (info->pre_charger_type) { case MAX8997_CHARGER_TYPE_USB: extcon_set_cable_state(info->edev, "USB", false); @@ -290,11 +288,11 @@ static int max8997_muic_handle_charger_type_detach( extcon_set_cable_state(info->edev, "Fast-charger", false); break; default: - ret = -EINVAL; + return -EINVAL; break; } - return ret; + return 0; } static int max8997_muic_handle_charger_type(struct max8997_muic_info *info, From 0cf6ad8a18f7f7bdbb81975188d9e0656ef277dd Mon Sep 17 00:00:00 2001 From: anish kumar Date: Thu, 30 Aug 2012 00:35:09 +0530 Subject: [PATCH 03/15] extcon: standard cable names definition and declaration changed With this change now individual drivers can use standard cable names as below: static const char *arizona_cable[] = { extcon_cable_name[EXTCON_USB], extcon_cable_name[EXTCON_USB_HOST], "CUSTOM_CABLE" NULL, } Signed-off-by: anish kumar Signed-off-by: MyungJoo Ham --- drivers/extcon/extcon-class.c | 4 +--- include/linux/extcon.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 946a3188b2b7..1e1a3f17a782 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -41,7 +41,7 @@ * every single port-type of the following cable names. Please choose cable * names that are actually used in your extcon device. */ -const char *extcon_cable_name[] = { +const char extcon_cable_name[][CABLE_NAME_MAX + 1] = { [EXTCON_USB] = "USB", [EXTCON_USB_HOST] = "USB-Host", [EXTCON_TA] = "TA", @@ -62,8 +62,6 @@ const char *extcon_cable_name[] = { [EXTCON_VIDEO_IN] = "Video-in", [EXTCON_VIDEO_OUT] = "Video-out", [EXTCON_MECHANICAL] = "Mechanical", - - NULL, }; static struct class *extcon_class; diff --git a/include/linux/extcon.h b/include/linux/extcon.h index 7443a560c9d0..2c26c14cd710 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -68,7 +68,7 @@ enum extcon_cable_name { EXTCON_VIDEO_OUT, EXTCON_MECHANICAL, }; -extern const char *extcon_cable_name[]; +extern const char extcon_cable_name[][CABLE_NAME_MAX + 1]; struct extcon_cable; From 28c0ada62d39eaafef03d88a4e6f4c5bcb6e1b6c Mon Sep 17 00:00:00 2001 From: anish kumar Date: Thu, 30 Aug 2012 00:35:10 +0530 Subject: [PATCH 04/15] extcon: optimising the check_mutually_exclusive function Rather than re-inventing the wheel we can use the hamming function to calculate the number of bits set to check for violation of exclusivity. Signed-off-by: anish kumar Signed-off-by: MyungJoo Ham --- drivers/extcon/extcon-class.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 1e1a3f17a782..1ce76a8d777b 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -89,17 +89,13 @@ static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state) return 0; for (i = 0; edev->mutually_exclusive[i]; i++) { - int count = 0, j; + int weight; u32 correspondants = new_state & edev->mutually_exclusive[i]; - u32 exp = 1; - for (j = 0; j < 32; j++) { - if (exp & correspondants) - count++; - if (count > 1) - return i + 1; - exp <<= 1; - } + /* calculate the total number of bits set */ + weight = hweight32(correspondants); + if (weight > 1) + return i + 1; } return 0; From 0dc77b6dabec8fd298392018cc0de5214af2dc43 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 24 Sep 2012 15:32:31 +0900 Subject: [PATCH 05/15] extcon: Unregister compat class at module unload to fix oops If you compile extcon with CONFIG_ANDROID and then load and unload the module you get a simple oops as the driver does not unregister its compat class and thus cannot register it again. Full trace: root@(none):~# modprobe extcon_class root@(none):~# rmmod extcon_class root@(none):~# modprobe extcon_class ------------[ cut here ]------------ WARNING: at fs/sysfs/dir.c:536 sysfs_add_one+0xde/0x100() sysfs: cannot create duplicate filename '/class/switch' Modules linked in: extcon_class(+) [last unloaded: extcon_class] Call Trace: 9f451a00: [<602a58bc>] printk+0x0/0xa8 9f451a18: [<60039b43>] warn_slowpath_common+0x93/0xd0 9f451a28: [<6012c6de>] sysfs_add_one+0xde/0x100 9f451a50: [<601d3d90>] strcat+0x0/0x40 9f451a68: [<60039cdc>] warn_slowpath_fmt+0x9c/0xa0 9f451a90: [<6002fe32>] unblock_signals+0x0/0x84 9f451ab0: [<60039c40>] warn_slowpath_fmt+0x0/0xa0 9f451ac0: [<6002fe32>] unblock_signals+0x0/0x84 9f451ae8: [<6012bd97>] sysfs_pathname.isra.10+0x57/0x70 9f451b00: [<601d3d90>] strcat+0x0/0x40 9f451b18: [<6012bd97>] sysfs_pathname.isra.10+0x57/0x70 9f451b48: [<6012c6de>] sysfs_add_one+0xde/0x100 9f451b78: [<6012c96f>] create_dir+0x8f/0x100 9f451bc0: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451bd8: [<6012cda6>] sysfs_create_dir+0xa6/0x1c0 9f451be8: [<601d89f1>] kvasprintf+0x81/0xa0 9f451bf8: [<601cf0f0>] kobject_get+0x0/0x50 9f451c18: [<601cf396>] kobject_add_internal+0x96/0x280 9f451c60: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451c78: [<601cfb93>] kobject_add+0xd3/0x140 9f451cc0: [<601cfac0>] kobject_add+0x0/0x140 9f451cd0: [<6002fe32>] unblock_signals+0x0/0x84 9f451cf8: [<6002fffc>] set_signals+0x29/0x3f 9f451d28: [<600c1de1>] kmem_cache_alloc+0xe1/0x100 9f451d78: [<601cffa0>] kobject_create_and_add+0x50/0xa0 9f451da8: [<601fbe76>] class_compat_register+0x56/0x80 9f451dc8: [] create_extcon_class+0x88/0xd0 [extcon_class] 9f451de8: [] extcon_class_init+0x10/0x12 [extcon_class] 9f451df8: [<600189a8>] do_one_initcall+0x48/0x1f0 9f451e20: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e30: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e58: [<6007e3c3>] sys_init_module+0xa3/0x280 9f451e88: [<6001e2ad>] handle_syscall+0x8d/0x90 9f451ea8: [<60033370>] userspace+0x405/0x531 9f451ee8: [<6001e380>] copy_chunk_to_user+0x0/0x40 9f451ef8: [<6001e5cd>] do_op_one_page+0x14d/0x220 9f451fd8: [<6001a355>] fork_handler+0x95/0xa0 ---[ end trace dd512cc03fe1c367 ]--- ------------[ cut here ]------------ WARNING: at lib/kobject.c:196 kobject_add_internal+0x26e/0x280() kobject_add_internal failed for switch with -EEXIST, don't try to register things with the same name in the same directory. Modules linked in: extcon_class(+) [last unloaded: extcon_class] Call Trace: 9f451ad0: [<602a58bc>] printk+0x0/0xa8 9f451ae8: [<60039b43>] warn_slowpath_common+0x93/0xd0 9f451af8: [<601cf56e>] kobject_add_internal+0x26e/0x280 9f451b18: [<601cf140>] kobject_put+0x0/0x70 9f451b20: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451b38: [<60039cdc>] warn_slowpath_fmt+0x9c/0xa0 9f451b88: [<60039c40>] warn_slowpath_fmt+0x0/0xa0 9f451bc0: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451bd8: [<6012cda6>] sysfs_create_dir+0xa6/0x1c0 9f451be8: [<601d89f1>] kvasprintf+0x81/0xa0 9f451bf8: [<601cf0f0>] kobject_get+0x0/0x50 9f451c18: [<601cf56e>] kobject_add_internal+0x26e/0x280 9f451c60: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451c78: [<601cfb93>] kobject_add+0xd3/0x140 9f451cc0: [<601cfac0>] kobject_add+0x0/0x140 9f451cd0: [<6002fe32>] unblock_signals+0x0/0x84 9f451cf8: [<6002fffc>] set_signals+0x29/0x3f 9f451d28: [<600c1de1>] kmem_cache_alloc+0xe1/0x100 9f451d78: [<601cffa0>] kobject_create_and_add+0x50/0xa0 9f451da8: [<601fbe76>] class_compat_register+0x56/0x80 9f451dc8: [] create_extcon_class+0x88/0xd0 [extcon_class] 9f451de8: [] extcon_class_init+0x10/0x12 [extcon_class] 9f451df8: [<600189a8>] do_one_initcall+0x48/0x1f0 9f451e20: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e30: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e58: [<6007e3c3>] sys_init_module+0xa3/0x280 9f451e88: [<6001e2ad>] handle_syscall+0x8d/0x90 9f451ea8: [<60033370>] userspace+0x405/0x531 9f451ee8: [<6001e380>] copy_chunk_to_user+0x0/0x40 9f451ef8: [<6001e5cd>] do_op_one_page+0x14d/0x220 9f451fd8: [<6001a355>] fork_handler+0x95/0xa0 ---[ end trace dd512cc03fe1c368 ]--- kobject_create_and_add: kobject_add error: -17 ------------[ cut here ]------------ WARNING: at drivers/extcon/extcon_class.c:545 create_extcon_class+0xbc/0xd0 [extcon_class]() cannot allocate Modules linked in: extcon_class(+) [last unloaded: extcon_class] Call Trace: 9f451c80: [<602a58bc>] printk+0x0/0xa8 9f451c98: [<60039b43>] warn_slowpath_common+0x93/0xd0 9f451ca0: [<6002fe32>] unblock_signals+0x0/0x84 9f451ca8: [] create_extcon_class+0xbc/0xd0 [extcon_class] 9f451cd0: [] extcon_class_init+0x0/0x12 [extcon_class] 9f451ce8: [<60039cdc>] warn_slowpath_fmt+0x9c/0xa0 9f451d20: [<6002fe32>] unblock_signals+0x0/0x84 9f451d28: [<60039c40>] warn_slowpath_fmt+0x0/0xa0 9f451d48: [<6002fffc>] set_signals+0x29/0x3f 9f451d58: [<601cf172>] kobject_put+0x32/0x70 9f451d78: [<600c22c3>] kfree+0xb3/0x100 9f451da8: [<601fbe9a>] class_compat_register+0x7a/0x80 9f451dc8: [] create_extcon_class+0xbc/0xd0 [extcon_class] 9f451de8: [] extcon_class_init+0x10/0x12 [extcon_class] 9f451df8: [<600189a8>] do_one_initcall+0x48/0x1f0 9f451e20: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e30: [<60061920>] blocking_notifier_call_chain+0x0/0x20 9f451e58: [<6007e3c3>] sys_init_module+0xa3/0x280 9f451e88: [<6001e2ad>] handle_syscall+0x8d/0x90 9f451ea8: [<60033370>] userspace+0x405/0x531 9f451ee8: [<6001e380>] copy_chunk_to_user+0x0/0x40 9f451ef8: [<6001e5cd>] do_op_one_page+0x14d/0x220 9f451fd8: [<6001a355>] fork_handler+0x95/0xa0 ---[ end trace dd512cc03fe1c369 ]--- FATAL: Error inserting extcon_class (/lib/modules/3.6.0-rc6-00178-g811315f/kernel/drivers/extcon/extcon_class.ko): Cannot allocate memory This patch fixes this. Cc: stable@vger.kernel.org Signed-off-by: Peter Huewe Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-class.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 1ce76a8d777b..63715cdfe988 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -819,6 +819,9 @@ module_init(extcon_class_init); static void __exit extcon_class_exit(void) { +#if defined(CONFIG_ANDROID) + class_compat_unregister(switch_class); +#endif class_destroy(extcon_class); } module_exit(extcon_class_exit); From 824a1bc045cef278aec15bef35d8d0b59ce77856 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 24 Sep 2012 15:36:24 +0900 Subject: [PATCH 06/15] extcon: unregister compat link on cleanup Since extcon registers this compat link at device registration (extcon_dev_register), we should probably remove them at deregistration/cleanup. Cc: stable@vger.kernel.org Signed-off-by: Peter Huewe Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-class.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 63715cdfe988..54dc00b7b9f6 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -570,6 +570,10 @@ static void extcon_cleanup(struct extcon_dev *edev, bool skip) kfree(edev->cables); } +#if defined(CONFIG_ANDROID) + if (switch_class) + class_compat_remove_link(switch_class, edev->dev, NULL); +#endif device_unregister(edev->dev); put_device(edev->dev); } From 5cd3c277ebc64e4bc30c5eb6412edd43b5730a4f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 26 Sep 2012 08:10:03 +0900 Subject: [PATCH 07/15] extcon: Fix return value in extcon_register_interest() Propagate the value returned from extcon_find_cable_index() instead of -ENODEV. For readability, -EINVAL is returned in place of the variable. Signed-off-by: Sachin Kamat Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-class.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 54dc00b7b9f6..79f5dbae0147 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -469,7 +469,7 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj, obj->cable_index = extcon_find_cable_index(obj->edev, cable_name); if (obj->cable_index < 0) - return -ENODEV; + return -EINVAL; obj->user_nb = nb; From 03019759b98de92b5507c8c2f6e253a35d59c868 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 2 Oct 2012 09:14:59 +0900 Subject: [PATCH 08/15] extcon: adc-jack: Fix checking return value of request_any_context_irq On failure, request_any_context_irq() returns a negative value. On success, it returns either IRQC_IS_HARDIRQ or IRQC_IS_NESTED. Also ensure adc_jack_probe() return 0 on success. Signed-off-by: Axel Lin Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-adc-jack.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index 725eb5aa8d8c..2cc6bec9f625 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c @@ -161,13 +161,12 @@ static int __devinit adc_jack_probe(struct platform_device *pdev) err = request_any_context_irq(data->irq, adc_jack_irq_thread, pdata->irq_flags, pdata->name, data); - if (err) { + if (err < 0) { dev_err(&pdev->dev, "error: irq %d\n", data->irq); - err = -EINVAL; goto err_irq; } - goto out; + return 0; err_irq: extcon_dev_unregister(&data->edev); From d9310e35a8d5aefad73b2f2387503082da0bea04 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 2 Oct 2012 09:16:53 +0900 Subject: [PATCH 09/15] extcon: adc-jack: Add missing MODULE_LICENSE This driver can be built as a module, add MODULE_LICENSE for it. For completeness, also adds MODULE_AUTHOR and MODULE_DESCRIPTION. Signed-off-by: Axel Lin Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-adc-jack.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index 2cc6bec9f625..e87196f6d2d2 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c @@ -14,6 +14,7 @@ * */ +#include #include #include #include @@ -195,3 +196,7 @@ static struct platform_driver adc_jack_driver = { }; module_platform_driver(adc_jack_driver); + +MODULE_AUTHOR("MyungJoo Ham "); +MODULE_DESCRIPTION("ADC Jack extcon driver"); +MODULE_LICENSE("GPL v2"); From 909f9ec0a42eeff94dbcac226664d225a11f10d6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 4 Oct 2012 09:53:45 +0900 Subject: [PATCH 10/15] extcon: Fix kerneldoc for extcon_set_cable_state and extcon_set_cable_state_ Signed-off-by: Axel Lin Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-class.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 79f5dbae0147..c27d58d6bbd2 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -356,7 +356,7 @@ int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name) EXPORT_SYMBOL_GPL(extcon_get_cable_state); /** - * extcon_get_cable_state_() - Set the status of a specific cable. + * extcon_set_cable_state_() - Set the status of a specific cable. * @edev: the extcon device that has the cable. * @index: cable index that can be retrieved by extcon_find_cable_index(). * @cable_state: the new cable status. The default semantics is @@ -376,7 +376,7 @@ int extcon_set_cable_state_(struct extcon_dev *edev, EXPORT_SYMBOL_GPL(extcon_set_cable_state_); /** - * extcon_get_cable_state() - Set the status of a specific cable. + * extcon_set_cable_state() - Set the status of a specific cable. * @edev: the extcon device that has the cable. * @cable_name: cable name. * @cable_state: the new cable status. The default semantics is From bf2627d66d416ff438f37643d32866aa93947be6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 4 Oct 2012 09:55:23 +0900 Subject: [PATCH 11/15] extcon: max77693: Use max77693_update_reg for rmw operations This simplifies the code. Signed-off-by: Axel Lin Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-max77693.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index e21387e2da5c..e0ed622a0df0 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -239,25 +239,19 @@ const char *max77693_extcon_cable[] = { static int max77693_muic_set_debounce_time(struct max77693_muic_info *info, enum max77693_muic_adc_debounce_time time) { - int ret = 0; - u8 ctrl3; + int ret; switch (time) { case ADC_DEBOUNCE_TIME_5MS: case ADC_DEBOUNCE_TIME_10MS: case ADC_DEBOUNCE_TIME_25MS: case ADC_DEBOUNCE_TIME_38_62MS: - ret = max77693_read_reg(info->max77693->regmap_muic, - MAX77693_MUIC_REG_CTRL3, &ctrl3); - ctrl3 &= ~CONTROL3_ADCDBSET_MASK; - ctrl3 |= (time << CONTROL3_ADCDBSET_SHIFT); - - ret = max77693_write_reg(info->max77693->regmap_muic, - MAX77693_MUIC_REG_CTRL3, ctrl3); - if (ret) { + ret = max77693_update_reg(info->max77693->regmap_muic, + MAX77693_MUIC_REG_CTRL3, + time << CONTROL3_ADCDBSET_SHIFT, + CONTROL3_ADCDBSET_MASK); + if (ret) dev_err(info->dev, "failed to set ADC debounce time\n"); - ret = -EINVAL; - } break; default: dev_err(info->dev, "invalid ADC debounce time\n"); From f8457d574f680a98c77846a15df13086ab1ab426 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 8 Oct 2012 14:41:49 +0900 Subject: [PATCH 12/15] extcon: MAX77693: Add platform data for MUIC device to initialize registers This patch add platform data for MUIC device to initialize register on probe() call because it should unmask interrupt mask register and initialize some register related to MUIC device. Signed-off-by: Chanwoo Choi Signed-off-by: Myungjoo Ham Signed-off-by: Kyungmin Park --- drivers/extcon/extcon-max77693.c | 27 +++++++++++++++++++++++++++ include/linux/mfd/max77693.h | 13 +++++++++++++ 2 files changed, 40 insertions(+) diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index e0ed622a0df0..cffeab65051e 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -651,6 +651,8 @@ static int max77693_muic_detect_accessory(struct max77693_muic_info *info) static int __devinit max77693_muic_probe(struct platform_device *pdev) { struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent); + struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev); + struct max77693_muic_platform_data *muic_pdata = pdata->muic_data; struct max77693_muic_info *info; int ret, i; u8 id; @@ -721,6 +723,31 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev) goto err_extcon; } + /* Initialize MUIC register by using platform data */ + for (i = 0 ; i < muic_pdata->num_init_data ; i++) { + enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR; + + max77693_write_reg(info->max77693->regmap_muic, + muic_pdata->init_data[i].addr, + muic_pdata->init_data[i].data); + + switch (muic_pdata->init_data[i].addr) { + case MAX77693_MUIC_REG_INTMASK1: + irq_src = MUIC_INT1; + break; + case MAX77693_MUIC_REG_INTMASK2: + irq_src = MUIC_INT2; + break; + case MAX77693_MUIC_REG_INTMASK3: + irq_src = MUIC_INT3; + break; + } + + if (irq_src < MAX77693_IRQ_GROUP_NR) + info->max77693->irq_masks_cur[irq_src] + = muic_pdata->init_data[i].data; + } + /* Check revision number of MUIC device*/ ret = max77693_read_reg(info->max77693->regmap_muic, MAX77693_MUIC_REG_ID, &id); diff --git a/include/linux/mfd/max77693.h b/include/linux/mfd/max77693.h index 1d28ae90384e..fe03b2d35d4f 100644 --- a/include/linux/mfd/max77693.h +++ b/include/linux/mfd/max77693.h @@ -30,7 +30,20 @@ #ifndef __LINUX_MFD_MAX77693_H #define __LINUX_MFD_MAX77693_H +struct max77693_reg_data { + u8 addr; + u8 data; +}; + +struct max77693_muic_platform_data { + struct max77693_reg_data *init_data; + int num_init_data; +}; + struct max77693_platform_data { int wakeup; + + /* muic data */ + struct max77693_muic_platform_data *muic_data; }; #endif /* __LINUX_MFD_MAX77693_H */ From 57e7cd37059bb00cd56b60b95b8799af0db91e18 Mon Sep 17 00:00:00 2001 From: anish kumar Date: Mon, 22 Oct 2012 09:43:33 +0900 Subject: [PATCH 13/15] extcon: driver model release call not needed There was a case where free and list_del can be called twice on the same pointer.So fixed it by re-arranging the code and removing a function which was not needed. Signed-off-by: anish kumar Signed-off-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/extcon/extcon-class.c | 75 ++++++++++++++++------------------- 1 file changed, 35 insertions(+), 40 deletions(-) diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index c27d58d6bbd2..39d3e4d48472 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -545,47 +545,9 @@ static int create_extcon_class(void) return 0; } -static void extcon_cleanup(struct extcon_dev *edev, bool skip) -{ - mutex_lock(&extcon_dev_list_lock); - list_del(&edev->entry); - mutex_unlock(&extcon_dev_list_lock); - - if (!skip && get_device(edev->dev)) { - int index; - - if (edev->mutually_exclusive && edev->max_supported) { - for (index = 0; edev->mutually_exclusive[index]; - index++) - kfree(edev->d_attrs_muex[index].attr.name); - kfree(edev->d_attrs_muex); - kfree(edev->attrs_muex); - } - - for (index = 0; index < edev->max_supported; index++) - kfree(edev->cables[index].attr_g.name); - - if (edev->max_supported) { - kfree(edev->extcon_dev_type.groups); - kfree(edev->cables); - } - -#if defined(CONFIG_ANDROID) - if (switch_class) - class_compat_remove_link(switch_class, edev->dev, NULL); -#endif - device_unregister(edev->dev); - put_device(edev->dev); - } - - kfree(edev->dev); -} - static void extcon_dev_release(struct device *dev) { - struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev); - - extcon_cleanup(edev, true); + kfree(dev); } static const char *muex_name = "mutually_exclusive"; @@ -811,7 +773,40 @@ EXPORT_SYMBOL_GPL(extcon_dev_register); */ void extcon_dev_unregister(struct extcon_dev *edev) { - extcon_cleanup(edev, false); + int index; + + mutex_lock(&extcon_dev_list_lock); + list_del(&edev->entry); + mutex_unlock(&extcon_dev_list_lock); + + if (IS_ERR_OR_NULL(get_device(edev->dev))) { + dev_err(edev->dev, "Failed to unregister extcon_dev (%s)\n", + dev_name(edev->dev)); + return; + } + + if (edev->mutually_exclusive && edev->max_supported) { + for (index = 0; edev->mutually_exclusive[index]; + index++) + kfree(edev->d_attrs_muex[index].attr.name); + kfree(edev->d_attrs_muex); + kfree(edev->attrs_muex); + } + + for (index = 0; index < edev->max_supported; index++) + kfree(edev->cables[index].attr_g.name); + + if (edev->max_supported) { + kfree(edev->extcon_dev_type.groups); + kfree(edev->cables); + } + +#if defined(CONFIG_ANDROID) + if (switch_class) + class_compat_remove_link(switch_class, edev->dev, NULL); +#endif + device_unregister(edev->dev); + put_device(edev->dev); } EXPORT_SYMBOL_GPL(extcon_dev_unregister); From 44b7bccf7c5372eab3408593ab2142a5dcde03f6 Mon Sep 17 00:00:00 2001 From: anish kumar Date: Mon, 22 Oct 2012 10:11:43 +0900 Subject: [PATCH 14/15] extcon: trivial: kfree missed from remove path Extcon core doesn't free the memory when we do unregister. Kfree is added in the remove path as it was missing. Signed-off-by: anish kumar Signed-off-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/extcon/extcon-max77693.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index cffeab65051e..a17d0d91ada2 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -783,6 +783,7 @@ static int __devexit max77693_muic_remove(struct platform_device *pdev) free_irq(muic_irqs[i].virq, info); cancel_work_sync(&info->irq_work); extcon_dev_unregister(info->edev); + kfree(info->edev); kfree(info); return 0; From 4f2de3bf177e57417963eec6a131a7bb2d2b660d Mon Sep 17 00:00:00 2001 From: Jenny TC Date: Thu, 18 Oct 2012 21:00:32 +0900 Subject: [PATCH 15/15] extcon : register for cable interest by cable name There are some scnearios where a driver/framework needs to register interest for a particular cable without specifying the extcon device name. One such scenario is charger notifications. The platform will have charger cabel which will be bound to any extcon device. It's not mandatory for the charger driver to know which extcon device it should use. This patch enables the support for registering interest for a cable just by cable name wihtout specifying the extcon device name Signed-off-by: Jenny TC Signed-off-by: MyungJoo Ham Tested-by: Chanwoo Choi -- Kernel-doc comment added by MyungJoo Ham --- drivers/extcon/extcon-class.c | 50 ++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 39d3e4d48472..d398821097f3 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -441,6 +441,8 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val, * extcon device. * @obj: an empty extcon_specific_cable_nb object to be returned. * @extcon_name: the name of extcon device. + * if NULL, extcon_register_interest will register + * every cable with the target cable_name given. * @cable_name: the target cable name. * @nb: the notifier block to get notified. * @@ -460,22 +462,44 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj, const char *extcon_name, const char *cable_name, struct notifier_block *nb) { - if (!obj || !extcon_name || !cable_name || !nb) + if (!obj || !cable_name || !nb) return -EINVAL; - obj->edev = extcon_get_extcon_dev(extcon_name); - if (!obj->edev) + if (extcon_name) { + obj->edev = extcon_get_extcon_dev(extcon_name); + if (!obj->edev) + return -ENODEV; + + obj->cable_index = extcon_find_cable_index(obj->edev, cable_name); + if (obj->cable_index < 0) + return -ENODEV; + + obj->user_nb = nb; + + obj->internal_nb.notifier_call = _call_per_cable; + + return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb); + } else { + struct class_dev_iter iter; + struct extcon_dev *extd; + struct device *dev; + + if (!extcon_class) + return -ENODEV; + class_dev_iter_init(&iter, extcon_class, NULL, NULL); + while ((dev = class_dev_iter_next(&iter))) { + extd = (struct extcon_dev *)dev_get_drvdata(dev); + + if (extcon_find_cable_index(extd, cable_name) < 0) + continue; + + class_dev_iter_exit(&iter); + return extcon_register_interest(obj, extd->name, + cable_name, nb); + } + return -ENODEV; - - obj->cable_index = extcon_find_cable_index(obj->edev, cable_name); - if (obj->cable_index < 0) - return -EINVAL; - - obj->user_nb = nb; - - obj->internal_nb.notifier_call = _call_per_cable; - - return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb); + } } /**