Skip to contentSkip to conversation

enable devicetree on arch-mmp

PATCH New Haojian Zhuang 5 participants 27 messages Jul 28, 2011 – Aug 1, 2011

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

v2 cover enable devicetree on arch-mmp

Changelog
v2:
* parse timer from DT
* remove CONFIG_MMP_USE_OF
* set NR_IRQS to 0 since sparse irq is enabled and allocated irq is started from NR_IRQS.
* change property names according to comments
* parse serial from DT and only use drivers/tty/serial/pxa.c. Avoid to touch drivers/tty/serial/of_serial.c

#1 lore raw

PATCH v2 1/7 ARM: mmp: parse irq from DT

Parse irq sepcifier from DT and translate it to Linux irq number. Remove the definition of NR_IRQS in irqs.h. Since sparse irq is enabled, nr_irqs will be calculated automatically.

---
 .../devicetree/bindings/arm/marvell/intc.txt       |  114 ++++++++++
 arch/arm/Kconfig                                   |    1 +
 arch/arm/mach-mmp/Makefile                         |    2 +
 arch/arm/mach-mmp/common.h                         |    1 +
 arch/arm/mach-mmp/include/mach/irqs.h              |    2 +-
 arch/arm/mach-mmp/intc.c                           |  224 ++++++++++++++++++++
 6 files changed, 343 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/marvell/intc.txt
 create mode 100644 arch/arm/mach-mmp/intc.c
Documentation/devicetree/bindings/arm/marvell/intc.txt new file +114 -0
new file mode 100644
index 0000000..80cef58
@@ -0,0 +1,114 @@
+* Interrupt Controller Binding for ARCH-MMP
+
+This binding specifies what properties must be available in device tree representation of an ARCH-MMP compliant interrupt controller.
+
+Required properties:
+
+	- compatible: Specifies the compatibility list of the interrupt
+	  controller. The type shall be <string> and the value shall be
+	  "mrvl,pxa168-intc" or "mrvl,mmp2-mux-intc".
+	  "mrvl,pxa168-intc" is the base interrupt controller. It must be
+	  included. It's compatible for pxa910, mmp2. "mrvl,mmp2-mux-intc"
+	  is the expanded interrupt controller, and it's optional.
+
+	- reg: Specified the base physical address(s) and size(s) of the
+	  interrupt controller's addressable register space. The type
+	  should be <prop-encoded-array>.
+
+	- interrupt-controller: The presence of this property identifies
+	  the node as interrupt controller. No property value should be
+	  defined.
+
+	- #interrupt-cells: Specifies the number of cells needed to encode
+	  an interrupt source. The type should be <u32> and the value should
+	  be 1.
+
+	- mrvl,intc-numbers: Specifies the number of interrupts is supported
+	  in this interrupt controller. The type should be <u32>.
+
+Optional properties:
+
+	- mrvl,intc-priority: Specifies the which path the interrupt is routed
+	  and the priority of this interrupt. The property is used in
+	  pxa168-intc. The value should be <u32>.
+
+	- mrvl,status-offset: Specifies the offset of status register. The
+	  property is used in mmp2-mux-intc. The type should be <u32>.
+
+	- mrvl,mask-offset: Specifies the offset of mask register. The
+	  property is used in mmp2-mux-intc. The type should be <u32>.
+
+	- mrvl,mfp-edge: Specifies the address of mfp edge detection register.
+	  The property is used while acking specified interrupt. The type
+	  should be <prop-encoded-array>. The first cell indicates the address
+	  of mfp edge detection register. The second cell indicates the
+	  index of interrupt in current interrupt controller that should
+	  handle mfp edge detection.
+
+* Examples
+
+Example 1:
+
+	/*
+	 * base INTC
+	 */
+	mmp_intc: interrupt-controller at d4282000 {
+		/* Compatible with pxa168-intc. */
+		compatible = "mrvl,pxa168-intc";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		/* Offset address of 0xd4282000 and size of 0x400. */
+		reg = <0xd4282000 0x400>;
+
+		#interrupt-cells = <1>;
+		interrupt-controller;
+
+		/* 64 interrupts are supported in this INTC. */
+		mrvl,intc-numbers = <64>;
+
+		/* priority bits in configuration register */
+		mrvl,intc-priority = <0x20>;
+	};
+
+Example 2:
+
+	/*
+	 * mux INTC that is internal wired to base INTC
+	 */
+	mux_intc4: interrupt-controller at d4282150 {
+		compatible = "mrvl,mmp2-mux-intc";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xd4282000 0x400>;
+
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&mmp_intc>;
+
+		/* interrupt source '4' of parent INTC. */
+		interrupts = <4>;
+
+		/* 2 interrupts are supported in this INTC. */
+		mrvl,intc-numbers = <2>;
+
+		/* Status offset address of 0x150. */
+		mrvl,status-offset = <0x150>;
+
+		/* Mask offset address of 0x168. */
+		mrvl,mask-offset = <0x168>;
+
+		/* mfp register of 0xd401e2c4 & interrupt index of 1 */
+		mrvl,mfp-edge = <0xd401e2c4 1>;
+	};
+
+Example 3:
+	/*
+	 * An interrupt generating device that is wired to an INTC.
+	 */
+	uart0: uart at d4030000 {
+		/* parent's '#interrupt-cells' property. */
+		interrupts = <27>;
+
+		/* The INTC that this device is wired to. */
+		interrupt-parent = <&mmp_intc>;
+	};
arch/arm/Kconfig +1 -0
index 17507b8..f18eb14 100644
@@ -542,6 +542,7 @@ config ARCH_MMP
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
+	select GENERIC_IRQ_CHIP
 	select HAVE_SCHED_CLOCK
 	select TICK_ONESHOT
 	select PLAT_PXA
arch/arm/mach-mmp/Makefile +2 -0
index 5c68382..e7862ea 100644
@@ -4,6 +4,8 @@
 
 obj-y				+= common.o clock.o devices.o time.o
 
+obj-$(CONFIG_OF_IRQ)		+= intc.o
+
 # SoC support
 obj-$(CONFIG_CPU_PXA168)	+= pxa168.o irq-pxa168.o
 obj-$(CONFIG_CPU_PXA910)	+= pxa910.o irq-pxa168.o
arch/arm/mach-mmp/common.h +1 -0
index ec8d65d..1c563c2 100644
@@ -6,3 +6,4 @@ extern void timer_init(int irq);
 
 extern void __init icu_init_irq(void);
 extern void __init mmp_map_io(void);
+extern void __init mmp_init_intc(void);
arch/arm/mach-mmp/include/mach/irqs.h +1 -1
index a09d328..65ec176 100644
@@ -224,6 +224,6 @@
 
 #define IRQ_BOARD_START			(IRQ_GPIO_START + IRQ_GPIO_NUM)
 
-#define NR_IRQS				(IRQ_BOARD_START)
+#define NR_IRQS				0
 
 #endif /* __ASM_MACH_IRQS_H */
arch/arm/mach-mmp/intc.c new file +224 -0

224 lines not on this page · raw message

Signature · 1 line
1.5.6.5
#2 lore raw

PATCH v2 2/7 ARM: mmp: parse timer configuration from DT

Parse timer configuration from DT. Now we can merge pxa910_timer and mmp2_timer into mmp_timer. Since most configuration between these two timers are same. The difference is recorded in DT.

---
 .../devicetree/bindings/arm/marvell/timer.txt      |   24 +++++++++
 arch/arm/mach-mmp/common.h                         |    2 +
 arch/arm/mach-mmp/time.c                           |   50 +++++++++++++++++++-
 3 files changed, 75 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/marvell/timer.txt
Documentation/devicetree/bindings/arm/marvell/timer.txt new file +24 -0
new file mode 100644
index 0000000..24a6f97
@@ -0,0 +1,24 @@
+* Timer Controller Binding for ARCH-MMP
+
+This binding specifies what properties must be available in device tree
+representation of an ARCH-MMP compliant timer controller.
+
+Required properties:
+
+	- compatible: Specifies the compatibility list of the timer controller.
+	  The type shall be <string> and the value shall be
+	  "mrvl,pxa168-timer".
+
+	- mrvl,clk-conf: Specifies the address and value of timer 
+	  configuration register.
+	  The type shall be <prop-encoded-array>. The first value indicates
+	  the physical address of timer configuration register. The second
+	  value indicates data should be written to timer configuration
+	  register.
+
+* Example
+
+	mmp_timer: {
+		compatible = "mrvl,pxa168-timer";
+		mrvl,clk-conf = <0xd4000034 0x33>;
+	};
arch/arm/mach-mmp/common.h +2 -0
index 1c563c2..890c664 100644
@@ -2,6 +2,8 @@
 
 struct sys_timer;
 
+extern struct sys_timer mmp_timer;
+
 extern void timer_init(int irq);
 
 extern void __init icu_init_irq(void);
arch/arm/mach-mmp/time.c +49 -1

65 lines not on this page · raw message

Signature · 1 line
1.5.6.5
#3 lore raw

PATCH v2 3/7 ARM: mmp: support DT on both dkb and brownstone

Add new boards.c to support both TTC-DKB and MMP2-BROWNSTONE. If CONFIG_OF isn't selected, we continue to use original ttc_dkb.c and brownstone.c.

While everything moving to DT in ARCH-MMP, ttc_dkb.c and brownstone.c will be abandoned.

---
 .../devicetree/bindings/arm/marvell/boards.txt     |    7 +
 arch/arm/boot/dts/mmp2-brownstone.dts              |  216 ++++++++++++++++++++
 arch/arm/boot/dts/pxa910-dkb.dts                   |   81 ++++++++
 arch/arm/mach-mmp/Makefile                         |    1 +
 arch/arm/mach-mmp/boards.c                         |  138 +++++++++++++
 5 files changed, 443 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/marvell/boards.txt
 create mode 100644 arch/arm/boot/dts/mmp2-brownstone.dts
 create mode 100644 arch/arm/boot/dts/pxa910-dkb.dts
 create mode 100644 arch/arm/mach-mmp/boards.c
Documentation/devicetree/bindings/arm/marvell/boards.txt new file +7 -0
new file mode 100644
index 0000000..a031a26
@@ -0,0 +1,7 @@
+TTC(pxa910) "DKB" evalutation board
+Required root node properties:
+	- compatible = "mrvl,pxa910-dkb", "mrvl,pxa910";
+
+mmp2(armada610) "Brownstone" evalutation board
+Required root node properties:
+	- compatible = "mrvl,mmp2-brownstone", "mrvl,mmp2";
arch/arm/boot/dts/mmp2-brownstone.dts new file +216 -0

216 lines not on this page · raw message

arch/arm/boot/dts/pxa910-dkb.dts new file +81 -0

81 lines not on this page · raw message

arch/arm/mach-mmp/Makefile +1 -0
index e7862ea..bdf5b23 100644
@@ -12,6 +12,7 @@ obj-$(CONFIG_CPU_PXA910)	+= pxa910.o irq-pxa168.o
 obj-$(CONFIG_CPU_MMP2)		+= mmp2.o irq-mmp2.o
 
 # board support
+obj-$(CONFIG_OF)		+= boards.o
 obj-$(CONFIG_MACH_ASPENITE)	+= aspenite.o
 obj-$(CONFIG_MACH_ZYLONITE2)	+= aspenite.o
 obj-$(CONFIG_MACH_AVENGERS_LITE)+= avengers_lite.o
arch/arm/mach-mmp/boards.c new file +138 -0

138 lines not on this page · raw message

Signature · 1 line
1.5.6.5
#4 lore raw

PATCH v2 4/7 tty: serial: support device tree in pxa

Support both normal platform driver and device tree driver in serial pxa.

---
 drivers/tty/serial/pxa.c |   51 ++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 45 insertions(+), 6 deletions(-)
drivers/tty/serial/pxa.c +45 -6
index 4302e6e..dadd201 100644
@@ -36,6 +36,7 @@
 #include <linux/circ_buf.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
@@ -54,6 +55,8 @@ struct uart_pxa_port {
 	char			*name;
 };
 
+#define PXA_SERIAL_NR		4
+
 static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
 {
 	offset <<= 2;
@@ -593,7 +596,7 @@ serial_pxa_type(struct uart_port *port)
 	return up->name;
 }
 
-static struct uart_pxa_port *serial_pxa_ports[4];
+static struct uart_pxa_port *serial_pxa_ports[PXA_SERIAL_NR];
 static struct uart_driver serial_pxa_reg;
 
 #ifdef CONFIG_SERIAL_PXA_CONSOLE
