Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ARM: OMAP: Add support for dmtimer v2 ip (Re: [PATCH v15 06/12] OMAP: dmtimer: switch-over to platform device driver)
From: Tony Lindgren @ 2011-09-19 17:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <B85A65D85D7EB246BE421B3FB0FBB59302575A0FBC@dbde02.ent.ti.com>

* Mohammed, Afzal <afzal@ti.com> [110918 21:48]:
> Hi Tony,
> 
> On Sat, Sep 17, 2011 at 07:05:31, Tony Lindgren wrote:
> > 
> > Afzal, care to check if that works for AM335X/TI816X/TI814X?
> 
> With following patch over yours, AM335X (the only board with me) boots up fine.

Thanks for catching that, will fold it in with your Signed-off-by.

Regards,

Tony

^ permalink raw reply

* [PATCH] ARM: OMAP: Add support for dmtimer v2 ip (Re: [PATCH v15 06/12] OMAP: dmtimer: switch-over to platform device driver)
From: Tony Lindgren @ 2011-09-19 17:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAC83Zv+X+huFrG+_LNadNwi9zRAWHGRvrQnvpAoZJK=30TK0fg@mail.gmail.com>

* DebBarma, Tarun Kanti <tarun.kanti@ti.com> [110918 04:53]:
> >
> > But we can map the interrupt registers separately and then have
> > the rest start from func_base that is different based on the timer
> > version. Rebasing the rest of the dmtimer hwmod patches on this
> > should be fairly easy, mostly just need to pass timer instead of
> > timer->io_base and use __raw_read/write for the interrupt registers.
> I went through the patch. It definitely looks much more simplified now.
> I will rebase on top of this change.

OK thanks, can I add your Acked-by then?

Tony

^ permalink raw reply

* [PATCH] ARM: OMAP: Add support for dmtimer v2 ip (Re: [PATCH v15 06/12] OMAP: dmtimer: switch-over to platform device driver)
From: Tony Lindgren @ 2011-09-19 17:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2A3DCF3DA181AD40BDE86A3150B27B6B03B4C80288@dbde02.ent.ti.com>

* Pedanekar, Hemant <hemantp@ti.com> [110918 20:32]:
> 
> Tony,
> Kernel boots fine on TI816X (should also boot on TI814X) with your patch
> and patches (including OSC clock fix) from series
> http://www.spinics.net/lists/linux-omap/msg57011.html  

OK good to hear, I assume I can add your Tested-by then?

Regards,

Tony

^ permalink raw reply

* [PATCH v3 4/4] ARM: S5PV210: UNIVERSAL_C210: Add support for M-5MOLS image sensor
From: Sylwester Nawrocki @ 2011-09-19 17:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1316453441-13525-1-git-send-email-s.nawrocki@samsung.com>

Add voltage regulator definitions for M-5MOLS camera, platform data
definition for the sensor and MIPI-CSI receiver drivers.
Add CAM power domain dependencies for FIMC and CSIS devices.
Define required I2C0 bus timings. Setup camera port A GPIO.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-exynos4/Kconfig               |    3 +
 arch/arm/mach-exynos4/mach-universal_c210.c |  206 +++++++++++++++++++++++++-
 2 files changed, 201 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index 3b594fe..f1fd20e 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -171,6 +171,7 @@ config MACH_UNIVERSAL_C210
 	select S5P_DEV_FIMC1
 	select S5P_DEV_FIMC2
 	select S5P_DEV_FIMC3
+	select S5P_DEV_CSIS0
 	select S5P_DEV_FIMD0
 	select S3C_DEV_HSMMC
 	select S3C_DEV_HSMMC2
@@ -188,6 +189,8 @@ config MACH_UNIVERSAL_C210
 	select EXYNOS4_SETUP_I2C3
 	select EXYNOS4_SETUP_I2C5
 	select EXYNOS4_SETUP_SDHCI
+	select EXYNOS4_SETUP_FIMC
+	select S5P_SETUP_MIPIPHY
 	help
 	  Machine support for Samsung Mobile Universal S5PC210 Reference
 	  Board.
diff --git a/arch/arm/mach-exynos4/mach-universal_c210.c b/arch/arm/mach-exynos4/mach-universal_c210.c
index 315c503..18cf5c7 100644
--- a/arch/arm/mach-exynos4/mach-universal_c210.c
+++ b/arch/arm/mach-exynos4/mach-universal_c210.c
@@ -37,9 +37,16 @@
 #include <plat/sdhci.h>
 #include <plat/pd.h>
 #include <plat/regs-fb-v4.h>
+#include <plat/fimc-core.h>
+#include <plat/camport.h>
+#include <plat/mipi_csis.h>
 
 #include <mach/map.h>
 
+#include <media/v4l2-mediabus.h>
+#include <media/s5p_fimc.h>
+#include <media/m5mols.h>
+
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define UNIVERSAL_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
 				 S3C2410_UCON_RXILEVEL |	\
