Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ARM: Samsung: Move fimc plat. device from board files to plat-samsung
From: Sylwester Nawrocki @ 2011-10-12 15:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <039b01cc8730$594ab530$0be01f90$%kim@samsung.com>

Move the platform device definitions from boards code to plat-samsung
to avoid multiple instances when multiple board support is compiled in.
The boards should select at least S5P_DEV_FIMC0 to enable FIMC support.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
Hi Kgene,

To decrease overall diff size, if it's not too late yet, you might want to
squash parts of this patch with previous commits:

0513218 ARM: S5PV210: Add support for M-5MOLS image sensor on UNIVERSAL_C210
39aefab ARM: S5PV210: Add support for NOON010PC30 sensor on GONI board

Here is the optional new patch summary:

ARM: Samsung: Add fimc platform device for s5p-fimc media device driver

The s5p-fimc driver now creates an aggregate media device which is bound
to "s5p-fimc-md" platform device. This patch adds such a platform device
instance to be registered by each board that requires FIMC device support.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>

Sorry for the noise. 

Regards,
Sylwester
---
 arch/arm/mach-exynos4/mach-universal_c210.c |    5 -----
 arch/arm/mach-s5pv210/mach-goni.c           |    5 -----
 arch/arm/plat-samsung/devs.c                |    5 +++++
 arch/arm/plat-samsung/include/plat/devs.h   |    1 +
 4 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-exynos4/mach-universal_c210.c b/arch/arm/mach-exynos4/mach-universal_c210.c
index 18cf5c7..2096c8b 100644
--- a/arch/arm/mach-exynos4/mach-universal_c210.c
+++ b/arch/arm/mach-exynos4/mach-universal_c210.c
@@ -920,11 +920,6 @@ static struct s5p_platform_fimc fimc_md_platdata = {
 	.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" },
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 01e4867..61da205 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -849,11 +849,6 @@ struct s5p_platform_fimc goni_fimc_md_platdata __initdata = {
 	.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,
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index cb6fd9e..4ca8b57 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -204,6 +204,11 @@ struct platform_device s5p_device_fimc0 = {
 		.coherent_dma_mask	= DMA_BIT_MASK(32),
 	},
 };
+
+struct platform_device s5p_device_fimc_md = {
+	.name	= "s5p-fimc-md",
+	.id	= -1,
+};
 #endif /* CONFIG_S5P_DEV_FIMC0 */
 
 #ifdef CONFIG_S5P_DEV_FIMC1
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 8f19241..ab633c9 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -77,6 +77,7 @@ extern struct platform_device s5p_device_fimc0;
 extern struct platform_device s5p_device_fimc1;
 extern struct platform_device s5p_device_fimc2;
 extern struct platform_device s5p_device_fimc3;
+extern struct platform_device s5p_device_fimc_md;
 extern struct platform_device s5p_device_fimd0;
 extern struct platform_device s5p_device_hdmi;
 extern struct platform_device s5p_device_i2c_hdmiphy;
-- 
1.7.7

^ permalink raw reply related

* Update: ARM Sub-Architecture Maintainers workshop at Kernel Summit 2011
From: Nicolas Pitre @ 2011-10-12 15:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E955A59.4090705@compulab.co.il>

On Wed, 12 Oct 2011, Igor Grinberg wrote:

> On 09/27/11 16:25, Igor Grinberg wrote:
> > On 08/30/11 09:00, Grant Likely wrote:
> >> Still accepting more proposals.  Send me the topics you are burning to discuss.
> > 
> > One of the LPC2011's bottom lines was:
> > "We need more people involved in ARM maintainership to help
> > the sub-architecture maintainers do a better job on
> > review/consolidation/generalization/etc. of the code."
> > 
> > Despite the major goal of the DT to reduce the SoC and
> > board specific code to absolute minimum, there will still be cases
> > (e.g. discrete power management circuitry) when there is no
> > appropriate DT solution available and the board file
> > is a necessity. Also there are already many boards that will remain
> > and will not be converted to DT.
> > 
> > Bringing all the above together, I'd like to propose a new "job"
> > for maintaining board specific code on a cross-platform basis.
> > 
> > Pros:
> > 1) There might (I have not checked this, but I'm sure there is) be
> > code in the existing board files (that are not likely to go away
> > at least in a couple of years) that can be consolidated and
> > may be even in a cross-platform manner.
> > 2) Lower the work load from SoC maintainers (that don't have enough
> > time to care much about the board specific changes).
> > 3) Some more eyes to review the newly submitted code.
> > 
> > Cons:
> > 1) Resulting overhead for the code to go upstream.
> > 2) Possible addition of merge conflicts.
> > 
> > 
> > I'd like to hear, what do you think of the above proposal?
> 
> Any thoughts? Yes? No? Why? WTF?

Well...  Please see http://lwn.net/Articles/443510/.

Since then,  ARnd Bergmann has led the arm-soc repository maintenance 
effort as you might have noticed.  Other cleanup/consolidation projects 
are also progressing in parallel.

Obviously, as always, we would always benefit from more reviewers and 
more people in maintainership roles.  The general situation has improved 
since a couple months ago, but any additional suggestions you might have 
will always be welcome.


Nicolas

^ permalink raw reply

* [RFC PATCH] tty/serial: atmel_serial: add device tree support
From: Nicolas Ferre @ 2011-10-12 15:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111004165226.GA10919@ponder.secretlab.ca>

