diff options
Diffstat (limited to 'arch')
130 files changed, 1987 insertions, 1601 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 68b456129be..894487479f3 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -37,6 +37,9 @@ config ARM  	  Europe.  There is an ARM Linux project with a web page at  	  <http://www.arm.linux.org.uk/>. +config ARM_HAS_SG_CHAIN +	bool +  config HAVE_PWM  	bool @@ -1346,7 +1349,6 @@ config SMP_ON_UP  config HAVE_ARM_SCU  	bool -	depends on SMP  	help  	  This option enables support for the ARM system coherency unit @@ -1715,17 +1717,34 @@ config ZBOOT_ROM  	  Say Y here if you intend to execute your compressed kernel image  	  (zImage) directly from ROM or flash.  If unsure, say N. +choice +	prompt "Include SD/MMC loader in zImage (EXPERIMENTAL)" +	depends on ZBOOT_ROM && ARCH_SH7372 && EXPERIMENTAL +	default ZBOOT_ROM_NONE +	help +	  Include experimental SD/MMC loading code in the ROM-able zImage. +	  With this enabled it is possible to write the the ROM-able zImage +	  kernel image to an MMC or SD card and boot the kernel straight +	  from the reset vector. At reset the processor Mask ROM will load +	  the first part of the the ROM-able zImage which in turn loads the +	  rest the kernel image to RAM. + +config ZBOOT_ROM_NONE +	bool "No SD/MMC loader in zImage (EXPERIMENTAL)" +	help +	  Do not load image from SD or MMC +  config ZBOOT_ROM_MMCIF  	bool "Include MMCIF loader in zImage (EXPERIMENTAL)" -	depends on ZBOOT_ROM && ARCH_SH7372 && EXPERIMENTAL  	help -	  Say Y here to include experimental MMCIF loading code in the -	  ROM-able zImage. With this enabled it is possible to write the -	  the ROM-able zImage kernel image to an MMC card and boot the -	  kernel straight from the reset vector. At reset the processor -	  Mask ROM will load the first part of the the ROM-able zImage -	  which in turn loads the rest the kernel image to RAM using the -	  MMCIF hardware block. +	  Load image from MMCIF hardware block. + +config ZBOOT_ROM_SH_MOBILE_SDHI +	bool "Include SuperH Mobile SDHI loader in zImage (EXPERIMENTAL)" +	help +	  Load image from SDHI hardware block + +endchoice  config CMDLINE  	string "Default kernel command string" diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 23aad072230..0c74a6fab95 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -6,13 +6,19 @@  OBJS		= -# Ensure that mmcif loader code appears early in the image +# Ensure that MMCIF loader code appears early in the image  # to minimise that number of bocks that have to be read in  # order to load it.  ifeq ($(CONFIG_ZBOOT_ROM_MMCIF),y) -ifeq ($(CONFIG_ARCH_SH7372),y)  OBJS		+= mmcif-sh7372.o  endif + +# Ensure that SDHI loader code appears early in the image +# to minimise that number of bocks that have to be read in +# order to load it. +ifeq ($(CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI),y) +OBJS		+= sdhi-shmobile.o +OBJS		+= sdhi-sh7372.o  endif  AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET) diff --git a/arch/arm/boot/compressed/head-shmobile.S b/arch/arm/boot/compressed/head-shmobile.S index c943d2e7da9..fe3719b516f 100644 --- a/arch/arm/boot/compressed/head-shmobile.S +++ b/arch/arm/boot/compressed/head-shmobile.S @@ -25,14 +25,14 @@  	/* load board-specific initialization code */  #include <mach/zboot.h> -#ifdef CONFIG_ZBOOT_ROM_MMCIF -	/* Load image from MMC */ -	adr	sp, __tmp_stack + 128 +#if defined(CONFIG_ZBOOT_ROM_MMCIF) || defined(CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI) +	/* Load image from MMC/SD */ +	adr	sp, __tmp_stack + 256  	ldr	r0, __image_start  	ldr	r1, __image_end  	subs	r1, r1, r0  	ldr	r0, __load_base -	bl	mmcif_loader +	bl	mmc_loader  	/* Jump to loaded code */  	ldr	r0, __loaded @@ -51,9 +51,9 @@ __loaded:  	.long	__continue  	.align  __tmp_stack: -	.space	128 +	.space	256  __continue: -#endif /* CONFIG_ZBOOT_ROM_MMCIF */ +#endif /* CONFIG_ZBOOT_ROM_MMC || CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI */  	b	1f  __atags:@ tag #1 diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 940b2017810..e95a5989602 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -353,7 +353,8 @@ not_relocated:	mov	r0, #0  		mov	r0, #0			@ must be zero  		mov	r1, r7			@ restore architecture number  		mov	r2, r8			@ restore atags pointer -		mov	pc, r4			@ call kernel + ARM(		mov	pc, r4	)		@ call kernel + THUMB(		bx	r4	)		@ entry point is always ARM  		.align	2  		.type	LC0, #object diff --git a/arch/arm/boot/compressed/mmcif-sh7372.c b/arch/arm/boot/compressed/mmcif-sh7372.c index 7453c8337b8..b6f61d9a5a1 100644 --- a/arch/arm/boot/compressed/mmcif-sh7372.c +++ b/arch/arm/boot/compressed/mmcif-sh7372.c @@ -40,7 +40,7 @@   * to an MMC card   * # dd if=vrl4.out of=/dev/sdx bs=512 seek=1   */ -asmlinkage void mmcif_loader(unsigned char *buf, unsigned long len) +asmlinkage void mmc_loader(unsigned char *buf, unsigned long len)  {  	mmc_init_progress();  	mmc_update_progress(MMC_PROGRESS_ENTER); diff --git a/arch/arm/boot/compressed/sdhi-sh7372.c b/arch/arm/boot/compressed/sdhi-sh7372.c new file mode 100644 index 00000000000..d403a8b24d7 --- /dev/null +++ b/arch/arm/boot/compressed/sdhi-sh7372.c @@ -0,0 +1,95 @@ +/* + * SuperH Mobile SDHI + * + * Copyright (C) 2010 Magnus Damm + * Copyright (C) 2010 Kuninori Morimoto + * Copyright (C) 2010 Simon Horman + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Parts inspired by u-boot + */ + +#include <linux/io.h> +#include <mach/mmc.h> +#include <linux/mmc/boot.h> +#include <linux/mmc/tmio.h> + +#include "sdhi-shmobile.h" + +#define PORT179CR       0xe60520b3 +#define PORT180CR       0xe60520b4 +#define PORT181CR       0xe60520b5 +#define PORT182CR       0xe60520b6 +#define PORT183CR       0xe60520b7 +#define PORT184CR       0xe60520b8 + +#define SMSTPCR3        0xe615013c + +#define CR_INPUT_ENABLE 0x10 +#define CR_FUNCTION1    0x01 + +#define SDHI1_BASE	(void __iomem *)0xe6860000 +#define SDHI_BASE	SDHI1_BASE + +/*  SuperH Mobile SDHI loader + * + * loads the zImage from an SD card starting from block 0 + * on physical partition 1 + * + * The image must be start with a vrl4 header and + * the zImage must start at offset 512 of the image. That is, + * at block 1 (=byte 512) of physical partition 1 + * + * Use the following line to write the vrl4 formated zImage + * to an SD card + * # dd if=vrl4.out of=/dev/sdx bs=512 + */ +asmlinkage void mmc_loader(unsigned short *buf, unsigned long len) +{ +	int high_capacity; + +	mmc_init_progress(); + +	mmc_update_progress(MMC_PROGRESS_ENTER); +        /* Initialise SDHI1 */ +        /* PORT184CR: GPIO_FN_SDHICMD1 Control */ +        __raw_writeb(CR_FUNCTION1, PORT184CR); +        /* PORT179CR: GPIO_FN_SDHICLK1 Control */ +        __raw_writeb(CR_INPUT_ENABLE|CR_FUNCTION1, PORT179CR); +        /* PORT181CR: GPIO_FN_SDHID1_3 Control */ +        __raw_writeb(CR_FUNCTION1, PORT183CR); +        /* PORT182CR: GPIO_FN_SDHID1_2 Control */ +        __raw_writeb(CR_FUNCTION1, PORT182CR); +        /* PORT183CR: GPIO_FN_SDHID1_1 Control */ +        __raw_writeb(CR_FUNCTION1, PORT181CR); +        /* PORT180CR: GPIO_FN_SDHID1_0 Control */ +        __raw_writeb(CR_FUNCTION1, PORT180CR); + +        /* Enable clock to SDHI1 hardware block */ +        __raw_writel(__raw_readl(SMSTPCR3) & ~(1 << 13), SMSTPCR3); + +	/* setup SDHI hardware */ +	mmc_update_progress(MMC_PROGRESS_INIT); +	high_capacity = sdhi_boot_init(SDHI_BASE); +	if (high_capacity < 0) +		goto err; + +	mmc_update_progress(MMC_PROGRESS_LOAD); +	/* load kernel */ +	if (sdhi_boot_do_read(SDHI_BASE, high_capacity, +			      0, /* Kernel is at block 1 */ +			      (len + TMIO_BBS - 1) / TMIO_BBS, buf)) +		goto err; + +        /* Disable clock to SDHI1 hardware block */ +        __raw_writel(__raw_readl(SMSTPCR3) & (1 << 13), SMSTPCR3); + +	mmc_update_progress(MMC_PROGRESS_DONE); + +	return; +err: +	for(;;); +} diff --git a/arch/arm/boot/compressed/sdhi-shmobile.c b/arch/arm/boot/compressed/sdhi-shmobile.c new file mode 100644 index 00000000000..bd3d4698095 --- /dev/null +++ b/arch/arm/boot/compressed/sdhi-shmobile.c @@ -0,0 +1,449 @@ +/* + * SuperH Mobile SDHI + * + * Copyright (C) 2010 Magnus Damm + * Copyright (C) 2010 Kuninori Morimoto + * Copyright (C) 2010 Simon Horman + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Parts inspired by u-boot + */ + +#include <linux/io.h> +#include <linux/mmc/host.h> +#include <linux/mmc/core.h> +#include <linux/mmc/mmc.h> +#include <linux/mmc/sd.h> +#include <linux/mmc/tmio.h> +#include <mach/sdhi.h> + +#define OCR_FASTBOOT		(1<<29) +#define OCR_HCS			(1<<30) +#define OCR_BUSY		(1<<31) + +#define RESP_CMD12		0x00000030 + +static inline u16 sd_ctrl_read16(void __iomem *base, int addr) +{ +        return __raw_readw(base + addr); +} + +static inline u32 sd_ctrl_read32(void __iomem *base, int addr) +{ +	return __raw_readw(base + addr) | +	       __raw_readw(base + addr + 2) << 16; +} + +static inline void sd_ctrl_write16(void __iomem *base, int addr, u16 val) +{ +	__raw_writew(val, base + addr); +} + +static inline void sd_ctrl_write32(void __iomem *base, int addr, u32 val) +{ +	__raw_writew(val, base + addr); +	__raw_writew(val >> 16, base + addr + 2); +} + +#define ALL_ERROR (TMIO_STAT_CMD_IDX_ERR | TMIO_STAT_CRCFAIL |		\ +		   TMIO_STAT_STOPBIT_ERR | TMIO_STAT_DATATIMEOUT |	\ +		   TMIO_STAT_RXOVERFLOW | TMIO_STAT_TXUNDERRUN |	\ +		   TMIO_STAT_CMDTIMEOUT | TMIO_STAT_ILL_ACCESS |	\ +		   TMIO_STAT_ILL_FUNC) + +static int sdhi_intr(void __iomem *base) +{ +	unsigned long state = sd_ctrl_read32(base, CTL_STATUS); + +	if (state & ALL_ERROR) { +		sd_ctrl_write32(base, CTL_STATUS, ~ALL_ERROR); +		sd_ctrl_write32(base, CTL_IRQ_MASK, +				ALL_ERROR | +				sd_ctrl_read32(base, CTL_IRQ_MASK)); +		return -EINVAL; +	} +	if (state & TMIO_STAT_CMDRESPEND) { +		sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_CMDRESPEND); +		sd_ctrl_write32(base, CTL_IRQ_MASK, +				TMIO_STAT_CMDRESPEND | +				sd_ctrl_read32(base, CTL_IRQ_MASK)); +		return 0; +	} +	if (state & TMIO_STAT_RXRDY) { +		sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_RXRDY); +		sd_ctrl_write32(base, CTL_IRQ_MASK, +				TMIO_STAT_RXRDY | TMIO_STAT_TXUNDERRUN | +				sd_ctrl_read32(base, CTL_IRQ_MASK)); +		return 0; +	} +	if (state & TMIO_STAT_DATAEND) { +		sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_DATAEND); +		sd_ctrl_write32(base, CTL_IRQ_MASK, +				TMIO_STAT_DATAEND | +				sd_ctrl_read32(base, CTL_IRQ_MASK)); +		return 0; +	} + +	return -EAGAIN; +} + +static int sdhi_boot_wait_resp_end(void __iomem *base) +{ +	int err = -EAGAIN, timeout = 10000000; + +	while (timeout--) { +		err = sdhi_intr(base); +		if (err != -EAGAIN) +			break; +		udelay(1); +	} + +	return err; +} + +/* SDHI_CLK_CTRL */ +#define CLK_MMC_ENABLE                 (1 << 8) +#define CLK_MMC_INIT                   (1 << 6)        /* clk / 256 */ + +static void sdhi_boot_mmc_clk_stop(void __iomem *base) +{ +	sd_ctrl_write16(base, CTL_CLK_AND_WAIT_CTL, 0x0000); +	msleep(10); +	sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL, ~CLK_MMC_ENABLE & +		sd_ctrl_read16(base, CTL_SD_CARD_CLK_CTL)); +	msleep(10); +} + +static void sdhi_boot_mmc_clk_start(void __iomem *base) +{ +	sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL, CLK_MMC_ENABLE | +		sd_ctrl_read16(base, CTL_SD_CARD_CLK_CTL)); +	msleep(10); +	sd_ctrl_write16(base, CTL_CLK_AND_WAIT_CTL, CLK_MMC_ENABLE); +	msleep(10); +} + +static void sdhi_boot_reset(void __iomem *base) +{ +	sd_ctrl_write16(base, CTL_RESET_SD, 0x0000); +	msleep(10); +	sd_ctrl_write16(base, CTL_RESET_SD, 0x0001); +	msleep(10); +} + +/* Set MMC clock / power. + * Note: This controller uses a simple divider scheme therefore it cannot + * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as + * MMC wont run that fast, it has to be clocked at 12MHz which is the next + * slowest setting. + */ +static int sdhi_boot_mmc_set_ios(void __iomem *base, struct mmc_ios *ios) +{ +	if (sd_ctrl_read32(base, CTL_STATUS) & TMIO_STAT_CMD_BUSY) +		return -EBUSY; + +	if (ios->clock) +		sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL, +				ios->clock | CLK_MMC_ENABLE); + +	/* Power sequence - OFF -> ON -> UP */ +	switch (ios->power_mode) { +	case MMC_POWER_OFF: /* power down SD bus */ +		sdhi_boot_mmc_clk_stop(base); +		break; +	case MMC_POWER_ON: /* power up SD bus */ +		break; +	case MMC_POWER_UP: /* start bus clock */ +		sdhi_boot_mmc_clk_start(base); +		break; +	} + +	switch (ios->bus_width) { +	case MMC_BUS_WIDTH_1: +		sd_ctrl_write16(base, CTL_SD_MEM_CARD_OPT, 0x80e0); +	break; +	case MMC_BUS_WIDTH_4: +		sd_ctrl_write16(base, CTL_SD_MEM_CARD_OPT, 0x00e0); +	break; +	} + +	/* Let things settle. delay taken from winCE driver */ +	udelay(140); + +	return 0; +} + +/* These are the bitmasks the tmio chip requires to implement the MMC response + * types. Note that R1 and R6 are the same in this scheme. */ +#define RESP_NONE      0x0300 +#define RESP_R1        0x0400 +#define RESP_R1B       0x0500 +#define RESP_R2        0x0600 +#define RESP_R3        0x0700 +#define DATA_PRESENT   0x0800 +#define TRANSFER_READ  0x1000 + +static int sdhi_boot_request(void __iomem *base, struct mmc_command *cmd) +{ +	int err, c = cmd->opcode; + +	switch (mmc_resp_type(cmd)) { +	case MMC_RSP_NONE: c |= RESP_NONE; break; +	case MMC_RSP_R1:   c |= RESP_R1;   break; +	case MMC_RSP_R1B:  c |= RESP_R1B;  break; +	case MMC_RSP_R2:   c |= RESP_R2;   break; +	case MMC_RSP_R3:   c |= RESP_R3;   break; +	default: +		return -EINVAL; +	} + +	/* No interrupts so this may not be cleared */ +	sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_CMDRESPEND); + +	sd_ctrl_write32(base, CTL_IRQ_MASK, TMIO_STAT_CMDRESPEND | +			sd_ctrl_read32(base, CTL_IRQ_MASK)); +	sd_ctrl_write32(base, CTL_ARG_REG, cmd->arg); +	sd_ctrl_write16(base, CTL_SD_CMD, c); + + +	sd_ctrl_write32(base, CTL_IRQ_MASK, +			~(TMIO_STAT_CMDRESPEND | ALL_ERROR) & +			sd_ctrl_read32(base, CTL_IRQ_MASK)); + +	err = sdhi_boot_wait_resp_end(base); +	if (err) +		return err; + +	cmd->resp[0] = sd_ctrl_read32(base, CTL_RESPONSE); + +	return 0; +} + +static int sdhi_boot_do_read_single(void __iomem *base, int high_capacity, +				    unsigned long block, unsigned short *buf) +{ +	int err, i; + +	/* CMD17 - Read */ +	{ +		struct mmc_command cmd; + +		cmd.opcode = MMC_READ_SINGLE_BLOCK | \ +			     TRANSFER_READ | DATA_PRESENT; +		if (high_capacity) +			cmd.arg = block; +		else +			cmd.arg = block * TMIO_BBS; +		cmd.flags = MMC_RSP_R1; +		err = sdhi_boot_request(base, &cmd); +		if (err) +			return err; +	} + +	sd_ctrl_write32(base, CTL_IRQ_MASK, +			~(TMIO_STAT_DATAEND | TMIO_STAT_RXRDY | +			  TMIO_STAT_TXUNDERRUN) & +			sd_ctrl_read32(base, CTL_IRQ_MASK)); +	err = sdhi_boot_wait_resp_end(base); +	if (err) +		return err; + +	sd_ctrl_write16(base, CTL_SD_XFER_LEN, TMIO_BBS); +	for (i = 0; i < TMIO_BBS / sizeof(*buf); i++) +		*buf++ = sd_ctrl_read16(base, RESP_CMD12); + +	err = sdhi_boot_wait_resp_end(base); +	if (err) +		return err; + +	return 0; +} + +int sdhi_boot_do_read(void __iomem *base, int high_capacity, +		      unsigned long offset, unsigned short count, +		      unsigned short *buf) +{ +	unsigned long i; +	int err = 0; + +	for (i = 0; i < count; i++) { +		err = sdhi_boot_do_read_single(base, high_capacity, offset + i, +					       buf + (i * TMIO_BBS / +						      sizeof(*buf))); +		if (err) +			return err; +	} + +	return 0; +} + +#define VOLTAGES (MMC_VDD_32_33 | MMC_VDD_33_34) + +int sdhi_boot_init(void __iomem *base) +{ +	bool sd_v2 = false, sd_v1_0 = false; +	unsigned short cid; +	int err, high_capacity = 0; + +	sdhi_boot_mmc_clk_stop(base); +	sdhi_boot_reset(base); + +	/* mmc0: clock 400000Hz busmode 1 powermode 2 cs 0 Vdd 21 width 0 timing 0 */ +	{ +		struct mmc_ios ios; +		ios.power_mode = MMC_POWER_ON; +		ios.bus_width = MMC_BUS_WIDTH_1; +		ios.clock = CLK_MMC_INIT; +		err = sdhi_boot_mmc_set_ios(base, &ios); +		if (err) +			return err; +	} + +	/* CMD0 */ +	{ +		struct mmc_command cmd; +		msleep(1); +		cmd.opcode = MMC_GO_IDLE_STATE; +		cmd.arg = 0; +		cmd.flags = MMC_RSP_NONE; +		err = sdhi_boot_request(base, &cmd); +		if (err) +			return err; +		msleep(2); +	} + +	/* CMD8 - Test for SD version 2 */ +	{ +		struct mmc_command cmd; +		cmd.opcode = SD_SEND_IF_COND; +		cmd.arg = (VOLTAGES != 0) << 8 | 0xaa; +		cmd.flags = MMC_RSP_R1; +		err = sdhi_boot_request(base, &cmd); /* Ignore error */ +		if ((cmd.resp[0] & 0xff) == 0xaa) +			sd_v2 = true; +	} + +	/* CMD55 - Get OCR (SD) */ +	{ +		int timeout = 1000; +		struct mmc_command cmd; + +		cmd.arg = 0; + +		do { +			cmd.opcode = MMC_APP_CMD; +			cmd.flags = MMC_RSP_R1; +			cmd.arg = 0; +			err = sdhi_boot_request(base, &cmd); +			if (err) +				break; + +			cmd.opcode = SD_APP_OP_COND; +			cmd.flags = MMC_RSP_R3; +			cmd.arg = (VOLTAGES & 0xff8000); +			if (sd_v2) +				cmd.arg |= OCR_HCS; +			cmd.arg |= OCR_FASTBOOT; +			err = sdhi_boot_request(base, &cmd); +			if (err) +				break; + +			msleep(1); +		} while((!(cmd.resp[0] & OCR_BUSY)) && --timeout); + +		if (!err && timeout) { +			if (!sd_v2) +				sd_v1_0 = true; +			high_capacity = (cmd.resp[0] & OCR_HCS) == OCR_HCS; +		} +	} + +	/* CMD1 - Get OCR (MMC) */ +	if (!sd_v2 && !sd_v1_0) { +		int timeout = 1000; +		struct mmc_command cmd; + +		do { +			cmd.opcode = MMC_SEND_OP_COND; +			cmd.arg = VOLTAGES | OCR_HCS; +			cmd.flags = MMC_RSP_R3; +			err = sdhi_boot_request(base, &cmd); +			if (err) +				return err; + +			msleep(1); +		} while((!(cmd.resp[0] & OCR_BUSY)) && --timeout); + +		if (!timeout) +			return -EAGAIN; + +		high_capacity = (cmd.resp[0] & OCR_HCS) == OCR_HCS; +	} + +	/* CMD2 - Get CID */ +	{ +		struct mmc_command cmd; +		cmd.opcode = MMC_ALL_SEND_CID; +		cmd.arg = 0; +		cmd.flags = MMC_RSP_R2; +		err = sdhi_boot_request(base, &cmd); +		if (err) +			return err; +	} + +	/* CMD3 +	 * MMC: Set the relative address +	 * SD:  Get the relative address +	 * Also puts the card into the standby state +	 */ +	{ +		struct mmc_command cmd; +		cmd.opcode = MMC_SET_RELATIVE_ADDR; +		cmd.arg = 0; +		cmd.flags = MMC_RSP_R1; +		err = sdhi_boot_request(base, &cmd); +		if (err) +			return err; +		cid = cmd.resp[0] >> 16; +	} + +	/* CMD9 - Get CSD */ +	{ +		struct mmc_command cmd; +		cmd.opcode = MMC_SEND_CSD; +		cmd.arg = cid << 16; +		cmd.flags = MMC_RSP_R2; +		err = sdhi_boot_request(base, &cmd); +		if (err) +			return err; +	} + +	/* CMD7 - Select the card */ +	{ +		struct mmc_command cmd; +		cmd.opcode = MMC_SELECT_CARD; +		//cmd.arg = rca << 16; +		cmd.arg = cid << 16; +		//cmd.flags = MMC_RSP_R1B; +		cmd.flags = MMC_RSP_R1; +		err = sdhi_boot_request(base, &cmd); +		if (err) +			return err; +	} + +	/* CMD16 - Set the block size */ +	{ +		struct mmc_command cmd; +		cmd.opcode = MMC_SET_BLOCKLEN; +		cmd.arg = TMIO_BBS; +		cmd.flags = MMC_RSP_R1; +		err = sdhi_boot_request(base, &cmd); +		if (err) +			return err; +	} + +	return high_capacity; +} diff --git a/arch/arm/boot/compressed/sdhi-shmobile.h b/arch/arm/boot/compressed/sdhi-shmobile.h new file mode 100644 index 00000000000..92eaa09f985 --- /dev/null +++ b/arch/arm/boot/compressed/sdhi-shmobile.h @@ -0,0 +1,11 @@ +#ifndef SDHI_MOBILE_H +#define SDHI_MOBILE_H + +#include <linux/compiler.h> + +int sdhi_boot_do_read(void __iomem *base, int high_capacity, +		      unsigned long offset, unsigned short count, +		      unsigned short *buf); +int sdhi_boot_init(void __iomem *base); + +#endif diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in index ea80abe7884..4e728834a1b 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.in +++ b/arch/arm/boot/compressed/vmlinux.lds.in @@ -33,20 +33,24 @@ SECTIONS      *(.text.*)      *(.fixup)      *(.gnu.warning) +    *(.glue_7t) +    *(.glue_7) +  } +  .rodata : {      *(.rodata)      *(.rodata.*) -    *(.glue_7) -    *(.glue_7t) +  } +  .piggydata : {      *(.piggydata) -    . = ALIGN(4);    } +  . = ALIGN(4);    _etext = .; +  .got.plt		: { *(.got.plt) }    _got_start = .;    .got			: { *(.got) }    _got_end = .; -  .got.plt		: { *(.got.plt) }    _edata = .;    . = BSS_START; diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 4ddd0a6ac7f..7bdd91766d6 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -179,22 +179,21 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,  {  	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);  	unsigned int shift = (d->irq % 4) * 8; -	unsigned int cpu = cpumask_first(mask_val); +	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);  	u32 val, mask, bit; -	if (cpu >= 8) +	if (cpu >= 8 || cpu >= nr_cpu_ids)  		return -EINVAL;  	mask = 0xff << shift;  	bit = 1 << (cpu + shift);  	spin_lock(&irq_controller_lock); -	d->node = cpu;  	val = readl_relaxed(reg) & ~mask;  	writel_relaxed(val | bit, reg);  	spin_unlock(&irq_controller_lock); -	return 0; +	return IRQ_SET_MASK_OK;  }  #endif diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h index b4892a06442..f4280593dfa 100644 --- a/arch/arm/include/asm/bitops.h +++ b/arch/arm/include/asm/bitops.h @@ -26,8 +26,8 @@  #include <linux/compiler.h>  #include <asm/system.h> -#define smp_mb__before_clear_bit()	mb() -#define smp_mb__after_clear_bit()	mb() +#define smp_mb__before_clear_bit()	smp_mb() +#define smp_mb__after_clear_bit()	smp_mb()  /*   * These functions are the basis of our bit ops. diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S index 2da8547de6d..2f1e2098dfe 100644 --- a/arch/arm/include/asm/entry-macro-multi.S +++ b/arch/arm/include/asm/entry-macro-multi.S @@ -4,8 +4,8 @@   * Interrupt handling.  Preserves r7, r8, r9   */  	.macro	arch_irq_handler_default -	get_irqnr_preamble r5, lr -1:	get_irqnr_and_base r0, r6, r5, lr +	get_irqnr_preamble r6, lr +1:	get_irqnr_and_base r0, r2, r6, lr  	movne	r1, sp  	@  	@ routine called with r0 = irq number, r1 = struct pt_regs * @@ -17,17 +17,17 @@  	/*  	 * XXX  	 * -	 * this macro assumes that irqstat (r6) and base (r5) are +	 * this macro assumes that irqstat (r2) and base (r6) are  	 * preserved from get_irqnr_and_base above  	 */ -	ALT_SMP(test_for_ipi r0, r6, r5, lr) +	ALT_SMP(test_for_ipi r0, r2, r6, lr)  	ALT_UP_B(9997f)  	movne	r1, sp  	adrne	lr, BSYM(1b)  	bne	do_IPI  #ifdef CONFIG_LOCAL_TIMERS -	test_for_ltirq r0, r6, r5, lr +	test_for_ltirq r0, r2, r6, lr  	movne	r0, sp  	adrne	lr, BSYM(1b)  	bne	do_local_timer @@ -40,7 +40,7 @@  	.align	5  	.global \symbol_name  \symbol_name: -	mov	r4, lr +	mov	r8, lr  	arch_irq_handler_default -	mov     pc, r4 +	mov     pc, r8  	.endm diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index 7544ce6b481..67c70a31a1b 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h @@ -52,7 +52,7 @@ reserve_pmu(enum arm_pmu_type device);   * a cookie.   */  extern int -release_pmu(struct platform_device *pdev); +release_pmu(enum arm_pmu_type type);  /**   * init_pmu() - Initialise the PMU. diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h index 8ec535e11fd..633d1cb84d8 100644 --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h @@ -82,13 +82,13 @@ extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);  extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);  extern void cpu_reset(unsigned long addr) __attribute__((noreturn));  #else -#define cpu_proc_init()			processor._proc_init() -#define cpu_proc_fin()			processor._proc_fin() -#define cpu_reset(addr)			processor.reset(addr) -#define cpu_do_idle()			processor._do_idle() -#define cpu_dcache_clean_area(addr,sz)	processor.dcache_clean_area(addr,sz) -#define cpu_set_pte_ext(ptep,pte,ext)	processor.set_pte_ext(ptep,pte,ext) -#define cpu_do_switch_mm(pgd,mm)	processor.switch_mm(pgd,mm) +#define cpu_proc_init			processor._proc_init +#define cpu_proc_fin			processor._proc_fin +#define cpu_reset			processor.reset +#define cpu_do_idle			processor._do_idle +#define cpu_dcache_clean_area		processor.dcache_clean_area +#define cpu_set_pte_ext			processor.set_pte_ext +#define cpu_do_switch_mm		processor.switch_mm  #endif  extern void cpu_resume(void); diff --git a/arch/arm/include/asm/scatterlist.h b/arch/arm/include/asm/scatterlist.h index 2f87870d934..cefdb8f898a 100644 --- a/arch/arm/include/asm/scatterlist.h +++ b/arch/arm/include/asm/scatterlist.h @@ -1,6 +1,10 @@  #ifndef _ASMARM_SCATTERLIST_H  #define _ASMARM_SCATTERLIST_H +#ifdef CONFIG_ARM_HAS_SG_CHAIN +#define ARCH_HAS_SG_CHAIN +#endif +  #include <asm/memory.h>  #include <asm/types.h>  #include <asm-generic/scatterlist.h> diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h index ee2ad8ae07a..915696dd9c7 100644 --- a/arch/arm/include/asm/setup.h +++ b/arch/arm/include/asm/setup.h @@ -187,12 +187,16 @@ struct tagtable {  #define __tag __used __attribute__((__section__(".taglist.init")))  #define __tagtable(tag, fn) \ -static struct tagtable __tagtable_##fn __tag = { tag, fn } +static const struct tagtable __tagtable_##fn __tag = { tag, fn }  /*   * Memory map description   */ -#define NR_BANKS 8 +#ifdef CONFIG_ARCH_EP93XX +# define NR_BANKS 16 +#else +# define NR_BANKS 8 +#endif  struct membank {  	phys_addr_t start; diff --git a/arch/arm/include/asm/suspend.h b/arch/arm/include/asm/suspend.h new file mode 100644 index 00000000000..b0e4e1a0231 --- /dev/null +++ b/arch/arm/include/asm/suspend.h @@ -0,0 +1,22 @@ +#ifndef __ASM_ARM_SUSPEND_H +#define __ASM_ARM_SUSPEND_H + +#include <asm/memory.h> +#include <asm/tlbflush.h> + +extern void cpu_resume(void); + +/* + * Hide the first two arguments to __cpu_suspend - these are an implementation + * detail which platform code shouldn't have to know about. + */ +static inline int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) +{ +	extern int __cpu_suspend(int, long, unsigned long, +				 int (*)(unsigned long)); +	int ret = __cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn); +	flush_tlb_all(); +	return ret; +} + +#endif diff --git a/arch/arm/include/asm/tcm.h b/arch/arm/include/asm/tcm.h index 5929ef5d927..8578d726ad7 100644 --- a/arch/arm/include/asm/tcm.h +++ b/arch/arm/include/asm/tcm.h @@ -27,5 +27,7 @@  void *tcm_alloc(size_t len);  void tcm_free(void *addr, size_t len); +bool tcm_dtcm_present(void); +bool tcm_itcm_present(void);  #endif diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h index d2005de383b..8077145698f 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h @@ -34,16 +34,12 @@  #define TLB_V6_D_ASID	(1 << 17)  #define TLB_V6_I_ASID	(1 << 18) -#define TLB_BTB		(1 << 28) -  /* Unified Inner Shareable TLB operations (ARMv7 MP extensions) */  #define TLB_V7_UIS_PAGE	(1 << 19)  #define TLB_V7_UIS_FULL (1 << 20)  #define TLB_V7_UIS_ASID (1 << 21) -/* Inner Shareable BTB operation (ARMv7 MP extensions) */ -#define TLB_V7_IS_BTB	(1 << 22) - +#define TLB_BARRIER	(1 << 28)  #define TLB_L2CLEAN_FR	(1 << 29)		/* Feroceon */  #define TLB_DCLEAN	(1 << 30)  #define TLB_WB		(1 << 31) @@ -58,7 +54,7 @@   *	  v4wb  - ARMv4 with write buffer without I TLB flush entry instruction   *	  v4wbi - ARMv4 with write buffer with I TLB flush entry instruction   *	  fr    - Feroceon (v4wbi with non-outer-cacheable page table walks) - *	  fa    - Faraday (v4 with write buffer with UTLB and branch target buffer (BTB)) + *	  fa    - Faraday (v4 with write buffer with UTLB)   *	  v6wbi - ARMv6 with write buffer with I TLB flush entry instruction   *	  v7wbi - identical to v6wbi   */ @@ -99,7 +95,7 @@  # define v4_always_flags	(-1UL)  #endif -#define fa_tlb_flags	(TLB_WB | TLB_BTB | TLB_DCLEAN | \ +#define fa_tlb_flags	(TLB_WB | TLB_DCLEAN | TLB_BARRIER | \  			 TLB_V4_U_FULL | TLB_V4_U_PAGE)  #ifdef CONFIG_CPU_TLB_FA @@ -166,7 +162,7 @@  # define v4wb_always_flags	(-1UL)  #endif -#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \ +#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \  			 TLB_V6_I_FULL | TLB_V6_D_FULL | \  			 TLB_V6_I_PAGE | TLB_V6_D_PAGE | \  			 TLB_V6_I_ASID | TLB_V6_D_ASID) @@ -184,9 +180,9 @@  # define v6wbi_always_flags	(-1UL)  #endif -#define v7wbi_tlb_flags_smp	(TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \ +#define v7wbi_tlb_flags_smp	(TLB_WB | TLB_DCLEAN | TLB_BARRIER | \  			 TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID) -#define v7wbi_tlb_flags_up	(TLB_WB | TLB_DCLEAN | TLB_BTB | \ +#define v7wbi_tlb_flags_up	(TLB_WB | TLB_DCLEAN | TLB_BARRIER | \  			 TLB_V6_U_FULL | TLB_V6_U_PAGE | TLB_V6_U_ASID)  #ifdef CONFIG_CPU_TLB_V7 @@ -341,15 +337,7 @@ static inline void local_flush_tlb_all(void)  	if (tlb_flag(TLB_V7_UIS_FULL))  		asm("mcr p15, 0, %0, c8, c3, 0" : : "r" (zero) : "cc"); -	if (tlb_flag(TLB_BTB)) { -		/* flush the branch target cache */ -		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); -		dsb(); -		isb(); -	} -	if (tlb_flag(TLB_V7_IS_BTB)) { -		/* flush the branch target cache */ -		asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc"); +	if (tlb_flag(TLB_BARRIER)) {  		dsb();  		isb();  	} @@ -389,17 +377,8 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)  		asm("mcr p15, 0, %0, c8, c3, 2" : : "r" (asid) : "cc");  #endif -	if (tlb_flag(TLB_BTB)) { -		/* flush the branch target cache */ -		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); -		dsb(); -	} -	if (tlb_flag(TLB_V7_IS_BTB)) { -		/* flush the branch target cache */ -		asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc"); +	if (tlb_flag(TLB_BARRIER))  		dsb(); -		isb(); -	}  }  static inline void @@ -439,17 +418,8 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)  		asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (uaddr) : "cc");  #endif -	if (tlb_flag(TLB_BTB)) { -		/* flush the branch target cache */ -		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); -		dsb(); -	} -	if (tlb_flag(TLB_V7_IS_BTB)) { -		/* flush the branch target cache */ -		asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc"); +	if (tlb_flag(TLB_BARRIER))  		dsb(); -		isb(); -	}  }  static inline void local_flush_tlb_kernel_page(unsigned long kaddr) @@ -482,15 +452,7 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)  	if (tlb_flag(TLB_V7_UIS_PAGE))  		asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (kaddr) : "cc"); -	if (tlb_flag(TLB_BTB)) { -		/* flush the branch target cache */ -		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); -		dsb(); -		isb(); -	} -	if (tlb_flag(TLB_V7_IS_BTB)) { -		/* flush the branch target cache */ -		asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc"); +	if (tlb_flag(TLB_BARRIER)) {  		dsb();  		isb();  	} diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h index f90756dc16d..5b29a667362 100644 --- a/arch/arm/include/asm/traps.h +++ b/arch/arm/include/asm/traps.h @@ -3,6 +3,9 @@  #include <linux/list.h> +struct pt_regs; +struct task_struct; +  struct undef_hook {  	struct list_head node;  	u32 instr_mask; diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 927522cfc12..16baba2e436 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -59,6 +59,9 @@ int main(void)    DEFINE(TI_TP_VALUE,		offsetof(struct thread_info, tp_value));    DEFINE(TI_FPSTATE,		offsetof(struct thread_info, fpstate));    DEFINE(TI_VFPSTATE,		offsetof(struct thread_info, vfpstate)); +#ifdef CONFIG_SMP +  DEFINE(VFP_CPU,		offsetof(union vfp_state, hard.cpu)); +#endif  #ifdef CONFIG_ARM_THUMBEE    DEFINE(TI_THUMBEE_STATE,	offsetof(struct thread_info, thumbee_state));  #endif diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 8f9ab5c9015..a87cbf889ff 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -29,21 +29,53 @@  #include <asm/entry-macro-multi.S>  /* - * Interrupt handling.  Preserves r7, r8, r9 + * Interrupt handling.   */  	.macro	irq_handler  #ifdef CONFIG_MULTI_IRQ_HANDLER -	ldr	r5, =handle_arch_irq +	ldr	r1, =handle_arch_irq  	mov	r0, sp -	ldr	r5, [r5] +	ldr	r1, [r1]  	adr	lr, BSYM(9997f) -	teq	r5, #0 -	movne	pc, r5 +	teq	r1, #0 +	movne	pc, r1  #endif  	arch_irq_handler_default  9997:  	.endm +	.macro	pabt_helper +	@ PABORT handler takes pt_regs in r2, fault address in r4 and psr in r5 +#ifdef MULTI_PABORT +	ldr	ip, .LCprocfns +	mov	lr, pc +	ldr	pc, [ip, #PROCESSOR_PABT_FUNC] +#else +	bl	CPU_PABORT_HANDLER +#endif +	.endm + +	.macro	dabt_helper + +	@ +	@ Call the processor-specific abort handler: +	@ +	@  r2 - pt_regs +	@  r4 - aborted context pc +	@  r5 - aborted context psr +	@ +	@ The abort handler must return the aborted address in r0, and +	@ the fault status register in r1.  r9 must be preserved. +	@ +#ifdef MULTI_DABORT +	ldr	ip, .LCprocfns +	mov	lr, pc +	ldr	pc, [ip, #PROCESSOR_DABT_FUNC] +#else +	bl	CPU_DABORT_HANDLER +#endif +	.endm +  #ifdef CONFIG_KPROBES  	.section	.kprobes.text,"ax",%progbits  #else @@ -126,106 +158,74 @@ ENDPROC(__und_invalid)   SPFIX(	subeq	sp, sp, #4	)  	stmia	sp, {r1 - r12} -	ldmia	r0, {r1 - r3} -	add	r5, sp, #S_SP - 4	@ here for interlock avoidance -	mov	r4, #-1			@  ""  ""      ""       "" -	add	r0, sp, #(S_FRAME_SIZE + \stack_hole - 4) - SPFIX(	addeq	r0, r0, #4	) -	str	r1, [sp, #-4]!		@ save the "real" r0 copied +	ldmia	r0, {r3 - r5} +	add	r7, sp, #S_SP - 4	@ here for interlock avoidance +	mov	r6, #-1			@  ""  ""      ""       "" +	add	r2, sp, #(S_FRAME_SIZE + \stack_hole - 4) + SPFIX(	addeq	r2, r2, #4	) +	str	r3, [sp, #-4]!		@ save the "real" r0 copied  					@ from the exception stack -	mov	r1, lr +	mov	r3, lr  	@  	@ We are now ready to fill in the remaining blanks on the stack:  	@ -	@  r0 - sp_svc -	@  r1 - lr_svc -	@  r2 - lr_<exception>, already fixed up for correct return/restart -	@  r3 - spsr_<exception> -	@  r4 - orig_r0 (see pt_regs definition in ptrace.h) +	@  r2 - sp_svc +	@  r3 - lr_svc +	@  r4 - lr_<exception>, already fixed up for correct return/restart +	@  r5 - spsr_<exception> +	@  r6 - orig_r0 (see pt_regs definition in ptrace.h)  	@ -	stmia	r5, {r0 - r4} +	stmia	r7, {r2 - r6} + +#ifdef CONFIG_TRACE_IRQFLAGS +	bl	trace_hardirqs_off +#endif  	.endm  	.align	5  __dabt_svc:  	svc_entry - -	@ -	@ get ready to re-enable interrupts if appropriate -	@ -	mrs	r9, cpsr -	tst	r3, #PSR_I_BIT -	biceq	r9, r9, #PSR_I_BIT - -	@ -	@ Call the processor-specific abort handler: -	@ -	@  r2 - aborted context pc -	@  r3 - aborted context cpsr -	@ -	@ The abort handler must return the aborted address in r0, and -	@ the fault status register in r1.  r9 must be preserved. -	@ -#ifdef MULTI_DABORT -	ldr	r4, .LCprocfns -	mov	lr, pc -	ldr	pc, [r4, #PROCESSOR_DABT_FUNC] -#else -	bl	CPU_DABORT_HANDLER -#endif - -	@ -	@ set desired IRQ state, then call main handler -	@ -	debug_entry r1 -	msr	cpsr_c, r9  	mov	r2, sp -	bl	do_DataAbort +	dabt_helper  	@  	@ IRQs off again before pulling preserved data off the stack  	@  	disable_irq_notrace -	@ -	@ restore SPSR and restart the instruction -	@ -	ldr	r2, [sp, #S_PSR] -	svc_exit r2				@ return from exception +#ifdef CONFIG_TRACE_IRQFLAGS +	tst	r5, #PSR_I_BIT +	bleq	trace_hardirqs_on +	tst	r5, #PSR_I_BIT +	blne	trace_hardirqs_off +#endif +	svc_exit r5				@ return from exception   UNWIND(.fnend		)  ENDPROC(__dabt_svc)  	.align	5  __irq_svc:  	svc_entry +	irq_handler -#ifdef CONFIG_TRACE_IRQFLAGS -	bl	trace_hardirqs_off -#endif  #ifdef CONFIG_PREEMPT  	get_thread_info tsk  	ldr	r8, [tsk, #TI_PREEMPT]		@ get preempt count -	add	r7, r8, #1			@ increment it -	str	r7, [tsk, #TI_PREEMPT] -#endif - -	irq_handler -#ifdef CONFIG_PREEMPT -	str	r8, [tsk, #TI_PREEMPT]		@ restore preempt count  	ldr	r0, [tsk, #TI_FLAGS]		@ get flags  	teq	r8, #0				@ if preempt count != 0  	movne	r0, #0				@ force flags to 0  	tst	r0, #_TIF_NEED_RESCHED  	blne	svc_preempt  #endif -	ldr	r4, [sp, #S_PSR]		@ irqs are already disabled +  #ifdef CONFIG_TRACE_IRQFLAGS -	tst	r4, #PSR_I_BIT -	bleq	trace_hardirqs_on +	@ The parent context IRQs must have been enabled to get here in +	@ the first place, so there's no point checking the PSR I bit. +	bl	trace_hardirqs_on  #endif -	svc_exit r4				@ return from exception +	svc_exit r5				@ return from exception   UNWIND(.fnend		)  ENDPROC(__irq_svc) @@ -251,7 +251,6 @@ __und_svc:  #else  	svc_entry  #endif -  	@  	@ call emulation code, which returns using r9 if it has emulated  	@ the instruction, or the more conventional lr if we are to treat @@ -260,15 +259,16 @@ __und_svc:  	@  r0 - instruction  	@  #ifndef	CONFIG_THUMB2_KERNEL -	ldr	r0, [r2, #-4] +	ldr	r0, [r4, #-4]  #else -	ldrh	r0, [r2, #-2]			@ Thumb instruction at LR - 2 +	ldrh	r0, [r4, #-2]			@ Thumb instruction at LR - 2  	and	r9, r0, #0xf800  	cmp	r9, #0xe800			@ 32-bit instruction if xx >= 0 -	ldrhhs	r9, [r2]			@ bottom 16 bits +	ldrhhs	r9, [r4]			@ bottom 16 bits  	orrhs	r0, r9, r0, lsl #16  #endif  	adr	r9, BSYM(1f) +	mov	r2, r4  	bl	call_fpe  	mov	r0, sp				@ struct pt_regs *regs @@ -282,45 +282,35 @@ __und_svc:  	@  	@ restore SPSR and restart the instruction  	@ -	ldr	r2, [sp, #S_PSR]		@ Get SVC cpsr -	svc_exit r2				@ return from exception +	ldr	r5, [sp, #S_PSR]		@ Get SVC cpsr +#ifdef CONFIG_TRACE_IRQFLAGS +	tst	r5, #PSR_I_BIT +	bleq	trace_hardirqs_on +	tst	r5, #PSR_I_BIT +	blne	trace_hardirqs_off +#endif +	svc_exit r5				@ return from exception   UNWIND(.fnend		)  ENDPROC(__und_svc)  	.align	5  __pabt_svc:  	svc_entry - -	@ -	@ re-enable interrupts if appropriate -	@ -	mrs	r9, cpsr -	tst	r3, #PSR_I_BIT -	biceq	r9, r9, #PSR_I_BIT - -	mov	r0, r2			@ pass address of aborted instruction. -#ifdef MULTI_PABORT -	ldr	r4, .LCprocfns -	mov	lr, pc -	ldr	pc, [r4, #PROCESSOR_PABT_FUNC] -#else -	bl	CPU_PABORT_HANDLER -#endif -	debug_entry r1 -	msr	cpsr_c, r9			@ Maybe enable interrupts  	mov	r2, sp				@ regs -	bl	do_PrefetchAbort		@ call abort handler +	pabt_helper  	@  	@ IRQs off again before pulling preserved data off the stack  	@  	disable_irq_notrace -	@ -	@ restore SPSR and restart the instruction -	@ -	ldr	r2, [sp, #S_PSR] -	svc_exit r2				@ return from exception +#ifdef CONFIG_TRACE_IRQFLAGS +	tst	r5, #PSR_I_BIT +	bleq	trace_hardirqs_on +	tst	r5, #PSR_I_BIT +	blne	trace_hardirqs_off +#endif +	svc_exit r5				@ return from exception   UNWIND(.fnend		)  ENDPROC(__pabt_svc) @@ -351,23 +341,23 @@ ENDPROC(__pabt_svc)   ARM(	stmib	sp, {r1 - r12}	)   THUMB(	stmia	sp, {r0 - r12}	) -	ldmia	r0, {r1 - r3} +	ldmia	r0, {r3 - r5}  	add	r0, sp, #S_PC		@ here for interlock avoidance -	mov	r4, #-1			@  ""  ""     ""        "" +	mov	r6, #-1			@  ""  ""     ""        "" -	str	r1, [sp]		@ save the "real" r0 copied +	str	r3, [sp]		@ save the "real" r0 copied  					@ from the exception stack  	@  	@ We are now ready to fill in the remaining blanks on the stack:  	@ -	@  r2 - lr_<exception>, already fixed up for correct return/restart -	@  r3 - spsr_<exception> -	@  r4 - orig_r0 (see pt_regs definition in ptrace.h) +	@  r4 - lr_<exception>, already fixed up for correct return/restart +	@  r5 - spsr_<exception> +	@  r6 - orig_r0 (see pt_regs definition in ptrace.h)  	@  	@ Also, separately save sp_usr and lr_usr  	@ -	stmia	r0, {r2 - r4} +	stmia	r0, {r4 - r6}   ARM(	stmdb	r0, {sp, lr}^			)   THUMB(	store_user_sp_lr r0, r1, S_SP - S_PC	) @@ -380,6 +370,10 @@ ENDPROC(__pabt_svc)  	@ Clear FP to mark the first stack frame  	@  	zero_fp + +#ifdef CONFIG_IRQSOFF_TRACER +	bl	trace_hardirqs_off +#endif  	.endm  	.macro	kuser_cmpxchg_check @@ -391,7 +385,7 @@ ENDPROC(__pabt_svc)  	@ if it was interrupted in a critical region.  Here we  	@ perform a quick test inline since it should be false  	@ 99.9999% of the time.  The rest is done out of line. -	cmp	r2, #TASK_SIZE +	cmp	r4, #TASK_SIZE  	blhs	kuser_cmpxchg64_fixup  #endif  #endif @@ -401,32 +395,9 @@ ENDPROC(__pabt_svc)  __dabt_usr:  	usr_entry  	kuser_cmpxchg_check - -	@ -	@ Call the processor-specific abort handler: -	@ -	@  r2 - aborted context pc -	@  r3 - aborted context cpsr -	@ -	@ The abort handler must return the aborted address in r0, and -	@ the fault status register in r1. -	@ -#ifdef MULTI_DABORT -	ldr	r4, .LCprocfns -	mov	lr, pc -	ldr	pc, [r4, #PROCESSOR_DABT_FUNC] -#else -	bl	CPU_DABORT_HANDLER -#endif - -	@ -	@ IRQs on, then call the main handler -	@ -	debug_entry r1 -	enable_irq  	mov	r2, sp -	adr	lr, BSYM(ret_from_exception) -	b	do_DataAbort +	dabt_helper +	b	ret_from_exception   UNWIND(.fnend		)  ENDPROC(__dabt_usr) @@ -434,28 +405,8 @@ ENDPROC(__dabt_usr)  __irq_usr:  	usr_entry  	kuser_cmpxchg_check - -#ifdef CONFIG_IRQSOFF_TRACER -	bl	trace_hardirqs_off -#endif - -	get_thread_info tsk -#ifdef CONFIG_PREEMPT -	ldr	r8, [tsk, #TI_PREEMPT]		@ get preempt count -	add	r7, r8, #1			@ increment it -	str	r7, [tsk, #TI_PREEMPT] -#endif -  	irq_handler -#ifdef CONFIG_PREEMPT -	ldr	r0, [tsk, #TI_PREEMPT] -	str	r8, [tsk, #TI_PREEMPT] -	teq	r0, r7 - ARM(	strne	r0, [r0, -r0]	) - THUMB(	movne	r0, #0		) - THUMB(	strne	r0, [r0]	) -#endif - +	get_thread_info tsk  	mov	why, #0  	b	ret_to_user_from_irq   UNWIND(.fnend		) @@ -467,6 +418,9 @@ ENDPROC(__irq_usr)  __und_usr:  	usr_entry +	mov	r2, r4 +	mov	r3, r5 +  	@  	@ fall through to the emulation code, which returns using r9 if  	@ it has emulated the instruction, or the more conventional lr @@ -682,19 +636,8 @@ ENDPROC(__und_usr_unknown)  	.align	5  __pabt_usr:  	usr_entry - -	mov	r0, r2			@ pass address of aborted instruction. -#ifdef MULTI_PABORT -	ldr	r4, .LCprocfns -	mov	lr, pc -	ldr	pc, [r4, #PROCESSOR_PABT_FUNC] -#else -	bl	CPU_PABORT_HANDLER -#endif -	debug_entry r1 -	enable_irq				@ Enable interrupts  	mov	r2, sp				@ regs -	bl	do_PrefetchAbort		@ call abort handler +	pabt_helper   UNWIND(.fnend		)  	/* fall through */  /* @@ -839,13 +782,13 @@ __kuser_cmpxchg64:				@ 0xffff0f60  	.text  kuser_cmpxchg64_fixup:  	@ Called from kuser_cmpxchg_fixup. -	@ r2 = address of interrupted insn (must be preserved). +	@ r4 = address of interrupted insn (must be preserved).  	@ sp = saved regs. r7 and r8 are clobbered.  	@ 1b = first critical insn, 2b = last critical insn. -	@ If r2 >= 1b and r2 <= 2b then saved pc_usr is set to 1b. +	@ If r4 >= 1b and r4 <= 2b then saved pc_usr is set to 1b.  	mov	r7, #0xffff0fff  	sub	r7, r7, #(0xffff0fff - (0xffff0f60 + (1b - __kuser_cmpxchg64))) -	subs	r8, r2, r7 +	subs	r8, r4, r7  	rsbcss	r8, r8, #(2b - 1b)  	strcs	r7, [sp, #S_PC]  #if __LINUX_ARM_ARCH__ < 6 @@ -915,13 +858,13 @@ __kuser_cmpxchg:				@ 0xffff0fc0  	.text  kuser_cmpxchg32_fixup:  	@ Called from kuser_cmpxchg_check macro. -	@ r2 = address of interrupted insn (must be preserved). +	@ r4 = address of interrupted insn (must be preserved).  	@ sp = saved regs. r7 and r8 are clobbered.  	@ 1b = first critical insn, 2b = last critical insn. -	@ If r2 >= 1b and r2 <= 2b then saved pc_usr is set to 1b. +	@ If r4 >= 1b and r4 <= 2b then saved pc_usr is set to 1b.  	mov	r7, #0xffff0fff  	sub	r7, r7, #(0xffff0fff - (0xffff0fc0 + (1b - __kuser_cmpxchg))) -	subs	r8, r2, r7 +	subs	r8, r4, r7  	rsbcss	r8, r8, #(2b - 1b)  	strcs	r7, [sp, #S_PC]  	mov	pc, lr diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 83e29adced6..9a8531eadd3 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -163,25 +163,6 @@  	.endm  #endif	/* !CONFIG_THUMB2_KERNEL */ -	@ -	@ Debug exceptions are taken as prefetch or data aborts. -	@ We must disable preemption during the handler so that -	@ we can access the debug registers safely. -	@ -	.macro	debug_entry, fsr -#if defined(CONFIG_HAVE_HW_BREAKPOINT) && defined(CONFIG_PREEMPT) -	ldr	r4, =0x40f		@ mask out fsr.fs -	and	r5, r4, \fsr -	cmp	r5, #2			@ debug exception -	bne	1f -	get_thread_info r10 -	ldr	r6, [r10, #TI_PREEMPT]	@ get preempt count -	add	r11, r6, #1		@ increment it -	str	r11, [r10, #TI_PREEMPT] -1: -#endif -	.endm -  /*   * These are the registers used in the syscall handler, and allow us to   * have in theory up to 7 arguments to a function - r0 to r6. diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S index 6b1e0ad9ec3..d46f25968be 100644 --- a/arch/arm/kernel/head-nommu.S +++ b/arch/arm/kernel/head-nommu.S @@ -32,8 +32,16 @@   * numbers for r1.   *   */ +	.arm +  	__HEAD  ENTRY(stext) + + THUMB(	adr	r9, BSYM(1f)	)	@ Kernel is always entered in ARM. + THUMB(	bx	r9		)	@ If this is a Thumb-2 kernel, + THUMB(	.thumb			)	@ switch to Thumb now. + THUMB(1:			) +  	setmode	PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode  						@ and irqs disabled  #ifndef CONFIG_CPU_CP15 diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 278c1b0ebb2..742b6108a00 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -71,8 +71,16 @@   * crap here - that's what the boot loader (or in extreme, well justified   * circumstances, zImage) is for.   */ +	.arm +  	__HEAD  ENTRY(stext) + + THUMB(	adr	r9, BSYM(1f)	)	@ Kernel is always entered in ARM. + THUMB(	bx	r9		)	@ If this is a Thumb-2 kernel, + THUMB(	.thumb			)	@ switch to Thumb now. + THUMB(1:			) +  	setmode	PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode  						@ and irqs disabled  	mrc	p15, 0, r9, c0, c0		@ get processor id diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 87acc25d7a3..a927ca1f556 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -796,7 +796,7 @@ unlock:  /*   * Called from either the Data Abort Handler [watchpoint] or the - * Prefetch Abort Handler [breakpoint] with preemption disabled. + * Prefetch Abort Handler [breakpoint] with interrupts disabled.   */  static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,  				 struct pt_regs *regs) @@ -804,8 +804,10 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,  	int ret = 0;  	u32 dscr; -	/* We must be called with preemption disabled. */ -	WARN_ON(preemptible()); +	preempt_disable(); + +	if (interrupts_enabled(regs)) +		local_irq_enable();  	/* We only handle watchpoints and hardware breakpoints. */  	ARM_DBG_READ(c1, 0, dscr); @@ -824,10 +826,6 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,  		ret = 1; /* Unhandled fault. */  	} -	/* -	 * Re-enable preemption after it was disabled in the -	 * low-level exception handling code. -	 */  	preempt_enable();  	return ret; diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 83bbad03fcc..0f928a131af 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -131,54 +131,63 @@ int __init arch_probe_nr_irqs(void)  #ifdef CONFIG_HOTPLUG_CPU -static bool migrate_one_irq(struct irq_data *d) +static bool migrate_one_irq(struct irq_desc *desc)  { -	unsigned int cpu = cpumask_any_and(d->affinity, cpu_online_mask); +	struct irq_data *d = irq_desc_get_irq_data(desc); +	const struct cpumask *affinity = d->affinity; +	struct irq_chip *c;  	bool ret = false; -	if (cpu >= nr_cpu_ids) { -		cpu = cpumask_any(cpu_online_mask); +	/* +	 * If this is a per-CPU interrupt, or the affinity does not +	 * include this CPU, then we have nothing to do. +	 */ +	if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity)) +		return false; + +	if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { +		affinity = cpu_online_mask;  		ret = true;  	} -	pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", d->irq, d->node, cpu); - -	d->chip->irq_set_affinity(d, cpumask_of(cpu), true); +	c = irq_data_get_irq_chip(d); +	if (c->irq_set_affinity) +		c->irq_set_affinity(d, affinity, true); +	else +		pr_debug("IRQ%u: unable to set affinity\n", d->irq);  	return ret;  }  /* - * The CPU has been marked offline.  Migrate IRQs off this CPU.  If - * the affinity settings do not allow other CPUs, force them onto any + * The current CPU has been marked offline.  Migrate IRQs off this CPU. + * If the affinity settings do not allow other CPUs, force them onto any   * available CPU. + * + * Note: we must iterate over all IRQs, whether they have an attached + * action structure or not, as we need to get chained interrupts too.   */  void migrate_irqs(void)  { -	unsigned int i, cpu = smp_processor_id(); +	unsigned int i;  	struct irq_desc *desc;  	unsigned long flags;  	local_irq_save(flags);  	for_each_irq_desc(i, desc) { -		struct irq_data *d = &desc->irq_data;  		bool affinity_broken = false; -		raw_spin_lock(&desc->lock); -		do { -			if (desc->action == NULL) -				break; - -			if (d->node != cpu) -				break; +		if (!desc) +			continue; -			affinity_broken = migrate_one_irq(d); -		} while (0); +		raw_spin_lock(&desc->lock); +		affinity_broken = migrate_one_irq(desc);  		raw_spin_unlock(&desc->lock);  		if (affinity_broken && printk_ratelimit()) -			pr_warning("IRQ%u no longer affine to CPU%u\n", i, cpu); +			pr_warning("IRQ%u no longer affine to CPU%u\n", i, +				smp_processor_id());  	}  	local_irq_restore(flags); diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 31326996dfe..53c9c2610cb 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -435,7 +435,7 @@ armpmu_reserve_hardware(void)  			if (irq >= 0)  				free_irq(irq, NULL);  		} -		release_pmu(pmu_device); +		release_pmu(ARM_PMU_DEVICE_CPU);  		pmu_device = NULL;  	} @@ -454,7 +454,7 @@ armpmu_release_hardware(void)  	}  	armpmu->stop(); -	release_pmu(pmu_device); +	release_pmu(ARM_PMU_DEVICE_CPU);  	pmu_device = NULL;  } diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c index 2c79eec1926..2b70709376c 100644 --- a/arch/arm/kernel/pmu.c +++ b/arch/arm/kernel/pmu.c @@ -17,6 +17,7 @@  #include <linux/interrupt.h>  #include <linux/kernel.h>  #include <linux/module.h> +#include <linux/of_device.h>  #include <linux/platform_device.h>  #include <asm/pmu.h> @@ -25,36 +26,88 @@ static volatile long pmu_lock;  static struct platform_device *pmu_devices[ARM_NUM_PMU_DEVICES]; -static int __devinit pmu_device_probe(struct platform_device *pdev) +static int __devinit pmu_register(struct platform_device *pdev, +					enum arm_pmu_type type)  { - -	if (pdev->id < 0 || pdev->id >= ARM_NUM_PMU_DEVICES) { +	if (type < 0 || type >= ARM_NUM_PMU_DEVICES) {  		pr_warning("received registration request for unknown " -				"device %d\n", pdev->id); +				"device %d\n", type);  		return -EINVAL;  	} -	if (pmu_devices[pdev->id]) -		pr_warning("registering new PMU device type %d overwrites " -				"previous registration!\n", pdev->id); -	else -		pr_info("registered new PMU device of type %d\n", -				pdev->id); +	if (pmu_devices[type]) { +		pr_warning("rejecting duplicate registration of PMU device " +			"type %d.", type); +		return -ENOSPC; +	} -	pmu_devices[pdev->id] = pdev; +	pr_info("registered new PMU device of type %d\n", type); +	pmu_devices[type] = pdev;  	return 0;  } -static struct platform_driver pmu_driver = { +#define OF_MATCH_PMU(_name, _type) {	\ +	.compatible = _name,		\ +	.data = (void *)_type,		\ +} + +#define OF_MATCH_CPU(name)	OF_MATCH_PMU(name, ARM_PMU_DEVICE_CPU) + +static struct of_device_id armpmu_of_device_ids[] = { +	OF_MATCH_CPU("arm,cortex-a9-pmu"), +	OF_MATCH_CPU("arm,cortex-a8-pmu"), +	OF_MATCH_CPU("arm,arm1136-pmu"), +	OF_MATCH_CPU("arm,arm1176-pmu"), +	{}, +}; + +#define PLAT_MATCH_PMU(_name, _type) {	\ +	.name		= _name,	\ +	.driver_data	= _type,	\ +} + +#define PLAT_MATCH_CPU(_name)	PLAT_MATCH_PMU(_name, ARM_PMU_DEVICE_CPU) + +static struct platform_device_id armpmu_plat_device_ids[] = { +	PLAT_MATCH_CPU("arm-pmu"), +	{}, +}; + +enum arm_pmu_type armpmu_device_type(struct platform_device *pdev) +{ +	const struct of_device_id	*of_id; +	const struct platform_device_id *pdev_id; + +	/* provided by of_device_id table */ +	if (pdev->dev.of_node) { +		of_id = of_match_device(armpmu_of_device_ids, &pdev->dev); +		BUG_ON(!of_id); +		return (enum arm_pmu_type)of_id->data; +	} + +	/* Provided by platform_device_id table */ +	pdev_id = platform_get_device_id(pdev); +	BUG_ON(!pdev_id); +	return pdev_id->driver_data; +} + +static int __devinit armpmu_device_probe(struct platform_device *pdev) +{ +	return pmu_register(pdev, armpmu_device_type(pdev)); +} + +static struct platform_driver armpmu_driver = {  	.driver		= {  		.name	= "arm-pmu", +		.of_match_table = armpmu_of_device_ids,  	}, -	.probe		= pmu_device_probe, +	.probe		= armpmu_device_probe, +	.id_table	= armpmu_plat_device_ids,  };  static int __init register_pmu_driver(void)  { -	return platform_driver_register(&pmu_driver); +	return platform_driver_register(&armpmu_driver);  }  device_initcall(register_pmu_driver); @@ -77,11 +130,11 @@ reserve_pmu(enum arm_pmu_type device)  EXPORT_SYMBOL_GPL(reserve_pmu);  int -release_pmu(struct platform_device *pdev) +release_pmu(enum arm_pmu_type device)  { -	if (WARN_ON(pdev != pmu_devices[pdev->id])) +	if (WARN_ON(!pmu_devices[device]))  		return -EINVAL; -	clear_bit_unlock(pdev->id, &pmu_lock); +	clear_bit_unlock(device, &pmu_lock);  	return 0;  }  EXPORT_SYMBOL_GPL(release_pmu); diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index f59653d6765..70bca649e92 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -343,54 +343,6 @@ static void __init feat_v6_fixup(void)  		elf_hwcap &= ~HWCAP_TLS;  } -static void __init setup_processor(void) -{ -	struct proc_info_list *list; - -	/* -	 * locate processor in the list of supported processor -	 * types.  The linker builds this table for us from the -	 * entries in arch/arm/mm/proc-*.S -	 */ -	list = lookup_processor_type(read_cpuid_id()); -	if (!list) { -		printk("CPU configuration botched (ID %08x), unable " -		       "to continue.\n", read_cpuid_id()); -		while (1); -	} - -	cpu_name = list->cpu_name; - -#ifdef MULTI_CPU -	processor = *list->proc; -#endif -#ifdef MULTI_TLB -	cpu_tlb = *list->tlb; -#endif -#ifdef MULTI_USER -	cpu_user = *list->user; -#endif -#ifdef MULTI_CACHE -	cpu_cache = *list->cache; -#endif - -	printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n", -	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15, -	       proc_arch[cpu_architecture()], cr_alignment); - -	sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS); -	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS); -	elf_hwcap = list->elf_hwcap; -#ifndef CONFIG_ARM_THUMB -	elf_hwcap &= ~HWCAP_THUMB; -#endif - -	feat_v6_fixup(); - -	cacheid_init(); -	cpu_proc_init(); -} -  /*   * cpu_init - initialise one CPU.   * @@ -406,6 +358,8 @@ void cpu_init(void)  		BUG();  	} +	cpu_proc_init(); +  	/*  	 * Define the placement constraint for the inline asm directive below.  	 * In Thumb-2, msr with an immediate value is not allowed. @@ -442,6 +396,54 @@ void cpu_init(void)  	    : "r14");  } +static void __init setup_processor(void) +{ +	struct proc_info_list *list; + +	/* +	 * locate processor in the list of supported processor +	 * types.  The linker builds this table for us from the +	 * entries in arch/arm/mm/proc-*.S +	 */ +	list = lookup_processor_type(read_cpuid_id()); +	if (!list) { +		printk("CPU configuration botched (ID %08x), unable " +		       "to continue.\n", read_cpuid_id()); +		while (1); +	} + +	cpu_name = list->cpu_name; + +#ifdef MULTI_CPU +	processor = *list->proc; +#endif +#ifdef MULTI_TLB +	cpu_tlb = *list->tlb; +#endif +#ifdef MULTI_USER +	cpu_user = *list->user; +#endif +#ifdef MULTI_CACHE +	cpu_cache = *list->cache; +#endif + +	printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n", +	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15, +	       proc_arch[cpu_architecture()], cr_alignment); + +	sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS); +	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS); +	elf_hwcap = list->elf_hwcap; +#ifndef CONFIG_ARM_THUMB +	elf_hwcap &= ~HWCAP_THUMB; +#endif + +	feat_v6_fixup(); + +	cacheid_init(); +	cpu_init(); +} +  void __init dump_machine_table(void)  {  	struct machine_desc *p; @@ -915,7 +917,6 @@ void __init setup_arch(char **cmdline_p)  #endif  	reserve_crashkernel(); -	cpu_init();  	tcm_init();  #ifdef CONFIG_ZONE_DMA diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S index 6398ead9d1c..dc902f2c684 100644 --- a/arch/arm/kernel/sleep.S +++ b/arch/arm/kernel/sleep.S @@ -10,64 +10,61 @@  /*   * Save CPU state for a suspend   *  r1 = v:p offset - *  r3 = virtual return function - * Note: sp is decremented to allocate space for CPU state on stack - * r0-r3,r9,r10,lr corrupted + *  r2 = suspend function arg0 + *  r3 = suspend function   */ -ENTRY(cpu_suspend) -	mov	r9, lr +ENTRY(__cpu_suspend) +	stmfd	sp!, {r4 - r11, lr}  #ifdef MULTI_CPU  	ldr	r10, =processor -	mov	r2, sp			@ current virtual SP -	ldr	r0, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state +	ldr	r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state  	ldr	ip, [r10, #CPU_DO_RESUME] @ virtual resume function -	sub	sp, sp, r0		@ allocate CPU state on stack -	mov	r0, sp			@ save pointer +#else +	ldr	r5, =cpu_suspend_size +	ldr	ip, =cpu_do_resume +#endif +	mov	r6, sp			@ current virtual SP +	sub	sp, sp, r5		@ allocate CPU state on stack +	mov	r0, sp			@ save pointer to CPU save block  	add	ip, ip, r1		@ convert resume fn to phys -	stmfd	sp!, {r1, r2, r3, ip}	@ save v:p, virt SP, retfn, phys resume fn -	ldr	r3, =sleep_save_sp -	add	r2, sp, r1		@ convert SP to phys +	stmfd	sp!, {r1, r6, ip}	@ save v:p, virt SP, phys resume fn +	ldr	r5, =sleep_save_sp +	add	r6, sp, r1		@ convert SP to phys +	stmfd	sp!, {r2, r3}		@ save suspend func arg and pointer  #ifdef CONFIG_SMP  	ALT_SMP(mrc p15, 0, lr, c0, c0, 5)  	ALT_UP(mov lr, #0)  	and	lr, lr, #15 -	str	r2, [r3, lr, lsl #2]	@ save phys SP +	str	r6, [r5, lr, lsl #2]	@ save phys SP  #else -	str	r2, [r3]		@ save phys SP +	str	r6, [r5]		@ save phys SP  #endif +#ifdef MULTI_CPU  	mov	lr, pc  	ldr	pc, [r10, #CPU_DO_SUSPEND] @ save CPU state  #else -	mov	r2, sp			@ current virtual SP -	ldr	r0, =cpu_suspend_size -	sub	sp, sp, r0		@ allocate CPU state on stack -	mov	r0, sp			@ save pointer -	stmfd	sp!, {r1, r2, r3}	@ save v:p, virt SP, return fn -	ldr	r3, =sleep_save_sp -	add	r2, sp, r1		@ convert SP to phys -#ifdef CONFIG_SMP -	ALT_SMP(mrc p15, 0, lr, c0, c0, 5) -	ALT_UP(mov lr, #0) -	and	lr, lr, #15 -	str	r2, [r3, lr, lsl #2]	@ save phys SP -#else -	str	r2, [r3]		@ save phys SP -#endif  	bl	cpu_do_suspend  #endif  	@ flush data cache  #ifdef MULTI_CACHE  	ldr	r10, =cpu_cache -	mov	lr, r9 +	mov	lr, pc  	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]  #else -	mov	lr, r9 -	b	__cpuc_flush_kern_all +	bl	__cpuc_flush_kern_all  #endif -ENDPROC(cpu_suspend) +	adr	lr, BSYM(cpu_suspend_abort) +	ldmfd	sp!, {r0, pc}		@ call suspend fn +ENDPROC(__cpu_suspend)  	.ltorg +cpu_suspend_abort: +	ldmia	sp!, {r1 - r3}		@ pop v:p, virt SP, phys resume fn +	mov	sp, r2 +	ldmfd	sp!, {r4 - r11, pc} +ENDPROC(cpu_suspend_abort) +  /*   * r0 = control register value   * r1 = v:p offset (preserved by cpu_do_resume) @@ -97,7 +94,9 @@ ENDPROC(cpu_resume_turn_mmu_on)  cpu_resume_after_mmu:  	str	r5, [r2, r4, lsl #2]	@ restore old mapping  	mcr	p15, 0, r0, c1, c0, 0	@ turn on D-cache -	mov	pc, lr +	bl	cpu_init		@ restore the und/abt/irq banked regs +	mov	r0, #0			@ return zero on success +	ldmfd	sp!, {r4 - r11, pc}  ENDPROC(cpu_resume_after_mmu)  /* @@ -120,20 +119,11 @@ ENTRY(cpu_resume)  	ldr	r0, sleep_save_sp	@ stack phys addr  #endif  	setmode	PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1  @ set SVC, irqs off -#ifdef MULTI_CPU -	@ load v:p, stack, return fn, resume fn -  ARM(	ldmia	r0!, {r1, sp, lr, pc}	) -THUMB(	ldmia	r0!, {r1, r2, r3, r4}	) +	@ load v:p, stack, resume fn +  ARM(	ldmia	r0!, {r1, sp, pc}	) +THUMB(	ldmia	r0!, {r1, r2, r3}	)  THUMB(	mov	sp, r2			) -THUMB(	mov	lr, r3			) -THUMB(	bx	r4			) -#else -	@ load v:p, stack, return fn -  ARM(	ldmia	r0!, {r1, sp, lr}	) -THUMB(	ldmia	r0!, {r1, r2, lr}	) -THUMB(	mov	sp, r2			) -	b	cpu_do_resume -#endif +THUMB(	bx	r3			)  ENDPROC(cpu_resume)  sleep_save_sp: diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index e7f92a4321f..167e3cbe1f2 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -365,8 +365,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)  	 */  	if (max_cpus > ncores)  		max_cpus = ncores; - -	if (max_cpus > 1) { +	if (ncores > 1 && max_cpus) {  		/*  		 * Enable the local timer or broadcast device for the  		 * boot CPU, but only if we have more than one CPU. @@ -374,6 +373,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)  		percpu_timer_setup();  		/* +		 * Initialise the present map, which describes the set of CPUs +		 * actually populated at the present time. A platform should +		 * re-initialize the map in platform_smp_prepare_cpus() if +		 * present != possible (e.g. physical hotplug). +		 */ +		init_cpu_present(&cpu_possible_map); + +		/*  		 * Initialise the SCU if there are more than one CPU  		 * and let them know where to start.  		 */ diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c index a1e757c3439..79ed5e7f204 100644 --- a/arch/arm/kernel/smp_scu.c +++ b/arch/arm/kernel/smp_scu.c @@ -20,6 +20,7 @@  #define SCU_INVALIDATE		0x0c  #define SCU_FPGA_REVISION	0x10 +#ifdef CONFIG_SMP  /*   * Get the number of CPU cores from the SCU configuration   */ @@ -50,6 +51,7 @@ void __init scu_enable(void __iomem *scu_base)  	 */  	flush_cache_all();  } +#endif  /*   * Set the executing CPUs power mode as defined.  This will be in diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c index f5cf660eefc..30e302d33e0 100644 --- a/arch/arm/kernel/tcm.c +++ b/arch/arm/kernel/tcm.c @@ -19,6 +19,8 @@  #include "tcm.h"  static struct gen_pool *tcm_pool; +static bool dtcm_present; +static bool itcm_present;  /* TCM section definitions from the linker */  extern char __itcm_start, __sitcm_text, __eitcm_text; @@ -90,6 +92,18 @@ void tcm_free(void *addr, size_t len)  }  EXPORT_SYMBOL(tcm_free); +bool tcm_dtcm_present(void) +{ +	return dtcm_present; +} +EXPORT_SYMBOL(tcm_dtcm_present); + +bool tcm_itcm_present(void) +{ +	return itcm_present; +} +EXPORT_SYMBOL(tcm_itcm_present); +  static int __init setup_tcm_bank(u8 type, u8 bank, u8 banks,  				  u32 *offset)  { @@ -134,6 +148,10 @@ static int __init setup_tcm_bank(u8 type, u8 bank, u8 banks,  			(tcm_region & 1) ? "" : "not ");  	} +	/* Not much fun you can do with a size 0 bank */ +	if (tcm_size == 0) +		return 0; +  	/* Force move the TCM bank to where we want it, enable */  	tcm_region = *offset | (tcm_region & 0x00000ffeU) | 1; @@ -165,12 +183,20 @@ void __init tcm_init(void)  	u32 tcm_status = read_cpuid_tcmstatus();  	u8 dtcm_banks = (tcm_status >> 16) & 0x03;  	u8 itcm_banks = (tcm_status & 0x03); +	size_t dtcm_code_sz = &__edtcm_data - &__sdtcm_data; +	size_t itcm_code_sz = &__eitcm_text - &__sitcm_text;  	char *start;  	char *end;  	char *ram;  	int ret;  	int i; +	/* Values greater than 2 for D/ITCM banks are "reserved" */ +	if (dtcm_banks > 2) +		dtcm_banks = 0; +	if (itcm_banks > 2) +		itcm_banks = 0; +  	/* Setup DTCM if present */  	if (dtcm_banks > 0) {  		for (i = 0; i < dtcm_banks; i++) { @@ -178,6 +204,13 @@ void __init tcm_init(void)  			if (ret)  				return;  		} +		/* This means you compiled more code than fits into DTCM */ +		if (dtcm_code_sz > (dtcm_end - DTCM_OFFSET)) { +			pr_info("CPU DTCM: %u bytes of code compiled to " +				"DTCM but only %lu bytes of DTCM present\n", +				dtcm_code_sz, (dtcm_end - DTCM_OFFSET)); +			goto no_dtcm; +		}  		dtcm_res.end = dtcm_end - 1;  		request_resource(&iomem_resource, &dtcm_res);  		dtcm_iomap[0].length = dtcm_end - DTCM_OFFSET; @@ -186,12 +219,16 @@ void __init tcm_init(void)  		start = &__sdtcm_data;  		end   = &__edtcm_data;  		ram   = &__dtcm_start; -		/* This means you compiled more code than fits into DTCM */ -		BUG_ON((end - start) > (dtcm_end - DTCM_OFFSET)); -		memcpy(start, ram, (end-start)); -		pr_debug("CPU DTCM: copied data from %p - %p\n", start, end); +		memcpy(start, ram, dtcm_code_sz); +		pr_debug("CPU DTCM: copied data from %p - %p\n", +			 start, end); +		dtcm_present = true; +	} else if (dtcm_code_sz) { +		pr_info("CPU DTCM: %u bytes of code compiled to DTCM but no " +			"DTCM banks present in CPU\n", dtcm_code_sz);  	} +no_dtcm:  	/* Setup ITCM if present */  	if (itcm_banks > 0) {  		for (i = 0; i < itcm_banks; i++) { @@ -199,6 +236,13 @@ void __init tcm_init(void)  			if (ret)  				return;  		} +		/* This means you compiled more code than fits into ITCM */ +		if (itcm_code_sz > (itcm_end - ITCM_OFFSET)) { +			pr_info("CPU ITCM: %u bytes of code compiled to " +				"ITCM but only %lu bytes of ITCM present\n", +				itcm_code_sz, (itcm_end - ITCM_OFFSET)); +			return; +		}  		itcm_res.end = itcm_end - 1;  		request_resource(&iomem_resource, &itcm_res);  		itcm_iomap[0].length = itcm_end - ITCM_OFFSET; @@ -207,10 +251,13 @@ void __init tcm_init(void)  		start = &__sitcm_text;  		end   = &__eitcm_text;  		ram   = &__itcm_start; -		/* This means you compiled more code than fits into ITCM */ -		BUG_ON((end - start) > (itcm_end - ITCM_OFFSET)); -		memcpy(start, ram, (end-start)); -		pr_debug("CPU ITCM: copied code from %p - %p\n", start, end); +		memcpy(start, ram, itcm_code_sz); +		pr_debug("CPU ITCM: copied code from %p - %p\n", +			 start, end); +		itcm_present = true; +	} else if (itcm_code_sz) { +		pr_info("CPU ITCM: %u bytes of code compiled to ITCM but no " +			"ITCM banks present in CPU\n", itcm_code_sz);  	}  } @@ -221,7 +268,6 @@ void __init tcm_init(void)   */  static int __init setup_tcm_pool(void)  { -	u32 tcm_status = read_cpuid_tcmstatus();  	u32 dtcm_pool_start = (u32) &__edtcm_data;  	u32 itcm_pool_start = (u32) &__eitcm_text;  	int ret; @@ -236,7 +282,7 @@ static int __init setup_tcm_pool(void)  	pr_debug("Setting up TCM memory pool\n");  	/* Add the rest of DTCM to the TCM pool */ -	if (tcm_status & (0x03 << 16)) { +	if (dtcm_present) {  		if (dtcm_pool_start < dtcm_end) {  			ret = gen_pool_add(tcm_pool, dtcm_pool_start,  					   dtcm_end - dtcm_pool_start, -1); @@ -253,7 +299,7 @@ static int __init setup_tcm_pool(void)  	}  	/* Add the rest of ITCM to the TCM pool */ -	if (tcm_status & 0x03) { +	if (itcm_present) {  		if (itcm_pool_start < itcm_end) {  			ret = gen_pool_add(tcm_pool, itcm_pool_start,  					   itcm_end - itcm_pool_start, -1); diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index e5287f21bad..bf977f8514f 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -38,57 +38,6 @@ jiffies = jiffies_64 + 4;  SECTIONS  { -#ifdef CONFIG_XIP_KERNEL -	. = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR); -#else -	. = PAGE_OFFSET + TEXT_OFFSET; -#endif - -	.init : {			/* Init code and data		*/ -		_stext = .; -		_sinittext = .; -			HEAD_TEXT -			INIT_TEXT -			ARM_EXIT_KEEP(EXIT_TEXT) -		_einittext = .; -		ARM_CPU_DISCARD(PROC_INFO) -		__arch_info_begin = .; -			*(.arch.info.init) -		__arch_info_end = .; -		__tagtable_begin = .; -			*(.taglist.init) -		__tagtable_end = .; -#ifdef CONFIG_SMP_ON_UP -		__smpalt_begin = .; -			*(.alt.smp.init) -		__smpalt_end = .; -#endif - -		__pv_table_begin = .; -			*(.pv_table) -		__pv_table_end = .; - -		INIT_SETUP(16) - -		INIT_CALLS -		CON_INITCALL -		SECURITY_INITCALL -		INIT_RAM_FS - -#ifndef CONFIG_XIP_KERNEL -		__init_begin = _stext; -		INIT_DATA -		ARM_EXIT_KEEP(EXIT_DATA) -#endif -	} - -	PERCPU_SECTION(32) - -#ifndef CONFIG_XIP_KERNEL -	. = ALIGN(PAGE_SIZE); -	__init_end = .; -#endif -  	/*  	 * unwind exit sections must be discarded before the rest of the  	 * unwind sections get included. @@ -106,10 +55,22 @@ SECTIONS  		*(.fixup)  		*(__ex_table)  #endif +#ifndef CONFIG_SMP_ON_UP +		*(.alt.smp.init) +#endif  	} +#ifdef CONFIG_XIP_KERNEL +	. = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR); +#else +	. = PAGE_OFFSET + TEXT_OFFSET; +#endif +	.head.text : { +		_text = .; +		HEAD_TEXT +	}  	.text : {			/* Real text segment		*/ -		_text = .;		/* Text and read-only data	*/ +		_stext = .;		/* Text and read-only data	*/  			__exception_text_start = .;  			*(.exception.text)  			__exception_text_end = .; @@ -122,8 +83,6 @@ SECTIONS  			*(.fixup)  #endif  			*(.gnu.warning) -			*(.rodata) -			*(.rodata.*)  			*(.glue_7)  			*(.glue_7t)  		. = ALIGN(4); @@ -152,10 +111,63 @@ SECTIONS  	_etext = .;			/* End of text and rodata section */ +#ifndef CONFIG_XIP_KERNEL +	. = ALIGN(PAGE_SIZE); +	__init_begin = .; +#endif + +	INIT_TEXT_SECTION(8) +	.exit.text : { +		ARM_EXIT_KEEP(EXIT_TEXT) +	} +	.init.proc.info : { +		ARM_CPU_DISCARD(PROC_INFO) +	} +	.init.arch.info : { +		__arch_info_begin = .; +		*(.arch.info.init) +		__arch_info_end = .; +	} +	.init.tagtable : { +		__tagtable_begin = .; +		*(.taglist.init) +		__tagtable_end = .; +	} +#ifdef CONFIG_SMP_ON_UP +	.init.smpalt : { +		__smpalt_begin = .; +		*(.alt.smp.init) +		__smpalt_end = .; +	} +#endif +	.init.pv_table : { +		__pv_table_begin = .; +		*(.pv_table) +		__pv_table_end = .; +	} +	.init.data : { +#ifndef CONFIG_XIP_KERNEL +		INIT_DATA +#endif +		INIT_SETUP(16) +		INIT_CALLS +		CON_INITCALL +		SECURITY_INITCALL +		INIT_RAM_FS +	} +#ifndef CONFIG_XIP_KERNEL +	.exit.data : { +		ARM_EXIT_KEEP(EXIT_DATA) +	} +#endif + +	PERCPU_SECTION(32) +  #ifdef CONFIG_XIP_KERNEL  	__data_loc = ALIGN(4);		/* location in binary */  	. = PAGE_OFFSET + TEXT_OFFSET;  #else +	__init_end = .;  	. = ALIGN(THREAD_SIZE);  	__data_loc = .;  #endif @@ -270,12 +282,6 @@ SECTIONS  	/* Default discards */  	DISCARDS - -#ifndef CONFIG_SMP_ON_UP -	/DISCARD/ : { -		*(.alt.smp.init) -	} -#endif  }  /* diff --git a/arch/arm/mach-bcmring/include/mach/entry-macro.S b/arch/arm/mach-bcmring/include/mach/entry-macro.S index 7d393ca010a..94c950d783b 100644 --- a/arch/arm/mach-bcmring/include/mach/entry-macro.S +++ b/arch/arm/mach-bcmring/include/mach/entry-macro.S @@ -80,7 +80,3 @@  		.macro  arch_ret_to_user, tmp1, tmp2  		.endm - -		.macro	irq_prio_table -		.endm - diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index 9844fa4cadc..9818f214d4f 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -520,7 +520,7 @@ fail:  	 */  	if (have_imager()) {  		label = "HD imager"; -		mux |= 1; +		mux |= 2;  		/* externally mux MMC1/ENET/AIC33 to imager */  		mux |= BIT(6) | BIT(5) | BIT(3); @@ -540,7 +540,7 @@ fail:  		resets &= ~BIT(1);  		if (have_tvp7002()) { -			mux |= 2; +			mux |= 1;  			resets &= ~BIT(2);  			label = "tvp7002 HD";  		} else { diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index e7221398e5a..cafbe13a82a 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -254,8 +254,10 @@ gpio_irq_handler(unsigned irq, struct irq_desc *desc)  {  	struct davinci_gpio_regs __iomem *g;  	u32 mask = 0xffff; +	struct davinci_gpio_controller *d; -	g = (__force struct davinci_gpio_regs __iomem *) irq_desc_get_handler_data(desc); +	d = (struct davinci_gpio_controller *)irq_desc_get_handler_data(desc); +	g = (struct davinci_gpio_regs __iomem *)d->regs;  	/* we only care about one bank */  	if (irq & 1) @@ -274,11 +276,14 @@ gpio_irq_handler(unsigned irq, struct irq_desc *desc)  		if (!status)  			break;  		__raw_writel(status, &g->intstat); -		if (irq & 1) -			status >>= 16;  		/* now demux them to the right lowlevel handler */ -		n = (int)irq_get_handler_data(irq); +		n = d->irq_base; +		if (irq & 1) { +			n += 16; +			status >>= 16; +		} +  		while (status) {  			res = ffs(status);  			n += res; @@ -424,7 +429,13 @@ static int __init davinci_gpio_irq_setup(void)  		/* set up all irqs in this bank */  		irq_set_chained_handler(bank_irq, gpio_irq_handler); -		irq_set_handler_data(bank_irq, (__force void *)g); + +		/* +		 * Each chip handles 32 gpios, and each irq bank consists of 16 +		 * gpio irqs. Pass the irq bank's corresponding controller to +		 * the chained irq handler. +		 */ +		irq_set_handler_data(bank_irq, &chips[gpio / 32]);  		for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) {  			irq_set_chip(irq, &gpio_irqchip); diff --git a/arch/arm/mach-davinci/include/mach/entry-macro.S b/arch/arm/mach-davinci/include/mach/entry-macro.S index fbdebc7cb40..e14c0dc0e12 100644 --- a/arch/arm/mach-davinci/include/mach/entry-macro.S +++ b/arch/arm/mach-davinci/include/mach/entry-macro.S @@ -46,6 +46,3 @@  #endif  1002:  		.endm - -		.macro	irq_prio_table -		.endm diff --git a/arch/arm/mach-davinci/irq.c b/arch/arm/mach-davinci/irq.c index bfe68ec4e1a..952dc126c39 100644 --- a/arch/arm/mach-davinci/irq.c +++ b/arch/arm/mach-davinci/irq.c @@ -52,8 +52,14 @@ davinci_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)  	struct irq_chip_type *ct;  	gc = irq_alloc_generic_chip("AINTC", 1, irq_start, base, handle_edge_irq); +	if (!gc) { +		pr_err("%s: irq_alloc_generic_chip for IRQ %u failed\n", +		       __func__, irq_start); +		return; +	} +  	ct = gc->chip_types; -	ct->chip.irq_ack = irq_gc_ack; +	ct->chip.irq_ack = irq_gc_ack_set_bit;  	ct->chip.irq_mask = irq_gc_mask_clr_bit;  	ct->chip.irq_unmask = irq_gc_mask_set_bit; diff --git a/arch/arm/mach-exynos4/platsmp.c b/arch/arm/mach-exynos4/platsmp.c index c5e65a02be8..b68d5bdf04c 100644 --- a/arch/arm/mach-exynos4/platsmp.c +++ b/arch/arm/mach-exynos4/platsmp.c @@ -154,14 +154,6 @@ void __init smp_init_cpus(void)  void __init platform_smp_prepare_cpus(unsigned int max_cpus)  { -	int i; - -	/* -	 * Initialise the present map, which describes the set of CPUs -	 * actually populated at the present time. -	 */ -	for (i = 0; i < max_cpus; i++) -		set_cpu_present(i, true);  	scu_enable(scu_base_addr()); diff --git a/arch/arm/mach-exynos4/pm.c b/arch/arm/mach-exynos4/pm.c index 8755ca8dd48..533c28f758c 100644 --- a/arch/arm/mach-exynos4/pm.c +++ b/arch/arm/mach-exynos4/pm.c @@ -280,7 +280,7 @@ static struct sleep_save exynos4_l2cc_save[] = {  	SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL),  }; -void exynos4_cpu_suspend(void) +static int exynos4_cpu_suspend(unsigned long arg)  {  	unsigned long tmp;  	unsigned long mask = 0xFFFFFFFF; diff --git a/arch/arm/mach-exynos4/sleep.S b/arch/arm/mach-exynos4/sleep.S index 6b62425417a..0984078f1eb 100644 --- a/arch/arm/mach-exynos4/sleep.S +++ b/arch/arm/mach-exynos4/sleep.S @@ -33,28 +33,6 @@  	.text  	/* -	 * s3c_cpu_save -	 * -	 * entry: -	 *	r1 = v:p offset -	 */ - -ENTRY(s3c_cpu_save) - -	stmfd	sp!, { r3 - r12, lr } -	ldr	r3, =resume_with_mmu -	bl	cpu_suspend - -	ldr	r0, =pm_cpu_sleep -	ldr	r0, [ r0 ] -	mov	pc, r0 - -resume_with_mmu: -	ldmfd	sp!, { r3 - r12, pc } - -	.ltorg - -	/*  	 * sleep magic, to allow the bootloader to check for an valid  	 * image to resume to. Must be the first word before the  	 * s3c_cpu_resume entry. diff --git a/arch/arm/mach-h720x/include/mach/entry-macro.S b/arch/arm/mach-h720x/include/mach/entry-macro.S index 6d3b917c4a1..c3948e5ba4a 100644 --- a/arch/arm/mach-h720x/include/mach/entry-macro.S +++ b/arch/arm/mach-h720x/include/mach/entry-macro.S @@ -57,9 +57,6 @@  		tst     \irqstat, #1		       @ bit 0 should be set  		.endm -		.macro  irq_prio_table -		.endm -  #else  #error hynix processor selection missmatch  #endif diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 74ed81a3cb1..07772575d7a 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -419,14 +419,20 @@ static void notrace ixp4xx_update_sched_clock(void)  /*   * clocksource   */ + +static cycle_t ixp4xx_clocksource_read(struct clocksource *c) +{ +	return *IXP4XX_OSTS; +} +  unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ;  EXPORT_SYMBOL(ixp4xx_timer_freq);  static void __init ixp4xx_clocksource_init(void)  {  	init_sched_clock(&cd, ixp4xx_update_sched_clock, 32, ixp4xx_timer_freq); -	clocksource_mmio_init(&IXP4XX_OSTS, "OSTS", ixp4xx_timer_freq, 200, 32, -			clocksource_mmio_readl_up); +	clocksource_mmio_init(NULL, "OSTS", ixp4xx_timer_freq, 200, 32, +			ixp4xx_clocksource_read);  }  /* diff --git a/arch/arm/mach-lpc32xx/include/mach/entry-macro.S b/arch/arm/mach-lpc32xx/include/mach/entry-macro.S index 870227c9660..b725f6c9397 100644 --- a/arch/arm/mach-lpc32xx/include/mach/entry-macro.S +++ b/arch/arm/mach-lpc32xx/include/mach/entry-macro.S @@ -41,7 +41,3 @@  	rsb	\irqnr, \irqnr, #31  	teq	\irqstat, #0  	.endm - -	.macro	irq_prio_table -	.endm - diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 72b4e763158..ab9f999106c 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -79,7 +79,7 @@ static APBC_CLK(ssp4, PXA168_SSP4, 4, 0);  static APBC_CLK(ssp5, PXA168_SSP5, 4, 0);  static APBC_CLK(keypad, PXA168_KPC, 0, 32000); -static APMU_CLK(nand, NAND, 0x01db, 208000000); +static APMU_CLK(nand, NAND, 0x19b, 156000000);  static APMU_CLK(lcd, LCD, 0x7f, 312000000);  /* device and clock bindings */ diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c index 8f92ccd26ed..1464607aa60 100644 --- a/arch/arm/mach-mmp/pxa910.c +++ b/arch/arm/mach-mmp/pxa910.c @@ -110,7 +110,7 @@ static APBC_CLK(pwm2, PXA910_PWM2, 1, 13000000);  static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000);  static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000); -static APMU_CLK(nand, NAND, 0x01db, 208000000); +static APMU_CLK(nand, NAND, 0x19b, 156000000);  static APMU_CLK(u2o, USB, 0x1b, 480000000);  /* device and clock bindings */ diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index 2034098cf01..315b9f36532 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c @@ -157,12 +157,4 @@ void __init smp_init_cpus(void)  void __init platform_smp_prepare_cpus(unsigned int max_cpus)  { -	int i; - -	/* -	 * Initialise the present map, which describes the set of CPUs -	 * actually populated at the present time. -	 */ -	for (i = 0; i < max_cpus; i++) -		set_cpu_present(i, true);  } diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index da53ba3917c..aab884fecc5 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -286,14 +286,15 @@ void omap3_save_scratchpad_contents(void)  	scratchpad_contents.boot_config_ptr = 0x0;  	if (cpu_is_omap3630())  		scratchpad_contents.public_restore_ptr = -			virt_to_phys(get_omap3630_restore_pointer()); +			virt_to_phys(omap3_restore_3630);  	else if (omap_rev() != OMAP3430_REV_ES3_0 &&  					omap_rev() != OMAP3430_REV_ES3_1)  		scratchpad_contents.public_restore_ptr = -			virt_to_phys(get_restore_pointer()); +			virt_to_phys(omap3_restore);  	else  		scratchpad_contents.public_restore_ptr = -			virt_to_phys(get_es3_restore_pointer()); +			virt_to_phys(omap3_restore_es3); +  	if (omap_type() == OMAP2_DEVICE_TYPE_GP)  		scratchpad_contents.secure_ram_restore_ptr = 0x0;  	else diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h index a016c8b59e0..d4ef75d5a38 100644 --- a/arch/arm/mach-omap2/control.h +++ b/arch/arm/mach-omap2/control.h @@ -386,9 +386,9 @@ extern void omap4_ctrl_pad_writel(u32 val, u16 offset);  extern void omap3_save_scratchpad_contents(void);  extern void omap3_clear_scratchpad_contents(void); -extern u32 *get_restore_pointer(void); -extern u32 *get_es3_restore_pointer(void); -extern u32 *get_omap3630_restore_pointer(void); +extern void omap3_restore(void); +extern void omap3_restore_es3(void); +extern void omap3_restore_3630(void);  extern u32 omap3_arm_context[128];  extern void omap3_control_save_context(void);  extern void omap3_control_restore_context(void); diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S index a48690b9099..ceb8b7e593d 100644 --- a/arch/arm/mach-omap2/include/mach/entry-macro.S +++ b/arch/arm/mach-omap2/include/mach/entry-macro.S @@ -165,6 +165,3 @@  #endif  #endif	/* MULTI_OMAP2 */ - -		.macro	irq_prio_table -		.endm diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index ecfe93c4b58..ce65e9329c7 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -125,14 +125,6 @@ void __init smp_init_cpus(void)  void __init platform_smp_prepare_cpus(unsigned int max_cpus)  { -	int i; - -	/* -	 * Initialise the present map, which describes the set of CPUs -	 * actually populated at the present time. -	 */ -	for (i = 0; i < max_cpus; i++) -		set_cpu_present(i, true);  	/*  	 * Initialise the SCU and wake up the secondary core using diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 45bcfce7735..04ee5664612 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -88,18 +88,28 @@ extern int pm_dbg_regset_init(int reg_set);  #define pm_dbg_regset_init(reg_set) do {} while (0);  #endif /* CONFIG_PM_DEBUG */ +/* 24xx */  extern void omap24xx_idle_loop_suspend(void); +extern unsigned int omap24xx_idle_loop_suspend_sz;  extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,  					void __iomem *sdrc_power); -extern void omap34xx_cpu_suspend(u32 *addr, int save_state); -extern int save_secure_ram_context(u32 *addr); -extern void omap3_save_scratchpad_contents(void); +extern unsigned int omap24xx_cpu_suspend_sz; -extern unsigned int omap24xx_idle_loop_suspend_sz; +/* 3xxx */ +extern void omap34xx_cpu_suspend(int save_state); + +/* omap3_do_wfi function pointer and size, for copy to SRAM */ +extern void omap3_do_wfi(void); +extern unsigned int omap3_do_wfi_sz; +/* ... and its pointer from SRAM after copy */ +extern void (*omap3_do_wfi_sram)(void); + +/* save_secure_ram_context function pointer and size, for copy to SRAM */ +extern int save_secure_ram_context(u32 *addr);  extern unsigned int save_secure_ram_context_sz; -extern unsigned int omap24xx_cpu_suspend_sz; -extern unsigned int omap34xx_cpu_suspend_sz; + +extern void omap3_save_scratchpad_contents(void);  #define PM_RTA_ERRATUM_i608		(1 << 0)  #define PM_SDRC_WAKEUP_ERRATUM_i583	(1 << 1) diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index c155c9d1c82..b77d82665ab 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -31,6 +31,8 @@  #include <linux/console.h>  #include <trace/events/power.h> +#include <asm/suspend.h> +  #include <plat/sram.h>  #include "clockdomain.h"  #include "powerdomain.h" @@ -40,8 +42,6 @@  #include <plat/gpmc.h>  #include <plat/dma.h> -#include <asm/tlbflush.h> -  #include "cm2xxx_3xxx.h"  #include "cm-regbits-34xx.h"  #include "prm-regbits-34xx.h" @@ -64,11 +64,6 @@ static inline bool is_suspending(void)  }  #endif -/* Scratchpad offsets */ -#define OMAP343X_TABLE_ADDRESS_OFFSET	   0xc4 -#define OMAP343X_TABLE_VALUE_OFFSET	   0xc0 -#define OMAP343X_CONTROL_REG_VALUE_OFFSET  0xc8 -  /* pm34xx errata defined in pm.h */  u16 pm34xx_errata; @@ -83,9 +78,8 @@ struct power_state {  static LIST_HEAD(pwrst_list); -static void (*_omap_sram_idle)(u32 *addr, int save_state); -  static int (*_omap_save_secure_sram)(u32 *addr); +void (*omap3_do_wfi_sram)(void);  static struct powerdomain *mpu_pwrdm, *neon_pwrdm;  static struct powerdomain *core_pwrdm, *per_pwrdm; @@ -312,28 +306,25 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)  	return IRQ_HANDLED;  } -/* Function to restore the table entry that was modified for enabling MMU */ -static void restore_table_entry(void) +static void omap34xx_save_context(u32 *save)  { -	void __iomem *scratchpad_address; -	u32 previous_value, control_reg_value; -	u32 *address; +	u32 val; -	scratchpad_address = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD); +	/* Read Auxiliary Control Register */ +	asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (val)); +	*save++ = 1; +	*save++ = val; -	/* Get address of entry that was modified */ -	address = (u32 *)__raw_readl(scratchpad_address + -				     OMAP343X_TABLE_ADDRESS_OFFSET); -	/* Get the previous value which needs to be restored */ -	previous_value = __raw_readl(scratchpad_address + -				     OMAP343X_TABLE_VALUE_OFFSET); -	address = __va(address); -	*address = previous_value; -	flush_tlb_all(); -	control_reg_value = __raw_readl(scratchpad_address -					+ OMAP343X_CONTROL_REG_VALUE_OFFSET); -	/* This will enable caches and prediction */ -	set_cr(control_reg_value); +	/* Read L2 AUX ctrl register */ +	asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (val)); +	*save++ = 1; +	*save++ = val; +} + +static int omap34xx_do_sram_idle(unsigned long save_state) +{ +	omap34xx_cpu_suspend(save_state); +	return 0;  }  void omap_sram_idle(void) @@ -352,9 +343,6 @@ void omap_sram_idle(void)  	int core_prev_state, per_prev_state;  	u32 sdrc_pwr = 0; -	if (!_omap_sram_idle) -		return; -  	pwrdm_clear_all_prev_pwrst(mpu_pwrdm);  	pwrdm_clear_all_prev_pwrst(neon_pwrdm);  	pwrdm_clear_all_prev_pwrst(core_pwrdm); @@ -432,12 +420,16 @@ void omap_sram_idle(void)  		sdrc_pwr = sdrc_read_reg(SDRC_POWER);  	/* -	 * omap3_arm_context is the location where ARM registers -	 * get saved. The restore path then reads from this -	 * location and restores them back. +	 * omap3_arm_context is the location where some ARM context +	 * get saved. The rest is placed on the stack, and restored +	 * from there before resuming.  	 */ -	_omap_sram_idle(omap3_arm_context, save_state); -	cpu_init(); +	if (save_state) +		omap34xx_save_context(omap3_arm_context); +	if (save_state == 1 || save_state == 3) +		cpu_suspend(save_state, omap34xx_do_sram_idle); +	else +		omap34xx_do_sram_idle(save_state);  	/* Restore normal SDRC POWER settings */  	if (omap_rev() >= OMAP3430_REV_ES3_0 && @@ -445,10 +437,6 @@ void omap_sram_idle(void)  	    core_next_state == PWRDM_POWER_OFF)  		sdrc_write_reg(sdrc_pwr, SDRC_POWER); -	/* Restore table entry modified during MMU restoration */ -	if (pwrdm_read_prev_pwrst(mpu_pwrdm) == PWRDM_POWER_OFF) -		restore_table_entry(); -  	/* CORE */  	if (core_next_state < PWRDM_POWER_ON) {  		core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm); @@ -852,10 +840,17 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)  	return 0;  } +/* + * Push functions to SRAM + * + * The minimum set of functions is pushed to SRAM for execution: + * - omap3_do_wfi for erratum i581 WA, + * - save_secure_ram_context for security extensions. + */  void omap_push_sram_idle(void)  { -	_omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend, -					omap34xx_cpu_suspend_sz); +	omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi, omap3_do_wfi_sz); +  	if (omap_type() != OMAP2_DEVICE_TYPE_GP)  		_omap_save_secure_sram = omap_sram_push(save_secure_ram_context,  				save_secure_ram_context_sz); @@ -920,7 +915,6 @@ static int __init omap3_pm_init(void)  	per_clkdm = clkdm_lookup("per_clkdm");  	core_clkdm = clkdm_lookup("core_clkdm"); -	omap_push_sram_idle();  #ifdef CONFIG_SUSPEND  	suspend_set_ops(&omap_pm_ops);  #endif /* CONFIG_SUSPEND */ diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S index 63f10669571..f2ea1bd1c69 100644 --- a/arch/arm/mach-omap2/sleep34xx.S +++ b/arch/arm/mach-omap2/sleep34xx.S @@ -74,46 +74,6 @@   * API functions   */ -/* - * The "get_*restore_pointer" functions are used to provide a - * physical restore address where the ROM code jumps while waking - * up from MPU OFF/OSWR state. - * The restore pointer is stored into the scratchpad. - */ - -	.text -/* Function call to get the restore pointer for resume from OFF */ -ENTRY(get_restore_pointer) -	stmfd	sp!, {lr}	@ save registers on stack -	adr	r0, restore -	ldmfd	sp!, {pc}	@ restore regs and return -ENDPROC(get_restore_pointer) -	.align -ENTRY(get_restore_pointer_sz) -	.word	. - get_restore_pointer - -	.text -/* Function call to get the restore pointer for 3630 resume from OFF */ -ENTRY(get_omap3630_restore_pointer) -	stmfd	sp!, {lr}	@ save registers on stack -	adr	r0, restore_3630 -	ldmfd	sp!, {pc}	@ restore regs and return -ENDPROC(get_omap3630_restore_pointer) -	.align -ENTRY(get_omap3630_restore_pointer_sz) -	.word	. - get_omap3630_restore_pointer - -	.text -/* Function call to get the restore pointer for ES3 to resume from OFF */ -ENTRY(get_es3_restore_pointer) -	stmfd	sp!, {lr}	@ save registers on stack -	adr	r0, restore_es3 -	ldmfd	sp!, {pc}	@ restore regs and return -ENDPROC(get_es3_restore_pointer) -	.align -ENTRY(get_es3_restore_pointer_sz) -	.word	. - get_es3_restore_pointer -  	.text  /*   * L2 cache needs to be toggled for stable OFF mode functionality on 3630. @@ -133,7 +93,7 @@ ENDPROC(enable_omap3630_toggle_l2_on_restore)  /* Function to call rom code to save secure ram context */  	.align	3  ENTRY(save_secure_ram_context) -	stmfd	sp!, {r1-r12, lr}	@ save registers on stack +	stmfd	sp!, {r4 - r11, lr}	@ save registers on stack  	adr	r3, api_params		@ r3 points to parameters  	str	r0, [r3,#0x4]		@ r0 has sdram address  	ldr	r12, high_mask @@ -152,7 +112,7 @@ ENTRY(save_secure_ram_context)  	nop  	nop  	nop -	ldmfd	sp!, {r1-r12, pc} +	ldmfd	sp!, {r4 - r11, pc}  	.align  sram_phy_addr_mask:  	.word	SRAM_BASE_P @@ -179,69 +139,38 @@ ENTRY(save_secure_ram_context_sz)   *   *   * Notes: - * - this code gets copied to internal SRAM at boot and after wake-up - *   from OFF mode. The execution pointer in SRAM is _omap_sram_idle. + * - only the minimum set of functions gets copied to internal SRAM at boot + *   and after wake-up from OFF mode, cf. omap_push_sram_idle. The function + *   pointers in SDRAM or SRAM are called depending on the desired low power + *   target state.   * - when the OMAP wakes up it continues at different execution points   *   depending on the low power mode (non-OFF vs OFF modes),   *   cf. 'Resume path for xxx mode' comments.   */  	.align	3  ENTRY(omap34xx_cpu_suspend) -	stmfd	sp!, {r0-r12, lr}	@ save registers on stack +	stmfd	sp!, {r4 - r11, lr}	@ save registers on stack  	/* -	 * r0 contains CPU context save/restore pointer in sdram -	 * r1 contains information about saving context: +	 * r0 contains information about saving context:  	 *   0 - No context lost  	 *   1 - Only L1 and logic lost  	 *   2 - Only L2 lost (Even L1 is retained we clean it along with L2)  	 *   3 - Both L1 and L2 lost and logic lost  	 */ -	/* Directly jump to WFI is the context save is not required */ -	cmp	r1, #0x0 -	beq	omap3_do_wfi +	/* +	 * For OFF mode: save context and jump to WFI in SDRAM (omap3_do_wfi) +	 * For non-OFF modes: jump to the WFI code in SRAM (omap3_do_wfi_sram) +	 */ +	ldr	r4, omap3_do_wfi_sram_addr +	ldr	r5, [r4] +	cmp	r0, #0x0		@ If no context save required, +	bxeq	r5			@  jump to the WFI code in SRAM +  	/* Otherwise fall through to the save context code */  save_context_wfi: -	mov	r8, r0			@ Store SDRAM address in r8 -	mrc	p15, 0, r5, c1, c0, 1	@ Read Auxiliary Control Register -	mov	r4, #0x1		@ Number of parameters for restore call -	stmia	r8!, {r4-r5}		@ Push parameters for restore call -	mrc	p15, 1, r5, c9, c0, 2	@ Read L2 AUX ctrl register -	stmia	r8!, {r4-r5}		@ Push parameters for restore call - -        /* Check what that target sleep state is from r1 */ -	cmp	r1, #0x2		@ Only L2 lost, no need to save context -	beq	clean_caches - -l1_logic_lost: -	mov	r4, sp			@ Store sp -	mrs	r5, spsr		@ Store spsr -	mov	r6, lr			@ Store lr -	stmia	r8!, {r4-r6} - -	mrc	p15, 0, r4, c1, c0, 2	@ Coprocessor access control register -	mrc	p15, 0, r5, c2, c0, 0	@ TTBR0 -	mrc	p15, 0, r6, c2, c0, 1	@ TTBR1 -	mrc	p15, 0, r7, c2, c0, 2	@ TTBCR -	stmia	r8!, {r4-r7} - -	mrc	p15, 0, r4, c3, c0, 0	@ Domain access Control Register -	mrc	p15, 0, r5, c10, c2, 0	@ PRRR -	mrc	p15, 0, r6, c10, c2, 1	@ NMRR -	stmia	r8!,{r4-r6} - -	mrc	p15, 0, r4, c13, c0, 1	@ Context ID -	mrc	p15, 0, r5, c13, c0, 2	@ User r/w thread and process ID -	mrc	p15, 0, r6, c12, c0, 0	@ Secure or NS vector base address -	mrs	r7, cpsr		@ Store current cpsr -	stmia	r8!, {r4-r7} - -	mrc	p15, 0, r4, c1, c0, 0	@ save control register -	stmia	r8!, {r4} - -clean_caches:  	/*  	 * jump out to kernel flush routine  	 *  - reuse that code is better @@ -284,7 +213,32 @@ clean_caches:   THUMB(	nop		)  	.arm -omap3_do_wfi: +	b	omap3_do_wfi + +/* + * Local variables + */ +omap3_do_wfi_sram_addr: +	.word omap3_do_wfi_sram +kernel_flush: +	.word v7_flush_dcache_all + +/* =================================== + * == WFI instruction => Enter idle == + * =================================== + */ + +/* + * Do WFI instruction + * Includes the resume path for non-OFF modes + * + * This code gets copied to internal SRAM and is accessible + * from both SDRAM and SRAM: + * - executed from SRAM for non-off modes (omap3_do_wfi_sram), + * - executed from SDRAM for OFF mode (omap3_do_wfi). + */ +	.align	3 +ENTRY(omap3_do_wfi)  	ldr	r4, sdrc_power		@ read the SDRC_POWER register  	ldr	r5, [r4]		@ read the contents of SDRC_POWER  	orr	r5, r5, #0x40		@ enable self refresh on idle req @@ -316,8 +270,86 @@ omap3_do_wfi:  	nop  	nop  	nop -	bl wait_sdrc_ok +/* + * This function implements the erratum ID i581 WA: + *  SDRC state restore before accessing the SDRAM + * + * Only used at return from non-OFF mode. For OFF + * mode the ROM code configures the SDRC and + * the DPLL before calling the restore code directly + * from DDR. + */ + +/* Make sure SDRC accesses are ok */ +wait_sdrc_ok: + +/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */ +	ldr	r4, cm_idlest_ckgen +wait_dpll3_lock: +	ldr	r5, [r4] +	tst	r5, #1 +	beq	wait_dpll3_lock + +	ldr	r4, cm_idlest1_core +wait_sdrc_ready: +	ldr	r5, [r4] +	tst	r5, #0x2 +	bne	wait_sdrc_ready +	/* allow DLL powerdown upon hw idle req */ +	ldr	r4, sdrc_power +	ldr	r5, [r4] +	bic	r5, r5, #0x40 +	str	r5, [r4] + +/* + * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a + * base instead. + * Be careful not to clobber r7 when maintaing this code. + */ + +is_dll_in_lock_mode: +	/* Is dll in lock mode? */ +	ldr	r4, sdrc_dlla_ctrl +	ldr	r5, [r4] +	tst	r5, #0x4 +	bne	exit_nonoff_modes	@ Return if locked +	/* wait till dll locks */ +	adr	r7, kick_counter +wait_dll_lock_timed: +	ldr	r4, wait_dll_lock_counter +	add	r4, r4, #1 +	str	r4, [r7, #wait_dll_lock_counter - kick_counter] +	ldr	r4, sdrc_dlla_status +	/* Wait 20uS for lock */ +	mov	r6, #8 +wait_dll_lock: +	subs	r6, r6, #0x1 +	beq	kick_dll +	ldr	r5, [r4] +	and	r5, r5, #0x4 +	cmp	r5, #0x4 +	bne	wait_dll_lock +	b	exit_nonoff_modes	@ Return when locked + +	/* disable/reenable DLL if not locked */ +kick_dll: +	ldr	r4, sdrc_dlla_ctrl +	ldr	r5, [r4] +	mov	r6, r5 +	bic	r6, #(1<<3)		@ disable dll +	str	r6, [r4] +	dsb +	orr	r6, r6, #(1<<3)		@ enable dll +	str	r6, [r4] +	dsb +	ldr	r4, kick_counter +	add	r4, r4, #1 +	str	r4, [r7]		@ kick_counter +	b	wait_dll_lock_timed + +exit_nonoff_modes: +	/* Re-enable C-bit if needed */  	mrc	p15, 0, r0, c1, c0, 0  	tst	r0, #(1 << 2)		@ Check C bit enabled?  	orreq	r0, r0, #(1 << 2)	@ Enable the C bit if cleared @@ -329,7 +361,32 @@ omap3_do_wfi:   * == Exit point from non-OFF modes ==   * ===================================   */ -	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return +	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return + +/* + * Local variables + */ +sdrc_power: +	.word	SDRC_POWER_V +cm_idlest1_core: +	.word	CM_IDLEST1_CORE_V +cm_idlest_ckgen: +	.word	CM_IDLEST_CKGEN_V +sdrc_dlla_status: +	.word	SDRC_DLLA_STATUS_V +sdrc_dlla_ctrl: +	.word	SDRC_DLLA_CTRL_V +	/* +	 * When exporting to userspace while the counters are in SRAM, +	 * these 2 words need to be at the end to facilitate retrival! +	 */ +kick_counter: +	.word	0 +wait_dll_lock_counter: +	.word	0 + +ENTRY(omap3_do_wfi_sz) +	.word	. - omap3_do_wfi  /* @@ -346,13 +403,17 @@ omap3_do_wfi:   *  restore_es3: applies to 34xx >= ES3.0   *  restore_3630: applies to 36xx   *  restore: common code for 3xxx + * + * Note: when back from CORE and MPU OFF mode we are running + *  from SDRAM, without MMU, without the caches and prediction. + *  Also the SRAM content has been cleared.   */ -restore_es3: +ENTRY(omap3_restore_es3)  	ldr	r5, pm_prepwstst_core_p  	ldr	r4, [r5]  	and	r4, r4, #0x3  	cmp	r4, #0x0	@ Check if previous power state of CORE is OFF -	bne	restore +	bne	omap3_restore	@ Fall through to OMAP3 common code  	adr	r0, es3_sdrc_fix  	ldr	r1, sram_base  	ldr	r2, es3_sdrc_fix_sz @@ -364,35 +425,32 @@ copy_to_sram:  	bne	copy_to_sram  	ldr	r1, sram_base  	blx	r1 -	b	restore +	b	omap3_restore	@ Fall through to OMAP3 common code +ENDPROC(omap3_restore_es3) -restore_3630: +ENTRY(omap3_restore_3630)  	ldr	r1, pm_prepwstst_core_p  	ldr	r2, [r1]  	and	r2, r2, #0x3  	cmp	r2, #0x0	@ Check if previous power state of CORE is OFF -	bne	restore +	bne	omap3_restore	@ Fall through to OMAP3 common code  	/* Disable RTA before giving control */  	ldr	r1, control_mem_rta  	mov	r2, #OMAP36XX_RTA_DISABLE  	str	r2, [r1] +ENDPROC(omap3_restore_3630)  	/* Fall through to common code for the remaining logic */ -restore: +ENTRY(omap3_restore)  	/* -	 * Check what was the reason for mpu reset and store the reason in r9: -	 *  0 - No context lost -	 *  1 - Only L1 and logic lost -	 *  2 - Only L2 lost - In this case, we wont be here -	 *  3 - Both L1 and L2 lost +	 * Read the pwstctrl register to check the reason for mpu reset. +	 * This tells us what was lost.  	 */  	ldr	r1, pm_pwstctrl_mpu  	ldr	r2, [r1]  	and	r2, r2, #0x3  	cmp	r2, #0x0	@ Check if target power state was OFF or RET -	moveq	r9, #0x3	@ MPU OFF => L1 and L2 lost -	movne	r9, #0x1	@ Only L1 and L2 lost => avoid L2 invalidation  	bne	logic_l1_restore  	ldr	r0, l2dis_3630 @@ -471,115 +529,39 @@ logic_l1_restore:  	orr	r1, r1, #2		@ re-enable L2 cache  	mcr	p15, 0, r1, c1, c0, 1  skipl2reen: -	mov	r1, #0 -	/* -	 * Invalidate all instruction caches to PoU -	 * and flush branch target cache -	 */ -	mcr	p15, 0, r1, c7, c5, 0 - -	ldr	r4, scratchpad_base -	ldr	r3, [r4,#0xBC] -	adds	r3, r3, #16 - -	ldmia	r3!, {r4-r6} -	mov	sp, r4			@ Restore sp -	msr	spsr_cxsf, r5		@ Restore spsr -	mov	lr, r6			@ Restore lr -	ldmia	r3!, {r4-r7} -	mcr	p15, 0, r4, c1, c0, 2	@ Coprocessor access Control Register -	mcr	p15, 0, r5, c2, c0, 0	@ TTBR0 -	mcr	p15, 0, r6, c2, c0, 1	@ TTBR1 -	mcr	p15, 0, r7, c2, c0, 2	@ TTBCR +	/* Now branch to the common CPU resume function */ +	b	cpu_resume +ENDPROC(omap3_restore) -	ldmia	r3!,{r4-r6} -	mcr	p15, 0, r4, c3, c0, 0	@ Domain access Control Register -	mcr	p15, 0, r5, c10, c2, 0	@ PRRR -	mcr	p15, 0, r6, c10, c2, 1	@ NMRR - - -	ldmia	r3!,{r4-r7} -	mcr	p15, 0, r4, c13, c0, 1	@ Context ID -	mcr	p15, 0, r5, c13, c0, 2	@ User r/w thread and process ID -	mrc	p15, 0, r6, c12, c0, 0	@ Secure or NS vector base address -	msr	cpsr, r7		@ store cpsr - -	/* Enabling MMU here */ -	mrc	p15, 0, r7, c2, c0, 2 	@ Read TTBRControl -	/* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1 */ -	and	r7, #0x7 -	cmp	r7, #0x0 -	beq	usettbr0 -ttbr_error: -	/* -	 * More work needs to be done to support N[0:2] value other than 0 -	 * So looping here so that the error can be detected -	 */ -	b	ttbr_error -usettbr0: -	mrc	p15, 0, r2, c2, c0, 0 -	ldr	r5, ttbrbit_mask -	and	r2, r5 -	mov	r4, pc -	ldr	r5, table_index_mask -	and	r4, r5			@ r4 = 31 to 20 bits of pc -	/* Extract the value to be written to table entry */ -	ldr	r1, table_entry -	/* r1 has the value to be written to table entry*/ -	add	r1, r1, r4 -	/* Getting the address of table entry to modify */ -	lsr	r4, #18 -	/* r2 has the location which needs to be modified */ -	add	r2, r4 -	/* Storing previous entry of location being modified */ -	ldr	r5, scratchpad_base -	ldr	r4, [r2] -	str	r4, [r5, #0xC0] -	/* Modify the table entry */ -	str	r1, [r2] -	/* -	 * Storing address of entry being modified -	 * - will be restored after enabling MMU -	 */ -	ldr	r5, scratchpad_base -	str	r2, [r5, #0xC4] - -	mov	r0, #0 -	mcr	p15, 0, r0, c7, c5, 4	@ Flush prefetch buffer -	mcr	p15, 0, r0, c7, c5, 6	@ Invalidate branch predictor array -	mcr	p15, 0, r0, c8, c5, 0	@ Invalidate instruction TLB -	mcr	p15, 0, r0, c8, c6, 0	@ Invalidate data TLB -	/* -	 * Restore control register. This enables the MMU. -	 * The caches and prediction are not enabled here, they -	 * will be enabled after restoring the MMU table entry. -	 */ -	ldmia	r3!, {r4} -	/* Store previous value of control register in scratchpad */ -	str	r4, [r5, #0xC8] -	ldr	r2, cache_pred_disable_mask -	and	r4, r2 -	mcr	p15, 0, r4, c1, c0, 0 -	dsb -	isb -	ldr     r0, =restoremmu_on -	bx      r0 +	.ltorg  /* - * ============================== - * == Exit point from OFF mode == - * ============================== + * Local variables   */ -restoremmu_on: -	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return - +pm_prepwstst_core_p: +	.word	PM_PREPWSTST_CORE_P +pm_pwstctrl_mpu: +	.word	PM_PWSTCTRL_MPU_P +scratchpad_base: +	.word	SCRATCHPAD_BASE_P +sram_base: +	.word	SRAM_BASE_P + 0x8000 +control_stat: +	.word	CONTROL_STAT +control_mem_rta: +	.word	CONTROL_MEM_RTA_CTRL +l2dis_3630: +	.word	0  /*   * Internal functions   */ -/* This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0 */ +/* + * This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0 + * Copied to and run from SRAM in order to reconfigure the SDRC parameters. + */  	.text  	.align	3  ENTRY(es3_sdrc_fix) @@ -609,6 +591,9 @@ ENTRY(es3_sdrc_fix)  	str	r5, [r4]		@ kick off refreshes  	bx	lr +/* + * Local variables + */  	.align  sdrc_syscfg:  	.word	SDRC_SYSCONFIG_P @@ -627,128 +612,3 @@ sdrc_manual_1:  ENDPROC(es3_sdrc_fix)  ENTRY(es3_sdrc_fix_sz)  	.word	. - es3_sdrc_fix - -/* - * This function implements the erratum ID i581 WA: - *  SDRC state restore before accessing the SDRAM - * - * Only used at return from non-OFF mode. For OFF - * mode the ROM code configures the SDRC and - * the DPLL before calling the restore code directly - * from DDR. - */ - -/* Make sure SDRC accesses are ok */ -wait_sdrc_ok: - -/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */ -	ldr	r4, cm_idlest_ckgen -wait_dpll3_lock: -	ldr	r5, [r4] -	tst	r5, #1 -	beq	wait_dpll3_lock - -	ldr	r4, cm_idlest1_core -wait_sdrc_ready: -	ldr	r5, [r4] -	tst	r5, #0x2 -	bne	wait_sdrc_ready -	/* allow DLL powerdown upon hw idle req */ -	ldr	r4, sdrc_power -	ldr	r5, [r4] -	bic	r5, r5, #0x40 -	str	r5, [r4] - -/* - * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a - * base instead. - * Be careful not to clobber r7 when maintaing this code. - */ - -is_dll_in_lock_mode: -	/* Is dll in lock mode? */ -	ldr	r4, sdrc_dlla_ctrl -	ldr	r5, [r4] -	tst	r5, #0x4 -	bxne	lr			@ Return if locked -	/* wait till dll locks */ -	adr	r7, kick_counter -wait_dll_lock_timed: -	ldr	r4, wait_dll_lock_counter -	add	r4, r4, #1 -	str	r4, [r7, #wait_dll_lock_counter - kick_counter] -	ldr	r4, sdrc_dlla_status -	/* Wait 20uS for lock */ -	mov	r6, #8 -wait_dll_lock: -	subs	r6, r6, #0x1 -	beq	kick_dll -	ldr	r5, [r4] -	and	r5, r5, #0x4 -	cmp	r5, #0x4 -	bne	wait_dll_lock -	bx	lr			@ Return when locked - -	/* disable/reenable DLL if not locked */ -kick_dll: -	ldr	r4, sdrc_dlla_ctrl -	ldr	r5, [r4] -	mov	r6, r5 -	bic	r6, #(1<<3)		@ disable dll -	str	r6, [r4] -	dsb -	orr	r6, r6, #(1<<3)		@ enable dll -	str	r6, [r4] -	dsb -	ldr	r4, kick_counter -	add	r4, r4, #1 -	str	r4, [r7]		@ kick_counter -	b	wait_dll_lock_timed - -	.align -cm_idlest1_core: -	.word	CM_IDLEST1_CORE_V -cm_idlest_ckgen: -	.word	CM_IDLEST_CKGEN_V -sdrc_dlla_status: -	.word	SDRC_DLLA_STATUS_V -sdrc_dlla_ctrl: -	.word	SDRC_DLLA_CTRL_V -pm_prepwstst_core_p: -	.word	PM_PREPWSTST_CORE_P -pm_pwstctrl_mpu: -	.word	PM_PWSTCTRL_MPU_P -scratchpad_base: -	.word	SCRATCHPAD_BASE_P -sram_base: -	.word	SRAM_BASE_P + 0x8000 -sdrc_power: -	.word	SDRC_POWER_V -ttbrbit_mask: -	.word	0xFFFFC000 -table_index_mask: -	.word	0xFFF00000 -table_entry: -	.word	0x00000C02 -cache_pred_disable_mask: -	.word	0xFFFFE7FB -control_stat: -	.word	CONTROL_STAT -control_mem_rta: -	.word	CONTROL_MEM_RTA_CTRL -kernel_flush: -	.word	v7_flush_dcache_all -l2dis_3630: -	.word	0 -	/* -	 * When exporting to userspace while the counters are in SRAM, -	 * these 2 words need to be at the end to facilitate retrival! -	 */ -kick_counter: -	.word	0 -wait_dll_lock_counter: -	.word	0 -ENDPROC(omap34xx_cpu_suspend) - -ENTRY(omap34xx_cpu_suspend_sz) -	.word	. - omap34xx_cpu_suspend diff --git a/arch/arm/mach-pnx4008/include/mach/entry-macro.S b/arch/arm/mach-pnx4008/include/mach/entry-macro.S index 8003037578e..db7eeebf30d 100644 --- a/arch/arm/mach-pnx4008/include/mach/entry-macro.S +++ b/arch/arm/mach-pnx4008/include/mach/entry-macro.S @@ -120,8 +120,3 @@  1003:  		.endm - -		.macro	irq_prio_table -		.endm - - diff --git a/arch/arm/mach-pxa/include/mach/pm.h b/arch/arm/mach-pxa/include/mach/pm.h index f15afe01299..51558bcee99 100644 --- a/arch/arm/mach-pxa/include/mach/pm.h +++ b/arch/arm/mach-pxa/include/mach/pm.h @@ -22,8 +22,8 @@ struct pxa_cpu_pm_fns {  extern struct pxa_cpu_pm_fns *pxa_cpu_pm_fns;  /* sleep.S */ -extern void pxa25x_cpu_suspend(unsigned int, long); -extern void pxa27x_cpu_suspend(unsigned int, long); +extern int pxa25x_finish_suspend(unsigned long); +extern int pxa27x_finish_suspend(unsigned long);  extern int pxa_pm_enter(suspend_state_t state);  extern int pxa_pm_prepare(void); diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c index 87ae3129f4f..b27544bcafc 100644 --- a/arch/arm/mach-pxa/mfp-pxa2xx.c +++ b/arch/arm/mach-pxa/mfp-pxa2xx.c @@ -347,9 +347,9 @@ static int pxa2xx_mfp_suspend(void)  		if ((gpio_desc[i].config & MFP_LPM_KEEP_OUTPUT) &&  		    (GPDR(i) & GPIO_bit(i))) {  			if (GPLR(i) & GPIO_bit(i)) -				PGSR(i) |= GPIO_bit(i); +				PGSR(gpio_to_bank(i)) |= GPIO_bit(i);  			else -				PGSR(i) &= ~GPIO_bit(i); +				PGSR(gpio_to_bank(i)) &= ~GPIO_bit(i);  		}  	} diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c index 65f24f0b77e..5a5329bc33f 100644 --- a/arch/arm/mach-pxa/palmz72.c +++ b/arch/arm/mach-pxa/palmz72.c @@ -33,6 +33,7 @@  #include <linux/i2c-gpio.h>  #include <asm/mach-types.h> +#include <asm/suspend.h>  #include <asm/mach/arch.h>  #include <asm/mach/map.h> diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index 51e1583265b..37178a8559b 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -42,7 +42,6 @@ int pxa_pm_enter(suspend_state_t state)  	/* *** go zzz *** */  	pxa_cpu_pm_fns->enter(state); -	cpu_init();  	if (state != PM_SUSPEND_STANDBY && pxa_cpu_pm_fns->restore) {  		/* after sleeping, validate the checksum */ diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index fed363cec9c..9c434d21a27 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -25,6 +25,7 @@  #include <linux/irq.h>  #include <asm/mach/map.h> +#include <asm/suspend.h>  #include <mach/hardware.h>  #include <mach/irqs.h>  #include <mach/gpio.h> @@ -244,7 +245,7 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state)  	switch (state) {  	case PM_SUSPEND_MEM: -		pxa25x_cpu_suspend(PWRMODE_SLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET); +		cpu_suspend(PWRMODE_SLEEP, pxa25x_finish_suspend);  		break;  	}  } diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 2fecbec58d8..9d2400b5f50 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -24,6 +24,7 @@  #include <asm/mach/map.h>  #include <mach/hardware.h>  #include <asm/irq.h> +#include <asm/suspend.h>  #include <mach/irqs.h>  #include <mach/gpio.h>  #include <mach/pxa27x.h> @@ -284,6 +285,11 @@ void pxa27x_cpu_pm_restore(unsigned long *sleep_save)  void pxa27x_cpu_pm_enter(suspend_state_t state)  {  	extern void pxa_cpu_standby(void); +#ifndef CONFIG_IWMMXT +	u64 acc0; + +	asm volatile("mra %Q0, %R0, acc0" : "=r" (acc0)); +#endif  	/* ensure voltage-change sequencer not initiated, which hangs */  	PCFR &= ~PCFR_FVC; @@ -299,7 +305,10 @@ void pxa27x_cpu_pm_enter(suspend_state_t state)  		pxa_cpu_standby();  		break;  	case PM_SUSPEND_MEM: -		pxa27x_cpu_suspend(pwrmode, PLAT_PHYS_OFFSET - PAGE_OFFSET); +		cpu_suspend(pwrmode, pxa27x_finish_suspend); +#ifndef CONFIG_IWMMXT +		asm volatile("mar acc0, %Q0, %R0" : "=r" (acc0)); +#endif  		break;  	}  } diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index 8521d7d6f1d..ef1c56a67af 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -24,6 +24,7 @@  #include <linux/i2c/pxa-i2c.h>  #include <asm/mach/map.h> +#include <asm/suspend.h>  #include <mach/hardware.h>  #include <mach/gpio.h>  #include <mach/pxa3xx-regs.h> @@ -141,8 +142,13 @@ static void pxa3xx_cpu_pm_suspend(void)  {  	volatile unsigned long *p = (volatile void *)0xc0000000;  	unsigned long saved_data = *p; +#ifndef CONFIG_IWMMXT +	u64 acc0; -	extern void pxa3xx_cpu_suspend(long); +	asm volatile("mra %Q0, %R0, acc0" : "=r" (acc0)); +#endif + +	extern int pxa3xx_finish_suspend(unsigned long);  	/* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */  	CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM); @@ -162,11 +168,15 @@ static void pxa3xx_cpu_pm_suspend(void)  	/* overwrite with the resume address */  	*p = virt_to_phys(cpu_resume); -	pxa3xx_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET); +	cpu_suspend(0, pxa3xx_finish_suspend);  	*p = saved_data;  	AD3ER = 0; + +#ifndef CONFIG_IWMMXT +	asm volatile("mar acc0, %Q0, %R0" : "=r" (acc0)); +#endif  }  static void pxa3xx_cpu_pm_enter(suspend_state_t state) diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index d130f77b6d1..2f37d43f51b 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -573,10 +573,10 @@ static struct pxafb_mode_info sharp_lq043t3dx02_mode = {  	.xres		= 480,  	.yres		= 272,  	.bpp		= 16, -	.hsync_len	= 4, +	.hsync_len	= 41,  	.left_margin	= 2,  	.right_margin	= 1, -	.vsync_len	= 1, +	.vsync_len	= 10,  	.upper_margin	= 3,  	.lower_margin	= 1,  	.sync		= 0, @@ -596,29 +596,31 @@ static void __init raumfeld_lcd_init(void)  {  	int ret; -	pxa_set_fb_info(NULL, &raumfeld_sharp_lcd_info); - -	/* Earlier devices had the backlight regulator controlled -	 * via PWM, later versions use another controller for that */ -	if ((system_rev & 0xff) < 2) { -		mfp_cfg_t raumfeld_pwm_pin_config = GPIO17_PWM0_OUT; -		pxa3xx_mfp_config(&raumfeld_pwm_pin_config, 1); -		platform_device_register(&raumfeld_pwm_backlight_device); -	} else -		platform_device_register(&raumfeld_lt3593_device); -  	ret = gpio_request(GPIO_TFT_VA_EN, "display VA enable");  	if (ret < 0)  		pr_warning("Unable to request GPIO_TFT_VA_EN\n");  	else  		gpio_direction_output(GPIO_TFT_VA_EN, 1); +	msleep(100); +  	ret = gpio_request(GPIO_DISPLAY_ENABLE, "display enable");  	if (ret < 0)  		pr_warning("Unable to request GPIO_DISPLAY_ENABLE\n");  	else  		gpio_direction_output(GPIO_DISPLAY_ENABLE, 1); +	/* Hardware revision 2 has the backlight regulator controlled +	 * by an LT3593, earlier and later devices use PWM for that. */ +	if ((system_rev & 0xff) == 2) { +		platform_device_register(&raumfeld_lt3593_device); +	} else { +		mfp_cfg_t raumfeld_pwm_pin_config = GPIO17_PWM0_OUT; +		pxa3xx_mfp_config(&raumfeld_pwm_pin_config, 1); +		platform_device_register(&raumfeld_pwm_backlight_device); +	} + +	pxa_set_fb_info(NULL, &raumfeld_sharp_lcd_info);  	platform_device_register(&pxa3xx_device_gcu);  } @@ -657,10 +659,10 @@ static struct lis3lv02d_platform_data lis3_pdata = {  #define SPI_AK4104	\  {			\ -	.modalias	= "ak4104",	\ -	.max_speed_hz	= 10000,	\ -	.bus_num	= 0,		\ -	.chip_select	= 0,		\ +	.modalias	= "ak4104-codec",	\ +	.max_speed_hz	= 10000,		\ +	.bus_num	= 0,			\ +	.chip_select	= 0,			\  	.controller_data = (void *) GPIO_SPDIF_CS,	\  } diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S index 6f5368899d8..1e544be9905 100644 --- a/arch/arm/mach-pxa/sleep.S +++ b/arch/arm/mach-pxa/sleep.S @@ -24,20 +24,9 @@  #ifdef CONFIG_PXA3xx  /* - * pxa3xx_cpu_suspend() - forces CPU into sleep state (S2D3C4) - * - * r0 = v:p offset + * pxa3xx_finish_suspend() - forces CPU into sleep state (S2D3C4)   */ -ENTRY(pxa3xx_cpu_suspend) - -#ifndef CONFIG_IWMMXT -	mra	r2, r3, acc0 -#endif -	stmfd	sp!, {r2 - r12, lr}	@ save registers on stack -	mov	r1, r0 -	ldr	r3, =pxa_cpu_resume	@ resume function -	bl	cpu_suspend - +ENTRY(pxa3xx_finish_suspend)  	mov	r0, #0x06		@ S2D3C4 mode  	mcr	p14, 0, r0, c7, c0, 0	@ enter sleep @@ -46,28 +35,18 @@ ENTRY(pxa3xx_cpu_suspend)  #ifdef CONFIG_PXA27x  /* - * pxa27x_cpu_suspend() + * pxa27x_finish_suspend()   *   * Forces CPU into sleep state.   *   * r0 = value for PWRMODE M field for desired sleep state - * r1 = v:p offset   */ -ENTRY(pxa27x_cpu_suspend) - -#ifndef CONFIG_IWMMXT -	mra	r2, r3, acc0 -#endif -	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack -	mov	r4, r0				@ save sleep mode -	ldr	r3, =pxa_cpu_resume		@ resume function -	bl	cpu_suspend - +ENTRY(pxa27x_finish_suspend)  	@ Put the processor to sleep  	@ (also workaround for sighting 28071)  	@ prepare value for sleep mode -	mov	r1, r4				@ sleep mode +	mov	r1, r0				@ sleep mode  	@ prepare pointer to physical address 0 (virtual mapping in generic.c)  	mov	r2, #UNCACHED_PHYS_0 @@ -99,21 +78,16 @@ ENTRY(pxa27x_cpu_suspend)  #ifdef CONFIG_PXA25x  /* - * pxa25x_cpu_suspend() + * pxa25x_finish_suspend()   *   * Forces CPU into sleep state.   *   * r0 = value for PWRMODE M field for desired sleep state - * r1 = v:p offset   */ -ENTRY(pxa25x_cpu_suspend) -	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack -	mov	r4, r0				@ save sleep mode -	ldr	r3, =pxa_cpu_resume		@ resume function -	bl	cpu_suspend +ENTRY(pxa25x_finish_suspend)  	@ prepare value for sleep mode -	mov	r1, r4				@ sleep mode +	mov	r1, r0				@ sleep mode  	@ prepare pointer to physical address 0 (virtual mapping in generic.c)  	mov	r2, #UNCACHED_PHYS_0 @@ -195,16 +169,3 @@ pxa_cpu_do_suspend:  	mcr	p14, 0, r1, c7, c0, 0		@ PWRMODE  20:	b	20b				@ loop waiting for sleep - -/* - * pxa_cpu_resume() - * - * entry point from bootloader into kernel during resume - */ -	.align 5 -pxa_cpu_resume: -	ldmfd	sp!, {r2, r3} -#ifndef CONFIG_IWMMXT -	mar	acc0, r2, r3 -#endif -	ldmfd	sp!, {r4 - r12, pc}		@ return to caller diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c index 00363c7ac18..9b99cc164de 100644 --- a/arch/arm/mach-pxa/zeus.c +++ b/arch/arm/mach-pxa/zeus.c @@ -31,6 +31,7 @@  #include <linux/can/platform/mcp251x.h>  #include <asm/mach-types.h> +#include <asm/suspend.h>  #include <asm/mach/arch.h>  #include <asm/mach/map.h> @@ -676,7 +677,7 @@ static struct pxa2xx_udc_mach_info zeus_udc_info = {  static void zeus_power_off(void)  {  	local_irq_disable(); -	pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET); +	cpu_suspend(PWRMODE_DEEPSLEEP, pxa27x_finish_suspend);  }  #else  #define zeus_power_off   NULL diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index b9a9805e482..dba6d0c1fc1 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -50,6 +50,7 @@ config MACH_REALVIEW_PB1176  	bool "Support RealView(R) Platform Baseboard for ARM1176JZF-S"  	select CPU_V6  	select ARM_GIC +	select HAVE_TCM  	help  	  Include support for the ARM(R) RealView(R) Platform Baseboard for  	  ARM1176JZF-S. diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index 963bf0d8119..4ae943bafa9 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -68,14 +68,6 @@ void __init smp_init_cpus(void)  void __init platform_smp_prepare_cpus(unsigned int max_cpus)  { -	int i; - -	/* -	 * Initialise the present map, which describes the set of CPUs -	 * actually populated at the present time. -	 */ -	for (i = 0; i < max_cpus; i++) -		set_cpu_present(i, true);  	scu_enable(scu_base_addr()); diff --git a/arch/arm/mach-s3c2412/pm.c b/arch/arm/mach-s3c2412/pm.c index 752b13a7b3d..f4077efa51f 100644 --- a/arch/arm/mach-s3c2412/pm.c +++ b/arch/arm/mach-s3c2412/pm.c @@ -37,12 +37,10 @@  extern void s3c2412_sleep_enter(void); -static void s3c2412_cpu_suspend(void) +static int s3c2412_cpu_suspend(unsigned long arg)  {  	unsigned long tmp; -	flush_cache_all(); -  	/* set our standby method to sleep */  	tmp = __raw_readl(S3C2412_PWRCFG); @@ -50,6 +48,8 @@ static void s3c2412_cpu_suspend(void)  	__raw_writel(tmp, S3C2412_PWRCFG);  	s3c2412_sleep_enter(); + +	panic("sleep resumed to originator?");  }  static void s3c2412_pm_prepare(void) diff --git a/arch/arm/mach-s3c2416/pm.c b/arch/arm/mach-s3c2416/pm.c index 41db2b21e21..9ec54f1d8e7 100644 --- a/arch/arm/mach-s3c2416/pm.c +++ b/arch/arm/mach-s3c2416/pm.c @@ -24,10 +24,8 @@  extern void s3c2412_sleep_enter(void); -static void s3c2416_cpu_suspend(void) +static int s3c2416_cpu_suspend(unsigned long arg)  { -	flush_cache_all(); -  	/* enable wakeup sources regardless of battery state */  	__raw_writel(S3C2443_PWRCFG_SLEEP, S3C2443_PWRCFG); @@ -35,6 +33,8 @@ static void s3c2416_cpu_suspend(void)  	__raw_writel(0x2BED, S3C2443_PWRMODE);  	s3c2412_sleep_enter(); + +	panic("sleep resumed to originator?");  }  static void s3c2416_pm_prepare(void) diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c index b197171e7d0..204bfafe4bf 100644 --- a/arch/arm/mach-s3c64xx/dma.c +++ b/arch/arm/mach-s3c64xx/dma.c @@ -113,7 +113,7 @@ found:  	return chan;  } -int s3c2410_dma_config(unsigned int channel, int xferunit) +int s3c2410_dma_config(enum dma_ch channel, int xferunit)  {  	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); @@ -297,7 +297,7 @@ static int s3c64xx_dma_flush(struct s3c2410_dma_chan *chan)  	return 0;  } -int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op) +int s3c2410_dma_ctrl(enum dma_ch channel, enum s3c2410_chan_op op)  {  	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); @@ -331,7 +331,7 @@ EXPORT_SYMBOL(s3c2410_dma_ctrl);   *   */ -int s3c2410_dma_enqueue(unsigned int channel, void *id, +int s3c2410_dma_enqueue(enum dma_ch channel, void *id,  			dma_addr_t data, int size)  {  	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); @@ -415,7 +415,7 @@ err_buff:  EXPORT_SYMBOL(s3c2410_dma_enqueue); -int s3c2410_dma_devconfig(unsigned int channel, +int s3c2410_dma_devconfig(enum dma_ch channel,  			  enum s3c2410_dmasrc source,  			  unsigned long devaddr)  { @@ -463,7 +463,7 @@ int s3c2410_dma_devconfig(unsigned int channel,  EXPORT_SYMBOL(s3c2410_dma_devconfig); -int s3c2410_dma_getposition(unsigned int channel, +int s3c2410_dma_getposition(enum dma_ch channel,  			    dma_addr_t *src, dma_addr_t *dst)  {  	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); @@ -487,7 +487,7 @@ EXPORT_SYMBOL(s3c2410_dma_getposition);   * get control of an dma channel  */ -int s3c2410_dma_request(unsigned int channel, +int s3c2410_dma_request(enum dma_ch channel,  			struct s3c2410_dma_client *client,  			void *dev)  { @@ -533,7 +533,7 @@ EXPORT_SYMBOL(s3c2410_dma_request);   * allowed to go through.  */ -int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client) +int s3c2410_dma_free(enum dma_ch channel, struct s3c2410_dma_client *client)  {  	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);  	unsigned long flags; diff --git a/arch/arm/mach-s3c64xx/pm.c b/arch/arm/mach-s3c64xx/pm.c index bc1c470b7de..8bad6437068 100644 --- a/arch/arm/mach-s3c64xx/pm.c +++ b/arch/arm/mach-s3c64xx/pm.c @@ -112,7 +112,7 @@ void s3c_pm_save_core(void)   * this.   */ -static void s3c64xx_cpu_suspend(void) +static int s3c64xx_cpu_suspend(unsigned long arg)  {  	unsigned long tmp; diff --git a/arch/arm/mach-s3c64xx/sleep.S b/arch/arm/mach-s3c64xx/sleep.S index 1f87732b232..34313f9c879 100644 --- a/arch/arm/mach-s3c64xx/sleep.S +++ b/arch/arm/mach-s3c64xx/sleep.S @@ -25,29 +25,6 @@  	.text -	/* s3c_cpu_save -	 * -	 * Save enough processor state to allow the restart of the pm.c -	 * code after resume. -	 * -	 * entry: -	 *	r1 = v:p offset -	*/ - -ENTRY(s3c_cpu_save) -	stmfd	sp!, { r4 - r12, lr } -	ldr	r3, =resume_with_mmu -	bl	cpu_suspend - -	@@ call final suspend code -	ldr	r0, =pm_cpu_sleep -	ldr	pc, [r0] -	 -	@@ return to the caller, after the MMU is turned on. -	@@ restore the last bits of the stack and return. -resume_with_mmu: -	ldmfd	sp!, { r4 - r12, pc }	@ return, from sp from s3c_cpu_save -  	/* Sleep magic, the word before the resume entry point so that the  	 * bootloader can check for a resumeable image. */ diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c index 24febae3d4c..309e388a8a8 100644 --- a/arch/arm/mach-s5pv210/pm.c +++ b/arch/arm/mach-s5pv210/pm.c @@ -88,7 +88,7 @@ static struct sleep_save s5pv210_core_save[] = {  	SAVE_ITEM(S3C2410_TCNTO(0)),  }; -void s5pv210_cpu_suspend(void) +void s5pv210_cpu_suspend(unsigned long arg)  {  	unsigned long tmp; diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S index a3d649466fb..e3452ccd4b0 100644 --- a/arch/arm/mach-s5pv210/sleep.S +++ b/arch/arm/mach-s5pv210/sleep.S @@ -32,27 +32,6 @@  	.text -	/* s3c_cpu_save -	 * -	 * entry: -	 *	r1 = v:p offset -	*/ - -ENTRY(s3c_cpu_save) - -	stmfd	sp!, { r3 - r12, lr } -	ldr	r3, =resume_with_mmu -	bl	cpu_suspend - -	ldr	r0, =pm_cpu_sleep -	ldr	r0, [ r0 ] -	mov	pc, r0 - -resume_with_mmu: -	ldmfd	sp!, { r3 - r12, pc } - -	.ltorg -  	/* sleep magic, to allow the bootloader to check for an valid  	 * image to resume to. Must be the first word before the  	 * s3c_cpu_resume entry. diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index c4661aab22f..bf85b8b259d 100644 --- a/arch/arm/mach-sa1100/pm.c +++ b/arch/arm/mach-sa1100/pm.c @@ -29,10 +29,11 @@  #include <mach/hardware.h>  #include <asm/memory.h> +#include <asm/suspend.h>  #include <asm/system.h>  #include <asm/mach/time.h> -extern void sa1100_cpu_suspend(long); +extern int sa1100_finish_suspend(unsigned long);  #define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x  #define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x] @@ -75,9 +76,7 @@ static int sa11x0_pm_enter(suspend_state_t state)  	PSPR = virt_to_phys(cpu_resume);  	/* go zzz */ -	sa1100_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET); - -	cpu_init(); +	cpu_suspend(0, sa1100_finish_suspend);  	/*  	 * Ensure not to come back here if it wasn't intended diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S index 04f2a618d4e..e8223315b44 100644 --- a/arch/arm/mach-sa1100/sleep.S +++ b/arch/arm/mach-sa1100/sleep.S @@ -22,18 +22,13 @@  		.text  /* - * sa1100_cpu_suspend() + * sa1100_finish_suspend()   *   * Causes sa11x0 to enter sleep state   *   */ -ENTRY(sa1100_cpu_suspend) -	stmfd	sp!, {r4 - r12, lr}		@ save registers on stack -	mov	r1, r0 -	ldr	r3, =sa1100_cpu_resume		@ return function -	bl	cpu_suspend - +ENTRY(sa1100_finish_suspend)  	@ disable clock switching  	mcr	p15, 0, r1, c15, c2, 2 @@ -139,13 +134,3 @@ sa1110_sdram_controller_fix:  	str	r13, [r12]  20:	b	20b			@ loop waiting for sleep - -/* - * cpu_sa1100_resume() - * - * entry point from bootloader into kernel during resume - */ -	.align 5 -sa1100_cpu_resume: -	mcr	p15, 0, r1, c15, c1, 2		@ enable clock switching -	ldmfd	sp!, {r4 - r12, pc}		@ return to caller diff --git a/arch/arm/mach-shark/include/mach/entry-macro.S b/arch/arm/mach-shark/include/mach/entry-macro.S index e2853c0a333..0bb6cc626eb 100644 --- a/arch/arm/mach-shark/include/mach/entry-macro.S +++ b/arch/arm/mach-shark/include/mach/entry-macro.S @@ -11,17 +11,17 @@  		.endm  		.macro  get_irqnr_preamble, base, tmp +		mov	\base, #0xe0000000  		.endm  		.macro  arch_ret_to_user, tmp1, tmp2  		.endm  		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp -		mov	r4, #0xe0000000  		mov	\irqstat, #0x0C -		strb	\irqstat, [r4, #0x20]		@outb(0x0C, 0x20) /* Poll command */ -		ldrb	\irqnr, [r4, #0x20]		@irq = inb(0x20) & 7 +		strb	\irqstat, [\base, #0x20]	@outb(0x0C, 0x20) /* Poll command */ +		ldrb	\irqnr, [\base, #0x20]		@irq = inb(0x20) & 7  		and	\irqstat, \irqnr, #0x80  		teq	\irqstat, #0  		beq	43f @@ -29,8 +29,8 @@  		teq	\irqnr, #2  		bne	44f  43:		mov	\irqstat, #0x0C -		strb	\irqstat, [r4, #0xa0]		@outb(0x0C, 0xA0) /* Poll command */ -		ldrb	\irqnr, [r4, #0xa0]		@irq = (inb(0xA0) & 7) + 8 +		strb	\irqstat, [\base, #0xa0]	@outb(0x0C, 0xA0) /* Poll command */ +		ldrb	\irqnr, [\base, #0xa0]		@irq = (inb(0xA0) & 7) + 8  		and	\irqstat, \irqnr, #0x80  		teq	\irqstat, #0  		beq	44f diff --git a/arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h b/arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h new file mode 100644 index 00000000000..4a81b01f1e8 --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h @@ -0,0 +1,21 @@ +#ifndef SDHI_SH7372_H +#define SDHI_SH7372_H + +#define SDGENCNTA       0xfe40009c + +/* The countdown of SDGENCNTA is controlled by + * ZB3D2CLK which runs at 149.5MHz. + * That is 149.5ticks/us. Approximate this as 150ticks/us. + */ +static void udelay(int us) +{ +	__raw_writel(us * 150, SDGENCNTA); +	while(__raw_readl(SDGENCNTA)) ; +} + +static void msleep(int ms) +{ +	udelay(ms * 1000); +} + +#endif diff --git a/arch/arm/mach-shmobile/include/mach/sdhi.h b/arch/arm/mach-shmobile/include/mach/sdhi.h new file mode 100644 index 00000000000..0ec9e69f2c3 --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/sdhi.h @@ -0,0 +1,16 @@ +#ifndef SDHI_H +#define SDHI_H + +/************************************************** + * + *		CPU specific settings + * + **************************************************/ + +#ifdef CONFIG_ARCH_SH7372 +#include "mach/sdhi-sh7372.h" +#else +#error "unsupported CPU." +#endif + +#endif /* SDHI_H */ diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index f3888feb1c6..66f980625a3 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c @@ -64,10 +64,5 @@ void __init smp_init_cpus(void)  void __init platform_smp_prepare_cpus(unsigned int max_cpus)  { -	int i; - -	for (i = 0; i < max_cpus; i++) -		set_cpu_present(i, true); -  	shmobile_smp_prepare_cpus();  } diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index b8ae3c978de..1a594dce8fb 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c @@ -129,14 +129,6 @@ void __init smp_init_cpus(void)  void __init platform_smp_prepare_cpus(unsigned int max_cpus)  { -	int i; - -	/* -	 * Initialise the present map, which describes the set of CPUs -	 * actually populated at the present time. -	 */ -	for (i = 0; i < max_cpus; i++) -		set_cpu_present(i, true);  	scu_enable(scu_base);  } diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index 0c527fe2ceb..a33df5f4c27 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -172,14 +172,6 @@ void __init smp_init_cpus(void)  void __init platform_smp_prepare_cpus(unsigned int max_cpus)  { -	int i; - -	/* -	 * Initialise the present map, which describes the set of CPUs -	 * actually populated at the present time. -	 */ -	for (i = 0; i < max_cpus; i++) -		set_cpu_present(i, true);  	scu_enable(scu_base_addr());  	wakeup_secondary(); diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 765a71ff7f3..bfd32f52c2d 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -229,10 +229,6 @@ static void ct_ca9x4_init_cpu_map(void)  static void ct_ca9x4_smp_enable(unsigned int max_cpus)  { -	int i; -	for (i = 0; i < max_cpus; i++) -		set_cpu_present(i, true); -  	scu_enable(MMIO_P2V(A9_MPCORE_SCU));  }  #endif diff --git a/arch/arm/mm/abort-ev4.S b/arch/arm/mm/abort-ev4.S index 4f18f9e87ba..54473cd4aba 100644 --- a/arch/arm/mm/abort-ev4.S +++ b/arch/arm/mm/abort-ev4.S @@ -3,14 +3,11 @@  /*   * Function: v4_early_abort   * - * Params  : r2 = address of aborted instruction - *         : r3 = saved SPSR + * Params  : r2 = pt_regs + *	   : r4 = aborted context pc + *	   : r5 = aborted context psr   * - * Returns : r0 = address of abort - *	   : r1 = FSR, bit 11 = write - *	   : r2-r8 = corrupted - *	   : r9 = preserved - *	   : sp = pointer to registers + * Returns : r4 - r11, r13 preserved   *   * Purpose : obtain information about current aborted instruction.   * Note: we read user space.  This means we might cause a data @@ -21,10 +18,8 @@  ENTRY(v4_early_abort)  	mrc	p15, 0, r1, c5, c0, 0		@ get FSR  	mrc	p15, 0, r0, c6, c0, 0		@ get FAR -	ldr	r3, [r2]			@ read aborted ARM instruction +	ldr	r3, [r4]			@ read aborted ARM instruction  	bic	r1, r1, #1 << 11 | 1 << 10	@ clear bits 11 and 10 of FSR  	tst	r3, #1 << 20			@ L = 1 -> write?  	orreq	r1, r1, #1 << 11		@ yes. -	mov	pc, lr - - +	b	do_DataAbort diff --git a/arch/arm/mm/abort-ev4t.S b/arch/arm/mm/abort-ev4t.S index b6282548f92..9da704e7b86 100644 --- a/arch/arm/mm/abort-ev4t.S +++ b/arch/arm/mm/abort-ev4t.S @@ -4,14 +4,11 @@  /*   * Function: v4t_early_abort   * - * Params  : r2 = address of aborted instruction - *         : r3 = saved SPSR + * Params  : r2 = pt_regs + *	   : r4 = aborted context pc + *	   : r5 = aborted context psr   * - * Returns : r0 = address of abort - *	   : r1 = FSR, bit 11 = write - *	   : r2-r8 = corrupted - *	   : r9 = preserved - *	   : sp = pointer to registers + * Returns : r4 - r11, r13 preserved   *   * Purpose : obtain information about current aborted instruction.   * Note: we read user space.  This means we might cause a data @@ -22,9 +19,9 @@  ENTRY(v4t_early_abort)  	mrc	p15, 0, r1, c5, c0, 0		@ get FSR  	mrc	p15, 0, r0, c6, c0, 0		@ get FAR -	do_thumb_abort -	ldreq	r3, [r2]			@ read aborted ARM instruction +	do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3 +	ldreq	r3, [r4]			@ read aborted ARM instruction  	bic	r1, r1, #1 << 11 | 1 << 10	@ clear bits 11 and 10 of FSR  	tst	r3, #1 << 20			@ check write  	orreq	r1, r1, #1 << 11 -	mov	pc, lr +	b	do_DataAbort diff --git a/arch/arm/mm/abort-ev5t.S b/arch/arm/mm/abort-ev5t.S index 02251b526c0..a0908d4653a 100644 --- a/arch/arm/mm/abort-ev5t.S +++ b/arch/arm/mm/abort-ev5t.S @@ -4,14 +4,11 @@  /*   * Function: v5t_early_abort   * - * Params  : r2 = address of aborted instruction - *         : r3 = saved SPSR + * Params  : r2 = pt_regs + *	   : r4 = aborted context pc + *	   : r5 = aborted context psr   * - * Returns : r0 = address of abort - *	   : r1 = FSR, bit 11 = write - *	   : r2-r8 = corrupted - *	   : r9 = preserved - *	   : sp = pointer to registers + * Returns : r4 - r11, r13 preserved   *   * Purpose : obtain information about current aborted instruction.   * Note: we read user space.  This means we might cause a data @@ -22,10 +19,10 @@  ENTRY(v5t_early_abort)  	mrc	p15, 0, r1, c5, c0, 0		@ get FSR  	mrc	p15, 0, r0, c6, c0, 0		@ get FAR -	do_thumb_abort -	ldreq	r3, [r2]			@ read aborted ARM instruction +	do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3 +	ldreq	r3, [r4]			@ read aborted ARM instruction  	bic	r1, r1, #1 << 11		@ clear bits 11 of FSR -	do_ldrd_abort +	do_ldrd_abort tmp=ip, insn=r3  	tst	r3, #1 << 20			@ check write  	orreq	r1, r1, #1 << 11 -	mov	pc, lr +	b	do_DataAbort diff --git a/arch/arm/mm/abort-ev5tj.S b/arch/arm/mm/abort-ev5tj.S index bce68d601c8..4006b7a6126 100644 --- a/arch/arm/mm/abort-ev5tj.S +++ b/arch/arm/mm/abort-ev5tj.S @@ -4,14 +4,11 @@  /*   * Function: v5tj_early_abort   * - * Params  : r2 = address of aborted instruction - *         : r3 = saved SPSR + * Params  : r2 = pt_regs + *	   : r4 = aborted context pc + *	   : r5 = aborted context psr   * - * Returns : r0 = address of abort - *	   : r1 = FSR, bit 11 = write - *	   : r2-r8 = corrupted - *	   : r9 = preserved - *	   : sp = pointer to registers + * Returns : r4 - r11, r13 preserved   *   * Purpose : obtain information about current aborted instruction.   * Note: we read user space.  This means we might cause a data @@ -23,13 +20,11 @@ ENTRY(v5tj_early_abort)  	mrc	p15, 0, r1, c5, c0, 0		@ get FSR  	mrc	p15, 0, r0, c6, c0, 0		@ get FAR  	bic	r1, r1, #1 << 11 | 1 << 10	@ clear bits 11 and 10 of FSR -	tst	r3, #PSR_J_BIT			@ Java? -	movne	pc, lr -	do_thumb_abort -	ldreq	r3, [r2]			@ read aborted ARM instruction -	do_ldrd_abort +	tst	r5, #PSR_J_BIT			@ Java? +	bne	do_DataAbort +	do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3 +	ldreq	r3, [r4]			@ read aborted ARM instruction +	do_ldrd_abort tmp=ip, insn=r3  	tst	r3, #1 << 20			@ L = 0 -> write  	orreq	r1, r1, #1 << 11		@ yes. -	mov	pc, lr - - +	b	do_DataAbort diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S index 1478aa52214..ff1f7cc11f8 100644 --- a/arch/arm/mm/abort-ev6.S +++ b/arch/arm/mm/abort-ev6.S @@ -4,14 +4,11 @@  /*   * Function: v6_early_abort   * - * Params  : r2 = address of aborted instruction - *         : r3 = saved SPSR + * Params  : r2 = pt_regs + *	   : r4 = aborted context pc + *	   : r5 = aborted context psr   * - * Returns : r0 = address of abort - *	   : r1 = FSR, bit 11 = write - *	   : r2-r8 = corrupted - *	   : r9 = preserved - *	   : sp = pointer to registers + * Returns : r4 - r11, r13 preserved   *   * Purpose : obtain information about current aborted instruction.   * Note: we read user space.  This means we might cause a data @@ -33,16 +30,14 @@ ENTRY(v6_early_abort)   * The test below covers all the write situations, including Java bytecodes   */  	bic	r1, r1, #1 << 11		@ clear bit 11 of FSR -	tst	r3, #PSR_J_BIT			@ Java? -	movne	pc, lr -	do_thumb_abort -	ldreq	r3, [r2]			@ read aborted ARM instruction +	tst	r5, #PSR_J_BIT			@ Java? +	bne	do_DataAbort +	do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3 +	ldreq	r3, [r4]			@ read aborted ARM instruction  #ifdef CONFIG_CPU_ENDIAN_BE8  	reveq	r3, r3  #endif -	do_ldrd_abort +	do_ldrd_abort tmp=ip, insn=r3  	tst	r3, #1 << 20			@ L = 0 -> write  	orreq	r1, r1, #1 << 11		@ yes. -	mov	pc, lr - - +	b	do_DataAbort diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S index ec88b157d3b..703375277ba 100644 --- a/arch/arm/mm/abort-ev7.S +++ b/arch/arm/mm/abort-ev7.S @@ -3,14 +3,11 @@  /*   * Function: v7_early_abort   * - * Params  : r2 = address of aborted instruction - *         : r3 = saved SPSR + * Params  : r2 = pt_regs + *	   : r4 = aborted context pc + *	   : r5 = aborted context psr   * - * Returns : r0 = address of abort - *	   : r1 = FSR, bit 11 = write - *	   : r2-r8 = corrupted - *	   : r9 = preserved - *	   : sp = pointer to registers + * Returns : r4 - r11, r13 preserved   *   * Purpose : obtain information about current aborted instruction.   */ @@ -37,18 +34,18 @@ ENTRY(v7_early_abort)  	ldr	r3, =0x40d			@ On permission fault  	and	r3, r1, r3  	cmp	r3, #0x0d -	movne	pc, lr +	bne	do_DataAbort  	mcr	p15, 0, r0, c7, c8, 0   	@ Retranslate FAR  	isb -	mrc	p15, 0, r2, c7, c4, 0   	@ Read the PAR -	and	r3, r2, #0x7b   		@ On translation fault +	mrc	p15, 0, ip, c7, c4, 0   	@ Read the PAR +	and	r3, ip, #0x7b   		@ On translation fault  	cmp	r3, #0x0b -	movne	pc, lr +	bne	do_DataAbort  	bic	r1, r1, #0xf			@ Fix up FSR FS[5:0] -	and	r2, r2, #0x7e -	orr	r1, r1, r2, LSR #1 +	and	ip, ip, #0x7e +	orr	r1, r1, ip, LSR #1  #endif -	mov	pc, lr +	b	do_DataAbort  ENDPROC(v7_early_abort) diff --git a/arch/arm/mm/abort-lv4t.S b/arch/arm/mm/abort-lv4t.S index 9fb7b0e25ea..f3982580c27 100644 --- a/arch/arm/mm/abort-lv4t.S +++ b/arch/arm/mm/abort-lv4t.S @@ -3,14 +3,11 @@  /*   * Function: v4t_late_abort   * - * Params  : r2 = address of aborted instruction - *         : r3 = saved SPSR + * Params  : r2 = pt_regs + *	   : r4 = aborted context pc + *	   : r5 = aborted context psr   * - * Returns : r0 = address of abort - *	   : r1 = FSR, bit 11 = write - *	   : r2-r8 = corrupted - *	   : r9 = preserved - *	   : sp = pointer to registers + * Returns : r4-r5, r10-r11, r13 preserved   *   * Purpose : obtain information about current aborted instruction.   * Note: we read user space.  This means we might cause a data @@ -18,7 +15,7 @@   * picture.  Unfortunately, this does happen.  We live with it.   */  ENTRY(v4t_late_abort) -	tst	r3, #PSR_T_BIT			@ check for thumb mode +	tst	r5, #PSR_T_BIT			@ check for thumb mode  #ifdef CONFIG_CPU_CP15_MMU  	mrc	p15, 0, r1, c5, c0, 0		@ get FSR  	mrc	p15, 0, r0, c6, c0, 0		@ get FAR @@ -28,7 +25,7 @@ ENTRY(v4t_late_abort)  	mov	r1, #0  #endif  	bne	.data_thumb_abort -	ldr	r8, [r2]			@ read arm instruction +	ldr	r8, [r4]			@ read arm instruction  	tst	r8, #1 << 20			@ L = 1 -> write?  	orreq	r1, r1, #1 << 11		@ yes.  	and	r7, r8, #15 << 24 @@ -47,86 +44,84 @@ ENTRY(v4t_late_abort)  /* 9 */	b	.data_arm_ldmstm		@ ldm*b	rn, <rlist>  /* a */	b	.data_unknown  /* b */	b	.data_unknown -/* c */	mov	pc, lr				@ ldc	rd, [rn], #m	@ Same as ldr	rd, [rn], #m -/* d */	mov	pc, lr				@ ldc	rd, [rn, #m] +/* c */	b	do_DataAbort			@ ldc	rd, [rn], #m	@ Same as ldr	rd, [rn], #m +/* d */	b	do_DataAbort			@ ldc	rd, [rn, #m]  /* e */	b	.data_unknown  /* f */  .data_unknown:	@ Part of jumptable -	mov	r0, r2 +	mov	r0, r4  	mov	r1, r8 -	mov	r2, sp -	bl	baddataabort -	b	ret_from_exception +	b	baddataabort  .data_arm_ldmstm:  	tst	r8, #1 << 21			@ check writeback bit -	moveq	pc, lr				@ no writeback -> no fixup +	beq	do_DataAbort			@ no writeback -> no fixup  	mov	r7, #0x11  	orr	r7, r7, #0x1100  	and	r6, r8, r7 -	and	r2, r8, r7, lsl #1 -	add	r6, r6, r2, lsr #1 -	and	r2, r8, r7, lsl #2 -	add	r6, r6, r2, lsr #2 -	and	r2, r8, r7, lsl #3 -	add	r6, r6, r2, lsr #3 +	and	r9, r8, r7, lsl #1 +	add	r6, r6, r9, lsr #1 +	and	r9, r8, r7, lsl #2 +	add	r6, r6, r9, lsr #2 +	and	r9, r8, r7, lsl #3 +	add	r6, r6, r9, lsr #3  	add	r6, r6, r6, lsr #8  	add	r6, r6, r6, lsr #4  	and	r6, r6, #15			@ r6 = no. of registers to transfer. -	and	r5, r8, #15 << 16		@ Extract 'n' from instruction -	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn' +	and	r9, r8, #15 << 16		@ Extract 'n' from instruction +	ldr	r7, [r2, r9, lsr #14]		@ Get register 'Rn'  	tst	r8, #1 << 23			@ Check U bit  	subne	r7, r7, r6, lsl #2		@ Undo increment  	addeq	r7, r7, r6, lsl #2		@ Undo decrement -	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn' -	mov	pc, lr +	str	r7, [r2, r9, lsr #14]		@ Put register 'Rn' +	b	do_DataAbort  .data_arm_lateldrhpre:  	tst	r8, #1 << 21			@ Check writeback bit -	moveq	pc, lr				@ No writeback -> no fixup +	beq	do_DataAbort			@ No writeback -> no fixup  .data_arm_lateldrhpost: -	and	r5, r8, #0x00f			@ get Rm / low nibble of immediate value +	and	r9, r8, #0x00f			@ get Rm / low nibble of immediate value  	tst	r8, #1 << 22			@ if (immediate offset)  	andne	r6, r8, #0xf00			@ { immediate high nibble -	orrne	r6, r5, r6, lsr #4		@   combine nibbles } else -	ldreq	r6, [sp, r5, lsl #2]		@ { load Rm value } +	orrne	r6, r9, r6, lsr #4		@   combine nibbles } else +	ldreq	r6, [r2, r9, lsl #2]		@ { load Rm value }  .data_arm_apply_r6_and_rn: -	and	r5, r8, #15 << 16		@ Extract 'n' from instruction -	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn' +	and	r9, r8, #15 << 16		@ Extract 'n' from instruction +	ldr	r7, [r2, r9, lsr #14]		@ Get register 'Rn'  	tst	r8, #1 << 23			@ Check U bit  	subne	r7, r7, r6			@ Undo incrmenet  	addeq	r7, r7, r6			@ Undo decrement -	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn' -	mov	pc, lr +	str	r7, [r2, r9, lsr #14]		@ Put register 'Rn' +	b	do_DataAbort  .data_arm_lateldrpreconst:  	tst	r8, #1 << 21			@ check writeback bit -	moveq	pc, lr				@ no writeback -> no fixup +	beq	do_DataAbort			@ no writeback -> no fixup  .data_arm_lateldrpostconst: -	movs	r2, r8, lsl #20			@ Get offset -	moveq	pc, lr				@ zero -> no fixup -	and	r5, r8, #15 << 16		@ Extract 'n' from instruction -	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn' +	movs	r6, r8, lsl #20			@ Get offset +	beq	do_DataAbort			@ zero -> no fixup +	and	r9, r8, #15 << 16		@ Extract 'n' from instruction +	ldr	r7, [r2, r9, lsr #14]		@ Get register 'Rn'  	tst	r8, #1 << 23			@ Check U bit -	subne	r7, r7, r2, lsr #20		@ Undo increment -	addeq	r7, r7, r2, lsr #20		@ Undo decrement -	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn' -	mov	pc, lr +	subne	r7, r7, r6, lsr #20		@ Undo increment +	addeq	r7, r7, r6, lsr #20		@ Undo decrement +	str	r7, [r2, r9, lsr #14]		@ Put register 'Rn' +	b	do_DataAbort  .data_arm_lateldrprereg:  	tst	r8, #1 << 21			@ check writeback bit -	moveq	pc, lr				@ no writeback -> no fixup +	beq	do_DataAbort			@ no writeback -> no fixup  .data_arm_lateldrpostreg:  	and	r7, r8, #15			@ Extract 'm' from instruction -	ldr	r6, [sp, r7, lsl #2]		@ Get register 'Rm' -	mov	r5, r8, lsr #7			@ get shift count -	ands	r5, r5, #31 +	ldr	r6, [r2, r7, lsl #2]		@ Get register 'Rm' +	mov	r9, r8, lsr #7			@ get shift count +	ands	r9, r9, #31  	and	r7, r8, #0x70			@ get shift type  	orreq	r7, r7, #8			@ shift count = 0  	add	pc, pc, r7  	nop -	mov	r6, r6, lsl r5			@ 0: LSL #!0 +	mov	r6, r6, lsl r9			@ 0: LSL #!0  	b	.data_arm_apply_r6_and_rn  	b	.data_arm_apply_r6_and_rn	@ 1: LSL #0  	nop @@ -134,7 +129,7 @@ ENTRY(v4t_late_abort)  	nop  	b	.data_unknown			@ 3: MUL?  	nop -	mov	r6, r6, lsr r5			@ 4: LSR #!0 +	mov	r6, r6, lsr r9			@ 4: LSR #!0  	b	.data_arm_apply_r6_and_rn  	mov	r6, r6, lsr #32			@ 5: LSR #32  	b	.data_arm_apply_r6_and_rn @@ -142,7 +137,7 @@ ENTRY(v4t_late_abort)  	nop  	b	.data_unknown			@ 7: MUL?  	nop -	mov	r6, r6, asr r5			@ 8: ASR #!0 +	mov	r6, r6, asr r9			@ 8: ASR #!0  	b	.data_arm_apply_r6_and_rn  	mov	r6, r6, asr #32			@ 9: ASR #32  	b	.data_arm_apply_r6_and_rn @@ -150,7 +145,7 @@ ENTRY(v4t_late_abort)  	nop  	b	.data_unknown			@ B: MUL?  	nop -	mov	r6, r6, ror r5			@ C: ROR #!0 +	mov	r6, r6, ror r9			@ C: ROR #!0  	b	.data_arm_apply_r6_and_rn  	mov	r6, r6, rrx			@ D: RRX  	b	.data_arm_apply_r6_and_rn @@ -159,7 +154,7 @@ ENTRY(v4t_late_abort)  	b	.data_unknown			@ F: MUL?  .data_thumb_abort: -	ldrh	r8, [r2]			@ read instruction +	ldrh	r8, [r4]			@ read instruction  	tst	r8, #1 << 11			@ L = 1 -> write?  	orreq	r1, r1, #1 << 8			@ yes  	and	r7, r8, #15 << 12 @@ -172,10 +167,10 @@ ENTRY(v4t_late_abort)  /* 3 */	b	.data_unknown  /* 4 */	b	.data_unknown  /* 5 */	b	.data_thumb_reg -/* 6 */	mov	pc, lr -/* 7 */	mov	pc, lr -/* 8 */	mov	pc, lr -/* 9 */	mov	pc, lr +/* 6 */	b	do_DataAbort +/* 7 */	b	do_DataAbort +/* 8 */	b	do_DataAbort +/* 9 */	b	do_DataAbort  /* A */	b	.data_unknown  /* B */	b	.data_thumb_pushpop  /* C */	b	.data_thumb_ldmstm @@ -185,41 +180,41 @@ ENTRY(v4t_late_abort)  .data_thumb_reg:  	tst	r8, #1 << 9 -	moveq	pc, lr +	beq	do_DataAbort  	tst	r8, #1 << 10			@ If 'S' (signed) bit is set  	movne	r1, #0				@ it must be a load instr -	mov	pc, lr +	b	do_DataAbort  .data_thumb_pushpop:  	tst	r8, #1 << 10  	beq	.data_unknown  	and	r6, r8, #0x55			@ hweight8(r8) + R bit -	and	r2, r8, #0xaa -	add	r6, r6, r2, lsr #1 -	and	r2, r6, #0xcc +	and	r9, r8, #0xaa +	add	r6, r6, r9, lsr #1 +	and	r9, r6, #0xcc  	and	r6, r6, #0x33 -	add	r6, r6, r2, lsr #2 +	add	r6, r6, r9, lsr #2  	movs	r7, r8, lsr #9			@ C = r8 bit 8 (R bit)  	adc	r6, r6, r6, lsr #4		@ high + low nibble + R bit  	and	r6, r6, #15			@ number of regs to transfer -	ldr	r7, [sp, #13 << 2] +	ldr	r7, [r2, #13 << 2]  	tst	r8, #1 << 11  	addeq	r7, r7, r6, lsl #2		@ increment SP if PUSH  	subne	r7, r7, r6, lsl #2		@ decrement SP if POP -	str	r7, [sp, #13 << 2] -	mov	pc, lr +	str	r7, [r2, #13 << 2] +	b	do_DataAbort  .data_thumb_ldmstm:  	and	r6, r8, #0x55			@ hweight8(r8) -	and	r2, r8, #0xaa -	add	r6, r6, r2, lsr #1 -	and	r2, r6, #0xcc +	and	r9, r8, #0xaa +	add	r6, r6, r9, lsr #1 +	and	r9, r6, #0xcc  	and	r6, r6, #0x33 -	add	r6, r6, r2, lsr #2 +	add	r6, r6, r9, lsr #2  	add	r6, r6, r6, lsr #4 -	and	r5, r8, #7 << 8 -	ldr	r7, [sp, r5, lsr #6] +	and	r9, r8, #7 << 8 +	ldr	r7, [r2, r9, lsr #6]  	and	r6, r6, #15			@ number of regs to transfer  	sub	r7, r7, r6, lsl #2		@ always decrement -	str	r7, [sp, r5, lsr #6] -	mov	pc, lr +	str	r7, [r2, r9, lsr #6] +	b	do_DataAbort diff --git a/arch/arm/mm/abort-macro.S b/arch/arm/mm/abort-macro.S index d7cb1bfa51a..52162d59407 100644 --- a/arch/arm/mm/abort-macro.S +++ b/arch/arm/mm/abort-macro.S @@ -9,34 +9,32 @@   *   */ -	.macro	do_thumb_abort -	tst	r3, #PSR_T_BIT +	.macro	do_thumb_abort, fsr, pc, psr, tmp +	tst	\psr, #PSR_T_BIT  	beq	not_thumb -	ldrh	r3, [r2]			@ Read aborted Thumb instruction -	and	r3, r3, # 0xfe00		@ Mask opcode field -	cmp	r3, # 0x5600			@ Is it ldrsb? -	orreq	r3, r3, #1 << 11		@ Set L-bit if yes -	tst	r3, #1 << 11			@ L = 0 -> write -	orreq	r1, r1, #1 << 11		@ yes. -	mov	pc, lr +	ldrh	\tmp, [\pc]			@ Read aborted Thumb instruction +	and	\tmp, \tmp, # 0xfe00		@ Mask opcode field +	cmp	\tmp, # 0x5600			@ Is it ldrsb? +	orreq	\tmp, \tmp, #1 << 11		@ Set L-bit if yes +	tst	\tmp, #1 << 11			@ L = 0 -> write +	orreq	\psr, \psr, #1 << 11		@ yes. +	b	do_DataAbort  not_thumb:  	.endm  /* - * We check for the following insturction encoding for LDRD. + * We check for the following instruction encoding for LDRD.   * - * [27:25] == 0 + * [27:25] == 000   *   [7:4] == 1101   *    [20] == 0   */ - 	.macro	do_ldrd_abort - 	tst	r3, #0x0e000000			@ [27:25] == 0 +	.macro	do_ldrd_abort, tmp, insn +	tst	\insn, #0x0e100000		@ [27:25,20] == 0  	bne	not_ldrd -	and	r2, r3, #0x000000f0		@ [7:4] == 1101 -	cmp	r2, #0x000000d0 -	bne	not_ldrd -	tst	r3, #1 << 20			@ [20] == 0 -	moveq	pc, lr +	and	\tmp, \insn, #0x000000f0	@ [7:4] == 1101 +	cmp	\tmp, #0x000000d0 +	beq	do_DataAbort  not_ldrd:  	.endm diff --git a/arch/arm/mm/abort-nommu.S b/arch/arm/mm/abort-nommu.S index 625e580945b..119cb479c2a 100644 --- a/arch/arm/mm/abort-nommu.S +++ b/arch/arm/mm/abort-nommu.S @@ -3,11 +3,11 @@  /*   * Function: nommu_early_abort   * - * Params  : r2 = address of aborted instruction - *         : r3 = saved SPSR + * Params  : r2 = pt_regs + *	   : r4 = aborted context pc + *	   : r5 = aborted context psr   * - * Returns : r0 = 0 (abort address) - *	   : r1 = 0 (FSR) + * Returns : r4 - r11, r13 preserved   *   * Note: There is no FSR/FAR on !CPU_CP15_MMU cores.   *       Just fill zero into the registers. @@ -16,5 +16,5 @@  ENTRY(nommu_early_abort)  	mov	r0, #0				@ clear r0, r1 (no FSR/FAR)  	mov	r1, #0 -	mov	pc, lr +	b	do_DataAbort  ENDPROC(nommu_early_abort) diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 724ba3bce72..be7c638b648 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -727,6 +727,9 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)  	int isize = 4;  	int thumb2_32b = 0; +	if (interrupts_enabled(regs)) +		local_irq_enable(); +  	instrptr = instruction_pointer(regs);  	fs = get_fs(); diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c index bdba6c65c90..63cca009713 100644 --- a/arch/arm/mm/copypage-v6.c +++ b/arch/arm/mm/copypage-v6.c @@ -41,7 +41,6 @@ static void v6_copy_user_highpage_nonaliasing(struct page *to,  	kfrom = kmap_atomic(from, KM_USER0);  	kto = kmap_atomic(to, KM_USER1);  	copy_page(kto, kfrom); -	__cpuc_flush_dcache_area(kto, PAGE_SIZE);  	kunmap_atomic(kto, KM_USER1);  	kunmap_atomic(kfrom, KM_USER0);  } diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index bc0e1d88fd3..55657c222d7 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -94,7 +94,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr)  		pud = pud_offset(pgd, addr);  		if (PTRS_PER_PUD != 1) -			printk(", *pud=%08lx", pud_val(*pud)); +			printk(", *pud=%08llx", (long long)pud_val(*pud));  		if (pud_none(*pud))  			break; @@ -285,6 +285,10 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)  	tsk = current;  	mm  = tsk->mm; +	/* Enable interrupts if they were enabled in the parent context. */ +	if (interrupts_enabled(regs)) +		local_irq_enable(); +  	/*  	 * If we're in an interrupt or have no user  	 * context, we must not take the fault.. diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 90a38c6baca..2fee782077c 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -434,6 +434,17 @@ static inline int free_area(unsigned long pfn, unsigned long end, char *s)  	return pages;  } +/* + * Poison init memory with an undefined instruction (ARM) or a branch to an + * undefined instruction (Thumb). + */ +static inline void poison_init_mem(void *s, size_t count) +{ +	u32 *p = (u32 *)s; +	while ((count = count - 4)) +		*p++ = 0xe7fddef0; +} +  static inline void  free_memmap(unsigned long start_pfn, unsigned long end_pfn)  { @@ -651,8 +662,8 @@ void __init mem_init(void)  			"    pkmap   : 0x%08lx - 0x%08lx   (%4ld MB)\n"  #endif  			"    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n" -			"      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"  			"      .text : 0x%p" " - 0x%p" "   (%4d kB)\n" +			"      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"  			"      .data : 0x%p" " - 0x%p" "   (%4d kB)\n"  			"       .bss : 0x%p" " - 0x%p" "   (%4d kB)\n", @@ -674,8 +685,8 @@ void __init mem_init(void)  #endif  			MLM(MODULES_VADDR, MODULES_END), -			MLK_ROUNDUP(__init_begin, __init_end),  			MLK_ROUNDUP(_text, _etext), +			MLK_ROUNDUP(__init_begin, __init_end),  			MLK_ROUNDUP(_sdata, _edata),  			MLK_ROUNDUP(__bss_start, __bss_stop)); @@ -716,11 +727,13 @@ void free_initmem(void)  #ifdef CONFIG_HAVE_TCM  	extern char __tcm_start, __tcm_end; +	poison_init_mem(&__tcm_start, &__tcm_end - &__tcm_start);  	totalram_pages += free_area(__phys_to_pfn(__pa(&__tcm_start)),  				    __phys_to_pfn(__pa(&__tcm_end)),  				    "TCM link");  #endif +	poison_init_mem(__init_begin, __init_end - __init_begin);  	if (!machine_is_integrator() && !machine_is_cintegrator())  		totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)),  					    __phys_to_pfn(__pa(__init_end)), @@ -733,10 +746,12 @@ static int keep_initrd;  void free_initrd_mem(unsigned long start, unsigned long end)  { -	if (!keep_initrd) +	if (!keep_initrd) { +		poison_init_mem((void *)start, PAGE_ALIGN(end) - start);  		totalram_pages += free_area(__phys_to_pfn(__pa(start)),  					    __phys_to_pfn(__pa(end)),  					    "initrd"); +	}  }  static int __init keepinitrd_setup(char *__unused) diff --git a/arch/arm/mm/pabort-legacy.S b/arch/arm/mm/pabort-legacy.S index 87970eba88e..8bbff025269 100644 --- a/arch/arm/mm/pabort-legacy.S +++ b/arch/arm/mm/pabort-legacy.S @@ -4,16 +4,18 @@  /*   * Function: legacy_pabort   * - * Params  : r0 = address of aborted instruction + * Params  : r2 = pt_regs + *	   : r4 = address of aborted instruction + *	   : r5 = psr for parent context   * - * Returns : r0 = address of abort - *	   : r1 = Simulated IFSR with section translation fault status + * Returns : r4 - r11, r13 preserved   *   * Purpose : obtain information about current prefetch abort.   */  	.align	5  ENTRY(legacy_pabort) +	mov	r0, r4  	mov	r1, #5 -	mov	pc, lr +	b	do_PrefetchAbort  ENDPROC(legacy_pabort) diff --git a/arch/arm/mm/pabort-v6.S b/arch/arm/mm/pabort-v6.S index 06e3d1ef211..9627646ce78 100644 --- a/arch/arm/mm/pabort-v6.S +++ b/arch/arm/mm/pabort-v6.S @@ -4,16 +4,18 @@  /*   * Function: v6_pabort   * - * Params  : r0 = address of aborted instruction + * Params  : r2 = pt_regs + *	   : r4 = address of aborted instruction + *	   : r5 = psr for parent context   * - * Returns : r0 = address of abort - *	   : r1 = IFSR + * Returns : r4 - r11, r13 preserved   *   * Purpose : obtain information about current prefetch abort.   */  	.align	5  ENTRY(v6_pabort) +	mov	r0, r4  	mrc	p15, 0, r1, c5, c0, 1		@ get IFSR -	mov	pc, lr +	b	do_PrefetchAbort  ENDPROC(v6_pabort) diff --git a/arch/arm/mm/pabort-v7.S b/arch/arm/mm/pabort-v7.S index a8b3b300a18..875761f44f3 100644 --- a/arch/arm/mm/pabort-v7.S +++ b/arch/arm/mm/pabort-v7.S @@ -2,12 +2,13 @@  #include <asm/assembler.h>  /* - * Function: v6_pabort + * Function: v7_pabort   * - * Params  : r0 = address of aborted instruction + * Params  : r2 = pt_regs + *	   : r4 = address of aborted instruction + *	   : r5 = psr for parent context   * - * Returns : r0 = address of abort - *	   : r1 = IFSR + * Returns : r4 - r11, r13 preserved   *   * Purpose : obtain information about current prefetch abort.   */ @@ -16,5 +17,5 @@  ENTRY(v7_pabort)  	mrc	p15, 0, r0, c6, c0, 2		@ get IFAR  	mrc	p15, 0, r1, c5, c0, 1		@ get IFSR -	mov	pc, lr +	b	do_PrefetchAbort  ENDPROC(v7_pabort) diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S index ebc0ca7f1a1..e5b974cddac 100644 --- a/arch/arm/mm/proc-arm6_7.S +++ b/arch/arm/mm/proc-arm6_7.S @@ -29,19 +29,19 @@ ENTRY(cpu_arm7_dcache_clean_area)  /*   * Function: arm6_7_data_abort ()   * - * Params  : r2 = address of aborted instruction - *	   : sp = pointer to registers + * Params  : r2 = pt_regs + *	   : r4 = aborted context pc + *	   : r5 = aborted context psr   *   * Purpose : obtain information about current aborted instruction   * - * Returns : r0 = address of abort - *	   : r1 = FSR + * Returns : r4-r5, r10-r11, r13 preserved   */  ENTRY(cpu_arm7_data_abort)  	mrc	p15, 0, r1, c5, c0, 0		@ get FSR  	mrc	p15, 0, r0, c6, c0, 0		@ get FAR -	ldr	r8, [r2]			@ read arm instruction +	ldr	r8, [r4]			@ read arm instruction  	tst	r8, #1 << 20			@ L = 0 -> write?  	orreq	r1, r1, #1 << 11		@ yes.  	and	r7, r8, #15 << 24 @@ -49,7 +49,7 @@ ENTRY(cpu_arm7_data_abort)  	nop  /* 0 */	b	.data_unknown -/* 1 */	mov	pc, lr				@ swp +/* 1 */	b	do_DataAbort			@ swp  /* 2 */	b	.data_unknown  /* 3 */	b	.data_unknown  /* 4 */	b	.data_arm_lateldrpostconst	@ ldr	rd, [rn], #m @@ -60,87 +60,85 @@ ENTRY(cpu_arm7_data_abort)  /* 9 */	b	.data_arm_ldmstm		@ ldm*b	rn, <rlist>  /* a */	b	.data_unknown  /* b */	b	.data_unknown -/* c */	mov	pc, lr				@ ldc	rd, [rn], #m	@ Same as ldr	rd, [rn], #m -/* d */	mov	pc, lr				@ ldc	rd, [rn, #m] +/* c */	b	do_DataAbort			@ ldc	rd, [rn], #m	@ Same as ldr	rd, [rn], #m +/* d */	b	do_DataAbort			@ ldc	rd, [rn, #m]  /* e */	b	.data_unknown  /* f */  .data_unknown:	@ Part of jumptable -	mov	r0, r2 +	mov	r0, r4  	mov	r1, r8 -	mov	r2, sp -	bl	baddataabort -	b	ret_from_exception +	b	baddataabort  ENTRY(cpu_arm6_data_abort)  	mrc	p15, 0, r1, c5, c0, 0		@ get FSR  	mrc	p15, 0, r0, c6, c0, 0		@ get FAR -	ldr	r8, [r2]			@ read arm instruction +	ldr	r8, [r4]			@ read arm instruction  	tst	r8, #1 << 20			@ L = 0 -> write?  	orreq	r1, r1, #1 << 11		@ yes.  	and	r7, r8, #14 << 24  	teq	r7, #8 << 24			@ was it ldm/stm -	movne	pc, lr +	bne	do_DataAbort  .data_arm_ldmstm:  	tst	r8, #1 << 21			@ check writeback bit -	moveq	pc, lr				@ no writeback -> no fixup +	beq	do_DataAbort			@ no writeback -> no fixup  	mov	r7, #0x11  	orr	r7, r7, #0x1100  	and	r6, r8, r7 -	and	r2, r8, r7, lsl #1 -	add	r6, r6, r2, lsr #1 -	and	r2, r8, r7, lsl #2 -	add	r6, r6, r2, lsr #2 -	and	r2, r8, r7, lsl #3 -	add	r6, r6, r2, lsr #3 +	and	r9, r8, r7, lsl #1 +	add	r6, r6, r9, lsr #1 +	and	r9, r8, r7, lsl #2 +	add	r6, r6, r9, lsr #2 +	and	r9, r8, r7, lsl #3 +	add	r6, r6, r9, lsr #3  	add	r6, r6, r6, lsr #8  	add	r6, r6, r6, lsr #4  	and	r6, r6, #15			@ r6 = no. of registers to transfer. -	and	r5, r8, #15 << 16		@ Extract 'n' from instruction -	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn' +	and	r9, r8, #15 << 16		@ Extract 'n' from instruction +	ldr	r7, [r2, r9, lsr #14]		@ Get register 'Rn'  	tst	r8, #1 << 23			@ Check U bit  	subne	r7, r7, r6, lsl #2		@ Undo increment  	addeq	r7, r7, r6, lsl #2		@ Undo decrement -	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn' -	mov	pc, lr +	str	r7, [r2, r9, lsr #14]		@ Put register 'Rn' +	b	do_DataAbort  .data_arm_apply_r6_and_rn: -	and	r5, r8, #15 << 16		@ Extract 'n' from instruction -	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn' +	and	r9, r8, #15 << 16		@ Extract 'n' from instruction +	ldr	r7, [r2, r9, lsr #14]		@ Get register 'Rn'  	tst	r8, #1 << 23			@ Check U bit  	subne	r7, r7, r6			@ Undo incrmenet  	addeq	r7, r7, r6			@ Undo decrement -	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn' -	mov	pc, lr +	str	r7, [r2, r9, lsr #14]		@ Put register 'Rn' +	b	do_DataAbort  .data_arm_lateldrpreconst:  	tst	r8, #1 << 21			@ check writeback bit -	moveq	pc, lr				@ no writeback -> no fixup +	beq	do_DataAbort			@ no writeback -> no fixup  .data_arm_lateldrpostconst: -	movs	r2, r8, lsl #20			@ Get offset -	moveq	pc, lr				@ zero -> no fixup -	and	r5, r8, #15 << 16		@ Extract 'n' from instruction -	ldr	r7, [sp, r5, lsr #14]		@ Get register 'Rn' +	movs	r6, r8, lsl #20			@ Get offset +	beq	do_DataAbort			@ zero -> no fixup +	and	r9, r8, #15 << 16		@ Extract 'n' from instruction +	ldr	r7, [r2, r9, lsr #14]		@ Get register 'Rn'  	tst	r8, #1 << 23			@ Check U bit -	subne	r7, r7, r2, lsr #20		@ Undo increment -	addeq	r7, r7, r2, lsr #20		@ Undo decrement -	str	r7, [sp, r5, lsr #14]		@ Put register 'Rn' -	mov	pc, lr +	subne	r7, r7, r6, lsr #20		@ Undo increment +	addeq	r7, r7, r6, lsr #20		@ Undo decrement +	str	r7, [r2, r9, lsr #14]		@ Put register 'Rn' +	b	do_DataAbort  .data_arm_lateldrprereg:  	tst	r8, #1 << 21			@ check writeback bit -	moveq	pc, lr				@ no writeback -> no fixup +	beq	do_DataAbort			@ no writeback -> no fixup  .data_arm_lateldrpostreg:  	and	r7, r8, #15			@ Extract 'm' from instruction -	ldr	r6, [sp, r7, lsl #2]		@ Get register 'Rm' -	mov	r5, r8, lsr #7			@ get shift count -	ands	r5, r5, #31 +	ldr	r6, [r2, r7, lsl #2]		@ Get register 'Rm' +	mov	r9, r8, lsr #7			@ get shift count +	ands	r9, r9, #31  	and	r7, r8, #0x70			@ get shift type  	orreq	r7, r7, #8			@ shift count = 0  	add	pc, pc, r7  	nop -	mov	r6, r6, lsl r5			@ 0: LSL #!0 +	mov	r6, r6, lsl r9			@ 0: LSL #!0  	b	.data_arm_apply_r6_and_rn  	b	.data_arm_apply_r6_and_rn	@ 1: LSL #0  	nop @@ -148,7 +146,7 @@ ENTRY(cpu_arm6_data_abort)  	nop  	b	.data_unknown			@ 3: MUL?  	nop -	mov	r6, r6, lsr r5			@ 4: LSR #!0 +	mov	r6, r6, lsr r9			@ 4: LSR #!0  	b	.data_arm_apply_r6_and_rn  	mov	r6, r6, lsr #32			@ 5: LSR #32  	b	.data_arm_apply_r6_and_rn @@ -156,7 +154,7 @@ ENTRY(cpu_arm6_data_abort)  	nop  	b	.data_unknown			@ 7: MUL?  	nop -	mov	r6, r6, asr r5			@ 8: ASR #!0 +	mov	r6, r6, asr r9			@ 8: ASR #!0  	b	.data_arm_apply_r6_and_rn  	mov	r6, r6, asr #32			@ 9: ASR #32  	b	.data_arm_apply_r6_and_rn @@ -164,7 +162,7 @@ ENTRY(cpu_arm6_data_abort)  	nop  	b	.data_unknown			@ B: MUL?  	nop -	mov	r6, r6, ror r5			@ C: ROR #!0 +	mov	r6, r6, ror r9			@ C: ROR #!0  	b	.data_arm_apply_r6_and_rn  	mov	r6, r6, rrx			@ D: RRX  	b	.data_arm_apply_r6_and_rn diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S index e71587852ca..07219c2ae11 100644 --- a/arch/arm/mm/proc-sa1100.S +++ b/arch/arm/mm/proc-sa1100.S @@ -34,7 +34,7 @@   */  #define DCACHELINESIZE	32 -	__INIT +	.section .text  /*   * cpu_sa1100_proc_init() @@ -45,8 +45,6 @@ ENTRY(cpu_sa1100_proc_init)  	mcr	p15, 0, r0, c9, c0, 5		@ Allow read-buffer operations from userland  	mov	pc, lr -	.section .text -  /*   * cpu_sa1100_proc_fin()   * diff --git a/arch/arm/mm/tlb-fa.S b/arch/arm/mm/tlb-fa.S index 7a2e56c5d89..d3ddcf9a76c 100644 --- a/arch/arm/mm/tlb-fa.S +++ b/arch/arm/mm/tlb-fa.S @@ -46,7 +46,6 @@ ENTRY(fa_flush_user_tlb_range)  	add	r0, r0, #PAGE_SZ  	cmp	r0, r1  	blo	1b -	mcr	p15, 0, r3, c7, c5, 6		@ invalidate BTB  	mcr	p15, 0, r3, c7, c10, 4		@ data write barrier  	mov	pc, lr @@ -60,9 +59,8 @@ ENTRY(fa_flush_kern_tlb_range)  	add	r0, r0, #PAGE_SZ  	cmp	r0, r1  	blo	1b -	mcr	p15, 0, r3, c7, c5, 6		@ invalidate BTB  	mcr	p15, 0, r3, c7, c10, 4		@ data write barrier -	mcr	p15, 0, r3, c7, c5, 4		@ prefetch flush +	mcr	p15, 0, r3, c7, c5, 4		@ prefetch flush (isb)  	mov	pc, lr  	__INITDATA diff --git a/arch/arm/mm/tlb-v6.S b/arch/arm/mm/tlb-v6.S index a685944735c..eca07f550a0 100644 --- a/arch/arm/mm/tlb-v6.S +++ b/arch/arm/mm/tlb-v6.S @@ -54,7 +54,6 @@ ENTRY(v6wbi_flush_user_tlb_range)  	add	r0, r0, #PAGE_SZ  	cmp	r0, r1  	blo	1b -	mcr	p15, 0, ip, c7, c5, 6		@ flush BTAC/BTB  	mcr	p15, 0, ip, c7, c10, 4		@ data synchronization barrier  	mov	pc, lr @@ -83,9 +82,8 @@ ENTRY(v6wbi_flush_kern_tlb_range)  	add	r0, r0, #PAGE_SZ  	cmp	r0, r1  	blo	1b -	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB  	mcr	p15, 0, r2, c7, c10, 4		@ data synchronization barrier -	mcr	p15, 0, r2, c7, c5, 4		@ prefetch flush +	mcr	p15, 0, r2, c7, c5, 4		@ prefetch flush (isb)  	mov	pc, lr  	__INIT diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S index ebd4290ce1e..845f461f8ec 100644 --- a/arch/arm/mm/tlb-v7.S +++ b/arch/arm/mm/tlb-v7.S @@ -48,9 +48,6 @@ ENTRY(v7wbi_flush_user_tlb_range)  	add	r0, r0, #PAGE_SZ  	cmp	r0, r1  	blo	1b -	mov	ip, #0 -	ALT_SMP(mcr	p15, 0, ip, c7, c1, 6)	@ flush BTAC/BTB Inner Shareable -	ALT_UP(mcr	p15, 0, ip, c7, c5, 6)	@ flush BTAC/BTB  	dsb  	mov	pc, lr  ENDPROC(v7wbi_flush_user_tlb_range) @@ -75,9 +72,6 @@ ENTRY(v7wbi_flush_kern_tlb_range)  	add	r0, r0, #PAGE_SZ  	cmp	r0, r1  	blo	1b -	mov	r2, #0 -	ALT_SMP(mcr	p15, 0, r2, c7, c1, 6)	@ flush BTAC/BTB Inner Shareable -	ALT_UP(mcr	p15, 0, r2, c7, c5, 6)	@ flush BTAC/BTB  	dsb  	isb  	mov	pc, lr diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S index 2e49e71b1b9..066d464d322 100644 --- a/arch/arm/plat-mxc/include/mach/entry-macro.S +++ b/arch/arm/plat-mxc/include/mach/entry-macro.S @@ -78,7 +78,3 @@  	movs \irqnr, \irqnr  #endif  	.endm - -	@ irq priority table (not used) -	.macro	irq_prio_table -	.endm diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 6af3d0b1f8d..363c91e44ef 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -394,20 +394,15 @@ void omap3_sram_restore_context(void)  }  #endif /* CONFIG_PM */ -static int __init omap34xx_sram_init(void) -{ -	_omap3_sram_configure_core_dpll = -		omap_sram_push(omap3_sram_configure_core_dpll, -			       omap3_sram_configure_core_dpll_sz); -	omap_push_sram_idle(); -	return 0; -} -#else +#endif /* CONFIG_ARCH_OMAP3 */ +  static inline int omap34xx_sram_init(void)  { +#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) +	omap3_sram_restore_context(); +#endif  	return 0;  } -#endif  int __init omap_sram_init(void)  { diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c index 5b4fffab1eb..41ab97ebe4c 100644 --- a/arch/arm/plat-orion/gpio.c +++ b/arch/arm/plat-orion/gpio.c @@ -432,7 +432,7 @@ void __init orion_gpio_init(int gpio_base, int ngpio,  	ct->regs.mask = ochip->mask_offset + GPIO_EDGE_MASK_OFF;  	ct->regs.ack = GPIO_EDGE_CAUSE_OFF;  	ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; -	ct->chip.irq_ack = irq_gc_ack; +	ct->chip.irq_ack = irq_gc_ack_clr_bit;  	ct->chip.irq_mask = irq_gc_mask_clr_bit;  	ct->chip.irq_unmask = irq_gc_mask_set_bit;  	ct->chip.irq_set_type = gpio_irq_set_type; diff --git a/arch/arm/plat-pxa/gpio.c b/arch/arm/plat-pxa/gpio.c index 48ebb9479b6..a11dc367050 100644 --- a/arch/arm/plat-pxa/gpio.c +++ b/arch/arm/plat-pxa/gpio.c @@ -50,7 +50,7 @@ static inline void __iomem *gpio_chip_base(struct gpio_chip *c)  	return container_of(c, struct pxa_gpio_chip, chip)->regbase;  } -static inline struct pxa_gpio_chip *gpio_to_chip(unsigned gpio) +static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio)  {  	return &pxa_gpio_chips[gpio_to_bank(gpio)];  } @@ -161,7 +161,7 @@ static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)  	int gpio = irq_to_gpio(d->irq);  	unsigned long gpdr, mask = GPIO_bit(gpio); -	c = gpio_to_chip(gpio); +	c = gpio_to_pxachip(gpio);  	if (type == IRQ_TYPE_PROBE) {  		/* Don't mess with enabled GPIOs using preconfigured edges or @@ -230,7 +230,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)  static void pxa_ack_muxed_gpio(struct irq_data *d)  {  	int gpio = irq_to_gpio(d->irq); -	struct pxa_gpio_chip *c = gpio_to_chip(gpio); +	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);  	__raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET);  } @@ -238,7 +238,7 @@ static void pxa_ack_muxed_gpio(struct irq_data *d)  static void pxa_mask_muxed_gpio(struct irq_data *d)  {  	int gpio = irq_to_gpio(d->irq); -	struct pxa_gpio_chip *c = gpio_to_chip(gpio); +	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);  	uint32_t grer, gfer;  	c->irq_mask &= ~GPIO_bit(gpio); @@ -252,7 +252,7 @@ static void pxa_mask_muxed_gpio(struct irq_data *d)  static void pxa_unmask_muxed_gpio(struct irq_data *d)  {  	int gpio = irq_to_gpio(d->irq); -	struct pxa_gpio_chip *c = gpio_to_chip(gpio); +	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);  	c->irq_mask |= GPIO_bit(gpio);  	update_edge_detect(c); diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index a79a8ccd25f..539bd0e3def 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -712,7 +712,7 @@ static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);   * get control of an dma channel  */ -int s3c2410_dma_request(unsigned int channel, +int s3c2410_dma_request(enum dma_ch channel,  			struct s3c2410_dma_client *client,  			void *dev)  { @@ -783,7 +783,7 @@ EXPORT_SYMBOL(s3c2410_dma_request);   * allowed to go through.  */ -int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client) +int s3c2410_dma_free(enum dma_ch channel, struct s3c2410_dma_client *client)  {  	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);  	unsigned long flags; @@ -974,7 +974,7 @@ static int s3c2410_dma_started(struct s3c2410_dma_chan *chan)  }  int -s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op) +s3c2410_dma_ctrl(enum dma_ch channel, enum s3c2410_chan_op op)  {  	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); @@ -1021,7 +1021,7 @@ EXPORT_SYMBOL(s3c2410_dma_ctrl);   * xfersize:     size of unit in bytes (1,2,4)  */ -int s3c2410_dma_config(unsigned int channel, +int s3c2410_dma_config(enum dma_ch channel,  		       int xferunit)  {  	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); @@ -1100,7 +1100,7 @@ EXPORT_SYMBOL(s3c2410_dma_config);   * devaddr:   physical address of the source  */ -int s3c2410_dma_devconfig(unsigned int channel, +int s3c2410_dma_devconfig(enum dma_ch channel,  			  enum s3c2410_dmasrc source,  			  unsigned long devaddr)  { @@ -1173,7 +1173,7 @@ EXPORT_SYMBOL(s3c2410_dma_devconfig);   * returns the current transfer points for the dma source and destination  */ -int s3c2410_dma_getposition(unsigned int channel, dma_addr_t *src, dma_addr_t *dst) +int s3c2410_dma_getposition(enum dma_ch channel, dma_addr_t *src, dma_addr_t *dst)  {  	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S index fd7032f84ae..c56612569b4 100644 --- a/arch/arm/plat-s3c24xx/sleep.S +++ b/arch/arm/plat-s3c24xx/sleep.S @@ -41,31 +41,6 @@  	.text -	/* s3c_cpu_save -	 * -	 * entry: -	 *	r1 = v:p offset -	*/ - -ENTRY(s3c_cpu_save) -	stmfd	sp!, { r4 - r12, lr } -	ldr	r3, =resume_with_mmu -	bl	cpu_suspend - -	@@ jump to final code to send system to sleep -	ldr	r0, =pm_cpu_sleep -	@@ldr	pc, [ r0 ] -	ldr	r0, [ r0 ] -	mov	pc, r0 -	 -	@@ return to the caller, after having the MMU -	@@ turned on, this restores the last bits from the -	@@ stack -resume_with_mmu: -	ldmfd	sp!, { r4 - r12, pc } - -	.ltorg -  	/* sleep magic, to allow the bootloader to check for an valid  	 * image to resume to. Must be the first word before the  	 * s3c_cpu_resume entry. diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c index 135abda31c9..327ab9f662e 100644 --- a/arch/arm/plat-s5p/irq-gpioint.c +++ b/arch/arm/plat-s5p/irq-gpioint.c @@ -152,7 +152,7 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)  	if (!gc)  		return -ENOMEM;  	ct = gc->chip_types; -	ct->chip.irq_ack = irq_gc_ack; +	ct->chip.irq_ack = irq_gc_ack_set_bit;  	ct->chip.irq_mask = irq_gc_mask_set_bit;  	ct->chip.irq_unmask = irq_gc_mask_clr_bit;  	ct->chip.irq_set_type = s5p_gpioint_set_type, diff --git a/arch/arm/plat-samsung/dma.c b/arch/arm/plat-samsung/dma.c index cb459dd9545..6143aa14768 100644 --- a/arch/arm/plat-samsung/dma.c +++ b/arch/arm/plat-samsung/dma.c @@ -41,7 +41,7 @@ struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel)   * irq?  */ -int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn) +int s3c2410_dma_set_opfn(enum dma_ch channel, s3c2410_dma_opfn_t rtn)  {  	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); @@ -56,7 +56,7 @@ int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn)  }  EXPORT_SYMBOL(s3c2410_dma_set_opfn); -int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn) +int s3c2410_dma_set_buffdone_fn(enum dma_ch channel, s3c2410_dma_cbfn_t rtn)  {  	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); @@ -71,7 +71,7 @@ int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn)  }  EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn); -int s3c2410_dma_setflags(unsigned int channel, unsigned int flags) +int s3c2410_dma_setflags(enum dma_ch channel, unsigned int flags)  {  	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); diff --git a/arch/arm/plat-samsung/include/plat/dma.h b/arch/arm/plat-samsung/include/plat/dma.h index 2e8f8c6560d..8c273b7a6f5 100644 --- a/arch/arm/plat-samsung/include/plat/dma.h +++ b/arch/arm/plat-samsung/include/plat/dma.h @@ -42,6 +42,7 @@ struct s3c2410_dma_client {  };  struct s3c2410_dma_chan; +enum dma_ch;  /* s3c2410_dma_cbfn_t   * @@ -62,7 +63,7 @@ typedef int  (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,   * request a dma channel exclusivley  */ -extern int s3c2410_dma_request(unsigned int channel, +extern int s3c2410_dma_request(enum dma_ch channel,  			       struct s3c2410_dma_client *, void *dev); @@ -71,14 +72,14 @@ extern int s3c2410_dma_request(unsigned int channel,   * change the state of the dma channel  */ -extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op); +extern int s3c2410_dma_ctrl(enum dma_ch channel, enum s3c2410_chan_op op);  /* s3c2410_dma_setflags   *   * set the channel's flags to a given state  */ -extern int s3c2410_dma_setflags(unsigned int channel, +extern int s3c2410_dma_setflags(enum dma_ch channel,  				unsigned int flags);  /* s3c2410_dma_free @@ -86,7 +87,7 @@ extern int s3c2410_dma_setflags(unsigned int channel,   * free the dma channel (will also abort any outstanding operations)  */ -extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *); +extern int s3c2410_dma_free(enum dma_ch channel, struct s3c2410_dma_client *);  /* s3c2410_dma_enqueue   * @@ -95,7 +96,7 @@ extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *);   * drained before the buffer is given to the DMA system.  */ -extern int s3c2410_dma_enqueue(unsigned int channel, void *id, +extern int s3c2410_dma_enqueue(enum dma_ch channel, void *id,  			       dma_addr_t data, int size);  /* s3c2410_dma_config @@ -103,14 +104,14 @@ extern int s3c2410_dma_enqueue(unsigned int channel, void *id,   * configure the dma channel  */ -extern int s3c2410_dma_config(unsigned int channel, int xferunit); +extern int s3c2410_dma_config(enum dma_ch channel, int xferunit);  /* s3c2410_dma_devconfig   *   * configure the device we're talking to  */ -extern int s3c2410_dma_devconfig(unsigned int channel, +extern int s3c2410_dma_devconfig(enum dma_ch channel,  		enum s3c2410_dmasrc source, unsigned long devaddr);  /* s3c2410_dma_getposition @@ -118,10 +119,10 @@ extern int s3c2410_dma_devconfig(unsigned int channel,   * get the position that the dma transfer is currently at  */ -extern int s3c2410_dma_getposition(unsigned int channel, +extern int s3c2410_dma_getposition(enum dma_ch channel,  				   dma_addr_t *src, dma_addr_t *dest); -extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn); -extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn); +extern int s3c2410_dma_set_opfn(enum dma_ch, s3c2410_dma_opfn_t rtn); +extern int s3c2410_dma_set_buffdone_fn(enum dma_ch, s3c2410_dma_cbfn_t rtn); diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h index 7fb6f6be8c8..f6749916d19 100644 --- a/arch/arm/plat-samsung/include/plat/pm.h +++ b/arch/arm/plat-samsung/include/plat/pm.h @@ -42,7 +42,7 @@ extern unsigned long s3c_irqwake_eintallow;  /* per-cpu sleep functions */  extern void (*pm_cpu_prep)(void); -extern void (*pm_cpu_sleep)(void); +extern int (*pm_cpu_sleep)(unsigned long);  /* Flags for PM Control */ @@ -52,10 +52,9 @@ extern unsigned char pm_uart_udivslot;  /* true to save UART UDIVSLOT */  /* from sleep.S */ -extern int  s3c_cpu_save(unsigned long *saveblk, long);  extern void s3c_cpu_resume(void); -extern void s3c2410_cpu_suspend(void); +extern int s3c2410_cpu_suspend(unsigned long);  /* sleep save info */ diff --git a/arch/arm/plat-samsung/irq-uart.c b/arch/arm/plat-samsung/irq-uart.c index 32582c0958e..657405c481d 100644 --- a/arch/arm/plat-samsung/irq-uart.c +++ b/arch/arm/plat-samsung/irq-uart.c @@ -54,8 +54,15 @@ static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq)  	gc = irq_alloc_generic_chip("s3c-uart", 1, uirq->base_irq, reg_base,  				    handle_level_irq); + +	if (!gc) { +		pr_err("%s: irq_alloc_generic_chip for IRQ %u failed\n", +		       __func__, uirq->base_irq); +		return; +	} +  	ct = gc->chip_types; -	ct->chip.irq_ack = irq_gc_ack; +	ct->chip.irq_ack = irq_gc_ack_set_bit;  	ct->chip.irq_mask = irq_gc_mask_set_bit;  	ct->chip.irq_unmask = irq_gc_mask_clr_bit;  	ct->regs.ack = S3C64XX_UINTP; diff --git a/arch/arm/plat-samsung/irq-vic-timer.c b/arch/arm/plat-samsung/irq-vic-timer.c index a607546ddbd..f714d060370 100644 --- a/arch/arm/plat-samsung/irq-vic-timer.c +++ b/arch/arm/plat-samsung/irq-vic-timer.c @@ -54,6 +54,13 @@ void __init s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq)  	s3c_tgc = irq_alloc_generic_chip("s3c-timer", 1, timer_irq,  					 S3C64XX_TINT_CSTAT, handle_level_irq); + +	if (!s3c_tgc) { +		pr_err("%s: irq_alloc_generic_chip for IRQ %d failed\n", +		       __func__, timer_irq); +		return; +	} +  	ct = s3c_tgc->chip_types;  	ct->chip.irq_mask = irq_gc_mask_clr_bit;  	ct->chip.irq_unmask = irq_gc_mask_set_bit; diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c index 5c0a440d6e1..5fa1742d019 100644 --- a/arch/arm/plat-samsung/pm.c +++ b/arch/arm/plat-samsung/pm.c @@ -20,6 +20,7 @@  #include <linux/io.h>  #include <asm/cacheflush.h> +#include <asm/suspend.h>  #include <mach/hardware.h>  #include <mach/map.h> @@ -231,7 +232,7 @@ static void __maybe_unused s3c_pm_show_resume_irqs(int start,  void (*pm_cpu_prep)(void); -void (*pm_cpu_sleep)(void); +int (*pm_cpu_sleep)(unsigned long);  #define any_allowed(mask, allow) (((mask) & (allow)) != (allow)) @@ -294,15 +295,11 @@ static int s3c_pm_enter(suspend_state_t state)  	s3c_pm_arch_stop_clocks(); -	/* s3c_cpu_save will also act as our return point from when +	/* this will also act as our return point from when  	 * we resume as it saves its own register state and restores it  	 * during the resume.  */ -	s3c_cpu_save(0, PLAT_PHYS_OFFSET - PAGE_OFFSET); - -	/* restore the cpu state using the kernel's cpu init code. */ - -	cpu_init(); +	cpu_suspend(0, pm_cpu_sleep);  	/* restore the system state */ diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index 9897dcfc16d..2d30c7f6edd 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -77,27 +77,27 @@ ENTRY(vfp_support_entry)  	bne	look_for_VFP_exceptions	@ VFP is already enabled  	DBGSTR1 "enable %x", r10 -	ldr	r3, last_VFP_context_address +	ldr	r3, vfp_current_hw_state_address  	orr	r1, r1, #FPEXC_EN	@ user FPEXC has the enable bit set -	ldr	r4, [r3, r11, lsl #2]	@ last_VFP_context pointer +	ldr	r4, [r3, r11, lsl #2]	@ vfp_current_hw_state pointer  	bic	r5, r1, #FPEXC_EX	@ make sure exceptions are disabled -	cmp	r4, r10 -	beq	check_for_exception	@ we are returning to the same -					@ process, so the registers are -					@ still there.  In this case, we do -					@ not want to drop a pending exception. +	cmp	r4, r10			@ this thread owns the hw context? +#ifndef CONFIG_SMP +	@ For UP, checking that this thread owns the hw context is +	@ sufficient to determine that the hardware state is valid. +	beq	vfp_hw_state_valid + +	@ On UP, we lazily save the VFP context.  As a different +	@ thread wants ownership of the VFP hardware, save the old +	@ state if there was a previous (valid) owner.  	VFPFMXR	FPEXC, r5		@ enable VFP, disable any pending  					@ exceptions, so we can get at the  					@ rest of it -#ifndef CONFIG_SMP -	@ Save out the current registers to the old thread state -	@ No need for SMP since this is not done lazily -  	DBGSTR1	"save old state %p", r4 -	cmp	r4, #0 -	beq	no_old_VFP_process +	cmp	r4, #0			@ if the vfp_current_hw_state is NULL +	beq	vfp_reload_hw		@ then the hw state needs reloading  	VFPFSTMIA r4, r5		@ save the working registers  	VFPFMRX	r5, FPSCR		@ current status  #ifndef CONFIG_CPU_FEROCEON @@ -110,13 +110,35 @@ ENTRY(vfp_support_entry)  1:  #endif  	stmia	r4, {r1, r5, r6, r8}	@ save FPEXC, FPSCR, FPINST, FPINST2 -					@ and point r4 at the word at the -					@ start of the register dump +vfp_reload_hw: + +#else +	@ For SMP, if this thread does not own the hw context, then we +	@ need to reload it.  No need to save the old state as on SMP, +	@ we always save the state when we switch away from a thread. +	bne	vfp_reload_hw + +	@ This thread has ownership of the current hardware context. +	@ However, it may have been migrated to another CPU, in which +	@ case the saved state is newer than the hardware context. +	@ Check this by looking at the CPU number which the state was +	@ last loaded onto. +	ldr	ip, [r10, #VFP_CPU] +	teq	ip, r11 +	beq	vfp_hw_state_valid + +vfp_reload_hw: +	@ We're loading this threads state into the VFP hardware. Update +	@ the CPU number which contains the most up to date VFP context. +	str	r11, [r10, #VFP_CPU] + +	VFPFMXR	FPEXC, r5		@ enable VFP, disable any pending +					@ exceptions, so we can get at the +					@ rest of it  #endif -no_old_VFP_process:  	DBGSTR1	"load state %p", r10 -	str	r10, [r3, r11, lsl #2]	@ update the last_VFP_context pointer +	str	r10, [r3, r11, lsl #2]	@ update the vfp_current_hw_state pointer  					@ Load the saved state back into the VFP  	VFPFLDMIA r10, r5		@ reload the working registers while  					@ FPEXC is in a safe state @@ -132,7 +154,8 @@ no_old_VFP_process:  #endif  	VFPFMXR	FPSCR, r5		@ restore status -check_for_exception: +@ The context stored in the VFP hardware is up to date with this thread +vfp_hw_state_valid:  	tst	r1, #FPEXC_EX  	bne	process_exception	@ might as well handle the pending  					@ exception before retrying branch @@ -207,8 +230,8 @@ ENTRY(vfp_save_state)  ENDPROC(vfp_save_state)  	.align -last_VFP_context_address: -	.word	last_VFP_context +vfp_current_hw_state_address: +	.word	vfp_current_hw_state  	.macro	tbl_branch, base, tmp, shift  #ifdef CONFIG_THUMB2_KERNEL diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 650d90be0f9..79bcb431693 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -33,7 +33,6 @@ void vfp_support_entry(void);  void vfp_null_entry(void);  void (*vfp_vector)(void) = vfp_null_entry; -union vfp_state *last_VFP_context[NR_CPUS];  /*   * Dual-use variable. @@ -43,6 +42,46 @@ union vfp_state *last_VFP_context[NR_CPUS];  unsigned int VFP_arch;  /* + * The pointer to the vfpstate structure of the thread which currently + * owns the context held in the VFP hardware, or NULL if the hardware + * context is invalid. + * + * For UP, this is sufficient to tell which thread owns the VFP context. + * However, for SMP, we also need to check the CPU number stored in the + * saved state too to catch migrations. + */ +union vfp_state *vfp_current_hw_state[NR_CPUS]; + +/* + * Is 'thread's most up to date state stored in this CPUs hardware? + * Must be called from non-preemptible context. + */ +static bool vfp_state_in_hw(unsigned int cpu, struct thread_info *thread) +{ +#ifdef CONFIG_SMP +	if (thread->vfpstate.hard.cpu != cpu) +		return false; +#endif +	return vfp_current_hw_state[cpu] == &thread->vfpstate; +} + +/* + * Force a reload of the VFP context from the thread structure.  We do + * this by ensuring that access to the VFP hardware is disabled, and + * clear last_VFP_context.  Must be called from non-preemptible context. + */ +static void vfp_force_reload(unsigned int cpu, struct thread_info *thread) +{ +	if (vfp_state_in_hw(cpu, thread)) { +		fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); +		vfp_current_hw_state[cpu] = NULL; +	} +#ifdef CONFIG_SMP +	thread->vfpstate.hard.cpu = NR_CPUS; +#endif +} + +/*   * Per-thread VFP initialization.   */  static void vfp_thread_flush(struct thread_info *thread) @@ -50,21 +89,27 @@ static void vfp_thread_flush(struct thread_info *thread)  	union vfp_state *vfp = &thread->vfpstate;  	unsigned int cpu; -	memset(vfp, 0, sizeof(union vfp_state)); - -	vfp->hard.fpexc = FPEXC_EN; -	vfp->hard.fpscr = FPSCR_ROUND_NEAREST; -  	/*  	 * Disable VFP to ensure we initialize it first.  We must ensure -	 * that the modification of last_VFP_context[] and hardware disable -	 * are done for the same CPU and without preemption. +	 * that the modification of vfp_current_hw_state[] and hardware +	 * disable are done for the same CPU and without preemption. +	 * +	 * Do this first to ensure that preemption won't overwrite our +	 * state saving should access to the VFP be enabled at this point.  	 */  	cpu = get_cpu(); -	if (last_VFP_context[cpu] == vfp) -		last_VFP_context[cpu] = NULL; +	if (vfp_current_hw_state[cpu] == vfp) +		vfp_current_hw_state[cpu] = NULL;  	fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);  	put_cpu(); + +	memset(vfp, 0, sizeof(union vfp_state)); + +	vfp->hard.fpexc = FPEXC_EN; +	vfp->hard.fpscr = FPSCR_ROUND_NEAREST; +#ifdef CONFIG_SMP +	vfp->hard.cpu = NR_CPUS; +#endif  }  static void vfp_thread_exit(struct thread_info *thread) @@ -73,8 +118,8 @@ static void vfp_thread_exit(struct thread_info *thread)  	union vfp_state *vfp = &thread->vfpstate;  	unsigned int cpu = get_cpu(); -	if (last_VFP_context[cpu] == vfp) -		last_VFP_context[cpu] = NULL; +	if (vfp_current_hw_state[cpu] == vfp) +		vfp_current_hw_state[cpu] = NULL;  	put_cpu();  } @@ -84,6 +129,9 @@ static void vfp_thread_copy(struct thread_info *thread)  	vfp_sync_hwstate(parent);  	thread->vfpstate = parent->vfpstate; +#ifdef CONFIG_SMP +	thread->vfpstate.hard.cpu = NR_CPUS; +#endif  }  /* @@ -129,17 +177,8 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)  		 * case the thread migrates to a different CPU. The  		 * restoring is done lazily.  		 */ -		if ((fpexc & FPEXC_EN) && last_VFP_context[cpu]) { -			vfp_save_state(last_VFP_context[cpu], fpexc); -			last_VFP_context[cpu]->hard.cpu = cpu; -		} -		/* -		 * Thread migration, just force the reloading of the -		 * state on the new CPU in case the VFP registers -		 * contain stale data. -		 */ -		if (thread->vfpstate.hard.cpu != cpu) -			last_VFP_context[cpu] = NULL; +		if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) +			vfp_save_state(vfp_current_hw_state[cpu], fpexc);  #endif  		/* @@ -415,7 +454,7 @@ static int vfp_pm_suspend(void)  	}  	/* clear any information we had about last context state */ -	memset(last_VFP_context, 0, sizeof(last_VFP_context)); +	memset(vfp_current_hw_state, 0, sizeof(vfp_current_hw_state));  	return 0;  } @@ -443,15 +482,15 @@ static void vfp_pm_init(void)  static inline void vfp_pm_init(void) { }  #endif /* CONFIG_PM */ +/* + * Ensure that the VFP state stored in 'thread->vfpstate' is up to date + * with the hardware state. + */  void vfp_sync_hwstate(struct thread_info *thread)  {  	unsigned int cpu = get_cpu(); -	/* -	 * If the thread we're interested in is the current owner of the -	 * hardware VFP state, then we need to save its state. -	 */ -	if (last_VFP_context[cpu] == &thread->vfpstate) { +	if (vfp_state_in_hw(cpu, thread)) {  		u32 fpexc = fmrx(FPEXC);  		/* @@ -465,36 +504,13 @@ void vfp_sync_hwstate(struct thread_info *thread)  	put_cpu();  } +/* Ensure that the thread reloads the hardware VFP state on the next use. */  void vfp_flush_hwstate(struct thread_info *thread)  {  	unsigned int cpu = get_cpu(); -	/* -	 * If the thread we're interested in is the current owner of the -	 * hardware VFP state, then we need to save its state. -	 */ -	if (last_VFP_context[cpu] == &thread->vfpstate) { -		u32 fpexc = fmrx(FPEXC); - -		fmxr(FPEXC, fpexc & ~FPEXC_EN); - -		/* -		 * Set the context to NULL to force a reload the next time -		 * the thread uses the VFP. -		 */ -		last_VFP_context[cpu] = NULL; -	} +	vfp_force_reload(cpu, thread); -#ifdef CONFIG_SMP -	/* -	 * For SMP we still have to take care of the case where the thread -	 * migrates to another CPU and then back to the original CPU on which -	 * the last VFP user is still the same thread. Mark the thread VFP -	 * state as belonging to a non-existent CPU so that the saved one will -	 * be reloaded in the above case. -	 */ -	thread->vfpstate.hard.cpu = NR_CPUS; -#endif  	put_cpu();  } @@ -513,8 +529,7 @@ static int vfp_hotplug(struct notifier_block *b, unsigned long action,  	void *hcpu)  {  	if (action == CPU_DYING || action == CPU_DYING_FROZEN) { -		unsigned int cpu = (long)hcpu; -		last_VFP_context[cpu] = NULL; +		vfp_force_reload((long)hcpu, current_thread_info());  	} else if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)  		vfp_enable(NULL);  	return NOTIFY_OK; diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c index c018696765d..5c74eb797f0 100644 --- a/arch/mips/kernel/i8259.c +++ b/arch/mips/kernel/i8259.c @@ -14,7 +14,7 @@  #include <linux/interrupt.h>  #include <linux/kernel.h>  #include <linux/spinlock.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h>  #include <linux/irq.h>  #include <asm/i8259.h> @@ -215,14 +215,13 @@ spurious_8259A_irq:  	}  } -static int i8259A_resume(struct sys_device *dev) +static void i8259A_resume(void)  {  	if (i8259A_auto_eoi >= 0)  		init_8259A(i8259A_auto_eoi); -	return 0;  } -static int i8259A_shutdown(struct sys_device *dev) +static void i8259A_shutdown(void)  {  	/* Put the i8259A into a quiescent state that  	 * the kernel initialization code can get it @@ -232,26 +231,17 @@ static int i8259A_shutdown(struct sys_device *dev)  		outb(0xff, PIC_MASTER_IMR);	/* mask all of 8259A-1 */  		outb(0xff, PIC_SLAVE_IMR);	/* mask all of 8259A-1 */  	} -	return 0;  } -static struct sysdev_class i8259_sysdev_class = { -	.name = "i8259", +static struct syscore_ops i8259_syscore_ops = {  	.resume = i8259A_resume,  	.shutdown = i8259A_shutdown,  }; -static struct sys_device device_i8259A = { -	.id	= 0, -	.cls	= &i8259_sysdev_class, -}; -  static int __init i8259A_init_sysfs(void)  { -	int error = sysdev_class_register(&i8259_sysdev_class); -	if (!error) -		error = sysdev_register(&device_i8259A); -	return error; +	register_syscore_ops(&i8259_syscore_ops); +	return 0;  }  device_initcall(i8259A_init_sysfs); diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 33867ec4a23..9d6a8effeda 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -12,6 +12,8 @@  #include <linux/of.h>  #include <linux/memblock.h>  #include <linux/vmalloc.h> +#include <linux/memory.h> +  #include <asm/firmware.h>  #include <asm/machdep.h>  #include <asm/pSeries_reconfig.h> @@ -20,24 +22,25 @@  static unsigned long get_memblock_size(void)  {  	struct device_node *np; -	unsigned int memblock_size = 0; +	unsigned int memblock_size = MIN_MEMORY_BLOCK_SIZE; +	struct resource r;  	np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");  	if (np) { -		const unsigned long *size; +		const __be64 *size;  		size = of_get_property(np, "ibm,lmb-size", NULL); -		memblock_size = size ? *size : 0; - +		if (size) +			memblock_size = be64_to_cpup(size);  		of_node_put(np); -	} else { +	} else  if (machine_is(pseries)) { +		/* This fallback really only applies to pseries */  		unsigned int memzero_size = 0; -		const unsigned int *regs;  		np = of_find_node_by_path("/memory@0");  		if (np) { -			regs = of_get_property(np, "reg", NULL); -			memzero_size = regs ? regs[3] : 0; +			if (!of_address_to_resource(np, 0, &r)) +				memzero_size = resource_size(&r);  			of_node_put(np);  		} @@ -50,16 +53,21 @@ static unsigned long get_memblock_size(void)  			sprintf(buf, "/memory@%x", memzero_size);  			np = of_find_node_by_path(buf);  			if (np) { -				regs = of_get_property(np, "reg", NULL); -				memblock_size = regs ? regs[3] : 0; +				if (!of_address_to_resource(np, 0, &r)) +					memblock_size = resource_size(&r);  				of_node_put(np);  			}  		}  	} -  	return memblock_size;  } +/* WARNING: This is going to override the generic definition whenever + * pseries is built-in regardless of what platform is active at boot + * time. This is fine for now as this is the only "option" and it + * should work everywhere. If not, we'll have to turn this into a + * ppc_md. callback + */  unsigned long memory_block_size_bytes(void)  {  	return get_memblock_size(); diff --git a/arch/sparc/include/asm/irqflags_32.h b/arch/sparc/include/asm/irqflags_32.h index d4d0711de0f..14848909e0d 100644 --- a/arch/sparc/include/asm/irqflags_32.h +++ b/arch/sparc/include/asm/irqflags_32.h @@ -18,7 +18,7 @@ extern void arch_local_irq_restore(unsigned long);  extern unsigned long arch_local_irq_save(void);  extern void arch_local_irq_enable(void); -static inline unsigned long arch_local_save_flags(void) +static inline notrace unsigned long arch_local_save_flags(void)  {  	unsigned long flags; @@ -26,17 +26,17 @@ static inline unsigned long arch_local_save_flags(void)  	return flags;  } -static inline void arch_local_irq_disable(void) +static inline notrace void arch_local_irq_disable(void)  {  	arch_local_irq_save();  } -static inline bool arch_irqs_disabled_flags(unsigned long flags) +static inline notrace bool arch_irqs_disabled_flags(unsigned long flags)  {  	return (flags & PSR_PIL) != 0;  } -static inline bool arch_irqs_disabled(void) +static inline notrace bool arch_irqs_disabled(void)  {  	return arch_irqs_disabled_flags(arch_local_save_flags());  } diff --git a/arch/sparc/include/asm/irqflags_64.h b/arch/sparc/include/asm/irqflags_64.h index aab969c82c2..23cd27f6beb 100644 --- a/arch/sparc/include/asm/irqflags_64.h +++ b/arch/sparc/include/asm/irqflags_64.h @@ -14,7 +14,7 @@  #ifndef __ASSEMBLY__ -static inline unsigned long arch_local_save_flags(void) +static inline notrace unsigned long arch_local_save_flags(void)  {  	unsigned long flags; @@ -26,7 +26,7 @@ static inline unsigned long arch_local_save_flags(void)  	return flags;  } -static inline void arch_local_irq_restore(unsigned long flags) +static inline notrace void arch_local_irq_restore(unsigned long flags)  {  	__asm__ __volatile__(  		"wrpr	%0, %%pil" @@ -36,7 +36,7 @@ static inline void arch_local_irq_restore(unsigned long flags)  	);  } -static inline void arch_local_irq_disable(void) +static inline notrace void arch_local_irq_disable(void)  {  	__asm__ __volatile__(  		"wrpr	%0, %%pil" @@ -46,7 +46,7 @@ static inline void arch_local_irq_disable(void)  	);  } -static inline void arch_local_irq_enable(void) +static inline notrace void arch_local_irq_enable(void)  {  	__asm__ __volatile__(  		"wrpr	0, %%pil" @@ -56,17 +56,17 @@ static inline void arch_local_irq_enable(void)  	);  } -static inline int arch_irqs_disabled_flags(unsigned long flags) +static inline notrace int arch_irqs_disabled_flags(unsigned long flags)  {  	return (flags > 0);  } -static inline int arch_irqs_disabled(void) +static inline notrace int arch_irqs_disabled(void)  {  	return arch_irqs_disabled_flags(arch_local_save_flags());  } -static inline unsigned long arch_local_irq_save(void) +static inline notrace unsigned long arch_local_irq_save(void)  {  	unsigned long flags, tmp; diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 9fe08a1ea6c..f445e98463e 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -293,7 +293,7 @@ maybe_smp4m_msg:  	WRITE_PAUSE  	wr	%l4, PSR_ET, %psr  	WRITE_PAUSE -	sll	%o3, 28, %o2		! shift for simpler checks below +	srl	%o3, 28, %o2		! shift for simpler checks below  maybe_smp4m_msg_check_single:  	andcc	%o2, 0x1, %g0  	beq,a	maybe_smp4m_msg_check_mask diff --git a/arch/sparc/mm/leon_mm.c b/arch/sparc/mm/leon_mm.c index c0e01297e64..e485a680499 100644 --- a/arch/sparc/mm/leon_mm.c +++ b/arch/sparc/mm/leon_mm.c @@ -226,7 +226,7 @@ void leon3_getCacheRegs(struct leon3_cacheregs *regs)   * Leon2 and Leon3 differ in their way of telling cache information   *   */ -int leon_flush_needed(void) +int __init leon_flush_needed(void)  {  	int flush_needed = -1;  	unsigned int ssize, sets; diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index da349723d41..37357a599dc 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1170,7 +1170,7 @@ comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"  config AMD_NUMA  	def_bool y  	prompt "Old style AMD Opteron NUMA detection" -	depends on NUMA && PCI +	depends on X86_64 && NUMA && PCI  	---help---  	  Enable AMD NUMA node topology detection.  You should say Y here if  	  you have a multi processor AMD system. This uses an old method to diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 4f0d46fefa7..14eed214b58 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -419,6 +419,14 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {  			DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"),  		},  	}, +	{	/* Handle problems with rebooting on the Latitude E6320. */ +		.callback = set_pci_reboot, +		.ident = "Dell Latitude E6320", +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6320"), +		}, +	},  	{ }  }; diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index d865c4aeec5..bbaaa005bf0 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -28,6 +28,7 @@  #include <linux/poison.h>  #include <linux/dma-mapping.h>  #include <linux/module.h> +#include <linux/memory.h>  #include <linux/memory_hotplug.h>  #include <linux/nmi.h>  #include <linux/gfp.h> @@ -895,8 +896,6 @@ const char *arch_vma_name(struct vm_area_struct *vma)  }  #ifdef CONFIG_X86_UV -#define MIN_MEMORY_BLOCK_SIZE   (1 << SECTION_SIZE_BITS) -  unsigned long memory_block_size_bytes(void)  {  	if (is_uv_system()) {  |