@@ -765,7 +768,10 @@ static int serial_pxa_probe(struct platform_device *dev)
 {
 	struct uart_pxa_port *sport;
 	struct resource *mmres, *irqres;
-	int ret;
+	struct device_node *np = dev->dev.of_node;
+	char name[32];
+	unsigned int clk = 0, spd = 0;
+	int ret, i;
 
 	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
 	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
@@ -776,11 +782,39 @@ static int serial_pxa_probe(struct platform_device *dev)
 	if (!sport)
 		return -ENOMEM;
 
+#ifdef CONFIG_OF
+	for (i = 0; i < PXA_SERIAL_NR; i++) {
+		if (serial_pxa_ports[i] == NULL)
+			break;
+	}
+	if (i >= PXA_SERIAL_NR) {
+		pr_warn("can't find pxa serial port\n");
+		return -ENODEV;
+	}
+
+	if (of_property_read_u32(np, "clock-frequency", &clk)) {
+		pr_warn("no clock-frequency property set\n");
+		return -ENODEV;
+	}
+	if (of_property_read_u32(np, "current-speed", &spd) == 0)
+		sport->port.custom_divisor = clk / (16 * spd);
+
+	sprintf(name, "pxa2xx-uart.%d", i);
+	sport->clk = clk_get_sys(name, NULL);
+	if (IS_ERR(sport->clk)) {
+		ret = PTR_ERR(sport->clk);
+		goto err_free;
+	}
+	sport->port.uartclk = clk;
+#else
+	i = dev->id;
 	sport->clk = clk_get(&dev->dev, NULL);
 	if (IS_ERR(sport->clk)) {
 		ret = PTR_ERR(sport->clk);
 		goto err_free;
 	}
+	sport->port.uartclk = clk_get_rate(sport->clk);
+#endif
 
 	sport->port.type = PORT_PXA;
 	sport->port.iotype = UPIO_MEM;
@@ -788,12 +822,11 @@ static int serial_pxa_probe(struct platform_device *dev)
 	sport->port.irq = irqres->start;
 	sport->port.fifosize = 64;
 	sport->port.ops = &serial_pxa_pops;
-	sport->port.line = dev->id;
+	sport->port.line = i;
 	sport->port.dev = &dev->dev;
 	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
 
-	switch (dev->id) {
+	switch (i) {
 	case 0: sport->name = "FFUART"; break;
 	case 1: sport->name = "BTUART"; break;
 	case 2: sport->name = "STUART"; break;
@@ -809,7 +842,7 @@ static int serial_pxa_probe(struct platform_device *dev)
 		goto err_clk;
 	}
 
-	serial_pxa_ports[dev->id] = sport;
+	serial_pxa_ports[i] = sport;
 
 	uart_add_one_port(&serial_pxa_reg, &sport->port);
 	platform_set_drvdata(dev, sport);
@@ -836,6 +869,11 @@ static int serial_pxa_remove(struct platform_device *dev)
 	return 0;
 }
 
+static struct of_device_id __devinitdata of_serial_pxa_table[] = {
+	{ .compatible = "mrvl,pxa270-serial", .data = (void *)PORT_PXA, },
+	{},
+};
+
 static struct platform_driver serial_pxa_driver = {
         .probe          = serial_pxa_probe,
         .remove         = serial_pxa_remove,
@@ -843,6 +881,7 @@ static struct platform_driver serial_pxa_driver = {
 	.driver		= {
 	        .name	= "pxa2xx-uart",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_serial_pxa_table,
 #ifdef CONFIG_PM
 		.pm	= &serial_pxa_pm_ops,
 #endif
Signature · 1 line
1.5.6.5
#5 lore raw

PATCH v2 5/7 tty: serial: check ops before registering console

Console should be only registered after port->ops assigned. If uart console doesn't match the current uart, port->ops keeps NULL.

---
 drivers/tty/serial/pxa.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/tty/serial/pxa.c +1 -1
index dadd201..3201a95 100644
@@ -683,7 +683,7 @@ serial_pxa_console_setup(struct console *co, char *options)
 	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
 		co->index = 0;
 	up = serial_pxa_ports[co->index];
-	if (!up)
+	if (!up || !up->port.ops)
 		return -ENODEV;
 
 	if (options)
Signature · 1 line
1.5.6.5
#6 lore raw

PATCH v2 6/7 i2c: pxa: support i2c controller from DT

support i2c-pxa controller from DT.

---
 drivers/i2c/busses/i2c-pxa.c |   51 +++++++++++++++++++++++++++++++----------
 1 files changed, 38 insertions(+), 13 deletions(-)
drivers/i2c/busses/i2c-pxa.c +38 -13
index d603646..8c27733 100644
@@ -29,6 +29,7 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/i2c-pxa.h>
+#include <linux/of_device.h>
 #include <linux/of_i2c.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
@@ -1044,15 +1045,31 @@ static const struct i2c_algorithm i2c_pxa_pio_algorithm = {
 	.functionality	= i2c_pxa_functionality,
 };
 
+static const struct of_device_id pxa_i2c_of_match[] = {
+	{ .compatible = "mrvl,pxa255-i2c",    .data = (void *)REGS_PXA2XX, },
+	{ .compatible = "mrvl,pxa300-pwri2c", .data = (void *)REGS_PXA3XX, },
+	{},
+};
+
 static int i2c_pxa_probe(struct platform_device *dev)
 {
+	struct device_node *np = dev->dev.of_node;
+	const struct of_device_id *match;
 	struct pxa_i2c *i2c;
-	struct resource *res;
 	struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
 	const struct platform_device_id *id = platform_get_device_id(dev);
-	enum pxa_i2c_types i2c_type = id->driver_data;
-	int ret;
-	int irq;
+	enum pxa_i2c_types i2c_type;
+	struct resource *res;
+	int irq, ret;
+	static int idx = 0;
+
+	if (np) {
+		match = of_match_device(pxa_i2c_of_match, &dev->dev);
+		if (match == NULL)
+			return -ENODEV;
+		i2c_type = (int)match->data;
+	} else
+		i2c_type = id->driver_data;
 
 	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
 	irq = platform_get_irq(dev, 0);
@@ -1074,16 +1091,23 @@ static int i2c_pxa_probe(struct platform_device *dev)
 	spin_lock_init(&i2c->lock);
 	init_waitqueue_head(&i2c->wait);
 
-	/*
-	 * If "dev->id" is negative we consider it as zero.
-	 * The reason to do so is to avoid sysfs names that only make
-	 * sense when there are multiple adapters.
-	 */
-	i2c->adap.nr = dev->id;
-	snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u",
-		 i2c->adap.nr);
 
-	i2c->clk = clk_get(&dev->dev, NULL);
+	if (np) {
+		i2c->adap.nr = idx++;
+		snprintf(i2c->adap.name, sizeof(i2c->adap.name),
+			"pxa2xx-i2c.%u", i2c->adap.nr);
+		i2c->clk = clk_get_sys(i2c->adap.name, NULL);
+	} else {
+		/*
+		 * If "dev->id" is negative we consider it as zero.
+		 * The reason to do so is to avoid sysfs names that only make
+		 * sense when there are multiple adapters.
+		 */
+		i2c->adap.nr = dev->id;
+		snprintf(i2c->adap.name, sizeof(i2c->adap.name),
+			"pxa_i2c-i2c.%u", i2c->adap.nr);
+		i2c->clk = clk_get(&dev->dev, NULL);
+	}
 	if (IS_ERR(i2c->clk)) {
 		ret = PTR_ERR(i2c->clk);
 		goto eclk;
@@ -1234,6 +1258,7 @@ static struct platform_driver i2c_pxa_driver = {
 		.name	= "pxa2xx-i2c",
 		.owner	= THIS_MODULE,
 		.pm	= I2C_PXA_DEV_PM_OPS,
+		.of_match_table	= pxa_i2c_of_match,
 	},
 	.id_table	= i2c_pxa_id_table,
 };
Signature · 1 line
1.5.6.5
#7 lore raw

PATCH v2 7/7 i2c: pxa: support to parse property

Support to parse some optional properties. These three properties are mrvl,use-polling, mrvl,i2c-frequency, mrvl,i2c-class.

After supporting these property, i2c-pxa driver can avoid to use platform data except for slave mode.

---
 .../devicetree/bindings/i2c/pxa255-i2c.txt         |   38 ++++++++++++++++++++
 drivers/i2c/busses/i2c-pxa.c                       |   20 +++++++---
 2 files changed, 52 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/i2c/pxa255-i2c.txt
Documentation/devicetree/bindings/i2c/pxa255-i2c.txt new file +38 -0
new file mode 100644
index 0000000..4b5afae
@@ -0,0 +1,38 @@
+PXA255 I2C
+
+The I2C-Controller is first used in PXA255. It's widely used in Intel/Marvell
+silicons.
+
+Optional Property:
+	- mrvl,use-polling: Specifies whether I2C-Controller is used in polling
+	  mode or interrupt mode. The type of property should be <empty>.
+
+	- mrvl,i2c-frequency: Specifies the frequency that the I2C-Controller
+	  is working. It indicates I2C-Controller running in standard(100Kb/s)
+	  or fast(400Kb/s) speed.
+	  The type of property should be <string>. The value should be "fast".
+
+	- mrvl,i2c-class: Specifies the adaptor class of I2C-Controller, such as
+	  hwmon or ddc bus. The type of property should be <u32>.
+
+Example:
+	i2c0: i2c at d4011000 {
+		compatible = "pxa2xx-i2c";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0xd4011000 0x60>;
+		/* I2C-Controller works in polling mode. */
+		mrvl,use-polling;
+		/* I2C-Controller's frequency is FAST. */
+		mrvl,i2c-frequency = "fast";
+		/* interrupt of I2C-Controller */
+		interrupts = <7>;
+		interrupt-parent = <&mmp_intc>;
+
+		pm860x: pmic at 34 {
+			interrupt-controller;
+			/* interrupt of pm860x */
+			interrupts = <4>;
+			interrupt-parent = <&mmp_intc>;
+		};
+	};
drivers/i2c/busses/i2c-pxa.c +14 -6
index 8c27733..cebcd26 100644
@@ -1061,6 +1061,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
 	enum pxa_i2c_types i2c_type;
 	struct resource *res;
 	int irq, ret;
+	char *p = NULL;
 	static int idx = 0;
 
 	if (np) {
@@ -1093,11 +1094,24 @@ static int i2c_pxa_probe(struct platform_device *dev)
 
 
 	if (np) {
+		if (of_get_property(np, "mrvl,use-polling", NULL))
+			i2c->use_pio = 1;
+		of_property_read_string(np, "mrvl,i2c-frequency", &p);
+		if (p && !strncmp(p, "fast", 4))
+			i2c->fast_mode = 1;
+		of_property_read_u32(np, "mrvl,i2c-class", &i2c->adap.class);
+
 		i2c->adap.nr = idx++;
 		snprintf(i2c->adap.name, sizeof(i2c->adap.name),
 			"pxa2xx-i2c.%u", i2c->adap.nr);
 		i2c->clk = clk_get_sys(i2c->adap.name, NULL);
 	} else {
+		if (plat) {
+			i2c->adap.class = plat->class;
+			i2c->use_pio = plat->use_pio;
+			i2c->fast_mode = plat->fast_mode;
+		}
+
 		/*
 		 * If "dev->id" is negative we consider it as zero.
 		 * The reason to do so is to avoid sysfs names that only make
@@ -1142,12 +1156,6 @@ static int i2c_pxa_probe(struct platform_device *dev)
 
 	clk_enable(i2c->clk);
 
-	if (plat) {
-		i2c->adap.class = plat->class;
-		i2c->use_pio = plat->use_pio;
-		i2c->fast_mode = plat->fast_mode;
-	}
-
 	if (i2c->use_pio) {
 		i2c->adap.algo = &i2c_pxa_pio_algorithm;
 	} else {
Signature · 1 line
1.5.6.5
#8 lore raw

PATCH v2 6/7 i2c: pxa: support i2c controller from DT

In reply to Haojian Zhuang
Quoted 61 lines · Haojian Zhuang

support i2c-pxa controller from DT.

---
 drivers/i2c/busses/i2c-pxa.c |   51 +++++++++++++++++++++++++++++++----------
 1 files changed, 38 insertions(+), 13 deletions(-)
drivers/i2c/busses/i2c-pxa.c +21 -6
index d603646..8c27733 100644
@@ -29,6 +29,7 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/i2c-pxa.h>
+#include <linux/of_device.h>
 #include <linux/of_i2c.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
@@ -1044,15 +1045,31 @@ static const struct i2c_algorithm i2c_pxa_pio_algorithm = {
 	.functionality	= i2c_pxa_functionality,
 };
 
+static const struct of_device_id pxa_i2c_of_match[] = {
+	{ .compatible = "mrvl,pxa255-i2c",    .data = (void *)REGS_PXA2XX, },
+	{ .compatible = "mrvl,pxa300-pwri2c", .data = (void *)REGS_PXA3XX, },
+	{},
+};
+
 static int i2c_pxa_probe(struct platform_device *dev)
 {
+	struct device_node *np = dev->dev.of_node;
+	const struct of_device_id *match;
 	struct pxa_i2c *i2c;
-	struct resource *res;
 	struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
 	const struct platform_device_id *id = platform_get_device_id(dev);
-	enum pxa_i2c_types i2c_type = id->driver_data;
-	int ret;
-	int irq;
+	enum pxa_i2c_types i2c_type;
+	struct resource *res;
+	int irq, ret;
+	static int idx = 0;
+
+	if (np) {
+		match = of_match_device(pxa_i2c_of_match, &dev->dev);
+		if (match == NULL)
+			return -ENODEV;
+		i2c_type = (int)match->data;
+	} else
+		i2c_type = id->driver_data;
 
 	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
 	irq = platform_get_irq(dev, 0);
@@ -1074,16 +1091,23 @@ static int i2c_pxa_probe(struct platform_device *dev)
 	spin_lock_init(&i2c->lock);
 	init_waitqueue_head(&i2c->wait);
 
-	/*
-	 * If "dev->id" is negative we consider it as zero.

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_probe(struct platform_device *dev) · line 1096

Quoted 10 lines
drivers/i2c/busses/i2c-pxa.c +2 -7
-	 * The reason to do so is to avoid sysfs names that only make
-	 * sense when there are multiple adapters.
-	 */
-	i2c->adap.nr = dev->id;
-	snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u",
-		 i2c->adap.nr);
 
-	i2c->clk = clk_get(&dev->dev, NULL);
+	if (np) {
+		i2c->adap.nr = idx++;

Use this so that a bus number gets dynamically assigned:

		i2c->adap.nr = -1;

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_probe(struct platform_device *dev) · line 1099

Quoted 3 lines
drivers/i2c/busses/i2c-pxa.c +3 -0
+		snprintf(i2c->adap.name, sizeof(i2c->adap.name),
+			"pxa2xx-i2c.%u", i2c->adap.nr);
+		i2c->clk = clk_get_sys(i2c->adap.name, NULL);

Missing i2c->adap.dev.of_node = dev->dev.of_node;

and after the bus is registered:

of_i2c_register_devices(&i2c->adap);

Quoted 25 lines
drivers/i2c/busses/i2c-pxa.c +12 -0
+	} else {
+		/*
+		 * If "dev->id" is negative we consider it as zero.
+		 * The reason to do so is to avoid sysfs names that only make
+		 * sense when there are multiple adapters.
+		 */
+		i2c->adap.nr = dev->id;
+		snprintf(i2c->adap.name, sizeof(i2c->adap.name),
+			"pxa_i2c-i2c.%u", i2c->adap.nr);
+		i2c->clk = clk_get(&dev->dev, NULL);
+	}
 	if (IS_ERR(i2c->clk)) {
 		ret = PTR_ERR(i2c->clk);
 		goto eclk;
@@ -1234,6 +1258,7 @@ static struct platform_driver i2c_pxa_driver = {
 		.name	= "pxa2xx-i2c",
 		.owner	= THIS_MODULE,
 		.pm	= I2C_PXA_DEV_PM_OPS,
+		.of_match_table	= pxa_i2c_of_match,
 	},
 	.id_table	= i2c_pxa_id_table,
 };
Signature · 1 line
1.5.6.5
#9 lore raw

PATCH v2 6/7 i2c: pxa: support i2c controller from DT

Quoted 15 lines · Grant Likely

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_probe(struct platform_device *dev) · line 1096

Quoted 12 lines · Haojian Zhuang
drivers/i2c/busses/i2c-pxa.c +2 -9
-	/*
-	 * If "dev->id" is negative we consider it as zero.
-	 * The reason to do so is to avoid sysfs names that only make
-	 * sense when there are multiple adapters.
-	 */
-	i2c->adap.nr = dev->id;
-	snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u",
-		 i2c->adap.nr);
 
-	i2c->clk = clk_get(&dev->dev, NULL);
+	if (np) {
+		i2c->adap.nr = idx++;

Use this so that a bus number gets dynamically assigned:

Quoted 7 lines
		i2c->adap.nr = -1;

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_probe(struct platform_device *dev) · line 1099

Quoted 3 lines
drivers/i2c/busses/i2c-pxa.c +3 -0
+		snprintf(i2c->adap.name, sizeof(i2c->adap.name),
+			"pxa2xx-i2c.%u", i2c->adap.nr);
+		i2c->clk = clk_get_sys(i2c->adap.name, NULL);

Missing i2c->adap.dev.of_node = dev->dev.of_node;

And here we go again. Is it really the case that this DT stuff doesn't have stable device names?

#10 lore raw

PATCH v2 6/7 i2c: pxa: support i2c controller from DT

Quoted 18 lines · Russell King - ARM Linux
Quoted 17 lines · Grant Likely

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_probe(struct platform_device *dev) · line 1096

Quoted 12 lines · Haojian Zhuang
drivers/i2c/busses/i2c-pxa.c +2 -9
-	/*
-	 * If "dev->id" is negative we consider it as zero.
-	 * The reason to do so is to avoid sysfs names that only make
-	 * sense when there are multiple adapters.
-	 */
-	i2c->adap.nr = dev->id;
-	snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u",
-		 i2c->adap.nr);
 
-	i2c->clk = clk_get(&dev->dev, NULL);
+	if (np) {
+		i2c->adap.nr = idx++;

Use this so that a bus number gets dynamically assigned:

		i2c->adap.nr = -1;
Quoted 8 lines
Quoted 5 lines

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_probe(struct platform_device *dev) · line 1099

Quoted 3 lines
drivers/i2c/busses/i2c-pxa.c +3 -0
+		snprintf(i2c->adap.name, sizeof(i2c->adap.name),
+			"pxa2xx-i2c.%u", i2c->adap.nr);
+		i2c->clk = clk_get_sys(i2c->adap.name, NULL);

Missing i2c->adap.dev.of_node = dev->dev.of_node;

And here we go again. Is it really the case that this DT stuff doesn't have stable device names?

Device tree names are completely stable, based on hardware addresses that don't change from boot to boot. Even for buses where access addresses are dynamically assigned, the device tree "reg property" address is based on a stable addressing form. For example, PCI devices use the (stable) configuration address as the reg property and USB devices use the (stable) hub port number.

People's tendency to want to assign sequential small integers in Linux has nothing to do with the device tree. I suspect that it's a carryover from the historical Unix major/minor device numbering model, but in any case, there's nothing unstable about the device tree naming model. Quite the opposite - stable naming was a fundamental criterion when I designed Open Firmware.

Quoted 5 lines

_______________________________________________
devicetree-discuss mailing list
devicetree-discuss at lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss

#11 lore raw

PATCH v2 6/7 i2c: pxa: support i2c controller from DT

Quoted 35 lines · Mitch Bradley
Quoted 18 lines · Russell King - ARM Linux
Quoted 17 lines · Grant Likely

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_probe(struct platform_device *dev) · line 1096

Quoted 12 lines · Haojian Zhuang
drivers/i2c/busses/i2c-pxa.c +2 -9
-	/*
-	 * If "dev->id" is negative we consider it as zero.
-	 * The reason to do so is to avoid sysfs names that only make
-	 * sense when there are multiple adapters.
-	 */
-	i2c->adap.nr = dev->id;
-	snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u",
-		 i2c->adap.nr);
 
-	i2c->clk = clk_get(&dev->dev, NULL);
+	if (np) {
+		i2c->adap.nr = idx++;

Use this so that a bus number gets dynamically assigned:

		i2c->adap.nr = -1;
Quoted 8 lines
Quoted 5 lines

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_probe(struct platform_device *dev) · line 1099

Quoted 3 lines
drivers/i2c/busses/i2c-pxa.c +3 -0
+		snprintf(i2c->adap.name, sizeof(i2c->adap.name),
+			"pxa2xx-i2c.%u", i2c->adap.nr);
+		i2c->clk = clk_get_sys(i2c->adap.name, NULL);

Missing i2c->adap.dev.of_node = dev->dev.of_node;

And here we go again. Is it really the case that this DT stuff doesn't have stable device names?

Device tree names are completely stable, based on hardware addresses that don't change from boot to boot. Even for buses where access addresses are dynamically assigned, the device tree "reg property" address is based on a stable addressing form. For example, PCI devices use the (stable) configuration address as the reg property and USB devices use the (stable) hub port number.

Quoted 6 lines

People's tendency to want to assign sequential small integers in Linux has nothing to do with the device tree. I suspect that it's a carryover from the historical Unix major/minor device numbering model, but in any case, there's nothing unstable about the device tree naming model. Quite the opposite - stable naming was a fundamental criterion when I designed Open Firmware.

Which means - if Grant is accepting the conversion of ARM to DT and upstreaming it, he needs to keep an eye on this madness and reject stuff which tries to do as per this patch.

#12 lore raw

PATCH v2 6/7 i2c: pxa: support i2c controller from DT

Quoted 20 lines · Russell King - ARM Linux
Quoted 19 lines · Mitch Bradley
Quoted 18 lines · Russell King - ARM Linux
Quoted 17 lines · Grant Likely

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_probe(struct platform_device *dev) · line 1096

Quoted 12 lines · Haojian Zhuang
drivers/i2c/busses/i2c-pxa.c +2 -9
-	/*
-	 * If "dev->id" is negative we consider it as zero.
-	 * The reason to do so is to avoid sysfs names that only make
-	 * sense when there are multiple adapters.
-	 */
-	i2c->adap.nr = dev->id;
-	snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u",
-		 i2c->adap.nr);
 
-	i2c->clk = clk_get(&dev->dev, NULL);
+	if (np) {
+		i2c->adap.nr = idx++;

Use this so that a bus number gets dynamically assigned:

		i2c->adap.nr = -1;
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 5 lines

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_probe(struct platform_device *dev) · line 1099

Quoted 3 lines
drivers/i2c/busses/i2c-pxa.c +3 -0
+		snprintf(i2c->adap.name, sizeof(i2c->adap.name),
+			"pxa2xx-i2c.%u", i2c->adap.nr);
+		i2c->clk = clk_get_sys(i2c->adap.name, NULL);

Missing i2c->adap.dev.of_node = dev->dev.of_node;

And here we go again. Is it really the case that this DT stuff doesn't have stable device names?

The "full_name" is indeed stable for a device_node, so that isn't actually the problem, but the full_name is the entire path from the root of the tree to the device. The problem is that it is far too long for to be used as (struct device*)->kobj.name, and it has '/' characters in it which aren't particularly friendly. The short node name is unique among its siblings, but not globally.

Currently the kernel constructs a 'short' name when creating a device with a heuristic that tries to use the physical address of the device and the node name. If that isn't available (ie. non-memory mapped devices), then it uses a globally incremented integer to assign each device a unique name so that sysfs doesn't freak out.

See of_device_make_bus_id() in drivers/of/platform.c

The /real/ problem is that I don't much like the heuristic; but I haven't been able to think of anything better. There is enough uncertainty (very tiny, but uncertainty never the less) on device names, and the fact that I'm hoping to improve the method of creating device names, that I don't want to rely on them for matching up resources.

Instead, the dev_resdata array that is passed into of_platform_populate() has a field to override the heuristic generated name which neatly solves the problem entirely without tracking down all the references that need to be added, and has the added advantage of DT and non-DT platforms using the same names.

The clk_get() changes in this patch are absolutely the wrong solution.

Quoted 14 lines
Quoted 7 lines

Device tree names are completely stable, based on hardware addresses that don't change from boot to boot. Even for buses where access addresses are dynamically assigned, the device tree "reg property" address is based on a stable addressing form. For example, PCI devices use the (stable) configuration address as the reg property and USB devices use the (stable) hub port number.

Quoted 6 lines

People's tendency to want to assign sequential small integers in Linux has nothing to do with the device tree. I suspect that it's a carryover from the historical Unix major/minor device numbering model, but in any case, there's nothing unstable about the device tree naming model. Quite the opposite - stable naming was a fundamental criterion when I designed Open Firmware.

Quoted 3 lines

Which means - if Grant is accepting the conversion of ARM to DT and upstreaming it, he needs to keep an eye on this madness and reject stuff which tries to do as per this patch.

Correct, I will nack/reject any patches messing about with clock attachment or similar changes. I was distracted by the other issues, so I didn't comment on it in this patch.

g.

#13 lore raw

PATCH v2 4/7 tty: serial: support device tree in pxa

In reply to Haojian Zhuang
Quoted 76 lines · Haojian Zhuang

Support both normal platform driver and device tree driver in serial pxa.

---
 drivers/tty/serial/pxa.c |   51 ++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 45 insertions(+), 6 deletions(-)
drivers/tty/serial/pxa.c +31 -2
index 4302e6e..dadd201 100644
@@ -36,6 +36,7 @@
 #include <linux/circ_buf.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
@@ -54,6 +55,8 @@ struct uart_pxa_port {
 	char			*name;
 };
 
+#define PXA_SERIAL_NR		4
+
 static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
 {
 	offset <<= 2;
@@ -593,7 +596,7 @@ serial_pxa_type(struct uart_port *port)
 	return up->name;
 }
 
-static struct uart_pxa_port *serial_pxa_ports[4];
+static struct uart_pxa_port *serial_pxa_ports[PXA_SERIAL_NR];
 static struct uart_driver serial_pxa_reg;
 
 #ifdef CONFIG_SERIAL_PXA_CONSOLE
@@ -765,7 +768,10 @@ static int serial_pxa_probe(struct platform_device *dev)
 {
 	struct uart_pxa_port *sport;
 	struct resource *mmres, *irqres;
-	int ret;
+	struct device_node *np = dev->dev.of_node;
+	char name[32];
+	unsigned int clk = 0, spd = 0;
+	int ret, i;
 
 	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
 	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
@@ -776,11 +782,39 @@ static int serial_pxa_probe(struct platform_device *dev)
 	if (!sport)
 		return -ENOMEM;
 
+#ifdef CONFIG_OF
+	for (i = 0; i < PXA_SERIAL_NR; i++) {
+		if (serial_pxa_ports[i] == NULL)
+			break;
+	}
+	if (i >= PXA_SERIAL_NR) {
+		pr_warn("can't find pxa serial port\n");
+		return -ENODEV;
+	}
+
+	if (of_property_read_u32(np, "clock-frequency", &clk)) {
+		pr_warn("no clock-frequency property set\n");
+		return -ENODEV;
+	}
+	if (of_property_read_u32(np, "current-speed", &spd) == 0)
+		sport->port.custom_divisor = clk / (16 * spd);
+
+	sprintf(name, "pxa2xx-uart.%d", i);
+	sport->clk = clk_get_sys(name, NULL);
+	if (IS_ERR(sport->clk)) {
+		ret = PTR_ERR(sport->clk);
+		goto err_free;
+	}

drivers/tty/serial/pxa.c static int serial_pxa_probe(struct platform_device *dev) · line 817

Quoted 10 lines
drivers/tty/serial/pxa.c +5 -0
+	sport->port.uartclk = clk;
+#else
+	i = dev->id;
 	sport->clk = clk_get(&dev->dev, NULL);
 	if (IS_ERR(sport->clk)) {
 		ret = PTR_ERR(sport->clk);
 		goto err_free;
 	}
+	sport->port.uartclk = clk_get_rate(sport->clk);
+#endif

This means a kernel build can either support DT or non-DT, but not both. DT & non-DT booting are full supported with the same kernel image, so don't do it this way.

Instead, check for the presence of an of_node. If it is there, do the DT parsing. If now, still support the old method.

Quoted 50 lines
drivers/tty/serial/pxa.c +9 -4
 	sport->port.type = PORT_PXA;
 	sport->port.iotype = UPIO_MEM;
@@ -788,12 +822,11 @@ static int serial_pxa_probe(struct platform_device *dev)
 	sport->port.irq = irqres->start;
 	sport->port.fifosize = 64;
 	sport->port.ops = &serial_pxa_pops;
-	sport->port.line = dev->id;
+	sport->port.line = i;
 	sport->port.dev = &dev->dev;
 	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
-	sport->port.uartclk = clk_get_rate(sport->clk);
 
-	switch (dev->id) {
+	switch (i) {
 	case 0: sport->name = "FFUART"; break;
 	case 1: sport->name = "BTUART"; break;
 	case 2: sport->name = "STUART"; break;
@@ -809,7 +842,7 @@ static int serial_pxa_probe(struct platform_device *dev)
 		goto err_clk;
 	}
 
-	serial_pxa_ports[dev->id] = sport;
+	serial_pxa_ports[i] = sport;
 
 	uart_add_one_port(&serial_pxa_reg, &sport->port);
 	platform_set_drvdata(dev, sport);
@@ -836,6 +869,11 @@ static int serial_pxa_remove(struct platform_device *dev)
 	return 0;
 }
 
+static struct of_device_id __devinitdata of_serial_pxa_table[] = {
+	{ .compatible = "mrvl,pxa270-serial", .data = (void *)PORT_PXA, },
+	{},
+};
+
 static struct platform_driver serial_pxa_driver = {
         .probe          = serial_pxa_probe,
         .remove         = serial_pxa_remove,
@@ -843,6 +881,7 @@ static struct platform_driver serial_pxa_driver = {
 	.driver		= {
 	        .name	= "pxa2xx-uart",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_serial_pxa_table,
 #ifdef CONFIG_PM
 		.pm	= &serial_pxa_pm_ops,
 #endif
Signature · 1 line
1.5.6.5
#14 lore raw

PATCH v2 4/7 tty: serial: support device tree in pxa

Quoted 39 lines · Grant Likely
Quoted 23 lines · Haojian Zhuang
drivers/tty/serial/pxa.c +23 -0
+#ifdef CONFIG_OF
+	for (i = 0; i < PXA_SERIAL_NR; i++) {
+		if (serial_pxa_ports[i] == NULL)
+			break;
+	}
+	if (i >= PXA_SERIAL_NR) {
+		pr_warn("can't find pxa serial port\n");
+		return -ENODEV;
+	}
+
+	if (of_property_read_u32(np, "clock-frequency", &clk)) {
+		pr_warn("no clock-frequency property set\n");
+		return -ENODEV;
+	}
+	if (of_property_read_u32(np, "current-speed", &spd) == 0)
+		sport->port.custom_divisor = clk / (16 * spd);
+
+	sprintf(name, "pxa2xx-uart.%d", i);
+	sport->clk = clk_get_sys(name, NULL);
+	if (IS_ERR(sport->clk)) {
+		ret = PTR_ERR(sport->clk);
+		goto err_free;
+	}

drivers/tty/serial/pxa.c static int serial_pxa_probe(struct platform_device *dev) · line 817

Quoted 10 lines
drivers/tty/serial/pxa.c +5 -0
+	sport->port.uartclk = clk;
+#else
+	i = dev->id;
 	sport->clk = clk_get(&dev->dev, NULL);
 	if (IS_ERR(sport->clk)) {
 		ret = PTR_ERR(sport->clk);
 		goto err_free;
 	}
+	sport->port.uartclk = clk_get_rate(sport->clk);
+#endif

This means a kernel build can either support DT or non-DT, but not both. DT & non-DT booting are full supported with the same kernel image, so don't do it this way.

Quoted 2 lines

Instead, check for the presence of an of_node. If it is there, do the DT parsing. If now, still support the old method.

Oh ffs, why is this DT stuff causing all the clk stuff to have to change. And specifically why is stuff converting to use clk_get_sys().

clk_get_sys() is there to allow system devices to get their clocks. It's not for general drivers to use.

Please, stop this madness.

#15 lore raw

PATCH v2 4/7 tty: serial: support device tree in pxa

Quoted 43 lines · Russell King - ARM Linux
Quoted 39 lines · Grant Likely
Quoted 23 lines · Haojian Zhuang
drivers/tty/serial/pxa.c +23 -0
+#ifdef CONFIG_OF
+	for (i = 0; i < PXA_SERIAL_NR; i++) {
+		if (serial_pxa_ports[i] == NULL)
+			break;
+	}
+	if (i >= PXA_SERIAL_NR) {
+		pr_warn("can't find pxa serial port\n");
+		return -ENODEV;
+	}
+
+	if (of_property_read_u32(np, "clock-frequency", &clk)) {
+		pr_warn("no clock-frequency property set\n");
+		return -ENODEV;
+	}
+	if (of_property_read_u32(np, "current-speed", &spd) == 0)
+		sport->port.custom_divisor = clk / (16 * spd);
+
+	sprintf(name, "pxa2xx-uart.%d", i);
+	sport->clk = clk_get_sys(name, NULL);
+	if (IS_ERR(sport->clk)) {
+		ret = PTR_ERR(sport->clk);
+		goto err_free;
+	}

drivers/tty/serial/pxa.c static int serial_pxa_probe(struct platform_device *dev) · line 817

Quoted 10 lines
drivers/tty/serial/pxa.c +5 -0
+	sport->port.uartclk = clk;
+#else
+	i = dev->id;
 	sport->clk = clk_get(&dev->dev, NULL);
 	if (IS_ERR(sport->clk)) {
 		ret = PTR_ERR(sport->clk);
 		goto err_free;
 	}
+	sport->port.uartclk = clk_get_rate(sport->clk);
+#endif

This means a kernel build can either support DT or non-DT, but not both. DT & non-DT booting are full supported with the same kernel image, so don't do it this way.

Quoted 2 lines

Instead, check for the presence of an of_node. If it is there, do the DT parsing. If now, still support the old method.

Quoted 7 lines

Oh ffs, why is this DT stuff causing all the clk stuff to have to change. And specifically why is stuff converting to use clk_get_sys().

clk_get_sys() is there to allow system devices to get their clocks. It's not for general drivers to use.

Please, stop this madness.

indeed.

g.

#16 lore raw

PATCH v2 4/7 tty: serial: support device tree in pxa

In reply to Russell King - ARM Linux
Quoted 43 lines · Russell King - ARM Linux
Quoted 39 lines · Grant Likely
Quoted 26 lines · Haojian Zhuang
(quoted diff) +26 -0
+#ifdef CONFIG_OF
+ ? for (i = 0; i < PXA_SERIAL_NR; i++) {
+ ? ? ? ? ? if (serial_pxa_ports[i] == NULL)
+ ? ? ? ? ? ? ? ? ? break;
+ ? }
+ ? if (i >= PXA_SERIAL_NR) {
+ ? ? ? ? ? pr_warn("can't find pxa serial port\n");
+ ? ? ? ? ? return -ENODEV;
+ ? }
+
+ ? if (of_property_read_u32(np, "clock-frequency", &clk)) {
+ ? ? ? ? ? pr_warn("no clock-frequency property set\n");
+ ? ? ? ? ? return -ENODEV;
+ ? }
+ ? if (of_property_read_u32(np, "current-speed", &spd) == 0)
+ ? ? ? ? ? sport->port.custom_divisor = clk / (16 * spd);
+
+ ? sprintf(name, "pxa2xx-uart.%d", i);
+ ? sport->clk = clk_get_sys(name, NULL);
+ ? if (IS_ERR(sport->clk)) {
+ ? ? ? ? ? ret = PTR_ERR(sport->clk);
+ ? ? ? ? ? goto err_free;
+ ? }
+ ? sport->port.uartclk = clk;
+#else
+ ? i = dev->id;
Quoted 7 lines

? ? sport->clk = clk_get(&dev->dev, NULL); ? ? if (IS_ERR(sport->clk)) {
? ? ? ? ? ? ret = PTR_ERR(sport->clk);
? ? ? ? ? ? goto err_free;
? ? }
+ ? sport->port.uartclk = clk_get_rate(sport->clk); +#endif

This means a kernel build can either support DT or non-DT, but not both. ?DT & non-DT booting are full supported with the same kernel image, so don't do it this way.

Quoted 2 lines

Instead, check for the presence of an of_node. ?If it is there, do the DT parsing. ?If now, still support the old method.

Quoted 8 lines

Oh ffs, why is this DT stuff causing all the clk stuff to have to change. And specifically why is stuff converting to use clk_get_sys().

clk_get_sys() is there to allow system devices to get their clocks. It's not for general drivers to use.

Please, stop this madness.

So how could I get these clocks?

Thanks
Haojian

#17 lore raw

PATCH v2 4/7 tty: serial: support device tree in pxa

Quoted 5 lines · Haojian Zhuang
Quoted 3 lines · Russell King - ARM Linux

Oh ffs, why is this DT stuff causing all the clk stuff to have to change. And specifically why is stuff converting to use clk_get_sys().

Quoted 7 lines
Quoted 5 lines

clk_get_sys() is there to allow system devices to get their clocks. It's not for general drivers to use.

Please, stop this madness.

So how could I get these clocks?

Add the new _stable_ DT device name to the clkdev list.

#18 lore raw

PATCH v2 3/7 ARM: mmp: support DT on both dkb and brownstone

In reply to Haojian Zhuang
Quoted 467 lines · Haojian Zhuang

Add new boards.c to support both TTC-DKB and MMP2-BROWNSTONE. If CONFIG_OF isn't selected, we continue to use original ttc_dkb.c and brownstone.c.

While everything moving to DT in ARCH-MMP, ttc_dkb.c and brownstone.c will be abandoned.

---
 .../devicetree/bindings/arm/marvell/boards.txt     |    7 +
 arch/arm/boot/dts/mmp2-brownstone.dts              |  216 ++++++++++++++++++++
 arch/arm/boot/dts/pxa910-dkb.dts                   |   81 ++++++++
 arch/arm/mach-mmp/Makefile                         |    1 +
 arch/arm/mach-mmp/boards.c                         |  138 +++++++++++++
 5 files changed, 443 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/marvell/boards.txt
 create mode 100644 arch/arm/boot/dts/mmp2-brownstone.dts
 create mode 100644 arch/arm/boot/dts/pxa910-dkb.dts
 create mode 100644 arch/arm/mach-mmp/boards.c
Documentation/devicetree/bindings/arm/marvell/boards.txt new file +7 -0
new file mode 100644
index 0000000..a031a26
@@ -0,0 +1,7 @@
+TTC(pxa910) "DKB" evalutation board
+Required root node properties:
+	- compatible = "mrvl,pxa910-dkb", "mrvl,pxa910";
+
+mmp2(armada610) "Brownstone" evalutation board
+Required root node properties:
+	- compatible = "mrvl,mmp2-brownstone", "mrvl,mmp2";
arch/arm/boot/dts/mmp2-brownstone.dts new file +216 -0
new file mode 100644
index 0000000..2673282
@@ -0,0 +1,216 @@
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Marvell MMP2 Brownstone";
+	compatible = "mrvl,mmp2-brownstone", "mrvl,mmp2";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&mmp_intc>;
+
+	memory {
+		reg = <0x00000000 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS2,38400 root=/dev/nfs nfsroot=192.168.1.100:192.168.1.101::255.255.255.0::eth0:on";
+		linux,stdout-path = &uart2;
+	};
+
+	soc at d4000000 {
+		compatible = "mrvl,mmp2", "mrvl,armada610", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		mmp_intc: interrupt-controller at d4282000 {
+			compatible = "mrvl,pxa168-intc";
+			/* reg: <offset & size> */
+			reg = <0xd4282000 0x400>;
+
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			mrvl,intc-numbers = <64>;
+			/* priority bits in conf register */
+			mrvl,intc-priority = <0x20>;
+		};
+
+		mux_intc4: interrupt-controller at d4282150 {
+			compatible = "mrvl,mmp2-mux-intc";
+			reg = <0xd4282150 0>;
+
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			interrupts = <4>;
+			mrvl,intc-numbers = <2>;
+			mrvl,status-offset = <0x150>;
+			mrvl,mask-offset = <0x168>;
+			/* mfp register & interrupt index */
+			mrvl,mfp-edge = <0xd401e2c4 1>;
+		};
+
+		mux_intc5: interrupt-controller at d4282154 {
+			compatible = "mrvl,mmp2-mux-intc";
+			reg = <0xd4282154 0>;
+
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			interrupts = <5>;
+			mrvl,intc-numbers = <2>;
+			mrvl,status-offset = <0x154>;
+			mrvl,mask-offset = <0x16c>;
+		};
+
+		mux_intc9: interrupt-controller at d4282180 {
+			compatible = "mrvl,mmp2-mux-intc";
+			reg = <0xd4282180 0>;
+
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			interrupts = <9>;
+			mrvl,intc-numbers = <3>;
+			mrvl,status-offset = <0x180>;
+			mrvl,mask-offset = <0x17c>;
+		};
+
+		mux_intc17: interrupt-controller at d4282158 {
+			compatible = "mrvl,mmp2-mux-intc";
+			reg = <0xd4282158 0>;
+
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			interrupts = <17>;
+			mrvl,intc-numbers = <5>;
+			mrvl,status-offset = <0x158>;
+			mrvl,mask-offset = <0x170>;
+		};
+
+		mux_intc35: interrupt-controller at d428215c {
+			compatible = "mrvl,mmp2-mux-intc";
+			reg = <0xd428215c 0>;
+
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			interrupts = <35>;
+			mrvl,intc-numbers = <15>;
+			mrvl,status-offset = <0x15c>;
+			mrvl,mask-offset = <0x174>;
+		};
+
+		mux_intc51: interrupt-controller at d4282160 {
+			compatible = "mrvl,mmp2-mux-intc";
+			reg = <0xd4282160 0>;
+
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			interrupts = <51>;
+			mrvl,intc-numbers = <2>;
+			mrvl,status-offset = <0x160>;
+			mrvl,mask-offset = <0x178>;
+		};
+
+		mux_intc55: interrupt-controller at d4282188 {
+			compatible = "mrvl,mmp2-mux-intc";
+			reg = <0xd4282188 0>;
+
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			interrupts = <55>;
+			mrvl,intc-numbers = <2>;
+			mrvl,status-offset = <0x188>;
+			mrvl,mask-offset = <0x184>;
+		};
+
+		mmp_timer: timer at 0 {
+			compatible = "mrvl,pxa168-timer";
+			interrupts = <13>;
+			mrvl,clk-conf = <0xd4000024 0x13>;
+		};
+
+		i2c0: i2c at d4011000 {
+			compatible = "mrvl,pxa255-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xd4011000 0x60>;
+			interrupts = <7>;
+			mrvl,i2c-frequency = "fast";
+		};
+
+		i2c1: i2c at d4031000 {
+			compatible = "mrvl,pxa255-i2c";
+			reg = <0xd4031000 0x60>;
+			interrupts = <0>;
+			interrupt-parent = <&mux_intc17>;
+			mrvl,i2c-frequency = "fast";
+		};
+
+		i2c2: i2c at d4032000 {
+			compatible = "mrvl,pxa255-i2c";
+			reg = <0xd4032000 0x60>;
+			interrupts = <1>;
+			interrupt-parent = <&mux_intc17>;
+			mrvl,i2c-frequency = "fast";
+		};
+
+		i2c3: i2c at d4033000 {
+			compatible = "mrvl,pxa255-i2c";
+			reg = <0xd4033000 0x60>;
+			interrupts = <2>;
+			interrupt-parent = <&mux_intc17>;
+			mrvl,i2c-frequency = "fast";
+		};
+
+		i2c4: i2c at d4033800 {
+			compatible = "mrvl,pxa255-i2c";
+			reg = <0xd4033800 0x60>;
+			interrupts = <3>;
+			interrupt-parent = <&mux_intc17>;
+			mrvl,i2c-frequency = "fast";
+		};
+
+		i2c5: i2c at d4034000 {
+			compatible = "mrvl,pxa255-i2c";
+			reg = <0xd4034000 0x60>;
+			interrupts = <4>;
+			interrupt-parent = <&mux_intc17>;
+			mrvl,i2c-frequency = "fast";
+		};
+
+		uart0: uart at d4030000 {
+			compatible = "mrvl,pxa270-serial";
+			reg = <0xd4030000 0x1000>;
+			reg-shift = <2>;
+			interrupts = <27>;
+			clock-frequency = <26000000>;
+			current-speed = <115200>;
+		};
+
+		uart1: uart at d4017000 {
+			compatible = "mrvl,pxa270-serial";
+			reg = <0xd4017000 0x1000>;
+			reg-shift = <2>;
+			interrupts = <28>;
+			clock-frequency = <26000000>;
+			current-speed = <115200>;
+		};
+
+		uart2: uart at d4018000 {
+			compatible = "mrvl,pxa270-serial";
+			reg = <0xd4018000 0x1000>;
+			reg-shift = <2>;
+			interrupts = <24>;
+			clock-frequency = <26000000>;
+			current-speed = <38400>;
+		};
+
+		uart3: uart at d4016000 {
+			compatible = "mrvl,pxa270-serial";
+			reg = <0xd4016000 0x1000>;
+			reg-shift = <2>;
+			interrupts = <46>;
+			clock-frequency = <26000000>;
+			current-speed = <115200>;
+		};
+	};
+};
arch/arm/boot/dts/pxa910-dkb.dts new file +81 -0
new file mode 100644
index 0000000..b9f75b7
@@ -0,0 +1,81 @@
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Marvell TTC DKB";
+	compatible = "mrvl,pxa910-dkb", "mrvl,pxa910";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&mmp_intc>;
+
+	memory {
+		reg = <0x00000000 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.100:192.168.1.101::255.255.255.0::eth0:on";
+		linux,stdout-path = &uart0;
+	};
+
+	soc at d4000000 {
+		compatible = "mrvl,pxa910", "simple-bus";
+		device_type = "soc";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0xd4000000 0xd4000000 0x00200000	/* APB */
+			0xd4200000 0xd4200000 0x00200000>;	/* AXI */
+
+		mmp_intc: interrupt-controller at d4282000 {
+			compatible = "mrvl,pxa168-intc";
+			/* reg: <offset & size> */
+			reg = <0xd4282000 0x400>;
+
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			mrvl,intc-numbers = <64>;
+			/* priority bits in conf register */
+			mrvl,intc-priority = <0x51>;
+		};
+
+		mmp_timer: timer at 0 {
+			compatible = "mrvl,pxa168-timer";
+			interrupts = <13>;
+			mrvl,clk-conf = <0xd4000034 0x33>;
+		};
+
+		i2c0: i2c at d4011000 {
+			compatible = "mrvl,pxa255-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xd4011000 0x60>;
+			interrupts = <7>;
+			mrvl,i2c-frequency = "fast";
+		};
+
+		i2c1: i2c at d4037000 {
+			compatible = "mrvl,pxa255-i2c";
+			reg = <0xd4037000 0x60>;
+			interrupts = <54>;
+			mrvl,i2c-frequency = "fast";
+		};
+
+		uart0: uart at d4017000 {
+			compatible = "mrvl,pxa270-serial";
+			reg = <0xd4017000 0x1000>;
+			reg-shift = <2>;
+			interrupts = <27>;
+			clock-frequency = <14745600>;
+			current-speed = <115200>;
+		};
+
+		uart1: uart at d4018000 {
+			compatible = "mrvl,pxa270-serial";
+			reg = <0xd4018000 0x1000>;
+			reg-shift = <2>;
+			interrupts = <28>;
+			clock-frequency = <14745600>;
+			current-speed = <115200>;
+		};
+	};
+};
arch/arm/mach-mmp/Makefile +1 -0
index e7862ea..bdf5b23 100644
@@ -12,6 +12,7 @@ obj-$(CONFIG_CPU_PXA910)	+= pxa910.o irq-pxa168.o
 obj-$(CONFIG_CPU_MMP2)		+= mmp2.o irq-mmp2.o
 
 # board support
+obj-$(CONFIG_OF)		+= boards.o
 obj-$(CONFIG_MACH_ASPENITE)	+= aspenite.o
 obj-$(CONFIG_MACH_ZYLONITE2)	+= aspenite.o
 obj-$(CONFIG_MACH_AVENGERS_LITE)+= avengers_lite.o
arch/arm/mach-mmp/boards.c new file +108 -0
new file mode 100644
index 0000000..13e61fb
@@ -0,0 +1,138 @@
+/*
+ *  linux/arch/arm/mach-mmp/boards.c
+ *
+ *  Support for the Multiple Marvell Development Platforms.
+ *
+ *  Copyright (C) 2009-2011 Marvell International Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/pxa-i2c.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/pxa910.h>
+#include <mach/mmp2.h>
+#include <mach/mfp-mmp2.h>
+
+#include "common.h"
+
+static void __init ttc_dkb_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *ttc_dkb_dt_match[] __initdata = {
+	"mrvl,pxa910-dkb",
+	NULL,
+};
+
+DT_MACHINE_START(TTC_DKB, "PXA910-based TTC-DKB Development Platform")
+	.map_io		= mmp_map_io,
+	.init_irq	= mmp_init_intc,
+	.timer		= &mmp_timer,
+	.init_machine	= ttc_dkb_init,
+	.dt_compat	= ttc_dkb_dt_match,
+MACHINE_END
+
+static unsigned long brownstone_pin_config[] __initdata = {
+	/* UART1 */
+	GPIO29_UART1_RXD,
+	GPIO30_UART1_TXD,
+
+	/* UART3 */
+	GPIO51_UART3_RXD,
+	GPIO52_UART3_TXD,
+
+	/* DFI */
+	GPIO168_DFI_D0,
+	GPIO167_DFI_D1,
+	GPIO166_DFI_D2,
+	GPIO165_DFI_D3,
+	GPIO107_DFI_D4,
+	GPIO106_DFI_D5,
+	GPIO105_DFI_D6,
+	GPIO104_DFI_D7,
+	GPIO111_DFI_D8,
+	GPIO164_DFI_D9,
+	GPIO163_DFI_D10,
+	GPIO162_DFI_D11,
+	GPIO161_DFI_D12,
+	GPIO110_DFI_D13,
+	GPIO109_DFI_D14,
+	GPIO108_DFI_D15,
+	GPIO143_ND_nCS0,
+	GPIO144_ND_nCS1,
+	GPIO147_ND_nWE,
+	GPIO148_ND_nRE,
+	GPIO150_ND_ALE,
+	GPIO149_ND_CLE,
+	GPIO112_ND_RDY0,
+	GPIO160_ND_RDY1,
+
+	/* PMIC */
+	PMIC_PMIC_INT | MFP_LPM_EDGE_FALL,
+
+	/* MMC0 */
+	GPIO131_MMC1_DAT3 | MFP_PULL_HIGH,
+	GPIO132_MMC1_DAT2 | MFP_PULL_HIGH,
+	GPIO133_MMC1_DAT1 | MFP_PULL_HIGH,
+	GPIO134_MMC1_DAT0 | MFP_PULL_HIGH,
+	GPIO136_MMC1_CMD | MFP_PULL_HIGH,
+	GPIO139_MMC1_CLK,
+	GPIO140_MMC1_CD | MFP_PULL_LOW,
+	GPIO141_MMC1_WP | MFP_PULL_LOW,
+
+	/* MMC1 */
+	GPIO37_MMC2_DAT3 | MFP_PULL_HIGH,
+	GPIO38_MMC2_DAT2 | MFP_PULL_HIGH,
+	GPIO39_MMC2_DAT1 | MFP_PULL_HIGH,
+	GPIO40_MMC2_DAT0 | MFP_PULL_HIGH,
+	GPIO41_MMC2_CMD | MFP_PULL_HIGH,
+	GPIO42_MMC2_CLK,
+
+	/* MMC2 */
+	GPIO165_MMC3_DAT7 | MFP_PULL_HIGH,
+	GPIO162_MMC3_DAT6 | MFP_PULL_HIGH,
+	GPIO166_MMC3_DAT5 | MFP_PULL_HIGH,
+	GPIO163_MMC3_DAT4 | MFP_PULL_HIGH,

arch/arm/mach-mmp/boards.c line 118

Quoted 10 lines
arch/arm/mach-mmp/boards.c new file +10 -0
+	GPIO167_MMC3_DAT3 | MFP_PULL_HIGH,
+	GPIO164_MMC3_DAT2 | MFP_PULL_HIGH,
+	GPIO168_MMC3_DAT1 | MFP_PULL_HIGH,
+	GPIO111_MMC3_DAT0 | MFP_PULL_HIGH,
+	GPIO112_MMC3_CMD | MFP_PULL_HIGH,
+	GPIO151_MMC3_CLK,
+
+	/* 5V regulator */
+	GPIO89_GPIO,
+};

This table is /already/ in brownstone.c. Why duplicate it?

Quoted 23 lines
arch/arm/mach-mmp/boards.c new file +20 -0
+
+static void __init brownstone_init(void)
+{
+	mfp_config(ARRAY_AND_SIZE(brownstone_pin_config));
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *brownstone_dt_match[] __initdata = {
+	"mrvl,mmp2-brownstone",
+	NULL,
+};
+
+DT_MACHINE_START(BROWNSTONE, "Brownstone Development Platform")
+	.map_io		= mmp_map_io,
+	.init_irq	= mmp_init_intc,
+	.timer		= &mmp_timer,
+	.init_machine	= brownstone_init,
+	.dt_compat	= brownstone_dt_match,
+MACHINE_END
Signature · 1 line
1.5.6.5
#19 lore raw

PATCH v2 3/7 ARM: mmp: support DT on both dkb and brownstone

Quoted 472 lines · Grant Likely
Quoted 471 lines · Haojian Zhuang

Add new boards.c to support both TTC-DKB and MMP2-BROWNSTONE. If CONFIG_OF isn't selected, we continue to use original ttc_dkb.c and brownstone.c.

While everything moving to DT in ARCH-MMP, ttc_dkb.c and brownstone.c will be abandoned.

---

?.../devicetree/bindings/arm/marvell/boards.txt ? ? | ? ?7 +
?arch/arm/boot/dts/mmp2-brownstone.dts ? ? ? ? ? ? ?| ?216 ++++++++++++++++++++
?arch/arm/boot/dts/pxa910-dkb.dts ? ? ? ? ? ? ? ? ? | ? 81 ++++++++
?arch/arm/mach-mmp/Makefile ? ? ? ? ? ? ? ? ? ? ? ? | ? ?1 +
?arch/arm/mach-mmp/boards.c ? ? ? ? ? ? ? ? ? ? ? ? | ?138 +++++++++++++

?5 files changed, 443 insertions(+), 0 deletions(-)
?create mode 100644 Documentation/devicetree/bindings/arm/marvell/boards.txt ?create mode 100644 arch/arm/boot/dts/mmp2-brownstone.dts ?create mode 100644 arch/arm/boot/dts/pxa910-dkb.dts
?create mode 100644 arch/arm/mach-mmp/boards.c

Documentation/devicetree/bindings/arm/marvell/boards.txt new file +7 -0
new file mode 100644
index 0000000..a031a26
@@ -0,0 +1,7 @@
+TTC(pxa910) "DKB" evalutation board
+Required root node properties:
+ ? ? - compatible = "mrvl,pxa910-dkb", "mrvl,pxa910";
+
+mmp2(armada610) "Brownstone" evalutation board
+Required root node properties:
+ ? ? - compatible = "mrvl,mmp2-brownstone", "mrvl,mmp2";
arch/arm/boot/dts/mmp2-brownstone.dts new file +216 -0
new file mode 100644
index 0000000..2673282
@@ -0,0 +1,216 @@
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+ ? ? model = "Marvell MMP2 Brownstone";
+ ? ? compatible = "mrvl,mmp2-brownstone", "mrvl,mmp2";
+ ? ? #address-cells = <1>;
+ ? ? #size-cells = <1>;
+ ? ? interrupt-parent = <&mmp_intc>;
+
+ ? ? memory {
+ ? ? ? ? ? ? reg = <0x00000000 0x20000000>;
+ ? ? };
+
+ ? ? chosen {
+ ? ? ? ? ? ? bootargs = "console=ttyS2,38400 root=/dev/nfs nfsroot=192.168.1.100:192.168.1.101::255.255.255.0::eth0:on";
+ ? ? ? ? ? ? linux,stdout-path = &uart2;
+ ? ? };
+
+ ? ? soc at d4000000 {
+ ? ? ? ? ? ? compatible = "mrvl,mmp2", "mrvl,armada610", "simple-bus";
+ ? ? ? ? ? ? #address-cells = <1>;
+ ? ? ? ? ? ? #size-cells = <1>;
+ ? ? ? ? ? ? ranges;
+
+ ? ? ? ? ? ? mmp_intc: interrupt-controller at d4282000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa168-intc";
+ ? ? ? ? ? ? ? ? ? ? /* reg: <offset & size> */
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4282000 0x400>;
+
+ ? ? ? ? ? ? ? ? ? ? #interrupt-cells = <1>;
+ ? ? ? ? ? ? ? ? ? ? interrupt-controller;
+ ? ? ? ? ? ? ? ? ? ? mrvl,intc-numbers = <64>;
+ ? ? ? ? ? ? ? ? ? ? /* priority bits in conf register */
+ ? ? ? ? ? ? ? ? ? ? mrvl,intc-priority = <0x20>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? mux_intc4: interrupt-controller at d4282150 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,mmp2-mux-intc";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4282150 0>;
+
+ ? ? ? ? ? ? ? ? ? ? #interrupt-cells = <1>;
+ ? ? ? ? ? ? ? ? ? ? interrupt-controller;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <4>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,intc-numbers = <2>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,status-offset = <0x150>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,mask-offset = <0x168>;
+ ? ? ? ? ? ? ? ? ? ? /* mfp register & interrupt index */
+ ? ? ? ? ? ? ? ? ? ? mrvl,mfp-edge = <0xd401e2c4 1>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? mux_intc5: interrupt-controller at d4282154 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,mmp2-mux-intc";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4282154 0>;
+
+ ? ? ? ? ? ? ? ? ? ? #interrupt-cells = <1>;
+ ? ? ? ? ? ? ? ? ? ? interrupt-controller;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <5>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,intc-numbers = <2>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,status-offset = <0x154>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,mask-offset = <0x16c>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? mux_intc9: interrupt-controller at d4282180 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,mmp2-mux-intc";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4282180 0>;
+
+ ? ? ? ? ? ? ? ? ? ? #interrupt-cells = <1>;
+ ? ? ? ? ? ? ? ? ? ? interrupt-controller;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <9>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,intc-numbers = <3>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,status-offset = <0x180>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,mask-offset = <0x17c>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? mux_intc17: interrupt-controller at d4282158 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,mmp2-mux-intc";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4282158 0>;
+
+ ? ? ? ? ? ? ? ? ? ? #interrupt-cells = <1>;
+ ? ? ? ? ? ? ? ? ? ? interrupt-controller;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <17>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,intc-numbers = <5>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,status-offset = <0x158>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,mask-offset = <0x170>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? mux_intc35: interrupt-controller at d428215c {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,mmp2-mux-intc";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd428215c 0>;
+
+ ? ? ? ? ? ? ? ? ? ? #interrupt-cells = <1>;
+ ? ? ? ? ? ? ? ? ? ? interrupt-controller;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <35>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,intc-numbers = <15>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,status-offset = <0x15c>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,mask-offset = <0x174>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? mux_intc51: interrupt-controller at d4282160 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,mmp2-mux-intc";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4282160 0>;
+
+ ? ? ? ? ? ? ? ? ? ? #interrupt-cells = <1>;
+ ? ? ? ? ? ? ? ? ? ? interrupt-controller;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <51>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,intc-numbers = <2>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,status-offset = <0x160>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,mask-offset = <0x178>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? mux_intc55: interrupt-controller at d4282188 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,mmp2-mux-intc";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4282188 0>;
+
+ ? ? ? ? ? ? ? ? ? ? #interrupt-cells = <1>;
+ ? ? ? ? ? ? ? ? ? ? interrupt-controller;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <55>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,intc-numbers = <2>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,status-offset = <0x188>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,mask-offset = <0x184>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? mmp_timer: timer at 0 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa168-timer";
+ ? ? ? ? ? ? ? ? ? ? interrupts = <13>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,clk-conf = <0xd4000024 0x13>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? i2c0: i2c at d4011000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa255-i2c";
+ ? ? ? ? ? ? ? ? ? ? #address-cells = <1>;
+ ? ? ? ? ? ? ? ? ? ? #size-cells = <0>;
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4011000 0x60>;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <7>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,i2c-frequency = "fast";
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? i2c1: i2c at d4031000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa255-i2c";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4031000 0x60>;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <0>;
+ ? ? ? ? ? ? ? ? ? ? interrupt-parent = <&mux_intc17>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,i2c-frequency = "fast";
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? i2c2: i2c at d4032000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa255-i2c";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4032000 0x60>;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <1>;
+ ? ? ? ? ? ? ? ? ? ? interrupt-parent = <&mux_intc17>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,i2c-frequency = "fast";
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? i2c3: i2c at d4033000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa255-i2c";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4033000 0x60>;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <2>;
+ ? ? ? ? ? ? ? ? ? ? interrupt-parent = <&mux_intc17>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,i2c-frequency = "fast";
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? i2c4: i2c at d4033800 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa255-i2c";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4033800 0x60>;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <3>;
+ ? ? ? ? ? ? ? ? ? ? interrupt-parent = <&mux_intc17>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,i2c-frequency = "fast";
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? i2c5: i2c at d4034000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa255-i2c";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4034000 0x60>;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <4>;
+ ? ? ? ? ? ? ? ? ? ? interrupt-parent = <&mux_intc17>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,i2c-frequency = "fast";
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? uart0: uart at d4030000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa270-serial";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4030000 0x1000>;
+ ? ? ? ? ? ? ? ? ? ? reg-shift = <2>;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <27>;
+ ? ? ? ? ? ? ? ? ? ? clock-frequency = <26000000>;
+ ? ? ? ? ? ? ? ? ? ? current-speed = <115200>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? uart1: uart at d4017000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa270-serial";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4017000 0x1000>;
+ ? ? ? ? ? ? ? ? ? ? reg-shift = <2>;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <28>;
+ ? ? ? ? ? ? ? ? ? ? clock-frequency = <26000000>;
+ ? ? ? ? ? ? ? ? ? ? current-speed = <115200>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? uart2: uart at d4018000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa270-serial";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4018000 0x1000>;
+ ? ? ? ? ? ? ? ? ? ? reg-shift = <2>;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <24>;
+ ? ? ? ? ? ? ? ? ? ? clock-frequency = <26000000>;
+ ? ? ? ? ? ? ? ? ? ? current-speed = <38400>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? uart3: uart at d4016000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa270-serial";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4016000 0x1000>;
+ ? ? ? ? ? ? ? ? ? ? reg-shift = <2>;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <46>;
+ ? ? ? ? ? ? ? ? ? ? clock-frequency = <26000000>;
+ ? ? ? ? ? ? ? ? ? ? current-speed = <115200>;
+ ? ? ? ? ? ? };
+ ? ? };
+};
arch/arm/boot/dts/pxa910-dkb.dts new file +81 -0
new file mode 100644
index 0000000..b9f75b7
@@ -0,0 +1,81 @@
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+ ? ? model = "Marvell TTC DKB";
+ ? ? compatible = "mrvl,pxa910-dkb", "mrvl,pxa910";
+ ? ? #address-cells = <1>;
+ ? ? #size-cells = <1>;
+ ? ? interrupt-parent = <&mmp_intc>;
+
+ ? ? memory {
+ ? ? ? ? ? ? reg = <0x00000000 0x20000000>;
+ ? ? };
+
+ ? ? chosen {
+ ? ? ? ? ? ? bootargs = "console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.100:192.168.1.101::255.255.255.0::eth0:on";
+ ? ? ? ? ? ? linux,stdout-path = &uart0;
+ ? ? };
+
+ ? ? soc at d4000000 {
+ ? ? ? ? ? ? compatible = "mrvl,pxa910", "simple-bus";
+ ? ? ? ? ? ? device_type = "soc";
+ ? ? ? ? ? ? #address-cells = <1>;
+ ? ? ? ? ? ? #size-cells = <1>;
+ ? ? ? ? ? ? ranges = <0xd4000000 0xd4000000 0x00200000 ? ? ?/* APB */
+ ? ? ? ? ? ? ? ? ? ? 0xd4200000 0xd4200000 0x00200000>; ? ? ?/* AXI */
+
+ ? ? ? ? ? ? mmp_intc: interrupt-controller at d4282000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa168-intc";
+ ? ? ? ? ? ? ? ? ? ? /* reg: <offset & size> */
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4282000 0x400>;
+
+ ? ? ? ? ? ? ? ? ? ? #interrupt-cells = <1>;
+ ? ? ? ? ? ? ? ? ? ? interrupt-controller;
+ ? ? ? ? ? ? ? ? ? ? mrvl,intc-numbers = <64>;
+ ? ? ? ? ? ? ? ? ? ? /* priority bits in conf register */
+ ? ? ? ? ? ? ? ? ? ? mrvl,intc-priority = <0x51>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? mmp_timer: timer at 0 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa168-timer";
+ ? ? ? ? ? ? ? ? ? ? interrupts = <13>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,clk-conf = <0xd4000034 0x33>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? i2c0: i2c at d4011000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa255-i2c";
+ ? ? ? ? ? ? ? ? ? ? #address-cells = <1>;
+ ? ? ? ? ? ? ? ? ? ? #size-cells = <0>;
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4011000 0x60>;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <7>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,i2c-frequency = "fast";
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? i2c1: i2c at d4037000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa255-i2c";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4037000 0x60>;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <54>;
+ ? ? ? ? ? ? ? ? ? ? mrvl,i2c-frequency = "fast";
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? uart0: uart at d4017000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa270-serial";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4017000 0x1000>;
+ ? ? ? ? ? ? ? ? ? ? reg-shift = <2>;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <27>;
+ ? ? ? ? ? ? ? ? ? ? clock-frequency = <14745600>;
+ ? ? ? ? ? ? ? ? ? ? current-speed = <115200>;
+ ? ? ? ? ? ? };
+
+ ? ? ? ? ? ? uart1: uart at d4018000 {
+ ? ? ? ? ? ? ? ? ? ? compatible = "mrvl,pxa270-serial";
+ ? ? ? ? ? ? ? ? ? ? reg = <0xd4018000 0x1000>;
+ ? ? ? ? ? ? ? ? ? ? reg-shift = <2>;
+ ? ? ? ? ? ? ? ? ? ? interrupts = <28>;
+ ? ? ? ? ? ? ? ? ? ? clock-frequency = <14745600>;
+ ? ? ? ? ? ? ? ? ? ? current-speed = <115200>;
+ ? ? ? ? ? ? };
+ ? ? };
+};
arch/arm/mach-mmp/Makefile +0 -0
index e7862ea..bdf5b23 100644
@@ -12,6 +12,7 @@ obj-$(CONFIG_CPU_PXA910) ? ?+= pxa910.o irq-pxa168.o

?obj-$(CONFIG_CPU_MMP2) ? ? ? ? ? ? ? += mmp2.o irq-mmp2.o

?# board support
+obj-$(CONFIG_OF) ? ? ? ? ? ? += boards.o ?obj-$(CONFIG_MACH_ASPENITE) ?+= aspenite.o ?obj-$(CONFIG_MACH_ZYLONITE2) += aspenite.o ?obj-$(CONFIG_MACH_AVENGERS_LITE)+= avengers_lite.o

arch/arm/mach-mmp/boards.c new file +112 -0
new file mode 100644
index 0000000..13e61fb
@@ -0,0 +1,138 @@
+/*
+ * ?linux/arch/arm/mach-mmp/boards.c
+ *
+ * ?Support for the Multiple Marvell Development Platforms.
+ *
+ * ?Copyright (C) 2009-2011 Marvell International Ltd.
+ *
+ * ?This program is free software; you can redistribute it and/or modify
+ * ?it under the terms of the GNU General Public License version 2 as
+ * ?publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/pxa-i2c.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/pxa910.h>
+#include <mach/mmp2.h>
+#include <mach/mfp-mmp2.h>
+
+#include "common.h"
+
+static void __init ttc_dkb_init(void)
+{
+ ? ? of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *ttc_dkb_dt_match[] __initdata = {
+ ? ? "mrvl,pxa910-dkb",
+ ? ? NULL,
+};
+
+DT_MACHINE_START(TTC_DKB, "PXA910-based TTC-DKB Development Platform")
+ ? ? .map_io ? ? ? ? = mmp_map_io,
+ ? ? .init_irq ? ? ? = mmp_init_intc,
+ ? ? .timer ? ? ? ? ?= &mmp_timer,
+ ? ? .init_machine ? = ttc_dkb_init,
+ ? ? .dt_compat ? ? ?= ttc_dkb_dt_match,
+MACHINE_END
+
+static unsigned long brownstone_pin_config[] __initdata = {
+ ? ? /* UART1 */
+ ? ? GPIO29_UART1_RXD,
+ ? ? GPIO30_UART1_TXD,
+
+ ? ? /* UART3 */
+ ? ? GPIO51_UART3_RXD,
+ ? ? GPIO52_UART3_TXD,
+
+ ? ? /* DFI */
+ ? ? GPIO168_DFI_D0,
+ ? ? GPIO167_DFI_D1,
+ ? ? GPIO166_DFI_D2,
+ ? ? GPIO165_DFI_D3,
+ ? ? GPIO107_DFI_D4,
+ ? ? GPIO106_DFI_D5,
+ ? ? GPIO105_DFI_D6,
+ ? ? GPIO104_DFI_D7,
+ ? ? GPIO111_DFI_D8,
+ ? ? GPIO164_DFI_D9,
+ ? ? GPIO163_DFI_D10,
+ ? ? GPIO162_DFI_D11,
+ ? ? GPIO161_DFI_D12,
+ ? ? GPIO110_DFI_D13,
+ ? ? GPIO109_DFI_D14,
+ ? ? GPIO108_DFI_D15,
+ ? ? GPIO143_ND_nCS0,
+ ? ? GPIO144_ND_nCS1,
+ ? ? GPIO147_ND_nWE,
+ ? ? GPIO148_ND_nRE,
+ ? ? GPIO150_ND_ALE,
+ ? ? GPIO149_ND_CLE,
+ ? ? GPIO112_ND_RDY0,
+ ? ? GPIO160_ND_RDY1,
+
+ ? ? /* PMIC */
+ ? ? PMIC_PMIC_INT | MFP_LPM_EDGE_FALL,
+
+ ? ? /* MMC0 */
+ ? ? GPIO131_MMC1_DAT3 | MFP_PULL_HIGH,
+ ? ? GPIO132_MMC1_DAT2 | MFP_PULL_HIGH,
+ ? ? GPIO133_MMC1_DAT1 | MFP_PULL_HIGH,
+ ? ? GPIO134_MMC1_DAT0 | MFP_PULL_HIGH,
+ ? ? GPIO136_MMC1_CMD | MFP_PULL_HIGH,
+ ? ? GPIO139_MMC1_CLK,
+ ? ? GPIO140_MMC1_CD | MFP_PULL_LOW,
+ ? ? GPIO141_MMC1_WP | MFP_PULL_LOW,
+
+ ? ? /* MMC1 */
+ ? ? GPIO37_MMC2_DAT3 | MFP_PULL_HIGH,
+ ? ? GPIO38_MMC2_DAT2 | MFP_PULL_HIGH,
+ ? ? GPIO39_MMC2_DAT1 | MFP_PULL_HIGH,
+ ? ? GPIO40_MMC2_DAT0 | MFP_PULL_HIGH,
+ ? ? GPIO41_MMC2_CMD | MFP_PULL_HIGH,
+ ? ? GPIO42_MMC2_CLK,
+
+ ? ? /* MMC2 */
+ ? ? GPIO165_MMC3_DAT7 | MFP_PULL_HIGH,
+ ? ? GPIO162_MMC3_DAT6 | MFP_PULL_HIGH,
+ ? ? GPIO166_MMC3_DAT5 | MFP_PULL_HIGH,
+ ? ? GPIO163_MMC3_DAT4 | MFP_PULL_HIGH,
+ ? ? GPIO167_MMC3_DAT3 | MFP_PULL_HIGH,
+ ? ? GPIO164_MMC3_DAT2 | MFP_PULL_HIGH,
+ ? ? GPIO168_MMC3_DAT1 | MFP_PULL_HIGH,
+ ? ? GPIO111_MMC3_DAT0 | MFP_PULL_HIGH,
Quoted 9 lines

arch/arm/mach-mmp/boards.c line 118

Quoted 6 lines
arch/arm/mach-mmp/boards.c new file +6 -0
+ ? ? GPIO112_MMC3_CMD | MFP_PULL_HIGH,
+ ? ? GPIO151_MMC3_CLK,
+
+ ? ? /* 5V regulator */
+ ? ? GPIO89_GPIO,
+};

This table is /already/ in brownstone.c. ?Why duplicate it?

As I mentioned, brownstone.c will be abandoned later.

Quoted 24 lines
Quoted 23 lines
arch/arm/mach-mmp/boards.c new file +20 -1
+
+static void __init brownstone_init(void)
+{
+ ? ? mfp_config(ARRAY_AND_SIZE(brownstone_pin_config));
+
+ ? ? of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *brownstone_dt_match[] __initdata = {
+ ? ? "mrvl,mmp2-brownstone",
+ ? ? NULL,
+};
+
+DT_MACHINE_START(BROWNSTONE, "Brownstone Development Platform")
+ ? ? .map_io ? ? ? ? = mmp_map_io,
+ ? ? .init_irq ? ? ? = mmp_init_intc,
+ ? ? .timer ? ? ? ? ?= &mmp_timer,
+ ? ? .init_machine ? = brownstone_init,
+ ? ? .dt_compat ? ? ?= brownstone_dt_match,
+MACHINE_END
--

1.5.6.5

#20 lore raw

PATCH v2 2/7 ARM: mmp: parse timer configuration from DT

In reply to Haojian Zhuang
Quoted 90 lines · Haojian Zhuang

Parse timer configuration from DT. Now we can merge pxa910_timer and mmp2_timer into mmp_timer. Since most configuration between these two timers are same. The difference is recorded in DT.

---
 .../devicetree/bindings/arm/marvell/timer.txt      |   24 +++++++++
 arch/arm/mach-mmp/common.h                         |    2 +
 arch/arm/mach-mmp/time.c                           |   50 +++++++++++++++++++-
 3 files changed, 75 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/marvell/timer.txt
Documentation/devicetree/bindings/arm/marvell/timer.txt new file +24 -0
new file mode 100644
index 0000000..24a6f97
@@ -0,0 +1,24 @@
+* Timer Controller Binding for ARCH-MMP
+
+This binding specifies what properties must be available in device tree
+representation of an ARCH-MMP compliant timer controller.
+
+Required properties:
+
+	- compatible: Specifies the compatibility list of the timer controller.
+	  The type shall be <string> and the value shall be
+	  "mrvl,pxa168-timer".
+
+	- mrvl,clk-conf: Specifies the address and value of timer 
+	  configuration register.
+	  The type shall be <prop-encoded-array>. The first value indicates
+	  the physical address of timer configuration register. The second
+	  value indicates data should be written to timer configuration
+	  register.
+
+* Example
+
+	mmp_timer: {
+		compatible = "mrvl,pxa168-timer";
+		mrvl,clk-conf = <0xd4000034 0x33>;
+	};
arch/arm/mach-mmp/common.h +2 -0
index 1c563c2..890c664 100644
@@ -2,6 +2,8 @@
 
 struct sys_timer;
 
+extern struct sys_timer mmp_timer;
+
 extern void timer_init(int irq);
 
 extern void __init icu_init_irq(void);
arch/arm/mach-mmp/time.c +12 -1
index 99833b9..5a90b27 100644
@@ -25,6 +25,8 @@
 
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/sched.h>
 
 #include <asm/sched_clock.h>
@@ -150,7 +152,7 @@ static void __init timer_config(void)
 
 	__raw_writel(cer & ~0x1, TIMERS_VIRT_BASE + TMR_CER); /* disable */
 
-	ccr &= (cpu_is_mmp2()) ? TMR_CCR_CS_0(0) : TMR_CCR_CS_0(3);
+	ccr &= TMR_CCR_CS_0(0);
 	__raw_writel(ccr, TIMERS_VIRT_BASE + TMR_CCR);
 
 	/* free-running mode */
@@ -187,3 +189,49 @@ void __init timer_init(int irq)
 	clocksource_register_hz(&cksrc, CLOCK_TICK_RATE);
 	clockevents_register_device(&ckevt);
 }
+
+#ifdef CONFIG_OF
+static void __init mmp_timer_init(void)
+{
+	struct device_node *np;
+	const __be32 *clk_offs;
+	void __iomem *conf;
+	unsigned int addr = 0, offs = 0;
+	int size, irq;

arch/arm/mach-mmp/time.c void __init timer_init(int irq) · line 210

Quoted 10 lines
arch/arm/mach-mmp/time.c +10 -0
+
+	np = of_find_compatible_node(NULL, NULL, "mrvl,pxa168-timer");
+
+	BUG_ON(!np);
+
+	of_node_get(np);
+	irq = irq_of_parse_and_map(np, 0);
+
+	clk_offs = of_get_property(np, "mrvl,clk-conf", &size);
+	if ((clk_offs == NULL) || (size != sizeof(int) * 2)) {

sizeof(u32)

I would recommend using of_property_read_u32_array() which does the sanity checking for you.

arch/arm/mach-mmp/time.c void __init timer_init(int irq) · line 216

Quoted 6 lines
arch/arm/mach-mmp/time.c +6 -0
+		pr_warn("mmp-timer: mrvl,clk-conf property is wrong\n");
+		goto out;
+	}
+	addr = be32_to_cpu(*clk_offs) & PAGE_MASK;
+	offs = be32_to_cpu(*clk_offs) - addr;
+	conf = ioremap(addr, PAGE_SIZE);

base addresses should be in a 'reg' property. I would put the register region into a 'reg' tuple so that of_iomap() works, and then encode just the offset/config-value pair into mrvl,clk-conf.

Quoted 24 lines
arch/arm/mach-mmp/time.c +21 -0
+	if (conf == NULL) {
+		pr_warn("mmp-timer: failed on mapping 0x%x\n", (uint32_t)conf);
+		goto out;
+	}
+	/* reset and configure */
+	__raw_writel(APBC_APBCLK | APBC_RST, conf + offs);
+	__raw_writel(be32_to_cpu(*++clk_offs), conf + offs);
+	__raw_readl(conf + offs);
+	iounmap(conf);
+
+	timer_init(irq);
+	return;
+out:
+	of_node_put(np);
+	return;
+}
+
+struct sys_timer mmp_timer = {
+	.init	= mmp_timer_init,
+};
+#endif
Signature · 1 line
1.5.6.5
#21 lore raw

PATCH v2 1/7 ARM: mmp: parse irq from DT

In reply to Haojian Zhuang
Quoted 153 lines · Haojian Zhuang

Parse irq sepcifier from DT and translate it to Linux irq number. Remove the definition of NR_IRQS in irqs.h. Since sparse irq is enabled, nr_irqs will be calculated automatically.

---
 .../devicetree/bindings/arm/marvell/intc.txt       |  114 ++++++++++
 arch/arm/Kconfig                                   |    1 +
 arch/arm/mach-mmp/Makefile                         |    2 +
 arch/arm/mach-mmp/common.h                         |    1 +
 arch/arm/mach-mmp/include/mach/irqs.h              |    2 +-
 arch/arm/mach-mmp/intc.c                           |  224 ++++++++++++++++++++
 6 files changed, 343 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/marvell/intc.txt
 create mode 100644 arch/arm/mach-mmp/intc.c
Documentation/devicetree/bindings/arm/marvell/intc.txt new file +114 -0
new file mode 100644
index 0000000..80cef58
@@ -0,0 +1,114 @@
+* Interrupt Controller Binding for ARCH-MMP
+
+This binding specifies what properties must be available in device tree representation of an ARCH-MMP compliant interrupt controller.
+
+Required properties:
+
+	- compatible: Specifies the compatibility list of the interrupt
+	  controller. The type shall be <string> and the value shall be
+	  "mrvl,pxa168-intc" or "mrvl,mmp2-mux-intc".
+	  "mrvl,pxa168-intc" is the base interrupt controller. It must be
+	  included. It's compatible for pxa910, mmp2. "mrvl,mmp2-mux-intc"
+	  is the expanded interrupt controller, and it's optional.
+
+	- reg: Specified the base physical address(s) and size(s) of the
+	  interrupt controller's addressable register space. The type
+	  should be <prop-encoded-array>.
+
+	- interrupt-controller: The presence of this property identifies
+	  the node as interrupt controller. No property value should be
+	  defined.
+
+	- #interrupt-cells: Specifies the number of cells needed to encode
+	  an interrupt source. The type should be <u32> and the value should
+	  be 1.
+
+	- mrvl,intc-numbers: Specifies the number of interrupts is supported
+	  in this interrupt controller. The type should be <u32>.
+
+Optional properties:
+
+	- mrvl,intc-priority: Specifies the which path the interrupt is routed
+	  and the priority of this interrupt. The property is used in
+	  pxa168-intc. The value should be <u32>.
+
+	- mrvl,status-offset: Specifies the offset of status register. The
+	  property is used in mmp2-mux-intc. The type should be <u32>.
+
+	- mrvl,mask-offset: Specifies the offset of mask register. The
+	  property is used in mmp2-mux-intc. The type should be <u32>.
+
+	- mrvl,mfp-edge: Specifies the address of mfp edge detection register.
+	  The property is used while acking specified interrupt. The type
+	  should be <prop-encoded-array>. The first cell indicates the address
+	  of mfp edge detection register. The second cell indicates the
+	  index of interrupt in current interrupt controller that should
+	  handle mfp edge detection.
+
+* Examples
+
+Example 1:
+
+	/*
+	 * base INTC
+	 */
+	mmp_intc: interrupt-controller at d4282000 {
+		/* Compatible with pxa168-intc. */
+		compatible = "mrvl,pxa168-intc";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		/* Offset address of 0xd4282000 and size of 0x400. */
+		reg = <0xd4282000 0x400>;
+
+		#interrupt-cells = <1>;
+		interrupt-controller;
+
+		/* 64 interrupts are supported in this INTC. */
+		mrvl,intc-numbers = <64>;
+
+		/* priority bits in configuration register */
+		mrvl,intc-priority = <0x20>;
+	};
+
+Example 2:
+
+	/*
+	 * mux INTC that is internal wired to base INTC
+	 */
+	mux_intc4: interrupt-controller at d4282150 {
+		compatible = "mrvl,mmp2-mux-intc";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xd4282000 0x400>;
+
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&mmp_intc>;
+
+		/* interrupt source '4' of parent INTC. */
+		interrupts = <4>;
+
+		/* 2 interrupts are supported in this INTC. */
+		mrvl,intc-numbers = <2>;
+
+		/* Status offset address of 0x150. */
+		mrvl,status-offset = <0x150>;
+
+		/* Mask offset address of 0x168. */
+		mrvl,mask-offset = <0x168>;
+
+		/* mfp register of 0xd401e2c4 & interrupt index of 1 */
+		mrvl,mfp-edge = <0xd401e2c4 1>;
+	};
+
+Example 3:
+	/*
+	 * An interrupt generating device that is wired to an INTC.
+	 */
+	uart0: uart at d4030000 {
+		/* parent's '#interrupt-cells' property. */
+		interrupts = <27>;
+
+		/* The INTC that this device is wired to. */
+		interrupt-parent = <&mmp_intc>;
+	};
arch/arm/Kconfig +1 -0
index 17507b8..f18eb14 100644
@@ -542,6 +542,7 @@ config ARCH_MMP
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
+	select GENERIC_IRQ_CHIP
 	select HAVE_SCHED_CLOCK
 	select TICK_ONESHOT
 	select PLAT_PXA
arch/arm/mach-mmp/Makefile +0 -0
index 5c68382..e7862ea 100644

arch/arm/mach-mmp/Makefile line 8

Quoted 5 lines
arch/arm/mach-mmp/Makefile +2 -0
@@ -4,6 +4,8 @@
 
 obj-y				+= common.o clock.o devices.o time.o
 
+obj-$(CONFIG_OF_IRQ)		+= intc.o
+

I'm still really confused about why an entirely new interrupt controller file is being added. Drivers already exist in mach-mmp for the mux and pxa168 interrupt controllers, but this adds a whole new driver. I would expect the existing drivers should be refactored to use irq generic chip, and then extend them to add DT support.

Quoted 17 lines
arch/arm/mach-mmp/Makefile +0 -0
 # SoC support
 obj-$(CONFIG_CPU_PXA168)	+= pxa168.o irq-pxa168.o
 obj-$(CONFIG_CPU_PXA910)	+= pxa910.o irq-pxa168.o
arch/arm/mach-mmp/common.h +1 -0
index ec8d65d..1c563c2 100644
@@ -6,3 +6,4 @@ extern void timer_init(int irq);
 
 extern void __init icu_init_irq(void);
 extern void __init mmp_map_io(void);
+extern void __init mmp_init_intc(void);
arch/arm/mach-mmp/include/mach/irqs.h +0 -0
index a09d328..65ec176 100644

arch/arm/mach-mmp/include/mach/irqs.h line 227

Quoted 5 lines
arch/arm/mach-mmp/include/mach/irqs.h +1 -1
@@ -224,6 +224,6 @@
 
 #define IRQ_BOARD_START			(IRQ_GPIO_START + IRQ_GPIO_NUM)
 
-#define NR_IRQS				(IRQ_BOARD_START)
+#define NR_IRQS				0

Why is NR_IRQs getting changed? I think this will break !CONFIG_SPARSE_IRQS, and it shouldn't be necessary for this conversion.

Quoted 240 lines
arch/arm/mach-mmp/include/mach/irqs.h +0 -1
-- 
 Regards,

Shawn

#endif /* __ASM_MACH_IRQS_H */

arch/arm/mach-mmp/intc.c new file +224 -0
new file mode 100644
index 0000000..2e44057
@@ -0,0 +1,224 @@
+/*
+ *  linux/arch/arm/mach-mmp/intc.c
+ *
+ *  Generic IRQ handling
+ *
+ *  Author:	Haojian Zhuang <[email protected]>
+ *  Copyright:	Marvell International Ltd. 2011
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+
+struct mmp_intc_info {
+	unsigned int		en_mask;
+	void __iomem		*virt_base;
+	void __iomem		*status;
+	void __iomem		*mfp_edge;
+	unsigned int		mfp_edge_index; /* index in irq domain */
+};
+
+static void mux_irq_ack(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct;
+	struct mmp_intc_info *info;
+	unsigned int data, irq_offs;
+
+	ct = gc->chip_types;
+	info = (struct mmp_intc_info *)ct->regs.ack;
+	irq_offs = d->irq - gc->irq_base;
+	/* clear MFP edge-detect */
+	if (info->mfp_edge && (info->mfp_edge_index == irq_offs)) {
+		data = __raw_readl(info->mfp_edge);
+		__raw_writel(data | (1 << 6), info->mfp_edge);
+		__raw_writel(data, info->mfp_edge);
+	}
+}
+
+static void mmp_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct irq_chip_generic *gc = irq_get_handler_data(irq);
+	struct irq_chip_type *ct;
+	struct mmp_intc_info *info;
+	unsigned long status, n;
+
+	ct = gc->chip_types;
+	info = (struct mmp_intc_info *)ct->regs.ack;
+	while (1) {
+		status = __raw_readl(info->status) & ~gc->mask_cache;
+		if (status == 0)
+			break;
+		n = find_first_bit(&status, BITS_PER_LONG);
+		while (n < BITS_PER_LONG) {
+			generic_handle_irq(gc->irq_base + n);
+			n = find_next_bit(&status, BITS_PER_LONG, n + 1);
+		}
+	}
+}
+
+static void mux_init_intc(struct mmp_intc_info *mmp_info)
+{
+	struct device_node *np;
+	struct mmp_intc_info *mux_info;
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+	const __be32 *edge;
+	unsigned int addr = 0, offs = 0;
+	unsigned int status, mask, irq_base, nr, data;
+	int cascade;
+
+	for_each_compatible_node(np, NULL, "mrvl,mmp2-mux-intc") {
+		if (of_get_property(np, "interrupt-controller", NULL) == NULL)
+			continue;
+		if (of_property_read_u32(np, "mrvl,intc-numbers", &nr) < 0) {
+			pr_warn("intc-numbers property is missed\n");
+			continue;
+		}
+		if (of_property_read_u32(np, "mrvl,status-offset", &status)
+			< 0) {
+			pr_warn("intc-status property is missed\n");
+			continue;
+		}
+		if (of_property_read_u32(np, "mrvl,mask-offset", &mask) < 0) {
+			pr_warn("intc-mask property is missed\n");
+			continue;
+		}
+
+		mux_info = kzalloc(sizeof(*mux_info), GFP_KERNEL);
+		if (mux_info == NULL)
+			goto out;
+		status += (unsigned int)mmp_info->virt_base;
+		mux_info->status = (void __iomem *)status;
+
+		edge = of_get_property(np, "mrvl,mfp-edge", NULL);
+		if (edge) {
+			addr = be32_to_cpu(*edge) & PAGE_MASK;
+			offs = be32_to_cpu(*edge) - addr;
+			mux_info->mfp_edge = ioremap(addr, PAGE_SIZE) + offs;
+			mux_info->mfp_edge_index = be32_to_cpu(*++edge);
+			/* clear mfp edge detection for initialization */
+			data = __raw_readl(mux_info->mfp_edge);
+			__raw_writel(data | (1 << 6), mux_info->mfp_edge);
+			__raw_writel(data, mux_info->mfp_edge);
+		}
+
+		/* allocate new irq */
+		cascade = irq_of_parse_and_map(np, 0);
+		irq_base = irq_alloc_descs(-1, 0, nr, 0);
+		irq_domain_add_simple(np, irq_base);
+
+		gc = irq_alloc_generic_chip("mux-intc", 1, irq_base,
+					mmp_info->virt_base, handle_level_irq);
+		ct = gc->chip_types;
+		ct->regs.ack = (unsigned int)mux_info;
+		ct->regs.mask = mask;
+		ct->chip.irq_ack = mux_irq_ack;
+		ct->chip.irq_mask = irq_gc_mask_set_bit;
+		ct->chip.irq_unmask = irq_gc_mask_clr_bit;
+		irq_setup_generic_chip(gc, IRQ_MSK(nr), IRQ_GC_INIT_MASK_CACHE,
+					IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+
+		irq_set_handler_data(cascade, gc);
+		irq_set_chained_handler(cascade, mmp_irq_demux_handler);
+	}
+out:
+	return;
+}
+
+static void mmp_irq_unmask(struct irq_data *d)
+{
+	struct mmp_intc_info *info = irq_data_get_irq_chip_data(d);
+
+	/* ICU_INT_CONF */
+	__raw_writel(info->en_mask, info->virt_base + (d->irq << 2));
+}
+
+static void mmp_irq_mask(struct irq_data *d)
+{
+	struct mmp_intc_info *info = irq_data_get_irq_chip_data(d);
+
+	__raw_writel(0, info->virt_base + (d->irq << 2));
+}
+
+static struct irq_chip mmp_irq_chip = {
+	.name		= "mmp-intc",
+	.irq_unmask	= mmp_irq_unmask,
+	.irq_mask	= mmp_irq_mask,
+	.irq_ack	= mmp_irq_mask,
+};
+
+void __init mmp_init_intc(void)
+{
+	struct mmp_intc_info *info;
+	struct device_node *np;
+	struct resource rs;
+	unsigned int cells, nr, enable, irq_base;
+	int i;
+
+	np = of_find_compatible_node(NULL, NULL, "mrvl,pxa168-intc");
+
+	BUG_ON(!np);
+
+	of_node_get(np);
+	if (of_get_property(np, "interrupt-controller", NULL) == NULL)
+		goto out;
+	if (of_property_read_u32(np, "#interrupt-cells", &cells) < 0) {
+		pr_warn("mmp-intc: interrupt-cells property is missed\n");
+		goto out;
+	}
+	if (cells != 1) {
+		pr_warn("mmp-intc: interrupt-cells property is incorrect\n");
+		goto out;
+	}
+	if (of_property_read_u32(np, "mrvl,intc-numbers", &nr) < 0) {
+		pr_warn("mmp-intc: mrvl,intc-numbers property is missed\n");
+		goto out;
+	}
+	if (of_property_read_u32(np, "mrvl,intc-priority", &enable) < 0) {
+		pr_warn("mmp-intc: mrvl,intc-priority property is missed\n");
+		goto out;
+	}
+	if (of_address_to_resource(np, 0, &rs) < 0) {
+		pr_warn("mmp-intc: invalid reg property\n");
+		goto out;
+	}
+
+	info = kzalloc(sizeof(struct mmp_intc_info), GFP_KERNEL);
+	if (info == NULL)
+		goto out;
+	info->en_mask = enable;
+	info->virt_base = ioremap(rs.start, PAGE_SIZE);
+	if (info->virt_base == NULL) {
+		pr_warn("mmp-intc: failed to remap reg base\n");
+		goto out_mem;
+	}
+
+	/* allocate new irq */
+	irq_base = irq_alloc_descs(-1, 0, nr, 0);
+	irq_domain_add_simple(np, 0);
+
+	for (i = irq_base; i < irq_base + nr; i++) {
+		irq_set_chip_data(i, info);
+		mmp_irq_mask(irq_get_irq_data(i));
+		irq_set_chip_and_handler(i, &mmp_irq_chip, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+	mux_init_intc(info);
+	of_node_put(np);
+	return;
+out_mem:
+	kfree(info);
+out:
+	of_node_put(np);
+	return;
+}
Signature · 1 line
1.5.6.5
#22 lore raw

PATCH v2 1/7 ARM: mmp: parse irq from DT

Quoted 157 lines · Grant Likely
Quoted 156 lines · Haojian Zhuang

Parse irq sepcifier from DT and translate it to Linux irq number. Remove the definition of NR_IRQS in irqs.h. Since sparse irq is enabled, nr_irqs will be calculated automatically.

---

?.../devicetree/bindings/arm/marvell/intc.txt ? ? ? | ?114 ++++++++++
?arch/arm/Kconfig ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | ? ?1 +
?arch/arm/mach-mmp/Makefile ? ? ? ? ? ? ? ? ? ? ? ? | ? ?2 +
?arch/arm/mach-mmp/common.h ? ? ? ? ? ? ? ? ? ? ? ? | ? ?1 +
?arch/arm/mach-mmp/include/mach/irqs.h ? ? ? ? ? ? ?| ? ?2 +-
?arch/arm/mach-mmp/intc.c ? ? ? ? ? ? ? ? ? ? ? ? ? | ?224 ++++++++++++++++++++

?6 files changed, 343 insertions(+), 1 deletions(-)
?create mode 100644 Documentation/devicetree/bindings/arm/marvell/intc.txt ?create mode 100644 arch/arm/mach-mmp/intc.c

Documentation/devicetree/bindings/arm/marvell/intc.txt new file +114 -0
new file mode 100644
index 0000000..80cef58
@@ -0,0 +1,114 @@
+* Interrupt Controller Binding for ARCH-MMP
+
+This binding specifies what properties must be available in device tree representation of an ARCH-MMP compliant interrupt controller.
+
+Required properties:
+
+ ? ? - compatible: Specifies the compatibility list of the interrupt
+ ? ? ? controller. The type shall be <string> and the value shall be
+ ? ? ? "mrvl,pxa168-intc" or "mrvl,mmp2-mux-intc".
+ ? ? ? "mrvl,pxa168-intc" is the base interrupt controller. It must be
+ ? ? ? included. It's compatible for pxa910, mmp2. "mrvl,mmp2-mux-intc"
+ ? ? ? is the expanded interrupt controller, and it's optional.
+
+ ? ? - reg: Specified the base physical address(s) and size(s) of the
+ ? ? ? interrupt controller's addressable register space. The type
+ ? ? ? should be <prop-encoded-array>.
+
+ ? ? - interrupt-controller: The presence of this property identifies
+ ? ? ? the node as interrupt controller. No property value should be
+ ? ? ? defined.
+
+ ? ? - #interrupt-cells: Specifies the number of cells needed to encode
+ ? ? ? an interrupt source. The type should be <u32> and the value should
+ ? ? ? be 1.
+
+ ? ? - mrvl,intc-numbers: Specifies the number of interrupts is supported
+ ? ? ? in this interrupt controller. The type should be <u32>.
+
+Optional properties:
+
+ ? ? - mrvl,intc-priority: Specifies the which path the interrupt is routed
+ ? ? ? and the priority of this interrupt. The property is used in
+ ? ? ? pxa168-intc. The value should be <u32>.
+
+ ? ? - mrvl,status-offset: Specifies the offset of status register. The
+ ? ? ? property is used in mmp2-mux-intc. The type should be <u32>.
+
+ ? ? - mrvl,mask-offset: Specifies the offset of mask register. The
+ ? ? ? property is used in mmp2-mux-intc. The type should be <u32>.
+
+ ? ? - mrvl,mfp-edge: Specifies the address of mfp edge detection register.
+ ? ? ? The property is used while acking specified interrupt. The type
+ ? ? ? should be <prop-encoded-array>. The first cell indicates the address
+ ? ? ? of mfp edge detection register. The second cell indicates the
+ ? ? ? index of interrupt in current interrupt controller that should
+ ? ? ? handle mfp edge detection.
+
+* Examples
+
+Example 1:
+
+ ? ? /*
+ ? ? ?* base INTC
+ ? ? ?*/
+ ? ? mmp_intc: interrupt-controller at d4282000 {
+ ? ? ? ? ? ? /* Compatible with pxa168-intc. */
+ ? ? ? ? ? ? compatible = "mrvl,pxa168-intc";
+ ? ? ? ? ? ? #address-cells = <1>;
+ ? ? ? ? ? ? #size-cells = <1>;
+ ? ? ? ? ? ? /* Offset address of 0xd4282000 and size of 0x400. */
+ ? ? ? ? ? ? reg = <0xd4282000 0x400>;
+
+ ? ? ? ? ? ? #interrupt-cells = <1>;
+ ? ? ? ? ? ? interrupt-controller;
+
+ ? ? ? ? ? ? /* 64 interrupts are supported in this INTC. */
+ ? ? ? ? ? ? mrvl,intc-numbers = <64>;
+
+ ? ? ? ? ? ? /* priority bits in configuration register */
+ ? ? ? ? ? ? mrvl,intc-priority = <0x20>;
+ ? ? };
+
+Example 2:
+
+ ? ? /*
+ ? ? ?* mux INTC that is internal wired to base INTC
+ ? ? ?*/
+ ? ? mux_intc4: interrupt-controller at d4282150 {
+ ? ? ? ? ? ? compatible = "mrvl,mmp2-mux-intc";
+ ? ? ? ? ? ? #address-cells = <1>;
+ ? ? ? ? ? ? #size-cells = <1>;
+ ? ? ? ? ? ? reg = <0xd4282000 0x400>;
+
+ ? ? ? ? ? ? #interrupt-cells = <1>;
+ ? ? ? ? ? ? interrupt-controller;
+ ? ? ? ? ? ? interrupt-parent = <&mmp_intc>;
+
+ ? ? ? ? ? ? /* interrupt source '4' of parent INTC. */
+ ? ? ? ? ? ? interrupts = <4>;
+
+ ? ? ? ? ? ? /* 2 interrupts are supported in this INTC. */
+ ? ? ? ? ? ? mrvl,intc-numbers = <2>;
+
+ ? ? ? ? ? ? /* Status offset address of 0x150. */
+ ? ? ? ? ? ? mrvl,status-offset = <0x150>;
+
+ ? ? ? ? ? ? /* Mask offset address of 0x168. */
+ ? ? ? ? ? ? mrvl,mask-offset = <0x168>;
+
+ ? ? ? ? ? ? /* mfp register of 0xd401e2c4 & interrupt index of 1 */
+ ? ? ? ? ? ? mrvl,mfp-edge = <0xd401e2c4 1>;
+ ? ? };
+
+Example 3:
+ ? ? /*
+ ? ? ?* An interrupt generating device that is wired to an INTC.
+ ? ? ?*/
+ ? ? uart0: uart at d4030000 {
+ ? ? ? ? ? ? /* parent's '#interrupt-cells' property. */
+ ? ? ? ? ? ? interrupts = <27>;
+
+ ? ? ? ? ? ? /* The INTC that this device is wired to. */
+ ? ? ? ? ? ? interrupt-parent = <&mmp_intc>;
+ ? ? };
arch/arm/Kconfig +0 -0
index 17507b8..f18eb14 100644
@@ -542,6 +542,7 @@ config ARCH_MMP

? ? ? select ARCH_REQUIRE_GPIOLIB
? ? ? select CLKDEV_LOOKUP
? ? ? select GENERIC_CLOCKEVENTS
+ ? ? select GENERIC_IRQ_CHIP
? ? ? select HAVE_SCHED_CLOCK
? ? ? select TICK_ONESHOT
? ? ? select PLAT_PXA

arch/arm/mach-mmp/Makefile +0 -0
index 5c68382..e7862ea 100644
@@ -4,6 +4,8 @@
 

?obj-y ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?+= common.o clock.o devices.o time.o

Quoted 9 lines

arch/arm/mach-mmp/Makefile

Quoted 2 lines
arch/arm/mach-mmp/Makefile +2 -0
+obj-$(CONFIG_OF_IRQ) ? ? ? ? += intc.o
+

I'm still really confused about why an entirely new interrupt controller file is being added. ?Drivers already exist in mach-mmp for the mux and pxa168 interrupt controllers, but this adds a whole new driver. ?I would expect the existing drivers should be refactored to use irq generic chip, and then extend them to add DT support.

Before applying this patch, two irq (irq-pxa168.c & irq-mmp2.c) exists. The block issue of merging them together is different register. Now DT can resolve different register. I'm planning to remove both of irq-pxa168.c & irq-mmp2.c after these DT patches.

Quoted 18 lines
Quoted 18 lines

?# SoC support
?obj-$(CONFIG_CPU_PXA168) ? ? += pxa168.o irq-pxa168.o ?obj-$(CONFIG_CPU_PXA910) ? ? += pxa910.o irq-pxa168.o

arch/arm/mach-mmp/common.h +1 -0
index ec8d65d..1c563c2 100644
@@ -6,3 +6,4 @@ extern void timer_init(int irq);
 
 ?extern void __init icu_init_irq(void);
 ?extern void __init mmp_map_io(void);
+extern void __init mmp_init_intc(void);
arch/arm/mach-mmp/include/mach/irqs.h +0 -0
index a09d328..65ec176 100644
@@ -224,6 +224,6 @@
 
Quoted 9 lines

arch/arm/mach-mmp/include/mach/irqs.h line 227

Quoted 4 lines
arch/arm/mach-mmp/include/mach/irqs.h +1 -1
 ?#define IRQ_BOARD_START ? ? ? ? ? ? ? ? ? ? ?(IRQ_GPIO_START + IRQ_GPIO_NUM)
 
-#define NR_IRQS ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(IRQ_BOARD_START)
+#define NR_IRQS ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0

Why is NR_IRQs getting changed? ?I think this will break !CONFIG_SPARSE_IRQS, and it shouldn't be necessary for this conversion.

If CONFIG_SPARSE_IRQ is enabled, arch_probe_nr_irqs() returns NR_IRQS in arm. It results registering NR_IRQS in early_irq_init(). If NR_IRQS is 200, 200 irqs are
registered in early_irq_init(). It's not my requirement. What I need is registering irq
from DT.

So I have to define NR_IRQS to 0. And CONFIG_SPARSE_IRQS is always enabled in ARCH_MMP. So it's selected in Kconfig by default.

Quoted 241 lines
Quoted 240 lines
arch/arm/mach-mmp/include/mach/irqs.h +0 -1
--
 Regards,

Shawn

?#endif /* __ASM_MACH_IRQS_H */

arch/arm/mach-mmp/intc.c new file +224 -1
new file mode 100644
index 0000000..2e44057
@@ -0,0 +1,224 @@
+/*
+ * ?linux/arch/arm/mach-mmp/intc.c
+ *
+ * ?Generic IRQ handling
+ *
+ * ?Author: ?Haojian Zhuang <[email protected]>
+ * ?Copyright: ? ? ? Marvell International Ltd. 2011
+ *
+ * ?This program is free software; you can redistribute it and/or modify
+ * ?it under the terms of the GNU General Public License version 2 as
+ * ?published by the Free Software Foundation.
+ */
+
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+
+struct mmp_intc_info {
+ ? ? unsigned int ? ? ? ? ? ?en_mask;
+ ? ? void __iomem ? ? ? ? ? ?*virt_base;
+ ? ? void __iomem ? ? ? ? ? ?*status;
+ ? ? void __iomem ? ? ? ? ? ?*mfp_edge;
+ ? ? unsigned int ? ? ? ? ? ?mfp_edge_index; /* index in irq domain */
+};
+
+static void mux_irq_ack(struct irq_data *d)
+{
+ ? ? struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ ? ? struct irq_chip_type *ct;
+ ? ? struct mmp_intc_info *info;
+ ? ? unsigned int data, irq_offs;
+
+ ? ? ct = gc->chip_types;
+ ? ? info = (struct mmp_intc_info *)ct->regs.ack;
+ ? ? irq_offs = d->irq - gc->irq_base;
+ ? ? /* clear MFP edge-detect */
+ ? ? if (info->mfp_edge && (info->mfp_edge_index == irq_offs)) {
+ ? ? ? ? ? ? data = __raw_readl(info->mfp_edge);
+ ? ? ? ? ? ? __raw_writel(data | (1 << 6), info->mfp_edge);
+ ? ? ? ? ? ? __raw_writel(data, info->mfp_edge);
+ ? ? }
+}
+
+static void mmp_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
+{
+ ? ? struct irq_chip_generic *gc = irq_get_handler_data(irq);
+ ? ? struct irq_chip_type *ct;
+ ? ? struct mmp_intc_info *info;
+ ? ? unsigned long status, n;
+
+ ? ? ct = gc->chip_types;
+ ? ? info = (struct mmp_intc_info *)ct->regs.ack;
+ ? ? while (1) {
+ ? ? ? ? ? ? status = __raw_readl(info->status) & ~gc->mask_cache;
+ ? ? ? ? ? ? if (status == 0)
+ ? ? ? ? ? ? ? ? ? ? break;
+ ? ? ? ? ? ? n = find_first_bit(&status, BITS_PER_LONG);
+ ? ? ? ? ? ? while (n < BITS_PER_LONG) {
+ ? ? ? ? ? ? ? ? ? ? generic_handle_irq(gc->irq_base + n);
+ ? ? ? ? ? ? ? ? ? ? n = find_next_bit(&status, BITS_PER_LONG, n + 1);
+ ? ? ? ? ? ? }
+ ? ? }
+}
+
+static void mux_init_intc(struct mmp_intc_info *mmp_info)
+{
+ ? ? struct device_node *np;
+ ? ? struct mmp_intc_info *mux_info;
+ ? ? struct irq_chip_generic *gc;
+ ? ? struct irq_chip_type *ct;
+ ? ? const __be32 *edge;
+ ? ? unsigned int addr = 0, offs = 0;
+ ? ? unsigned int status, mask, irq_base, nr, data;
+ ? ? int cascade;
+
+ ? ? for_each_compatible_node(np, NULL, "mrvl,mmp2-mux-intc") {
+ ? ? ? ? ? ? if (of_get_property(np, "interrupt-controller", NULL) == NULL)
+ ? ? ? ? ? ? ? ? ? ? continue;
+ ? ? ? ? ? ? if (of_property_read_u32(np, "mrvl,intc-numbers", &nr) < 0) {
+ ? ? ? ? ? ? ? ? ? ? pr_warn("intc-numbers property is missed\n");
+ ? ? ? ? ? ? ? ? ? ? continue;
+ ? ? ? ? ? ? }
+ ? ? ? ? ? ? if (of_property_read_u32(np, "mrvl,status-offset", &status)
+ ? ? ? ? ? ? ? ? ? ? < 0) {
+ ? ? ? ? ? ? ? ? ? ? pr_warn("intc-status property is missed\n");
+ ? ? ? ? ? ? ? ? ? ? continue;
+ ? ? ? ? ? ? }
+ ? ? ? ? ? ? if (of_property_read_u32(np, "mrvl,mask-offset", &mask) < 0) {
+ ? ? ? ? ? ? ? ? ? ? pr_warn("intc-mask property is missed\n");
+ ? ? ? ? ? ? ? ? ? ? continue;
+ ? ? ? ? ? ? }
+
+ ? ? ? ? ? ? mux_info = kzalloc(sizeof(*mux_info), GFP_KERNEL);
+ ? ? ? ? ? ? if (mux_info == NULL)
+ ? ? ? ? ? ? ? ? ? ? goto out;
+ ? ? ? ? ? ? status += (unsigned int)mmp_info->virt_base;
+ ? ? ? ? ? ? mux_info->status = (void __iomem *)status;
+
+ ? ? ? ? ? ? edge = of_get_property(np, "mrvl,mfp-edge", NULL);
+ ? ? ? ? ? ? if (edge) {
+ ? ? ? ? ? ? ? ? ? ? addr = be32_to_cpu(*edge) & PAGE_MASK;
+ ? ? ? ? ? ? ? ? ? ? offs = be32_to_cpu(*edge) - addr;
+ ? ? ? ? ? ? ? ? ? ? mux_info->mfp_edge = ioremap(addr, PAGE_SIZE) + offs;
+ ? ? ? ? ? ? ? ? ? ? mux_info->mfp_edge_index = be32_to_cpu(*++edge);
+ ? ? ? ? ? ? ? ? ? ? /* clear mfp edge detection for initialization */
+ ? ? ? ? ? ? ? ? ? ? data = __raw_readl(mux_info->mfp_edge);
+ ? ? ? ? ? ? ? ? ? ? __raw_writel(data | (1 << 6), mux_info->mfp_edge);
+ ? ? ? ? ? ? ? ? ? ? __raw_writel(data, mux_info->mfp_edge);
+ ? ? ? ? ? ? }
+
+ ? ? ? ? ? ? /* allocate new irq */
+ ? ? ? ? ? ? cascade = irq_of_parse_and_map(np, 0);
+ ? ? ? ? ? ? irq_base = irq_alloc_descs(-1, 0, nr, 0);
+ ? ? ? ? ? ? irq_domain_add_simple(np, irq_base);
+
+ ? ? ? ? ? ? gc = irq_alloc_generic_chip("mux-intc", 1, irq_base,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mmp_info->virt_base, handle_level_irq);
+ ? ? ? ? ? ? ct = gc->chip_types;
+ ? ? ? ? ? ? ct->regs.ack = (unsigned int)mux_info;
+ ? ? ? ? ? ? ct->regs.mask = mask;
+ ? ? ? ? ? ? ct->chip.irq_ack = mux_irq_ack;
+ ? ? ? ? ? ? ct->chip.irq_mask = irq_gc_mask_set_bit;
+ ? ? ? ? ? ? ct->chip.irq_unmask = irq_gc_mask_clr_bit;
+ ? ? ? ? ? ? irq_setup_generic_chip(gc, IRQ_MSK(nr), IRQ_GC_INIT_MASK_CACHE,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+
+ ? ? ? ? ? ? irq_set_handler_data(cascade, gc);
+ ? ? ? ? ? ? irq_set_chained_handler(cascade, mmp_irq_demux_handler);
+ ? ? }
+out:
+ ? ? return;
+}
+
+static void mmp_irq_unmask(struct irq_data *d)
+{
+ ? ? struct mmp_intc_info *info = irq_data_get_irq_chip_data(d);
+
+ ? ? /* ICU_INT_CONF */
+ ? ? __raw_writel(info->en_mask, info->virt_base + (d->irq << 2));
+}
+
+static void mmp_irq_mask(struct irq_data *d)
+{
+ ? ? struct mmp_intc_info *info = irq_data_get_irq_chip_data(d);
+
+ ? ? __raw_writel(0, info->virt_base + (d->irq << 2));
+}
+
+static struct irq_chip mmp_irq_chip = {
+ ? ? .name ? ? ? ? ? = "mmp-intc",
+ ? ? .irq_unmask ? ? = mmp_irq_unmask,
+ ? ? .irq_mask ? ? ? = mmp_irq_mask,
+ ? ? .irq_ack ? ? ? ?= mmp_irq_mask,
+};
+
+void __init mmp_init_intc(void)
+{
+ ? ? struct mmp_intc_info *info;
+ ? ? struct device_node *np;
+ ? ? struct resource rs;
+ ? ? unsigned int cells, nr, enable, irq_base;
+ ? ? int i;
+
+ ? ? np = of_find_compatible_node(NULL, NULL, "mrvl,pxa168-intc");
+
+ ? ? BUG_ON(!np);
+
+ ? ? of_node_get(np);
+ ? ? if (of_get_property(np, "interrupt-controller", NULL) == NULL)
+ ? ? ? ? ? ? goto out;
+ ? ? if (of_property_read_u32(np, "#interrupt-cells", &cells) < 0) {
+ ? ? ? ? ? ? pr_warn("mmp-intc: interrupt-cells property is missed\n");
+ ? ? ? ? ? ? goto out;
+ ? ? }
+ ? ? if (cells != 1) {
+ ? ? ? ? ? ? pr_warn("mmp-intc: interrupt-cells property is incorrect\n");
+ ? ? ? ? ? ? goto out;
+ ? ? }
+ ? ? if (of_property_read_u32(np, "mrvl,intc-numbers", &nr) < 0) {
+ ? ? ? ? ? ? pr_warn("mmp-intc: mrvl,intc-numbers property is missed\n");
+ ? ? ? ? ? ? goto out;
+ ? ? }
+ ? ? if (of_property_read_u32(np, "mrvl,intc-priority", &enable) < 0) {
+ ? ? ? ? ? ? pr_warn("mmp-intc: mrvl,intc-priority property is missed\n");
+ ? ? ? ? ? ? goto out;
+ ? ? }
+ ? ? if (of_address_to_resource(np, 0, &rs) < 0) {
+ ? ? ? ? ? ? pr_warn("mmp-intc: invalid reg property\n");
+ ? ? ? ? ? ? goto out;
+ ? ? }
+
+ ? ? info = kzalloc(sizeof(struct mmp_intc_info), GFP_KERNEL);
+ ? ? if (info == NULL)
+ ? ? ? ? ? ? goto out;
+ ? ? info->en_mask = enable;
+ ? ? info->virt_base = ioremap(rs.start, PAGE_SIZE);
+ ? ? if (info->virt_base == NULL) {
+ ? ? ? ? ? ? pr_warn("mmp-intc: failed to remap reg base\n");
+ ? ? ? ? ? ? goto out_mem;
+ ? ? }
+
+ ? ? /* allocate new irq */
+ ? ? irq_base = irq_alloc_descs(-1, 0, nr, 0);
+ ? ? irq_domain_add_simple(np, 0);
+
+ ? ? for (i = irq_base; i < irq_base + nr; i++) {
+ ? ? ? ? ? ? irq_set_chip_data(i, info);
+ ? ? ? ? ? ? mmp_irq_mask(irq_get_irq_data(i));
+ ? ? ? ? ? ? irq_set_chip_and_handler(i, &mmp_irq_chip, handle_level_irq);
+ ? ? ? ? ? ? set_irq_flags(i, IRQF_VALID);
+ ? ? }
+ ? ? mux_init_intc(info);
+ ? ? of_node_put(np);
+ ? ? return;
+out_mem:
+ ? ? kfree(info);
+out:
+ ? ? of_node_put(np);
+ ? ? return;
+}
--

1.5.6.5

#23 lore raw

PATCH v2 1/7 ARM: mmp: parse irq from DT

Quoted 33 lines · Haojian Zhuang
Quoted 15 lines · Grant Likely
Quoted 15 lines
arch/arm/mach-mmp/common.h +1 -0
index ec8d65d..1c563c2 100644
@@ -6,3 +6,4 @@ extern void timer_init(int irq);
 
 ?extern void __init icu_init_irq(void);
 ?extern void __init mmp_map_io(void);
+extern void __init mmp_init_intc(void);
arch/arm/mach-mmp/include/mach/irqs.h +0 -0
index a09d328..65ec176 100644
@@ -224,6 +224,6 @@
 
Quoted 9 lines

arch/arm/mach-mmp/include/mach/irqs.h line 227

Quoted 4 lines
arch/arm/mach-mmp/include/mach/irqs.h +1 -1
 ?#define IRQ_BOARD_START ? ? ? ? ? ? ? ? ? ? ?(IRQ_GPIO_START + IRQ_GPIO_NUM)
 
-#define NR_IRQS ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(IRQ_BOARD_START)
+#define NR_IRQS ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0

Why is NR_IRQs getting changed? ?I think this will break !CONFIG_SPARSE_IRQS, and it shouldn't be necessary for this conversion.

If CONFIG_SPARSE_IRQ is enabled, arch_probe_nr_irqs() returns NR_IRQS in arm. It results registering NR_IRQS in early_irq_init(). If NR_IRQS is 200, 200 irqs are
registered in early_irq_init(). It's not my requirement. What I need is registering irq
from DT.

Quoted 2 lines

So I have to define NR_IRQS to 0. And CONFIG_SPARSE_IRQS is always enabled in ARCH_MMP. So it's selected in Kconfig by default.

My point is, that applying this patch will break anyone depending on non-DT mach-mmp support. I'm completely fine with you doing so, but you need to be extra careful that it is done in a bisectable way. At no point in the commit series should the kernel be unable to build a working mmp image.

g.

#24 lore raw

PATCH v2 1/7 ARM: mmp: parse irq from DT

Quoted 37 lines · Grant Likely
Quoted 33 lines · Haojian Zhuang
Quoted 15 lines · Grant Likely
Quoted 15 lines
arch/arm/mach-mmp/common.h +1 -0
index ec8d65d..1c563c2 100644
@@ -6,3 +6,4 @@ extern void timer_init(int irq);
 
 ?extern void __init icu_init_irq(void);
 ?extern void __init mmp_map_io(void);
+extern void __init mmp_init_intc(void);
arch/arm/mach-mmp/include/mach/irqs.h +0 -0
index a09d328..65ec176 100644
@@ -224,6 +224,6 @@
 
Quoted 9 lines

arch/arm/mach-mmp/include/mach/irqs.h line 227

Quoted 4 lines
arch/arm/mach-mmp/include/mach/irqs.h +1 -1
 ?#define IRQ_BOARD_START ? ? ? ? ? ? ? ? ? ? ?(IRQ_GPIO_START + IRQ_GPIO_NUM)
 
-#define NR_IRQS ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(IRQ_BOARD_START)
+#define NR_IRQS ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0

Why is NR_IRQs getting changed? ?I think this will break !CONFIG_SPARSE_IRQS, and it shouldn't be necessary for this conversion.

If CONFIG_SPARSE_IRQ is enabled, arch_probe_nr_irqs() returns NR_IRQS in arm. It results registering NR_IRQS in early_irq_init(). If NR_IRQS is 200, 200 irqs are
registered in early_irq_init(). It's not my requirement. What I need is registering irq
from DT.

Quoted 2 lines

So I have to define NR_IRQS to 0. And CONFIG_SPARSE_IRQS is always enabled in ARCH_MMP. So it's selected in Kconfig by default.

Quoted 9 lines

My point is, that applying this patch will break anyone depending on non-DT mach-mmp support. ?I'm completely fine with you doing so, but you need to be extra careful that it is done in a bisectable way. ?At no point in the commit series should the kernel be unable to build a working mmp image.

g.

Since .nr_irqs property is assigned in machine descriptor of brownstone.c or ttc_dkb.c, nr_irqs equals to machine_desc->nr_irqs (arch/arm/kernel/irq.c).

Even NR_IRQS is defined as 0, machine_desc->nr_irqs can help us to pre-allocate irq numbers while CONFIG_OF isn't defined.

So it's not an issue in ARCH_MMP. And I tested it that everything is well.

Thanks
Haojian

#25 lore raw

PATCH v2 1/7 ARM: mmp: parse irq from DT

Quoted 48 lines · Haojian Zhuang
Quoted 37 lines · Grant Likely
Quoted 33 lines · Haojian Zhuang
Quoted 15 lines · Grant Likely
Quoted 15 lines
arch/arm/mach-mmp/common.h +1 -0
index ec8d65d..1c563c2 100644
@@ -6,3 +6,4 @@ extern void timer_init(int irq);
 
 ?extern void __init icu_init_irq(void);
 ?extern void __init mmp_map_io(void);
+extern void __init mmp_init_intc(void);
arch/arm/mach-mmp/include/mach/irqs.h +0 -0
index a09d328..65ec176 100644
@@ -224,6 +224,6 @@
 
Quoted 9 lines

arch/arm/mach-mmp/include/mach/irqs.h line 227

Quoted 4 lines
arch/arm/mach-mmp/include/mach/irqs.h +1 -1
 ?#define IRQ_BOARD_START ? ? ? ? ? ? ? ? ? ? ?(IRQ_GPIO_START + IRQ_GPIO_NUM)
 
-#define NR_IRQS ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(IRQ_BOARD_START)
+#define NR_IRQS ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0

Why is NR_IRQs getting changed? ?I think this will break !CONFIG_SPARSE_IRQS, and it shouldn't be necessary for this conversion.

If CONFIG_SPARSE_IRQ is enabled, arch_probe_nr_irqs() returns NR_IRQS in arm. It results registering NR_IRQS in early_irq_init(). If NR_IRQS is 200, 200 irqs are
registered in early_irq_init(). It's not my requirement. What I need is registering irq
from DT.

Quoted 2 lines

So I have to define NR_IRQS to 0. And CONFIG_SPARSE_IRQS is always enabled in ARCH_MMP. So it's selected in Kconfig by default.

Quoted 9 lines

My point is, that applying this patch will break anyone depending on non-DT mach-mmp support. ?I'm completely fine with you doing so, but you need to be extra careful that it is done in a bisectable way. ?At no point in the commit series should the kernel be unable to build a working mmp image.

g.

Quoted 7 lines

Since .nr_irqs property is assigned in machine descriptor of brownstone.c or ttc_dkb.c, nr_irqs equals to machine_desc->nr_irqs (arch/arm/kernel/irq.c).

Even NR_IRQS is defined as 0, machine_desc->nr_irqs can help us to pre-allocate irq numbers while CONFIG_OF isn't defined.

So it's not an issue in ARCH_MMP. And I tested it that everything is well.

Okay, that answers my question. Thanks.

g.

#26 lore raw

PATCH v2 1/7 ARM: mmp: parse irq from DT

In reply to Haojian Zhuang
Quoted 3 lines · Haojian Zhuang
arch/arm/mach-mmp/intc.c new file +3 -0
+	unsigned int status, mask, irq_base, nr, data;
+	int cascade;
+

...

arch/arm/mach-mmp/intc.c line 101

Quoted 5 lines
arch/arm/mach-mmp/intc.c new file +5 -0
+		mux_info = kzalloc(sizeof(*mux_info), GFP_KERNEL);
+		if (mux_info == NULL)
+			goto out;
+		status += (unsigned int)mmp_info->virt_base;
+		mux_info->status = (void __iomem *)status;

This is silly. Why not just do:

		mux_info->status = mmp_info->virt_base + status;

and avoid those horrible casts?