On 10/04/2011 06:52 PM, Grant Likely :
> On Mon, Oct 03, 2011 at 08:58:48PM -0500, Rob Herring wrote:
>> On 10/03/2011 04:51 AM, Nicolas Ferre wrote:
>>>  static int __devinit atmel_serial_probe(struct platform_device *pdev)
>>>  {
>>>  	struct atmel_uart_port *port;
>>> +	struct device_node *np = pdev->dev.of_node;
>>>  	struct atmel_uart_data *pdata = pdev->dev.platform_data;
>>>  	void *data;
>>>  	int ret;
>>>  
>>>  	BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
>>>  
>>> -	port = &atmel_ports[pdata->num];
>>> +	if (np) {
>>> +		ret = of_alias_get_id(np, "serial");
>>> +		if (ret < 0)
>>> +			goto err;
>>
>> I'll defer to Grant on this. There aren't any other drivers using this.
>>
> 
> This is the correct thing to do.
> 
> One note however; I prefer driver to *not* require an alias to be
> present.  By all means, use an alias if it is available, but the
> driver should auto-enumerate if it is not.  There is a patch that
> makes of_alias_get_id() do this for you, but it hasn't been mainlined
> yet and it is still a bit in flux.  There will be something that takes
> care of this for you, but be aware that the function name may change.
> 
> In the mean time, this patch is okay.
> 
> Acked-by: Grant Likely <grant.likely@secretlab.ca>

Grant,

I have reworked this atmel_serial device tree support so I did not add
your "Acked-by" to this new series. I repost it right now.
I hope this new implementation will be even better though ;-)

Bye,
-- 
Nicolas Ferre

^ permalink raw reply

* [PATCH v3] ARM: EXYNOS4: Add support for M-5MOLS camera on Nuri board
From: Sylwester Nawrocki @ 2011-10-12 15:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <069701cc88dc$7a484100$6ed8c300$%kim@samsung.com>

Add voltage regulator and platform data definition for M-5MOLS sensor
and MIPI-CSI receiver drivers. Add CAM power domain dependencies for
FIMC device and set up camera port A GPIO. Configure I2C0 bus timings.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: HeungJun Kim <riverful.kim@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
Changes since v2:
 - removed static "s5p-fimc-md" platform device instance  

Changes since v1:
 - whitespace cleanup	
 - removed unnecessary gpio_free()
---
 arch/arm/mach-exynos4/Kconfig     |    9 ++
 arch/arm/mach-exynos4/mach-nuri.c |  151 +++++++++++++++++++++++++++++++++++++
 2 files changed, 160 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index dd660eb..7c1d255 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -215,6 +215,7 @@ config MACH_UNIVERSAL_C210
 config MACH_NURI
 	bool "Mobile NURI Board"
 	select CPU_EXYNOS4210
+	select S5P_GPIO_INT
 	select S3C_DEV_WDT
 	select S3C_DEV_RTC
 	select S5P_DEV_FIMD0
@@ -224,15 +225,23 @@ config MACH_NURI
 	select S3C_DEV_I2C1
 	select S3C_DEV_I2C3
 	select S3C_DEV_I2C5
+	select S5P_DEV_CSIS0
+	select S5P_DEV_FIMC0
+	select S5P_DEV_FIMC1
+	select S5P_DEV_FIMC2
+	select S5P_DEV_FIMC3
 	select S5P_DEV_MFC
 	select S5P_DEV_USB_EHCI
+	select S5P_SETUP_MIPIPHY
 	select EXYNOS4_DEV_PD
+	select EXYNOS4_SETUP_FIMC
 	select EXYNOS4_SETUP_FIMD0
 	select EXYNOS4_SETUP_I2C1
 	select EXYNOS4_SETUP_I2C3
 	select EXYNOS4_SETUP_I2C5
 	select EXYNOS4_SETUP_SDHCI
 	select EXYNOS4_SETUP_USB_PHY
+	select S5P_SETUP_MIPIPHY
 	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_ADC
 	help
diff --git a/arch/arm/mach-exynos4/mach-nuri.c b/arch/arm/mach-exynos4/mach-nuri.c
index 20932ec..816a502 100644
--- a/arch/arm/mach-exynos4/mach-nuri.c
+++ b/arch/arm/mach-exynos4/mach-nuri.c
@@ -27,6 +27,9 @@
 #include <linux/pwm_backlight.h>
 
 #include <video/platform_lcd.h>
+#include <media/m5mols.h>
+#include <media/s5p_fimc.h>
+#include <media/v4l2-mediabus.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -45,6 +48,9 @@
 #include <plat/iic.h>
 #include <plat/mfc.h>
 #include <plat/pd.h>
+#include <plat/fimc-core.h>
+#include <plat/camport.h>
+#include <plat/mipi_csis.h>
 
 #include <mach/map.h>
 
@@ -65,6 +71,8 @@
 enum fixed_regulator_id {
 	FIXED_REG_ID_MMC = 0,
 	FIXED_REG_ID_MAX8903,
+	FIXED_REG_ID_CAM_A28V,
+	FIXED_REG_ID_CAM_12V,
 };
 
 static struct s3c2410_uartcfg nuri_uartcfgs[] __initdata = {
@@ -1110,10 +1118,140 @@ static void __init nuri_ehci_init(void)
 	s5p_ehci_set_platdata(pdata);
 }
 
+/* CAMERA */
+static struct regulator_consumer_supply cam_vdda_supply[] = {
+	REGULATOR_SUPPLY("a_sensor", "0-001f"),
+};
+
+static struct regulator_init_data cam_vdda_reg_init_data = {
+	.constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+	.num_consumer_supplies = ARRAY_SIZE(cam_vdda_supply),
+	.consumer_supplies = cam_vdda_supply,
+};
+
+static struct fixed_voltage_config cam_vdda_fixed_voltage_cfg = {
+	.supply_name	= "CAM_IO_EN",
+	.microvolts	= 2800000,
+	.gpio		= EXYNOS4_GPE2(1), /* CAM_IO_EN */
+	.enable_high	= 1,
+	.init_data	= &cam_vdda_reg_init_data,
+};
+
+static struct platform_device cam_vdda_fixed_rdev = {
+	.name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_A28V,
+	.dev = { .platform_data	= &cam_vdda_fixed_voltage_cfg },
+};
+
+static struct regulator_consumer_supply camera_8m_12v_supply =
+	REGULATOR_SUPPLY("dig_12", "0-001f");
+
+static struct regulator_init_data cam_8m_12v_reg_init_data = {
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &camera_8m_12v_supply,
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS
+	},
+};
+
+static struct fixed_voltage_config cam_8m_12v_fixed_voltage_cfg = {
+	.supply_name	= "8M_1.2V",
+	.microvolts	= 1200000,
+	.gpio		= EXYNOS4_GPE2(5), /* 8M_1.2V_EN */
+	.enable_high	= 1,
+	.init_data	= &cam_8m_12v_reg_init_data,
+};
+
+static struct platform_device cam_8m_12v_fixed_rdev = {
+	.name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_12V,
+	.dev = { .platform_data = &cam_8m_12v_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_MEGA_RST	EXYNOS4_GPY3(7) /* ISP_RESET */
+#define GPIO_CAM_8M_ISP_INT	EXYNOS4_GPL2(5)
+
+static struct m5mols_platform_data m5mols_platdata = {
+	.gpio_reset = GPIO_CAM_MEGA_RST,
+};
+
+static struct i2c_board_info m5mols_board_info = {
+	I2C_BOARD_INFO("M5MOLS", 0x1F),
+	.platform_data	= &m5mols_platdata,
+};
+
+static struct s5p_fimc_isp_info nuri_camera_sensors[] = {
+	{
+		.flags		= V4L2_MBUS_PCLK_SAMPLE_FALLING |
+				  V4L2_MBUS_VSYNC_ACTIVE_LOW,
+		.bus_type	= FIMC_MIPI_CSI2,
+		.board_info	= &m5mols_board_info,
+		.clk_frequency	= 24000000UL,
+		.csi_data_align	= 32,
+	},
+};
+
+static struct s5p_platform_fimc fimc_md_platdata = {
+	.isp_info	= nuri_camera_sensors,
+	.num_clients	= ARRAY_SIZE(nuri_camera_sensors),
+};
+
+static struct gpio nuri_camera_gpios[] = {
+	{ GPIO_CAM_8M_ISP_INT,	GPIOF_IN,           "8M_ISP_INT"  },
+	{ GPIO_CAM_MEGA_RST,	GPIOF_OUT_INIT_LOW, "CAM_8M_NRST" },
+};
+
+static void nuri_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(nuri_camera_gpios,
+			       ARRAY_SIZE(nuri_camera_gpios))) {
+		pr_err("%s: GPIO request failed\n", __func__);
+		return;
+	}
+
+	m5mols_board_info.irq = s5p_register_gpio_interrupt(GPIO_CAM_8M_ISP_INT);
+	if (!IS_ERR_VALUE(m5mols_board_info.irq))
+		s3c_gpio_cfgpin(GPIO_CAM_8M_ISP_INT, S3C_GPIO_SFN(0xF));
+	else
+		pr_err("%s: Failed to configure 8M_ISP_INT GPIO\n", __func__);
+
+	/* Free GPIOs controlled directly by the sensor drivers. */
+	gpio_free(GPIO_CAM_MEGA_RST);
+
+	if (exynos4_fimc_setup_gpio(S5P_CAMPORT_A)) {
+		pr_err("%s: Camera port A setup failed\n", __func__);
+		return;
+	}
+	/* Increase drive strength of the sensor clock output */
+	s5p_gpio_set_drvstr(EXYNOS4_GPJ1(3), S5P_GPIO_DRVSTR_LV4);
+}
+
+static struct s3c2410_platform_i2c nuri_i2c0_platdata __initdata = {
+	.frequency	= 400000U,
+	.sda_delay	= 200,
+};
+
 static struct platform_device *nuri_devices[] __initdata = {
 	/* Samsung Platform Devices */
 	&s3c_device_i2c5, /* PMIC should initialize first */
+	&s3c_device_i2c0,
 	&emmc_fixed_voltage,
+	&s5p_device_mipi_csis0,
+	&s5p_device_fimc0,
+	&s5p_device_fimc1,
+	&s5p_device_fimc2,
+	&s5p_device_fimc3,
 	&s5p_device_fimd0,
 	&s3c_device_hsmmc0,
 	&s3c_device_hsmmc2,
@@ -1130,6 +1268,8 @@ static struct platform_device *nuri_devices[] __initdata = {
 	&s5p_device_mfc_r,
 	&exynos4_device_pd[PD_MFC],
 	&exynos4_device_pd[PD_LCD0],
+	&exynos4_device_pd[PD_CAM],
+	&s5p_device_fimc_md,
 
 	/* NURI Devices */
 	&nuri_gpio_keys,
@@ -1137,6 +1277,8 @@ static struct platform_device *nuri_devices[] __initdata = {
 	&nuri_backlight_device,
 	&max8903_fixed_reg_dev,
 	&nuri_max8903_device,
+	&cam_vdda_fixed_rdev,
+	&cam_8m_12v_fixed_rdev,
 };
 
 static void __init nuri_map_io(void)
@@ -1157,6 +1299,7 @@ static void __init nuri_machine_init(void)
 	nuri_tsp_init();
 	nuri_power_init();
 
+	s3c_i2c0_set_platdata(&nuri_i2c0_platdata);
 	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
 	s3c_i2c3_set_platdata(&i2c3_data);
 	i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
@@ -1168,6 +1311,8 @@ static void __init nuri_machine_init(void)
 
 	s5p_fimd0_set_platdata(&nuri_fb_pdata);
 
+	nuri_camera_init();
+
 	nuri_ehci_init();
 	clk_xusbxti.rate = 24000000;
 
@@ -1175,6 +1320,12 @@ static void __init nuri_machine_init(void)
 	platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_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(NURI, "NURI")
-- 
1.7.7

^ permalink raw reply related

* [PATCH 4/9] ARM: SPMP8000: Add ADC driver
From: Jonathan Cameron @ 2011-10-12 15:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111012144251.GM3647@opensource.wolfsonmicro.com>

On 10/12/11 15:42, Mark Brown wrote:
> On Tue, Oct 11, 2011 at 05:24:47PM +0200, Arnd Bergmann wrote:
>> On Tuesday 11 October 2011, Mark Brown wrote:
> 
>>> I'm not sure that IIO isn't the kernel subsystem we're looking for here
>>> - as I keep saying when this comes up it's just representing bare DACs
>>> and ADCs pretty directly which looks like a generic subsystem to me.
> 
>> Possible, yes. Until now, IIO is a subsystem for user-level access
>> not for kernel access though, so it's not the right place yet.
>> If we decide to let IIO handle all ADC input, do you think it would
>> also be the right place to do PWM output, rather than having a
>> separate subsystem for that?
> 
> Off the top of my head I'd expect PWM to be a separate thing which could
> optionally synthesize stuff onto an IIO device (bitbanging the PWM
> essentially).  The specialized PWM stuff tends to be "output this steady
> state for an indefinite period" type interface rather than "here's a
> batch of samples, output them".
Same can be true of dds chips, with the addition that they often have
gpio type switching between a set of predefined frequencies (FM basically).
+ weird waveform choices sometimes.

^ permalink raw reply

* [PATCH v2] arm/tegra: pinmux: ioremap registers
From: Stephen Warren @ 2011-10-12 15:54 UTC (permalink / raw)
  To: linux-arm-kernel

Use ioremap to obtain access to registers instead of using static
mappings. This reduces the number of users of the static mappings, which
will eventually allow them to be removed.

Note that on Tegra30, the number of register "banks" will decrease to 2,
and the packing of specific bits into registers will change significantly.
That's why this change adds the "*_bank" fields to the pingroup tables,
rather than implementing some more hard-coded scheme.

Also, completely remove the implementation of suspend/resume; Tegra doesn't
yet support suspend/resume, and the implementation is complex for the
general pinmux driver:

* Not all registers are used within each bank, so we probably shouldn't
  just iterate over every register in the bank, and save/restore it,
  since that would mean touching undefined registers.

* Registers are shared between pingroups, so we can't simply iterate over
  each pingroup, and save/restore the registers it uses.

It'd probably be best have probe() calculate a bitmask of actually-used
registers for each bank, and have suspend/resume iterate over those
bitmaps.

Oh, and Real Soon Now, I should be looking into converting this driver to
the new pinmux/pinctrl subsystem, so I didn't want to put too much work
into the current incarnation.

v2: s/space/bank/ to match comments on reg_* fields in pinmux.h.
    Re-order bank/reg parameters to pg_readl/pg_writel.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 arch/arm/mach-tegra/include/mach/pinmux.h |    4 +
 arch/arm/mach-tegra/pinmux-t2-tables.c    |   76 +++-------------
 arch/arm/mach-tegra/pinmux.c              |  137 ++++++++++++++++++++++-------
 3 files changed, 123 insertions(+), 94 deletions(-)

diff --git a/arch/arm/mach-tegra/include/mach/pinmux.h b/arch/arm/mach-tegra/include/mach/pinmux.h
index defd877..bb7dfdb 100644
--- a/arch/arm/mach-tegra/include/mach/pinmux.h
+++ b/arch/arm/mach-tegra/include/mach/pinmux.h
@@ -199,6 +199,7 @@ struct tegra_drive_pingroup_config {
 
 struct tegra_drive_pingroup_desc {
 	const char *name;
+	s16 reg_bank;
 	s16 reg;
 };
 
@@ -207,6 +208,9 @@ struct tegra_pingroup_desc {
 	int funcs[4];
 	int func_safe;
 	int vddio;
+	s16 tri_bank;	/* Register bank the tri_reg exists within */
+	s16 mux_bank;	/* Register bank the mux_reg exists within */
+	s16 pupd_bank;	/* Register bank the pupd_reg exists within */
 	s16 tri_reg; 	/* offset into the TRISTATE_REG_* register bank */
 	s16 mux_reg;	/* offset into the PIN_MUX_CTL_* register bank */
 	s16 pupd_reg;	/* offset into the PULL_UPDOWN_REG_* register bank */
diff --git a/arch/arm/mach-tegra/pinmux-t2-tables.c b/arch/arm/mach-tegra/pinmux-t2-tables.c
index a475367..a0dc2bc 100644
--- a/arch/arm/mach-tegra/pinmux-t2-tables.c
+++ b/arch/arm/mach-tegra/pinmux-t2-tables.c
@@ -31,10 +31,16 @@
 #include <mach/pinmux.h>
 #include <mach/suspend.h>
 
+#define TRISTATE_REG_A		0x14
+#define PIN_MUX_CTL_REG_A	0x80
+#define PULLUPDOWN_REG_A	0xa0
+#define PINGROUP_REG_A		0x868
+
 #define DRIVE_PINGROUP(pg_name, r)				\
 	[TEGRA_DRIVE_PINGROUP_ ## pg_name] = {			\
 		.name = #pg_name,				\
-		.reg = r					\
+		.reg_bank = 3,					\
+		.reg = ((r) - PINGROUP_REG_A)			\
 	}
 
 const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = {
@@ -90,11 +96,14 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE
 			TEGRA_MUX_ ## f3,			\
 		},						\
 		.func_safe = TEGRA_MUX_ ## f_safe,		\
-		.tri_reg = tri_r,				\
+		.tri_bank = 0,					\
+		.tri_reg = ((tri_r) - TRISTATE_REG_A),		\
 		.tri_bit = tri_b,				\
-		.mux_reg = mux_r,				\
+		.mux_bank = 1,					\
+		.mux_reg = ((mux_r) - PIN_MUX_CTL_REG_A),	\
 		.mux_bit = mux_b,				\
-		.pupd_reg = pupd_r,				\
+		.pupd_bank = 2,				\
+		.pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A),	\
 		.pupd_bit = pupd_b,				\
 	}
 
@@ -217,62 +226,3 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = {
 	PINGROUP(XM2C,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xA8, 30),
 	PINGROUP(XM2D,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xA8, 28),
 };
-
-#ifdef CONFIG_PM
-#define TRISTATE_REG_A         0x14
-#define TRISTATE_REG_NUM       4
-#define PIN_MUX_CTL_REG_A      0x80
-#define PIN_MUX_CTL_REG_NUM    8
-#define PULLUPDOWN_REG_A       0xa0
-#define PULLUPDOWN_REG_NUM     5
-
-static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM +
-		      PULLUPDOWN_REG_NUM +
-		      ARRAY_SIZE(tegra_soc_drive_pingroups)];
-
-static inline unsigned long pg_readl(unsigned long offset)
-{
-	return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
-}
-
-static inline void pg_writel(unsigned long value, unsigned long offset)
-{
-	writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
-}
-
-void tegra_pinmux_suspend(void)
-{
-	unsigned int i;
-	u32 *ctx = pinmux_reg;
-
-	for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
-		*ctx++ = pg_readl(PIN_MUX_CTL_REG_A + i*4);
-
-	for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
-		*ctx++ = pg_readl(PULLUPDOWN_REG_A + i*4);
-
-	for (i = 0; i < TRISTATE_REG_NUM; i++)
-		*ctx++ = pg_readl(TRISTATE_REG_A + i*4);
-
-	for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
-		*ctx++ = pg_readl(tegra_soc_drive_pingroups[i].reg);
-}
-
-void tegra_pinmux_resume(void)
-{
-	unsigned int i;
-	u32 *ctx = pinmux_reg;
-
-	for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
-		pg_writel(*ctx++, PIN_MUX_CTL_REG_A + i*4);
-
-	for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
-		pg_writel(*ctx++, PULLUPDOWN_REG_A + i*4);
-
-	for (i = 0; i < TRISTATE_REG_NUM; i++)
-		pg_writel(*ctx++, TRISTATE_REG_A + i*4);
-
-	for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
-		pg_writel(*ctx++, tegra_soc_drive_pingroups[i].reg);
-}
-#endif
diff --git a/arch/arm/mach-tegra/pinmux.c b/arch/arm/mach-tegra/pinmux.c
index 46b9d87..e4b736a 100644
--- a/arch/arm/mach-tegra/pinmux.c
+++ b/arch/arm/mach-tegra/pinmux.c
@@ -170,15 +170,17 @@ static const char *pupd_name(unsigned long val)
 	}
 }
 
