enable devicetree on arch-mmp
Subsystems (7)
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
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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
@@ -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
@@ -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
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
@@ -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
@@ -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
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
@@ -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
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
@@ -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
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
@@ -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
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
@@ -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
@@ -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
PATCH v2 6/7 i2c: pxa: support i2c controller from DT
In reply to Haojian ZhuangQuoted 61 lines · Haojian Zhuang
support i2c-pxa controller from DT.
Signed-off-by Haojian Zhuang <[email protected]>--- drivers/i2c/busses/i2c-pxa.c | 51 +++++++++++++++++++++++++++++++---------- 1 files changed, 38 insertions(+), 13 deletions(-)drivers/i2c/busses/i2c-pxa.c +21
-6@@ -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
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?
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
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.
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.
PATCH v2 4/7 tty: serial: support device tree in pxa
In reply to Haojian ZhuangQuoted 76 lines · Haojian Zhuang
Support both normal platform driver and device tree driver in serial pxa.
Signed-off-by Haojian Zhuang <[email protected]>--- drivers/tty/serial/pxa.c | 51 ++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 45 insertions(+), 6 deletions(-)drivers/tty/serial/pxa.c +31
-2@@ -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
-4sport->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
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.
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.
PATCH v2 4/7 tty: serial: support device tree in pxa
In reply to Russell King - ARM LinuxQuoted 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);
? ? ? ? ? ? gotoerr_free;
? ? }
+ ?sport->port.uartclk=clk_get_rate(sport->clk); +#endifThis 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
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.
PATCH v2 3/7 ARM: mmp: support DT on both dkb and brownstone
In reply to Haojian ZhuangQuoted 467 lines · Haojian Zhuang
Add new
boards.cto support both TTC-DKB and MMP2-BROWNSTONE. IfCONFIG_OFisn't selected, we continue to use originalttc_dkb.candbrownstone.c.While everything moving to DT in ARCH-MMP,
ttc_dkb.candbrownstone.cwill be abandoned.Signed-off-by Haojian Zhuang <[email protected]>--- .../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.cDocumentation/devicetree/bindings/arm/marvell/boards.txt new file +7
-0@@ -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@@ -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@@ -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@@ -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.oarch/arm/mach-mmp/boards.c new file +108
-0@@ -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
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.cto support both TTC-DKB and MMP2-BROWNSTONE. IfCONFIG_OFisn't selected, we continue to use originalttc_dkb.candbrownstone.c.While everything moving to DT in ARCH-MMP,
ttc_dkb.candbrownstone.cwill be abandoned.Signed-off-by Haojian Zhuang <[email protected]>---
?.../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 100644Documentation/devicetree/bindings/arm/marvell/boards.txt?create mode 100644arch/arm/boot/dts/mmp2-brownstone.dts?create mode 100644arch/arm/boot/dts/pxa910-dkb.dts
?create mode 100644arch/arm/mach-mmp/boards.cDocumentation/devicetree/bindings/arm/marvell/boards.txt new file +7
-0@@ -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@@ -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@@ -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@@ -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.oarch/arm/mach-mmp/boards.c new file +112
-0@@ -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
PATCH v2 2/7 ARM: mmp: parse timer configuration from DT
In reply to Haojian ZhuangQuoted 90 lines · Haojian Zhuang
Parse timer configuration from DT. Now we can merge
pxa910_timerandmmp2_timerintommp_timer. Since most configuration between these two timers are same. The difference is recorded in DT.Signed-off-by Haojian Zhuang <[email protected]>--- .../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.txtDocumentation/devicetree/bindings/arm/marvell/timer.txt new file +24
-0@@ -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@@ -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@@ -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
PATCH v2 1/7 ARM: mmp: parse irq from DT
In reply to Haojian ZhuangQuoted 153 lines · Haojian Zhuang
Parse irq sepcifier from DT and translate it to Linux irq number. Remove the definition of
NR_IRQSinirqs.h. Since sparse irq is enabled,nr_irqswill be calculated automatically.Signed-off-by Haojian Zhuang <[email protected]>--- .../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.cDocumentation/devicetree/bindings/arm/marvell/intc.txt new file +114
-0@@ -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@@ -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_PXAarch/arm/mach-mmp/Makefile +0
-0
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.oarch/arm/mach-mmp/common.h +1
-0@@ -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
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@@ -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
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_IRQSinirqs.h. Since sparse irq is enabled,nr_irqswill be calculated automatically.Signed-off-by Haojian Zhuang <[email protected]>---
?.../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 100644Documentation/devicetree/bindings/arm/marvell/intc.txt?create mode 100644arch/arm/mach-mmp/intc.cDocumentation/devicetree/bindings/arm/marvell/intc.txt new file +114
-0@@ -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@@ -542,6 +542,7 @@ config ARCH_MMP? ? ? select
ARCH_REQUIRE_GPIOLIB
? ? ? selectCLKDEV_LOOKUP
? ? ? selectGENERIC_CLOCKEVENTS
+ ? ? selectGENERIC_IRQ_CHIP
? ? ? selectHAVE_SCHED_CLOCK
? ? ? selectTICK_ONESHOT
? ? ? selectPLAT_PXAarch/arm/mach-mmp/Makefile +0
-0@@ -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.oarch/arm/mach-mmp/common.h +1
-0@@ -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@@ -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 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0Why is
NR_IRQsgetting 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@@ -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
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@@ -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@@ -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 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0Why is
NR_IRQsgetting changed? ?I think this will break !CONFIG_SPARSE_IRQS, and it shouldn't be necessary for this conversion.If
CONFIG_SPARSE_IRQis enabled,arch_probe_nr_irqs()returnsNR_IRQSin arm. It results registeringNR_IRQSinearly_irq_init(). IfNR_IRQSis 200, 200 irqs are
registered inearly_irq_init(). It's not my requirement. What I need is registering irq
from DT.
Quoted 2 lines
So I have to define
NR_IRQSto 0. AndCONFIG_SPARSE_IRQSis always enabled inARCH_MMP. So it's selected inKconfigby 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.
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@@ -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@@ -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 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0Why is
NR_IRQsgetting changed? ?I think this will break !CONFIG_SPARSE_IRQS, and it shouldn't be necessary for this conversion.If
CONFIG_SPARSE_IRQis enabled,arch_probe_nr_irqs()returnsNR_IRQSin arm. It results registeringNR_IRQSinearly_irq_init(). IfNR_IRQSis 200, 200 irqs are
registered inearly_irq_init(). It's not my requirement. What I need is registering irq
from DT.Quoted 2 lines
So I have to define
NR_IRQSto 0. AndCONFIG_SPARSE_IRQSis always enabled inARCH_MMP. So it's selected inKconfigby 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
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@@ -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@@ -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 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0Why is
NR_IRQsgetting changed? ?I think this will break !CONFIG_SPARSE_IRQS, and it shouldn't be necessary for this conversion.If
CONFIG_SPARSE_IRQis enabled,arch_probe_nr_irqs()returnsNR_IRQSin arm. It results registeringNR_IRQSinearly_irq_init(). IfNR_IRQSis 200, 200 irqs are
registered inearly_irq_init(). It's not my requirement. What I need is registering irq
from DT.Quoted 2 lines
So I have to define
NR_IRQSto 0. AndCONFIG_SPARSE_IRQSis always enabled inARCH_MMP. So it's selected inKconfigby 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.corttc_dkb.c,nr_irqsequals tomachine_desc->nr_irqs(arch/arm/kernel/irq.c).Even
NR_IRQSis defined as 0,machine_desc->nr_irqscan help us to pre-allocate irq numbers whileCONFIG_OFisn'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.
PATCH v2 1/7 ARM: mmp: parse irq from DT
In reply to Haojian ZhuangQuoted 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?