ARM: 7668/1: fix memset-related crashes caused by recent GCC (4.7.2) optimizations

commit 455bd4c430b0c0a361f38e8658a0d6cb469942b5 upstream.

Recent GCC versions (e.g. GCC-4.7.2) perform optimizations based on
assumptions about the implementation of memset and similar functions.
The current ARM optimized memset code does not return the value of
its first argument, as is usually expected from standard implementations.

For instance in the following function:

void debug_mutex_lock_common(struct mutex *lock, struct mutex_waiter *waiter)
{
	memset(waiter, MUTEX_DEBUG_INIT, sizeof(*waiter));
	waiter->magic = waiter;
	INIT_LIST_HEAD(&waiter->list);
}

compiled as:

800554d0 <debug_mutex_lock_common>:
800554d0:       e92d4008        push    {r3, lr}
800554d4:       e1a00001        mov     r0, r1
800554d8:       e3a02010        mov     r2, #16 ; 0x10
800554dc:       e3a01011        mov     r1, #17 ; 0x11
800554e0:       eb04426e        bl      80165ea0 <memset>
800554e4:       e1a03000        mov     r3, r0
800554e8:       e583000c        str     r0, [r3, #12]
800554ec:       e5830000        str     r0, [r3]
800554f0:       e5830004        str     r0, [r3, #4]
800554f4:       e8bd8008        pop     {r3, pc}

GCC assumes memset returns the value of pointer 'waiter' in register r0; causing
register/memory corruptions.

This patch fixes the return value of the assembly version of memset.
It adds a 'mov' instruction and merges an additional load+store into
existing load/store instructions.
For ease of review, here is a breakdown of the patch into 4 simple steps:

Step 1
======
Perform the following substitutions:
ip -> r8, then
r0 -> ip,
and insert 'mov ip, r0' as the first statement of the function.
At this point, we have a memset() implementation returning the proper result,
but corrupting r8 on some paths (the ones that were using ip).

Step 2
======
Make sure r8 is saved and restored when (! CALGN(1)+0) == 1:

save r8:
-       str     lr, [sp, #-4]!
+       stmfd   sp!, {r8, lr}

and restore r8 on both exit paths:
-       ldmeqfd sp!, {pc}               @ Now <64 bytes to go.
+       ldmeqfd sp!, {r8, pc}           @ Now <64 bytes to go.
(...)
        tst     r2, #16
        stmneia ip!, {r1, r3, r8, lr}
-       ldr     lr, [sp], #4
+       ldmfd   sp!, {r8, lr}

Step 3
======
Make sure r8 is saved and restored when (! CALGN(1)+0) == 0:

save r8:
-       stmfd   sp!, {r4-r7, lr}
+       stmfd   sp!, {r4-r8, lr}

and restore r8 on both exit paths:
        bgt     3b
-       ldmeqfd sp!, {r4-r7, pc}
+       ldmeqfd sp!, {r4-r8, pc}
(...)
        tst     r2, #16
        stmneia ip!, {r4-r7}
-       ldmfd   sp!, {r4-r7, lr}
+       ldmfd   sp!, {r4-r8, lr}

Step 4
======
Rewrite register list "r4-r7, r8" as "r4-r8".

Signed-off-by: Ivan Djelic <ivan.djelic@parrot.com>
Reviewed-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Dirk Behme <dirk.behme@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Eric Bénard <eric@eukrea.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
ARM: 7670/1: fix the memset fix

commit 418df63adac56841ef6b0f1fcf435bc64d4ed177 upstream.

Commit 455bd4c430b0 ("ARM: 7668/1: fix memset-related crashes caused by
recent GCC (4.7.2) optimizations") attempted to fix a compliance issue
with the memset return value.  However the memset itself became broken
by that patch for misaligned pointers.

This fixes the above by branching over the entry code from the
misaligned fixup code to avoid reloading the original pointer.

Also, because the function entry alignment is wrong in the Thumb mode
compilation, that fixup code is moved to the end.

While at it, the entry instructions are slightly reworked to help dual
issue pipelines.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
Tested-by: Alexander Holler <holler@ahsoftware.de>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Eric Bénard <eric@eukrea.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net: smsc phy: disable energy detect power for LAN87x0

- link detection isn't reliable when the automatic power down
  via link energy detection is enabled
arm: pia-am335x: cleanup resolved TODO comments

Signed-off-by: Björn Krombholz <b.krombholz@pironex.de>
pia-am335x-mmi: update touch threshold for cap touch

- use a higher default threashold for the capacitive touch on MMI boards
- the old value caused jumping cursors in some cases

Signed-off-by: Björn Krombholz <b.krombholz@pironex.de>
arm: am33xx: add missing pinmux signals for can0

Signed-off-by: Björn Krombholz <b.krombholz@pironex.de>
arm: pia-am335x: fix pinmux signal names

- gpmc_beXn -> gpmc_benX
- gpio3_10 pin base signal fix

Signed-off-by: Björn Krombholz <b.krombholz@pironex.de>
arm: pia-am335x: fix pmic device registration

- We saw spinlock lockups on some devices when the TPS65910 device in it's
  own init function. The reason is unclear.
- Put the I2C device platform info to the generic array of I2C data
  and initialize with all the other devices on the bus, pmic_init is only
  used to setup the INT pin and should be called before i2c1_init

Signed-off-by: Björn Krombholz <b.krombholz@pironex.de>
pia-am335x-mmi: disable omap rtc device on MMI boards

- TPS RTC is used and should be initialized as /dev/rtc0

Signed-off-by: Björn Krombholz <b.krombholz@pironex.de>
mfd: tps65910: fix regcache max register address

- max_register specifies the maximum index not the number of registers
- remove unneccessary num_reg_defaults_raw setting

Signed-off-by: Björn Krombholz <b.krombholz@pironex.de>
arm: pia-am335x: make UID EEPROM board specific

- not all piA-AM335x boards have the 24CS variant of the EEPROM.

Signed-off-by: Björn Krombholz <b.krombholz@pironex.de>
arm: pia-am335x: reorder spi/mmc init

- make sure mmc is initialized before spi, as for some unknown
  reason we see a deadlock otherwise in some configurations during
  rootfs mounting.

Signed-off-by: Björn Krombholz <b.krombholz@pironex.de>

Conflicts:
	arch/arm/mach-omap2/board-am335xpia.c
arm: pia-am335x: unify unconnected cpsw phy configs

- set unconnected MII interfaces to PHY address 0:0f on all boards

Signed-off-by: Björn Krombholz <b.krombholz@pironex.de>

Conflicts:
	arch/arm/mach-omap2/board-am335xpia.c
ARM: 7668/1: fix memset-related crashes caused by recent GCC (4.7.2) optimizations

commit 455bd4c430b0c0a361f38e8658a0d6cb469942b5 upstream.

Recent GCC versions (e.g. GCC-4.7.2) perform optimizations based on
assumptions about the implementation of memset and similar functions.
The current ARM optimized memset code does not return the value of
its first argument, as is usually expected from standard implementations.

For instance in the following function:

void debug_mutex_lock_common(struct mutex *lock, struct mutex_waiter *waiter)
{
	memset(waiter, MUTEX_DEBUG_INIT, sizeof(*waiter));
	waiter->magic = waiter;
	INIT_LIST_HEAD(&waiter->list);
}

compiled as:

800554d0 <debug_mutex_lock_common>:
800554d0:       e92d4008        push    {r3, lr}
800554d4:       e1a00001        mov     r0, r1
800554d8:       e3a02010        mov     r2, #16 ; 0x10
800554dc:       e3a01011        mov     r1, #17 ; 0x11
800554e0:       eb04426e        bl      80165ea0 <memset>
800554e4:       e1a03000        mov     r3, r0
800554e8:       e583000c        str     r0, [r3, #12]
800554ec:       e5830000        str     r0, [r3]
800554f0:       e5830004        str     r0, [r3, #4]
800554f4:       e8bd8008        pop     {r3, pc}

GCC assumes memset returns the value of pointer 'waiter' in register r0; causing
register/memory corruptions.

This patch fixes the return value of the assembly version of memset.
It adds a 'mov' instruction and merges an additional load+store into
existing load/store instructions.
For ease of review, here is a breakdown of the patch into 4 simple steps:

Step 1
======
Perform the following substitutions:
ip -> r8, then
r0 -> ip,
and insert 'mov ip, r0' as the first statement of the function.
At this point, we have a memset() implementation returning the proper result,
but corrupting r8 on some paths (the ones that were using ip).

Step 2
======
Make sure r8 is saved and restored when (! CALGN(1)+0) == 1:

save r8:
-       str     lr, [sp, #-4]!
+       stmfd   sp!, {r8, lr}

and restore r8 on both exit paths:
-       ldmeqfd sp!, {pc}               @ Now <64 bytes to go.
+       ldmeqfd sp!, {r8, pc}           @ Now <64 bytes to go.
(...)
        tst     r2, #16
        stmneia ip!, {r1, r3, r8, lr}
-       ldr     lr, [sp], #4
+       ldmfd   sp!, {r8, lr}

Step 3
======
Make sure r8 is saved and restored when (! CALGN(1)+0) == 0:

save r8:
-       stmfd   sp!, {r4-r7, lr}
+       stmfd   sp!, {r4-r8, lr}

and restore r8 on both exit paths:
        bgt     3b
-       ldmeqfd sp!, {r4-r7, pc}
+       ldmeqfd sp!, {r4-r8, pc}
(...)
        tst     r2, #16
        stmneia ip!, {r4-r7}
-       ldmfd   sp!, {r4-r7, lr}
+       ldmfd   sp!, {r4-r8, lr}

Step 4
======
Rewrite register list "r4-r7, r8" as "r4-r8".

Signed-off-by: Ivan Djelic <ivan.djelic@parrot.com>
Reviewed-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Dirk Behme <dirk.behme@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Eric Bénard <eric@eukrea.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
ARM: 7670/1: fix the memset fix

commit 418df63adac56841ef6b0f1fcf435bc64d4ed177 upstream.

Commit 455bd4c430b0 ("ARM: 7668/1: fix memset-related crashes caused by
recent GCC (4.7.2) optimizations") attempted to fix a compliance issue
with the memset return value.  However the memset itself became broken
by that patch for misaligned pointers.

This fixes the above by branching over the entry code from the
misaligned fixup code to avoid reloading the original pointer.

Also, because the function entry alignment is wrong in the Thumb mode
compilation, that fixup code is moved to the end.

While at it, the entry instructions are slightly reworked to help dual
issue pipelines.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
Tested-by: Alexander Holler <holler@ahsoftware.de>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Eric Bénard <eric@eukrea.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
pia-am335x-mmi: update touch threshold for cap touch

- use a higher default threashold for the capacitive touch on MMI boards
- the old value caused jumping cursors in some cases

Signed-off-by: Björn Krombholz <b.krombholz@pironex.de>
input: ft4x06: fix setting the touch threshold in probe

- use the correct buffer

Signed-off-by: Björn Krombholz <b.krombholz@pironex.de>
pia-am335x-mmi: lower touch threshold further

- depending on ambient temperature, the selected threshold was too high

Signed-off-by: Björn Krombholz <b.krombholz@pironex.de>
Merge branch 'pia335x-mmi-dev' into pia335x-dev

* pia335x-mmi-dev:
  pia-am335x-mmi: lower touch threshold further
  input: ft4x06: fix setting the touch threshold in probe
  pia-am335x-mmi: update touch threshold for cap touch
  ARM: 7670/1: fix the memset fix
  ARM: 7668/1: fix memset-related crashes caused by recent GCC (4.7.2) optimizations
  arm: pia-am335x: unify unconnected cpsw phy configs
  arm: pia-am335x: reorder spi/mmc init
  arm: pia-am335x: make UID EEPROM board specific
  mfd: tps65910: fix regcache max register address
  pia-am335x-mmi: disable omap rtc device on MMI boards
  arm: pia-am335x: fix pmic device registration
  arm: pia-am335x: fix pinmux signal names
  arm: am33xx: add missing pinmux signals for can0

Conflicts:
	arch/arm/mach-omap2/board-am335xpia.c
iio: add simple DAC driver for MAX536x I2C DAC

- MAX536x is a simple 1 channel 6 bit I2C DAC
- This driver supports all variants MAX5360, MAX5361, MAX5362, which
  only differ in the default Vref Voltage.

Signed-off-by: Björn Krombholz <b.krombholz@pironex.de>