+static int nbanks;
+static void __iomem **regs;
 
-static inline unsigned long pg_readl(unsigned long offset)
+static inline u32 pg_readl(u32 bank, u32 reg)
 {
-	return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+	return readl(regs[bank] + reg);
 }
 
-static inline void pg_writel(unsigned long value, unsigned long offset)
+static inline void pg_writel(u32 val, u32 bank, u32 reg)
 {
-	writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+	writel(val, regs[bank] + reg);
 }
 
 static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
@@ -218,10 +220,10 @@ static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(pingroups[pg].mux_reg);
+	reg = pg_readl(pingroups[pg].mux_bank, pingroups[pg].mux_reg);
 	reg &= ~(0x3 << pingroups[pg].mux_bit);
 	reg |= mux << pingroups[pg].mux_bit;
-	pg_writel(reg, pingroups[pg].mux_reg);
+	pg_writel(reg, pingroups[pg].mux_bank, pingroups[pg].mux_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -242,11 +244,11 @@ int tegra_pinmux_set_tristate(enum tegra_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(pingroups[pg].tri_reg);
+	reg = pg_readl(pingroups[pg].tri_bank, pingroups[pg].tri_reg);
 	reg &= ~(0x1 << pingroups[pg].tri_bit);
 	if (tristate)
 		reg |= 1 << pingroups[pg].tri_bit;
-	pg_writel(reg, pingroups[pg].tri_reg);
+	pg_writel(reg, pingroups[pg].tri_bank, pingroups[pg].tri_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -273,10 +275,10 @@ int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(pingroups[pg].pupd_reg);
+	reg = pg_readl(pingroups[pg].pupd_bank, pingroups[pg].pupd_reg);
 	reg &= ~(0x3 << pingroups[pg].pupd_bit);
 	reg |= pupd << pingroups[pg].pupd_bit;
-	pg_writel(reg, pingroups[pg].pupd_reg);
+	pg_writel(reg, pingroups[pg].pupd_bank, pingroups[pg].pupd_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -363,12 +365,12 @@ static int tegra_drive_pinmux_set_hsm(enum tegra_drive_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	if (hsm == TEGRA_HSM_ENABLE)
 		reg |= (1 << 2);
 	else
 		reg &= ~(1 << 2);
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -388,12 +390,12 @@ static int tegra_drive_pinmux_set_schmitt(enum tegra_drive_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	if (schmitt == TEGRA_SCHMITT_ENABLE)
 		reg |= (1 << 3);
 	else
 		reg &= ~(1 << 3);
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -413,10 +415,10 @@ static int tegra_drive_pinmux_set_drive(enum tegra_drive_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x3 << 4);
 	reg |= drive << 4;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -436,10 +438,10 @@ static int tegra_drive_pinmux_set_pull_down(enum tegra_drive_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x1f << 12);
 	reg |= pull_down << 12;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -459,10 +461,10 @@ static int tegra_drive_pinmux_set_pull_up(enum tegra_drive_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x1f << 12);
 	reg |= pull_up << 12;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -482,10 +484,10 @@ static int tegra_drive_pinmux_set_slew_rising(enum tegra_drive_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x3 << 28);
 	reg |= slew_rising << 28;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -505,10 +507,10 @@ static int tegra_drive_pinmux_set_slew_falling(enum tegra_drive_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x3 << 30);
 	reg |= slew_falling << 30;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -668,6 +670,74 @@ void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *co
 
 static int __init tegra_pinmux_probe(struct platform_device *pdev)
 {
+	struct resource *res;
+	int i;
+	int config_bad = 0;
+
+	for (i = 0; ; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res)
+			break;
+	}
+	nbanks = i;
+
+	for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
+		if (pingroups[i].tri_bank >= nbanks) {
+			dev_err(&pdev->dev, "pingroup %d: bad tri_bank\n", i);
+			config_bad = 1;
+		}
+
+		if (pingroups[i].mux_bank >= nbanks) {
+			dev_err(&pdev->dev, "pingroup %d: bad mux_bank\n", i);
+			config_bad = 1;
+		}
+
+		if (pingroups[i].pupd_bank >= nbanks) {
+			dev_err(&pdev->dev, "pingroup %d: bad pupd_bank\n", i);
+			config_bad = 1;
+		}
+	}
+
+	for (i = 0; i < TEGRA_MAX_DRIVE_PINGROUP; i++) {
+		if (drive_pingroups[i].reg_bank >= nbanks) {
+			dev_err(&pdev->dev,
+				"drive pingroup %d: bad reg_bank\n", i);
+			config_bad = 1;
+		}
+	}
+
+	if (config_bad)
+		return -ENODEV;
+
+	regs = devm_kzalloc(&pdev->dev, nbanks * sizeof(*regs), GFP_KERNEL);
+	if (!regs) {
+		dev_err(&pdev->dev, "Can't alloc regs pointer\n");
+		return -ENODEV;
+	}
+
+	for (i = 0; i < nbanks; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res) {
+			dev_err(&pdev->dev, "Missing MEM resource\n");
+			return -ENODEV;
+		}
+
+		if (!devm_request_mem_region(&pdev->dev, res->start,
+					    resource_size(res),
+					    dev_name(&pdev->dev))) {
+			dev_err(&pdev->dev,
+				"Couldn't request MEM resource %d\n", i);
+			return -ENODEV;
+		}
+
+		regs[i] = devm_ioremap(&pdev->dev, res->start,
+					resource_size(res));
+		if (!regs) {
+			dev_err(&pdev->dev, "Couldn't ioremap regs %d\n", i);
+			return -ENODEV;
+		}
+	}
+
 	return 0;
 }
 
@@ -710,6 +780,7 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
 	int len;
 
 	for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
+		unsigned long reg;
 		unsigned long tri;
 		unsigned long mux;
 		unsigned long pupd;
@@ -722,8 +793,9 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
 			seq_printf(s, "TEGRA_MUX_NONE");
 			len = strlen("NONE");
 		} else {
-			mux = (pg_readl(pingroups[i].mux_reg) >>
-			       pingroups[i].mux_bit) & 0x3;
+			reg = pg_readl(pingroups[i].mux_bank,
+					pingroups[i].mux_reg);
+			mux = (reg >> pingroups[i].mux_bit) & 0x3;
 			if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) {
 				seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1);
 				len = 5;
@@ -739,8 +811,9 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
 			seq_printf(s, "TEGRA_PUPD_NORMAL");
 			len = strlen("NORMAL");
 		} else {
-			pupd = (pg_readl(pingroups[i].pupd_reg) >>
-				pingroups[i].pupd_bit) & 0x3;
+			reg = pg_readl(pingroups[i].pupd_bank,
+					pingroups[i].pupd_reg);
+			pupd = (reg >> pingroups[i].pupd_bit) & 0x3;
 			seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd));
 			len = strlen(pupd_name(pupd));
 		}
@@ -749,8 +822,9 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
 		if (pingroups[i].tri_reg < 0) {
 			seq_printf(s, "TEGRA_TRI_NORMAL");
 		} else {
-			tri = (pg_readl(pingroups[i].tri_reg) >>
-			       pingroups[i].tri_bit) & 0x1;
+			reg = pg_readl(pingroups[i].tri_bank,
+					pingroups[i].tri_reg);
+			tri = (reg >> pingroups[i].tri_bit) & 0x1;
 
 			seq_printf(s, "TEGRA_TRI_%s", tri_name(tri));
 		}
@@ -785,7 +859,8 @@ static int dbg_drive_pinmux_show(struct seq_file *s, void *unused)
 		dbg_pad_field(s, 7 - len);
 
 
-		reg = pg_readl(drive_pingroups[i].reg);
+		reg = pg_readl(drive_pingroups[i].reg_bank,
+				drive_pingroups[i].reg);
 		if (HSM_EN(reg)) {
 			seq_printf(s, "TEGRA_HSM_ENABLE");
 			len = 16;
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH v9 0/3] Add support for tegra2 based ventana board
From: Stephen Warren @ 2011-10-12 15:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318420387-6802-1-git-send-email-pdeschrijver@nvidia.com>

pdeschrijver at nvidia.com wrote at Wednesday, October 12, 2011 5:53 AM:
> This patch set adds support for the tegra2 based ventana development board.
> 
> Boot tested on ventana.
> 
> Uses a table based approach to select the correct init function.
> 
> Provoke kernel warning when no suitable pinmux table can be found.

Whole series:

Acked-by: Stephen Warren <swarren@nvidia.com>

Thanks for following up on my picky comments:-)

--
nvpublic

^ permalink raw reply

* [PATCH v2 0/5] tty/serial: atmel_serial: Device Tree support
From: Nicolas Ferre @ 2011-10-12 16:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

The goal of this patch series is to add device tree support to Atmel USART
driver: atmel_serial.
As this driver support RS485 mode, generic RS485 bindings have been added.

Some modifications are also included to ease the transition to parameter
settings comming from device tree.
The enumeration of ports is enhanced to be able to deal with several types
of port numbering: platform data, device tree or automatic.

Nicolas Ferre (5):
      tty/serial: RS485 bindings for device tree
      tty/serial: atmel_serial: change platform_data variable name
      tty/serial: atmel_serial: whitespace and braces modifications
      tty/serial: atmel_serial: auto-enumerate ports
      tty/serial: atmel_serial: add device tree support

 Documentation/devicetree/bindings/serial/rs485.txt |   31 +++++
 .../devicetree/bindings/tty/serial/atmel-usart.txt |   27 +++++
 Documentation/serial/serial-rs485.txt              |    5 +
 drivers/tty/serial/atmel_serial.c                  |  122 +++++++++++++++++---
 4 files changed, 170 insertions(+), 15 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/serial/rs485.txt
 create mode 100644 Documentation/devicetree/bindings/tty/serial/atmel-usart.txt

^ permalink raw reply

* [PATCH v2 1/5] tty/serial: RS485 bindings for device tree
From: Nicolas Ferre @ 2011-10-12 16:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318435620-7481-1-git-send-email-nicolas.ferre@atmel.com>

Generic bindings for RS485 feature included in some UARTs.
Those bindings have to be used withing an UART device tree node.
Documentation updated to link to the bindings definition.

Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 Documentation/devicetree/bindings/serial/rs485.txt |   31 ++++++++++++++++++++
 .../devicetree/bindings/tty/serial/atmel-usart.txt |   27 +++++++++++++++++
 Documentation/serial/serial-rs485.txt              |    5 +++
 3 files changed, 63 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/serial/rs485.txt
 create mode 100644 Documentation/devicetree/bindings/tty/serial/atmel-usart.txt