@@ -192,6 +199,7 @@ static struct regulator_init_data lp3974_ldo2_data = {
 static struct regulator_consumer_supply lp3974_ldo3_consumer[] = {
 	REGULATOR_SUPPLY("vdd", "exynos4-hdmi"),
 	REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"),
+	REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"),
 };
 
 static struct regulator_init_data lp3974_ldo3_data = {
@@ -254,6 +262,10 @@ static struct regulator_init_data lp3974_ldo6_data = {
 	},
 };
 
+static struct regulator_consumer_supply lp3974_ldo7_consumer[] = {
+	REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"),
+};
+
 static struct regulator_init_data lp3974_ldo7_data = {
 	.constraints	= {
 		.name		= "VLCD+VMIPI_1.8V",
@@ -265,6 +277,8 @@ static struct regulator_init_data lp3974_ldo7_data = {
 			.disabled	= 1,
 		},
 	},
+	.num_consumer_supplies	= ARRAY_SIZE(lp3974_ldo7_consumer),
+	.consumer_supplies	= lp3974_ldo7_consumer,
 };
 
 static struct regulator_consumer_supply lp3974_ldo8_consumer[] = {
@@ -313,6 +327,9 @@ static struct regulator_init_data lp3974_ldo10_data = {
 	},
 };
 
+static struct regulator_consumer_supply lp3974_ldo11_consumer =
+	REGULATOR_SUPPLY("dig_28", "0-001f");
+
 static struct regulator_init_data lp3974_ldo11_data = {
 	.constraints	= {
 		.name		= "CAM_AF_3.3V",
@@ -324,6 +341,8 @@ static struct regulator_init_data lp3974_ldo11_data = {
 			.disabled	= 1,
 		},
 	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &lp3974_ldo11_consumer,
 };
 
 static struct regulator_init_data lp3974_ldo12_data = {
@@ -352,6 +371,9 @@ static struct regulator_init_data lp3974_ldo13_data = {
 	},
 };
 
+static struct regulator_consumer_supply lp3974_ldo14_consumer =
+	REGULATOR_SUPPLY("dig_18", "0-001f");
+
 static struct regulator_init_data lp3974_ldo14_data = {
 	.constraints	= {
 		.name		= "CAM_I_HOST_1.8V",
@@ -363,8 +385,14 @@ static struct regulator_init_data lp3974_ldo14_data = {
 			.disabled	= 1,
 		},
 	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &lp3974_ldo14_consumer,
 };
 
+
+static struct regulator_consumer_supply lp3974_ldo15_consumer =
+	REGULATOR_SUPPLY("dig_12", "0-001f");
+
 static struct regulator_init_data lp3974_ldo15_data = {
 	.constraints	= {
 		.name		= "CAM_S_DIG+FM33_CORE_1.2V",
@@ -376,6 +404,12 @@ static struct regulator_init_data lp3974_ldo15_data = {
 			.disabled	= 1,
 		},
 	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &lp3974_ldo15_consumer,
+};
+
+static struct regulator_consumer_supply lp3974_ldo16_consumer[] = {
+	REGULATOR_SUPPLY("a_sensor", "0-001f"),
 };
 
 static struct regulator_init_data lp3974_ldo16_data = {
@@ -389,6 +423,8 @@ static struct regulator_init_data lp3974_ldo16_data = {
 			.disabled	= 1,
 		},
 	},
+	.num_consumer_supplies	= ARRAY_SIZE(lp3974_ldo16_consumer),
+	.consumer_supplies	= lp3974_ldo16_consumer,
 };
 
 static struct regulator_init_data lp3974_ldo17_data = {
@@ -499,6 +535,15 @@ static struct max8998_platform_data universal_lp3974_pdata = {
 	.wakeup			= true,
 };
 
+
+enum fixed_regulator_id {
+	FIXED_REG_ID_MMC0,
+	FIXED_REG_ID_HDMI_5V,
+	FIXED_REG_ID_CAM_S_IF,
+	FIXED_REG_ID_CAM_I_CORE,
+	FIXED_REG_ID_CAM_VT_DIO,
+};
+
 static struct regulator_consumer_supply hdmi_fixed_consumer =
 	REGULATOR_SUPPLY("hdmi-en", "exynos4-hdmi");
 
@@ -521,7 +566,7 @@ static struct fixed_voltage_config hdmi_fixed_voltage_config = {
 
 static struct platform_device hdmi_fixed_voltage = {
 	.name			= "reg-fixed-voltage",
-	.id			= 6,
+	.id			= FIXED_REG_ID_HDMI_5V,
 	.dev			= {
 		.platform_data	= &hdmi_fixed_voltage_config,
 	},
@@ -628,6 +673,11 @@ static void __init universal_touchkey_init(void)
 	gpio_direction_output(gpio, 1);
 }
 
+static struct s3c2410_platform_i2c universal_i2c0_platdata __initdata = {
+	.frequency	= 300 * 1000,
+	.sda_delay	= 200,
+};
+
 /* GPIO KEYS */
 static struct gpio_keys_button universal_gpio_keys_tables[] = {
 	{
@@ -713,7 +763,7 @@ static struct fixed_voltage_config mmc0_fixed_voltage_config = {
 
 static struct platform_device mmc0_fixed_voltage = {
 	.name			= "reg-fixed-voltage",
-	.id			= 0,
+	.id			= FIXED_REG_ID_MMC0,
 	.dev			= {
 		.platform_data	= &mmc0_fixed_voltage_config,
 	},
@@ -747,11 +797,6 @@ static void __init universal_sdhci_init(void)
 	s3c_sdhci3_set_platdata(&universal_hsmmc3_data);
 }
 
-/* I2C0 */
-static struct i2c_board_info i2c0_devs[] __initdata = {
-	/* Camera, To be updated */
-};
-
 /* I2C1 */
 static struct i2c_board_info i2c1_devs[] __initdata = {
 	/* Gyro, To be updated */
@@ -783,8 +828,139 @@ static struct s3c_fb_platdata universal_lcd_pdata __initdata = {
 	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
 };
 
+static struct regulator_consumer_supply cam_i_core_supply =
+	REGULATOR_SUPPLY("core", "0-001f");
+
+static struct regulator_init_data cam_i_core_reg_init_data = {
+	.constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &cam_i_core_supply,
+};
+
+static struct fixed_voltage_config cam_i_core_fixed_voltage_cfg = {
+	.supply_name	= "CAM_I_CORE_1.2V",
+	.microvolts	= 1200000,
+	.gpio		= EXYNOS4_GPE2(2),	/* CAM_8M_CORE_EN */
+	.enable_high	= 1,
+	.init_data	= &cam_i_core_reg_init_data,
+};
+
+static struct platform_device cam_i_core_fixed_reg_dev = {
+	.name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_I_CORE,
+	.dev = { .platform_data	= &cam_i_core_fixed_voltage_cfg },
+};
+
+static struct regulator_consumer_supply cam_s_if_supply =
+	REGULATOR_SUPPLY("d_sensor", "0-001f");
+
+static struct regulator_init_data cam_s_if_reg_init_data = {
+	.constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &cam_s_if_supply,
+};
+
+static struct fixed_voltage_config cam_s_if_fixed_voltage_cfg = {
+	.supply_name	= "CAM_S_IF_1.8V",
+	.microvolts	= 1800000,
+	.gpio		= EXYNOS4_GPE3(0),	/* CAM_PWR_EN1 */
+	.enable_high	= 1,
+	.init_data	= &cam_s_if_reg_init_data,
+};
+
+static struct platform_device cam_s_if_fixed_reg_dev = {
+	.name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_S_IF,
+	.dev = { .platform_data	= &cam_s_if_fixed_voltage_cfg },
+};
+
+static struct s5p_platform_mipi_csis mipi_csis_platdata = {
+	.clk_rate	= 166000000UL,
+	.lanes		= 2,
+	.alignment	= 32,
+	.hs_settle	= 12,
+	.phy_enable	= s5p_csis_phy_enable,
+};
+
+#define GPIO_CAM_LEVEL_EN(n)	EXYNOS4_GPE4(n + 3)
+#define GPIO_CAM_8M_ISP_INT	EXYNOS4_GPX1(5)	/* XEINT_13 */
+#define GPIO_CAM_MEGA_nRST	EXYNOS4_GPE2(5)
+
+static int m5mols_set_power(struct device *dev, int on)
+{
+	gpio_set_value(GPIO_CAM_LEVEL_EN(1), !on);
+	gpio_set_value(GPIO_CAM_LEVEL_EN(2), !!on);
+	return 0;
+}
+
+static struct m5mols_platform_data m5mols_platdata = {
+	.gpio_reset	= GPIO_CAM_MEGA_nRST,
+	.reset_polarity	= 0,
+	.set_power	= m5mols_set_power,
+};
+
+static struct i2c_board_info m5mols_board_info = {
+	I2C_BOARD_INFO("M5MOLS", 0x1F),
+	.platform_data = &m5mols_platdata,
+};
+
+static struct s5p_fimc_isp_info universal_camera_sensors[] = {
+	{
+		.mux_id		= 0,
+		.flags		= V4L2_MBUS_PCLK_SAMPLE_FALLING |
+				  V4L2_MBUS_VSYNC_ACTIVE_LOW,
+		.bus_type	= FIMC_MIPI_CSI2,
+		.board_info	= &m5mols_board_info,
+		.i2c_bus_num	= 0,
+		.clk_frequency	= 21600000UL,
+		.csi_data_align	= 32,
+	},
+};
+
+static struct s5p_platform_fimc fimc_md_platdata = {
+	.isp_info	= universal_camera_sensors,
+	.num_clients	= ARRAY_SIZE(universal_camera_sensors),
+};
+
+struct platform_device s5p_device_fimc_md = {
+	.name	= "s5p-fimc-md",
+	.id	= -1,
+};
+
+static struct gpio universal_camera_gpios[] = {
+	{ GPIO_CAM_LEVEL_EN(1),	GPIOF_OUT_INIT_HIGH, "CAM_LVL_EN1" },
+	{ GPIO_CAM_LEVEL_EN(2),	GPIOF_OUT_INIT_LOW,  "CAM_LVL_EN2" },
+	{ GPIO_CAM_8M_ISP_INT,	GPIOF_IN,            "8M_ISP_INT"  },
+	{ GPIO_CAM_MEGA_nRST,	GPIOF_OUT_INIT_LOW,  "CAM_8M_NRST" },
+};
+
+static void universal_camera_init(void)
+{
+	s3c_set_platdata(&mipi_csis_platdata, sizeof(mipi_csis_platdata),
+			 &s5p_device_mipi_csis0);
+	s3c_set_platdata(&fimc_md_platdata,  sizeof(fimc_md_platdata),
+			 &s5p_device_fimc_md);
+
+	if (gpio_request_array(universal_camera_gpios,
+			       ARRAY_SIZE(universal_camera_gpios))) {
+		pr_err("%s: GPIO request failed\n", __func__);
+		return;
+	}
+
+	if (!s3c_gpio_cfgpin(GPIO_CAM_8M_ISP_INT, S3C_GPIO_SFN(0xf)))
+		m5mols_board_info.irq = gpio_to_irq(GPIO_CAM_8M_ISP_INT);
+	else
+		pr_err("Failed to configure 8M_ISP_INT GPIO\n");
+
+	/* Free GPIOs controlled directly by the sensor drivers. */
+	gpio_free(GPIO_CAM_MEGA_nRST);
+	gpio_free(GPIO_CAM_8M_ISP_INT);
+
+	if (exynos4_fimc_setup_gpio(S5P_CAMPORT_A))
+		pr_err("Camera port A setup failed\n");
+}
+
 static struct platform_device *universal_devices[] __initdata = {
 	/* Samsung Platform Devices */
+	&s5p_device_mipi_csis0,
 	&s5p_device_fimc0,
 	&s5p_device_fimc1,
 	&s5p_device_fimc2,
@@ -793,6 +969,7 @@ static struct platform_device *universal_devices[] __initdata = {
 	&s3c_device_hsmmc0,
 	&s3c_device_hsmmc2,
 	&s3c_device_hsmmc3,
+	&s3c_device_i2c0,
 	&s3c_device_i2c3,
 	&s3c_device_i2c5,
 	&s5p_device_i2c_hdmiphy,
@@ -812,6 +989,10 @@ static struct platform_device *universal_devices[] __initdata = {
 	&s5p_device_mfc_r,
 	&exynos4_device_pd[PD_MFC],
 	&exynos4_device_pd[PD_LCD0],
+	&exynos4_device_pd[PD_CAM],
+	&cam_i_core_fixed_reg_dev,
+	&cam_s_if_fixed_reg_dev,
+	&s5p_device_fimc_md,
 };
 
 static void __init universal_map_io(void)
@@ -845,7 +1026,7 @@ static void __init universal_machine_init(void)
 	universal_sdhci_init();
 	s5p_tv_setup();
 
-	i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
+	s3c_i2c0_set_platdata(&universal_i2c0_platdata);
 	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
 
 	universal_tsp_init();
@@ -862,10 +1043,19 @@ static void __init universal_machine_init(void)
 	i2c_register_board_info(I2C_GPIO_BUS_12, i2c_gpio12_devs,
 			ARRAY_SIZE(i2c_gpio12_devs));
 
+	universal_camera_init();
+
 	/* Last */
 	platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
+
 	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
 	s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
+
+	s5p_device_fimc0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc1.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc2.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_fimc3.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+	s5p_device_mipi_csis0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
 }
 
 MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
-- 
1.7.6.3

^ permalink raw reply related

* [PATCH v3 3/4] ARM: EXYNOS4: Rename sclk_cam clocks for FIMC driver
From: Sylwester Nawrocki @ 2011-09-19 17:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1316453441-13525-1-git-send-email-s.nawrocki@samsung.com>

The sclk_cam clocks are now controlled by the top level FIMC media
device driver bound to "s5p-fimc-md" platform device.
Rename sclk_cam clocks so they accessible by the corresponding
driver.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-exynos4/clock.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
index da9567a..a25c818 100644
--- a/arch/arm/mach-exynos4/clock.c
+++ b/arch/arm/mach-exynos4/clock.c
@@ -1084,8 +1084,7 @@ static struct clksrc_clk clksrcs[] = {
 		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 28, .size = 4 },
 	}, {
 		.clk		= {
-			.name		= "sclk_cam",
-			.devname	= "exynos4-fimc.0",
+			.name		= "sclk_cam0",
 			.enable		= exynos4_clksrc_mask_cam_ctrl,
 			.ctrlbit	= (1 << 16),
 		},
@@ -1094,8 +1093,7 @@ static struct clksrc_clk clksrcs[] = {
 		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 16, .size = 4 },
 	}, {
 		.clk		= {
-			.name		= "sclk_cam",
-			.devname	= "exynos4-fimc.1",
+			.name		= "sclk_cam1",
 			.enable		= exynos4_clksrc_mask_cam_ctrl,
 			.ctrlbit	= (1 << 20),
 		},
-- 
1.7.6.3

^ permalink raw reply related

* [PATCH v3 2/4] ARM: S5PV210: Add support for NOON010PC30 sensor on GONI board
From: Sylwester Nawrocki @ 2011-09-19 17:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1316453441-13525-1-git-send-email-s.nawrocki@samsung.com>

Add platform data for CIF camera sensor and FIMC platform data
entries for it. Add platform device for s5p-fimc media device
driver and the camera port A I/O pins initialization.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-s5pv210/Kconfig     |    1 +
 arch/arm/mach-s5pv210/mach-goni.c |   53 +++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index ccef034..f22c683 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -99,6 +99,7 @@ config MACH_GONI
 	select S5PV210_SETUP_I2C2
 	select S5PV210_SETUP_KEYPAD
 	select S5PV210_SETUP_SDHCI
+	select S5PV210_SETUP_FIMC
 	help
 	  Machine support for Samsung GONI board
 	  S5PC110(MCP) is one of package option of S5PV210
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 14578f5..01e4867 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -48,6 +48,11 @@
 #include <plat/s5p-time.h>
 #include <plat/mfc.h>
 #include <plat/regs-fb-v4.h>
+#include <plat/camport.h>
+
+#include <media/v4l2-mediabus.h>
+#include <media/s5p_fimc.h>
+#include <media/noon010pc30.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define GONI_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -272,6 +277,14 @@ static void __init goni_tsp_init(void)
 	i2c2_devs[0].irq = gpio_to_irq(gpio);
 }
 
+static void goni_camera_init(void)
+{
+	s5pv210_fimc_setup_gpio(S5P_CAMPORT_A);
+
+	/* Set max driver strength on CAM_A_CLKOUT pin. */
+	s5p_gpio_set_drvstr(S5PV210_GPE1(3), S5P_GPIO_DRVSTR_LV4);
+}
+
 /* MAX8998 regulators */
 #if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
 
@@ -808,6 +821,39 @@ static void goni_setup_sdhci(void)
 	s3c_sdhci2_set_platdata(&goni_hsmmc2_data);
 };
 
+static struct noon010pc30_platform_data noon010pc30_pldata = {
+	.clk_rate	= 16000000UL,
+	.gpio_nreset	= S5PV210_GPB(2), /* CAM_CIF_NRST */
+	.gpio_nstby	= S5PV210_GPB(0), /* CAM_CIF_NSTBY */
+};
+
+static struct i2c_board_info noon010pc30_board_info = {
+	I2C_BOARD_INFO("NOON010PC30", 0x60 >> 1),
+	.platform_data = &noon010pc30_pldata,
+};
+
+static struct s5p_fimc_isp_info goni_camera_sensors[] = {
+	{
+		.mux_id		= 0,
+		.flags		= V4L2_MBUS_PCLK_SAMPLE_FALLING |
+				  V4L2_MBUS_VSYNC_ACTIVE_LOW,
+		.bus_type	= FIMC_ITU_601,
+		.board_info	= &noon010pc30_board_info,
+		.i2c_bus_num	= 0,
+		.clk_frequency	= 16000000UL,
+	},
+};
+
+struct s5p_platform_fimc goni_fimc_md_platdata __initdata = {
+	.isp_info	= goni_camera_sensors,
+	.num_clients	= ARRAY_SIZE(goni_camera_sensors),
+};
+
+struct platform_device s5p_device_fimc_md = {
+	.name		= "s5p-fimc-md",
+	.id		= -1,
+};
+
 static struct platform_device *goni_devices[] __initdata = {
 	&s3c_device_fb,
 	&s5p_device_onenand,
@@ -825,6 +871,7 @@ static struct platform_device *goni_devices[] __initdata = {
 	&s5p_device_fimc0,
 	&s5p_device_fimc1,
 	&s5p_device_fimc2,
+	&s5p_device_fimc_md,
 	&s3c_device_hsmmc0,
 	&s3c_device_hsmmc1,
 	&s3c_device_hsmmc2,
@@ -893,6 +940,12 @@ static void __init goni_machine_init(void)
 	/* FB */
 	s3c_fb_set_platdata(&goni_lcd_pdata);
 
+	/* FIMC */
+	s3c_set_platdata(&goni_fimc_md_platdata, sizeof(goni_fimc_md_platdata),
+			 &s5p_device_fimc_md);
+
+	goni_camera_init();
+
 	/* SPI */
 	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 
-- 
1.7.6.3

^ permalink raw reply related

* [PATCH v3 1/4] ARM: S5PV210: Rename sclk_cam clocks for FIMC media driver
From: Sylwester Nawrocki @ 2011-09-19 17:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1316453441-13525-1-git-send-email-s.nawrocki@samsung.com>

The sclk_cam clocks are now controlled by the top level FIMC media
device driver bound to "s5p-fimc-md" platform device.
Rename sclk_cam clocks so they accessible by the corresponding
driver.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-s5pv210/clock.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index ad553ee..4c5ac7a 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -879,8 +879,7 @@ static struct clksrc_clk clksrcs[] = {
 		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 20, .size = 4 },
 	}, {
 		.clk		= {
-			.name		= "sclk_cam",
-			.devname	= "s5pv210-fimc.0",
+			.name		= "sclk_cam0",
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 3),
 		},
@@ -889,8 +888,7 @@ static struct clksrc_clk clksrcs[] = {
 		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 },
 	}, {
 		.clk		= {
-			.name		= "sclk_cam",
-			.devname	= "s5pv210-fimc.1",
+			.name		= "sclk_cam1",
 			.enable		= s5pv210_clk_mask0_ctrl,
 			.ctrlbit	= (1 << 4),
 		},
-- 
1.7.6.3

^ permalink raw reply related

* [PATCH v3 0/4] ARM: Samsung: Add board setup for M-5MOLS and NOON010PC30 camera sensors
From: Sylwester Nawrocki @ 2011-09-19 17:30 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

the following change set adds board setup code for NOOON01PC30 sensor on GONI 
and M-5MOLS on UNIVERSAL_C210 board.
Some clocks are modified in line with latest FIMC driver modifications for v3.2.

Changes since previous version:
 - improved error handling, switched to gpio_request_array()
 - created against git://github.com/kgene/linux-samsung.git for-next

Sylwester Nawrocki (4):
  ARM: S5PV210: Rename sclk_cam clocks for FIMC media driver
  ARM: S5PV210: Add support for NOON010PC30 sensor on GONI board
  ARM: EXYNOS4: Rename sclk_cam clocks for FIMC driver
  ARM: S5PV210: UNIVERSAL_C210: Add support for M-5MOLS image sensor

 arch/arm/mach-exynos4/Kconfig               |    3 +
 arch/arm/mach-exynos4/clock.c               |    6 +-
 arch/arm/mach-exynos4/mach-universal_c210.c |  206 +++++++++++++++++++++++++-
 arch/arm/mach-s5pv210/Kconfig               |    1 +
 arch/arm/mach-s5pv210/clock.c               |    6 +-
 arch/arm/mach-s5pv210/mach-goni.c           |   53 +++++++
 6 files changed, 259 insertions(+), 16 deletions(-)
-- 
1.7.6.3

The patches can be pulled from git://git.infradead.org/users/kmpark/linux-2.6-samsung, 
branch samsung-board-camera.

Thanks,
--
Sylwester Nawrocki
Samsung Poland R&D Center

^ permalink raw reply

* [PATCH] arm/dt: Add SoC detection macros
From: Allen Martin @ 2011-09-19 17:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110917112321.GE16381@n2100.arm.linux.org.uk>

> What I'm saying is that in that scenario it should not be necessary to edit the
> kernel to invent new SoC types, and then teach it that Tegra4 is mostly the
> same as Tegra3.  That information should all be encoded into the DT rather
> than the C code in the kernel.
> 
> So, I think adding this SoC type stuff is the wrong approach to the problem.

What ends up happening in practice for a lot of hw blocks inside the SoC, is that tegra4 is mostly the same as tegra3 with a few new registers and bug fixes that slightly change the programming model.  So either we have to add device quirks to teach device tree about the differences, and pass those in as flags to the driver, or we can do SoC detection at runtime in the driver.  It sounds like the consensus from you and Olof is that the first is preferable.

-Allen

^ permalink raw reply

* [PATCH] ARM: pl330: Fix a race condition
From: Javi Merino @ 2011-09-19 17:11 UTC (permalink / raw)
  To: linux-arm-kernel

If two requests have been submitted and one of them is running, if you
call pl330_chan_ctrl(ch_id, PL330_OP_START), there's a window of time
between the spin_lock_irqsave() and the _state() check in which the
running transaction may finish.  In that case, we don't receive the
interrupt (because they are disabled), but _start() sees that the DMA
is stopped, so it starts it.  The problem is that it sends the
transaction that has just finished again, because pl330_update()
hasn't mark it as done yet.

This patch moves the _state() check out of the critical section, which
removes the race condition.  It also treats PL330_STATE_COMPLETING as
still executing, because that introduces another race condition now
that we call _state() with interrupts enabled.  Namely, if we read the
state as "completing" and the DMA sends the interrupt before we
disable interrupts, pl330_update() starts the next transaction and
returns.  Then the _start() in pl330_chan_ctrl() will patiently wait
until the just issued transaction finishes (because the state we read
was PL330_STATE_COMPLETING) and when it does, it _trigger()s the same
transaction again.

Signed-off-by: Javi Merino <javi.merino@arm.com>
Cc: Jassi Brar <jassi.brar@samsung.com>
---
 arch/arm/common/pl330.c |   12 +++++++-----
 1 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c
index 97912fa..26b5615 100644
--- a/arch/arm/common/pl330.c
+++ b/arch/arm/common/pl330.c
@@ -936,9 +936,9 @@ static bool _trigger(struct pl330_thread *thrd)
 	return true;
 }
 
-static bool _start(struct pl330_thread *thrd)
+static bool _start(struct pl330_thread *thrd, u32 state)
 {
-	switch (_state(thrd)) {
+	switch (state) {
 	case PL330_STATE_FAULT_COMPLETING:
 		UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING);
 
@@ -949,7 +949,6 @@ static bool _start(struct pl330_thread *thrd)
 		_stop(thrd);
 
 	case PL330_STATE_KILLING:
-	case PL330_STATE_COMPLETING:
 		UNTIL(thrd, PL330_STATE_STOPPED)
 
 	case PL330_STATE_STOPPED:
@@ -961,6 +960,7 @@ static bool _start(struct pl330_thread *thrd)
 	case PL330_STATE_UPDTPC:
 	case PL330_STATE_CACHEMISS:
 	case PL330_STATE_EXECUTING:
+	case PL330_STATE_COMPLETING:
 		return true;
 
 	case PL330_STATE_WFE: /* For RESUME, nothing yet */
@@ -1471,7 +1471,7 @@ int pl330_update(const struct pl330_info *pi)
 			MARK_FREE(rqdone);
 
 			/* Get going again ASAP */
-			_start(thrd);
+			_start(thrd, _state(thrd));
 
 			/* For now, just make a list of callbacks to be done */
 			list_add_tail(&rqdone->rqd, &pl330->req_done);
@@ -1510,12 +1510,14 @@ int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op)
 	struct pl330_dmac *pl330;
 	unsigned long flags;
 	int ret = 0, active;
+	u32 dma_state;
 
 	if (!thrd || thrd->free || thrd->dmac->state == DYING)
 		return -EINVAL;
 
 	pl330 = thrd->dmac;
 
+	dma_state = _state(thrd);
 	spin_lock_irqsave(&pl330->lock, flags);
 
 	switch (op) {
@@ -1546,7 +1548,7 @@ int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op)
 
 		/* Start the next */
 	case PL330_OP_START:
-		if (!_start(thrd))
+		if (!_start(thrd, dma_state))
 			ret = -EIO;
 		break;
 
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH] ARM: BUG() dies silently
From: Russell King - ARM Linux @ 2011-09-19 16:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110919144313.GU16381@n2100.arm.linux.org.uk>

On Mon, Sep 19, 2011 at 03:43:13PM +0100, Russell King - ARM Linux wrote:
> On Mon, Sep 19, 2011 at 09:26:49AM -0500, Ramirez Luna, Omar wrote:
> > Hi
> > 
> > On Sat, Sep 17, 2011 at 1:07 AM, Rabin Vincent <rabin@rab.in> wrote:
> > > If the "Use generic BUG() handler" patch is only scheduled for the next
> > > merge window and not for 3.1, can this patch be merged instead for 3.1
> > > and -stable? ?This problem is easily seen with GCC 4.6.
> > 
> > I can send it for both and let the maintainers decide.
> > 
> > Russell, do you give your ack?
> 
> I think it's too large a change for -stable and 3.1 - let's get it into
> 3.2 first, and make sure no one sees any regressions there.  Then we can
> think about submitting it to stable once its proven itself.

And we're seeing link failures with the patch in the kernel, so it's
*definitely* not stable material as it stands, even if the current code
is a problem for GCC 4.6.

Regressions trump bug fixes.

^ permalink raw reply

* [PATCH 7/7] ARM: pm: add L2 cache cleaning for suspend
From: Russell King - ARM Linux @ 2011-09-19 16:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110919163741.GE16591@n2100.arm.linux.org.uk>

We need to ensure that state is pushed out from the L2 cache when
suspending so that the resume paths can access their data before the
MMU and caches have been re-initialized.  Add the necessary calls to
__cpu_suspend_save().

Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/kernel/suspend.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c
index 2d60f19..93a22d2 100644
--- a/arch/arm/kernel/suspend.c
+++ b/arch/arm/kernel/suspend.c
@@ -28,6 +28,9 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
 	cpu_do_suspend(ptr);
 
 	flush_cache_all();
+	outer_clean_range(*save_ptr, *save_ptr + ptrsz);
+	outer_clean_range(virt_to_phys(save_ptr),
+			  virt_to_phys(save_ptr) + sizeof(*save_ptr));
 }
 
 /*
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 6/7] ARM: pm: convert some assembly to C
From: Russell King - ARM Linux @ 2011-09-19 16:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110919163741.GE16591@n2100.arm.linux.org.uk>

Convert some of the sleep.S guts to C code, which makes it easier to
use our macros and to add L2 cache handling.  We provide a helper
function, __cpu_suspend_save(), which deals with saving the common
state, setting up for resume, and flushing caches.

The remainder left as assembly code is the saving of the CPU general
purpose registers, and allocating space on the stack to save the CPU
specific registers and resume state.

Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/include/asm/proc-fns.h |    8 ++++++
 arch/arm/kernel/sleep.S         |   53 ++++++++++++--------------------------
 arch/arm/kernel/suspend.c       |   24 +++++++++++++++--
 3 files changed, 46 insertions(+), 39 deletions(-)

diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index 633d1cb..9e92cb2 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -81,6 +81,10 @@ extern void cpu_dcache_clean_area(void *, int);
 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));
+
+/* These three are private to arch/arm/kernel/suspend.c */
+extern void cpu_do_suspend(void *);
+extern void cpu_do_resume(void *);
 #else
 #define cpu_proc_init			processor._proc_init
 #define cpu_proc_fin			processor._proc_fin
@@ -89,6 +93,10 @@ extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
 #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
+
+/* These three are private to arch/arm/kernel/suspend.c */
+#define cpu_do_suspend			processor.do_suspend
+#define cpu_do_resume			processor.do_resume
 #endif
 
 extern void cpu_resume(void);
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index c9a43ca..020e99c 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -8,54 +8,35 @@
 	.text
 
 /*
- * Save CPU state for a suspend
- *  r0 = phys addr of temporary page tables
- *  r1 = v:p offset
- *  r2 = suspend function arg0
- *  r3 = suspend function
+ * Save CPU state for a suspend.  This saves the CPU general purpose
+ * registers, and allocates space on the kernel stack to save the CPU
+ * specific registers and some other data for resume.
+ *  r0 = suspend function arg0
+ *  r1 = suspend function
  */
 ENTRY(__cpu_suspend)
 	stmfd	sp!, {r4 - r11, lr}
-	mov	r4, r0
 #ifdef MULTI_CPU
 	ldr	r10, =processor
-	ldr	r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
-	ldr	ip, [r10, #CPU_DO_RESUME] @ virtual resume function
+	ldr	r4, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
 #else
-	ldr	r5, =cpu_suspend_size
-	ldr	ip, =cpu_do_resume
+	ldr	r4, =cpu_suspend_size
 #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!, {r4, r6, ip}	@ save phys pgd, 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
+	mov	r5, sp			@ current virtual SP
+	add	r4, r4, #12		@ Space for pgd, virt sp, phys resume fn
+	sub	sp, sp, r4		@ allocate CPU state on stack
+	stmfd	sp!, {r0, r1}		@ save suspend func arg and pointer
+	add	r0, sp, #8		@ save pointer to save block
+	mov	r1, r4			@ size of save block
+	mov	r2, r5			@ virtual SP
+	ldr	r3, =sleep_save_sp
 #ifdef CONFIG_SMP
 	ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
 	ALT_UP(mov lr, #0)
 	and	lr, lr, #15
-	str	r6, [r5, lr, lsl #2]	@ save phys SP
-#else
-	str	r6, [r5]		@ save phys SP
-#endif
-#ifdef MULTI_CPU
-	mov	lr, pc
-	ldr	pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
-#else
-	bl	cpu_do_suspend
-#endif
-
-	@ flush data cache
-#ifdef MULTI_CACHE
-	ldr	r10, =cpu_cache
-	mov	lr, pc
-	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
-#else
-	bl	__cpuc_flush_kern_all
+	add	r3, r3, lr, lsl #2
 #endif
+	bl	__cpu_suspend_save
 	adr	lr, BSYM(cpu_suspend_abort)
 	ldmfd	sp!, {r0, pc}		@ call suspend fn
 ENDPROC(__cpu_suspend)
diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c
index ed4160b..2d60f19 100644
--- a/arch/arm/kernel/suspend.c
+++ b/arch/arm/kernel/suspend.c
@@ -8,10 +8,29 @@
 
 static pgd_t *suspend_pgd;
 
-extern int __cpu_suspend(int, long, unsigned long, int (*)(unsigned long));
+extern int __cpu_suspend(unsigned long, int (*)(unsigned long));
 extern void cpu_resume_mmu(void);
 
 /*
+ * This is called by __cpu_suspend() to save the state, and do whatever
+ * flushing is required to ensure that when the CPU goes to sleep we have
+ * the necessary data available when the caches are not searched.
+ */
+void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
+{
+	*save_ptr = virt_to_phys(ptr);
+
+	/* This must correspond to the LDM in cpu_resume() assembly */
+	*ptr++ = virt_to_phys(suspend_pgd);
+	*ptr++ = sp;
+	*ptr++ = virt_to_phys(cpu_do_resume);
+
+	cpu_do_suspend(ptr);
+
+	flush_cache_all();
+}
+
+/*
  * Hide the first two arguments to __cpu_suspend - these are an implementation
  * detail which platform code shouldn't have to know about.
  */
@@ -29,8 +48,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
 	 * resume (indicated by a zero return code), we need to switch
 	 * back to the correct page tables.
 	 */
-	ret = __cpu_suspend(virt_to_phys(suspend_pgd),
-			    PHYS_OFFSET - PAGE_OFFSET, arg, fn);
+	ret = __cpu_suspend(arg, fn);
 	if (ret == 0) {
 		cpu_switch_mm(mm->pgd, mm);
 		local_flush_tlb_all();
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 5/7] ARM: pm: get rid of cpu_resume_turn_mmu_on
From: Russell King - ARM Linux @ 2011-09-19 16:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110919163741.GE16591@n2100.arm.linux.org.uk>

We don't require cpu_resume_turn_mmu_on as we can combine the ldr
instruction with the following code provided we ensure that
cpu_resume_mmu is aligned for older CPUs.  Note that we also align
to a 32-byte boundary to ensure that the code can't cross a section
boundary.

Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/kernel/sleep.S   |    8 ++------
 arch/arm/kernel/suspend.c |    4 ++--
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index 25d42df..c9a43ca 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -72,19 +72,15 @@ ENDPROC(cpu_suspend_abort)
 /*
  * r0 = control register value
  */
+	.align	5
 ENTRY(cpu_resume_mmu)
 	ldr	r3, =cpu_resume_after_mmu
-	b	cpu_resume_turn_mmu_on
-ENDPROC(cpu_resume_mmu)
-	.ltorg
-	.align	5
-ENTRY(cpu_resume_turn_mmu_on)
 	mcr	p15, 0, r0, c1, c0, 0	@ turn on MMU, I-cache, etc
 	mrc	p15, 0, r0, c0, c0, 0	@ read id reg
 	mov	r0, r0
 	mov	r0, r0
 	mov	pc, r3			@ jump to virtual address
-ENDPROC(cpu_resume_turn_mmu_on)
+ENDPROC(cpu_resume_mmu)
 cpu_resume_after_mmu:
 	bl	cpu_init		@ restore the und/abt/irq banked regs
 	mov	r0, #0			@ return zero on success
diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c
index 2beda56..ed4160b 100644
--- a/arch/arm/kernel/suspend.c
+++ b/arch/arm/kernel/suspend.c
@@ -9,7 +9,7 @@
 static pgd_t *suspend_pgd;
 
 extern int __cpu_suspend(int, long, unsigned long, int (*)(unsigned long));
-extern void cpu_resume_turn_mmu_on(void);
+extern void cpu_resume_mmu(void);
 
 /*
  * Hide the first two arguments to __cpu_suspend - these are an implementation
@@ -43,7 +43,7 @@ static int __init cpu_suspend_init(void)
 {
 	suspend_pgd = pgd_alloc(&init_mm);
 	if (suspend_pgd) {
-		unsigned long addr = virt_to_phys(cpu_resume_turn_mmu_on);
+		unsigned long addr = virt_to_phys(cpu_resume_mmu);
 		identity_mapping_add(suspend_pgd, addr, addr + SECTION_SIZE);
 	}
 	return suspend_pgd ? 0 : -ENOMEM;
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 4/7] ARM: pm: no need to save/restore context ID register
From: Russell King - ARM Linux @ 2011-09-19 16:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110919163741.GE16591@n2100.arm.linux.org.uk>

There is no need to save and restore the context ID register on ARMv6
and ARMv7 with a temporary page table as we write the context ID
register when we switch back to the real page tables for the thread.

Moreover, the temporary page tables do not contain any non-global
mappings, so the context ID value should not be used.  To be safe,
initialize the register to a reserved context ID value.

Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/mm/proc-v6.S |   33 ++++++++++++++++-----------------
 arch/arm/mm/proc-v7.S |   13 ++++++-------
 2 files changed, 22 insertions(+), 24 deletions(-)

diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 2e27b46..d061d2f 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -128,19 +128,18 @@ ENTRY(cpu_v6_set_pte_ext)
 
 /* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
 .globl	cpu_v6_suspend_size
-.equ	cpu_v6_suspend_size, 4 * 7
+.equ	cpu_v6_suspend_size, 4 * 6
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_v6_do_suspend)
-	stmfd	sp!, {r4 - r10, lr}
+	stmfd	sp!, {r4 - r9, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mrc	p15, 0, r5, c13, c0, 1	@ Context ID
-	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r7, c2, c0, 1	@ Translation table base 1
-	mrc	p15, 0, r8, c1, c0, 1	@ auxiliary control register
-	mrc	p15, 0, r9, c1, c0, 2	@ co-processor access control
-	mrc	p15, 0, r10, c1, c0, 0	@ control register
-	stmia	r0, {r4 - r10}
-	ldmfd	sp!, {r4- r10, pc}
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 1	@ Translation table base 1
+	mrc	p15, 0, r7, c1, c0, 1	@ auxiliary control register
+	mrc	p15, 0, r8, c1, c0, 2	@ co-processor access control
+	mrc	p15, 0, r9, c1, c0, 0	@ control register
+	stmia	r0, {r4 - r9}
+	ldmfd	sp!, {r4- r9, pc}
 ENDPROC(cpu_v6_do_suspend)
 
 ENTRY(cpu_v6_do_resume)
@@ -149,19 +148,19 @@ ENTRY(cpu_v6_do_resume)
 	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
 	mcr	p15, 0, ip, c7, c15, 0	@ clean+invalidate cache
 	mcr	p15, 0, ip, c7, c10, 4	@ drain write buffer
-	ldmia	r0, {r4 - r10}
+	mcr	p15, 0, ip, c13, c0, 1	@ set reserved context ID
+	ldmia	r0, {r4 - r9}
 	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mcr	p15, 0, r5, c13, c0, 1	@ Context ID
-	mcr	p15, 0, r6, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
 	ALT_SMP(orr	r1, r1, #TTB_FLAGS_SMP)
 	ALT_UP(orr	r1, r1, #TTB_FLAGS_UP)
 	mcr	p15, 0, r1, c2, c0, 0	@ Translation table base 0
-	mcr	p15, 0, r7, c2, c0, 1	@ Translation table base 1
-	mcr	p15, 0, r8, c1, c0, 1	@ auxiliary control register
-	mcr	p15, 0, r9, c1, c0, 2	@ co-processor access control
+	mcr	p15, 0, r6, c2, c0, 1	@ Translation table base 1
+	mcr	p15, 0, r7, c1, c0, 1	@ auxiliary control register
+	mcr	p15, 0, r8, c1, c0, 2	@ co-processor access control
 	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
 	mcr	p15, 0, ip, c7, c5, 4	@ ISB
-	mov	r0, r10			@ control register
+	mov	r0, r9			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_v6_do_resume)
 #endif
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index b56004f..6af366c 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -217,14 +217,13 @@ ENDPROC(cpu_v7_set_pte_ext)
 
 /* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
 .globl	cpu_v7_suspend_size
-.equ	cpu_v7_suspend_size, 4 * 8
+.equ	cpu_v7_suspend_size, 4 * 7
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_v7_do_suspend)
 	stmfd	sp!, {r4 - r10, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mrc	p15, 0, r5, c13, c0, 1	@ Context ID
-	mrc	p15, 0, r6, c13, c0, 3	@ User r/o thread ID
-	stmia	r0!, {r4 - r6}
+	mrc	p15, 0, r5, c13, c0, 3	@ User r/o thread ID
+	stmia	r0!, {r4 - r5}
 	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
 	mrc	p15, 0, r7, c2, c0, 1	@ TTB 1
 	mrc	p15, 0, r8, c1, c0, 0	@ Control register
@@ -238,10 +237,10 @@ ENTRY(cpu_v7_do_resume)
 	mov	ip, #0
 	mcr	p15, 0, ip, c8, c7, 0	@ invalidate TLBs
 	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
-	ldmia	r0!, {r4 - r6}
+	mcr	p15, 0, ip, c13, c0, 1	@ set reserved context ID
+	ldmia	r0!, {r4 - r5}
 	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mcr	p15, 0, r5, c13, c0, 1	@ Context ID
-	mcr	p15, 0, r6, c13, c0, 3	@ User r/o thread ID
+	mcr	p15, 0, r5, c13, c0, 3	@ User r/o thread ID
 	ldmia	r0, {r6 - r10}
 	mcr	p15, 0, r6, c3, c0, 0	@ Domain ID
 	ALT_SMP(orr	r1, r1, #TTB_FLAGS_SMP)
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 3/7] ARM: pm: only use preallocated page table during resume
From: Russell King - ARM Linux @ 2011-09-19 16:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110919163741.GE16591@n2100.arm.linux.org.uk>

Only use the preallocated page table during the resume, not while
suspending.  This avoids the overhead of having to switch unnecessarily
to the resume page table in the suspend path.

Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/kernel/sleep.S   |   19 +++++++++----------
 arch/arm/kernel/suspend.c |   17 ++++++++++-------
 arch/arm/mm/proc-arm920.S |   17 ++++++++---------
 arch/arm/mm/proc-arm926.S |   17 ++++++++---------
 arch/arm/mm/proc-sa1100.S |   21 ++++++++++-----------
 arch/arm/mm/proc-v6.S     |   31 ++++++++++++++++---------------
 arch/arm/mm/proc-v7.S     |   33 +++++++++++++++++----------------
 arch/arm/mm/proc-xsc3.S   |   22 +++++++++++-----------
 arch/arm/mm/proc-xscale.S |   21 ++++++++++-----------
 9 files changed, 99 insertions(+), 99 deletions(-)

diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index 8cf13de..25d42df 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -9,12 +9,14 @@
 
 /*
  * Save CPU state for a suspend
+ *  r0 = phys addr of temporary page tables
  *  r1 = v:p offset
  *  r2 = suspend function arg0
  *  r3 = suspend function
  */
 ENTRY(__cpu_suspend)
 	stmfd	sp!, {r4 - r11, lr}
+	mov	r4, r0
 #ifdef MULTI_CPU
 	ldr	r10, =processor
 	ldr	r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
@@ -27,7 +29,7 @@ ENTRY(__cpu_suspend)
 	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!, {r6, ip}		@ save virt SP, phys resume fn
+	stmfd	sp!, {r4, r6, ip}	@ save phys pgd, 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
@@ -60,7 +62,7 @@ ENDPROC(__cpu_suspend)
 	.ltorg
 
 cpu_suspend_abort:
-	ldmia	sp!, {r2 - r3}		@ pop virt SP, phys resume fn
+	ldmia	sp!, {r1 - r3}		@ pop phys pgd, virt SP, phys resume fn
 	teq	r0, #0
 	moveq	r0, #1			@ force non-zero value
 	mov	sp, r2
@@ -69,9 +71,6 @@ ENDPROC(cpu_suspend_abort)
 
 /*
  * r0 = control register value
- * r1 = v:p offset (preserved by cpu_do_resume)
- * r2 = phys page table base
- * r3 = L1 section flags
  */
 ENTRY(cpu_resume_mmu)
 	ldr	r3, =cpu_resume_after_mmu
@@ -112,11 +111,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
-	@ load stack, resume fn
-  ARM(	ldmia	r0!, {sp, pc}	)
-THUMB(	ldmia	r0!, {r2, r3}	)
-THUMB(	mov	sp, r2		)
-THUMB(	bx	r3		)
+	@ load phys pgd, stack, resume fn
+  ARM(	ldmia	r0!, {r1, sp, pc}	)
+THUMB(	ldmia	r0!, {r1, r2, r3}	)
+THUMB(	mov	sp, r2			)
+THUMB(	bx	r3			)
 ENDPROC(cpu_resume)
 
 sleep_save_sp:
diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c
index 0a33f10..2beda56 100644
--- a/arch/arm/kernel/suspend.c
+++ b/arch/arm/kernel/suspend.c
@@ -24,14 +24,17 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
 		return -EINVAL;
 
 	/*
-	 * Temporarily switch the page tables to our suspend page
-	 * tables, which contain the temporary identity mapping
-	 * required for resuming.
+	 * Provide a temporary page table with an identity mapping for
+	 * the MMU-enable code, required for resuming.  On successful
+	 * resume (indicated by a zero return code), we need to switch
+	 * back to the correct page tables.
 	 */
-	cpu_switch_mm(suspend_pgd, mm);
-	ret = __cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn);
-	cpu_switch_mm(mm->pgd, mm);
-	local_flush_tlb_all();
+	ret = __cpu_suspend(virt_to_phys(suspend_pgd),
+			    PHYS_OFFSET - PAGE_OFFSET, arg, fn);
+	if (ret == 0) {
+		cpu_switch_mm(mm->pgd, mm);
+		local_flush_tlb_all();
+	}
 
 	return ret;
 }
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 035d57b..88fb3d9 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -379,27 +379,26 @@ ENTRY(cpu_arm920_set_pte_ext)
 
 /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 .globl	cpu_arm920_suspend_size
-.equ	cpu_arm920_suspend_size, 4 * 4
+.equ	cpu_arm920_suspend_size, 4 * 3
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_arm920_do_suspend)
-	stmfd	sp!, {r4 - r7, lr}
+	stmfd	sp!, {r4 - r6, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ PID
 	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
-	mrc	p15, 0, r7, c1, c0, 0	@ Control register
-	stmia	r0, {r4 - r7}
-	ldmfd	sp!, {r4 - r7, pc}
+	mrc	p15, 0, r6, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r6}
+	ldmfd	sp!, {r4 - r6, pc}
 ENDPROC(cpu_arm920_do_suspend)
 
 ENTRY(cpu_arm920_do_resume)
 	mov	ip, #0
 	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
 	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
-	ldmia	r0, {r4 - r7}
+	ldmia	r0, {r4 - r6}
 	mcr	p15, 0, r4, c13, c0, 0	@ PID
 	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
-	mov	r0, r7			@ control register
+	mcr	p15, 0, r1, c2, c0, 0	@ TTB address
+	mov	r0, r6			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_arm920_do_resume)
 #endif
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 48add84..9f8fd91 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -394,27 +394,26 @@ ENTRY(cpu_arm926_set_pte_ext)
 
 /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 .globl	cpu_arm926_suspend_size
-.equ	cpu_arm926_suspend_size, 4 * 4
+.equ	cpu_arm926_suspend_size, 4 * 3
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_arm926_do_suspend)
-	stmfd	sp!, {r4 - r7, lr}
+	stmfd	sp!, {r4 - r6, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ PID
 	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
-	mrc	p15, 0, r7, c1, c0, 0	@ Control register
-	stmia	r0, {r4 - r7}
-	ldmfd	sp!, {r4 - r7, pc}
+	mrc	p15, 0, r6, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r6}
+	ldmfd	sp!, {r4 - r6, pc}
 ENDPROC(cpu_arm926_do_suspend)
 
 ENTRY(cpu_arm926_do_resume)
 	mov	ip, #0
 	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
 	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
-	ldmia	r0, {r4 - r7}
+	ldmia	r0, {r4 - r6}
 	mcr	p15, 0, r4, c13, c0, 0	@ PID
 	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
-	mov	r0, r7			@ control register
+	mcr	p15, 0, r1, c2, c0, 0	@ TTB address
+	mov	r0, r6			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_arm926_do_resume)
 #endif
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 52f73fb..7d91545 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -168,20 +168,19 @@ ENTRY(cpu_sa1100_set_pte_ext)
 	mov	pc, lr
 
 .globl	cpu_sa1100_suspend_size
-.equ	cpu_sa1100_suspend_size, 4*4
+.equ	cpu_sa1100_suspend_size, 4 * 3
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_sa1100_do_suspend)
-	stmfd	sp!, {r4 - r7, lr}
+	stmfd	sp!, {r4 - r6, lr}
 	mrc	p15, 0, r4, c3, c0, 0		@ domain ID
-	mrc	p15, 0, r5, c2, c0, 0		@ translation table base addr
-	mrc	p15, 0, r6, c13, c0, 0		@ PID
-	mrc	p15, 0, r7, c1, c0, 0		@ control reg
-	stmia	r0, {r4 - r7}			@ store cp regs
-	ldmfd	sp!, {r4 - r7, pc}
+	mrc	p15, 0, r5, c13, c0, 0		@ PID
+	mrc	p15, 0, r6, c1, c0, 0		@ control reg
+	stmia	r0, {r4 - r6}			@ store cp regs
+	ldmfd	sp!, {r4 - r6, pc}
 ENDPROC(cpu_sa1100_do_suspend)
 
 ENTRY(cpu_sa1100_do_resume)
-	ldmia	r0, {r4 - r7}			@ load cp regs
+	ldmia	r0, {r4 - r6}			@ load cp regs
 	mov	ip, #0
 	mcr	p15, 0, ip, c8, c7, 0		@ flush I+D TLBs
 	mcr	p15, 0, ip, c7, c7, 0		@ flush I&D cache
@@ -189,9 +188,9 @@ ENTRY(cpu_sa1100_do_resume)
 	mcr	p15, 0, ip, c9, c0, 5		@ allow user space to use RB
 
 	mcr	p15, 0, r4, c3, c0, 0		@ domain ID
-	mcr	p15, 0, r5, c2, c0, 0		@ translation table base addr
-	mcr	p15, 0, r6, c13, c0, 0		@ PID
-	mov	r0, r7				@ control register
+	mcr	p15, 0, r1, c2, c0, 0		@ translation table base addr
+	mcr	p15, 0, r5, c13, c0, 0		@ PID
+	mov	r0, r6				@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_sa1100_do_resume)
 #endif
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 414e369..2e27b46 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -128,20 +128,19 @@ ENTRY(cpu_v6_set_pte_ext)
 
 /* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
 .globl	cpu_v6_suspend_size
-.equ	cpu_v6_suspend_size, 4 * 8
+.equ	cpu_v6_suspend_size, 4 * 7
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_v6_do_suspend)
-	stmfd	sp!, {r4 - r11, lr}
+	stmfd	sp!, {r4 - r10, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
 	mrc	p15, 0, r5, c13, c0, 1	@ Context ID
 	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r7, c2, c0, 0	@ Translation table base 0
-	mrc	p15, 0, r8, c2, c0, 1	@ Translation table base 1
-	mrc	p15, 0, r9, c1, c0, 1	@ auxiliary control register
-	mrc	p15, 0, r10, c1, c0, 2	@ co-processor access control
-	mrc	p15, 0, r11, c1, c0, 0	@ control register
-	stmia	r0, {r4 - r11}
-	ldmfd	sp!, {r4- r11, pc}
+	mrc	p15, 0, r7, c2, c0, 1	@ Translation table base 1
+	mrc	p15, 0, r8, c1, c0, 1	@ auxiliary control register
+	mrc	p15, 0, r9, c1, c0, 2	@ co-processor access control
+	mrc	p15, 0, r10, c1, c0, 0	@ control register
+	stmia	r0, {r4 - r10}
+	ldmfd	sp!, {r4- r10, pc}
 ENDPROC(cpu_v6_do_suspend)
 
 ENTRY(cpu_v6_do_resume)
@@ -150,17 +149,19 @@ ENTRY(cpu_v6_do_resume)
 	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
 	mcr	p15, 0, ip, c7, c15, 0	@ clean+invalidate cache
 	mcr	p15, 0, ip, c7, c10, 4	@ drain write buffer
-	ldmia	r0, {r4 - r11}
+	ldmia	r0, {r4 - r10}
 	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
 	mcr	p15, 0, r5, c13, c0, 1	@ Context ID
 	mcr	p15, 0, r6, c3, c0, 0	@ Domain ID
-	mcr	p15, 0, r7, c2, c0, 0	@ Translation table base 0
-	mcr	p15, 0, r8, c2, c0, 1	@ Translation table base 1
-	mcr	p15, 0, r9, c1, c0, 1	@ auxiliary control register
-	mcr	p15, 0, r10, c1, c0, 2	@ co-processor access control
+	ALT_SMP(orr	r1, r1, #TTB_FLAGS_SMP)
+	ALT_UP(orr	r1, r1, #TTB_FLAGS_UP)
+	mcr	p15, 0, r1, c2, c0, 0	@ Translation table base 0
+	mcr	p15, 0, r7, c2, c0, 1	@ Translation table base 1
+	mcr	p15, 0, r8, c1, c0, 1	@ auxiliary control register
+	mcr	p15, 0, r9, c1, c0, 2	@ co-processor access control
 	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
 	mcr	p15, 0, ip, c7, c5, 4	@ ISB
-	mov	r0, r11			@ control register
+	mov	r0, r10			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_v6_do_resume)
 #endif
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 21d6910..b56004f 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -217,22 +217,21 @@ ENDPROC(cpu_v7_set_pte_ext)
 
 /* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
 .globl	cpu_v7_suspend_size
-.equ	cpu_v7_suspend_size, 4 * 9
+.equ	cpu_v7_suspend_size, 4 * 8
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_v7_do_suspend)
-	stmfd	sp!, {r4 - r11, lr}
+	stmfd	sp!, {r4 - r10, lr}
 	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
 	mrc	p15, 0, r5, c13, c0, 1	@ Context ID
 	mrc	p15, 0, r6, c13, c0, 3	@ User r/o thread ID
 	stmia	r0!, {r4 - r6}
 	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r7, c2, c0, 0	@ TTB 0
-	mrc	p15, 0, r8, c2, c0, 1	@ TTB 1
-	mrc	p15, 0, r9, c1, c0, 0	@ Control register
-	mrc	p15, 0, r10, c1, c0, 1	@ Auxiliary control register
-	mrc	p15, 0, r11, c1, c0, 2	@ Co-processor access control
-	stmia	r0, {r6 - r11}
-	ldmfd	sp!, {r4 - r11, pc}
+	mrc	p15, 0, r7, c2, c0, 1	@ TTB 1
+	mrc	p15, 0, r8, c1, c0, 0	@ Control register
+	mrc	p15, 0, r9, c1, c0, 1	@ Auxiliary control register
+	mrc	p15, 0, r10, c1, c0, 2	@ Co-processor access control
+	stmia	r0, {r6 - r10}
+	ldmfd	sp!, {r4 - r10, pc}
 ENDPROC(cpu_v7_do_suspend)
 
 ENTRY(cpu_v7_do_resume)
@@ -243,22 +242,24 @@ ENTRY(cpu_v7_do_resume)
 	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
 	mcr	p15, 0, r5, c13, c0, 1	@ Context ID
 	mcr	p15, 0, r6, c13, c0, 3	@ User r/o thread ID
-	ldmia	r0, {r6 - r11}
+	ldmia	r0, {r6 - r10}
 	mcr	p15, 0, r6, c3, c0, 0	@ Domain ID
-	mcr	p15, 0, r7, c2, c0, 0	@ TTB 0
-	mcr	p15, 0, r8, c2, c0, 1	@ TTB 1
+	ALT_SMP(orr	r1, r1, #TTB_FLAGS_SMP)
+	ALT_UP(orr	r1, r1, #TTB_FLAGS_UP)
+	mcr	p15, 0, r1, c2, c0, 0	@ TTB 0
+	mcr	p15, 0, r7, c2, c0, 1	@ TTB 1
 	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
 	mrc	p15, 0, r4, c1, c0, 1	@ Read Auxiliary control register
-	teq	r4, r10			@ Is it already set?
-	mcrne	p15, 0, r10, c1, c0, 1	@ No, so write it
-	mcr	p15, 0, r11, c1, c0, 2	@ Co-processor access control
+	teq	r4, r9			@ Is it already set?
+	mcrne	p15, 0, r9, c1, c0, 1	@ No, so write it
+	mcr	p15, 0, r10, c1, c0, 2	@ Co-processor access control
 	ldr	r4, =PRRR		@ PRRR
 	ldr	r5, =NMRR		@ NMRR
 	mcr	p15, 0, r4, c10, c2, 0	@ write PRRR
 	mcr	p15, 0, r5, c10, c2, 1	@ write NMRR
 	isb
 	dsb
-	mov	r0, r9			@ control register
+	mov	r0, r8			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_v7_do_resume)
 #endif
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index efd4949..abf0507 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -406,24 +406,23 @@ ENTRY(cpu_xsc3_set_pte_ext)
 	.align
 
 .globl	cpu_xsc3_suspend_size
-.equ	cpu_xsc3_suspend_size, 4 * 7
+.equ	cpu_xsc3_suspend_size, 4 * 6
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_xsc3_do_suspend)
-	stmfd	sp!, {r4 - r10, lr}
+	stmfd	sp!, {r4 - r9, lr}
 	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
 	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
 	mrc	p15, 0, r6, c13, c0, 0	@ PID
 	mrc 	p15, 0, r7, c3, c0, 0	@ domain ID
-	mrc 	p15, 0, r8, c2, c0, 0	@ translation table base addr
-	mrc	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
-	mrc 	p15, 0, r10, c1, c0, 0	@ control reg
+	mrc	p15, 0, r8, c1, c0, 1	@ auxiliary control reg
+	mrc 	p15, 0, r9, c1, c0, 0	@ control reg
 	bic	r4, r4, #2		@ clear frequency change bit
-	stmia	r0, {r4 - r10}		@ store cp regs
-	ldmia	sp!, {r4 - r10, pc}
+	stmia	r0, {r4 - r9}		@ store cp regs
+	ldmia	sp!, {r4 - r9, pc}
 ENDPROC(cpu_xsc3_do_suspend)
 
 ENTRY(cpu_xsc3_do_resume)
-	ldmia	r0, {r4 - r10}		@ load cp regs
+	ldmia	r0, {r4 - r9}		@ load cp regs
 	mov	ip, #0
 	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
 	mcr	p15, 0, ip, c7, c10, 4	@ drain write (&fill) buffer
@@ -433,9 +432,10 @@ ENTRY(cpu_xsc3_do_resume)
 	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
 	mcr	p15, 0, r6, c13, c0, 0	@ PID
 	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
-	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
-	mcr	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
-	mov	r0, r10			@ control register
+	orr	r1, r1, #0x18		@ cache the page table in L2
+	mcr	p15, 0, r1, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r8, c1, c0, 1	@ auxiliary control reg
+	mov	r0, r9			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_xsc3_do_resume)
 #endif
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 37dbada..3277904 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -520,24 +520,23 @@ ENTRY(cpu_xscale_set_pte_ext)
 	.align
 
 .globl	cpu_xscale_suspend_size
-.equ	cpu_xscale_suspend_size, 4 * 7
+.equ	cpu_xscale_suspend_size, 4 * 6
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_xscale_do_suspend)
-	stmfd	sp!, {r4 - r10, lr}
+	stmfd	sp!, {r4 - r9, lr}
 	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
 	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
 	mrc	p15, 0, r6, c13, c0, 0	@ PID
 	mrc	p15, 0, r7, c3, c0, 0	@ domain ID
-	mrc	p15, 0, r8, c2, c0, 0	@ translation table base addr
-	mrc	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
-	mrc	p15, 0, r10, c1, c0, 0	@ control reg
+	mrc	p15, 0, r8, c1, c1, 0	@ auxiliary control reg
+	mrc	p15, 0, r9, c1, c0, 0	@ control reg
 	bic	r4, r4, #2		@ clear frequency change bit
-	stmia	r0, {r4 - r10}		@ store cp regs
-	ldmfd	sp!, {r4 - r10, pc}
+	stmia	r0, {r4 - r9}		@ store cp regs
+	ldmfd	sp!, {r4 - r9, pc}
 ENDPROC(cpu_xscale_do_suspend)
 
 ENTRY(cpu_xscale_do_resume)
-	ldmia	r0, {r4 - r10}		@ load cp regs
+	ldmia	r0, {r4 - r9}		@ load cp regs
 	mov	ip, #0
 	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I & D TLBs
 	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
@@ -545,9 +544,9 @@ ENTRY(cpu_xscale_do_resume)
 	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
 	mcr	p15, 0, r6, c13, c0, 0	@ PID
 	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
-	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
-	mcr	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
-	mov	r0, r10			@ control register
+	mcr	p15, 0, r1, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r8, c1, c1, 0	@ auxiliary control reg
+	mov	r0, r9			@ control register
 	b	cpu_resume_mmu
 ENDPROC(cpu_xscale_do_resume)
 #endif
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 2/7] ARM: pm: preallocate a page table for suspend/resume
From: Russell King - ARM Linux @ 2011-09-19 16:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110919163741.GE16591@n2100.arm.linux.org.uk>

Preallocate a page table and setup an identity mapping for the MMU
enable code.  This means we don't have to "borrow" a page table to
do this, avoiding complexities with L2 cache coherency.

Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/include/asm/suspend.h |   17 +-------------
 arch/arm/kernel/Makefile       |    2 +-
 arch/arm/kernel/sleep.S        |   33 ++++++++++-----------------
 arch/arm/kernel/suspend.c      |   48 ++++++++++++++++++++++++++++++++++++++++
 arch/arm/mm/proc-arm920.S      |    4 ---
 arch/arm/mm/proc-arm926.S      |    4 ---
 arch/arm/mm/proc-sa1100.S      |    4 ---
 arch/arm/mm/proc-v6.S          |    6 -----
 arch/arm/mm/proc-v7.S          |    6 -----
 arch/arm/mm/proc-xsc3.S        |    6 -----
 arch/arm/mm/proc-xscale.S      |    4 ---
 11 files changed, 62 insertions(+), 72 deletions(-)
 create mode 100644 arch/arm/kernel/suspend.c

diff --git a/arch/arm/include/asm/suspend.h b/arch/arm/include/asm/suspend.h
index b0e4e1a..1c0a551 100644
--- a/arch/arm/include/asm/suspend.h
+++ b/arch/arm/include/asm/suspend.h
@@ -1,22 +1,7 @@
 #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;
-}
+extern int cpu_suspend(unsigned long, int (*)(unsigned long));
 
 #endif
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index f7887dc..787b888 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -29,7 +29,7 @@ obj-$(CONFIG_MODULES)		+= armksyms.o module.o
 obj-$(CONFIG_ARTHUR)		+= arthur.o
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
 obj-$(CONFIG_PCI)		+= bios32.o isa.o
-obj-$(CONFIG_PM_SLEEP)		+= sleep.o
+obj-$(CONFIG_PM_SLEEP)		+= sleep.o suspend.o
 obj-$(CONFIG_HAVE_SCHED_CLOCK)	+= sched_clock.o
 obj-$(CONFIG_SMP)		+= smp.o smp_tlb.o
 obj-$(CONFIG_HAVE_ARM_SCU)	+= smp_scu.o
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index 46a9f46..8cf13de 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -27,7 +27,7 @@ ENTRY(__cpu_suspend)
 	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, r6, ip}	@ save v:p, virt SP, phys resume fn
+	stmfd	sp!, {r6, ip}		@ save 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
@@ -60,7 +60,7 @@ ENDPROC(__cpu_suspend)
 	.ltorg
 
 cpu_suspend_abort:
-	ldmia	sp!, {r1 - r3}		@ pop v:p, virt SP, phys resume fn
+	ldmia	sp!, {r2 - r3}		@ pop virt SP, phys resume fn
 	teq	r0, #0
 	moveq	r0, #1			@ force non-zero value
 	mov	sp, r2
@@ -74,28 +74,19 @@ ENDPROC(cpu_suspend_abort)
  * r3 = L1 section flags
  */
 ENTRY(cpu_resume_mmu)
-	adr	r4, cpu_resume_turn_mmu_on
-	mov	r4, r4, lsr #20
-	orr	r3, r3, r4, lsl #20
-	ldr	r5, [r2, r4, lsl #2]	@ save old mapping
-	str	r3, [r2, r4, lsl #2]	@ setup 1:1 mapping for mmu code
-	sub	r2, r2, r1
 	ldr	r3, =cpu_resume_after_mmu
-	bic	r1, r0, #CR_C		@ ensure D-cache is disabled
 	b	cpu_resume_turn_mmu_on
 ENDPROC(cpu_resume_mmu)
 	.ltorg
 	.align	5
-cpu_resume_turn_mmu_on:
-	mcr	p15, 0, r1, c1, c0, 0	@ turn on MMU, I-cache, etc
-	mrc	p15, 0, r1, c0, c0, 0	@ read id reg
-	mov	r1, r1
-	mov	r1, r1
+ENTRY(cpu_resume_turn_mmu_on)
+	mcr	p15, 0, r0, c1, c0, 0	@ turn on MMU, I-cache, etc
+	mrc	p15, 0, r0, c0, c0, 0	@ read id reg
+	mov	r0, r0
+	mov	r0, r0
 	mov	pc, r3			@ jump to virtual address
 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
 	bl	cpu_init		@ restore the und/abt/irq banked regs
 	mov	r0, #0			@ return zero on success
 	ldmfd	sp!, {r4 - r11, pc}
@@ -121,11 +112,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
-	@ load v:p, stack, resume fn
-  ARM(	ldmia	r0!, {r1, sp, pc}	)
-THUMB(	ldmia	r0!, {r1, r2, r3}	)
-THUMB(	mov	sp, r2			)
-THUMB(	bx	r3			)
+	@ load stack, resume fn
+  ARM(	ldmia	r0!, {sp, pc}	)
+THUMB(	ldmia	r0!, {r2, r3}	)
+THUMB(	mov	sp, r2		)
+THUMB(	bx	r3		)
 ENDPROC(cpu_resume)
 
 sleep_save_sp:
diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c
new file mode 100644
index 0000000..0a33f10
--- /dev/null
+++ b/arch/arm/kernel/suspend.c
@@ -0,0 +1,48 @@
+#include <linux/init.h>
+
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/memory.h>
+#include <asm/suspend.h>
+#include <asm/tlbflush.h>
+
+static pgd_t *suspend_pgd;
+
+extern int __cpu_suspend(int, long, unsigned long, int (*)(unsigned long));
+extern void cpu_resume_turn_mmu_on(void);
+
+/*
+ * Hide the first two arguments to __cpu_suspend - these are an implementation
+ * detail which platform code shouldn't have to know about.
+ */
+int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
+{
+	struct mm_struct *mm = current->active_mm;
+	int ret;
+
+	if (!suspend_pgd)
+		return -EINVAL;
+
+	/*
+	 * Temporarily switch the page tables to our suspend page
+	 * tables, which contain the temporary identity mapping
+	 * required for resuming.
+	 */
+	cpu_switch_mm(suspend_pgd, mm);
+	ret = __cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn);
+	cpu_switch_mm(mm->pgd, mm);
+	local_flush_tlb_all();
+
+	return ret;
+}
+
+static int __init cpu_suspend_init(void)
+{
+	suspend_pgd = pgd_alloc(&init_mm);
+	if (suspend_pgd) {
+		unsigned long addr = virt_to_phys(cpu_resume_turn_mmu_on);
+		identity_mapping_add(suspend_pgd, addr, addr + SECTION_SIZE);
+	}
+	return suspend_pgd ? 0 : -ENOMEM;
+}
+core_initcall(cpu_suspend_init);
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 2e6849b..035d57b 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -400,10 +400,6 @@ ENTRY(cpu_arm920_do_resume)
 	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
 	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
 	mov	r0, r7			@ control register
-	mov	r2, r6, lsr #14		@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
-		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
 	b	cpu_resume_mmu
 ENDPROC(cpu_arm920_do_resume)
 #endif
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index cd8f79c..48add84 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -415,10 +415,6 @@ ENTRY(cpu_arm926_do_resume)
 	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
 	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
 	mov	r0, r7			@ control register
-	mov	r2, r6, lsr #14		@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
-		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
 	b	cpu_resume_mmu
 ENDPROC(cpu_arm926_do_resume)
 #endif
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 69e7f2e..52f73fb 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -192,10 +192,6 @@ ENTRY(cpu_sa1100_do_resume)
 	mcr	p15, 0, r5, c2, c0, 0		@ translation table base addr
 	mcr	p15, 0, r6, c13, c0, 0		@ PID
 	mov	r0, r7				@ control register
-	mov	r2, r5, lsr #14			@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
-		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
 	b	cpu_resume_mmu
 ENDPROC(cpu_sa1100_do_resume)
 #endif
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index a923aa0..414e369 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -161,14 +161,8 @@ ENTRY(cpu_v6_do_resume)
 	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
 	mcr	p15, 0, ip, c7, c5, 4	@ ISB
 	mov	r0, r11			@ control register
-	mov	r2, r7, lsr #14		@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, cpu_resume_l1_flags
 	b	cpu_resume_mmu
 ENDPROC(cpu_v6_do_resume)
-cpu_resume_l1_flags:
-	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
-	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
 #endif
 
 	string	cpu_v6_name, "ARMv6-compatible processor"
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 9049c07..21d6910 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -259,14 +259,8 @@ ENTRY(cpu_v7_do_resume)
 	isb
 	dsb
 	mov	r0, r9			@ control register
-	mov	r2, r7, lsr #14		@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, cpu_resume_l1_flags
 	b	cpu_resume_mmu
 ENDPROC(cpu_v7_do_resume)
-cpu_resume_l1_flags:
-	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
-	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
 #endif
 
 	__CPUINIT
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index 755e1bf..efd4949 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -435,13 +435,7 @@ ENTRY(cpu_xsc3_do_resume)
 	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
 	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
 	mcr	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
-
-	@ temporarily map resume_turn_on_mmu into the page table,
-	@ otherwise prefetch abort occurs after MMU is turned on
 	mov	r0, r10			@ control register
-	mov	r2, r8, lsr #14		@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, =0x542e		@ section flags
 	b	cpu_resume_mmu
 ENDPROC(cpu_xsc3_do_resume)
 #endif
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index fbc06e5..37dbada 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -548,10 +548,6 @@ ENTRY(cpu_xscale_do_resume)
 	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
 	mcr	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
 	mov	r0, r10			@ control register
-	mov	r2, r8, lsr #14		@ get TTB0 base
-	mov	r2, r2, lsl #14
-	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
-		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
 	b	cpu_resume_mmu
 ENDPROC(cpu_xscale_do_resume)
 #endif
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 1/7] ARM: pm: force non-zero return value from __cpu_suspend when aborting
From: Russell King - ARM Linux @ 2011-09-19 16:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110919163741.GE16591@n2100.arm.linux.org.uk>

Ensure that the return value from __cpu_suspend is non-zero when
aborting.  Zero indicates a successful suspend occurred.

Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/kernel/sleep.S |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index dc902f2..46a9f46 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -61,6 +61,8 @@ ENDPROC(__cpu_suspend)
 
 cpu_suspend_abort:
 	ldmia	sp!, {r1 - r3}		@ pop v:p, virt SP, phys resume fn
+	teq	r0, #0
+	moveq	r0, #1			@ force non-zero value
 	mov	sp, r2
 	ldmfd	sp!, {r4 - r11, pc}
 ENDPROC(cpu_suspend_abort)
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 0/7] Add L2 cache cleaning to generic CPU suspend
From: Russell King - ARM Linux @ 2011-09-19 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

This is a re-post of the previous patch series, but with an additional
TLB flush to ensure that hte global TLB entry in the page tables is
flushed out.  This is a flush of all TLB entries, but it could probably
be more targetted if we need to.

Original cover mail follows:

Some systems (such as OMAP) preserve the L2 cache across a suspend/
resume cycle.  This means they do not perform L2 cache maintanence
in their suspend finisher function.

However, the side effect is that the saved CPU state is not readable
by the resume code because it is sitting in the L2 cache.

This patch series adds L2 cache cleaning to the generic CPU suspend/
resume support code, making it possible to use this on systems with
L2 cache enabled without having to clean/invalidate the entire L2
cache.

We also add a separate page table, allocated at boot time, for the
resume process to use so we don't have to fiddle about with tweaking
entries in the current processes page table.  Moreover, the current
processes page table may be in use by another CPU in the system if
these paths are used from cpuidle or hotplug, so changing the page
table is technically unsound.

Overall, this makes it possible for OMAP4 systems to use this code.

^ permalink raw reply

* [PATCH 10/11] ARM: pm: convert some assembly to C
From: Russell King - ARM Linux @ 2011-09-19 16:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110907154828.GA21987@e102568-lin.cambridge.arm.com>

On Wed, Sep 07, 2011 at 04:48:28PM +0100, Lorenzo Pieralisi wrote:
> > @@ -29,8 +48,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
> >  	 * resume (indicated by a zero return code), we need to switch
> >  	 * back to the correct page tables.
> >  	 */
> > -	ret = __cpu_suspend(virt_to_phys(suspend_pgd),
> > -			    PHYS_OFFSET - PAGE_OFFSET, arg, fn);
> > +	ret = __cpu_suspend(arg, fn);
> >  	if (ret == 0)
> >  		cpu_switch_mm(mm->pgd, mm);
> 
> It is still early testing, but without a local tlb flush here I am getting
> random segmentation faults in user space.
> My fear is that 1:1 global TLB entries cause issues if user space processes 
> happen to map those pages at addresses overlapping 1:1 mapping set-up for 
> resume and we do not flush the TLB.

Yes, having the global TLB entry potentially in userspace is a problem.
I don't think we can get around this any other way than by calling
local_flush_tlb_all() here.  I'll post an updated series shortly.

^ permalink raw reply

* [PATCH] ARM: mach-qong: Add watchdog support
From: Stefano Babic @ 2011-09-19 16:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1316440786-21118-1-git-send-email-fabio.estevam@freescale.com>

On 09/19/2011 03:59 PM, Fabio Estevam wrote:
> Add watchdog support for mach-qong target.
> 
> Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
> ---
>  arch/arm/mach-imx/Kconfig     |    1 +
>  arch/arm/mach-imx/mach-qong.c |    1 +
>  2 files changed, 2 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index 0519dd7..8748531 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -485,6 +485,7 @@ config MACH_QONG
>  	bool "Support Dave/DENX QongEVB-LITE platform"
>  	select SOC_IMX31
>  	select IMX_HAVE_PLATFORM_IMX_UART
> +	select IMX_HAVE_PLATFORM_IMX2_WDT
>  	help
>  	  Include support for Dave/DENX QongEVB-LITE platform. This includes
>  	  specific configurations for the board and its peripherals.
> diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c
> index 3626f48..44462ce 100644
> --- a/arch/arm/mach-imx/mach-qong.c
> +++ b/arch/arm/mach-imx/mach-qong.c
> @@ -249,6 +249,7 @@ static void __init qong_init(void)
>  	mxc_init_imx_uart();
>  	qong_init_nor_mtd();
>  	qong_init_fpga();
> +	imx31_add_imx2_wdt(NULL);
>  }
>  

