diff options
47 files changed, 2159 insertions, 227 deletions
diff --git a/Documentation/ABI/stable/sysfs-driver-w1_ds28e04 b/Documentation/ABI/stable/sysfs-driver-w1_ds28e04 new file mode 100644 index 000000000000..26579ee868c9 --- /dev/null +++ b/Documentation/ABI/stable/sysfs-driver-w1_ds28e04 | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | What: /sys/bus/w1/devices/.../pio | ||
| 2 | Date: May 2012 | ||
| 3 | Contact: Markus Franke <franm@hrz.tu-chemnitz.de> | ||
| 4 | Description: read/write the contents of the two PIO's of the DS28E04-100 | ||
| 5 | see Documentation/w1/slaves/w1_ds28e04 for detailed information | ||
| 6 | Users: any user space application which wants to communicate with DS28E04-100 | ||
| 7 | |||
| 8 | |||
| 9 | |||
| 10 | What: /sys/bus/w1/devices/.../eeprom | ||
| 11 | Date: May 2012 | ||
| 12 | Contact: Markus Franke <franm@hrz.tu-chemnitz.de> | ||
| 13 | Description: read/write the contents of the EEPROM memory of the DS28E04-100 | ||
| 14 | see Documentation/w1/slaves/w1_ds28e04 for detailed information | ||
| 15 | Users: any user space application which wants to communicate with DS28E04-100 | ||
diff --git a/Documentation/ABI/testing/dev-kmsg b/Documentation/ABI/testing/dev-kmsg index 281ecc5f9709..7e7e07a82e0e 100644 --- a/Documentation/ABI/testing/dev-kmsg +++ b/Documentation/ABI/testing/dev-kmsg | |||
| @@ -58,16 +58,18 @@ Description: The /dev/kmsg character device node provides userspace access | |||
| 58 | 58 | ||
| 59 | The output format consists of a prefix carrying the syslog | 59 | The output format consists of a prefix carrying the syslog |
| 60 | prefix including priority and facility, the 64 bit message | 60 | prefix including priority and facility, the 64 bit message |
| 61 | sequence number and the monotonic timestamp in microseconds. | 61 | sequence number and the monotonic timestamp in microseconds, |
| 62 | The values are separated by a ','. Future extensions might | 62 | and a flag field. All fields are separated by a ','. |
| 63 | add more comma separated values before the terminating ';'. | 63 | |
| 64 | Unknown values should be gracefully ignored. | 64 | Future extensions might add more comma separated values before |
| 65 | the terminating ';'. Unknown fields and values should be | ||
| 66 | gracefully ignored. | ||
| 65 | 67 | ||
| 66 | The human readable text string starts directly after the ';' | 68 | The human readable text string starts directly after the ';' |
| 67 | and is terminated by a '\n'. Untrusted values derived from | 69 | and is terminated by a '\n'. Untrusted values derived from |
| 68 | hardware or other facilities are printed, therefore | 70 | hardware or other facilities are printed, therefore |
| 69 | all non-printable characters in the log message are escaped | 71 | all non-printable characters and '\' itself in the log message |
| 70 | by "\x00" C-style hex encoding. | 72 | are escaped by "\x00" C-style hex encoding. |
| 71 | 73 | ||
| 72 | A line starting with ' ', is a continuation line, adding | 74 | A line starting with ' ', is a continuation line, adding |
| 73 | key/value pairs to the log message, which provide the machine | 75 | key/value pairs to the log message, which provide the machine |
| @@ -75,11 +77,11 @@ Description: The /dev/kmsg character device node provides userspace access | |||
| 75 | userspace. | 77 | userspace. |
| 76 | 78 | ||
| 77 | Example: | 79 | Example: |
| 78 | 7,160,424069;pci_root PNP0A03:00: host bridge window [io 0x0000-0x0cf7] (ignored) | 80 | 7,160,424069,-;pci_root PNP0A03:00: host bridge window [io 0x0000-0x0cf7] (ignored) |
| 79 | SUBSYSTEM=acpi | 81 | SUBSYSTEM=acpi |
| 80 | DEVICE=+acpi:PNP0A03:00 | 82 | DEVICE=+acpi:PNP0A03:00 |
| 81 | 6,339,5140900;NET: Registered protocol family 10 | 83 | 6,339,5140900,-;NET: Registered protocol family 10 |
| 82 | 30,340,5690716;udevd[80]: starting version 181 | 84 | 30,340,5690716,-;udevd[80]: starting version 181 |
| 83 | 85 | ||
| 84 | The DEVICE= key uniquely identifies devices the following way: | 86 | The DEVICE= key uniquely identifies devices the following way: |
| 85 | b12:8 - block dev_t | 87 | b12:8 - block dev_t |
| @@ -87,4 +89,13 @@ Description: The /dev/kmsg character device node provides userspace access | |||
| 87 | n8 - netdev ifindex | 89 | n8 - netdev ifindex |
| 88 | +sound:card0 - subsystem:devname | 90 | +sound:card0 - subsystem:devname |
| 89 | 91 | ||
| 92 | The flags field carries '-' by default. A 'c' indicates a | ||
| 93 | fragment of a line. All following fragments are flagged with | ||
| 94 | '+'. Note, that these hints about continuation lines are not | ||
| 95 | neccessarily correct, and the stream could be interleaved with | ||
| 96 | unrelated messages, but merging the lines in the output | ||
| 97 | usually produces better human readable results. A similar | ||
| 98 | logic is used internally when messages are printed to the | ||
| 99 | console, /proc/kmsg or the syslog() syscall. | ||
| 100 | |||
| 90 | Users: dmesg(1), userspace kernel log consumers | 101 | Users: dmesg(1), userspace kernel log consumers |
diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt index 4a7b54bd37e8..b0714d8f678a 100644 --- a/Documentation/stable_kernel_rules.txt +++ b/Documentation/stable_kernel_rules.txt | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | Everything you ever wanted to know about Linux 2.6 -stable releases. | 1 | Everything you ever wanted to know about Linux -stable releases. |
| 2 | 2 | ||
| 3 | Rules on what kind of patches are accepted, and which ones are not, into the | 3 | Rules on what kind of patches are accepted, and which ones are not, into the |
| 4 | "-stable" tree: | 4 | "-stable" tree: |
| @@ -42,10 +42,10 @@ Procedure for submitting patches to the -stable tree: | |||
| 42 | cherry-picked than this can be specified in the following format in | 42 | cherry-picked than this can be specified in the following format in |
| 43 | the sign-off area: | 43 | the sign-off area: |
| 44 | 44 | ||
| 45 | Cc: <stable@vger.kernel.org> # .32.x: a1f84a3: sched: Check for idle | 45 | Cc: <stable@vger.kernel.org> # 3.3.x: a1f84a3: sched: Check for idle |
| 46 | Cc: <stable@vger.kernel.org> # .32.x: 1b9508f: sched: Rate-limit newidle | 46 | Cc: <stable@vger.kernel.org> # 3.3.x: 1b9508f: sched: Rate-limit newidle |
| 47 | Cc: <stable@vger.kernel.org> # .32.x: fd21073: sched: Fix affinity logic | 47 | Cc: <stable@vger.kernel.org> # 3.3.x: fd21073: sched: Fix affinity logic |
| 48 | Cc: <stable@vger.kernel.org> # .32.x | 48 | Cc: <stable@vger.kernel.org> # 3.3.x |
| 49 | Signed-off-by: Ingo Molnar <mingo@elte.hu> | 49 | Signed-off-by: Ingo Molnar <mingo@elte.hu> |
| 50 | 50 | ||
| 51 | The tag sequence has the meaning of: | 51 | The tag sequence has the meaning of: |
| @@ -79,6 +79,15 @@ Review cycle: | |||
| 79 | security kernel team, and not go through the normal review cycle. | 79 | security kernel team, and not go through the normal review cycle. |
| 80 | Contact the kernel security team for more details on this procedure. | 80 | Contact the kernel security team for more details on this procedure. |
| 81 | 81 | ||
| 82 | Trees: | ||
| 83 | |||
| 84 | - The queues of patches, for both completed versions and in progress | ||
| 85 | versions can be found at: | ||
| 86 | http://git.kernel.org/?p=linux/kernel/git/stable/stable-queue.git | ||
| 87 | - The finalized and tagged releases of all stable kernels can be found | ||
| 88 | in separate branches per version at: | ||
| 89 | http://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git | ||
| 90 | |||
| 82 | 91 | ||
| 83 | Review committee: | 92 | Review committee: |
| 84 | 93 | ||
diff --git a/Documentation/w1/slaves/w1_ds28e04 b/Documentation/w1/slaves/w1_ds28e04 new file mode 100644 index 000000000000..85bc9a7e02fe --- /dev/null +++ b/Documentation/w1/slaves/w1_ds28e04 | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | Kernel driver w1_ds28e04 | ||
| 2 | ======================== | ||
| 3 | |||
| 4 | Supported chips: | ||
| 5 | * Maxim DS28E04-100 4096-Bit Addressable 1-Wire EEPROM with PIO | ||
| 6 | |||
| 7 | supported family codes: | ||
| 8 | W1_FAMILY_DS28E04 0x1C | ||
| 9 | |||
| 10 | Author: Markus Franke, <franke.m@sebakmt.com> <franm@hrz.tu-chemnitz.de> | ||
| 11 | |||
| 12 | Description | ||
| 13 | ----------- | ||
| 14 | |||
| 15 | Support is provided through the sysfs files "eeprom" and "pio". CRC checking | ||
| 16 | during memory accesses can optionally be enabled/disabled via the device | ||
| 17 | attribute "crccheck". The strong pull-up can optionally be enabled/disabled | ||
| 18 | via the module parameter "w1_strong_pullup". | ||
| 19 | |||
| 20 | Memory Access | ||
| 21 | |||
| 22 | A read operation on the "eeprom" file reads the given amount of bytes | ||
| 23 | from the EEPROM of the DS28E04. | ||
| 24 | |||
| 25 | A write operation on the "eeprom" file writes the given byte sequence | ||
| 26 | to the EEPROM of the DS28E04. If CRC checking mode is enabled only | ||
| 27 | fully alligned blocks of 32 bytes with valid CRC16 values (in bytes 30 | ||
| 28 | and 31) are allowed to be written. | ||
| 29 | |||
| 30 | PIO Access | ||
| 31 | |||
| 32 | The 2 PIOs of the DS28E04-100 are accessible via the "pio" sysfs file. | ||
| 33 | |||
| 34 | The current status of the PIO's is returned as an 8 bit value. Bit 0/1 | ||
| 35 | represent the state of PIO_0/PIO_1. Bits 2..7 do not care. The PIO's are | ||
| 36 | driven low-active, i.e. the driver delivers/expects low-active values. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 9b8a5daaf403..429e72cc13fc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -2728,6 +2728,14 @@ M: Mimi Zohar <zohar@us.ibm.com> | |||
| 2728 | S: Supported | 2728 | S: Supported |
| 2729 | F: security/integrity/evm/ | 2729 | F: security/integrity/evm/ |
| 2730 | 2730 | ||
| 2731 | EXTERNAL CONNECTOR SUBSYSTEM (EXTCON) | ||
| 2732 | M: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
| 2733 | M: Chanwoo Choi <cw00.choi@samsung.com> | ||
| 2734 | L: linux-kernel@vger.kernel.org | ||
| 2735 | S: Maintained | ||
| 2736 | F: drivers/extcon/ | ||
| 2737 | F: Documentation/extcon/ | ||
| 2738 | |||
| 2731 | EXYNOS DP DRIVER | 2739 | EXYNOS DP DRIVER |
| 2732 | M: Jingoo Han <jg1.han@samsung.com> | 2740 | M: Jingoo Han <jg1.han@samsung.com> |
| 2733 | L: linux-fbdev@vger.kernel.org | 2741 | L: linux-fbdev@vger.kernel.org |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 2bcef657a60c..181ed2660b33 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
| @@ -743,7 +743,6 @@ int bus_add_driver(struct device_driver *drv) | |||
| 743 | } | 743 | } |
| 744 | } | 744 | } |
| 745 | 745 | ||
| 746 | kobject_uevent(&priv->kobj, KOBJ_ADD); | ||
| 747 | return 0; | 746 | return 0; |
| 748 | 747 | ||
| 749 | out_unregister: | 748 | out_unregister: |
diff --git a/drivers/base/core.c b/drivers/base/core.c index 346be8b78b24..f338037a4f3d 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
| @@ -85,14 +85,13 @@ const char *dev_driver_string(const struct device *dev) | |||
| 85 | } | 85 | } |
| 86 | EXPORT_SYMBOL(dev_driver_string); | 86 | EXPORT_SYMBOL(dev_driver_string); |
| 87 | 87 | ||
| 88 | #define to_dev(obj) container_of(obj, struct device, kobj) | ||
| 89 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) | 88 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) |
| 90 | 89 | ||
| 91 | static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, | 90 | static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, |
| 92 | char *buf) | 91 | char *buf) |
| 93 | { | 92 | { |
| 94 | struct device_attribute *dev_attr = to_dev_attr(attr); | 93 | struct device_attribute *dev_attr = to_dev_attr(attr); |
| 95 | struct device *dev = to_dev(kobj); | 94 | struct device *dev = kobj_to_dev(kobj); |
| 96 | ssize_t ret = -EIO; | 95 | ssize_t ret = -EIO; |
| 97 | 96 | ||
| 98 | if (dev_attr->show) | 97 | if (dev_attr->show) |
| @@ -108,7 +107,7 @@ static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr, | |||
| 108 | const char *buf, size_t count) | 107 | const char *buf, size_t count) |
| 109 | { | 108 | { |
| 110 | struct device_attribute *dev_attr = to_dev_attr(attr); | 109 | struct device_attribute *dev_attr = to_dev_attr(attr); |
| 111 | struct device *dev = to_dev(kobj); | 110 | struct device *dev = kobj_to_dev(kobj); |
| 112 | ssize_t ret = -EIO; | 111 | ssize_t ret = -EIO; |
| 113 | 112 | ||
| 114 | if (dev_attr->store) | 113 | if (dev_attr->store) |
| @@ -182,7 +181,7 @@ EXPORT_SYMBOL_GPL(device_show_int); | |||
| 182 | */ | 181 | */ |
| 183 | static void device_release(struct kobject *kobj) | 182 | static void device_release(struct kobject *kobj) |
| 184 | { | 183 | { |
| 185 | struct device *dev = to_dev(kobj); | 184 | struct device *dev = kobj_to_dev(kobj); |
| 186 | struct device_private *p = dev->p; | 185 | struct device_private *p = dev->p; |
| 187 | 186 | ||
| 188 | if (dev->release) | 187 | if (dev->release) |
| @@ -200,7 +199,7 @@ static void device_release(struct kobject *kobj) | |||
| 200 | 199 | ||
| 201 | static const void *device_namespace(struct kobject *kobj) | 200 | static const void *device_namespace(struct kobject *kobj) |
| 202 | { | 201 | { |
| 203 | struct device *dev = to_dev(kobj); | 202 | struct device *dev = kobj_to_dev(kobj); |
| 204 | const void *ns = NULL; | 203 | const void *ns = NULL; |
| 205 | 204 | ||
| 206 | if (dev->class && dev->class->ns_type) | 205 | if (dev->class && dev->class->ns_type) |
| @@ -221,7 +220,7 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj) | |||
| 221 | struct kobj_type *ktype = get_ktype(kobj); | 220 | struct kobj_type *ktype = get_ktype(kobj); |
| 222 | 221 | ||
| 223 | if (ktype == &device_ktype) { | 222 | if (ktype == &device_ktype) { |
| 224 | struct device *dev = to_dev(kobj); | 223 | struct device *dev = kobj_to_dev(kobj); |
| 225 | if (dev->bus) | 224 | if (dev->bus) |
| 226 | return 1; | 225 | return 1; |
| 227 | if (dev->class) | 226 | if (dev->class) |
| @@ -232,7 +231,7 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj) | |||
| 232 | 231 | ||
| 233 | static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj) | 232 | static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj) |
| 234 | { | 233 | { |
| 235 | struct device *dev = to_dev(kobj); | 234 | struct device *dev = kobj_to_dev(kobj); |
| 236 | 235 | ||
| 237 | if (dev->bus) | 236 | if (dev->bus) |
| 238 | return dev->bus->name; | 237 | return dev->bus->name; |
| @@ -244,7 +243,7 @@ static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj) | |||
| 244 | static int dev_uevent(struct kset *kset, struct kobject *kobj, | 243 | static int dev_uevent(struct kset *kset, struct kobject *kobj, |
| 245 | struct kobj_uevent_env *env) | 244 | struct kobj_uevent_env *env) |
| 246 | { | 245 | { |
| 247 | struct device *dev = to_dev(kobj); | 246 | struct device *dev = kobj_to_dev(kobj); |
| 248 | int retval = 0; | 247 | int retval = 0; |
| 249 | 248 | ||
| 250 | /* add device node properties if present */ | 249 | /* add device node properties if present */ |
| @@ -1132,7 +1131,7 @@ int device_register(struct device *dev) | |||
| 1132 | */ | 1131 | */ |
| 1133 | struct device *get_device(struct device *dev) | 1132 | struct device *get_device(struct device *dev) |
| 1134 | { | 1133 | { |
| 1135 | return dev ? to_dev(kobject_get(&dev->kobj)) : NULL; | 1134 | return dev ? kobj_to_dev(kobject_get(&dev->kobj)) : NULL; |
| 1136 | } | 1135 | } |
| 1137 | 1136 | ||
| 1138 | /** | 1137 | /** |
| @@ -1754,25 +1753,25 @@ int device_move(struct device *dev, struct device *new_parent, | |||
| 1754 | set_dev_node(dev, dev_to_node(new_parent)); | 1753 | set_dev_node(dev, dev_to_node(new_parent)); |
| 1755 | } | 1754 | } |
| 1756 | 1755 | ||
| 1757 | if (!dev->class) | 1756 | if (dev->class) { |
| 1758 | goto out_put; | 1757 | error = device_move_class_links(dev, old_parent, new_parent); |
| 1759 | error = device_move_class_links(dev, old_parent, new_parent); | 1758 | if (error) { |
| 1760 | if (error) { | 1759 | /* We ignore errors on cleanup since we're hosed anyway... */ |
| 1761 | /* We ignore errors on cleanup since we're hosed anyway... */ | 1760 | device_move_class_links(dev, new_parent, old_parent); |
| 1762 | device_move_class_links(dev, new_parent, old_parent); | 1761 | if (!kobject_move(&dev->kobj, &old_parent->kobj)) { |
| 1763 | if (!kobject_move(&dev->kobj, &old_parent->kobj)) { | 1762 | if (new_parent) |
| 1764 | if (new_parent) | 1763 | klist_remove(&dev->p->knode_parent); |
| 1765 | klist_remove(&dev->p->knode_parent); | 1764 | dev->parent = old_parent; |
| 1766 | dev->parent = old_parent; | 1765 | if (old_parent) { |
| 1767 | if (old_parent) { | 1766 | klist_add_tail(&dev->p->knode_parent, |
| 1768 | klist_add_tail(&dev->p->knode_parent, | 1767 | &old_parent->p->klist_children); |
| 1769 | &old_parent->p->klist_children); | 1768 | set_dev_node(dev, dev_to_node(old_parent)); |
| 1770 | set_dev_node(dev, dev_to_node(old_parent)); | 1769 | } |
| 1771 | } | 1770 | } |
| 1771 | cleanup_glue_dir(dev, new_parent_kobj); | ||
| 1772 | put_device(new_parent); | ||
| 1773 | goto out; | ||
| 1772 | } | 1774 | } |
| 1773 | cleanup_glue_dir(dev, new_parent_kobj); | ||
| 1774 | put_device(new_parent); | ||
| 1775 | goto out; | ||
| 1776 | } | 1775 | } |
| 1777 | switch (dpm_order) { | 1776 | switch (dpm_order) { |
| 1778 | case DPM_ORDER_NONE: | 1777 | case DPM_ORDER_NONE: |
| @@ -1787,7 +1786,7 @@ int device_move(struct device *dev, struct device *new_parent, | |||
| 1787 | device_pm_move_last(dev); | 1786 | device_pm_move_last(dev); |
| 1788 | break; | 1787 | break; |
| 1789 | } | 1788 | } |
| 1790 | out_put: | 1789 | |
| 1791 | put_device(old_parent); | 1790 | put_device(old_parent); |
| 1792 | out: | 1791 | out: |
| 1793 | device_pm_unlock(); | 1792 | device_pm_unlock(); |
| @@ -1812,6 +1811,13 @@ void device_shutdown(void) | |||
| 1812 | while (!list_empty(&devices_kset->list)) { | 1811 | while (!list_empty(&devices_kset->list)) { |
| 1813 | dev = list_entry(devices_kset->list.prev, struct device, | 1812 | dev = list_entry(devices_kset->list.prev, struct device, |
| 1814 | kobj.entry); | 1813 | kobj.entry); |
| 1814 | |||
| 1815 | /* | ||
| 1816 | * hold reference count of device's parent to | ||
| 1817 | * prevent it from being freed because parent's | ||
| 1818 | * lock is to be held | ||
| 1819 | */ | ||
| 1820 | get_device(dev->parent); | ||
| 1815 | get_device(dev); | 1821 | get_device(dev); |
| 1816 | /* | 1822 | /* |
| 1817 | * Make sure the device is off the kset list, in the | 1823 | * Make sure the device is off the kset list, in the |
| @@ -1820,6 +1826,11 @@ void device_shutdown(void) | |||
| 1820 | list_del_init(&dev->kobj.entry); | 1826 | list_del_init(&dev->kobj.entry); |
| 1821 | spin_unlock(&devices_kset->list_lock); | 1827 | spin_unlock(&devices_kset->list_lock); |
| 1822 | 1828 | ||
| 1829 | /* hold lock to avoid race with probe/release */ | ||
| 1830 | if (dev->parent) | ||
| 1831 | device_lock(dev->parent); | ||
| 1832 | device_lock(dev); | ||
| 1833 | |||
| 1823 | /* Don't allow any more runtime suspends */ | 1834 | /* Don't allow any more runtime suspends */ |
| 1824 | pm_runtime_get_noresume(dev); | 1835 | pm_runtime_get_noresume(dev); |
| 1825 | pm_runtime_barrier(dev); | 1836 | pm_runtime_barrier(dev); |
| @@ -1831,7 +1842,13 @@ void device_shutdown(void) | |||
| 1831 | dev_dbg(dev, "shutdown\n"); | 1842 | dev_dbg(dev, "shutdown\n"); |
| 1832 | dev->driver->shutdown(dev); | 1843 | dev->driver->shutdown(dev); |
| 1833 | } | 1844 | } |
| 1845 | |||
| 1846 | device_unlock(dev); | ||
| 1847 | if (dev->parent) | ||
| 1848 | device_unlock(dev->parent); | ||
| 1849 | |||
| 1834 | put_device(dev); | 1850 | put_device(dev); |
| 1851 | put_device(dev->parent); | ||
| 1835 | 1852 | ||
| 1836 | spin_lock(&devices_kset->list_lock); | 1853 | spin_lock(&devices_kset->list_lock); |
| 1837 | } | 1854 | } |
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index dcb8a6e48692..e3bbed8a617c 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
| @@ -85,8 +85,20 @@ static void deferred_probe_work_func(struct work_struct *work) | |||
| 85 | * manipulate the deferred list | 85 | * manipulate the deferred list |
| 86 | */ | 86 | */ |
| 87 | mutex_unlock(&deferred_probe_mutex); | 87 | mutex_unlock(&deferred_probe_mutex); |
| 88 | |||
| 89 | /* | ||
| 90 | * Force the device to the end of the dpm_list since | ||
| 91 | * the PM code assumes that the order we add things to | ||
| 92 | * the list is a good order for suspend but deferred | ||
| 93 | * probe makes that very unsafe. | ||
| 94 | */ | ||
| 95 | device_pm_lock(); | ||
| 96 | device_pm_move_last(dev); | ||
| 97 | device_pm_unlock(); | ||
| 98 | |||
| 88 | dev_dbg(dev, "Retrying from deferred list\n"); | 99 | dev_dbg(dev, "Retrying from deferred list\n"); |
| 89 | bus_probe_device(dev); | 100 | bus_probe_device(dev); |
| 101 | |||
| 90 | mutex_lock(&deferred_probe_mutex); | 102 | mutex_lock(&deferred_probe_mutex); |
| 91 | 103 | ||
| 92 | put_device(dev); | 104 | put_device(dev); |
| @@ -283,6 +295,7 @@ probe_failed: | |||
| 283 | devres_release_all(dev); | 295 | devres_release_all(dev); |
| 284 | driver_sysfs_remove(dev); | 296 | driver_sysfs_remove(dev); |
| 285 | dev->driver = NULL; | 297 | dev->driver = NULL; |
| 298 | dev_set_drvdata(dev, NULL); | ||
| 286 | 299 | ||
| 287 | if (ret == -EPROBE_DEFER) { | 300 | if (ret == -EPROBE_DEFER) { |
| 288 | /* Driver requested deferred probing */ | 301 | /* Driver requested deferred probing */ |
| @@ -356,10 +369,9 @@ int driver_probe_device(struct device_driver *drv, struct device *dev) | |||
| 356 | pr_debug("bus: '%s': %s: matched device %s with driver %s\n", | 369 | pr_debug("bus: '%s': %s: matched device %s with driver %s\n", |
| 357 | drv->bus->name, __func__, dev_name(dev), drv->name); | 370 | drv->bus->name, __func__, dev_name(dev), drv->name); |
| 358 | 371 | ||
| 359 | pm_runtime_get_noresume(dev); | ||
| 360 | pm_runtime_barrier(dev); | 372 | pm_runtime_barrier(dev); |
| 361 | ret = really_probe(dev, drv); | 373 | ret = really_probe(dev, drv); |
| 362 | pm_runtime_put_sync(dev); | 374 | pm_runtime_idle(dev); |
| 363 | 375 | ||
| 364 | return ret; | 376 | return ret; |
| 365 | } | 377 | } |
| @@ -406,9 +418,8 @@ int device_attach(struct device *dev) | |||
| 406 | ret = 0; | 418 | ret = 0; |
| 407 | } | 419 | } |
| 408 | } else { | 420 | } else { |
| 409 | pm_runtime_get_noresume(dev); | ||
| 410 | ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); | 421 | ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); |
| 411 | pm_runtime_put_sync(dev); | 422 | pm_runtime_idle(dev); |
| 412 | } | 423 | } |
| 413 | out_unlock: | 424 | out_unlock: |
| 414 | device_unlock(dev); | 425 | device_unlock(dev); |
| @@ -487,6 +498,7 @@ static void __device_release_driver(struct device *dev) | |||
| 487 | drv->remove(dev); | 498 | drv->remove(dev); |
| 488 | devres_release_all(dev); | 499 | devres_release_all(dev); |
| 489 | dev->driver = NULL; | 500 | dev->driver = NULL; |
| 501 | dev_set_drvdata(dev, NULL); | ||
| 490 | klist_remove(&dev->p->knode_driver); | 502 | klist_remove(&dev->p->knode_driver); |
| 491 | if (dev->bus) | 503 | if (dev->bus) |
| 492 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, | 504 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, |
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c index 24e88fe29ec1..c30f3e1d0efc 100644 --- a/drivers/base/dma-buf.c +++ b/drivers/base/dma-buf.c | |||
| @@ -493,6 +493,7 @@ EXPORT_SYMBOL_GPL(dma_buf_vmap); | |||
| 493 | /** | 493 | /** |
| 494 | * dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap. | 494 | * dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap. |
| 495 | * @dmabuf: [in] buffer to vunmap | 495 | * @dmabuf: [in] buffer to vunmap |
| 496 | * @vaddr: [in] vmap to vunmap | ||
| 496 | */ | 497 | */ |
| 497 | void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) | 498 | void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) |
| 498 | { | 499 | { |
diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 1b85949e3d2f..560a7173f810 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c | |||
| @@ -186,6 +186,7 @@ EXPORT_SYMBOL(dma_release_from_coherent); | |||
| 186 | * @vma: vm_area for the userspace memory | 186 | * @vma: vm_area for the userspace memory |
| 187 | * @vaddr: cpu address returned by dma_alloc_from_coherent | 187 | * @vaddr: cpu address returned by dma_alloc_from_coherent |
| 188 | * @size: size of the memory buffer allocated by dma_alloc_from_coherent | 188 | * @size: size of the memory buffer allocated by dma_alloc_from_coherent |
| 189 | * @ret: result from remap_pfn_range() | ||
| 189 | * | 190 | * |
| 190 | * This checks whether the memory was allocated from the per-device | 191 | * This checks whether the memory was allocated from the per-device |
| 191 | * coherent memory pool and if so, maps that memory to the provided vma. | 192 | * coherent memory pool and if so, maps that memory to the provided vma. |
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 207c27ddf828..974e301a1ef0 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c | |||
| @@ -185,8 +185,12 @@ int driver_register(struct device_driver *drv) | |||
| 185 | if (ret) | 185 | if (ret) |
| 186 | return ret; | 186 | return ret; |
| 187 | ret = driver_add_groups(drv, drv->groups); | 187 | ret = driver_add_groups(drv, drv->groups); |
| 188 | if (ret) | 188 | if (ret) { |
| 189 | bus_remove_driver(drv); | 189 | bus_remove_driver(drv); |
| 190 | return ret; | ||
| 191 | } | ||
| 192 | kobject_uevent(&drv->p->kobj, KOBJ_ADD); | ||
| 193 | |||
| 190 | return ret; | 194 | return ret; |
| 191 | } | 195 | } |
| 192 | EXPORT_SYMBOL_GPL(driver_register); | 196 | EXPORT_SYMBOL_GPL(driver_register); |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 5401814c874d..803cfc1597a9 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
| @@ -22,8 +22,6 @@ | |||
| 22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 23 | #include <linux/sched.h> | 23 | #include <linux/sched.h> |
| 24 | 24 | ||
| 25 | #define to_dev(obj) container_of(obj, struct device, kobj) | ||
| 26 | |||
| 27 | MODULE_AUTHOR("Manuel Estrada Sainz"); | 25 | MODULE_AUTHOR("Manuel Estrada Sainz"); |
| 28 | MODULE_DESCRIPTION("Multi purpose firmware loading support"); | 26 | MODULE_DESCRIPTION("Multi purpose firmware loading support"); |
| 29 | MODULE_LICENSE("GPL"); | 27 | MODULE_LICENSE("GPL"); |
| @@ -290,7 +288,7 @@ static ssize_t firmware_data_read(struct file *filp, struct kobject *kobj, | |||
| 290 | struct bin_attribute *bin_attr, | 288 | struct bin_attribute *bin_attr, |
| 291 | char *buffer, loff_t offset, size_t count) | 289 | char *buffer, loff_t offset, size_t count) |
| 292 | { | 290 | { |
| 293 | struct device *dev = to_dev(kobj); | 291 | struct device *dev = kobj_to_dev(kobj); |
| 294 | struct firmware_priv *fw_priv = to_firmware_priv(dev); | 292 | struct firmware_priv *fw_priv = to_firmware_priv(dev); |
| 295 | struct firmware *fw; | 293 | struct firmware *fw; |
| 296 | ssize_t ret_count; | 294 | ssize_t ret_count; |
| @@ -384,7 +382,7 @@ static ssize_t firmware_data_write(struct file *filp, struct kobject *kobj, | |||
| 384 | struct bin_attribute *bin_attr, | 382 | struct bin_attribute *bin_attr, |
| 385 | char *buffer, loff_t offset, size_t count) | 383 | char *buffer, loff_t offset, size_t count) |
| 386 | { | 384 | { |
| 387 | struct device *dev = to_dev(kobj); | 385 | struct device *dev = kobj_to_dev(kobj); |
| 388 | struct firmware_priv *fw_priv = to_firmware_priv(dev); | 386 | struct firmware_priv *fw_priv = to_firmware_priv(dev); |
| 389 | struct firmware *fw; | 387 | struct firmware *fw; |
| 390 | ssize_t retval; | 388 | ssize_t retval; |
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index 29c5cf852efc..16716356d1fe 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig | |||
| @@ -21,6 +21,16 @@ config EXTCON_GPIO | |||
| 21 | Say Y here to enable GPIO based extcon support. Note that GPIO | 21 | Say Y here to enable GPIO based extcon support. Note that GPIO |
| 22 | extcon supports single state per extcon instance. | 22 | extcon supports single state per extcon instance. |
| 23 | 23 | ||
| 24 | config EXTCON_MAX77693 | ||
| 25 | tristate "MAX77693 EXTCON Support" | ||
| 26 | depends on MFD_MAX77693 | ||
| 27 | select IRQ_DOMAIN | ||
| 28 | select REGMAP_I2C | ||
| 29 | help | ||
| 30 | If you say yes here you get support for the MUIC device of | ||
| 31 | Maxim MAX77693 PMIC. The MAX77693 MUIC is a USB port accessory | ||
| 32 | detector and switch. | ||
| 33 | |||
| 24 | config EXTCON_MAX8997 | 34 | config EXTCON_MAX8997 |
| 25 | tristate "MAX8997 EXTCON Support" | 35 | tristate "MAX8997 EXTCON Support" |
| 26 | depends on MFD_MAX8997 | 36 | depends on MFD_MAX8997 |
| @@ -29,4 +39,12 @@ config EXTCON_MAX8997 | |||
| 29 | Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory | 39 | Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory |
| 30 | detector and switch. | 40 | detector and switch. |
| 31 | 41 | ||
| 42 | config EXTCON_ARIZONA | ||
| 43 | tristate "Wolfson Arizona EXTCON support" | ||
| 44 | depends on MFD_ARIZONA | ||
| 45 | help | ||
| 46 | Say Y here to enable support for external accessory detection | ||
| 47 | with Wolfson Arizona devices. These are audio CODECs with | ||
| 48 | advanced audio accessory detection support. | ||
| 49 | |||
| 32 | endif # MULTISTATE_SWITCH | 50 | endif # MULTISTATE_SWITCH |
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile index 86020bdb6da0..88961b332348 100644 --- a/drivers/extcon/Makefile +++ b/drivers/extcon/Makefile | |||
| @@ -4,4 +4,6 @@ | |||
| 4 | 4 | ||
| 5 | obj-$(CONFIG_EXTCON) += extcon_class.o | 5 | obj-$(CONFIG_EXTCON) += extcon_class.o |
| 6 | obj-$(CONFIG_EXTCON_GPIO) += extcon_gpio.o | 6 | obj-$(CONFIG_EXTCON_GPIO) += extcon_gpio.o |
| 7 | obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o | ||
| 7 | obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o | 8 | obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o |
| 9 | obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o | ||
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c new file mode 100644 index 000000000000..427a289f32a5 --- /dev/null +++ b/drivers/extcon/extcon-arizona.c | |||
| @@ -0,0 +1,490 @@ | |||
| 1 | /* | ||
| 2 | * extcon-arizona.c - Extcon driver Wolfson Arizona devices | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Wolfson Microelectronics plc | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/i2c.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/err.h> | ||
| 23 | #include <linux/gpio.h> | ||
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <linux/pm_runtime.h> | ||
| 26 | #include <linux/regulator/consumer.h> | ||
| 27 | #include <linux/extcon.h> | ||
| 28 | |||
| 29 | #include <linux/mfd/arizona/core.h> | ||
| 30 | #include <linux/mfd/arizona/pdata.h> | ||
| 31 | #include <linux/mfd/arizona/registers.h> | ||
| 32 | |||
| 33 | struct arizona_extcon_info { | ||
| 34 | struct device *dev; | ||
| 35 | struct arizona *arizona; | ||
| 36 | struct mutex lock; | ||
| 37 | struct regulator *micvdd; | ||
| 38 | |||
| 39 | int micd_mode; | ||
| 40 | const struct arizona_micd_config *micd_modes; | ||
| 41 | int micd_num_modes; | ||
| 42 | |||
| 43 | bool micd_reva; | ||
| 44 | |||
| 45 | bool mic; | ||
| 46 | bool detecting; | ||
| 47 | int jack_flips; | ||
| 48 | |||
| 49 | struct extcon_dev edev; | ||
| 50 | }; | ||
| 51 | |||
| 52 | static const struct arizona_micd_config micd_default_modes[] = { | ||
| 53 | { ARIZONA_ACCDET_SRC, 1 << ARIZONA_MICD_BIAS_SRC_SHIFT, 0 }, | ||
| 54 | { 0, 2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 }, | ||
| 55 | }; | ||
| 56 | |||
| 57 | #define ARIZONA_CABLE_MECHANICAL 0 | ||
| 58 | #define ARIZONA_CABLE_MICROPHONE 1 | ||
| 59 | #define ARIZONA_CABLE_HEADPHONE 2 | ||
| 60 | |||
| 61 | static const char *arizona_cable[] = { | ||
| 62 | "Mechanical", | ||
| 63 | "Microphone", | ||
| 64 | "Headphone", | ||
| 65 | NULL, | ||
| 66 | }; | ||
| 67 | |||
| 68 | static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode) | ||
| 69 | { | ||
| 70 | struct arizona *arizona = info->arizona; | ||
| 71 | |||
| 72 | gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio, | ||
| 73 | info->micd_modes[mode].gpio); | ||
| 74 | regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, | ||
| 75 | ARIZONA_MICD_BIAS_SRC_MASK, | ||
| 76 | info->micd_modes[mode].bias); | ||
| 77 | regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1, | ||
| 78 | ARIZONA_ACCDET_SRC, info->micd_modes[mode].src); | ||
| 79 | |||
| 80 | info->micd_mode = mode; | ||
| 81 | |||
| 82 | dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode); | ||
| 83 | } | ||
| 84 | |||
| 85 | static void arizona_start_mic(struct arizona_extcon_info *info) | ||
| 86 | { | ||
| 87 | struct arizona *arizona = info->arizona; | ||
| 88 | bool change; | ||
| 89 | int ret; | ||
| 90 | |||
| 91 | info->detecting = true; | ||
| 92 | info->mic = false; | ||
| 93 | info->jack_flips = 0; | ||
| 94 | |||
| 95 | /* Microphone detection can't use idle mode */ | ||
| 96 | pm_runtime_get(info->dev); | ||
| 97 | |||
| 98 | ret = regulator_enable(info->micvdd); | ||
| 99 | if (ret != 0) { | ||
| 100 | dev_err(arizona->dev, "Failed to enable MICVDD: %d\n", | ||
| 101 | ret); | ||
| 102 | } | ||
| 103 | |||
| 104 | if (info->micd_reva) { | ||
| 105 | regmap_write(arizona->regmap, 0x80, 0x3); | ||
| 106 | regmap_write(arizona->regmap, 0x294, 0); | ||
| 107 | regmap_write(arizona->regmap, 0x80, 0x0); | ||
| 108 | } | ||
| 109 | |||
| 110 | regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, | ||
| 111 | ARIZONA_MICD_ENA, ARIZONA_MICD_ENA, | ||
| 112 | &change); | ||
| 113 | if (!change) { | ||
| 114 | regulator_disable(info->micvdd); | ||
| 115 | pm_runtime_put_autosuspend(info->dev); | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | static void arizona_stop_mic(struct arizona_extcon_info *info) | ||
| 120 | { | ||
| 121 | struct arizona *arizona = info->arizona; | ||
| 122 | bool change; | ||
| 123 | |||
| 124 | regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, | ||
| 125 | ARIZONA_MICD_ENA, 0, | ||
| 126 | &change); | ||
| 127 | |||
| 128 | if (info->micd_reva) { | ||
| 129 | regmap_write(arizona->regmap, 0x80, 0x3); | ||
| 130 | regmap_write(arizona->regmap, 0x294, 2); | ||
| 131 | regmap_write(arizona->regmap, 0x80, 0x0); | ||
| 132 | } | ||
| 133 | |||
| 134 | if (change) { | ||
| 135 | regulator_disable(info->micvdd); | ||
| 136 | pm_runtime_put_autosuspend(info->dev); | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | static irqreturn_t arizona_micdet(int irq, void *data) | ||
| 141 | { | ||
| 142 | struct arizona_extcon_info *info = data; | ||
| 143 | struct arizona *arizona = info->arizona; | ||
| 144 | unsigned int val; | ||
| 145 | int ret; | ||
| 146 | |||
| 147 | mutex_lock(&info->lock); | ||
| 148 | |||
| 149 | ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val); | ||
| 150 | if (ret != 0) { | ||
| 151 | dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret); | ||
| 152 | return IRQ_NONE; | ||
| 153 | } | ||
| 154 | |||
| 155 | dev_dbg(arizona->dev, "MICDET: %x\n", val); | ||
| 156 | |||
| 157 | if (!(val & ARIZONA_MICD_VALID)) { | ||
| 158 | dev_warn(arizona->dev, "Microphone detection state invalid\n"); | ||
| 159 | mutex_unlock(&info->lock); | ||
| 160 | return IRQ_NONE; | ||
| 161 | } | ||
| 162 | |||
| 163 | /* Due to jack detect this should never happen */ | ||
| 164 | if (!(val & ARIZONA_MICD_STS)) { | ||
| 165 | dev_warn(arizona->dev, "Detected open circuit\n"); | ||
| 166 | info->detecting = false; | ||
| 167 | goto handled; | ||
| 168 | } | ||
| 169 | |||
| 170 | /* If we got a high impedence we should have a headset, report it. */ | ||
| 171 | if (info->detecting && (val & 0x400)) { | ||
| 172 | ret = extcon_update_state(&info->edev, | ||
| 173 | 1 << ARIZONA_CABLE_MICROPHONE | | ||
| 174 | 1 << ARIZONA_CABLE_HEADPHONE, | ||
| 175 | 1 << ARIZONA_CABLE_MICROPHONE | | ||
| 176 | 1 << ARIZONA_CABLE_HEADPHONE); | ||
| 177 | |||
| 178 | if (ret != 0) | ||
| 179 | dev_err(arizona->dev, "Headset report failed: %d\n", | ||
| 180 | ret); | ||
| 181 | |||
| 182 | info->mic = true; | ||
| 183 | info->detecting = false; | ||
| 184 | goto handled; | ||
| 185 | } | ||
| 186 | |||
| 187 | /* If we detected a lower impedence during initial startup | ||
| 188 | * then we probably have the wrong polarity, flip it. Don't | ||
| 189 | * do this for the lowest impedences to speed up detection of | ||
| 190 | * plain headphones. If both polarities report a low | ||
| 191 | * impedence then give up and report headphones. | ||
| 192 | */ | ||
| 193 | if (info->detecting && (val & 0x3f8)) { | ||
| 194 | info->jack_flips++; | ||
| 195 | |||
| 196 | if (info->jack_flips >= info->micd_num_modes) { | ||
| 197 | dev_dbg(arizona->dev, "Detected headphone\n"); | ||
| 198 | info->detecting = false; | ||
| 199 | arizona_stop_mic(info); | ||
| 200 | |||
| 201 | ret = extcon_set_cable_state_(&info->edev, | ||
| 202 | ARIZONA_CABLE_HEADPHONE, | ||
| 203 | true); | ||
| 204 | if (ret != 0) | ||
| 205 | dev_err(arizona->dev, | ||
| 206 | "Headphone report failed: %d\n", | ||
| 207 | ret); | ||
| 208 | } else { | ||
| 209 | info->micd_mode++; | ||
| 210 | if (info->micd_mode == info->micd_num_modes) | ||
| 211 | info->micd_mode = 0; | ||
| 212 | arizona_extcon_set_mode(info, info->micd_mode); | ||
| 213 | |||
| 214 | info->jack_flips++; | ||
| 215 | } | ||
| 216 | |||
| 217 | goto handled; | ||
| 218 | } | ||
| 219 | |||
| 220 | /* | ||
| 221 | * If we're still detecting and we detect a short then we've | ||
| 222 | * got a headphone. Otherwise it's a button press, the | ||
| 223 | * button reporting is stubbed out for now. | ||
| 224 | */ | ||
| 225 | if (val & 0x3fc) { | ||
| 226 | if (info->mic) { | ||
| 227 | dev_dbg(arizona->dev, "Mic button detected\n"); | ||
| 228 | |||
| 229 | } else if (info->detecting) { | ||
| 230 | dev_dbg(arizona->dev, "Headphone detected\n"); | ||
| 231 | info->detecting = false; | ||
| 232 | arizona_stop_mic(info); | ||
| 233 | |||
| 234 | ret = extcon_set_cable_state_(&info->edev, | ||
| 235 | ARIZONA_CABLE_HEADPHONE, | ||
| 236 | true); | ||
| 237 | if (ret != 0) | ||
| 238 | dev_err(arizona->dev, | ||
| 239 | "Headphone report failed: %d\n", | ||
| 240 | ret); | ||
| 241 | } else { | ||
| 242 | dev_warn(arizona->dev, "Button with no mic: %x\n", | ||
| 243 | val); | ||
| 244 | } | ||
| 245 | } else { | ||
| 246 | dev_dbg(arizona->dev, "Mic button released\n"); | ||
| 247 | } | ||
| 248 | |||
| 249 | handled: | ||
| 250 | pm_runtime_mark_last_busy(info->dev); | ||
| 251 | mutex_unlock(&info->lock); | ||
| 252 | |||
| 253 | return IRQ_HANDLED; | ||
| 254 | } | ||
| 255 | |||
| 256 | static irqreturn_t arizona_jackdet(int irq, void *data) | ||
| 257 | { | ||
| 258 | struct arizona_extcon_info *info = data; | ||
| 259 | struct arizona *arizona = info->arizona; | ||
| 260 | unsigned int val; | ||
| 261 | int ret; | ||
| 262 | |||
| 263 | pm_runtime_get_sync(info->dev); | ||
| 264 | |||
| 265 | mutex_lock(&info->lock); | ||
| 266 | |||
| 267 | ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val); | ||
| 268 | if (ret != 0) { | ||
| 269 | dev_err(arizona->dev, "Failed to read jackdet status: %d\n", | ||
| 270 | ret); | ||
| 271 | mutex_unlock(&info->lock); | ||
| 272 | pm_runtime_put_autosuspend(info->dev); | ||
| 273 | return IRQ_NONE; | ||
| 274 | } | ||
| 275 | |||
| 276 | if (val & ARIZONA_JD1_STS) { | ||
| 277 | dev_dbg(arizona->dev, "Detected jack\n"); | ||
| 278 | ret = extcon_set_cable_state_(&info->edev, | ||
| 279 | ARIZONA_CABLE_MECHANICAL, true); | ||
| 280 | |||
| 281 | if (ret != 0) | ||
| 282 | dev_err(arizona->dev, "Mechanical report failed: %d\n", | ||
| 283 | ret); | ||
| 284 | |||
| 285 | arizona_start_mic(info); | ||
| 286 | } else { | ||
| 287 | dev_dbg(arizona->dev, "Detected jack removal\n"); | ||
| 288 | |||
| 289 | arizona_stop_mic(info); | ||
| 290 | |||
| 291 | ret = extcon_update_state(&info->edev, 0xffffffff, 0); | ||
| 292 | if (ret != 0) | ||
| 293 | dev_err(arizona->dev, "Removal report failed: %d\n", | ||
| 294 | ret); | ||
| 295 | } | ||
| 296 | |||
| 297 | mutex_unlock(&info->lock); | ||
| 298 | |||
| 299 | pm_runtime_mark_last_busy(info->dev); | ||
| 300 | pm_runtime_put_autosuspend(info->dev); | ||
| 301 | |||
| 302 | return IRQ_HANDLED; | ||
| 303 | } | ||
| 304 | |||
| 305 | static int __devinit arizona_extcon_probe(struct platform_device *pdev) | ||
| 306 | { | ||
| 307 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | ||
| 308 | struct arizona_pdata *pdata; | ||
| 309 | struct arizona_extcon_info *info; | ||
| 310 | int ret, mode; | ||
| 311 | |||
| 312 | pdata = dev_get_platdata(arizona->dev); | ||
| 313 | |||
| 314 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); | ||
| 315 | if (!info) { | ||
| 316 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
| 317 | ret = -ENOMEM; | ||
| 318 | goto err; | ||
| 319 | } | ||
| 320 | |||
| 321 | info->micvdd = devm_regulator_get(arizona->dev, "MICVDD"); | ||
| 322 | if (IS_ERR(info->micvdd)) { | ||
| 323 | ret = PTR_ERR(info->micvdd); | ||
| 324 | dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret); | ||
| 325 | goto err; | ||
| 326 | } | ||
| 327 | |||
| 328 | mutex_init(&info->lock); | ||
| 329 | info->arizona = arizona; | ||
| 330 | info->dev = &pdev->dev; | ||
| 331 | info->detecting = true; | ||
| 332 | platform_set_drvdata(pdev, info); | ||
| 333 | |||
| 334 | switch (arizona->type) { | ||
| 335 | case WM5102: | ||
| 336 | switch (arizona->rev) { | ||
| 337 | case 0: | ||
| 338 | info->micd_reva = true; | ||
| 339 | break; | ||
| 340 | default: | ||
| 341 | break; | ||
| 342 | } | ||
| 343 | break; | ||
| 344 | default: | ||
| 345 | break; | ||
| 346 | } | ||
| 347 | |||
| 348 | info->edev.name = "Headset Jack"; | ||
| 349 | info->edev.supported_cable = arizona_cable; | ||
| 350 | |||
| 351 | ret = extcon_dev_register(&info->edev, arizona->dev); | ||
| 352 | if (ret < 0) { | ||
| 353 | dev_err(arizona->dev, "extcon_dev_regster() failed: %d\n", | ||
| 354 | ret); | ||
| 355 | goto err; | ||
| 356 | } | ||
| 357 | |||
| 358 | if (pdata->num_micd_configs) { | ||
| 359 | info->micd_modes = pdata->micd_configs; | ||
| 360 | info->micd_num_modes = pdata->num_micd_configs; | ||
| 361 | } else { | ||
| 362 | info->micd_modes = micd_default_modes; | ||
| 363 | info->micd_num_modes = ARRAY_SIZE(micd_default_modes); | ||
| 364 | } | ||
| 365 | |||
| 366 | if (arizona->pdata.micd_pol_gpio > 0) { | ||
| 367 | if (info->micd_modes[0].gpio) | ||
| 368 | mode = GPIOF_OUT_INIT_HIGH; | ||
| 369 | else | ||
| 370 | mode = GPIOF_OUT_INIT_LOW; | ||
| 371 | |||
| 372 | ret = devm_gpio_request_one(&pdev->dev, | ||
| 373 | arizona->pdata.micd_pol_gpio, | ||
| 374 | mode, | ||
| 375 | "MICD polarity"); | ||
| 376 | if (ret != 0) { | ||
| 377 | dev_err(arizona->dev, "Failed to request GPIO%d: %d\n", | ||
| 378 | arizona->pdata.micd_pol_gpio, ret); | ||
| 379 | goto err_register; | ||
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | arizona_extcon_set_mode(info, 0); | ||
| 384 | |||
| 385 | pm_runtime_enable(&pdev->dev); | ||
| 386 | pm_runtime_idle(&pdev->dev); | ||
| 387 | pm_runtime_get_sync(&pdev->dev); | ||
| 388 | |||
| 389 | ret = arizona_request_irq(arizona, ARIZONA_IRQ_JD_RISE, | ||
| 390 | "JACKDET rise", arizona_jackdet, info); | ||
| 391 | if (ret != 0) { | ||
| 392 | dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n", | ||
| 393 | ret); | ||
| 394 | goto err_register; | ||
| 395 | } | ||
| 396 | |||
| 397 | ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 1); | ||
| 398 | if (ret != 0) { | ||
| 399 | dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n", | ||
| 400 | ret); | ||
| 401 | goto err_rise; | ||
| 402 | } | ||
| 403 | |||
| 404 | ret = arizona_request_irq(arizona, ARIZONA_IRQ_JD_FALL, | ||
| 405 | "JACKDET fall", arizona_jackdet, info); | ||
| 406 | if (ret != 0) { | ||
| 407 | dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret); | ||
| 408 | goto err_rise_wake; | ||
| 409 | } | ||
| 410 | |||
| 411 | ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 1); | ||
| 412 | if (ret != 0) { | ||
| 413 | dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n", | ||
| 414 | ret); | ||
| 415 | goto err_fall; | ||
| 416 | } | ||
| 417 | |||
| 418 | ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET, | ||
| 419 | "MICDET", arizona_micdet, info); | ||
| 420 | if (ret != 0) { | ||
| 421 | dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret); | ||
| 422 | goto err_fall_wake; | ||
| 423 | } | ||
| 424 | |||
| 425 | regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, | ||
| 426 | ARIZONA_MICD_BIAS_STARTTIME_MASK | | ||
| 427 | ARIZONA_MICD_RATE_MASK, | ||
| 428 | 7 << ARIZONA_MICD_BIAS_STARTTIME_SHIFT | | ||
| 429 | 8 << ARIZONA_MICD_RATE_SHIFT); | ||
| 430 | |||
| 431 | arizona_clk32k_enable(arizona); | ||
| 432 | regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE, | ||
| 433 | ARIZONA_JD1_DB, ARIZONA_JD1_DB); | ||
| 434 | regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, | ||
| 435 | ARIZONA_JD1_ENA, ARIZONA_JD1_ENA); | ||
| 436 | |||
| 437 | pm_runtime_put(&pdev->dev); | ||
| 438 | |||
| 439 | return 0; | ||
| 440 | |||
| 441 | err_fall_wake: | ||
| 442 | arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 0); | ||
| 443 | err_fall: | ||
| 444 | arizona_free_irq(arizona, ARIZONA_IRQ_JD_FALL, info); | ||
| 445 | err_rise_wake: | ||
| 446 | arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 0); | ||
| 447 | err_rise: | ||
| 448 | arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info); | ||
| 449 | err_register: | ||
| 450 | pm_runtime_disable(&pdev->dev); | ||
| 451 | extcon_dev_unregister(&info->edev); | ||
| 452 | err: | ||
| 453 | return ret; | ||
| 454 | } | ||
| 455 | |||
| 456 | static int __devexit arizona_extcon_remove(struct platform_device *pdev) | ||
| 457 | { | ||
| 458 | struct arizona_extcon_info *info = platform_get_drvdata(pdev); | ||
| 459 | struct arizona *arizona = info->arizona; | ||
| 460 | |||
| 461 | pm_runtime_disable(&pdev->dev); | ||
| 462 | |||
| 463 | arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 0); | ||
| 464 | arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 0); | ||
| 465 | arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info); | ||
| 466 | arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info); | ||
| 467 | arizona_free_irq(arizona, ARIZONA_IRQ_JD_FALL, info); | ||
| 468 | regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, | ||
| 469 | ARIZONA_JD1_ENA, 0); | ||
| 470 | arizona_clk32k_disable(arizona); | ||
| 471 | extcon_dev_unregister(&info->edev); | ||
| 472 | |||
| 473 | return 0; | ||
| 474 | } | ||
| 475 | |||
| 476 | static struct platform_driver arizona_extcon_driver = { | ||
| 477 | .driver = { | ||
| 478 | .name = "arizona-extcon", | ||
| 479 | .owner = THIS_MODULE, | ||
| 480 | }, | ||
| 481 | .probe = arizona_extcon_probe, | ||
| 482 | .remove = __devexit_p(arizona_extcon_remove), | ||
| 483 | }; | ||
| 484 | |||
| 485 | module_platform_driver(arizona_extcon_driver); | ||
| 486 | |||
| 487 | MODULE_DESCRIPTION("Arizona Extcon driver"); | ||
| 488 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
| 489 | MODULE_LICENSE("GPL"); | ||
| 490 | MODULE_ALIAS("platform:extcon-arizona"); | ||
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c new file mode 100644 index 000000000000..920a609b2c35 --- /dev/null +++ b/drivers/extcon/extcon-max77693.c | |||
| @@ -0,0 +1,779 @@ | |||
| 1 | /* | ||
| 2 | * extcon-max77693.c - MAX77693 extcon driver to support MAX77693 MUIC | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Samsung Electrnoics | ||
| 5 | * Chanwoo Choi <cw00.choi@samsung.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/i2c.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | #include <linux/interrupt.h> | ||
| 23 | #include <linux/err.h> | ||
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <linux/mfd/max77693.h> | ||
| 26 | #include <linux/mfd/max77693-private.h> | ||
| 27 | #include <linux/extcon.h> | ||
| 28 | #include <linux/regmap.h> | ||
| 29 | #include <linux/irqdomain.h> | ||
| 30 | |||
| 31 | #define DEV_NAME "max77693-muic" | ||
| 32 | |||
| 33 | /* MAX77693 MUIC - STATUS1~3 Register */ | ||
| 34 | #define STATUS1_ADC_SHIFT (0) | ||
| 35 | #define STATUS1_ADCLOW_SHIFT (5) | ||
| 36 | #define STATUS1_ADCERR_SHIFT (6) | ||
| 37 | #define STATUS1_ADC1K_SHIFT (7) | ||
| 38 | #define STATUS1_ADC_MASK (0x1f << STATUS1_ADC_SHIFT) | ||
| 39 | #define STATUS1_ADCLOW_MASK (0x1 << STATUS1_ADCLOW_SHIFT) | ||
| 40 | #define STATUS1_ADCERR_MASK (0x1 << STATUS1_ADCERR_SHIFT) | ||
| 41 | #define STATUS1_ADC1K_MASK (0x1 << STATUS1_ADC1K_SHIFT) | ||
| 42 | |||
| 43 | #define STATUS2_CHGTYP_SHIFT (0) | ||
| 44 | #define STATUS2_CHGDETRUN_SHIFT (3) | ||
| 45 | #define STATUS2_DCDTMR_SHIFT (4) | ||
| 46 | #define STATUS2_DXOVP_SHIFT (5) | ||
| 47 | #define STATUS2_VBVOLT_SHIFT (6) | ||
| 48 | #define STATUS2_VIDRM_SHIFT (7) | ||
| 49 | #define STATUS2_CHGTYP_MASK (0x7 << STATUS2_CHGTYP_SHIFT) | ||
| 50 | #define STATUS2_CHGDETRUN_MASK (0x1 << STATUS2_CHGDETRUN_SHIFT) | ||
| 51 | #define STATUS2_DCDTMR_MASK (0x1 << STATUS2_DCDTMR_SHIFT) | ||
| 52 | #define STATUS2_DXOVP_MASK (0x1 << STATUS2_DXOVP_SHIFT) | ||
| 53 | #define STATUS2_VBVOLT_MASK (0x1 << STATUS2_VBVOLT_SHIFT) | ||
| 54 | #define STATUS2_VIDRM_MASK (0x1 << STATUS2_VIDRM_SHIFT) | ||
| 55 | |||
| 56 | #define STATUS3_OVP_SHIFT (2) | ||
| 57 | #define STATUS3_OVP_MASK (0x1 << STATUS3_OVP_SHIFT) | ||
| 58 | |||
| 59 | /* MAX77693 CDETCTRL1~2 register */ | ||
| 60 | #define CDETCTRL1_CHGDETEN_SHIFT (0) | ||
| 61 | #define CDETCTRL1_CHGTYPMAN_SHIFT (1) | ||
| 62 | #define CDETCTRL1_DCDEN_SHIFT (2) | ||
| 63 | #define CDETCTRL1_DCD2SCT_SHIFT (3) | ||
| 64 | #define CDETCTRL1_CDDELAY_SHIFT (4) | ||
| 65 | #define CDETCTRL1_DCDCPL_SHIFT (5) | ||
| 66 | #define CDETCTRL1_CDPDET_SHIFT (7) | ||
| 67 | #define CDETCTRL1_CHGDETEN_MASK (0x1 << CDETCTRL1_CHGDETEN_SHIFT) | ||
| 68 | #define CDETCTRL1_CHGTYPMAN_MASK (0x1 << CDETCTRL1_CHGTYPMAN_SHIFT) | ||
| 69 | #define CDETCTRL1_DCDEN_MASK (0x1 << CDETCTRL1_DCDEN_SHIFT) | ||
| 70 | #define CDETCTRL1_DCD2SCT_MASK (0x1 << CDETCTRL1_DCD2SCT_SHIFT) | ||
| 71 | #define CDETCTRL1_CDDELAY_MASK (0x1 << CDETCTRL1_CDDELAY_SHIFT) | ||
| 72 | #define CDETCTRL1_DCDCPL_MASK (0x1 << CDETCTRL1_DCDCPL_SHIFT) | ||
| 73 | #define CDETCTRL1_CDPDET_MASK (0x1 << CDETCTRL1_CDPDET_SHIFT) | ||
| 74 | |||
| 75 | #define CDETCTRL2_VIDRMEN_SHIFT (1) | ||
| 76 | #define CDETCTRL2_DXOVPEN_SHIFT (3) | ||
| 77 | #define CDETCTRL2_VIDRMEN_MASK (0x1 << CDETCTRL2_VIDRMEN_SHIFT) | ||
| 78 | #define CDETCTRL2_DXOVPEN_MASK (0x1 << CDETCTRL2_DXOVPEN_SHIFT) | ||
| 79 | |||
| 80 | /* MAX77693 MUIC - CONTROL1~3 register */ | ||
| 81 | #define COMN1SW_SHIFT (0) | ||
| 82 | #define COMP2SW_SHIFT (3) | ||
| 83 | #define COMN1SW_MASK (0x7 << COMN1SW_SHIFT) | ||
| 84 | #define COMP2SW_MASK (0x7 << COMP2SW_SHIFT) | ||
| 85 | #define COMP_SW_MASK (COMP2SW_MASK | COMN1SW_MASK) | ||
| 86 | #define CONTROL1_SW_USB ((1 << COMP2SW_SHIFT) \ | ||
| 87 | | (1 << COMN1SW_SHIFT)) | ||
| 88 | #define CONTROL1_SW_AUDIO ((2 << COMP2SW_SHIFT) \ | ||
| 89 | | (2 << COMN1SW_SHIFT)) | ||
| 90 | #define CONTROL1_SW_UART ((3 << COMP2SW_SHIFT) \ | ||
| 91 | | (3 << COMN1SW_SHIFT)) | ||
| 92 | #define CONTROL1_SW_OPEN ((0 << COMP2SW_SHIFT) \ | ||
| 93 | | (0 << COMN1SW_SHIFT)) | ||
| 94 | |||
| 95 | #define CONTROL2_LOWPWR_SHIFT (0) | ||
| 96 | #define CONTROL2_ADCEN_SHIFT (1) | ||
| 97 | #define CONTROL2_CPEN_SHIFT (2) | ||
| 98 | #define CONTROL2_SFOUTASRT_SHIFT (3) | ||
| 99 | #define CONTROL2_SFOUTORD_SHIFT (4) | ||
| 100 | #define CONTROL2_ACCDET_SHIFT (5) | ||
| 101 | #define CONTROL2_USBCPINT_SHIFT (6) | ||
| 102 | #define CONTROL2_RCPS_SHIFT (7) | ||
| 103 | #define CONTROL2_LOWPWR_MASK (0x1 << CONTROL2_LOWPWR_SHIFT) | ||
| 104 | #define CONTROL2_ADCEN_MASK (0x1 << CONTROL2_ADCEN_SHIFT) | ||
| 105 | #define CONTROL2_CPEN_MASK (0x1 << CONTROL2_CPEN_SHIFT) | ||
| 106 | #define CONTROL2_SFOUTASRT_MASK (0x1 << CONTROL2_SFOUTASRT_SHIFT) | ||
| 107 | #define CONTROL2_SFOUTORD_MASK (0x1 << CONTROL2_SFOUTORD_SHIFT) | ||
| 108 | #define CONTROL2_ACCDET_MASK (0x1 << CONTROL2_ACCDET_SHIFT) | ||
| 109 | #define CONTROL2_USBCPINT_MASK (0x1 << CONTROL2_USBCPINT_SHIFT) | ||
| 110 | #define CONTROL2_RCPS_MASK (0x1 << CONTROL2_RCPS_SHIFT) | ||
| 111 | |||
| 112 | #define CONTROL3_JIGSET_SHIFT (0) | ||
| 113 | #define CONTROL3_BTLDSET_SHIFT (2) | ||
| 114 | #define CONTROL3_ADCDBSET_SHIFT (4) | ||
| 115 | #define CONTROL3_JIGSET_MASK (0x3 << CONTROL3_JIGSET_SHIFT) | ||
| 116 | #define CONTROL3_BTLDSET_MASK (0x3 << CONTROL3_BTLDSET_SHIFT) | ||
| 117 | #define CONTROL3_ADCDBSET_MASK (0x3 << CONTROL3_ADCDBSET_SHIFT) | ||
| 118 | |||
| 119 | enum max77693_muic_adc_debounce_time { | ||
| 120 | ADC_DEBOUNCE_TIME_5MS = 0, | ||
| 121 | ADC_DEBOUNCE_TIME_10MS, | ||
| 122 | ADC_DEBOUNCE_TIME_25MS, | ||
| 123 | ADC_DEBOUNCE_TIME_38_62MS, | ||
| 124 | }; | ||
| 125 | |||
| 126 | struct max77693_muic_info { | ||
| 127 | struct device *dev; | ||
| 128 | struct max77693_dev *max77693; | ||
| 129 | struct extcon_dev *edev; | ||
| 130 | int prev_adc; | ||
| 131 | int prev_adc_gnd; | ||
| 132 | int prev_chg_type; | ||
| 133 | u8 status[2]; | ||
| 134 | |||
| 135 | int irq; | ||
| 136 | struct work_struct irq_work; | ||
| 137 | struct mutex mutex; | ||
| 138 | }; | ||
| 139 | |||
| 140 | enum max77693_muic_charger_type { | ||
| 141 | MAX77693_CHARGER_TYPE_NONE = 0, | ||
| 142 | MAX77693_CHARGER_TYPE_USB, | ||
| 143 | MAX77693_CHARGER_TYPE_DOWNSTREAM_PORT, | ||
| 144 | MAX77693_CHARGER_TYPE_DEDICATED_CHG, | ||
| 145 | MAX77693_CHARGER_TYPE_APPLE_500MA, | ||
| 146 | MAX77693_CHARGER_TYPE_APPLE_1A_2A, | ||
| 147 | MAX77693_CHARGER_TYPE_DEAD_BATTERY = 7, | ||
| 148 | }; | ||
| 149 | |||
| 150 | /** | ||
| 151 | * struct max77693_muic_irq | ||
| 152 | * @irq: the index of irq list of MUIC device. | ||
| 153 | * @name: the name of irq. | ||
| 154 | * @virq: the virtual irq to use irq domain | ||
| 155 | */ | ||
| 156 | struct max77693_muic_irq { | ||
| 157 | unsigned int irq; | ||
| 158 | const char *name; | ||
| 159 | unsigned int virq; | ||
| 160 | }; | ||
| 161 | |||
| 162 | static struct max77693_muic_irq muic_irqs[] = { | ||
| 163 | { MAX77693_MUIC_IRQ_INT1_ADC, "muic-ADC" }, | ||
| 164 | { MAX77693_MUIC_IRQ_INT1_ADC_LOW, "muic-ADCLOW" }, | ||
| 165 | { MAX77693_MUIC_IRQ_INT1_ADC_ERR, "muic-ADCError" }, | ||
| 166 | { MAX77693_MUIC_IRQ_INT1_ADC1K, "muic-ADC1K" }, | ||
| 167 | { MAX77693_MUIC_IRQ_INT2_CHGTYP, "muic-CHGTYP" }, | ||
| 168 | { MAX77693_MUIC_IRQ_INT2_CHGDETREUN, "muic-CHGDETREUN" }, | ||
| 169 | { MAX77693_MUIC_IRQ_INT2_DCDTMR, "muic-DCDTMR" }, | ||
| 170 | { MAX77693_MUIC_IRQ_INT2_DXOVP, "muic-DXOVP" }, | ||
| 171 | { MAX77693_MUIC_IRQ_INT2_VBVOLT, "muic-VBVOLT" }, | ||
| 172 | { MAX77693_MUIC_IRQ_INT2_VIDRM, "muic-VIDRM" }, | ||
| 173 | { MAX77693_MUIC_IRQ_INT3_EOC, "muic-EOC" }, | ||
| 174 | { MAX77693_MUIC_IRQ_INT3_CGMBC, "muic-CGMBC" }, | ||
| 175 | { MAX77693_MUIC_IRQ_INT3_OVP, "muic-OVP" }, | ||
| 176 | { MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR, "muic-MBCCHG_ERR" }, | ||
| 177 | { MAX77693_MUIC_IRQ_INT3_CHG_ENABLED, "muic-CHG_ENABLED" }, | ||
| 178 | { MAX77693_MUIC_IRQ_INT3_BAT_DET, "muic-BAT_DET" }, | ||
| 179 | }; | ||
| 180 | |||
| 181 | /* Define supported accessory type */ | ||
| 182 | enum max77693_muic_acc_type { | ||
| 183 | MAX77693_MUIC_ADC_GROUND = 0x0, | ||
| 184 | MAX77693_MUIC_ADC_SEND_END_BUTTON, | ||
| 185 | MAX77693_MUIC_ADC_REMOTE_S1_BUTTON, | ||
| 186 | MAX77693_MUIC_ADC_REMOTE_S2_BUTTON, | ||
| 187 | MAX77693_MUIC_ADC_REMOTE_S3_BUTTON, | ||
| 188 | MAX77693_MUIC_ADC_REMOTE_S4_BUTTON, | ||
| 189 | MAX77693_MUIC_ADC_REMOTE_S5_BUTTON, | ||
| 190 | MAX77693_MUIC_ADC_REMOTE_S6_BUTTON, | ||
| 191 | MAX77693_MUIC_ADC_REMOTE_S7_BUTTON, | ||
| 192 | MAX77693_MUIC_ADC_REMOTE_S8_BUTTON, | ||
| 193 | MAX77693_MUIC_ADC_REMOTE_S9_BUTTON, | ||
| 194 | MAX77693_MUIC_ADC_REMOTE_S10_BUTTON, | ||
| 195 | MAX77693_MUIC_ADC_REMOTE_S11_BUTTON, | ||
| 196 | MAX77693_MUIC_ADC_REMOTE_S12_BUTTON, | ||
| 197 | MAX77693_MUIC_ADC_RESERVED_ACC_1, | ||
| 198 | MAX77693_MUIC_ADC_RESERVED_ACC_2, | ||
| 199 | MAX77693_MUIC_ADC_RESERVED_ACC_3, | ||
| 200 | MAX77693_MUIC_ADC_RESERVED_ACC_4, | ||
| 201 | MAX77693_MUIC_ADC_RESERVED_ACC_5, | ||
| 202 | MAX77693_MUIC_ADC_CEA936_AUDIO, | ||
| 203 | MAX77693_MUIC_ADC_PHONE_POWERED_DEV, | ||
| 204 | MAX77693_MUIC_ADC_TTY_CONVERTER, | ||
| 205 | MAX77693_MUIC_ADC_UART_CABLE, | ||
| 206 | MAX77693_MUIC_ADC_CEA936A_TYPE1_CHG, | ||
| 207 | MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF, | ||
| 208 | MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON, | ||
| 209 | MAX77693_MUIC_ADC_AV_CABLE_NOLOAD, | ||
| 210 | MAX77693_MUIC_ADC_CEA936A_TYPE2_CHG, | ||
| 211 | MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF, | ||
| 212 | MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON, | ||
| 213 | MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE, | ||
| 214 | MAX77693_MUIC_ADC_OPEN, | ||
| 215 | |||
| 216 | /* The below accessories have same ADC value so ADCLow and | ||
| 217 | ADC1K bit is used to separate specific accessory */ | ||
| 218 | MAX77693_MUIC_GND_USB_OTG = 0x100, /* ADC:0x0, ADCLow:0, ADC1K:0 */ | ||
| 219 | MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* ADC:0x0, ADCLow:1, ADC1K:0 */ | ||
| 220 | MAX77693_MUIC_GND_MHL_CABLE = 0x103, /* ADC:0x0, ADCLow:1, ADC1K:1 */ | ||
| 221 | }; | ||
| 222 | |||
| 223 | /* MAX77693 MUIC device support below list of accessories(external connector) */ | ||
| 224 | const char *max77693_extcon_cable[] = { | ||
| 225 | [0] = "USB", | ||
| 226 | [1] = "USB-Host", | ||
| 227 | [2] = "TA", | ||
| 228 | [3] = "Fast-charger", | ||
| 229 | [4] = "Slow-charger", | ||
| 230 | [5] = "Charge-downstream", | ||
| 231 | [6] = "MHL", | ||
| 232 | [7] = "Audio-video-load", | ||
| 233 | [8] = "Audio-video-noload", | ||
| 234 | [9] = "JIG", | ||
| 235 | |||
| 236 | NULL, | ||
| 237 | }; | ||
| 238 | |||
| 239 | static int max77693_muic_set_debounce_time(struct max77693_muic_info *info, | ||
| 240 | enum max77693_muic_adc_debounce_time time) | ||
| 241 | { | ||
| 242 | int ret = 0; | ||
| 243 | u8 ctrl3; | ||
| 244 | |||
| 245 | switch (time) { | ||
| 246 | case ADC_DEBOUNCE_TIME_5MS: | ||
| 247 | case ADC_DEBOUNCE_TIME_10MS: | ||
| 248 | case ADC_DEBOUNCE_TIME_25MS: | ||
| 249 | case ADC_DEBOUNCE_TIME_38_62MS: | ||
| 250 | ret = max77693_read_reg(info->max77693->regmap_muic, | ||
| 251 | MAX77693_MUIC_REG_CTRL3, &ctrl3); | ||
| 252 | ctrl3 &= ~CONTROL3_ADCDBSET_MASK; | ||
| 253 | ctrl3 |= (time << CONTROL3_ADCDBSET_SHIFT); | ||
| 254 | |||
| 255 | ret = max77693_write_reg(info->max77693->regmap_muic, | ||
| 256 | MAX77693_MUIC_REG_CTRL3, ctrl3); | ||
| 257 | if (ret) { | ||
| 258 | dev_err(info->dev, "failed to set ADC debounce time\n"); | ||
| 259 | ret = -EINVAL; | ||
| 260 | } | ||
| 261 | break; | ||
| 262 | default: | ||
| 263 | dev_err(info->dev, "invalid ADC debounce time\n"); | ||
| 264 | ret = -EINVAL; | ||
| 265 | break; | ||
| 266 | } | ||
| 267 | |||
| 268 | return ret; | ||
| 269 | }; | ||
| 270 | |||
| 271 | static int max77693_muic_set_path(struct max77693_muic_info *info, | ||
| 272 | u8 val, bool attached) | ||
| 273 | { | ||
| 274 | int ret = 0; | ||
| 275 | u8 ctrl1, ctrl2 = 0; | ||
| 276 | |||
| 277 | if (attached) | ||
| 278 | ctrl1 = val; | ||
| 279 | else | ||
| 280 | ctrl1 = CONTROL1_SW_OPEN; | ||
| 281 | |||
| 282 | ret = max77693_update_reg(info->max77693->regmap_muic, | ||
| 283 | MAX77693_MUIC_REG_CTRL1, ctrl1, COMP_SW_MASK); | ||
| 284 | if (ret < 0) { | ||
| 285 | dev_err(info->dev, "failed to update MUIC register\n"); | ||
| 286 | goto out; | ||
| 287 | } | ||
| 288 | |||
| 289 | if (attached) | ||
| 290 | ctrl2 |= CONTROL2_CPEN_MASK; /* LowPwr=0, CPEn=1 */ | ||
| 291 | else | ||
| 292 | ctrl2 |= CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */ | ||
| 293 | |||
| 294 | ret = max77693_update_reg(info->max77693->regmap_muic, | ||
| 295 | MAX77693_MUIC_REG_CTRL2, ctrl2, | ||
| 296 | CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK); | ||
| 297 | if (ret < 0) { | ||
| 298 | dev_err(info->dev, "failed to update MUIC register\n"); | ||
| 299 | goto out; | ||
| 300 | } | ||
| 301 | |||
| 302 | dev_info(info->dev, | ||
| 303 | "CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n", | ||
| 304 | ctrl1, ctrl2, attached ? "attached" : "detached"); | ||
| 305 | out: | ||
| 306 | return ret; | ||
| 307 | } | ||
| 308 | |||
| 309 | static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info, | ||
| 310 | bool attached) | ||
| 311 | { | ||
| 312 | int ret = 0; | ||
| 313 | int type; | ||
| 314 | int adc, adc1k, adclow; | ||
| 315 | |||
| 316 | if (attached) { | ||
| 317 | adc = info->status[0] & STATUS1_ADC_MASK; | ||
| 318 | adclow = info->status[0] & STATUS1_ADCLOW_MASK; | ||
| 319 | adclow >>= STATUS1_ADCLOW_SHIFT; | ||
| 320 | adc1k = info->status[0] & STATUS1_ADC1K_MASK; | ||
| 321 | adc1k >>= STATUS1_ADC1K_SHIFT; | ||
| 322 | |||
| 323 | /** | ||
| 324 | * [0x1][ADCLow][ADC1K] | ||
| 325 | * [0x1 0 0 ] : USB_OTG | ||
| 326 | * [0x1 1 0 ] : Audio Video Cable with load | ||
| 327 | * [0x1 1 1 ] : MHL | ||
| 328 | */ | ||
| 329 | type = ((0x1 << 8) | (adclow << 1) | adc1k); | ||
| 330 | |||
| 331 | /* Store previous ADC value to handle accessory | ||
| 332 | when accessory will be detached */ | ||
| 333 | info->prev_adc = adc; | ||
| 334 | info->prev_adc_gnd = type; | ||
| 335 | } else | ||
| 336 | type = info->prev_adc_gnd; | ||
| 337 | |||
| 338 | switch (type) { | ||
| 339 | case MAX77693_MUIC_GND_USB_OTG: | ||
| 340 | /* USB_OTG */ | ||
| 341 | ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached); | ||
| 342 | if (ret < 0) | ||
| 343 | goto out; | ||
| 344 | extcon_set_cable_state(info->edev, "USB-Host", attached); | ||
| 345 | break; | ||
| 346 | case MAX77693_MUIC_GND_AV_CABLE_LOAD: | ||
| 347 | /* Audio Video Cable with load */ | ||
| 348 | ret = max77693_muic_set_path(info, CONTROL1_SW_AUDIO, attached); | ||
| 349 | if (ret < 0) | ||
| 350 | goto out; | ||
| 351 | extcon_set_cable_state(info->edev, | ||
| 352 | "Audio-video-load", attached); | ||
| 353 | break; | ||
| 354 | case MAX77693_MUIC_GND_MHL_CABLE: | ||
| 355 | /* MHL */ | ||
| 356 | extcon_set_cable_state(info->edev, "MHL", attached); | ||
| 357 | break; | ||
| 358 | default: | ||
| 359 | dev_err(info->dev, "faild to detect %s accessory\n", | ||
| 360 | attached ? "attached" : "detached"); | ||
| 361 | dev_err(info->dev, "- adc:0x%x, adclow:0x%x, adc1k:0x%x\n", | ||
| 362 | adc, adclow, adc1k); | ||
| 363 | ret = -EINVAL; | ||
| 364 | break; | ||
| 365 | } | ||
| 366 | |||
| 367 | out: | ||
| 368 | return ret; | ||
| 369 | } | ||
| 370 | |||
| 371 | static int max77693_muic_adc_handler(struct max77693_muic_info *info, | ||
| 372 | int curr_adc, bool attached) | ||
| 373 | { | ||
| 374 | int ret = 0; | ||
| 375 | int adc; | ||
| 376 | |||
| 377 | if (attached) { | ||
| 378 | /* Store ADC value to handle accessory | ||
| 379 | when accessory will be detached */ | ||
| 380 | info->prev_adc = curr_adc; | ||
| 381 | adc = curr_adc; | ||
| 382 | } else | ||
| 383 | adc = info->prev_adc; | ||
| 384 | |||
| 385 | dev_info(info->dev, | ||
| 386 | "external connector is %s (adc:0x%02x, prev_adc:0x%x)\n", | ||
| 387 | attached ? "attached" : "detached", curr_adc, info->prev_adc); | ||
| 388 | |||
| 389 | switch (adc) { | ||
| 390 | case MAX77693_MUIC_ADC_GROUND: | ||
| 391 | /* USB_OTG/MHL/Audio */ | ||
| 392 | max77693_muic_adc_ground_handler(info, attached); | ||
| 393 | break; | ||
| 394 | case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF: | ||
| 395 | case MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON: | ||
| 396 | /* USB */ | ||
| 397 | ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached); | ||
| 398 | if (ret < 0) | ||
| 399 | goto out; | ||
| 400 | extcon_set_cable_state(info->edev, "USB", attached); | ||
| 401 | break; | ||
| 402 | case MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF: | ||
| 403 | case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON: | ||
| 404 | /* JIG */ | ||
| 405 | ret = max77693_muic_set_path(info, CONTROL1_SW_UART, attached); | ||
| 406 | if (ret < 0) | ||
| 407 | goto out; | ||
| 408 | extcon_set_cable_state(info->edev, "JIG", attached); | ||
| 409 | break; | ||
| 410 | case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE: | ||
| 411 | /* Audio Video cable with no-load */ | ||
| 412 | ret = max77693_muic_set_path(info, CONTROL1_SW_AUDIO, attached); | ||
| 413 | if (ret < 0) | ||
| 414 | goto out; | ||
| 415 | extcon_set_cable_state(info->edev, | ||
| 416 | "Audio-video-noload", attached); | ||
| 417 | break; | ||
| 418 | case MAX77693_MUIC_ADC_SEND_END_BUTTON: | ||
| 419 | case MAX77693_MUIC_ADC_REMOTE_S1_BUTTON: | ||
| 420 | case MAX77693_MUIC_ADC_REMOTE_S2_BUTTON: | ||
| 421 | case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON: | ||
| 422 | case MAX77693_MUIC_ADC_REMOTE_S4_BUTTON: | ||
| 423 | case MAX77693_MUIC_ADC_REMOTE_S5_BUTTON: | ||
| 424 | case MAX77693_MUIC_ADC_REMOTE_S6_BUTTON: | ||
| 425 | case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON: | ||
| 426 | case MAX77693_MUIC_ADC_REMOTE_S8_BUTTON: | ||
| 427 | case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON: | ||
| 428 | case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON: | ||
| 429 | case MAX77693_MUIC_ADC_REMOTE_S11_BUTTON: | ||
| 430 | case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON: | ||
| 431 | case MAX77693_MUIC_ADC_RESERVED_ACC_1: | ||
| 432 | case MAX77693_MUIC_ADC_RESERVED_ACC_2: | ||
| 433 | case MAX77693_MUIC_ADC_RESERVED_ACC_3: | ||
| 434 | case MAX77693_MUIC_ADC_RESERVED_ACC_4: | ||
| 435 | case MAX77693_MUIC_ADC_RESERVED_ACC_5: | ||
| 436 | case MAX77693_MUIC_ADC_CEA936_AUDIO: | ||
| 437 | case MAX77693_MUIC_ADC_PHONE_POWERED_DEV: | ||
| 438 | case MAX77693_MUIC_ADC_TTY_CONVERTER: | ||
| 439 | case MAX77693_MUIC_ADC_UART_CABLE: | ||
| 440 | case MAX77693_MUIC_ADC_CEA936A_TYPE1_CHG: | ||
| 441 | case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: | ||
| 442 | case MAX77693_MUIC_ADC_CEA936A_TYPE2_CHG: | ||
| 443 | /* This accessory isn't used in general case if it is specially | ||
| 444 | needed to detect additional accessory, should implement | ||
| 445 | proper operation when this accessory is attached/detached. */ | ||
| 446 | dev_info(info->dev, | ||
| 447 | "accessory is %s but it isn't used (adc:0x%x)\n", | ||
| 448 | attached ? "attached" : "detached", adc); | ||
| 449 | goto out; | ||
| 450 | default: | ||
| 451 | dev_err(info->dev, | ||
| 452 | "failed to detect %s accessory (adc:0x%x)\n", | ||
| 453 | attached ? "attached" : "detached", adc); | ||
| 454 | ret = -EINVAL; | ||
| 455 | goto out; | ||
| 456 | } | ||
| 457 | |||
| 458 | out: | ||
| 459 | return ret; | ||
| 460 | } | ||
| 461 | |||
| 462 | static int max77693_muic_chg_handler(struct max77693_muic_info *info, | ||
| 463 | int curr_chg_type, bool attached) | ||
| 464 | { | ||
| 465 | int ret = 0; | ||
| 466 | int chg_type; | ||
| 467 | |||
| 468 | if (attached) { | ||
| 469 | /* Store previous charger type to control | ||
| 470 | when charger accessory will be detached */ | ||
| 471 | info->prev_chg_type = curr_chg_type; | ||
| 472 | chg_type = curr_chg_type; | ||
| 473 | } else | ||
| 474 | chg_type = info->prev_chg_type; | ||
| 475 | |||
| 476 | dev_info(info->dev, | ||
| 477 | "external connector is %s(chg_type:0x%x, prev_chg_type:0x%x)\n", | ||
| 478 | attached ? "attached" : "detached", | ||
| 479 | curr_chg_type, info->prev_chg_type); | ||
| 480 | |||
| 481 | switch (chg_type) { | ||
| 482 | case MAX77693_CHARGER_TYPE_USB: | ||
| 483 | ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached); | ||
| 484 | if (ret < 0) | ||
| 485 | goto out; | ||
| 486 | extcon_set_cable_state(info->edev, "USB", attached); | ||
| 487 | break; | ||
| 488 | case MAX77693_CHARGER_TYPE_DOWNSTREAM_PORT: | ||
| 489 | extcon_set_cable_state(info->edev, | ||
| 490 | "Charge-downstream", attached); | ||
| 491 | break; | ||
| 492 | case MAX77693_CHARGER_TYPE_DEDICATED_CHG: | ||
| 493 | extcon_set_cable_state(info->edev, "TA", attached); | ||
| 494 | break; | ||
| 495 | case MAX77693_CHARGER_TYPE_APPLE_500MA: | ||
| 496 | extcon_set_cable_state(info->edev, "Slow-charger", attached); | ||
| 497 | break; | ||
| 498 | case MAX77693_CHARGER_TYPE_APPLE_1A_2A: | ||
| 499 | extcon_set_cable_state(info->edev, "Fast-charger", attached); | ||
| 500 | break; | ||
| 501 | case MAX77693_CHARGER_TYPE_DEAD_BATTERY: | ||
| 502 | break; | ||
| 503 | default: | ||
| 504 | dev_err(info->dev, | ||
| 505 | "failed to detect %s accessory (chg_type:0x%x)\n", | ||
| 506 | attached ? "attached" : "detached", chg_type); | ||
| 507 | ret = -EINVAL; | ||
| 508 | goto out; | ||
| 509 | } | ||
| 510 | |||
| 511 | out: | ||
| 512 | return ret; | ||
| 513 | } | ||
| 514 | |||
| 515 | static void max77693_muic_irq_work(struct work_struct *work) | ||
| 516 | { | ||
| 517 | struct max77693_muic_info *info = container_of(work, | ||
| 518 | struct max77693_muic_info, irq_work); | ||
| 519 | int curr_adc, curr_chg_type; | ||
| 520 | int irq_type = -1; | ||
| 521 | int i, ret = 0; | ||
| 522 | bool attached = true; | ||
| 523 | |||
| 524 | if (!info->edev) | ||
| 525 | return; | ||
| 526 | |||
| 527 | mutex_lock(&info->mutex); | ||
| 528 | |||
| 529 | for (i = 0 ; i < ARRAY_SIZE(muic_irqs) ; i++) | ||
| 530 | if (info->irq == muic_irqs[i].virq) | ||
| 531 | irq_type = muic_irqs[i].irq; | ||
| 532 | |||
| 533 | ret = max77693_bulk_read(info->max77693->regmap_muic, | ||
| 534 | MAX77693_MUIC_REG_STATUS1, 2, info->status); | ||
| 535 | if (ret) { | ||
| 536 | dev_err(info->dev, "failed to read MUIC register\n"); | ||
| 537 | mutex_unlock(&info->mutex); | ||
| 538 | return; | ||
| 539 | } | ||
| 540 | |||
| 541 | switch (irq_type) { | ||
| 542 | case MAX77693_MUIC_IRQ_INT1_ADC: | ||
| 543 | case MAX77693_MUIC_IRQ_INT1_ADC_LOW: | ||
| 544 | case MAX77693_MUIC_IRQ_INT1_ADC_ERR: | ||
| 545 | case MAX77693_MUIC_IRQ_INT1_ADC1K: | ||
| 546 | /* Handle all of accessory except for | ||
| 547 | type of charger accessory */ | ||
| 548 | curr_adc = info->status[0] & STATUS1_ADC_MASK; | ||
| 549 | curr_adc >>= STATUS1_ADC_SHIFT; | ||
| 550 | |||
| 551 | /* Check accossory state which is either detached or attached */ | ||
| 552 | if (curr_adc == MAX77693_MUIC_ADC_OPEN) | ||
| 553 | attached = false; | ||
| 554 | |||
| 555 | ret = max77693_muic_adc_handler(info, curr_adc, attached); | ||
| 556 | break; | ||
| 557 | case MAX77693_MUIC_IRQ_INT2_CHGTYP: | ||
| 558 | case MAX77693_MUIC_IRQ_INT2_CHGDETREUN: | ||
| 559 | case MAX77693_MUIC_IRQ_INT2_DCDTMR: | ||
| 560 | case MAX77693_MUIC_IRQ_INT2_DXOVP: | ||
| 561 | case MAX77693_MUIC_IRQ_INT2_VBVOLT: | ||
| 562 | case MAX77693_MUIC_IRQ_INT2_VIDRM: | ||
| 563 | /* Handle charger accessory */ | ||
| 564 | curr_chg_type = info->status[1] & STATUS2_CHGTYP_MASK; | ||
| 565 | curr_chg_type >>= STATUS2_CHGTYP_SHIFT; | ||
| 566 | |||
| 567 | /* Check charger accossory state which | ||
| 568 | is either detached or attached */ | ||
| 569 | if (curr_chg_type == MAX77693_CHARGER_TYPE_NONE) | ||
| 570 | attached = false; | ||
| 571 | |||
| 572 | ret = max77693_muic_chg_handler(info, curr_chg_type, attached); | ||
| 573 | break; | ||
| 574 | case MAX77693_MUIC_IRQ_INT3_EOC: | ||
| 575 | case MAX77693_MUIC_IRQ_INT3_CGMBC: | ||
| 576 | case MAX77693_MUIC_IRQ_INT3_OVP: | ||
| 577 | case MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR: | ||
| 578 | case MAX77693_MUIC_IRQ_INT3_CHG_ENABLED: | ||
| 579 | case MAX77693_MUIC_IRQ_INT3_BAT_DET: | ||
| 580 | break; | ||
| 581 | default: | ||
| 582 | dev_err(info->dev, "muic interrupt: irq %d occurred\n", | ||
| 583 | irq_type); | ||
| 584 | break; | ||
| 585 | } | ||
| 586 | |||
| 587 | if (ret < 0) | ||
| 588 | dev_err(info->dev, "failed to handle MUIC interrupt\n"); | ||
| 589 | |||
| 590 | mutex_unlock(&info->mutex); | ||
| 591 | |||
| 592 | return; | ||
| 593 | } | ||
| 594 | |||
| 595 | static irqreturn_t max77693_muic_irq_handler(int irq, void *data) | ||
| 596 | { | ||
| 597 | struct max77693_muic_info *info = data; | ||
| 598 | |||
| 599 | info->irq = irq; | ||
| 600 | schedule_work(&info->irq_work); | ||
| 601 | |||
| 602 | return IRQ_HANDLED; | ||
| 603 | } | ||
| 604 | |||
| 605 | static struct regmap_config max77693_muic_regmap_config = { | ||
| 606 | .reg_bits = 8, | ||
| 607 | .val_bits = 8, | ||
| 608 | }; | ||
| 609 | |||
| 610 | static int max77693_muic_detect_accessory(struct max77693_muic_info *info) | ||
| 611 | { | ||
| 612 | int ret = 0; | ||
| 613 | int adc, chg_type; | ||
| 614 | |||
| 615 | mutex_lock(&info->mutex); | ||
| 616 | |||
| 617 | /* Read STATUSx register to detect accessory */ | ||
| 618 | ret = max77693_bulk_read(info->max77693->regmap_muic, | ||
| 619 | MAX77693_MUIC_REG_STATUS1, 2, info->status); | ||
| 620 | if (ret) { | ||
| 621 | dev_err(info->dev, "failed to read MUIC register\n"); | ||
| 622 | mutex_unlock(&info->mutex); | ||
| 623 | return -EINVAL; | ||
| 624 | } | ||
| 625 | |||
| 626 | adc = info->status[0] & STATUS1_ADC_MASK; | ||
| 627 | adc >>= STATUS1_ADC_SHIFT; | ||
| 628 | |||
| 629 | if (adc != MAX77693_MUIC_ADC_OPEN) { | ||
| 630 | dev_info(info->dev, | ||
| 631 | "external connector is attached (adc:0x%02x)\n", adc); | ||
| 632 | |||
| 633 | ret = max77693_muic_adc_handler(info, adc, true); | ||
| 634 | if (ret < 0) | ||
| 635 | dev_err(info->dev, "failed to detect accessory\n"); | ||
| 636 | goto out; | ||
| 637 | } | ||
| 638 | |||
| 639 | chg_type = info->status[1] & STATUS2_CHGTYP_MASK; | ||
| 640 | chg_type >>= STATUS2_CHGTYP_SHIFT; | ||
| 641 | |||
| 642 | if (chg_type != MAX77693_CHARGER_TYPE_NONE) { | ||
| 643 | dev_info(info->dev, | ||
| 644 | "external connector is attached (chg_type:0x%x)\n", | ||
| 645 | chg_type); | ||
| 646 | |||
| 647 | max77693_muic_chg_handler(info, chg_type, true); | ||
| 648 | if (ret < 0) | ||
| 649 | dev_err(info->dev, "failed to detect charger accessory\n"); | ||
| 650 | } | ||
| 651 | |||
| 652 | out: | ||
| 653 | mutex_unlock(&info->mutex); | ||
| 654 | return ret; | ||
| 655 | } | ||
| 656 | |||
| 657 | static int __devinit max77693_muic_probe(struct platform_device *pdev) | ||
| 658 | { | ||
| 659 | struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent); | ||
| 660 | struct max77693_muic_info *info; | ||
| 661 | int ret, i; | ||
| 662 | u8 id; | ||
| 663 | |||
| 664 | info = kzalloc(sizeof(struct max77693_muic_info), GFP_KERNEL); | ||
| 665 | if (!info) { | ||
| 666 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
| 667 | ret = -ENOMEM; | ||
| 668 | goto err_kfree; | ||
| 669 | } | ||
| 670 | info->dev = &pdev->dev; | ||
| 671 | info->max77693 = max77693; | ||
| 672 | info->max77693->regmap_muic = regmap_init_i2c(info->max77693->muic, | ||
| 673 | &max77693_muic_regmap_config); | ||
| 674 | if (IS_ERR(info->max77693->regmap_muic)) { | ||
| 675 | ret = PTR_ERR(info->max77693->regmap_muic); | ||
| 676 | dev_err(max77693->dev, | ||
| 677 | "failed to allocate register map: %d\n", ret); | ||
| 678 | goto err_regmap; | ||
| 679 | } | ||
| 680 | platform_set_drvdata(pdev, info); | ||
| 681 | mutex_init(&info->mutex); | ||
| 682 | |||
| 683 | INIT_WORK(&info->irq_work, max77693_muic_irq_work); | ||
| 684 | |||
| 685 | /* Support irq domain for MAX77693 MUIC device */ | ||
| 686 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) { | ||
| 687 | struct max77693_muic_irq *muic_irq = &muic_irqs[i]; | ||
| 688 | int virq = 0; | ||
| 689 | |||
| 690 | virq = irq_create_mapping(max77693->irq_domain, muic_irq->irq); | ||
| 691 | if (!virq) | ||
| 692 | goto err_irq; | ||
| 693 | muic_irq->virq = virq; | ||
| 694 | |||
| 695 | ret = request_threaded_irq(virq, NULL, | ||
| 696 | max77693_muic_irq_handler, | ||
| 697 | 0, muic_irq->name, info); | ||
| 698 | if (ret) { | ||
| 699 | dev_err(&pdev->dev, | ||
| 700 | "failed: irq request (IRQ: %d," | ||
| 701 | " error :%d)\n", | ||
| 702 | muic_irq->irq, ret); | ||
| 703 | |||
| 704 | for (i = i - 1; i >= 0; i--) | ||
| 705 | free_irq(muic_irq->virq, info); | ||
| 706 | goto err_irq; | ||
| 707 | } | ||
| 708 | } | ||
| 709 | |||
| 710 | /* Initialize extcon device */ | ||
| 711 | info->edev = kzalloc(sizeof(struct extcon_dev), GFP_KERNEL); | ||
| 712 | if (!info->edev) { | ||
| 713 | dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); | ||
| 714 | ret = -ENOMEM; | ||
| 715 | goto err_irq; | ||
| 716 | } | ||
| 717 | info->edev->name = DEV_NAME; | ||
| 718 | info->edev->supported_cable = max77693_extcon_cable; | ||
| 719 | ret = extcon_dev_register(info->edev, NULL); | ||
| 720 | if (ret) { | ||
| 721 | dev_err(&pdev->dev, "failed to register extcon device\n"); | ||
| 722 | goto err_extcon; | ||
| 723 | } | ||
| 724 | |||
| 725 | /* Check revision number of MUIC device*/ | ||
| 726 | ret = max77693_read_reg(info->max77693->regmap_muic, | ||
| 727 | MAX77693_MUIC_REG_ID, &id); | ||
| 728 | if (ret < 0) { | ||
| 729 | dev_err(&pdev->dev, "failed to read revision number\n"); | ||
| 730 | goto err_extcon; | ||
| 731 | } | ||
| 732 | dev_info(info->dev, "device ID : 0x%x\n", id); | ||
| 733 | |||
| 734 | /* Set ADC debounce time */ | ||
| 735 | max77693_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS); | ||
| 736 | |||
| 737 | /* Detect accessory on boot */ | ||
| 738 | max77693_muic_detect_accessory(info); | ||
| 739 | |||
| 740 | return ret; | ||
| 741 | |||
| 742 | err_extcon: | ||
| 743 | kfree(info->edev); | ||
| 744 | err_irq: | ||
| 745 | err_regmap: | ||
| 746 | kfree(info); | ||
| 747 | err_kfree: | ||
| 748 | return ret; | ||
| 749 | } | ||
| 750 | |||
| 751 | static int __devexit max77693_muic_remove(struct platform_device *pdev) | ||
| 752 | { | ||
| 753 | struct max77693_muic_info *info = platform_get_drvdata(pdev); | ||
| 754 | int i; | ||
| 755 | |||
| 756 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) | ||
| 757 | free_irq(muic_irqs[i].virq, info); | ||
| 758 | cancel_work_sync(&info->irq_work); | ||
| 759 | extcon_dev_unregister(info->edev); | ||
| 760 | kfree(info); | ||
| 761 | |||
| 762 | return 0; | ||
| 763 | } | ||
| 764 | |||
| 765 | static struct platform_driver max77693_muic_driver = { | ||
| 766 | .driver = { | ||
| 767 | .name = DEV_NAME, | ||
| 768 | .owner = THIS_MODULE, | ||
| 769 | }, | ||
| 770 | .probe = max77693_muic_probe, | ||
| 771 | .remove = __devexit_p(max77693_muic_remove), | ||
| 772 | }; | ||
| 773 | |||
| 774 | module_platform_driver(max77693_muic_driver); | ||
| 775 | |||
| 776 | MODULE_DESCRIPTION("Maxim MAX77693 Extcon driver"); | ||
| 777 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); | ||
| 778 | MODULE_LICENSE("GPL"); | ||
| 779 | MODULE_ALIAS("platform:extcon-max77693"); | ||
diff --git a/drivers/extcon/extcon_class.c b/drivers/extcon/extcon_class.c index 159aeb07b3ba..f6419f9db76c 100644 --- a/drivers/extcon/extcon_class.c +++ b/drivers/extcon/extcon_class.c | |||
| @@ -65,7 +65,7 @@ const char *extcon_cable_name[] = { | |||
| 65 | NULL, | 65 | NULL, |
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | struct class *extcon_class; | 68 | static struct class *extcon_class; |
| 69 | #if defined(CONFIG_ANDROID) | 69 | #if defined(CONFIG_ANDROID) |
| 70 | static struct class_compat *switch_class; | 70 | static struct class_compat *switch_class; |
| 71 | #endif /* CONFIG_ANDROID */ | 71 | #endif /* CONFIG_ANDROID */ |
diff --git a/drivers/extcon/extcon_gpio.c b/drivers/extcon/extcon_gpio.c index 8a0dcc11c7c7..fe3db45fa83c 100644 --- a/drivers/extcon/extcon_gpio.c +++ b/drivers/extcon/extcon_gpio.c | |||
| @@ -105,25 +105,25 @@ static int __devinit gpio_extcon_probe(struct platform_device *pdev) | |||
| 105 | 105 | ||
| 106 | ret = extcon_dev_register(&extcon_data->edev, &pdev->dev); | 106 | ret = extcon_dev_register(&extcon_data->edev, &pdev->dev); |
| 107 | if (ret < 0) | 107 | if (ret < 0) |
| 108 | goto err_extcon_dev_register; | 108 | return ret; |
| 109 | 109 | ||
| 110 | ret = gpio_request_one(extcon_data->gpio, GPIOF_DIR_IN, pdev->name); | 110 | ret = gpio_request_one(extcon_data->gpio, GPIOF_DIR_IN, pdev->name); |
| 111 | if (ret < 0) | 111 | if (ret < 0) |
| 112 | goto err_request_gpio; | 112 | goto err; |
| 113 | 113 | ||
| 114 | INIT_DELAYED_WORK(&extcon_data->work, gpio_extcon_work); | 114 | INIT_DELAYED_WORK(&extcon_data->work, gpio_extcon_work); |
| 115 | 115 | ||
| 116 | extcon_data->irq = gpio_to_irq(extcon_data->gpio); | 116 | extcon_data->irq = gpio_to_irq(extcon_data->gpio); |
| 117 | if (extcon_data->irq < 0) { | 117 | if (extcon_data->irq < 0) { |
| 118 | ret = extcon_data->irq; | 118 | ret = extcon_data->irq; |
| 119 | goto err_detect_irq_num_failed; | 119 | goto err; |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | ret = request_any_context_irq(extcon_data->irq, gpio_irq_handler, | 122 | ret = request_any_context_irq(extcon_data->irq, gpio_irq_handler, |
| 123 | pdata->irq_flags, pdev->name, | 123 | pdata->irq_flags, pdev->name, |
| 124 | extcon_data); | 124 | extcon_data); |
| 125 | if (ret < 0) | 125 | if (ret < 0) |
| 126 | goto err_request_irq; | 126 | goto err; |
| 127 | 127 | ||
| 128 | platform_set_drvdata(pdev, extcon_data); | 128 | platform_set_drvdata(pdev, extcon_data); |
| 129 | /* Perform initial detection */ | 129 | /* Perform initial detection */ |
| @@ -131,13 +131,8 @@ static int __devinit gpio_extcon_probe(struct platform_device *pdev) | |||
| 131 | 131 | ||
| 132 | return 0; | 132 | return 0; |
| 133 | 133 | ||
| 134 | err_request_irq: | 134 | err: |
| 135 | err_detect_irq_num_failed: | ||
| 136 | gpio_free(extcon_data->gpio); | ||
| 137 | err_request_gpio: | ||
| 138 | extcon_dev_unregister(&extcon_data->edev); | 135 | extcon_dev_unregister(&extcon_data->edev); |
| 139 | err_extcon_dev_register: | ||
| 140 | devm_kfree(&pdev->dev, extcon_data); | ||
| 141 | 136 | ||
| 142 | return ret; | 137 | return ret; |
| 143 | } | 138 | } |
| @@ -148,9 +143,7 @@ static int __devexit gpio_extcon_remove(struct platform_device *pdev) | |||
| 148 | 143 | ||
| 149 | cancel_delayed_work_sync(&extcon_data->work); | 144 | cancel_delayed_work_sync(&extcon_data->work); |
| 150 | free_irq(extcon_data->irq, extcon_data); | 145 | free_irq(extcon_data->irq, extcon_data); |
| 151 | gpio_free(extcon_data->gpio); | ||
| 152 | extcon_dev_unregister(&extcon_data->edev); | 146 | extcon_dev_unregister(&extcon_data->edev); |
| 153 | devm_kfree(&pdev->dev, extcon_data); | ||
| 154 | 147 | ||
| 155 | return 0; | 148 | return 0; |
| 156 | } | 149 | } |
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index b9426a6592ee..0614ff3a7d7e 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h | |||
| @@ -411,7 +411,7 @@ enum { | |||
| 411 | #define HV_PRESENT_BIT 0x80000000 | 411 | #define HV_PRESENT_BIT 0x80000000 |
| 412 | 412 | ||
| 413 | #define HV_LINUX_GUEST_ID_LO 0x00000000 | 413 | #define HV_LINUX_GUEST_ID_LO 0x00000000 |
| 414 | #define HV_LINUX_GUEST_ID_HI 0xB16B00B5 | 414 | #define HV_LINUX_GUEST_ID_HI 2976579765 |
| 415 | #define HV_LINUX_GUEST_ID (((u64)HV_LINUX_GUEST_ID_HI << 32) | \ | 415 | #define HV_LINUX_GUEST_ID (((u64)HV_LINUX_GUEST_ID_HI << 32) | \ |
| 416 | HV_LINUX_GUEST_ID_LO) | 416 | HV_LINUX_GUEST_ID_LO) |
| 417 | 417 | ||
diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c index de31cae1ba53..74fad941c56c 100644 --- a/drivers/power/ds2780_battery.c +++ b/drivers/power/ds2780_battery.c | |||
| @@ -39,7 +39,6 @@ struct ds2780_device_info { | |||
| 39 | struct device *dev; | 39 | struct device *dev; |
| 40 | struct power_supply bat; | 40 | struct power_supply bat; |
| 41 | struct device *w1_dev; | 41 | struct device *w1_dev; |
| 42 | struct task_struct *mutex_holder; | ||
| 43 | }; | 42 | }; |
| 44 | 43 | ||
| 45 | enum current_types { | 44 | enum current_types { |
| @@ -64,10 +63,7 @@ static inline struct power_supply *to_power_supply(struct device *dev) | |||
| 64 | static inline int ds2780_battery_io(struct ds2780_device_info *dev_info, | 63 | static inline int ds2780_battery_io(struct ds2780_device_info *dev_info, |
| 65 | char *buf, int addr, size_t count, int io) | 64 | char *buf, int addr, size_t count, int io) |
| 66 | { | 65 | { |
| 67 | if (dev_info->mutex_holder == current) | 66 | return w1_ds2780_io(dev_info->w1_dev, buf, addr, count, io); |
| 68 | return w1_ds2780_io_nolock(dev_info->w1_dev, buf, addr, count, io); | ||
| 69 | else | ||
| 70 | return w1_ds2780_io(dev_info->w1_dev, buf, addr, count, io); | ||
| 71 | } | 67 | } |
| 72 | 68 | ||
| 73 | static inline int ds2780_read8(struct ds2780_device_info *dev_info, u8 *val, | 69 | static inline int ds2780_read8(struct ds2780_device_info *dev_info, u8 *val, |
| @@ -779,7 +775,6 @@ static int __devinit ds2780_battery_probe(struct platform_device *pdev) | |||
| 779 | dev_info->bat.properties = ds2780_battery_props; | 775 | dev_info->bat.properties = ds2780_battery_props; |
| 780 | dev_info->bat.num_properties = ARRAY_SIZE(ds2780_battery_props); | 776 | dev_info->bat.num_properties = ARRAY_SIZE(ds2780_battery_props); |
| 781 | dev_info->bat.get_property = ds2780_battery_get_property; | 777 | dev_info->bat.get_property = ds2780_battery_get_property; |
| 782 | dev_info->mutex_holder = current; | ||
| 783 | 778 | ||
| 784 | ret = power_supply_register(&pdev->dev, &dev_info->bat); | 779 | ret = power_supply_register(&pdev->dev, &dev_info->bat); |
| 785 | if (ret) { | 780 | if (ret) { |
| @@ -809,8 +804,6 @@ static int __devinit ds2780_battery_probe(struct platform_device *pdev) | |||
| 809 | goto fail_remove_bin_file; | 804 | goto fail_remove_bin_file; |
| 810 | } | 805 | } |
| 811 | 806 | ||
| 812 | dev_info->mutex_holder = NULL; | ||
| 813 | |||
| 814 | return 0; | 807 | return 0; |
| 815 | 808 | ||
| 816 | fail_remove_bin_file: | 809 | fail_remove_bin_file: |
| @@ -830,8 +823,6 @@ static int __devexit ds2780_battery_remove(struct platform_device *pdev) | |||
| 830 | { | 823 | { |
| 831 | struct ds2780_device_info *dev_info = platform_get_drvdata(pdev); | 824 | struct ds2780_device_info *dev_info = platform_get_drvdata(pdev); |
| 832 | 825 | ||
| 833 | dev_info->mutex_holder = current; | ||
| 834 | |||
| 835 | /* remove attributes */ | 826 | /* remove attributes */ |
| 836 | sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group); | 827 | sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group); |
| 837 | 828 | ||
diff --git a/drivers/power/ds2781_battery.c b/drivers/power/ds2781_battery.c index 975684a40f15..5f92a4bb33f9 100644 --- a/drivers/power/ds2781_battery.c +++ b/drivers/power/ds2781_battery.c | |||
| @@ -37,7 +37,6 @@ struct ds2781_device_info { | |||
| 37 | struct device *dev; | 37 | struct device *dev; |
| 38 | struct power_supply bat; | 38 | struct power_supply bat; |
| 39 | struct device *w1_dev; | 39 | struct device *w1_dev; |
| 40 | struct task_struct *mutex_holder; | ||
| 41 | }; | 40 | }; |
| 42 | 41 | ||
| 43 | enum current_types { | 42 | enum current_types { |
| @@ -62,11 +61,7 @@ static inline struct power_supply *to_power_supply(struct device *dev) | |||
| 62 | static inline int ds2781_battery_io(struct ds2781_device_info *dev_info, | 61 | static inline int ds2781_battery_io(struct ds2781_device_info *dev_info, |
| 63 | char *buf, int addr, size_t count, int io) | 62 | char *buf, int addr, size_t count, int io) |
| 64 | { | 63 | { |
| 65 | if (dev_info->mutex_holder == current) | 64 | return w1_ds2781_io(dev_info->w1_dev, buf, addr, count, io); |
| 66 | return w1_ds2781_io_nolock(dev_info->w1_dev, buf, addr, | ||
| 67 | count, io); | ||
| 68 | else | ||
| 69 | return w1_ds2781_io(dev_info->w1_dev, buf, addr, count, io); | ||
| 70 | } | 65 | } |
| 71 | 66 | ||
| 72 | int w1_ds2781_read(struct ds2781_device_info *dev_info, char *buf, | 67 | int w1_ds2781_read(struct ds2781_device_info *dev_info, char *buf, |
| @@ -775,7 +770,6 @@ static int __devinit ds2781_battery_probe(struct platform_device *pdev) | |||
| 775 | dev_info->bat.properties = ds2781_battery_props; | 770 | dev_info->bat.properties = ds2781_battery_props; |
| 776 | dev_info->bat.num_properties = ARRAY_SIZE(ds2781_battery_props); | 771 | dev_info->bat.num_properties = ARRAY_SIZE(ds2781_battery_props); |
| 777 | dev_info->bat.get_property = ds2781_battery_get_property; | 772 | dev_info->bat.get_property = ds2781_battery_get_property; |
| 778 | dev_info->mutex_holder = current; | ||
| 779 | 773 | ||
| 780 | ret = power_supply_register(&pdev->dev, &dev_info->bat); | 774 | ret = power_supply_register(&pdev->dev, &dev_info->bat); |
| 781 | if (ret) { | 775 | if (ret) { |
| @@ -805,8 +799,6 @@ static int __devinit ds2781_battery_probe(struct platform_device *pdev) | |||
| 805 | goto fail_remove_bin_file; | 799 | goto fail_remove_bin_file; |
| 806 | } | 800 | } |
| 807 | 801 | ||
| 808 | dev_info->mutex_holder = NULL; | ||
| 809 | |||
| 810 | return 0; | 802 | return 0; |
| 811 | 803 | ||
| 812 | fail_remove_bin_file: | 804 | fail_remove_bin_file: |
| @@ -826,8 +818,6 @@ static int __devexit ds2781_battery_remove(struct platform_device *pdev) | |||
| 826 | { | 818 | { |
| 827 | struct ds2781_device_info *dev_info = platform_get_drvdata(pdev); | 819 | struct ds2781_device_info *dev_info = platform_get_drvdata(pdev); |
| 828 | 820 | ||
| 829 | dev_info->mutex_holder = current; | ||
| 830 | |||
| 831 | /* remove attributes */ | 821 | /* remove attributes */ |
| 832 | sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2781_attr_group); | 822 | sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2781_attr_group); |
| 833 | 823 | ||
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c index a0c8965c1a79..530a2d309063 100644 --- a/drivers/w1/masters/ds1wm.c +++ b/drivers/w1/masters/ds1wm.c | |||
| @@ -334,7 +334,9 @@ static void ds1wm_search(void *data, struct w1_master *master_dev, | |||
| 334 | return; | 334 | return; |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | mutex_lock(&master_dev->bus_mutex); | ||
| 337 | if (ds1wm_reset(ds1wm_data)) { | 338 | if (ds1wm_reset(ds1wm_data)) { |
| 339 | mutex_unlock(&master_dev->bus_mutex); | ||
| 338 | dev_dbg(&ds1wm_data->pdev->dev, | 340 | dev_dbg(&ds1wm_data->pdev->dev, |
| 339 | "pass: %d reset error (or no slaves)\n", pass); | 341 | "pass: %d reset error (or no slaves)\n", pass); |
| 340 | break; | 342 | break; |
| @@ -387,6 +389,7 @@ static void ds1wm_search(void *data, struct w1_master *master_dev, | |||
| 387 | 389 | ||
| 388 | } | 390 | } |
| 389 | if (ds1wm_data->read_error) { | 391 | if (ds1wm_data->read_error) { |
| 392 | mutex_unlock(&master_dev->bus_mutex); | ||
| 390 | dev_err(&ds1wm_data->pdev->dev, | 393 | dev_err(&ds1wm_data->pdev->dev, |
| 391 | "pass: %d read error, retrying\n", pass); | 394 | "pass: %d read error, retrying\n", pass); |
| 392 | break; | 395 | break; |
| @@ -400,6 +403,7 @@ static void ds1wm_search(void *data, struct w1_master *master_dev, | |||
| 400 | dev_dbg(&ds1wm_data->pdev->dev, | 403 | dev_dbg(&ds1wm_data->pdev->dev, |
| 401 | "pass: %d resetting bus\n", pass); | 404 | "pass: %d resetting bus\n", pass); |
| 402 | ds1wm_reset(ds1wm_data); | 405 | ds1wm_reset(ds1wm_data); |
| 406 | mutex_unlock(&master_dev->bus_mutex); | ||
| 403 | if ((r_prime & ((u64)1 << 63)) && (d & ((u64)1 << 63))) { | 407 | if ((r_prime & ((u64)1 << 63)) && (d & ((u64)1 << 63))) { |
| 404 | dev_err(&ds1wm_data->pdev->dev, | 408 | dev_err(&ds1wm_data->pdev->dev, |
| 405 | "pass: %d bus error, retrying\n", pass); | 409 | "pass: %d bus error, retrying\n", pass); |
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c index 291897c881be..4b0fcf3c2d03 100644 --- a/drivers/w1/masters/omap_hdq.c +++ b/drivers/w1/masters/omap_hdq.c | |||
| @@ -178,6 +178,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status) | |||
| 178 | hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT); | 178 | hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT); |
| 179 | if (ret == 0) { | 179 | if (ret == 0) { |
| 180 | dev_dbg(hdq_data->dev, "TX wait elapsed\n"); | 180 | dev_dbg(hdq_data->dev, "TX wait elapsed\n"); |
| 181 | ret = -ETIMEDOUT; | ||
| 181 | goto out; | 182 | goto out; |
| 182 | } | 183 | } |
| 183 | 184 | ||
| @@ -185,7 +186,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status) | |||
| 185 | /* check irqstatus */ | 186 | /* check irqstatus */ |
| 186 | if (!(*status & OMAP_HDQ_INT_STATUS_TXCOMPLETE)) { | 187 | if (!(*status & OMAP_HDQ_INT_STATUS_TXCOMPLETE)) { |
| 187 | dev_dbg(hdq_data->dev, "timeout waiting for" | 188 | dev_dbg(hdq_data->dev, "timeout waiting for" |
| 188 | "TXCOMPLETE/RXCOMPLETE, %x", *status); | 189 | " TXCOMPLETE/RXCOMPLETE, %x", *status); |
| 189 | ret = -ETIMEDOUT; | 190 | ret = -ETIMEDOUT; |
| 190 | goto out; | 191 | goto out; |
| 191 | } | 192 | } |
| @@ -196,7 +197,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status) | |||
| 196 | OMAP_HDQ_FLAG_CLEAR, &tmp_status); | 197 | OMAP_HDQ_FLAG_CLEAR, &tmp_status); |
| 197 | if (ret) { | 198 | if (ret) { |
| 198 | dev_dbg(hdq_data->dev, "timeout waiting GO bit" | 199 | dev_dbg(hdq_data->dev, "timeout waiting GO bit" |
| 199 | "return to zero, %x", tmp_status); | 200 | " return to zero, %x", tmp_status); |
| 200 | } | 201 | } |
| 201 | 202 | ||
| 202 | out: | 203 | out: |
| @@ -339,7 +340,7 @@ static int omap_hdq_break(struct hdq_data *hdq_data) | |||
| 339 | &tmp_status); | 340 | &tmp_status); |
| 340 | if (ret) | 341 | if (ret) |
| 341 | dev_dbg(hdq_data->dev, "timeout waiting INIT&GO bits" | 342 | dev_dbg(hdq_data->dev, "timeout waiting INIT&GO bits" |
| 342 | "return to zero, %x", tmp_status); | 343 | " return to zero, %x", tmp_status); |
| 343 | 344 | ||
| 344 | out: | 345 | out: |
| 345 | mutex_unlock(&hdq_data->hdq_mutex); | 346 | mutex_unlock(&hdq_data->hdq_mutex); |
| @@ -351,7 +352,6 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val) | |||
| 351 | { | 352 | { |
| 352 | int ret = 0; | 353 | int ret = 0; |
| 353 | u8 status; | 354 | u8 status; |
| 354 | unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT; | ||
| 355 | 355 | ||
| 356 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); | 356 | ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); |
| 357 | if (ret < 0) { | 357 | if (ret < 0) { |
| @@ -369,22 +369,20 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val) | |||
| 369 | OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO, | 369 | OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO, |
| 370 | OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO); | 370 | OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO); |
| 371 | /* | 371 | /* |
| 372 | * The RX comes immediately after TX. It | 372 | * The RX comes immediately after TX. |
| 373 | * triggers another interrupt before we | ||
| 374 | * sleep. So we have to wait for RXCOMPLETE bit. | ||
| 375 | */ | 373 | */ |
| 376 | while (!(hdq_data->hdq_irqstatus | 374 | wait_event_timeout(hdq_wait_queue, |
| 377 | & OMAP_HDQ_INT_STATUS_RXCOMPLETE) | 375 | (hdq_data->hdq_irqstatus |
| 378 | && time_before(jiffies, timeout)) { | 376 | & OMAP_HDQ_INT_STATUS_RXCOMPLETE), |
| 379 | schedule_timeout_uninterruptible(1); | 377 | OMAP_HDQ_TIMEOUT); |
| 380 | } | 378 | |
| 381 | hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, 0, | 379 | hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, 0, |
| 382 | OMAP_HDQ_CTRL_STATUS_DIR); | 380 | OMAP_HDQ_CTRL_STATUS_DIR); |
| 383 | status = hdq_data->hdq_irqstatus; | 381 | status = hdq_data->hdq_irqstatus; |
| 384 | /* check irqstatus */ | 382 | /* check irqstatus */ |
| 385 | if (!(status & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) { | 383 | if (!(status & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) { |
| 386 | dev_dbg(hdq_data->dev, "timeout waiting for" | 384 | dev_dbg(hdq_data->dev, "timeout waiting for" |
| 387 | "RXCOMPLETE, %x", status); | 385 | " RXCOMPLETE, %x", status); |
| 388 | ret = -ETIMEDOUT; | 386 | ret = -ETIMEDOUT; |
| 389 | goto out; | 387 | goto out; |
| 390 | } | 388 | } |
| @@ -394,7 +392,7 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val) | |||
| 394 | out: | 392 | out: |
| 395 | mutex_unlock(&hdq_data->hdq_mutex); | 393 | mutex_unlock(&hdq_data->hdq_mutex); |
| 396 | rtn: | 394 | rtn: |
| 397 | return 0; | 395 | return ret; |
| 398 | 396 | ||
| 399 | } | 397 | } |
| 400 | 398 | ||
| @@ -456,7 +454,7 @@ static int omap_hdq_put(struct hdq_data *hdq_data) | |||
| 456 | 454 | ||
| 457 | if (0 == hdq_data->hdq_usecount) { | 455 | if (0 == hdq_data->hdq_usecount) { |
| 458 | dev_dbg(hdq_data->dev, "attempt to decrement use count" | 456 | dev_dbg(hdq_data->dev, "attempt to decrement use count" |
| 459 | "when it is zero"); | 457 | " when it is zero"); |
| 460 | ret = -EINVAL; | 458 | ret = -EINVAL; |
| 461 | } else { | 459 | } else { |
| 462 | hdq_data->hdq_usecount--; | 460 | hdq_data->hdq_usecount--; |
| @@ -524,7 +522,7 @@ static void omap_w1_write_byte(void *_hdq, u8 byte) | |||
| 524 | mutex_unlock(&hdq_data->hdq_mutex); | 522 | mutex_unlock(&hdq_data->hdq_mutex); |
| 525 | 523 | ||
| 526 | ret = hdq_write_byte(hdq_data, byte, &status); | 524 | ret = hdq_write_byte(hdq_data, byte, &status); |
| 527 | if (ret == 0) { | 525 | if (ret < 0) { |
| 528 | dev_dbg(hdq_data->dev, "TX failure:Ctrl status %x\n", status); | 526 | dev_dbg(hdq_data->dev, "TX failure:Ctrl status %x\n", status); |
| 529 | return; | 527 | return; |
| 530 | } | 528 | } |
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index eb9e376d6244..67526690acbc 100644 --- a/drivers/w1/slaves/Kconfig +++ b/drivers/w1/slaves/Kconfig | |||
| @@ -94,6 +94,19 @@ config W1_SLAVE_DS2781 | |||
| 94 | 94 | ||
| 95 | If you are unsure, say N. | 95 | If you are unsure, say N. |
| 96 | 96 | ||
| 97 | config W1_SLAVE_DS28E04 | ||
| 98 | tristate "4096-Bit Addressable 1-Wire EEPROM with PIO (DS28E04-100)" | ||
| 99 | depends on W1 | ||
| 100 | select CRC16 | ||
| 101 | help | ||
| 102 | If you enable this you will have the DS28E04-100 | ||
| 103 | chip support. | ||
| 104 | |||
| 105 | Say Y here if you want to use a 1-wire | ||
| 106 | 4kb EEPROM with PIO family device (DS28E04). | ||
| 107 | |||
| 108 | If you are unsure, say N. | ||
| 109 | |||
| 97 | config W1_SLAVE_BQ27000 | 110 | config W1_SLAVE_BQ27000 |
| 98 | tristate "BQ27000 slave support" | 111 | tristate "BQ27000 slave support" |
| 99 | depends on W1 | 112 | depends on W1 |
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile index c4f1859fb520..05188f6aab5a 100644 --- a/drivers/w1/slaves/Makefile +++ b/drivers/w1/slaves/Makefile | |||
| @@ -12,3 +12,4 @@ obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o | |||
| 12 | obj-$(CONFIG_W1_SLAVE_DS2780) += w1_ds2780.o | 12 | obj-$(CONFIG_W1_SLAVE_DS2780) += w1_ds2780.o |
| 13 | obj-$(CONFIG_W1_SLAVE_DS2781) += w1_ds2781.o | 13 | obj-$(CONFIG_W1_SLAVE_DS2781) += w1_ds2781.o |
| 14 | obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o | 14 | obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o |
| 15 | obj-$(CONFIG_W1_SLAVE_DS28E04) += w1_ds28e04.o | ||
diff --git a/drivers/w1/slaves/w1_bq27000.c b/drivers/w1/slaves/w1_bq27000.c index 52ad812fa1e7..773dca5beafe 100644 --- a/drivers/w1/slaves/w1_bq27000.c +++ b/drivers/w1/slaves/w1_bq27000.c | |||
| @@ -31,10 +31,10 @@ static int w1_bq27000_read(struct device *dev, unsigned int reg) | |||
| 31 | u8 val; | 31 | u8 val; |
| 32 | struct w1_slave *sl = container_of(dev->parent, struct w1_slave, dev); | 32 | struct w1_slave *sl = container_of(dev->parent, struct w1_slave, dev); |
| 33 | 33 | ||
| 34 | mutex_lock(&sl->master->mutex); | 34 | mutex_lock(&sl->master->bus_mutex); |
| 35 | w1_write_8(sl->master, HDQ_CMD_READ | reg); | 35 | w1_write_8(sl->master, HDQ_CMD_READ | reg); |
| 36 | val = w1_read_8(sl->master); | 36 | val = w1_read_8(sl->master); |
| 37 | mutex_unlock(&sl->master->mutex); | 37 | mutex_unlock(&sl->master->bus_mutex); |
| 38 | 38 | ||
| 39 | return val; | 39 | return val; |
| 40 | } | 40 | } |
diff --git a/drivers/w1/slaves/w1_ds2408.c b/drivers/w1/slaves/w1_ds2408.c index 8e813eed0f0a..441ad3a3b586 100644 --- a/drivers/w1/slaves/w1_ds2408.c +++ b/drivers/w1/slaves/w1_ds2408.c | |||
| @@ -52,11 +52,11 @@ static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf) | |||
| 52 | if (!buf) | 52 | if (!buf) |
| 53 | return -EINVAL; | 53 | return -EINVAL; |
| 54 | 54 | ||
| 55 | mutex_lock(&sl->master->mutex); | 55 | mutex_lock(&sl->master->bus_mutex); |
| 56 | dev_dbg(&sl->dev, "mutex locked"); | 56 | dev_dbg(&sl->dev, "mutex locked"); |
| 57 | 57 | ||
| 58 | if (w1_reset_select_slave(sl)) { | 58 | if (w1_reset_select_slave(sl)) { |
| 59 | mutex_unlock(&sl->master->mutex); | 59 | mutex_unlock(&sl->master->bus_mutex); |
| 60 | return -EIO; | 60 | return -EIO; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| @@ -66,7 +66,7 @@ static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf) | |||
| 66 | w1_write_block(sl->master, wrbuf, 3); | 66 | w1_write_block(sl->master, wrbuf, 3); |
| 67 | *buf = w1_read_8(sl->master); | 67 | *buf = w1_read_8(sl->master); |
| 68 | 68 | ||
| 69 | mutex_unlock(&sl->master->mutex); | 69 | mutex_unlock(&sl->master->bus_mutex); |
| 70 | dev_dbg(&sl->dev, "mutex unlocked"); | 70 | dev_dbg(&sl->dev, "mutex unlocked"); |
| 71 | return 1; | 71 | return 1; |
| 72 | } | 72 | } |
| @@ -165,7 +165,7 @@ static ssize_t w1_f29_write_output( | |||
| 165 | return -EFAULT; | 165 | return -EFAULT; |
| 166 | 166 | ||
| 167 | dev_dbg(&sl->dev, "locking mutex for write_output"); | 167 | dev_dbg(&sl->dev, "locking mutex for write_output"); |
| 168 | mutex_lock(&sl->master->mutex); | 168 | mutex_lock(&sl->master->bus_mutex); |
| 169 | dev_dbg(&sl->dev, "mutex locked"); | 169 | dev_dbg(&sl->dev, "mutex locked"); |
| 170 | 170 | ||
| 171 | if (w1_reset_select_slave(sl)) | 171 | if (w1_reset_select_slave(sl)) |
| @@ -200,14 +200,14 @@ static ssize_t w1_f29_write_output( | |||
| 200 | /* read the result of the READ_PIO_REGS command */ | 200 | /* read the result of the READ_PIO_REGS command */ |
| 201 | if (w1_read_8(sl->master) == *buf) { | 201 | if (w1_read_8(sl->master) == *buf) { |
| 202 | /* success! */ | 202 | /* success! */ |
| 203 | mutex_unlock(&sl->master->mutex); | 203 | mutex_unlock(&sl->master->bus_mutex); |
| 204 | dev_dbg(&sl->dev, | 204 | dev_dbg(&sl->dev, |
| 205 | "mutex unlocked, retries:%d", retries); | 205 | "mutex unlocked, retries:%d", retries); |
| 206 | return 1; | 206 | return 1; |
| 207 | } | 207 | } |
| 208 | } | 208 | } |
| 209 | error: | 209 | error: |
| 210 | mutex_unlock(&sl->master->mutex); | 210 | mutex_unlock(&sl->master->bus_mutex); |
| 211 | dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries); | 211 | dev_dbg(&sl->dev, "mutex unlocked in error, retries:%d", retries); |
| 212 | 212 | ||
| 213 | return -EIO; | 213 | return -EIO; |
| @@ -228,7 +228,7 @@ static ssize_t w1_f29_write_activity( | |||
| 228 | if (count != 1 || off != 0) | 228 | if (count != 1 || off != 0) |
| 229 | return -EFAULT; | 229 | return -EFAULT; |
| 230 | 230 | ||
| 231 | mutex_lock(&sl->master->mutex); | 231 | mutex_lock(&sl->master->bus_mutex); |
| 232 | 232 | ||
| 233 | if (w1_reset_select_slave(sl)) | 233 | if (w1_reset_select_slave(sl)) |
| 234 | goto error; | 234 | goto error; |
| @@ -236,7 +236,7 @@ static ssize_t w1_f29_write_activity( | |||
| 236 | while (retries--) { | 236 | while (retries--) { |
| 237 | w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES); | 237 | w1_write_8(sl->master, W1_F29_FUNC_RESET_ACTIVITY_LATCHES); |
| 238 | if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) { | 238 | if (w1_read_8(sl->master) == W1_F29_SUCCESS_CONFIRM_BYTE) { |
| 239 | mutex_unlock(&sl->master->mutex); | 239 | mutex_unlock(&sl->master->bus_mutex); |
| 240 | return 1; | 240 | return 1; |
| 241 | } | 241 | } |
| 242 | if (w1_reset_resume_command(sl->master)) | 242 | if (w1_reset_resume_command(sl->master)) |
| @@ -244,7 +244,7 @@ static ssize_t w1_f29_write_activity( | |||
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | error: | 246 | error: |
| 247 | mutex_unlock(&sl->master->mutex); | 247 | mutex_unlock(&sl->master->bus_mutex); |
| 248 | return -EIO; | 248 | return -EIO; |
| 249 | } | 249 | } |
| 250 | 250 | ||
| @@ -263,7 +263,7 @@ static ssize_t w1_f29_write_status_control( | |||
| 263 | if (count != 1 || off != 0) | 263 | if (count != 1 || off != 0) |
| 264 | return -EFAULT; | 264 | return -EFAULT; |
| 265 | 265 | ||
| 266 | mutex_lock(&sl->master->mutex); | 266 | mutex_lock(&sl->master->bus_mutex); |
| 267 | 267 | ||
| 268 | if (w1_reset_select_slave(sl)) | 268 | if (w1_reset_select_slave(sl)) |
| 269 | goto error; | 269 | goto error; |
| @@ -285,12 +285,12 @@ static ssize_t w1_f29_write_status_control( | |||
| 285 | w1_write_block(sl->master, w1_buf, 3); | 285 | w1_write_block(sl->master, w1_buf, 3); |
| 286 | if (w1_read_8(sl->master) == *buf) { | 286 | if (w1_read_8(sl->master) == *buf) { |
| 287 | /* success! */ | 287 | /* success! */ |
| 288 | mutex_unlock(&sl->master->mutex); | 288 | mutex_unlock(&sl->master->bus_mutex); |
| 289 | return 1; | 289 | return 1; |
| 290 | } | 290 | } |
| 291 | } | 291 | } |
| 292 | error: | 292 | error: |
| 293 | mutex_unlock(&sl->master->mutex); | 293 | mutex_unlock(&sl->master->bus_mutex); |
| 294 | 294 | ||
| 295 | return -EIO; | 295 | return -EIO; |
| 296 | } | 296 | } |
diff --git a/drivers/w1/slaves/w1_ds2423.c b/drivers/w1/slaves/w1_ds2423.c index 7a7dbe5026f1..40a10b5ed120 100644 --- a/drivers/w1/slaves/w1_ds2423.c +++ b/drivers/w1/slaves/w1_ds2423.c | |||
| @@ -66,7 +66,7 @@ static ssize_t w1_counter_read(struct device *device, | |||
| 66 | wrbuf[0] = 0xA5; | 66 | wrbuf[0] = 0xA5; |
| 67 | wrbuf[1] = rom_addr & 0xFF; | 67 | wrbuf[1] = rom_addr & 0xFF; |
| 68 | wrbuf[2] = rom_addr >> 8; | 68 | wrbuf[2] = rom_addr >> 8; |
| 69 | mutex_lock(&dev->mutex); | 69 | mutex_lock(&dev->bus_mutex); |
| 70 | if (!w1_reset_select_slave(sl)) { | 70 | if (!w1_reset_select_slave(sl)) { |
| 71 | w1_write_block(dev, wrbuf, 3); | 71 | w1_write_block(dev, wrbuf, 3); |
| 72 | read_byte_count = 0; | 72 | read_byte_count = 0; |
| @@ -124,7 +124,7 @@ static ssize_t w1_counter_read(struct device *device, | |||
| 124 | } else { | 124 | } else { |
| 125 | c -= snprintf(out_buf + PAGE_SIZE - c, c, "Connection error"); | 125 | c -= snprintf(out_buf + PAGE_SIZE - c, c, "Connection error"); |
| 126 | } | 126 | } |
| 127 | mutex_unlock(&dev->mutex); | 127 | mutex_unlock(&dev->bus_mutex); |
| 128 | return PAGE_SIZE - c; | 128 | return PAGE_SIZE - c; |
| 129 | } | 129 | } |
| 130 | 130 | ||
diff --git a/drivers/w1/slaves/w1_ds2431.c b/drivers/w1/slaves/w1_ds2431.c index 84e2410aec1d..984b30331a45 100644 --- a/drivers/w1/slaves/w1_ds2431.c +++ b/drivers/w1/slaves/w1_ds2431.c | |||
| @@ -107,7 +107,7 @@ static ssize_t w1_f2d_read_bin(struct file *filp, struct kobject *kobj, | |||
| 107 | if (count == 0) | 107 | if (count == 0) |
| 108 | return 0; | 108 | return 0; |
| 109 | 109 | ||
| 110 | mutex_lock(&sl->master->mutex); | 110 | mutex_lock(&sl->master->bus_mutex); |
| 111 | 111 | ||
| 112 | /* read directly from the EEPROM in chunks of W1_F2D_READ_MAXLEN */ | 112 | /* read directly from the EEPROM in chunks of W1_F2D_READ_MAXLEN */ |
| 113 | while (todo > 0) { | 113 | while (todo > 0) { |
| @@ -126,7 +126,7 @@ static ssize_t w1_f2d_read_bin(struct file *filp, struct kobject *kobj, | |||
| 126 | off += W1_F2D_READ_MAXLEN; | 126 | off += W1_F2D_READ_MAXLEN; |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | mutex_unlock(&sl->master->mutex); | 129 | mutex_unlock(&sl->master->bus_mutex); |
| 130 | 130 | ||
| 131 | return count; | 131 | return count; |
| 132 | } | 132 | } |
| @@ -214,7 +214,7 @@ static ssize_t w1_f2d_write_bin(struct file *filp, struct kobject *kobj, | |||
| 214 | if (count == 0) | 214 | if (count == 0) |
| 215 | return 0; | 215 | return 0; |
| 216 | 216 | ||
| 217 | mutex_lock(&sl->master->mutex); | 217 | mutex_lock(&sl->master->bus_mutex); |
| 218 | 218 | ||
| 219 | /* Can only write data in blocks of the size of the scratchpad */ | 219 | /* Can only write data in blocks of the size of the scratchpad */ |
| 220 | addr = off; | 220 | addr = off; |
| @@ -259,7 +259,7 @@ static ssize_t w1_f2d_write_bin(struct file *filp, struct kobject *kobj, | |||
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | out_up: | 261 | out_up: |
| 262 | mutex_unlock(&sl->master->mutex); | 262 | mutex_unlock(&sl->master->bus_mutex); |
| 263 | 263 | ||
| 264 | return count; | 264 | return count; |
| 265 | } | 265 | } |
diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c index 0f7b8f9c509a..85f2cdb27fa2 100644 --- a/drivers/w1/slaves/w1_ds2433.c +++ b/drivers/w1/slaves/w1_ds2433.c | |||
| @@ -107,7 +107,7 @@ static ssize_t w1_f23_read_bin(struct file *filp, struct kobject *kobj, | |||
| 107 | if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0) | 107 | if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0) |
| 108 | return 0; | 108 | return 0; |
| 109 | 109 | ||
| 110 | mutex_lock(&sl->master->mutex); | 110 | mutex_lock(&sl->master->bus_mutex); |
| 111 | 111 | ||
| 112 | #ifdef CONFIG_W1_SLAVE_DS2433_CRC | 112 | #ifdef CONFIG_W1_SLAVE_DS2433_CRC |
| 113 | 113 | ||
| @@ -138,7 +138,7 @@ static ssize_t w1_f23_read_bin(struct file *filp, struct kobject *kobj, | |||
| 138 | #endif /* CONFIG_W1_SLAVE_DS2433_CRC */ | 138 | #endif /* CONFIG_W1_SLAVE_DS2433_CRC */ |
| 139 | 139 | ||
| 140 | out_up: | 140 | out_up: |
| 141 | mutex_unlock(&sl->master->mutex); | 141 | mutex_unlock(&sl->master->bus_mutex); |
| 142 | 142 | ||
| 143 | return count; | 143 | return count; |
| 144 | } | 144 | } |
| @@ -233,7 +233,7 @@ static ssize_t w1_f23_write_bin(struct file *filp, struct kobject *kobj, | |||
| 233 | } | 233 | } |
| 234 | #endif /* CONFIG_W1_SLAVE_DS2433_CRC */ | 234 | #endif /* CONFIG_W1_SLAVE_DS2433_CRC */ |
| 235 | 235 | ||
| 236 | mutex_lock(&sl->master->mutex); | 236 | mutex_lock(&sl->master->bus_mutex); |
| 237 | 237 | ||
| 238 | /* Can only write data to one page at a time */ | 238 | /* Can only write data to one page at a time */ |
| 239 | idx = 0; | 239 | idx = 0; |
| @@ -251,7 +251,7 @@ static ssize_t w1_f23_write_bin(struct file *filp, struct kobject *kobj, | |||
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | out_up: | 253 | out_up: |
| 254 | mutex_unlock(&sl->master->mutex); | 254 | mutex_unlock(&sl->master->bus_mutex); |
| 255 | 255 | ||
| 256 | return count; | 256 | return count; |
| 257 | } | 257 | } |
diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c index 5754c9a4f58b..aa7bd5fa2fa8 100644 --- a/drivers/w1/slaves/w1_ds2760.c +++ b/drivers/w1/slaves/w1_ds2760.c | |||
| @@ -31,7 +31,7 @@ static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count, | |||
| 31 | if (!dev) | 31 | if (!dev) |
| 32 | return 0; | 32 | return 0; |
| 33 | 33 | ||
| 34 | mutex_lock(&sl->master->mutex); | 34 | mutex_lock(&sl->master->bus_mutex); |
| 35 | 35 | ||
| 36 | if (addr > DS2760_DATA_SIZE || addr < 0) { | 36 | if (addr > DS2760_DATA_SIZE || addr < 0) { |
| 37 | count = 0; | 37 | count = 0; |
| @@ -54,7 +54,7 @@ static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count, | |||
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | out: | 56 | out: |
| 57 | mutex_unlock(&sl->master->mutex); | 57 | mutex_unlock(&sl->master->bus_mutex); |
| 58 | 58 | ||
| 59 | return count; | 59 | return count; |
| 60 | } | 60 | } |
| @@ -76,14 +76,14 @@ static int w1_ds2760_eeprom_cmd(struct device *dev, int addr, int cmd) | |||
| 76 | if (!dev) | 76 | if (!dev) |
| 77 | return -EINVAL; | 77 | return -EINVAL; |
| 78 | 78 | ||
| 79 | mutex_lock(&sl->master->mutex); | 79 | mutex_lock(&sl->master->bus_mutex); |
| 80 | 80 | ||
| 81 | if (w1_reset_select_slave(sl) == 0) { | 81 | if (w1_reset_select_slave(sl) == 0) { |
| 82 | w1_write_8(sl->master, cmd); | 82 | w1_write_8(sl->master, cmd); |
| 83 | w1_write_8(sl->master, addr); | 83 | w1_write_8(sl->master, addr); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | mutex_unlock(&sl->master->mutex); | 86 | mutex_unlock(&sl->master->bus_mutex); |
| 87 | return 0; | 87 | return 0; |
| 88 | } | 88 | } |
| 89 | 89 | ||
diff --git a/drivers/w1/slaves/w1_ds2780.c b/drivers/w1/slaves/w1_ds2780.c index 39f78c0b143c..7b09307de0ef 100644 --- a/drivers/w1/slaves/w1_ds2780.c +++ b/drivers/w1/slaves/w1_ds2780.c | |||
| @@ -60,30 +60,16 @@ int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, | |||
| 60 | if (!dev) | 60 | if (!dev) |
| 61 | return -ENODEV; | 61 | return -ENODEV; |
| 62 | 62 | ||
| 63 | mutex_lock(&sl->master->mutex); | 63 | mutex_lock(&sl->master->bus_mutex); |
| 64 | 64 | ||
| 65 | ret = w1_ds2780_do_io(dev, buf, addr, count, io); | 65 | ret = w1_ds2780_do_io(dev, buf, addr, count, io); |
| 66 | 66 | ||
| 67 | mutex_unlock(&sl->master->mutex); | 67 | mutex_unlock(&sl->master->bus_mutex); |
| 68 | 68 | ||
| 69 | return ret; | 69 | return ret; |
| 70 | } | 70 | } |
| 71 | EXPORT_SYMBOL(w1_ds2780_io); | 71 | EXPORT_SYMBOL(w1_ds2780_io); |
| 72 | 72 | ||
| 73 | int w1_ds2780_io_nolock(struct device *dev, char *buf, int addr, size_t count, | ||
| 74 | int io) | ||
| 75 | { | ||
| 76 | int ret; | ||
| 77 | |||
| 78 | if (!dev) | ||
| 79 | return -ENODEV; | ||
| 80 | |||
| 81 | ret = w1_ds2780_do_io(dev, buf, addr, count, io); | ||
| 82 | |||
| 83 | return ret; | ||
| 84 | } | ||
| 85 | EXPORT_SYMBOL(w1_ds2780_io_nolock); | ||
| 86 | |||
| 87 | int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd) | 73 | int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd) |
| 88 | { | 74 | { |
| 89 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | 75 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); |
| @@ -91,14 +77,14 @@ int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd) | |||
| 91 | if (!dev) | 77 | if (!dev) |
| 92 | return -EINVAL; | 78 | return -EINVAL; |
| 93 | 79 | ||
| 94 | mutex_lock(&sl->master->mutex); | 80 | mutex_lock(&sl->master->bus_mutex); |
| 95 | 81 | ||
| 96 | if (w1_reset_select_slave(sl) == 0) { | 82 | if (w1_reset_select_slave(sl) == 0) { |
| 97 | w1_write_8(sl->master, cmd); | 83 | w1_write_8(sl->master, cmd); |
| 98 | w1_write_8(sl->master, addr); | 84 | w1_write_8(sl->master, addr); |
| 99 | } | 85 | } |
| 100 | 86 | ||
| 101 | mutex_unlock(&sl->master->mutex); | 87 | mutex_unlock(&sl->master->bus_mutex); |
| 102 | return 0; | 88 | return 0; |
| 103 | } | 89 | } |
| 104 | EXPORT_SYMBOL(w1_ds2780_eeprom_cmd); | 90 | EXPORT_SYMBOL(w1_ds2780_eeprom_cmd); |
diff --git a/drivers/w1/slaves/w1_ds2780.h b/drivers/w1/slaves/w1_ds2780.h index 737379365021..a1fba79eb1b5 100644 --- a/drivers/w1/slaves/w1_ds2780.h +++ b/drivers/w1/slaves/w1_ds2780.h | |||
| @@ -124,8 +124,6 @@ | |||
| 124 | 124 | ||
| 125 | extern int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, | 125 | extern int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count, |
| 126 | int io); | 126 | int io); |
| 127 | extern int w1_ds2780_io_nolock(struct device *dev, char *buf, int addr, | ||
| 128 | size_t count, int io); | ||
| 129 | extern int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd); | 127 | extern int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd); |
| 130 | 128 | ||
| 131 | #endif /* !_W1_DS2780_H */ | 129 | #endif /* !_W1_DS2780_H */ |
diff --git a/drivers/w1/slaves/w1_ds2781.c b/drivers/w1/slaves/w1_ds2781.c index 0d0c7985293f..877daf74159c 100644 --- a/drivers/w1/slaves/w1_ds2781.c +++ b/drivers/w1/slaves/w1_ds2781.c | |||
| @@ -58,30 +58,16 @@ int w1_ds2781_io(struct device *dev, char *buf, int addr, size_t count, | |||
| 58 | if (!dev) | 58 | if (!dev) |
| 59 | return -ENODEV; | 59 | return -ENODEV; |
| 60 | 60 | ||
| 61 | mutex_lock(&sl->master->mutex); | 61 | mutex_lock(&sl->master->bus_mutex); |
| 62 | 62 | ||
| 63 | ret = w1_ds2781_do_io(dev, buf, addr, count, io); | 63 | ret = w1_ds2781_do_io(dev, buf, addr, count, io); |
| 64 | 64 | ||
| 65 | mutex_unlock(&sl->master->mutex); | 65 | mutex_unlock(&sl->master->bus_mutex); |
| 66 | 66 | ||
| 67 | return ret; | 67 | return ret; |
| 68 | } | 68 | } |
| 69 | EXPORT_SYMBOL(w1_ds2781_io); | 69 | EXPORT_SYMBOL(w1_ds2781_io); |
| 70 | 70 | ||
| 71 | int w1_ds2781_io_nolock(struct device *dev, char *buf, int addr, size_t count, | ||
| 72 | int io) | ||
| 73 | { | ||
| 74 | int ret; | ||
| 75 | |||
| 76 | if (!dev) | ||
| 77 | return -ENODEV; | ||
| 78 | |||
| 79 | ret = w1_ds2781_do_io(dev, buf, addr, count, io); | ||
| 80 | |||
| 81 | return ret; | ||
| 82 | } | ||
| 83 | EXPORT_SYMBOL(w1_ds2781_io_nolock); | ||
| 84 | |||
| 85 | int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd) | 71 | int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd) |
| 86 | { | 72 | { |
| 87 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); | 73 | struct w1_slave *sl = container_of(dev, struct w1_slave, dev); |
| @@ -89,14 +75,14 @@ int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd) | |||
| 89 | if (!dev) | 75 | if (!dev) |
| 90 | return -EINVAL; | 76 | return -EINVAL; |
| 91 | 77 | ||
| 92 | mutex_lock(&sl->master->mutex); | 78 | mutex_lock(&sl->master->bus_mutex); |
| 93 | 79 | ||
| 94 | if (w1_reset_select_slave(sl) == 0) { | 80 | if (w1_reset_select_slave(sl) == 0) { |
| 95 | w1_write_8(sl->master, cmd); | 81 | w1_write_8(sl->master, cmd); |
| 96 | w1_write_8(sl->master, addr); | 82 | w1_write_8(sl->master, addr); |
| 97 | } | 83 | } |
| 98 | 84 | ||
| 99 | mutex_unlock(&sl->master->mutex); | 85 | mutex_unlock(&sl->master->bus_mutex); |
| 100 | return 0; | 86 | return 0; |
| 101 | } | 87 | } |
| 102 | EXPORT_SYMBOL(w1_ds2781_eeprom_cmd); | 88 | EXPORT_SYMBOL(w1_ds2781_eeprom_cmd); |
diff --git a/drivers/w1/slaves/w1_ds2781.h b/drivers/w1/slaves/w1_ds2781.h index 82bc66497b43..557dfb0b4f64 100644 --- a/drivers/w1/slaves/w1_ds2781.h +++ b/drivers/w1/slaves/w1_ds2781.h | |||
| @@ -129,8 +129,6 @@ | |||
| 129 | 129 | ||
| 130 | extern int w1_ds2781_io(struct device *dev, char *buf, int addr, size_t count, | 130 | extern int w1_ds2781_io(struct device *dev, char *buf, int addr, size_t count, |
| 131 | int io); | 131 | int io); |
| 132 | extern int w1_ds2781_io_nolock(struct device *dev, char *buf, int addr, | ||
| 133 | size_t count, int io); | ||
| 134 | extern int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd); | 132 | extern int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd); |
| 135 | 133 | ||
| 136 | #endif /* !_W1_DS2781_H */ | 134 | #endif /* !_W1_DS2781_H */ |
diff --git a/drivers/w1/slaves/w1_ds28e04.c b/drivers/w1/slaves/w1_ds28e04.c new file mode 100644 index 000000000000..98117db595bb --- /dev/null +++ b/drivers/w1/slaves/w1_ds28e04.c | |||
| @@ -0,0 +1,469 @@ | |||
| 1 | /* | ||
| 2 | * w1_ds28e04.c - w1 family 1C (DS28E04) driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2012 Markus Franke <franke.m@sebakmt.com> | ||
| 5 | * | ||
| 6 | * This source code is licensed under the GNU General Public License, | ||
| 7 | * Version 2. See the file COPYING for more details. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/kernel.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/moduleparam.h> | ||
| 13 | #include <linux/device.h> | ||
| 14 | #include <linux/types.h> | ||
| 15 | #include <linux/delay.h> | ||
| 16 | #include <linux/slab.h> | ||
| 17 | #include <linux/crc16.h> | ||
| 18 | #include <linux/uaccess.h> | ||
| 19 | |||
| 20 | #define CRC16_INIT 0 | ||
| 21 | #define CRC16_VALID 0xb001 | ||
| 22 | |||
| 23 | #include "../w1.h" | ||
| 24 | #include "../w1_int.h" | ||
| 25 | #include "../w1_family.h" | ||
| 26 | |||
| 27 | MODULE_LICENSE("GPL"); | ||
| 28 | MODULE_AUTHOR("Markus Franke <franke.m@sebakmt.com>, <franm@hrz.tu-chemnitz.de>"); | ||
| 29 | MODULE_DESCRIPTION("w1 family 1C driver for DS28E04, 4kb EEPROM and PIO"); | ||
| 30 | |||
| 31 | /* Allow the strong pullup to be disabled, but default to enabled. | ||
| 32 | * If it was disabled a parasite powered device might not get the required | ||
| 33 | * current to copy the data from the scratchpad to EEPROM. If it is enabled | ||
| 34 | * parasite powered devices have a better chance of getting the current | ||
| 35 | * required. | ||
| 36 | */ | ||
| 37 | static int w1_strong_pullup = 1; | ||
| 38 | module_param_named(strong_pullup, w1_strong_pullup, int, 0); | ||
| 39 | |||
| 40 | /* enable/disable CRC checking on DS28E04-100 memory accesses */ | ||
| 41 | static char w1_enable_crccheck = 1; | ||
| 42 | |||
| 43 | #define W1_EEPROM_SIZE 512 | ||
| 44 | #define W1_PAGE_COUNT 16 | ||
| 45 | #define W1_PAGE_SIZE 32 | ||
| 46 | #define W1_PAGE_BITS 5 | ||
| 47 | #define W1_PAGE_MASK 0x1F | ||
| 48 | |||
| 49 | #define W1_F1C_READ_EEPROM 0xF0 | ||
| 50 | #define W1_F1C_WRITE_SCRATCH 0x0F | ||
| 51 | #define W1_F1C_READ_SCRATCH 0xAA | ||
| 52 | #define W1_F1C_COPY_SCRATCH 0x55 | ||
| 53 | #define W1_F1C_ACCESS_WRITE 0x5A | ||
| 54 | |||
| 55 | #define W1_1C_REG_LOGIC_STATE 0x220 | ||
| 56 | |||
| 57 | struct w1_f1C_data { | ||
| 58 | u8 memory[W1_EEPROM_SIZE]; | ||
| 59 | u32 validcrc; | ||
| 60 | }; | ||
| 61 | |||
| 62 | /** | ||
| 63 | * Check the file size bounds and adjusts count as needed. | ||
| 64 | * This would not be needed if the file size didn't reset to 0 after a write. | ||
| 65 | */ | ||
| 66 | static inline size_t w1_f1C_fix_count(loff_t off, size_t count, size_t size) | ||
| 67 | { | ||
| 68 | if (off > size) | ||
| 69 | return 0; | ||
| 70 | |||
| 71 | if ((off + count) > size) | ||
| 72 | return size - off; | ||
| 73 | |||
| 74 | return count; | ||
| 75 | } | ||
| 76 | |||
| 77 | static int w1_f1C_refresh_block(struct w1_slave *sl, struct w1_f1C_data *data, | ||
| 78 | int block) | ||
| 79 | { | ||
| 80 | u8 wrbuf[3]; | ||
| 81 | int off = block * W1_PAGE_SIZE; | ||
| 82 | |||
| 83 | if (data->validcrc & (1 << block)) | ||
| 84 | return 0; | ||
| 85 | |||
| 86 | if (w1_reset_select_slave(sl)) { | ||
| 87 | data->validcrc = 0; | ||
| 88 | return -EIO; | ||
| 89 | } | ||
| 90 | |||
| 91 | wrbuf[0] = W1_F1C_READ_EEPROM; | ||
| 92 | wrbuf[1] = off & 0xff; | ||
| 93 | wrbuf[2] = off >> 8; | ||
| 94 | w1_write_block(sl->master, wrbuf, 3); | ||
| 95 | w1_read_block(sl->master, &data->memory[off], W1_PAGE_SIZE); | ||
| 96 | |||
| 97 | /* cache the block if the CRC is valid */ | ||
| 98 | if (crc16(CRC16_INIT, &data->memory[off], W1_PAGE_SIZE) == CRC16_VALID) | ||
| 99 | data->validcrc |= (1 << block); | ||
| 100 | |||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 104 | static int w1_f1C_read(struct w1_slave *sl, int addr, int len, char *data) | ||
| 105 | { | ||
| 106 | u8 wrbuf[3]; | ||
| 107 | |||
| 108 | /* read directly from the EEPROM */ | ||
| 109 | if (w1_reset_select_slave(sl)) | ||
| 110 | return -EIO; | ||
| 111 | |||
| 112 | wrbuf[0] = W1_F1C_READ_EEPROM; | ||
| 113 | wrbuf[1] = addr & 0xff; | ||
| 114 | wrbuf[2] = addr >> 8; | ||
| 115 | |||
| 116 | w1_write_block(sl->master, wrbuf, sizeof(wrbuf)); | ||
| 117 | return w1_read_block(sl->master, data, len); | ||
| 118 | } | ||
| 119 | |||
| 120 | static ssize_t w1_f1C_read_bin(struct file *filp, struct kobject *kobj, | ||
| 121 | struct bin_attribute *bin_attr, | ||
| 122 | char *buf, loff_t off, size_t count) | ||
| 123 | { | ||
| 124 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | ||
| 125 | struct w1_f1C_data *data = sl->family_data; | ||
| 126 | int i, min_page, max_page; | ||
| 127 | |||
| 128 | count = w1_f1C_fix_count(off, count, W1_EEPROM_SIZE); | ||
| 129 | if (count == 0) | ||
| 130 | return 0; | ||
| 131 | |||
| 132 | mutex_lock(&sl->master->mutex); | ||
| 133 | |||
| 134 | if (w1_enable_crccheck) { | ||
| 135 | min_page = (off >> W1_PAGE_BITS); | ||
| 136 | max_page = (off + count - 1) >> W1_PAGE_BITS; | ||
| 137 | for (i = min_page; i <= max_page; i++) { | ||
| 138 | if (w1_f1C_refresh_block(sl, data, i)) { | ||
| 139 | count = -EIO; | ||
| 140 | goto out_up; | ||
| 141 | } | ||
| 142 | } | ||
| 143 | memcpy(buf, &data->memory[off], count); | ||
| 144 | } else { | ||
| 145 | count = w1_f1C_read(sl, off, count, buf); | ||
| 146 | } | ||
| 147 | |||
| 148 | out_up: | ||
| 149 | mutex_unlock(&sl->master->mutex); | ||
| 150 | |||
| 151 | return count; | ||
| 152 | } | ||
| 153 | |||
| 154 | /** | ||
| 155 | * Writes to the scratchpad and reads it back for verification. | ||
| 156 | * Then copies the scratchpad to EEPROM. | ||
| 157 | * The data must be on one page. | ||
| 158 | * The master must be locked. | ||
| 159 | * | ||
| 160 | * @param sl The slave structure | ||
| 161 | * @param addr Address for the write | ||
| 162 | * @param len length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK)) | ||
| 163 | * @param data The data to write | ||
| 164 | * @return 0=Success -1=failure | ||
| 165 | */ | ||
| 166 | static int w1_f1C_write(struct w1_slave *sl, int addr, int len, const u8 *data) | ||
| 167 | { | ||
| 168 | u8 wrbuf[4]; | ||
| 169 | u8 rdbuf[W1_PAGE_SIZE + 3]; | ||
| 170 | u8 es = (addr + len - 1) & 0x1f; | ||
| 171 | unsigned int tm = 10; | ||
| 172 | int i; | ||
| 173 | struct w1_f1C_data *f1C = sl->family_data; | ||
| 174 | |||
| 175 | /* Write the data to the scratchpad */ | ||
| 176 | if (w1_reset_select_slave(sl)) | ||
| 177 | return -1; | ||
| 178 | |||
| 179 | wrbuf[0] = W1_F1C_WRITE_SCRATCH; | ||
| 180 | wrbuf[1] = addr & 0xff; | ||
| 181 | wrbuf[2] = addr >> 8; | ||
| 182 | |||
| 183 | w1_write_block(sl->master, wrbuf, 3); | ||
| 184 | w1_write_block(sl->master, data, len); | ||
| 185 | |||
| 186 | /* Read the scratchpad and verify */ | ||
| 187 | if (w1_reset_select_slave(sl)) | ||
| 188 | return -1; | ||
| 189 | |||
| 190 | w1_write_8(sl->master, W1_F1C_READ_SCRATCH); | ||
| 191 | w1_read_block(sl->master, rdbuf, len + 3); | ||
| 192 | |||
| 193 | /* Compare what was read against the data written */ | ||
| 194 | if ((rdbuf[0] != wrbuf[1]) || (rdbuf[1] != wrbuf[2]) || | ||
| 195 | (rdbuf[2] != es) || (memcmp(data, &rdbuf[3], len) != 0)) | ||
| 196 | return -1; | ||
| 197 | |||
| 198 | /* Copy the scratchpad to EEPROM */ | ||
| 199 | if (w1_reset_select_slave(sl)) | ||
| 200 | return -1; | ||
| 201 | |||
| 202 | wrbuf[0] = W1_F1C_COPY_SCRATCH; | ||
| 203 | wrbuf[3] = es; | ||
| 204 | |||
| 205 | for (i = 0; i < sizeof(wrbuf); ++i) { | ||
| 206 | /* issue 10ms strong pullup (or delay) on the last byte | ||
| 207 | for writing the data from the scratchpad to EEPROM */ | ||
| 208 | if (w1_strong_pullup && i == sizeof(wrbuf)-1) | ||
| 209 | w1_next_pullup(sl->master, tm); | ||
| 210 | |||
| 211 | w1_write_8(sl->master, wrbuf[i]); | ||
| 212 | } | ||
| 213 | |||
| 214 | if (!w1_strong_pullup) | ||
| 215 | msleep(tm); | ||
| 216 | |||
| 217 | if (w1_enable_crccheck) { | ||
| 218 | /* invalidate cached data */ | ||
| 219 | f1C->validcrc &= ~(1 << (addr >> W1_PAGE_BITS)); | ||
| 220 | } | ||
| 221 | |||
| 222 | /* Reset the bus to wake up the EEPROM (this may not be needed) */ | ||
| 223 | w1_reset_bus(sl->master); | ||
| 224 | |||
| 225 | return 0; | ||
| 226 | } | ||
| 227 | |||
| 228 | static ssize_t w1_f1C_write_bin(struct file *filp, struct kobject *kobj, | ||
| 229 | struct bin_attribute *bin_attr, | ||
| 230 | char *buf, loff_t off, size_t count) | ||
| 231 | |||
| 232 | { | ||
| 233 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | ||
| 234 | int addr, len, idx; | ||
| 235 | |||
| 236 | count = w1_f1C_fix_count(off, count, W1_EEPROM_SIZE); | ||
| 237 | if (count == 0) | ||
| 238 | return 0; | ||
| 239 | |||
| 240 | if (w1_enable_crccheck) { | ||
| 241 | /* can only write full blocks in cached mode */ | ||
| 242 | if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) { | ||
| 243 | dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n", | ||
| 244 | (int)off, count); | ||
| 245 | return -EINVAL; | ||
| 246 | } | ||
| 247 | |||
| 248 | /* make sure the block CRCs are valid */ | ||
| 249 | for (idx = 0; idx < count; idx += W1_PAGE_SIZE) { | ||
| 250 | if (crc16(CRC16_INIT, &buf[idx], W1_PAGE_SIZE) | ||
| 251 | != CRC16_VALID) { | ||
| 252 | dev_err(&sl->dev, "bad CRC at offset %d\n", | ||
| 253 | (int)off); | ||
| 254 | return -EINVAL; | ||
| 255 | } | ||
| 256 | } | ||
| 257 | } | ||
| 258 | |||
| 259 | mutex_lock(&sl->master->mutex); | ||
| 260 | |||
| 261 | /* Can only write data to one page at a time */ | ||
| 262 | idx = 0; | ||
| 263 | while (idx < count) { | ||
| 264 | addr = off + idx; | ||
| 265 | len = W1_PAGE_SIZE - (addr & W1_PAGE_MASK); | ||
| 266 | if (len > (count - idx)) | ||
| 267 | len = count - idx; | ||
| 268 | |||
| 269 | if (w1_f1C_write(sl, addr, len, &buf[idx]) < 0) { | ||
| 270 | count = -EIO; | ||
| 271 | goto out_up; | ||
| 272 | } | ||
| 273 | idx += len; | ||
| 274 | } | ||
| 275 | |||
| 276 | out_up: | ||
| 277 | mutex_unlock(&sl->master->mutex); | ||
| 278 | |||
| 279 | return count; | ||
| 280 | } | ||
| 281 | |||
| 282 | static ssize_t w1_f1C_read_pio(struct file *filp, struct kobject *kobj, | ||
| 283 | struct bin_attribute *bin_attr, | ||
| 284 | char *buf, loff_t off, size_t count) | ||
| 285 | |||
| 286 | { | ||
| 287 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | ||
| 288 | int ret; | ||
| 289 | |||
| 290 | /* check arguments */ | ||
| 291 | if (off != 0 || count != 1 || buf == NULL) | ||
| 292 | return -EINVAL; | ||
| 293 | |||
| 294 | mutex_lock(&sl->master->mutex); | ||
| 295 | ret = w1_f1C_read(sl, W1_1C_REG_LOGIC_STATE, count, buf); | ||
| 296 | mutex_unlock(&sl->master->mutex); | ||
| 297 | |||
| 298 | return ret; | ||
| 299 | } | ||
| 300 | |||
| 301 | static ssize_t w1_f1C_write_pio(struct file *filp, struct kobject *kobj, | ||
| 302 | struct bin_attribute *bin_attr, | ||
| 303 | char *buf, loff_t off, size_t count) | ||
| 304 | |||
| 305 | { | ||
| 306 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | ||
| 307 | u8 wrbuf[3]; | ||
| 308 | u8 ack; | ||
| 309 | |||
| 310 | /* check arguments */ | ||
| 311 | if (off != 0 || count != 1 || buf == NULL) | ||
| 312 | return -EINVAL; | ||
| 313 | |||
| 314 | mutex_lock(&sl->master->mutex); | ||
| 315 | |||
| 316 | /* Write the PIO data */ | ||
| 317 | if (w1_reset_select_slave(sl)) { | ||
| 318 | mutex_unlock(&sl->master->mutex); | ||
| 319 | return -1; | ||
| 320 | } | ||
| 321 | |||
| 322 | /* set bit 7..2 to value '1' */ | ||
| 323 | *buf = *buf | 0xFC; | ||
| 324 | |||
| 325 | wrbuf[0] = W1_F1C_ACCESS_WRITE; | ||
| 326 | wrbuf[1] = *buf; | ||
| 327 | wrbuf[2] = ~(*buf); | ||
| 328 | w1_write_block(sl->master, wrbuf, 3); | ||
| 329 | |||
| 330 | w1_read_block(sl->master, &ack, sizeof(ack)); | ||
| 331 | |||
| 332 | mutex_unlock(&sl->master->mutex); | ||
| 333 | |||
| 334 | /* check for acknowledgement */ | ||
| 335 | if (ack != 0xAA) | ||
| 336 | return -EIO; | ||
| 337 | |||
| 338 | return count; | ||
| 339 | } | ||
| 340 | |||
| 341 | static ssize_t w1_f1C_show_crccheck(struct device *dev, | ||
| 342 | struct device_attribute *attr, char *buf) | ||
| 343 | { | ||
| 344 | if (put_user(w1_enable_crccheck + 0x30, buf)) | ||
| 345 | return -EFAULT; | ||
| 346 | |||
| 347 | return sizeof(w1_enable_crccheck); | ||
| 348 | } | ||
| 349 | |||
| 350 | static ssize_t w1_f1C_store_crccheck(struct device *dev, | ||
| 351 | struct device_attribute *attr, | ||
| 352 | const char *buf, size_t count) | ||
| 353 | { | ||
| 354 | char val; | ||
| 355 | |||
| 356 | if (count != 1 || !buf) | ||
| 357 | return -EINVAL; | ||
| 358 | |||
| 359 | if (get_user(val, buf)) | ||
| 360 | return -EFAULT; | ||
| 361 | |||
| 362 | /* convert to decimal */ | ||
| 363 | val = val - 0x30; | ||
| 364 | if (val != 0 && val != 1) | ||
| 365 | return -EINVAL; | ||
| 366 | |||
| 367 | /* set the new value */ | ||
| 368 | w1_enable_crccheck = val; | ||
| 369 | |||
| 370 | return sizeof(w1_enable_crccheck); | ||
| 371 | } | ||
| 372 | |||
| 373 | #define NB_SYSFS_BIN_FILES 2 | ||
| 374 | static struct bin_attribute w1_f1C_bin_attr[NB_SYSFS_BIN_FILES] = { | ||
| 375 | { | ||
| 376 | .attr = { | ||
| 377 | .name = "eeprom", | ||
| 378 | .mode = S_IRUGO | S_IWUSR, | ||
| 379 | }, | ||
| 380 | .size = W1_EEPROM_SIZE, | ||
| 381 | .read = w1_f1C_read_bin, | ||
| 382 | .write = w1_f1C_write_bin, | ||
| 383 | }, | ||
| 384 | { | ||
| 385 | .attr = { | ||
| 386 | .name = "pio", | ||
| 387 | .mode = S_IRUGO | S_IWUSR, | ||
| 388 | }, | ||
| 389 | .size = 1, | ||
| 390 | .read = w1_f1C_read_pio, | ||
| 391 | .write = w1_f1C_write_pio, | ||
| 392 | } | ||
| 393 | }; | ||
| 394 | |||
| 395 | static DEVICE_ATTR(crccheck, S_IWUSR | S_IRUGO, | ||
| 396 | w1_f1C_show_crccheck, w1_f1C_store_crccheck); | ||
| 397 | |||
| 398 | static int w1_f1C_add_slave(struct w1_slave *sl) | ||
| 399 | { | ||
| 400 | int err = 0; | ||
| 401 | int i; | ||
| 402 | struct w1_f1C_data *data = NULL; | ||
| 403 | |||
| 404 | if (w1_enable_crccheck) { | ||
| 405 | data = kzalloc(sizeof(struct w1_f1C_data), GFP_KERNEL); | ||
| 406 | if (!data) | ||
| 407 | return -ENOMEM; | ||
| 408 | sl->family_data = data; | ||
| 409 | } | ||
| 410 | |||
| 411 | /* create binary sysfs attributes */ | ||
| 412 | for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i) | ||
| 413 | err = sysfs_create_bin_file( | ||
| 414 | &sl->dev.kobj, &(w1_f1C_bin_attr[i])); | ||
| 415 | |||
| 416 | if (!err) { | ||
| 417 | /* create device attributes */ | ||
| 418 | err = device_create_file(&sl->dev, &dev_attr_crccheck); | ||
| 419 | } | ||
| 420 | |||
| 421 | if (err) { | ||
| 422 | /* remove binary sysfs attributes */ | ||
| 423 | for (i = 0; i < NB_SYSFS_BIN_FILES; ++i) | ||
| 424 | sysfs_remove_bin_file( | ||
| 425 | &sl->dev.kobj, &(w1_f1C_bin_attr[i])); | ||
| 426 | |||
| 427 | kfree(data); | ||
| 428 | } | ||
| 429 | |||
| 430 | return err; | ||
| 431 | } | ||
| 432 | |||
| 433 | static void w1_f1C_remove_slave(struct w1_slave *sl) | ||
| 434 | { | ||
| 435 | int i; | ||
| 436 | |||
| 437 | kfree(sl->family_data); | ||
| 438 | sl->family_data = NULL; | ||
| 439 | |||
| 440 | /* remove device attributes */ | ||
| 441 | device_remove_file(&sl->dev, &dev_attr_crccheck); | ||
| 442 | |||
| 443 | /* remove binary sysfs attributes */ | ||
| 444 | for (i = 0; i < NB_SYSFS_BIN_FILES; ++i) | ||
| 445 | sysfs_remove_bin_file(&sl->dev.kobj, &(w1_f1C_bin_attr[i])); | ||
| 446 | } | ||
| 447 | |||
| 448 | static struct w1_family_ops w1_f1C_fops = { | ||
| 449 | .add_slave = w1_f1C_add_slave, | ||
| 450 | .remove_slave = w1_f1C_remove_slave, | ||
| 451 | }; | ||
| 452 | |||
| 453 | static struct w1_family w1_family_1C = { | ||
| 454 | .fid = W1_FAMILY_DS28E04, | ||
| 455 | .fops = &w1_f1C_fops, | ||
| 456 | }; | ||
| 457 | |||
| 458 | static int __init w1_f1C_init(void) | ||
| 459 | { | ||
| 460 | return w1_register_family(&w1_family_1C); | ||
| 461 | } | ||
| 462 | |||
| 463 | static void __exit w1_f1C_fini(void) | ||
| 464 | { | ||
| 465 | w1_unregister_family(&w1_family_1C); | ||
| 466 | } | ||
| 467 | |||
| 468 | module_init(w1_f1C_init); | ||
| 469 | module_exit(w1_f1C_fini); | ||
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index ff29ae747ee8..d90062b211f8 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c | |||
| @@ -179,7 +179,7 @@ static ssize_t w1_therm_read(struct device *device, | |||
| 179 | int i, max_trying = 10; | 179 | int i, max_trying = 10; |
| 180 | ssize_t c = PAGE_SIZE; | 180 | ssize_t c = PAGE_SIZE; |
| 181 | 181 | ||
| 182 | i = mutex_lock_interruptible(&dev->mutex); | 182 | i = mutex_lock_interruptible(&dev->bus_mutex); |
| 183 | if (i != 0) | 183 | if (i != 0) |
| 184 | return i; | 184 | return i; |
| 185 | 185 | ||
| @@ -207,19 +207,19 @@ static ssize_t w1_therm_read(struct device *device, | |||
| 207 | w1_write_8(dev, W1_CONVERT_TEMP); | 207 | w1_write_8(dev, W1_CONVERT_TEMP); |
| 208 | 208 | ||
| 209 | if (external_power) { | 209 | if (external_power) { |
| 210 | mutex_unlock(&dev->mutex); | 210 | mutex_unlock(&dev->bus_mutex); |
| 211 | 211 | ||
| 212 | sleep_rem = msleep_interruptible(tm); | 212 | sleep_rem = msleep_interruptible(tm); |
| 213 | if (sleep_rem != 0) | 213 | if (sleep_rem != 0) |
| 214 | return -EINTR; | 214 | return -EINTR; |
| 215 | 215 | ||
| 216 | i = mutex_lock_interruptible(&dev->mutex); | 216 | i = mutex_lock_interruptible(&dev->bus_mutex); |
| 217 | if (i != 0) | 217 | if (i != 0) |
| 218 | return i; | 218 | return i; |
| 219 | } else if (!w1_strong_pullup) { | 219 | } else if (!w1_strong_pullup) { |
| 220 | sleep_rem = msleep_interruptible(tm); | 220 | sleep_rem = msleep_interruptible(tm); |
| 221 | if (sleep_rem != 0) { | 221 | if (sleep_rem != 0) { |
| 222 | mutex_unlock(&dev->mutex); | 222 | mutex_unlock(&dev->bus_mutex); |
| 223 | return -EINTR; | 223 | return -EINTR; |
| 224 | } | 224 | } |
| 225 | } | 225 | } |
| @@ -258,7 +258,7 @@ static ssize_t w1_therm_read(struct device *device, | |||
| 258 | 258 | ||
| 259 | c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n", | 259 | c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n", |
| 260 | w1_convert_temp(rom, sl->family->fid)); | 260 | w1_convert_temp(rom, sl->family->fid)); |
| 261 | mutex_unlock(&dev->mutex); | 261 | mutex_unlock(&dev->bus_mutex); |
| 262 | 262 | ||
| 263 | return PAGE_SIZE - c; | 263 | return PAGE_SIZE - c; |
| 264 | } | 264 | } |
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 2f2e894ea0c8..1a574370d2cd 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
| @@ -557,7 +557,7 @@ static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
| 557 | struct w1_master *md = NULL; | 557 | struct w1_master *md = NULL; |
| 558 | struct w1_slave *sl = NULL; | 558 | struct w1_slave *sl = NULL; |
| 559 | char *event_owner, *name; | 559 | char *event_owner, *name; |
| 560 | int err; | 560 | int err = 0; |
| 561 | 561 | ||
| 562 | if (dev->driver == &w1_master_driver) { | 562 | if (dev->driver == &w1_master_driver) { |
| 563 | md = container_of(dev, struct w1_master, dev); | 563 | md = container_of(dev, struct w1_master, dev); |
| @@ -576,19 +576,17 @@ static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
| 576 | event_owner, name, dev_name(dev)); | 576 | event_owner, name, dev_name(dev)); |
| 577 | 577 | ||
| 578 | if (dev->driver != &w1_slave_driver || !sl) | 578 | if (dev->driver != &w1_slave_driver || !sl) |
| 579 | return 0; | 579 | goto end; |
| 580 | 580 | ||
| 581 | err = add_uevent_var(env, "W1_FID=%02X", sl->reg_num.family); | 581 | err = add_uevent_var(env, "W1_FID=%02X", sl->reg_num.family); |
| 582 | if (err) | 582 | if (err) |
| 583 | return err; | 583 | goto end; |
| 584 | 584 | ||
| 585 | err = add_uevent_var(env, "W1_SLAVE_ID=%024LX", | 585 | err = add_uevent_var(env, "W1_SLAVE_ID=%024LX", |
| 586 | (unsigned long long)sl->reg_num.id); | 586 | (unsigned long long)sl->reg_num.id); |
| 587 | if (err) | 587 | end: |
| 588 | return err; | 588 | return err; |
| 589 | 589 | } | |
| 590 | return 0; | ||
| 591 | }; | ||
| 592 | #else | 590 | #else |
| 593 | static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) | 591 | static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 594 | { | 592 | { |
| @@ -887,16 +885,21 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb | |||
| 887 | * | 885 | * |
| 888 | * Return 0 - device(s) present, 1 - no devices present. | 886 | * Return 0 - device(s) present, 1 - no devices present. |
| 889 | */ | 887 | */ |
| 888 | mutex_lock(&dev->bus_mutex); | ||
| 890 | if (w1_reset_bus(dev)) { | 889 | if (w1_reset_bus(dev)) { |
| 890 | mutex_unlock(&dev->bus_mutex); | ||
| 891 | dev_dbg(&dev->dev, "No devices present on the wire.\n"); | 891 | dev_dbg(&dev->dev, "No devices present on the wire.\n"); |
| 892 | break; | 892 | break; |
| 893 | } | 893 | } |
| 894 | 894 | ||
| 895 | /* Do fast search on single slave bus */ | 895 | /* Do fast search on single slave bus */ |
| 896 | if (dev->max_slave_count == 1) { | 896 | if (dev->max_slave_count == 1) { |
| 897 | int rv; | ||
| 897 | w1_write_8(dev, W1_READ_ROM); | 898 | w1_write_8(dev, W1_READ_ROM); |
| 899 | rv = w1_read_block(dev, (u8 *)&rn, 8); | ||
| 900 | mutex_unlock(&dev->bus_mutex); | ||
| 898 | 901 | ||
| 899 | if (w1_read_block(dev, (u8 *)&rn, 8) == 8 && rn) | 902 | if (rv == 8 && rn) |
| 900 | cb(dev, rn); | 903 | cb(dev, rn); |
| 901 | 904 | ||
| 902 | break; | 905 | break; |
| @@ -929,10 +932,12 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb | |||
| 929 | rn |= (tmp64 << i); | 932 | rn |= (tmp64 << i); |
| 930 | 933 | ||
| 931 | if (kthread_should_stop()) { | 934 | if (kthread_should_stop()) { |
| 935 | mutex_unlock(&dev->bus_mutex); | ||
| 932 | dev_dbg(&dev->dev, "Abort w1_search\n"); | 936 | dev_dbg(&dev->dev, "Abort w1_search\n"); |
| 933 | return; | 937 | return; |
| 934 | } | 938 | } |
| 935 | } | 939 | } |
| 940 | mutex_unlock(&dev->bus_mutex); | ||
| 936 | 941 | ||
| 937 | if ( (triplet_ret & 0x03) != 0x03 ) { | 942 | if ( (triplet_ret & 0x03) != 0x03 ) { |
| 938 | if ( (desc_bit == last_zero) || (last_zero < 0)) | 943 | if ( (desc_bit == last_zero) || (last_zero < 0)) |
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index 4d012ca3f32c..45908e56c2f8 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h | |||
| @@ -180,6 +180,7 @@ struct w1_master | |||
| 180 | 180 | ||
| 181 | struct task_struct *thread; | 181 | struct task_struct *thread; |
| 182 | struct mutex mutex; | 182 | struct mutex mutex; |
| 183 | struct mutex bus_mutex; | ||
| 183 | 184 | ||
| 184 | struct device_driver *driver; | 185 | struct device_driver *driver; |
| 185 | struct device dev; | 186 | struct device dev; |
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h index 874aeb05011b..b00ada44a89b 100644 --- a/drivers/w1/w1_family.h +++ b/drivers/w1/w1_family.h | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #define W1_FAMILY_SMEM_01 0x01 | 30 | #define W1_FAMILY_SMEM_01 0x01 |
| 31 | #define W1_FAMILY_SMEM_81 0x81 | 31 | #define W1_FAMILY_SMEM_81 0x81 |
| 32 | #define W1_THERM_DS18S20 0x10 | 32 | #define W1_THERM_DS18S20 0x10 |
| 33 | #define W1_FAMILY_DS28E04 0x1C | ||
| 33 | #define W1_COUNTER_DS2423 0x1D | 34 | #define W1_COUNTER_DS2423 0x1D |
| 34 | #define W1_THERM_DS1822 0x22 | 35 | #define W1_THERM_DS1822 0x22 |
| 35 | #define W1_EEPROM_DS2433 0x23 | 36 | #define W1_EEPROM_DS2433 0x23 |
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index 68288355727a..5a98649f6abc 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c | |||
| @@ -76,6 +76,7 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl, | |||
| 76 | 76 | ||
| 77 | INIT_LIST_HEAD(&dev->slist); | 77 | INIT_LIST_HEAD(&dev->slist); |
| 78 | mutex_init(&dev->mutex); | 78 | mutex_init(&dev->mutex); |
| 79 | mutex_init(&dev->bus_mutex); | ||
| 79 | 80 | ||
| 80 | memcpy(&dev->dev, device, sizeof(struct device)); | 81 | memcpy(&dev->dev, device, sizeof(struct device)); |
| 81 | dev_set_name(&dev->dev, "w1_bus_master%u", dev->id); | 82 | dev_set_name(&dev->dev, "w1_bus_master%u", dev->id); |
| @@ -117,7 +118,7 @@ int w1_add_master_device(struct w1_bus_master *master) | |||
| 117 | return(-EINVAL); | 118 | return(-EINVAL); |
| 118 | } | 119 | } |
| 119 | /* While it would be electrically possible to make a device that | 120 | /* While it would be electrically possible to make a device that |
| 120 | * generated a strong pullup in bit bang mode, only hardare that | 121 | * generated a strong pullup in bit bang mode, only hardware that |
| 121 | * controls 1-wire time frames are even expected to support a strong | 122 | * controls 1-wire time frames are even expected to support a strong |
| 122 | * pullup. w1_io.c would need to support calling set_pullup before | 123 | * pullup. w1_io.c would need to support calling set_pullup before |
| 123 | * the last write_bit operation of a w1_write_8 which it currently | 124 | * the last write_bit operation of a w1_write_8 which it currently |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index d17c20fd74e6..4733eab34a23 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
| @@ -495,7 +495,7 @@ void debugfs_remove(struct dentry *dentry) | |||
| 495 | struct dentry *parent; | 495 | struct dentry *parent; |
| 496 | int ret; | 496 | int ret; |
| 497 | 497 | ||
| 498 | if (!dentry) | 498 | if (IS_ERR_OR_NULL(dentry)) |
| 499 | return; | 499 | return; |
| 500 | 500 | ||
| 501 | parent = dentry->d_parent; | 501 | parent = dentry->d_parent; |
| @@ -527,7 +527,7 @@ void debugfs_remove_recursive(struct dentry *dentry) | |||
| 527 | struct dentry *child; | 527 | struct dentry *child; |
| 528 | struct dentry *parent; | 528 | struct dentry *parent; |
| 529 | 529 | ||
| 530 | if (!dentry) | 530 | if (IS_ERR_OR_NULL(dentry)) |
| 531 | return; | 531 | return; |
| 532 | 532 | ||
| 533 | parent = dentry->d_parent; | 533 | parent = dentry->d_parent; |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index a5cf784f9cc2..6b0bb00d4d2b 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
| @@ -307,6 +307,7 @@ static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags) | |||
| 307 | { | 307 | { |
| 308 | struct sysfs_dirent *sd; | 308 | struct sysfs_dirent *sd; |
| 309 | int is_dir; | 309 | int is_dir; |
| 310 | int type; | ||
| 310 | 311 | ||
| 311 | if (flags & LOOKUP_RCU) | 312 | if (flags & LOOKUP_RCU) |
| 312 | return -ECHILD; | 313 | return -ECHILD; |
| @@ -326,6 +327,15 @@ static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags) | |||
| 326 | if (strcmp(dentry->d_name.name, sd->s_name) != 0) | 327 | if (strcmp(dentry->d_name.name, sd->s_name) != 0) |
| 327 | goto out_bad; | 328 | goto out_bad; |
| 328 | 329 | ||
| 330 | /* The sysfs dirent has been moved to a different namespace */ | ||
| 331 | type = KOBJ_NS_TYPE_NONE; | ||
| 332 | if (sd->s_parent) { | ||
| 333 | type = sysfs_ns_type(sd->s_parent); | ||
| 334 | if (type != KOBJ_NS_TYPE_NONE && | ||
| 335 | sysfs_info(dentry->d_sb)->ns[type] != sd->s_ns) | ||
| 336 | goto out_bad; | ||
| 337 | } | ||
| 338 | |||
| 329 | mutex_unlock(&sysfs_mutex); | 339 | mutex_unlock(&sysfs_mutex); |
| 330 | out_valid: | 340 | out_valid: |
| 331 | return 1; | 341 | return 1; |
diff --git a/include/linux/device.h b/include/linux/device.h index 5083bccae967..52a5f15a2223 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
| @@ -691,6 +691,11 @@ struct device { | |||
| 691 | struct iommu_group *iommu_group; | 691 | struct iommu_group *iommu_group; |
| 692 | }; | 692 | }; |
| 693 | 693 | ||
| 694 | static inline struct device *kobj_to_dev(struct kobject *kobj) | ||
| 695 | { | ||
| 696 | return container_of(kobj, struct device, kobj); | ||
| 697 | } | ||
| 698 | |||
| 694 | /* Get the wakeup routines, which depend on struct device */ | 699 | /* Get the wakeup routines, which depend on struct device */ |
| 695 | #include <linux/pm_wakeup.h> | 700 | #include <linux/pm_wakeup.h> |
| 696 | 701 | ||
diff --git a/include/linux/extcon/extcon_gpio.h b/include/linux/extcon/extcon_gpio.h index a2129b73dcb1..2d8307f7d67d 100644 --- a/include/linux/extcon/extcon_gpio.h +++ b/include/linux/extcon/extcon_gpio.h | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | * @irq_flags IRQ Flags (e.g., IRQF_TRIGGER_LOW). | 31 | * @irq_flags IRQ Flags (e.g., IRQF_TRIGGER_LOW). |
| 32 | * @state_on print_state is overriden with state_on if attached. If Null, | 32 | * @state_on print_state is overriden with state_on if attached. If Null, |
| 33 | * default method of extcon class is used. | 33 | * default method of extcon class is used. |
| 34 | * @state_off print_state is overriden with state_on if dettached. If Null, | 34 | * @state_off print_state is overriden with state_on if detached. If Null, |
| 35 | * default method of extcon class is used. | 35 | * default method of extcon class is used. |
| 36 | * | 36 | * |
| 37 | * Note that in order for state_on or state_off to be valid, both state_on | 37 | * Note that in order for state_on or state_off to be valid, both state_on |
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 017a7fb5a1fc..ae0aaa9d42fa 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | 16 | ||
| 17 | #ifdef CONFIG_BLOCK | 17 | #ifdef CONFIG_BLOCK |
| 18 | 18 | ||
| 19 | #define kobj_to_dev(k) container_of((k), struct device, kobj) | ||
| 20 | #define dev_to_disk(device) container_of((device), struct gendisk, part0.__dev) | 19 | #define dev_to_disk(device) container_of((device), struct gendisk, part0.__dev) |
| 21 | #define dev_to_part(device) container_of((device), struct hd_struct, __dev) | 20 | #define dev_to_part(device) container_of((device), struct hd_struct, __dev) |
| 22 | #define disk_to_dev(disk) (&(disk)->part0.__dev) | 21 | #define disk_to_dev(disk) (&(disk)->part0.__dev) |
diff --git a/kernel/printk.c b/kernel/printk.c index ac4bc9e79465..50c96b5651b6 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
| @@ -216,6 +216,7 @@ struct log { | |||
| 216 | */ | 216 | */ |
| 217 | static DEFINE_RAW_SPINLOCK(logbuf_lock); | 217 | static DEFINE_RAW_SPINLOCK(logbuf_lock); |
| 218 | 218 | ||
| 219 | #ifdef CONFIG_PRINTK | ||
| 219 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ | 220 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ |
| 220 | static u64 syslog_seq; | 221 | static u64 syslog_seq; |
| 221 | static u32 syslog_idx; | 222 | static u32 syslog_idx; |
| @@ -228,14 +229,19 @@ static u32 log_first_idx; | |||
| 228 | 229 | ||
| 229 | /* index and sequence number of the next record to store in the buffer */ | 230 | /* index and sequence number of the next record to store in the buffer */ |
| 230 | static u64 log_next_seq; | 231 | static u64 log_next_seq; |
| 231 | #ifdef CONFIG_PRINTK | ||
| 232 | static u32 log_next_idx; | 232 | static u32 log_next_idx; |
| 233 | 233 | ||
| 234 | /* the next printk record to write to the console */ | ||
| 235 | static u64 console_seq; | ||
| 236 | static u32 console_idx; | ||
| 237 | static enum log_flags console_prev; | ||
| 238 | |||
| 234 | /* the next printk record to read after the last 'clear' command */ | 239 | /* the next printk record to read after the last 'clear' command */ |
| 235 | static u64 clear_seq; | 240 | static u64 clear_seq; |
| 236 | static u32 clear_idx; | 241 | static u32 clear_idx; |
| 237 | 242 | ||
| 238 | #define LOG_LINE_MAX 1024 | 243 | #define PREFIX_MAX 32 |
| 244 | #define LOG_LINE_MAX 1024 - PREFIX_MAX | ||
| 239 | 245 | ||
| 240 | /* record buffer */ | 246 | /* record buffer */ |
| 241 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) | 247 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) |
| @@ -360,6 +366,7 @@ static void log_store(int facility, int level, | |||
| 360 | struct devkmsg_user { | 366 | struct devkmsg_user { |
| 361 | u64 seq; | 367 | u64 seq; |
| 362 | u32 idx; | 368 | u32 idx; |
| 369 | enum log_flags prev; | ||
| 363 | struct mutex lock; | 370 | struct mutex lock; |
| 364 | char buf[8192]; | 371 | char buf[8192]; |
| 365 | }; | 372 | }; |
| @@ -425,6 +432,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, | |||
| 425 | struct log *msg; | 432 | struct log *msg; |
| 426 | u64 ts_usec; | 433 | u64 ts_usec; |
| 427 | size_t i; | 434 | size_t i; |
| 435 | char cont = '-'; | ||
| 428 | size_t len; | 436 | size_t len; |
| 429 | ssize_t ret; | 437 | ssize_t ret; |
| 430 | 438 | ||
| @@ -462,8 +470,25 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, | |||
| 462 | msg = log_from_idx(user->idx); | 470 | msg = log_from_idx(user->idx); |
| 463 | ts_usec = msg->ts_nsec; | 471 | ts_usec = msg->ts_nsec; |
| 464 | do_div(ts_usec, 1000); | 472 | do_div(ts_usec, 1000); |
| 465 | len = sprintf(user->buf, "%u,%llu,%llu;", | 473 | |
| 466 | (msg->facility << 3) | msg->level, user->seq, ts_usec); | 474 | /* |
| 475 | * If we couldn't merge continuation line fragments during the print, | ||
| 476 | * export the stored flags to allow an optional external merge of the | ||
| 477 | * records. Merging the records isn't always neccessarily correct, like | ||
| 478 | * when we hit a race during printing. In most cases though, it produces | ||
| 479 | * better readable output. 'c' in the record flags mark the first | ||
| 480 | * fragment of a line, '+' the following. | ||
| 481 | */ | ||
| 482 | if (msg->flags & LOG_CONT && !(user->prev & LOG_CONT)) | ||
| 483 | cont = 'c'; | ||
| 484 | else if ((msg->flags & LOG_CONT) || | ||
| 485 | ((user->prev & LOG_CONT) && !(msg->flags & LOG_PREFIX))) | ||
| 486 | cont = '+'; | ||
| 487 | |||
| 488 | len = sprintf(user->buf, "%u,%llu,%llu,%c;", | ||
| 489 | (msg->facility << 3) | msg->level, | ||
| 490 | user->seq, ts_usec, cont); | ||
| 491 | user->prev = msg->flags; | ||
| 467 | 492 | ||
| 468 | /* escape non-printable characters */ | 493 | /* escape non-printable characters */ |
| 469 | for (i = 0; i < msg->text_len; i++) { | 494 | for (i = 0; i < msg->text_len; i++) { |
| @@ -646,6 +671,15 @@ void log_buf_kexec_setup(void) | |||
| 646 | VMCOREINFO_SYMBOL(log_buf_len); | 671 | VMCOREINFO_SYMBOL(log_buf_len); |
| 647 | VMCOREINFO_SYMBOL(log_first_idx); | 672 | VMCOREINFO_SYMBOL(log_first_idx); |
| 648 | VMCOREINFO_SYMBOL(log_next_idx); | 673 | VMCOREINFO_SYMBOL(log_next_idx); |
| 674 | /* | ||
| 675 | * Export struct log size and field offsets. User space tools can | ||
| 676 | * parse it and detect any changes to structure down the line. | ||
| 677 | */ | ||
| 678 | VMCOREINFO_STRUCT_SIZE(log); | ||
| 679 | VMCOREINFO_OFFSET(log, ts_nsec); | ||
| 680 | VMCOREINFO_OFFSET(log, len); | ||
| 681 | VMCOREINFO_OFFSET(log, text_len); | ||
| 682 | VMCOREINFO_OFFSET(log, dict_len); | ||
| 649 | } | 683 | } |
| 650 | #endif | 684 | #endif |
| 651 | 685 | ||
| @@ -876,7 +910,7 @@ static size_t msg_print_text(const struct log *msg, enum log_flags prev, | |||
| 876 | 910 | ||
| 877 | if (buf) { | 911 | if (buf) { |
| 878 | if (print_prefix(msg, syslog, NULL) + | 912 | if (print_prefix(msg, syslog, NULL) + |
| 879 | text_len + 1>= size - len) | 913 | text_len + 1 >= size - len) |
| 880 | break; | 914 | break; |
| 881 | 915 | ||
| 882 | if (prefix) | 916 | if (prefix) |
| @@ -907,7 +941,7 @@ static int syslog_print(char __user *buf, int size) | |||
| 907 | struct log *msg; | 941 | struct log *msg; |
| 908 | int len = 0; | 942 | int len = 0; |
| 909 | 943 | ||
| 910 | text = kmalloc(LOG_LINE_MAX, GFP_KERNEL); | 944 | text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); |
| 911 | if (!text) | 945 | if (!text) |
| 912 | return -ENOMEM; | 946 | return -ENOMEM; |
| 913 | 947 | ||
| @@ -930,7 +964,8 @@ static int syslog_print(char __user *buf, int size) | |||
| 930 | 964 | ||
| 931 | skip = syslog_partial; | 965 | skip = syslog_partial; |
| 932 | msg = log_from_idx(syslog_idx); | 966 | msg = log_from_idx(syslog_idx); |
| 933 | n = msg_print_text(msg, syslog_prev, true, text, LOG_LINE_MAX); | 967 | n = msg_print_text(msg, syslog_prev, true, text, |
| 968 | LOG_LINE_MAX + PREFIX_MAX); | ||
| 934 | if (n - syslog_partial <= size) { | 969 | if (n - syslog_partial <= size) { |
| 935 | /* message fits into buffer, move forward */ | 970 | /* message fits into buffer, move forward */ |
| 936 | syslog_idx = log_next(syslog_idx); | 971 | syslog_idx = log_next(syslog_idx); |
| @@ -969,7 +1004,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear) | |||
| 969 | char *text; | 1004 | char *text; |
| 970 | int len = 0; | 1005 | int len = 0; |
| 971 | 1006 | ||
| 972 | text = kmalloc(LOG_LINE_MAX, GFP_KERNEL); | 1007 | text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); |
| 973 | if (!text) | 1008 | if (!text) |
| 974 | return -ENOMEM; | 1009 | return -ENOMEM; |
| 975 | 1010 | ||
| @@ -1022,7 +1057,8 @@ static int syslog_print_all(char __user *buf, int size, bool clear) | |||
| 1022 | struct log *msg = log_from_idx(idx); | 1057 | struct log *msg = log_from_idx(idx); |
| 1023 | int textlen; | 1058 | int textlen; |
| 1024 | 1059 | ||
| 1025 | textlen = msg_print_text(msg, prev, true, text, LOG_LINE_MAX); | 1060 | textlen = msg_print_text(msg, prev, true, text, |
| 1061 | LOG_LINE_MAX + PREFIX_MAX); | ||
| 1026 | if (textlen < 0) { | 1062 | if (textlen < 0) { |
| 1027 | len = textlen; | 1063 | len = textlen; |
| 1028 | break; | 1064 | break; |
| @@ -1349,20 +1385,36 @@ static struct cont { | |||
| 1349 | u64 ts_nsec; /* time of first print */ | 1385 | u64 ts_nsec; /* time of first print */ |
| 1350 | u8 level; /* log level of first message */ | 1386 | u8 level; /* log level of first message */ |
| 1351 | u8 facility; /* log level of first message */ | 1387 | u8 facility; /* log level of first message */ |
| 1388 | enum log_flags flags; /* prefix, newline flags */ | ||
| 1352 | bool flushed:1; /* buffer sealed and committed */ | 1389 | bool flushed:1; /* buffer sealed and committed */ |
| 1353 | } cont; | 1390 | } cont; |
| 1354 | 1391 | ||
| 1355 | static void cont_flush(void) | 1392 | static void cont_flush(enum log_flags flags) |
| 1356 | { | 1393 | { |
| 1357 | if (cont.flushed) | 1394 | if (cont.flushed) |
| 1358 | return; | 1395 | return; |
| 1359 | if (cont.len == 0) | 1396 | if (cont.len == 0) |
| 1360 | return; | 1397 | return; |
| 1361 | 1398 | ||
| 1362 | log_store(cont.facility, cont.level, LOG_NOCONS, cont.ts_nsec, | 1399 | if (cont.cons) { |
| 1363 | NULL, 0, cont.buf, cont.len); | 1400 | /* |
| 1364 | 1401 | * If a fragment of this line was directly flushed to the | |
| 1365 | cont.flushed = true; | 1402 | * console; wait for the console to pick up the rest of the |
| 1403 | * line. LOG_NOCONS suppresses a duplicated output. | ||
| 1404 | */ | ||
| 1405 | log_store(cont.facility, cont.level, flags | LOG_NOCONS, | ||
| 1406 | cont.ts_nsec, NULL, 0, cont.buf, cont.len); | ||
| 1407 | cont.flags = flags; | ||
| 1408 | cont.flushed = true; | ||
| 1409 | } else { | ||
| 1410 | /* | ||
| 1411 | * If no fragment of this line ever reached the console, | ||
| 1412 | * just submit it to the store and free the buffer. | ||
| 1413 | */ | ||
| 1414 | log_store(cont.facility, cont.level, flags, 0, | ||
| 1415 | NULL, 0, cont.buf, cont.len); | ||
| 1416 | cont.len = 0; | ||
| 1417 | } | ||
| 1366 | } | 1418 | } |
| 1367 | 1419 | ||
| 1368 | static bool cont_add(int facility, int level, const char *text, size_t len) | 1420 | static bool cont_add(int facility, int level, const char *text, size_t len) |
| @@ -1371,7 +1423,8 @@ static bool cont_add(int facility, int level, const char *text, size_t len) | |||
| 1371 | return false; | 1423 | return false; |
| 1372 | 1424 | ||
| 1373 | if (cont.len + len > sizeof(cont.buf)) { | 1425 | if (cont.len + len > sizeof(cont.buf)) { |
| 1374 | cont_flush(); | 1426 | /* the line gets too long, split it up in separate records */ |
| 1427 | cont_flush(LOG_CONT); | ||
| 1375 | return false; | 1428 | return false; |
| 1376 | } | 1429 | } |
| 1377 | 1430 | ||
| @@ -1380,12 +1433,17 @@ static bool cont_add(int facility, int level, const char *text, size_t len) | |||
| 1380 | cont.level = level; | 1433 | cont.level = level; |
| 1381 | cont.owner = current; | 1434 | cont.owner = current; |
| 1382 | cont.ts_nsec = local_clock(); | 1435 | cont.ts_nsec = local_clock(); |
| 1436 | cont.flags = 0; | ||
| 1383 | cont.cons = 0; | 1437 | cont.cons = 0; |
| 1384 | cont.flushed = false; | 1438 | cont.flushed = false; |
| 1385 | } | 1439 | } |
| 1386 | 1440 | ||
| 1387 | memcpy(cont.buf + cont.len, text, len); | 1441 | memcpy(cont.buf + cont.len, text, len); |
| 1388 | cont.len += len; | 1442 | cont.len += len; |
| 1443 | |||
| 1444 | if (cont.len > (sizeof(cont.buf) * 80) / 100) | ||
| 1445 | cont_flush(LOG_CONT); | ||
| 1446 | |||
| 1389 | return true; | 1447 | return true; |
| 1390 | } | 1448 | } |
| 1391 | 1449 | ||
| @@ -1394,7 +1452,7 @@ static size_t cont_print_text(char *text, size_t size) | |||
| 1394 | size_t textlen = 0; | 1452 | size_t textlen = 0; |
| 1395 | size_t len; | 1453 | size_t len; |
| 1396 | 1454 | ||
| 1397 | if (cont.cons == 0) { | 1455 | if (cont.cons == 0 && (console_prev & LOG_NEWLINE)) { |
| 1398 | textlen += print_time(cont.ts_nsec, text); | 1456 | textlen += print_time(cont.ts_nsec, text); |
| 1399 | size -= textlen; | 1457 | size -= textlen; |
| 1400 | } | 1458 | } |
| @@ -1409,7 +1467,8 @@ static size_t cont_print_text(char *text, size_t size) | |||
| 1409 | } | 1467 | } |
| 1410 | 1468 | ||
| 1411 | if (cont.flushed) { | 1469 | if (cont.flushed) { |
| 1412 | text[textlen++] = '\n'; | 1470 | if (cont.flags & LOG_NEWLINE) |
| 1471 | text[textlen++] = '\n'; | ||
| 1413 | /* got everything, release buffer */ | 1472 | /* got everything, release buffer */ |
| 1414 | cont.len = 0; | 1473 | cont.len = 0; |
| 1415 | } | 1474 | } |
| @@ -1507,7 +1566,7 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
| 1507 | * or another task also prints continuation lines. | 1566 | * or another task also prints continuation lines. |
| 1508 | */ | 1567 | */ |
| 1509 | if (cont.len && (lflags & LOG_PREFIX || cont.owner != current)) | 1568 | if (cont.len && (lflags & LOG_PREFIX || cont.owner != current)) |
| 1510 | cont_flush(); | 1569 | cont_flush(LOG_NEWLINE); |
| 1511 | 1570 | ||
| 1512 | /* buffer line if possible, otherwise store it right away */ | 1571 | /* buffer line if possible, otherwise store it right away */ |
| 1513 | if (!cont_add(facility, level, text, text_len)) | 1572 | if (!cont_add(facility, level, text, text_len)) |
| @@ -1525,7 +1584,7 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
| 1525 | if (cont.len && cont.owner == current) { | 1584 | if (cont.len && cont.owner == current) { |
| 1526 | if (!(lflags & LOG_PREFIX)) | 1585 | if (!(lflags & LOG_PREFIX)) |
| 1527 | stored = cont_add(facility, level, text, text_len); | 1586 | stored = cont_add(facility, level, text, text_len); |
| 1528 | cont_flush(); | 1587 | cont_flush(LOG_NEWLINE); |
| 1529 | } | 1588 | } |
| 1530 | 1589 | ||
| 1531 | if (!stored) | 1590 | if (!stored) |
| @@ -1616,9 +1675,20 @@ asmlinkage int printk(const char *fmt, ...) | |||
| 1616 | } | 1675 | } |
| 1617 | EXPORT_SYMBOL(printk); | 1676 | EXPORT_SYMBOL(printk); |
| 1618 | 1677 | ||
| 1619 | #else | 1678 | #else /* CONFIG_PRINTK */ |
| 1620 | 1679 | ||
| 1680 | #define LOG_LINE_MAX 0 | ||
| 1681 | #define PREFIX_MAX 0 | ||
| 1621 | #define LOG_LINE_MAX 0 | 1682 | #define LOG_LINE_MAX 0 |
| 1683 | static u64 syslog_seq; | ||
| 1684 | static u32 syslog_idx; | ||
| 1685 | static u64 console_seq; | ||
| 1686 | static u32 console_idx; | ||
| 1687 | static enum log_flags syslog_prev; | ||
| 1688 | static u64 log_first_seq; | ||
| 1689 | static u32 log_first_idx; | ||
| 1690 | static u64 log_next_seq; | ||
| 1691 | static enum log_flags console_prev; | ||
| 1622 | static struct cont { | 1692 | static struct cont { |
| 1623 | size_t len; | 1693 | size_t len; |
| 1624 | size_t cons; | 1694 | size_t cons; |
| @@ -1902,10 +1972,34 @@ void wake_up_klogd(void) | |||
| 1902 | this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); | 1972 | this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); |
| 1903 | } | 1973 | } |
| 1904 | 1974 | ||
| 1905 | /* the next printk record to write to the console */ | 1975 | static void console_cont_flush(char *text, size_t size) |
| 1906 | static u64 console_seq; | 1976 | { |
| 1907 | static u32 console_idx; | 1977 | unsigned long flags; |
| 1908 | static enum log_flags console_prev; | 1978 | size_t len; |
| 1979 | |||
| 1980 | raw_spin_lock_irqsave(&logbuf_lock, flags); | ||
| 1981 | |||
| 1982 | if (!cont.len) | ||
| 1983 | goto out; | ||
| 1984 | |||
| 1985 | /* | ||
| 1986 | * We still queue earlier records, likely because the console was | ||
| 1987 | * busy. The earlier ones need to be printed before this one, we | ||
| 1988 | * did not flush any fragment so far, so just let it queue up. | ||
| 1989 | */ | ||
| 1990 | if (console_seq < log_next_seq && !cont.cons) | ||
| 1991 | goto out; | ||
| 1992 | |||
| 1993 | len = cont_print_text(text, size); | ||
| 1994 | raw_spin_unlock(&logbuf_lock); | ||
| 1995 | stop_critical_timings(); | ||
| 1996 | call_console_drivers(cont.level, text, len); | ||
| 1997 | start_critical_timings(); | ||
| 1998 | local_irq_restore(flags); | ||
| 1999 | return; | ||
| 2000 | out: | ||
| 2001 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | ||
| 2002 | } | ||
| 1909 | 2003 | ||
| 1910 | /** | 2004 | /** |
| 1911 | * console_unlock - unlock the console system | 2005 | * console_unlock - unlock the console system |
| @@ -1923,7 +2017,7 @@ static enum log_flags console_prev; | |||
| 1923 | */ | 2017 | */ |
| 1924 | void console_unlock(void) | 2018 | void console_unlock(void) |
| 1925 | { | 2019 | { |
| 1926 | static char text[LOG_LINE_MAX]; | 2020 | static char text[LOG_LINE_MAX + PREFIX_MAX]; |
| 1927 | static u64 seen_seq; | 2021 | static u64 seen_seq; |
| 1928 | unsigned long flags; | 2022 | unsigned long flags; |
| 1929 | bool wake_klogd = false; | 2023 | bool wake_klogd = false; |
| @@ -1937,19 +2031,7 @@ void console_unlock(void) | |||
| 1937 | console_may_schedule = 0; | 2031 | console_may_schedule = 0; |
| 1938 | 2032 | ||
| 1939 | /* flush buffered message fragment immediately to console */ | 2033 | /* flush buffered message fragment immediately to console */ |
| 1940 | raw_spin_lock_irqsave(&logbuf_lock, flags); | 2034 | console_cont_flush(text, sizeof(text)); |
| 1941 | if (cont.len && (cont.cons < cont.len || cont.flushed)) { | ||
| 1942 | size_t len; | ||
| 1943 | |||
| 1944 | len = cont_print_text(text, sizeof(text)); | ||
| 1945 | raw_spin_unlock(&logbuf_lock); | ||
| 1946 | stop_critical_timings(); | ||
| 1947 | call_console_drivers(cont.level, text, len); | ||
| 1948 | start_critical_timings(); | ||
| 1949 | local_irq_restore(flags); | ||
| 1950 | } else | ||
| 1951 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | ||
| 1952 | |||
| 1953 | again: | 2035 | again: |
| 1954 | for (;;) { | 2036 | for (;;) { |
| 1955 | struct log *msg; | 2037 | struct log *msg; |
| @@ -1986,6 +2068,7 @@ skip: | |||
| 1986 | * will properly dump everything later. | 2068 | * will properly dump everything later. |
| 1987 | */ | 2069 | */ |
| 1988 | msg->flags &= ~LOG_NOCONS; | 2070 | msg->flags &= ~LOG_NOCONS; |
| 2071 | console_prev = msg->flags; | ||
| 1989 | goto skip; | 2072 | goto skip; |
| 1990 | } | 2073 | } |
| 1991 | 2074 | ||