diff --git a/Documentation/devicetree/bindings/serial/rs485.txt b/Documentation/devicetree/bindings/serial/rs485.txt
new file mode 100644
index 0000000..1e753c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/rs485.txt
@@ -0,0 +1,31 @@
+* RS485 serial communications
+
+The RTS signal is capable of automatically controlling line direction for
+the built-in half-duplex mode.
+The properties described hereafter shall be given to a half-duplex capable
+UART node.
+
+Required properties:
+- rs485-rts-delay: prop-encoded-array <a b> where:
+  * a is the delay beteween rts signal and beginning of data sent in milliseconds.
+      it corresponds to the delay before sending data.
+  * b is the delay between end of data sent and rts signal in milliseconds
+      it corresponds to the delay after sending data and actual release of the line.
+
+Optional properties:
+- linux,rs485-enabled-at-boot-time: empty property telling to enable the rs485
+  feature at boot time. It can be disabled later with proper ioctl.
+- rs485-rx-during-tx: empty property that enables the receiving of data even
+  whilst sending data.
+
+RS485 example for Atmel USART:
+	usart0: serial at fff8c000 {
+		compatible = "atmel,at91sam9260-usart";
+		reg = <0xfff8c000 0x4000>;
+		interrupts = <7>;
+		atmel,use-dma-rx;
+		atmel,use-dma-tx;
+		linux,rs485-enabled-at-boot-time;
+		rs485-rts-delay = <0 200>;		// in milliseconds
+	};
+
diff --git a/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt b/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt
new file mode 100644
index 0000000..a49d9a1
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt
@@ -0,0 +1,27 @@
+* Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART)
+
+Required properties:
+- compatible: Should be "atmel,<chip>-usart"
+  The compatible <chip> indicated will be the first SoC to support an
+  additional mode or an USART new feature.
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt
+
+Optional properties:
+- atmel,use-dma-rx: use of PDC or DMA for receiving data
+- atmel,use-dma-tx: use of PDC or DMA for transmitting data
+
+<chip> compatible description:
+- at91rm9200:  legacy USART support
+- at91sam9260: generic USART implementation for SAM9 SoCs
+
+Example:
+
+	usart0: serial at fff8c000 {
+		compatible = "atmel,at91sam9260-usart";
+		reg = <0xfff8c000 0x4000>;
+		interrupts = <7>;
+		atmel,use-dma-rx;
+		atmel,use-dma-tx;
+	};
+
diff --git a/Documentation/serial/serial-rs485.txt b/Documentation/serial/serial-rs485.txt
index c8878f8..079cb3d 100644
--- a/Documentation/serial/serial-rs485.txt
+++ b/Documentation/serial/serial-rs485.txt
@@ -28,6 +28,10 @@
    RS485 communications. This data structure is used to set and configure RS485
    parameters in the platform data and in ioctls.
 
+   The device tree can also provide RS485 boot time parameters (see [2]
+   for bindings). The driver is in charge of filling this data structure from
+   the values given by the device tree.
+
    Any driver for devices capable of working both as RS232 and RS485 should
    provide at least the following ioctls:
 
@@ -121,3 +125,4 @@
 5. REFERENCES
 
  [1]	include/linux/serial.h
+ [2]	Documentation/devicetree/bindings/serial/rs485.txt
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH v2 2/5] tty/serial: atmel_serial: change platform_data variable name
From: Nicolas Ferre @ 2011-10-12 16:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318435620-7481-1-git-send-email-nicolas.ferre@atmel.com>

Easier to follow if platform_data name is pdata.

Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/tty/serial/atmel_serial.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index c7232a9..a507daa 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -1417,13 +1417,13 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
 				      struct platform_device *pdev)
 {
 	struct uart_port *port = &atmel_port->uart;
-	struct atmel_uart_data *data = pdev->dev.platform_data;
+	struct atmel_uart_data *pdata = pdev->dev.platform_data;
 
 	port->iotype		= UPIO_MEM;
 	port->flags		= UPF_BOOT_AUTOCONF;
 	port->ops		= &atmel_pops;
 	port->fifosize		= 1;
-	port->line		= data->num;
+	port->line		= pdata->num;
 	port->dev		= &pdev->dev;
 	port->mapbase	= pdev->resource[0].start;
 	port->irq	= pdev->resource[1].start;
@@ -1433,9 +1433,9 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
 
 	memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
 
-	if (data->regs)
+	if (pdata->regs)
 		/* Already mapped by setup code */
-		port->membase = data->regs;
+		port->membase = pdata->regs;
 	else {
 		port->flags	|= UPF_IOREMAP;
 		port->membase	= NULL;
@@ -1450,9 +1450,9 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
 		/* only enable clock when USART is in use */
 	}
 
-	atmel_port->use_dma_rx = data->use_dma_rx;
-	atmel_port->use_dma_tx = data->use_dma_tx;
-	atmel_port->rs485	= data->rs485;
+	atmel_port->use_dma_rx = pdata->use_dma_rx;
+	atmel_port->use_dma_tx = pdata->use_dma_tx;
+	atmel_port->rs485	= pdata->rs485;
 	/* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */
 	if (atmel_port->rs485.flags & SER_RS485_ENABLED)
 		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH v2 3/5] tty/serial: atmel_serial: whitespace and braces modifications
From: Nicolas Ferre @ 2011-10-12 16:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318435620-7481-1-git-send-email-nicolas.ferre@atmel.com>

Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/tty/serial/atmel_serial.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index a507daa..bb72354 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -1433,10 +1433,10 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
 
 	memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
 
-	if (pdata->regs)
+	if (pdata->regs) {
 		/* Already mapped by setup code */
 		port->membase = pdata->regs;
-	else {
+	} else {
 		port->flags	|= UPF_IOREMAP;
 		port->membase	= NULL;
 	}
@@ -1450,9 +1450,10 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
 		/* only enable clock when USART is in use */
 	}
 
-	atmel_port->use_dma_rx = pdata->use_dma_rx;
-	atmel_port->use_dma_tx = pdata->use_dma_tx;
+	atmel_port->use_dma_rx	= pdata->use_dma_rx;
+	atmel_port->use_dma_tx	= pdata->use_dma_tx;
 	atmel_port->rs485	= pdata->rs485;
+
 	/* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */
 	if (atmel_port->rs485.flags & SER_RS485_ENABLED)
 		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH v2 4/5] tty/serial: atmel_serial: auto-enumerate ports
From: Nicolas Ferre @ 2011-10-12 16:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318435620-7481-1-git-send-email-nicolas.ferre@atmel.com>

If no platform data provided to enumerate ports, use a bit field
to choose port number and check if port is already initialized.
Use this mechanism for both console and plain serial ports.

Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/tty/serial/atmel_serial.c |   44 ++++++++++++++++++++++++++++++------
 1 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index bb72354..1074329 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -157,6 +157,7 @@ struct atmel_uart_port {
 };
 
 static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
+static unsigned long atmel_ports_in_use;
 
 #ifdef SUPPORT_SYSRQ
 static struct console atmel_console;
@@ -1423,7 +1424,6 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
 	port->flags		= UPF_BOOT_AUTOCONF;
 	port->ops		= &atmel_pops;
 	port->fifosize		= 1;
-	port->line		= pdata->num;
 	port->dev		= &pdev->dev;
 	port->mapbase	= pdev->resource[0].start;
 	port->irq	= pdev->resource[1].start;
@@ -1613,10 +1613,15 @@ static struct console atmel_console = {
 static int __init atmel_console_init(void)
 {
 	if (atmel_default_console_device) {
-		add_preferred_console(ATMEL_DEVICENAME,
-				      atmel_default_console_device->id, NULL);
-		atmel_init_port(&atmel_ports[atmel_default_console_device->id],
-				atmel_default_console_device);
+		int id = atmel_default_console_device->id;
+		struct atmel_uart_port *port = &atmel_ports[id];
+
+		set_bit(id, &atmel_ports_in_use);
+		port->backup_imr = 0;
+		port->uart.line = id;
+
+		add_preferred_console(ATMEL_DEVICENAME, id, NULL);
+		atmel_init_port(port, atmel_default_console_device);
 		register_console(&atmel_console);
 	}
 
@@ -1715,12 +1720,33 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
 	struct atmel_uart_port *port;
 	struct atmel_uart_data *pdata = pdev->dev.platform_data;
 	void *data;
-	int ret;
+	int ret = -ENODEV;
 
 	BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
 
-	port = &atmel_ports[pdata->num];
+	if (pdata)
+		ret = pdata->num;
+
+	if (ret < 0)
+		/* port id not found in platform data:
+		 * auto-enumerate it */
+		ret = find_first_zero_bit(&atmel_ports_in_use,
+				sizeof(atmel_ports_in_use));
+
+	if (ret > ATMEL_MAX_UART) {
+		ret = -ENODEV;
+		goto err;
+	}
+
+	if (test_and_set_bit(ret, &atmel_ports_in_use)) {
+		/* port already in use */
+		ret = -EBUSY;
+		goto err;
+	}
+
+	port = &atmel_ports[ret];
 	port->backup_imr = 0;
+	port->uart.line = ret;
 
 	atmel_init_port(port, pdev);
 
@@ -1766,7 +1792,7 @@ err_alloc_ring:
 		clk_put(port->clk);
 		port->clk = NULL;
 	}
-
+err:
 	return ret;
 }
 
@@ -1786,6 +1812,8 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev)
 
 	/* "port" is allocated statically, so we shouldn't free it */
 
+	clear_bit(port->line, &atmel_ports_in_use);
+
 	clk_put(atmel_port->clk);
 
 	return ret;
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH v2 5/5] tty/serial: atmel_serial: add device tree support
From: Nicolas Ferre @ 2011-10-12 16:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318435620-7481-1-git-send-email-nicolas.ferre@atmel.com>

Will use aliases to enumerate ports, if available.

Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/tty/serial/atmel_serial.c |   79 +++++++++++++++++++++++++++++++++----
 1 files changed, 71 insertions(+), 8 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 1074329..fc4081e 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -33,6 +33,8 @@
 #include <linux/sysrq.h>
 #include <linux/tty_flip.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/atmel_pdc.h>
 #include <linux/atmel_serial.h>
@@ -163,6 +165,16 @@ static unsigned long atmel_ports_in_use;
 static struct console atmel_console;
 #endif
 
+#if defined(CONFIG_OF)
+static const struct of_device_id atmel_serial_dt_ids[] = {
+	{ .compatible = "atmel,at91rm9200-usart" },
+	{ .compatible = "atmel,at91sam9260-usart" },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, atmel_serial_dt_ids);
+#endif
+
 static inline struct atmel_uart_port *
 to_atmel_uart_port(struct uart_port *uart)
 {
@@ -1411,6 +1423,48 @@ static struct uart_ops atmel_pops = {
 #endif
 };
 
+static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port,
+					 struct device_node *np)
+{
+	u32 rs485_delay[2];
+
+	/* DMA/PDC usage specification */
+	if (of_get_property(np, "atmel,use-dma-rx", NULL))
+		atmel_port->use_dma_rx	= 1;
+	else
+		atmel_port->use_dma_rx	= 0;
+	if (of_get_property(np, "atmel,use-dma-tx", NULL))
+		atmel_port->use_dma_tx	= 1;
+	else
+		atmel_port->use_dma_tx	= 0;
+
+	/* rs485 properties */
+	if (of_property_read_u32_array(np, "rs485-rts-delay",
+					    rs485_delay, 2) == 0) {
+		struct serial_rs485 *rs485conf = &atmel_port->rs485;
+
+		rs485conf->delay_rts_before_send = rs485_delay[0];
+		rs485conf->delay_rts_after_send = rs485_delay[1];
+		rs485conf->flags = 0;
+
+		if (rs485conf->delay_rts_before_send == 0 &&
+		    rs485conf->delay_rts_after_send == 0) {
+			rs485conf->flags |= SER_RS485_RTS_ON_SEND;
+		} else {
+			if (rs485conf->delay_rts_before_send)
+				rs485conf->flags |= SER_RS485_RTS_BEFORE_SEND;
+			if (rs485conf->delay_rts_after_send)
+				rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
+		}
+
+		if (of_get_property(np, "rs485-rx-during-tx", NULL))
+			rs485conf->flags |= SER_RS485_RX_DURING_TX;
+
+		if (of_get_property(np, "linux,rs485-enabled-at-boot-time", NULL))
+			rs485conf->flags |= SER_RS485_ENABLED;
+	}
+}
+
 /*
  * Configure the port from the platform device resource info.
  */