Thanks for fixing !

Tested-by : Stefano Babic <sbabic@denx.de>

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

^ permalink raw reply

* [PATCH 00/11] Add L2 cache cleaning to generic CPU suspend
From: Russell King - ARM Linux @ 2011-09-19 16:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110910161002.GA462@S2100-06.ap.freescale.net>

On Sun, Sep 11, 2011 at 12:10:04AM +0800, Shawn Guo wrote:
> On Thu, Sep 01, 2011 at 11:57:54PM +0800, Shawn Guo wrote:
> > On Thu, Sep 01, 2011 at 04:34:51PM +0100, Russell King - ARM Linux wrote:
> > > On Thu, Sep 01, 2011 at 11:33:43PM +0800, Shawn Guo wrote:
> > > > This is also the case on i.MX6Q, which L2 cache is retained during a
> > > > suspend/resume cycle.  Currently, I have to call into the following
> > > > before calling generic cpu_suspend() to clean/invalidate the entire
> > > > L2 cache.
> > > > 
> > > > 	outer_flush_all();
> > > > 	outer_disable();
> > > > 
> > > > But there is a wired thing on using generic cpu_resume().  I have to
> > > > invalidate L1 before calling into cpu_resume() like below.
> > > > 
> > > > ENTRY(imx6q_cpu_resume)
> > > >         bl      v7_invalidate_l1
> > > >         b       cpu_resume
> > > > ENDPROC(imx6q_cpu_resume)
> > > > 
> > > > ENTRY(imx6q_secondary_startup)
> > > >         bl      v7_invalidate_l1
> > > >         b       secondary_startup
> > > > ENDPROC(imx6q_secondary_startup)
> > > > 
> > > > The v7_invalidate_l1() is the function copied from mach-tegra/headsmp.S,
> > > > which has to be called before calling secondary_startup to boot
> > > > secondary cores (same situation between Tegra and i.MX6Q).
> > > 
> > > Presumably that's because your L1 cache contains randomized data with
> > > random validity (and presumably random dirtyness) at boot time - something
> > > which unfortunately the ARM ARM permits.  I don't think we can go to the
> > > extent of dealing with this in the generic code as it would unnecessarily
> > > perturb those implementations which either the boot loader has already
> > > sorted out that issue, or which don't have the issue at all.
> > > 
> > Yes, agreed.  It seems that Tegra and i.MX6Q are the only two CA9MP
> > cases here.  But is it possible to maintain this v7_invalidate_l1()
> > function in cache-v7.S, so that we do not need to duplicate it in
> > platform codes?
> > 
> > > > Before applying this patch series, I have something like below actually
> > > > working.
> > > > 
> > > > 
> > > > 	outer_flush_all();
> > > > 	outer_disable();
> > > > 	imx_set_cpu_jump(0, imx6q_cpu_resume);
> > > > 	/* Zzz ... */
> > > > 	cpu_suspend(0, imx6q_suspend_finish);
> > > > 
> > > > I expect with you patches applied, I can still have it work with simply
> > > > removing those two lines outer cache codes.
> > > 
> > > That should be the case.
> > > 
> > > > But unfortunately, I'm
> > > > running into Oops when resuming back.  And I also have Oops with
> > > > imx_set_cpu_jump(0, cpu_resume) which means skipping the
> > > > v7_invalidate_l1() and calling generic cpu_resume() only.
> > > 
> > > Do you have a copy of the oops?
> > > 
> > 
> Hi Russell,
> 
> After following your great debugging clue that we need to enable L2
> before calling into generic cpu_resume(), now this patch series works
> great for imx6q.  Thanks a lot, and here is my tag.
> 
> Tested-by: Shawn Guo <shawn.guo@linaro.org>