@@ -1420,6 +1474,14 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
 	struct uart_port *port = &atmel_port->uart;
 	struct atmel_uart_data *pdata = pdev->dev.platform_data;
 
+	if (pdev->dev.of_node) {
+		atmel_of_init_port(atmel_port, pdev->dev.of_node);
+	} else {
+		atmel_port->use_dma_rx	= pdata->use_dma_rx;
+		atmel_port->use_dma_tx	= pdata->use_dma_tx;
+		atmel_port->rs485	= pdata->rs485;
+	}
+
 	port->iotype		= UPIO_MEM;
 	port->flags		= UPF_BOOT_AUTOCONF;
 	port->ops		= &atmel_pops;
@@ -1433,7 +1495,7 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
 
 	memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
 
-	if (pdata->regs) {
+	if (pdata && pdata->regs) {
 		/* Already mapped by setup code */
 		port->membase = pdata->regs;
 	} else {
@@ -1450,10 +1512,6 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
 		/* only enable clock when USART is in use */
 	}
 
-	atmel_port->use_dma_rx	= pdata->use_dma_rx;
-	atmel_port->use_dma_tx	= pdata->use_dma_tx;
-	atmel_port->rs485	= pdata->rs485;
-
 	/* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */
 	if (atmel_port->rs485.flags & SER_RS485_ENABLED)
 		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
@@ -1718,17 +1776,21 @@ static int atmel_serial_resume(struct platform_device *pdev)
 static int __devinit atmel_serial_probe(struct platform_device *pdev)
 {
 	struct atmel_uart_port *port;
+	struct device_node *np = pdev->dev.of_node;
 	struct atmel_uart_data *pdata = pdev->dev.platform_data;
 	void *data;
 	int ret = -ENODEV;
 
 	BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
 
-	if (pdata)
-		ret = pdata->num;
+	if (np)
+		ret = of_alias_get_id(np, "serial");
+	else
+		if (pdata)
+			ret = pdata->num;
 
 	if (ret < 0)
-		/* port id not found in platform data:
+		/* port id not found in platform data nor device-tree aliases:
 		 * auto-enumerate it */
 		ret = find_first_zero_bit(&atmel_ports_in_use,
 				sizeof(atmel_ports_in_use));
@@ -1827,6 +1889,7 @@ static struct platform_driver atmel_serial_driver = {
 	.driver		= {
 		.name	= "atmel_usart",
 		.owner	= THIS_MODULE,
+		.of_match_table	= of_match_ptr(atmel_serial_dt_ids),
 	},
 };
 
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 1/3] ARM: Samsung: Move timer irq numbers to end of linux irq space
From: Rob Herring @ 2011-10-12 16:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318234289-22041-2-git-send-email-thomas.abraham@linaro.org>

On 10/10/2011 03:11 AM, Thomas Abraham wrote:
> All of Samsung's s5p platforms have timer irqs statically mapped from linux
> irq numbers 11 to 15. These timer irqs are moved to end of the statically
> mapped linux irq space and the hardware irqs, which were statically mapped
> starting from 32 is moved to start from 0. The NR_IRQS macro is consolidated
> for all the s5p platforms in this process.
> 
> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
> ---
>  arch/arm/mach-exynos4/include/mach/entry-macro.S |    1 -
>  arch/arm/mach-exynos4/include/mach/irqs.h        |    3 +--
>  arch/arm/mach-s5p64x0/include/mach/irqs.h        |    4 +---
>  arch/arm/mach-s5pc100/include/mach/irqs.h        |    3 +--
>  arch/arm/mach-s5pv210/include/mach/irqs.h        |    3 +--
>  arch/arm/plat-samsung/include/plat/irqs.h        |    7 +++++--
>  6 files changed, 9 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/arm/mach-exynos4/include/mach/entry-macro.S b/arch/arm/mach-exynos4/include/mach/entry-macro.S
> index 4c9adbd..5c4fbcc 100644
> --- a/arch/arm/mach-exynos4/include/mach/entry-macro.S
> +++ b/arch/arm/mach-exynos4/include/mach/entry-macro.S
> @@ -72,7 +72,6 @@
>  		cmpcc	\irqnr, \irqnr
>  		cmpne	\irqnr, \tmp
>  		cmpcs	\irqnr, \irqnr
> -		addne	\irqnr, \irqnr, #32


With this change, can't you now use the common entry-macro-gic.S?


>  		.endm
>  
> diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
> index dfd4b7e..43087c3 100644
> --- a/arch/arm/mach-exynos4/include/mach/irqs.h
> +++ b/arch/arm/mach-exynos4/include/mach/irqs.h
> @@ -163,7 +163,6 @@
>  #define IRQ_GPIO2_NR_GROUPS	9
>  #define IRQ_GPIO_END		(S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
>  
> -/* Set the default NR_IRQS */
> -#define NR_IRQS			(IRQ_GPIO_END + 64)
> +#define IRQ_TIMER_BASE		(IRQ_GPIO_END + 64)
>  
>  #endif /* __ASM_ARCH_IRQS_H */
> diff --git a/arch/arm/mach-s5p64x0/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h
> index 53982db..bea73cc 100644
> --- a/arch/arm/mach-s5p64x0/include/mach/irqs.h
> +++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h
> @@ -141,8 +141,6 @@
>  
>  #define IRQ_EINT_GROUP(grp, x)	(IRQ_EINT_GROUP##grp##_BASE + (x))
>  
> -/* Set the default NR_IRQS */
> -
> -#define NR_IRQS			(IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
> +#define IRQ_TIMER_BASE		(IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
>  
>  #endif /* __ASM_ARCH_IRQS_H */
> diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h
> index d2eb475..3a9d300 100644
> --- a/arch/arm/mach-s5pc100/include/mach/irqs.h
> +++ b/arch/arm/mach-s5pc100/include/mach/irqs.h
> @@ -104,8 +104,7 @@
>  #define S5P_GPIOINT_BASE	(IRQ_EINT(31) + 1)
>  #define S5P_GPIOINT_GROUP_MAXNR	21
>  
> -/* Set the default NR_IRQS */
> -#define NR_IRQS			(IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
> +#define IRQ_TIMER_BASE		(IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
>  
>  /* Compatibility */
>  #define IRQ_LCD_FIFO		IRQ_LCD0
> diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
> index 5e0de3a..df3173a 100644
> --- a/arch/arm/mach-s5pv210/include/mach/irqs.h
> +++ b/arch/arm/mach-s5pv210/include/mach/irqs.h
> @@ -125,8 +125,7 @@
>  #define S5P_GPIOINT_BASE	(IRQ_EINT(31) + 1)
>  #define S5P_GPIOINT_GROUP_MAXNR	22
>  
> -/* Set the default NR_IRQS */
> -#define NR_IRQS			(IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
> +#define IRQ_TIMER_BASE		(IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
>  
>  /* Compatibility */
>  #define IRQ_LCD_FIFO		IRQ_LCD0
> diff --git a/arch/arm/plat-samsung/include/plat/irqs.h b/arch/arm/plat-samsung/include/plat/irqs.h
> index 08d1a7e..b8918b3 100644
> --- a/arch/arm/plat-samsung/include/plat/irqs.h
> +++ b/arch/arm/plat-samsung/include/plat/irqs.h
> @@ -22,7 +22,7 @@
>   * mulitple of 32 to allow the common code to work
>   */
>  
> -#define S5P_IRQ_OFFSET		(32)
> +#define S5P_IRQ_OFFSET		(0)

Just remove this.

>  
>  #define S5P_IRQ(x)		((x) + S5P_IRQ_OFFSET)
>  
> @@ -44,13 +44,14 @@
>  #define S5P_IRQ_VIC2(x)		(S5P_VIC2_BASE + (x))
>  #define S5P_IRQ_VIC3(x)		(S5P_VIC3_BASE + (x))
>  
> -#define S5P_TIMER_IRQ(x)	(11 + (x))
> +#define S5P_TIMER_IRQ(x)	(IRQ_TIMER_BASE + (x))
>  
>  #define IRQ_TIMER0		S5P_TIMER_IRQ(0)
>  #define IRQ_TIMER1		S5P_TIMER_IRQ(1)
>  #define IRQ_TIMER2		S5P_TIMER_IRQ(2)
>  #define IRQ_TIMER3		S5P_TIMER_IRQ(3)
>  #define IRQ_TIMER4		S5P_TIMER_IRQ(4)
> +#define IRQ_TIMER_COUNT		(5)
>  
>  #define IRQ_EINT(x)		((x) < 16 ? ((x) + S5P_EINT_BASE1) \
>  					: ((x) - 16 + S5P_EINT_BASE2))
> @@ -77,4 +78,6 @@
>  #define S5P_IRQ_TYPE_EDGE_RISING	(0x03)
>  #define S5P_IRQ_TYPE_EDGE_BOTH		(0x04)
>  
> +#define NR_IRQS			(IRQ_TIMER_BASE + IRQ_TIMER_COUNT)
> +
>  #endif /* __PLAT_SAMSUNG_IRQS_H */

Really these timer irqs should be converted to irq domains and be
dynamically allocated in the linux irq space, but this is at least a
step in the right direction.

Rob

^ permalink raw reply

* [PATCH] ARM: kprobes: only patch instructions on one CPU
From: Rabin Vincent @ 2011-10-12 16:12 UTC (permalink / raw)
  To: linux-arm-kernel

The text patching needs to be done only once, instead of once on each
CPU.  The other CPUs will busy wait inside the stop machine code until
the patching is done.

Cc: Jon Medhurst <tixy@yxit.co.uk>
Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Rabin Vincent <rabin@rab.in>
---
 arch/arm/kernel/kprobes.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 129c116..e9f95300 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -127,7 +127,7 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
 		flush_insns(addr, sizeof(u16));
 	} else if (addr & 2) {
 		/* A 32-bit instruction spanning two words needs special care */
-		stop_machine(set_t32_breakpoint, (void *)addr, &cpu_online_map);
+		stop_machine(set_t32_breakpoint, (void *)addr, NULL);
 	} else {
 		/* Word aligned 32-bit instruction can be written atomically */
 		u32 bkp = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION;
@@ -190,7 +190,7 @@ int __kprobes __arch_disarm_kprobe(void *p)
 
 void __kprobes arch_disarm_kprobe(struct kprobe *p)
 {
-	stop_machine(__arch_disarm_kprobe, p, &cpu_online_map);
+	stop_machine(__arch_disarm_kprobe, p, NULL);
 }
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 2/3] ARM: Exynos4: Add ioremap interceptor for statically remapped regions
From: Rob Herring @ 2011-10-12 16:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318234289-22041-3-git-send-email-thomas.abraham@linaro.org>

On 10/10/2011 03:11 AM, Thomas Abraham wrote:
> ioremap() request for statically remapped regions are intercepted and the
> statically assigned virtual address is returned. For requests for which
> there are no statically remapped regions, the requests are let through.
> 
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
> ---
>  arch/arm/mach-exynos4/cpu.c             |   16 ++++++++++++++++
>  arch/arm/mach-exynos4/include/mach/io.h |    4 ++++
>  2 files changed, 20 insertions(+), 0 deletions(-)
> 

You won't need this with Nico's vmalloc.h clean-up series. It does
exactly this but generically for all platforms.

Rob

^ permalink raw reply

* [PATCH] gpio: exynos4: Add device tree support
From: Thomas Abraham @ 2011-10-12 16:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E95AE26.8080702@gmail.com>

On 12 October 2011 20:41, Rob Herring <robherring2@gmail.com> wrote:
> On 10/11/2011 11:06 AM, Thomas Abraham wrote:
>> On 11 October 2011 21:00, Rob Herring <robherring2@gmail.com> wrote:
>>> On 10/11/2011 10:19 AM, Thomas Abraham wrote:
>>>> Hi Rob,
>>>>
>>>> On 11 October 2011 20:41, Rob Herring <robherring2@gmail.com> wrote:
>>>>> Thomas,
>>>>>
>>>>> On 10/11/2011 03:16 AM, Thomas Abraham wrote:
>>>>>> As gpio chips get registered, a device tree node which represents the
>>>>>> gpio chip is searched and attached to it. A translate function is also
>>>>>> provided to convert the gpio specifier into actual platform settings
>>>>>> for pin function selection, pull up/down and driver strength settings.
>>>>>>
>>>>>> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
>>>>>> ---
>>>>>> This patch is based on the latest consolidated Samsung GPIO driver available
>>>>>> in the following tree:
>>>>>> ? https://github.com/kgene/linux-samsung.git ?branch: for-next
>>>>>>
>>>>>> ?.../devicetree/bindings/gpio/gpio-samsung.txt ? ? ?| ? 30 +++++++++++
>>>>>> ?drivers/gpio/gpio-samsung.c ? ? ? ? ? ? ? ? ? ? ? ?| ? 53 ++++++++++++++++++++
>>>>>> ?2 files changed, 83 insertions(+), 0 deletions(-)
>>>>>> ?create mode 100644 Documentation/devicetree/bindings/gpio/gpio-samsung.txt
>>>>>>
>>>>>> diff --git a/Documentation/devicetree/bindings/gpio/gpio-samsung.txt b/Documentation/devicetree/bindings/gpio/gpio-samsung.txt
>>>>>> new file mode 100644
>>>>>> index 0000000..883faeb
>>>>>> --- /dev/null
>>>>>> +++ b/Documentation/devicetree/bindings/gpio/gpio-samsung.txt
>>>>>> @@ -0,0 +1,30 @@
>>>>>> +Samsung Exynos4 GPIO Controller
>>>>>> +
>>>>>> +Required properties:
>>>>>> +- compatible: Format of compatible property value should be
>>>>>> + ?"samsung,exynos4-gpio-<controller_name>". Example: For GPA0 controller, the
>>>>>> + ?compatible property value should be "samsung,exynos4-gpio-gpa0".
>>>>>
>>>>> Isn't gpa0 an instance of the h/w, not a version?
>>>>
>>>> GPA0 is a instance of the gpio controller. There are several such
>>>> instances and there could be differences in those instances such as
>>>> the number of GPIO lines managed by that gpio controller instance.
>>>>
>>>
>>> That doesn't seem like a reason to have different compatible strings.
>>> Does that affect the programming model of the controller? Unused lines
>>> whether at the board level or SOC level shouldn't really matter.
>>
>>
>> No, that does not affect the programming of the controller. The reason
>> for the instance name extension in compatible string is to match the
>> gpio_chip with a gpio controller node. When matched, the of_node
>> pointer of the gpio_chip is set to point to that controller node.
>>
>> This might not be the best possible implementation but the device tree
>> support code in this patch is dictated by the structure of the
>> existing gpio driver code. As you suggested previously, I will look at
>> reworking the gpio driver a little later but for now, there was a need
>> for working gpio dt solution to make progress on dt support for other
>> controllers.
>
> Linux should provide clues about what's needed in a binding, but the
> binding should not be defined based on current Linux code. Doing the
> binding one way and changing it later is not a good plan.

Ok. When starting on this, two compatible values where used for the
gpio controllers, one was "samsung,exynos4-gpio" and another was
"samsung,exynos4-gpio-<ctrl_name>". And when the gpio dt support would
mature, the second compatible value could be dropped. Non-linux
platforms could always use the generic "samsung,exynos4-gpio"
compatible value to match. I moved to using only
"samsung,exynos4-gpio-<ctrl_name>" just before sending this patch
because I was not sure of the right approach.

>
> I think you need to convert all users of gpio over as well so you can
> move to dynamic gpio_chip creation and gpio numbering. Or maybe you can
> match based on base address? This is going to be a common problem as
> gpio is converted over to DT. Perhaps Grant or others have suggestions
> on the approach to use.

Yes, I agree with you about the dynamic gpio_chip creation and gpio
numbering. Probably, I should have focussed more on this before moving
to dt support for other controllers.

But matching based on base address is still an option if that is
better than matching with compatible values as defined currently. The
'struct samsung_gpio_chip' which encapsulates 'struct gpio_chip' has
information about the base address of the gpio controller. The match
of gpio device node with 'struct gpio_chip' can be quickly moved over
to base address matching. Would this be better than the current
approach?

Thank you for your comments Rob.

Regards,
Thomas.

>
> Rob
>

^ permalink raw reply

* [PATCH V4 3/3] ARM: SAMSUNG: Add lookup of sdhci-s3c clocks using generic names
From: Sylwester Nawrocki @ 2011-10-12 16:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAPs=JDf2N1kh4BO9nPBb-J6k51e-ytntrNOvw_UOKtw-ktdycA@mail.gmail.com>

On 10/12/2011 02:36 PM, Rajeshwari Birje wrote:
> On Wed, Oct 12, 2011 at 3:54 PM, Sylwester Nawrocki
> <s.nawrocki@samsung.com> wrote:
>> Hi Rajeshwari,
>>
>> On 10/12/2011 11:43 AM, Rajeshwari Shinde wrote:
>>> Add support for lookup of sdhci-s3c controller clocks using generic names
>>> for s3c2416, s3c64xx, s5pc100, s5pv210 and exynos4 SoC's.
>>>
>>> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
>>> ---
>>>  arch/arm/mach-exynos4/clock.c         |   88 ++++++++++-------
>>>  arch/arm/mach-s3c2416/clock.c         |   68 +++++++------
>>>  arch/arm/mach-s3c64xx/clock.c         |  126 +++++++++++++++----------
>>>  arch/arm/mach-s5pc100/clock.c         |  130 ++++++++++++++++----------
>>>  arch/arm/mach-s5pv210/clock.c         |  167 ++++++++++++++++++++-------------
>>>  arch/arm/plat-s3c24xx/s3c2443-clock.c |   15 ++-
>>>  6 files changed, 359 insertions(+), 235 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
>>> index 9f50e33..c6383b9 100644
>>> --- a/arch/arm/mach-exynos4/clock.c
>>> +++ b/arch/arm/mach-exynos4/clock.c
>>> @@ -1157,42 +1157,6 @@ static struct clksrc_clk clksrcs[] = {
>>>               .reg_div = { .reg = S5P_CLKDIV_MFC, .shift = 0, .size = 4 },
...
>>> +static struct clksrc_clk clk_sclk_mmc0 = {
>>> +     .clk            = {
>>> +             .name           = "sclk_mmc",
>>> +             .devname        = "s3c-sdhci.0",
>>
>> Would it make sense to drop this 'devname' field here and others
>> until sclk_mmc3 ....
> 
> *** The devname here distinguishes these clocks. So it should be okay
> to have a devname for these clocks.

I'm not sure what's Mr Kukjin's opinion on that, but I personally would really
like to see all the devname fields disappear from samsung clk data structures.
Possibly if all involved people would keep that in mind we could achieve this
over time.

> 
>>
>>> +             .parent         = &clk_dout_mmc0.clk,
>>> +             .enable         = exynos4_clksrc_mask_fsys_ctrl,
>>> +             .ctrlbit        = (1 << 0),
>>> +     },
>>> +     .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 8, .size = 8 },
>>> +};
>>> +
>>> +static struct clksrc_clk clk_sclk_mmc1 = {
>>> +     .clk            = {
>>> +             .name           = "sclk_mmc",
>>> +             .devname        = "s3c-sdhci.1",
>>
>>> +             .parent         = &clk_dout_mmc1.clk,
>>> +             .enable         = exynos4_clksrc_mask_fsys_ctrl,
>>> +             .ctrlbit        = (1 << 4),
>>> +     },
>>> +     .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 24, .size = 8 },
>>> +};
>>> +
>>> +static struct clksrc_clk clk_sclk_mmc2 = {
>>> +     .clk            = {
>>> +             .name           = "sclk_mmc",
>>> +             .devname        = "s3c-sdhci.2",
>>
>>> +             .parent         = &clk_dout_mmc2.clk,
>>> +             .enable         = exynos4_clksrc_mask_fsys_ctrl,
>>> +             .ctrlbit        = (1 << 8),
>>> +     },
>>> +     .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 8, .size = 8 },
>>> +};
>>> +
>>> +static struct clksrc_clk clk_sclk_mmc3 = {
>>> +     .clk            = {
>>> +             .name           = "sclk_mmc",
>>> +             .devname        = "s3c-sdhci.3",
>>
>>> +             .parent         = &clk_dout_mmc3.clk,
>>> +             .enable         = exynos4_clksrc_mask_fsys_ctrl,
>>> +             .ctrlbit        = (1 << 12),
>>> +     },
>>> +     .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 },
>>> +};
>>> +
>>>  /* Clock initialization code */
>>>  static struct clksrc_clk *sysclks[] = {
>>>       &clk_mout_apll,
>>> @@ -1289,6 +1297,10 @@ static struct clksrc_clk *clksrc_cdev[] = {
>>>       &clk_sclk_uart1,
>>>       &clk_sclk_uart2,
>>>       &clk_sclk_uart3,
>>> +     &clk_sclk_mmc0,
>>> +     &clk_sclk_mmc1,
>>> +     &clk_sclk_mmc2,
>>> +     &clk_sclk_mmc3,
>>
>> ..then drop the above 4 lines...
> 
> **** The registration for these clocks are important. The
> s3c_register_clksrc() function sets the .ops of this clock and also
> its parent. So the registration cannot be dropped.

OK.

> 
>>
>>>  };
>>>
>>>  static struct clk_lookup exynos4_clk_lookup[] = {
>>> @@ -1296,6 +1308,10 @@ static struct clk_lookup exynos4_clk_lookup[] = {
>>>       CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &clk_sclk_uart1.clk),
>>>       CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &clk_sclk_uart2.clk),
>>>       CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &clk_sclk_uart3.clk),
>>> +     CLKDEV_INIT("exynos4-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
>>> +     CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
>>> +     CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
>>> +     CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &clk_sclk_mmc3.clk),
>>
>> ..and add something like:
>>
>>  +      CLKDEV_INIT("s3c-sdhci.0", "sclk_mmc", &clk_sclk_mmc0.clk),
>>  +      CLKDEV_INIT("s3c-sdhci.1", "sclk_mmc", &clk_sclk_mmc1.clk),
>>  +      CLKDEV_INIT("s3c-sdhci.2", "sclk_mmc", &clk_sclk_mmc2.clk),
>>  +      CLKDEV_INIT("s3c-sdhci.3", "sclk_mmc", &clk_sclk_mmc3.clk),
>>
>> ?
> 
> **** The driver uses a common name for the possible bus clock sources,
> that is ?mmc_busclk?. This keeps the clock lookup code in the driver
> simple. Also, there could be SoC?s which do no use sclk_mmc as the bus
> clock name as per the user manual

OK, I was aware of that. I didn't mean removing the "mmc_busclk.2" entries,
just adding another 4, which are created anyway by s3c_register_clksrc()
function. But for now I think the patch is OK.

> 
> 
>>
>> Also I'm wondering why we're using different device names for clk_sclk_mmc0..3
>> clocks, i.e. exynos4-sdhci.? and s3c-sdhci.? ?
>>
>> Does it all work on exynos ? I would expect the device name to be same
>> across all the clock definitions, otherwise clk_get(dev, ..) will fail.
> 
> **** There was a patch submitted to rename the device name of sdhci
> for Exynos to exynos4-sdhci. I will remove this change from this patch
> and let that patch handle this change.

I wouldn't do that. IMHO it's better to keep this patch as is, to make the final
diff size lower.
Perhaps it's even worth to consider doing the clock rename altogether in this patch.
But it's of course up to you.


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

^ permalink raw reply

* [PATCH 1/3] ARM: Samsung: Move timer irq numbers to end of linux irq space
From: Thomas Abraham @ 2011-10-12 16:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E95BC01.8090805@gmail.com>