Is that for all these patches?

^ permalink raw reply

* [PATCH 5/5] ARM: gic: add OF based initialization
From: Russell King - ARM Linux @ 2011-09-19 16:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E77310A.3000106@ti.com>

On Mon, Sep 19, 2011 at 02:09:46PM +0200, Cousson, Benoit wrote:
> Every CortexA9 based SoC have to add the 32 offset to the SoC level
> interrupt number line. The ID numbering scheme is relevant only inside
> the GIC, but at SoC level only the IRQ lines that entered the MP core
> are relevant. That ID is a pure internal GIC encoding.

As far as SPIs go, I think what should be done is that the DT should
refer to a SPI phandle plus the SPI number, and be done with just that.

The point as to whether SoCs internally use SPIs themselves is a complete
distraction - if they're using SPIs internally then we _also_ need some
way for the on-SoC peripherals to refer to them too.

What the GIC exports are 16 PPIs per CPU, 16 SGIs and N SPIs.  That's what
we should be modelling for the GIC, not something else.  So peripherals
connect to an SPI numbered N where N >= 0.

How we want SPIs to map to Linux IRQ numbers is the issue, and as things
stand at present, we want SPI0 to map to IRQ32 on all platforms where the
GIC is the root, to avoid any unnecessary complexity (because the hardware
tells us that SPI0 gives us ID32 in the interrupt acknowledge register.)
Doing anything else requires computation or a lookup table, and we shouldn't
be doing that kind of thing unless there's a real reason to do so (there
isn't, especially with sparse irq support.)