On 12 October 2011 21:40, Rob Herring <robherring2@gmail.com> wrote:
> On 10/10/2011 03:11 AM, Thomas Abraham wrote:
>> All of Samsung's s5p platforms have timer irqs statically mapped from linux
>> irq numbers 11 to 15. These timer irqs are moved to end of the statically
>> mapped linux irq space and the hardware irqs, which were statically mapped
>> starting from 32 is moved to start from 0. The NR_IRQS macro is consolidated
>> for all the s5p platforms in this process.
>>
>> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
>> ---
>> ?arch/arm/mach-exynos4/include/mach/entry-macro.S | ? ?1 -
>> ?arch/arm/mach-exynos4/include/mach/irqs.h ? ? ? ?| ? ?3 +--
>> ?arch/arm/mach-s5p64x0/include/mach/irqs.h ? ? ? ?| ? ?4 +---
>> ?arch/arm/mach-s5pc100/include/mach/irqs.h ? ? ? ?| ? ?3 +--
>> ?arch/arm/mach-s5pv210/include/mach/irqs.h ? ? ? ?| ? ?3 +--
>> ?arch/arm/plat-samsung/include/plat/irqs.h ? ? ? ?| ? ?7 +++++--
>> ?6 files changed, 9 insertions(+), 12 deletions(-)
>>
>> diff --git a/arch/arm/mach-exynos4/include/mach/entry-macro.S b/arch/arm/mach-exynos4/include/mach/entry-macro.S
>> index 4c9adbd..5c4fbcc 100644
>> --- a/arch/arm/mach-exynos4/include/mach/entry-macro.S
>> +++ b/arch/arm/mach-exynos4/include/mach/entry-macro.S
>> @@ -72,7 +72,6 @@
>> ? ? ? ? ? ? ? cmpcc ? \irqnr, \irqnr
>> ? ? ? ? ? ? ? cmpne ? \irqnr, \tmp
>> ? ? ? ? ? ? ? cmpcs ? \irqnr, \irqnr
>> - ? ? ? ? ? ? addne ? \irqnr, \irqnr, #32
>
>
> With this change, can't you now use the common entry-macro-gic.S?


The get_irqnr_preamble macro is quite different from that in
entry-macro-gic.S file. Maybe it is possible to use the common
entry-macro-gic.S file with some rework of exynos machine code.


>
>
>> ? ? ? ? ? ? ? .endm
>>
>> diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
>> index dfd4b7e..43087c3 100644
>> --- a/arch/arm/mach-exynos4/include/mach/irqs.h
>> +++ b/arch/arm/mach-exynos4/include/mach/irqs.h
>> @@ -163,7 +163,6 @@
>> ?#define IRQ_GPIO2_NR_GROUPS ?9
>> ?#define IRQ_GPIO_END ? ? ? ? (S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
>>
>> -/* Set the default NR_IRQS */
>> -#define NR_IRQS ? ? ? ? ? ? ? ? ? ? ?(IRQ_GPIO_END + 64)
>> +#define IRQ_TIMER_BASE ? ? ? ? ? ? ? (IRQ_GPIO_END + 64)
>>
>> ?#endif /* __ASM_ARCH_IRQS_H */
>> diff --git a/arch/arm/mach-s5p64x0/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h
>> index 53982db..bea73cc 100644
>> --- a/arch/arm/mach-s5p64x0/include/mach/irqs.h
>> +++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h
>> @@ -141,8 +141,6 @@
>>
>> ?#define IRQ_EINT_GROUP(grp, x) ? ? ? (IRQ_EINT_GROUP##grp##_BASE + (x))
>>
>> -/* Set the default NR_IRQS */
>> -
>> -#define NR_IRQS ? ? ? ? ? ? ? ? ? ? ?(IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
>> +#define IRQ_TIMER_BASE ? ? ? ? ? ? ? (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
>>
>> ?#endif /* __ASM_ARCH_IRQS_H */
>> diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h
>> index d2eb475..3a9d300 100644
>> --- a/arch/arm/mach-s5pc100/include/mach/irqs.h
>> +++ b/arch/arm/mach-s5pc100/include/mach/irqs.h
>> @@ -104,8 +104,7 @@
>> ?#define S5P_GPIOINT_BASE ? ? (IRQ_EINT(31) + 1)
>> ?#define S5P_GPIOINT_GROUP_MAXNR ? ? ?21
>>
>> -/* Set the default NR_IRQS */
>> -#define NR_IRQS ? ? ? ? ? ? ? ? ? ? ?(IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
>> +#define IRQ_TIMER_BASE ? ? ? ? ? ? ? (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
>>
>> ?/* Compatibility */
>> ?#define IRQ_LCD_FIFO ? ? ? ? IRQ_LCD0
>> diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
>> index 5e0de3a..df3173a 100644
>> --- a/arch/arm/mach-s5pv210/include/mach/irqs.h
>> +++ b/arch/arm/mach-s5pv210/include/mach/irqs.h
>> @@ -125,8 +125,7 @@
>> ?#define S5P_GPIOINT_BASE ? ? (IRQ_EINT(31) + 1)
>> ?#define S5P_GPIOINT_GROUP_MAXNR ? ? ?22
>>
>> -/* Set the default NR_IRQS */
>> -#define NR_IRQS ? ? ? ? ? ? ? ? ? ? ?(IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
>> +#define IRQ_TIMER_BASE ? ? ? ? ? ? ? (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
>>
>> ?/* Compatibility */
>> ?#define IRQ_LCD_FIFO ? ? ? ? IRQ_LCD0
>> diff --git a/arch/arm/plat-samsung/include/plat/irqs.h b/arch/arm/plat-samsung/include/plat/irqs.h
>> index 08d1a7e..b8918b3 100644
>> --- a/arch/arm/plat-samsung/include/plat/irqs.h
>> +++ b/arch/arm/plat-samsung/include/plat/irqs.h
>> @@ -22,7 +22,7 @@
>> ? * mulitple of 32 to allow the common code to work
>> ? */
>>
>> -#define S5P_IRQ_OFFSET ? ? ? ? ? ? ? (32)
>> +#define S5P_IRQ_OFFSET ? ? ? ? ? ? ? (0)
>
> Just remove this.

Ok.

>
>>
>> ?#define S5P_IRQ(x) ? ? ? ? ? ((x) + S5P_IRQ_OFFSET)
>>
>> @@ -44,13 +44,14 @@
>> ?#define S5P_IRQ_VIC2(x) ? ? ? ? ? ? ?(S5P_VIC2_BASE + (x))
>> ?#define S5P_IRQ_VIC3(x) ? ? ? ? ? ? ?(S5P_VIC3_BASE + (x))
>>
>> -#define S5P_TIMER_IRQ(x) ? ? (11 + (x))
>> +#define S5P_TIMER_IRQ(x) ? ? (IRQ_TIMER_BASE + (x))
>>
>> ?#define IRQ_TIMER0 ? ? ? ? ? S5P_TIMER_IRQ(0)
>> ?#define IRQ_TIMER1 ? ? ? ? ? S5P_TIMER_IRQ(1)
>> ?#define IRQ_TIMER2 ? ? ? ? ? S5P_TIMER_IRQ(2)
>> ?#define IRQ_TIMER3 ? ? ? ? ? S5P_TIMER_IRQ(3)
>> ?#define IRQ_TIMER4 ? ? ? ? ? S5P_TIMER_IRQ(4)
>> +#define IRQ_TIMER_COUNT ? ? ? ? ? ? ?(5)
>>
>> ?#define IRQ_EINT(x) ? ? ? ? ?((x) < 16 ? ((x) + S5P_EINT_BASE1) \
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? : ((x) - 16 + S5P_EINT_BASE2))
>> @@ -77,4 +78,6 @@
>> ?#define S5P_IRQ_TYPE_EDGE_RISING ? ? (0x03)
>> ?#define S5P_IRQ_TYPE_EDGE_BOTH ? ? ? ? ? ? ? (0x04)
>>
>> +#define NR_IRQS ? ? ? ? ? ? ? ? ? ? ?(IRQ_TIMER_BASE + IRQ_TIMER_COUNT)
>> +
>> ?#endif /* __PLAT_SAMSUNG_IRQS_H */
>
> Really these timer irqs should be converted to irq domains and be
> dynamically allocated in the linux irq space, but this is at least a
> step in the right direction.

Ok.

Thanks for your comments.

Regards,
Thomas.

>
> Rob
>

^ permalink raw reply

* [PATCH 2/3] ARM: Exynos4: Add ioremap interceptor for statically remapped regions
From: Thomas Abraham @ 2011-10-12 16:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E95BC8E.8010105@gmail.com>

On 12 October 2011 21:43, Rob Herring <robherring2@gmail.com> wrote:
> On 10/10/2011 03:11 AM, Thomas Abraham wrote:
>> ioremap() request for statically remapped regions are intercepted and the
>> statically assigned virtual address is returned. For requests for which
>> there are no statically remapped regions, the requests are let through.
>>
>> Cc: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
>> ---
>> ?arch/arm/mach-exynos4/cpu.c ? ? ? ? ? ? | ? 16 ++++++++++++++++
>> ?arch/arm/mach-exynos4/include/mach/io.h | ? ?4 ++++
>> ?2 files changed, 20 insertions(+), 0 deletions(-)
>>
>
> You won't need this with Nico's vmalloc.h clean-up series. It does
> exactly this but generically for all platforms.

Ok. Thanks for your suggestion. I will move to using Nico's patches.

Regards,
Thomas.

>
> Rob
>

^ permalink raw reply

* [PATCH] [RFC PATCH] ARM: kprobes: Make breakpoint setting/clearing SMP safe
From: Rabin Vincent @ 2011-10-12 16:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1310474402-5398-1-git-send-email-tixy@yxit.co.uk>

On Tue, Jul 12, 2011 at 18:10, Tixy <tixy@yxit.co.uk> wrote:
> Both these issues are known and the kprobe implementation uses
> stop_machine() to avoid them, however, this is not sufficient.
> stop_machine() does not perform any kind on synchronisation between CPUs
> so it it still possible for one CPU to call the breakpoint changing
> function before another CPU has been interrupted to do likewise.
>
> To fix this problem, this patch creates a new function
> sync_stop_machine() which ensures that all online CPUs execute the
> specified function at the same time.

AFAICS stop_machine() already does what you want.  When you use
stop_machine(), the actual call to your function is done (on each
CPU's stopper thread) using the stop_machine_cpu_stop() function,
which already has the synchronization between CPUs which you're
trying to do here.

^ permalink raw reply

* [PATCH 1/4] dmaengine: at_hdmac: platform data move to use .id_table
From: Nicolas Ferre @ 2011-10-12 16:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318342612.1546.352.camel@vkoul-udesk3>

On 10/11/2011 04:16 PM, Vinod Koul :
> On Mon, 2011-10-10 at 18:37 +0200, Nicolas Ferre wrote:
>> We remove platform data from DMA controller and move
>> to the use of .id_table to distinguish between compatible
>> types. The two implementations allow to determine the
>> number of channels and the capabilities of the controller.
>>
>> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
>> ---
>>  drivers/dma/at_hdmac.c      |   48 ++++++++++++++++++++++++++++++++++---------
>>  drivers/dma/at_hdmac_regs.h |    8 +++++++
>>  2 files changed, 46 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
>> index fcfa0a8..fef57bc 100644
>> --- a/drivers/dma/at_hdmac.c
>> +++ b/drivers/dma/at_hdmac.c
>> @@ -1175,6 +1175,18 @@ static void atc_free_chan_resources(struct dma_chan *chan)
>>  
>>  /*--  Module Management  -----------------------------------------------*/
>>  
>> +static struct platform_device_id atdma_devtypes[] = {
>> +	{
>> +		.name = "at91sam9rl_dma",
>> +		.driver_data = ATDMA_DEVTYPE_SAM9RL,
>> +	}, {
>> +		.name = "at91sam9g45_dma",
>> +		.driver_data = ATDMA_DEVTYPE_SAM9G45,
>> +	}, {
>> +		/* sentinel */
>> +	}
>> +};
>> +
>>  /**
>>   * at_dma_off - disable DMA controller
>>   * @atdma: the Atmel HDAMC device
>> @@ -1193,18 +1205,32 @@ static void at_dma_off(struct at_dma *atdma)
>>  
>>  static int __init at_dma_probe(struct platform_device *pdev)
>>  {
>> -	struct at_dma_platform_data *pdata;
>>  	struct resource		*io;
>>  	struct at_dma		*atdma;
>>  	size_t			size;
>>  	int			irq;
>>  	int			err;
>>  	int			i;
>> +	u32                     nr_channels;
>> +	dma_cap_mask_t          cap_mask = {};
>> +	enum atdma_devtype	atdmatype;
>> +
>> +	dma_cap_set(DMA_MEMCPY, cap_mask);
>> +
>> +	/* get DMA parameters from controller type */
>> +	atdmatype = platform_get_device_id(pdev)->driver_data;
>>  
>> -	/* get DMA Controller parameters from platform */
>> -	pdata = pdev->dev.platform_data;
>> -	if (!pdata || pdata->nr_channels > AT_DMA_MAX_NR_CHANNELS)
>> +	switch (atdmatype) {
>> +	case ATDMA_DEVTYPE_SAM9RL:
>> +		nr_channels = 2;
>> +		break;
>> +	case ATDMA_DEVTYPE_SAM9G45:
>> +		nr_channels = 8;
>> +		dma_cap_set(DMA_SLAVE, cap_mask);
>> +		break;
>> +	default:
>>  		return -EINVAL;
>> +	}
>>  
>>  	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>  	if (!io)
>> @@ -1215,14 +1241,15 @@ static int __init at_dma_probe(struct platform_device *pdev)
>>  		return irq;
>>  
>>  	size = sizeof(struct at_dma);
>> -	size += pdata->nr_channels * sizeof(struct at_dma_chan);
>> +	size += nr_channels * sizeof(struct at_dma_chan);
>>  	atdma = kzalloc(size, GFP_KERNEL);
>>  	if (!atdma)
>>  		return -ENOMEM;
>>  
>> -	/* discover transaction capabilites from the platform data */
>> -	atdma->dma_common.cap_mask = pdata->cap_mask;
>> -	atdma->all_chan_mask = (1 << pdata->nr_channels) - 1;
>> +	/* discover transaction capabilites */
> capabilities

Yes.

>> +	atdma->dma_common.cap_mask = cap_mask;
>> +	atdma->all_chan_mask = (1 << nr_channels) - 1;
>> +	atdma->devtype = atdmatype;
>>  
>>  	size = resource_size(io);
>>  	if (!request_mem_region(io->start, size, pdev->dev.driver->name)) {
>> @@ -1268,7 +1295,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
>>  
>>  	/* initialize channels related values */
>>  	INIT_LIST_HEAD(&atdma->dma_common.channels);
>> -	for (i = 0; i < pdata->nr_channels; i++) {
>> +	for (i = 0; i < nr_channels; i++) {
>>  		struct at_dma_chan	*atchan = &atdma->chan[i];
>>  
>>  		atchan->chan_common.device = &atdma->dma_common;
>> @@ -1313,7 +1340,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
>>  	dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n",
>>  	  dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "",
>>  	  dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)  ? "slave " : "",
>> -	  pdata->nr_channels);
>> +	  nr_channels);
> indent?

Well, this dev_info statement seems pretty well indented: if I use a
tab, then I cross the 80 column rule, and I would like to keep the "?:"
operator on one line... So I would like to keep it like this.

>>  	dma_async_device_register(&atdma->dma_common);
>>  
>> @@ -1495,6 +1522,7 @@ static const struct dev_pm_ops at_dma_dev_pm_ops = {
>>  static struct platform_driver at_dma_driver = {
>>  	.remove		= __exit_p(at_dma_remove),
>>  	.shutdown	= at_dma_shutdown,
>> +	.id_table	= atdma_devtypes,
>>  	.driver = {
>>  		.name	= "at_hdmac",
>>  		.pm	= &at_dma_dev_pm_ops,
>> diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
>> index aa4c9ae..d7d6737 100644
>> --- a/drivers/dma/at_hdmac_regs.h
>> +++ b/drivers/dma/at_hdmac_regs.h
>> @@ -248,9 +248,16 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
>>  
>>  /*--  Controller  ------------------------------------------------------*/
>>  
>> +enum atdma_devtype {
>> +	ATDMA_DEVTYPE_UNDEFINED = 0,
>> +	ATDMA_DEVTYPE_SAM9RL,	/* compatible with SAM9RL DMA controller */
>> +	ATDMA_DEVTYPE_SAM9G45,	/* compatible with SAM9G45 DMA controller */
>> +};
>> +
>>  /**
>>   * struct at_dma - internal representation of an Atmel HDMA Controller
>>   * @chan_common: common dmaengine dma_device object members
>> + * @atdma_devtype: identifier of DMA controller compatibility
>>   * @ch_regs: memory mapped register base
>>   * @clk: dma controller clock
>>   * @save_imr: interrupt mask register that is saved on suspend/resume cycle
>> @@ -260,6 +267,7 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
>>   */
>>  struct at_dma {
>>  	struct dma_device	dma_common;
>> +	enum atdma_devtype	devtype;
>>  	void __iomem		*regs;
>>  	struct clk		*clk;
>>  	u32			save_imr;
> Little confused at this, where is the remove of existing platfrom data
> per the changelog?

Well, yes, it is the use of platform data that is removed, not the
structure it self. I change the log message in my v2 patch series.

thanks, bye,
-- 
Nicolas Ferre

^ permalink raw reply

* [PATCH 1/4] dmaengine: at_hdmac: platform data move to use .id_table
From: Nicolas Ferre @ 2011-10-12 16:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E95C1AF.5080803@atmel.com>

On 10/12/2011 06:34 PM, Nicolas Ferre :
> On 10/11/2011 04:16 PM, Vinod Koul :

[..]

>> Little confused at this, where is the remove of existing platfrom data
>> per the changelog?
> 
> Well, yes, it is the use of platform data that is removed, not the
> structure it self. I change the log message in my v2 patch series.

v3 actually...

Bye,
-- 
Nicolas Ferre

^ permalink raw reply

* [PATCH v3 0/4] dmaengine: Device Tree support for Atmel DMA
From: Nicolas Ferre @ 2011-10-12 16:57 UTC (permalink / raw)
  To: linux-arm-kernel

This series add the device tree support to Atmel DMA controller driver:
at_hdmac.
The removal of platform data ease the conversion to device tree. It also have
the additional benefit of being simpler and cleaner.

Nicolas Ferre (4):
      dmaengine: at_hdmac: platform data move to use .id_table
      dmaengine: at_hdmac: add device tree support
      ARM: at91/dma: remove platform data from DMA controller
      ARM: at91/dma: DMA controller registering with DT support

 .../devicetree/bindings/dma/atmel-dma.txt          |   14 ++++
 arch/arm/mach-at91/at91sam9g45_devices.c           |   17 ++---
 arch/arm/mach-at91/at91sam9rl_devices.c            |    8 +--
 arch/arm/mach-at91/include/mach/at_hdmac.h         |   10 ---
 drivers/dma/at_hdmac.c                             |   76 +++++++++++++++++---
 drivers/dma/at_hdmac_regs.h                        |    8 ++
 6 files changed, 97 insertions(+), 36 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/dma/atmel-dma.txt

Best regards,
-- 
Nicolas Ferre

^ permalink raw reply

* [PATCH v3 1/4] dmaengine: at_hdmac: platform data move to use .id_table
From: Nicolas Ferre @ 2011-10-12 16:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1318438634-11826-1-git-send-email-nicolas.ferre@atmel.com>

We remove the use of platform data from DMA controller driver.
We now use of .id_table to distinguish between compatible
types. The two implementations allow to determine the
number of channels and the capabilities of the controller.

Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/dma/at_hdmac.c      |   48 ++++++++++++++++++++++++++++++++++---------
 drivers/dma/at_hdmac_regs.h |    8 +++++++
 2 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index fcfa0a8..d1869c5 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -1175,6 +1175,18 @@ static void atc_free_chan_resources(struct dma_chan *chan)
 
 /*--  Module Management  -----------------------------------------------*/
 
+static struct platform_device_id atdma_devtypes[] = {
+	{
+		.name = "at91sam9rl_dma",
+		.driver_data = ATDMA_DEVTYPE_SAM9RL,
+	}, {
+		.name = "at91sam9g45_dma",
+		.driver_data = ATDMA_DEVTYPE_SAM9G45,
+	}, {
+		/* sentinel */
+	}
+};
+
 /**
  * at_dma_off - disable DMA controller
  * @atdma: the Atmel HDAMC device
@@ -1193,18 +1205,32 @@ static void at_dma_off(struct at_dma *atdma)
 
 static int __init at_dma_probe(struct platform_device *pdev)
 {
-	struct at_dma_platform_data *pdata;
 	struct resource		*io;
 	struct at_dma		*atdma;
 	size_t			size;
 	int			irq;
 	int			err;
 	int			i;
+	u32                     nr_channels;
+	dma_cap_mask_t          cap_mask = {};
+	enum atdma_devtype	atdmatype;
+
+	dma_cap_set(DMA_MEMCPY, cap_mask);
+
+	/* get DMA parameters from controller type */
+	atdmatype = platform_get_device_id(pdev)->driver_data;
 
-	/* get DMA Controller parameters from platform */
-	pdata = pdev->dev.platform_data;
-	if (!pdata || pdata->nr_channels > AT_DMA_MAX_NR_CHANNELS)
+	switch (atdmatype) {
+	case ATDMA_DEVTYPE_SAM9RL:
+		nr_channels = 2;
+		break;
+	case ATDMA_DEVTYPE_SAM9G45:
+		nr_channels = 8;
+		dma_cap_set(DMA_SLAVE, cap_mask);
+		break;
+	default:
 		return -EINVAL;
+	}
 
 	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!io)
@@ -1215,14 +1241,15 @@ static int __init at_dma_probe(struct platform_device *pdev)
 		return irq;
 
 	size = sizeof(struct at_dma);
-	size += pdata->nr_channels * sizeof(struct at_dma_chan);
+	size += nr_channels * sizeof(struct at_dma_chan);
 	atdma = kzalloc(size, GFP_KERNEL);
 	if (!atdma)
 		return -ENOMEM;
 
-	/* discover transaction capabilites from the platform data */
-	atdma->dma_common.cap_mask = pdata->cap_mask;
-	atdma->all_chan_mask = (1 << pdata->nr_channels) - 1;
+	/* discover transaction capabilities */
+	atdma->dma_common.cap_mask = cap_mask;
+	atdma->all_chan_mask = (1 << nr_channels) - 1;
+	atdma->devtype = atdmatype;
 
 	size = resource_size(io);
 	if (!request_mem_region(io->start, size, pdev->dev.driver->name)) {
@@ -1268,7 +1295,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
 
 	/* initialize channels related values */
 	INIT_LIST_HEAD(&atdma->dma_common.channels);
-	for (i = 0; i < pdata->nr_channels; i++) {
+	for (i = 0; i < nr_channels; i++) {
 		struct at_dma_chan	*atchan = &atdma->chan[i];
 
 		atchan->chan_common.device = &atdma->dma_common;
@@ -1313,7 +1340,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
 	dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n",
 	  dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "",
 	  dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)  ? "slave " : "",
-	  pdata->nr_channels);
+	  nr_channels);
 
 	dma_async_device_register(&atdma->dma_common);
 
@@ -1495,6 +1522,7 @@ static const struct dev_pm_ops at_dma_dev_pm_ops = {
 static struct platform_driver at_dma_driver = {
 	.remove		= __exit_p(at_dma_remove),
 	.shutdown	= at_dma_shutdown,
+	.id_table	= atdma_devtypes,
 	.driver = {
 		.name	= "at_hdmac",
 		.pm	= &at_dma_dev_pm_ops,
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index aa4c9ae..d7d6737 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -248,9 +248,16 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
 
 /*--  Controller  ------------------------------------------------------*/
 
+enum atdma_devtype {
+	ATDMA_DEVTYPE_UNDEFINED = 0,
+	ATDMA_DEVTYPE_SAM9RL,	/* compatible with SAM9RL DMA controller */
+	ATDMA_DEVTYPE_SAM9G45,	/* compatible with SAM9G45 DMA controller */
+};
+
 /**
  * struct at_dma - internal representation of an Atmel HDMA Controller
  * @chan_common: common dmaengine dma_device object members
+ * @atdma_devtype: identifier of DMA controller compatibility
  * @ch_regs: memory mapped register base
  * @clk: dma controller clock
  * @save_imr: interrupt mask register that is saved on suspend/resume cycle
@@ -260,6 +267,7 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
  */
 struct at_dma {
 	struct dma_device	dma_common;
+	enum atdma_devtype	devtype;
 	void __iomem		*regs;
 	struct clk		*clk;
 	u32			save_imr;
-- 
1.7.5.4

^ permalink raw reply related


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