As far as PPIs go, support for that is still being worked on, and most of
that at present does not go through genirq stuff (and it isn't relevant to
use the standard genirq interfaces for PPIs _anyway_.)

SGIs don't use genirq in any way, and are used for SMP IPIs.  That's
completely separate from the way IRQs are used - they're not connected
to devices at all. (They're provided as an inter-processor communication
method.)  So forget SGIs.  They may apparantly occupy IRQ IDs 0-15, but
reality is they leave those IDs unused, IRQs 0-15 are not requestable,
which is a definite *good* thing.

^ permalink raw reply

* PLEA: Please fix mach/gpio.h includes (was: Re: [RFC PATCH 2/2] GPIO: add gpiolib and irqchip for CSR SiRFprimaII GPIO controller)
From: Arnd Bergmann @ 2011-09-19 15:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkda6Bz_0odpLXokDdkPMyQKD6x5GnD52xnKZmDw1_sXW8A@mail.gmail.com>

On Monday 19 September 2011, Linus Walleij wrote:
> On Tuesday 09 August 2011, Barry Song wrote:
> 
> > Or do we want to delete the whole arch/arm/mach-xxx/include/mach directory?
> >
> > If not, it is probably that SoC can still hold some chip-specific APIs
> > in arch/arm/mach-xxx/include/mach/yyy.h.
> 
> I was actually proposing patches that moved GPIO headers from
> <mach/foo-gpio> to <linux/gpio/foo.h> but they were NAK:ed or
> frowned upon, so I guess we're keeping the <mach/*> include
> union namespace for machine/SoC-specific headers.
> 
> Now we just try to make files in this namespace have unqiue
> names.

That doesn't really sound like a long-term solution. I think the idea
for the single-zimage work is to eventually make the mach/ headers
local to the mach-* directory so they cannot be included from any
device drivers at all.

For any constants in those headers, they should be communicated
to the drivers using the platform data or (better) device tree
information.

The platform specific APIs that you mentioned are a bigger problem,
and I think the focus for those should be on avoiding them with
proper generic infrastructure and having only selected interfaces
exported through asm/*.h or linux/*.h where that is not an option.

	Arnd

^ permalink raw reply

* READ THIS: the next mach-types update
From: Richard Cochran @ 2011-09-19 15:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2659680.vCa59q5ODA@wuerfel>

On Sun, Sep 18, 2011 at 05:44:25PM +0200, Arnd Bergmann wrote:
> Post them for review again. The rules for new boards are much stricter
> now, but we still allow them to get merged if they look good enough.

Okay. I think I can combine the three boards into one set of source
files.

Thanks,
Richard

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox