Skip to contentSkip to conversation

Few more patches for Kumar's powerpc.git

PATCH Superseded Anton Vorontsov 6 participants 26 messages Apr 18, 2008 – Apr 21, 2008

Subsystems (5)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

v2 cover Few more patches for Kumar's powerpc.git

Hello Kumar,

This is the second try...

Signature · 3 lines
Anton Vorontsov
email: [email protected]
irc://irc.freenode.net/bd2
#1 lore raw

PATCH v2 1/5 sysdev: implement FSL GTM support

GTM stands for General-purpose Timers Module and able to generate timer{1,2,3,4} interrupts. These timers are used by the drivers that need time precise interrupts (like for USB transactions scheduling for the Freescale USB Host controller as found in some QE and CPM chips), or these timers could be used as wakeup events from the CPU deep-sleep mode.

Things unimplemented:
1. Cascaded (32 bit) timers (1-2, 3-4).
This is straightforward to implement when needed, two timers should be marked as "requested" and configured as appropriate.
2. Super-cascaded (64 bit) timers (1-2-3-4).
This is also straightforward to implement when needed, all timers should be marked as "requested" and configured as appropriate.

---
 Documentation/powerpc/booting-without-of.txt |   32 +++-
 arch/powerpc/Kconfig                         |    5 +
 arch/powerpc/sysdev/Makefile                 |    1 +
 arch/powerpc/sysdev/fsl_gtm.c                |  365 ++++++++++++++++++++++++++
 include/asm-powerpc/fsl_gtm.h                |  108 ++++++++
 5 files changed, 510 insertions(+), 1 deletions(-)
 create mode 100644 arch/powerpc/sysdev/fsl_gtm.c
 create mode 100644 include/asm-powerpc/fsl_gtm.h
Documentation/powerpc/booting-without-of.txt +31 -1
index 4cc7800..827b630 100644
@@ -57,7 +57,8 @@ Table of Contents
       n) 4xx/Axon EMAC ethernet nodes
       o) Xilinx IP cores
       p) Freescale Synchronous Serial Interface
-	  q) USB EHCI controllers
+      q) USB EHCI controllers
+      r) Freescale General-purpose Timers Module
 
   VII - Marvell Discovery mv64[345]6x System Controller chips
     1) The /system-controller node
@@ -2825,6 +2826,35 @@ platforms are moved over to use the flattened-device-tree model.
 		   big-endian;
 	   };
 
+    r) Freescale General-purpose Timers Module
+
+    Required properties:
+      - compatible : should be "fsl,gtm" ("fsl,qe-gtm" in addition for QE
+                     GTMs or "fsl,cpm2-gtm" for CPM2 GTMs).
+      - reg : should contain gtm registers location and length (0x40).
+      - interrupts : should contain four interrupts.
+      - interrupt-parent : interrupt source phandle.
+      - clock-frequency : specifies the frequency driving the timer.
+
+    Example:
+
+    timer@500 {
+    	compatible = "fsl,gtm";
+    	reg = <0x500 0x40>;
+    	interrupts = <90 8 78 8 84 8 72 8>;
+    	interrupt-parent = <&ipic>;
+    	/* filled by u-boot */
+    	clock-frequency = <0>;
+    };
+
+    timer@440 {
+    	compatible = "fsl,qe-gtm", "fsl,gtm";
+    	reg = <0x440 0x40>;
+    	interrupts = <12 13 14 15>;
+    	interrupt-parent = <&qeic>;
+    	/* filled by u-boot */
+    	clock-frequency = <0>;
+    };
 
 VII - Marvell Discovery mv64[345]6x System Controller chips
 ===========================================================
arch/powerpc/Kconfig +5 -0
index 7f2f126..ad874e4 100644
@@ -525,6 +525,11 @@ config FSL_LBC
 	help
 	  Freescale Localbus support
 
+config FSL_GTM
+	bool
+	help
+	  Freescale General-purpose Timers support
+
 # Yes MCA RS/6000s exist but Linux-PPC does not currently support any
 config MCA
 	bool
arch/powerpc/sysdev/Makefile +1 -0
index 6d386d0..9d3ddd2 100644
@@ -13,6 +13,7 @@ obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
 obj-$(CONFIG_FSL_PCI)		+= fsl_pci.o
 obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
+obj-$(CONFIG_FSL_GTM)		+= fsl_gtm.o
 obj-$(CONFIG_RAPIDIO)		+= fsl_rio.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
arch/powerpc/sysdev/fsl_gtm.c new file +365 -0

365 lines not on this page · raw message

include/asm-powerpc/fsl_gtm.h new file +108 -0

108 lines not on this page · raw message

Signature · 1 line
1.5.5
#2 lore raw

Re: [PATCH 1/5] [POWERPC] sysdev: implement FSL GTM support

2008/4/18 Anton Vorontsov <[email protected]>:

Quoted 6 lines

GTM stands for General-purpose Timers Module and able to generate
timer{1,2,3,4} interrupts. These timers are used by the drivers that need time precise interrupts (like for USB transactions scheduling for the Freescale USB Host controller as found in some QE and CPM chips), or these timers could be used as wakeup events from the CPU deep-sleep mode.

Comments below.

Quoted 1 line

diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentatio=

n/powerpc/booting-without-of.txt

Quoted 11 lines

index 4cc7800..827b630 100644
--- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt @@ -57,7 +57,8 @@ Table of Contents
n) 4xx/Axon EMAC ethernet nodes
o) Xilinx IP cores
p) Freescale Synchronous Serial Interface
- q) USB EHCI controllers
+ q) USB EHCI controllers
+ r) Freescale General-purpose Timers Module

Quoted 3 lines

VII - Marvell Discovery mv64[345]6x System Controller chips
1) The /system-controller node
@@ -2825,6 +2826,35 @@ platforms are moved over to use the flattened-dev=

ice-tree model.

Quoted 7 lines
                   big-endian;
           };

+ r) Freescale General-purpose Timers Module
+
+ Required properties:
+ - compatible : should be "fsl,gtm" ("fsl,qe-gtm" in addition for =

QE

Quoted 1 line

+ GTMs or "fsl,cpm2-gtm" for CPM2 GTMs).

I don't think this is specific enough. It is a very real possibility for Freescale to produce another part with a "general purpose timers module" that isn't register level compatible (and fsl,i2c is an example of what not to do). The compatible string should include the exact chip version. Newer parts can also claim compatibility with older ones.

Defining a 'generic' compatible value is also known as "making stuff up". = :-)

Quoted 23 lines
 +      - reg : should contain gtm registers location and length (0x40).
 +      - interrupts : should contain four interrupts.
 +      - interrupt-parent : interrupt source phandle.
 +      - clock-frequency : specifies the frequency driving the timer.
 +
 +    Example:
 +
 +    timer@500 {
 +       compatible =3D "fsl,gtm";
 +       reg =3D <0x500 0x40>;
 +       interrupts =3D <90 8 78 8 84 8 72 8>;
 +       interrupt-parent =3D <&ipic>;
 +       /* filled by u-boot */
 +       clock-frequency =3D <0>;
 +    };
 +
 +    timer@440 {
 +       compatible =3D "fsl,qe-gtm", "fsl,gtm";
 +       reg =3D <0x440 0x40>;
 +       interrupts =3D <12 13 14 15>;
 +       interrupt-parent =3D <&qeic>;
 +       /* filled by u-boot */
 +       clock-frequency =3D <0>;
Quoted 4 lines

+ };

VII - Marvell Discovery mv64[345]6x System Controller chips =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

Quoted 21 lines

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 7f2f126..ad874e4 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -525,6 +525,11 @@ config FSL_LBC
help
Freescale Localbus support

+config FSL_GTM
+ bool
+ help
+ Freescale General-purpose Timers support
+
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any config MCA
bool
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 6d386d0..9d3ddd2 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_MMIO_NVRAM) +=3D mmio_nvram.o

Quoted 8 lines
  obj-$(CONFIG_FSL_SOC)          +=3D fsl_soc.o
  obj-$(CONFIG_FSL_PCI)          +=3D fsl_pci.o
  obj-$(CONFIG_FSL_LBC)          +=3D fsl_lbc.o
 +obj-$(CONFIG_FSL_GTM)          +=3D fsl_gtm.o
  obj-$(CONFIG_RAPIDIO)          +=3D fsl_rio.o
  obj-$(CONFIG_TSI108_BRIDGE)    +=3D tsi108_pci.o tsi108_dev.o
  obj-$(CONFIG_QUICC_ENGINE)     +=3D qe_lib/

diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm=

.c

Quoted 7 lines

new file mode 100644
index 0000000..d29df56
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_gtm.c
@@ -0,0 +1,365 @@
+/*
+ * Freescale General-purpose Timers Module

Quoted 8 lines

+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ * Shlomi Gridish <[email protected]>
+ * Jerry Huang <[email protected]>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ * Anton Vorontsov <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modif=

y it

Quoted 1 line

+ * under the terms of the GNU General Public License as published by=

the

Quoted 1 line

+ * Free Software Foundation; either version 2 of the License, or (at =

your

Quoted 6 lines

+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>

Quoted 8 lines

+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <asm/fsl_gtm.h>
+
+/**
+ * gtm_get_timer - request GTM timer to use it with the rest of GTM API
+ * @width: timer width (only 16 bits wide timers implemented so far=

)

Quoted 29 lines

+ *
+ * This function reserves GTM timer for later use. It returns gtm_timer
+ * structure to use with the rest of GTM API, you should use timer->irq
+ * to manage timer interrupt.
+ */
+struct gtm_timer *gtm_get_timer(int width)
+{

 +       struct device_node *np;
 +       struct gtm *gtm =3D NULL;
 +       int i;
 +
 +       if (width !=3D 16)
 +               return ERR_PTR(-ENOSYS);
 +
 +       for_each_compatible_node(np, NULL, "fsl,gtm") {
 +               if (!np->data) {
 +                       WARN_ON(1);
 +                       continue;
 +               }
 +               gtm =3D np->data;
 +
 +               spin_lock_irq(&gtm->lock);
 +
 +               for (i =3D 0; i < ARRAY_SIZE(gtm->timers); i++) {
 +                       if (!gtm->timers[i].requested) {
 +                               gtm->timers[i].requested =3D true;
 +                               spin_unlock_irq(&gtm->lock);
 +                               of_node_put(np);
 +                               return &gtm->timers[i];
Quoted 11 lines

+ }
+ }
+
+ spin_unlock_irq(&gtm->lock);
+ }
+
+ if (gtm)
+ return ERR_PTR(-EBUSY);
+ return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL(gtm_get_timer);

This isn't a very efficient construct. You've already located all of the relevant nodes in the gtm_init() function. Searching the device tree is not efficient, so it should be avoided and only be performed once. Can you move the extraction of data from the tree to gtm_init() and only parse the drivers list of timers in this function?

Quoted 6 lines

+
+/**
+ * gtm_get_specific_timer - request specific GTM timer

 + * @gtm:       specific GTM, pass here GTM's device_node->data
 + * @timer:     specific timer number, Timer1 is 0.
 + * @width:     timer width (only 16 bits wide timers implemented so far=

)

Quoted 6 lines

+ *
+ * This function reserves GTM timer for later use. It returns gtm_timer
+ * structure to use with the rest of GTM API, you should use timer->irq
+ * to manage timer interrupt.
+ */
+struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, int timer, in=

t width)

Quoted 15 lines

+{
+ struct gtm_timer *ret =3D ERR_PTR(-EBUSY);
+
+ if (width !=3D 16)
+ return ERR_PTR(-ENOSYS);
+
+ spin_lock_irq(&gtm->lock);
+
+ if (gtm->timers[timer].requested)
+ goto out;
+
+ ret =3D &gtm->timers[timer];
+ ret->requested =3D true;
+
+out:

Quoted 8 lines

+ spin_unlock_irq(&gtm->lock);
+ return ret;
+}
+EXPORT_SYMBOL(gtm_get_specific_timer);
+
+/**
+ * gtm_put_timer - release GTM timer
+ * @width: timer width (only 16 bits wide timers implemented so far=

)

Quoted 7 lines

+ *
+ * This function releases GTM timer so others may request it.
+ */
+void gtm_put_timer(struct gtm_timer *tmr)
+{
+ spin_lock_irq(&tmr->gtm->lock);
+

Quoted 8 lines

+ tmr->requested =3D false;
+
+ spin_unlock_irq(&tmr->gtm->lock);
+}
+EXPORT_SYMBOL(gtm_put_timer);
+
+/*
+ * This is back-end for the exported functions, it's used to reset sing=

le

Quoted 13 lines

+ * timer in reference mode.
+ */
+static int gtm_reset_ref_timer16(struct gtm_timer *tmr, int frequency,
+ int reference_value, bool free_run)
+{

 +       struct gtm *gtm =3D tmr->gtm;
 +       int num =3D tmr - &gtm->timers[0];
 +       unsigned int prescaler;
 +       u8 iclk =3D GTMDR_ICLK_ICLK;
 +       u8 psr;
 +       u8 sps;
 +       unsigned long flags;
 +       int max_prescaler =3D 256 * 256 * 16;
Quoted 8 lines

+
+ /* CPM2 doesn't have primary prescaler */
+ if (!tmr->gtpsr)
+ max_prescaler /=3D 256;
+
+ prescaler =3D gtm->clock / frequency;
+ /*
+ * We have two 8 bit prescalers -- primary and secondary (psr, s=

ps),

Quoted 2 lines

+ * plus "slow go" mode (clk / 16). So, total prescale value is
+ * 16 * (psr + 1) * (sps + 1). Though, for CPM2 GTMs we losing p=

sr.

Quoted 13 lines

+ */
+ if (prescaler > max_prescaler)
+ return -EINVAL;
+
+ if (prescaler > max_prescaler / 16) {
+ iclk =3D GTMDR_ICLK_SLGO;
+ prescaler /=3D 16;
+ }
+
+ if (prescaler <=3D 256) {
+ psr =3D 0;
+ sps =3D prescaler - 1;
+ } else {

Quoted 8 lines

+ psr =3D 256 - 1;
+ sps =3D prescaler / 256 - 1;
+ }
+
+ spin_lock_irqsave(&gtm->lock, flags);
+
+ /*
+ * Properly reset timers: stop, reset, set up prescalers, refere=

nce

Quoted 14 lines

+ * value and clear event register.
+ */
+ clrsetbits_8(tmr->gtcfr, ~(GTCFR_STP(num) | GTCFR_RST(num)),
+ GTCFR_STP(num) | GTCFR_RST(num));
+
+ setbits8(tmr->gtcfr, GTCFR_STP(num));
+
+ if (tmr->gtpsr)
+ out_be16(tmr->gtpsr, psr);
+ clrsetbits_be16(tmr->gtmdr, 0xFFFF, iclk | GTMDR_SPS(sps) |
+ GTMDR_ORI | (free_run ? GTMDR_FRR : 0));

 +       out_be16(tmr->gtcnr, 0);
 +       out_be16(tmr->gtrfr, reference_value);
 +       out_be16(tmr->gtevr, 0xFFFF);
Quoted 11 lines

+
+ /* Let it be. */
+ clrbits8(tmr->gtcfr, GTCFR_STP(num));
+
+ spin_unlock_irqrestore(&gtm->lock, flags);
+
+ return 0;
+}
+/**
+ * gtm_reset_timer16 - reset 16 bit timer with arbitrary precision
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get=

_timer

Quoted 5 lines
 + * @usec:      timer interval in microseconds
 + * @reload:    if set, the timer will reset upon expiry rather than
 + *             continue running free.

+ *
+ * This function (re)sets the GTM timer so that it counts up to the req=

uested

Quoted 1 line

+ * interval value, and fires the interrupt when the value is reached. T=

his

Quoted 1 line

+ * function will reduce the precision of the timer as needed in order f=

or the

Quoted 3 lines

+ * requested timeout to fit in a 16-bit register.
+ */
+int gtm_reset_timer16(struct gtm_timer *tmr, unsigned long usec, bool r=

eload)

Quoted 2 lines

+{
+ /* quite obvious, frequency which is enough for =B5Sec precision=

*/

Quoted 11 lines

+ int freq =3D 1000000;
+ unsigned int bit;
+
+ bit =3D fls_long(usec);
+ if (bit > 15) {
+ freq >>=3D bit - 15;
+ usec >>=3D bit - 15;
+ }
+
+ if (!freq)
+ return -EINVAL;

Quoted 8 lines

+
+ return gtm_reset_ref_timer16(tmr, freq, usec, reload);
+}
+EXPORT_SYMBOL(gtm_reset_timer16);
+
+/**
+ * gtm_reset_utimer16 - reset 16 bits timer
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get=

_timer

Quoted 5 lines
 + * @usec:      timer interval in microseconds
 + * @reload:    if set, the timer will reset upon expiry rather than
 + *             continue running free.

+ *
+ * This function (re)sets GTM timer so that it counts up to the request=

ed

Quoted 1 line

+ * interval value, and fires the interrupt when the value is reached. I=

f reload

Quoted 1 line

+ * flag was set, timer will also reset itself upon reference value, oth=

erwise

Quoted 5 lines

+ * it continues to increment.
+ */
+int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool reload) +{
+ /* quite obvious, frequency which is enough for =B5Sec precision=

*/

Quoted 4 lines

+ const int freq =3D 1000000;
+
+ /*
+ * We can lower the frequency (and probably power consumption) b=

y

Quoted 1 line

+ * dividing both frequency and usec by 2 until there is no remai=

nder.

Quoted 1 line

+ * But we won't bother with this unless savings are measured, so=

just

Quoted 10 lines

+ * run the timer as is.
+ */
+
+ return gtm_reset_ref_timer16(tmr, freq, usec, reload);
+}
+EXPORT_SYMBOL(gtm_reset_utimer16);
+
+/**
+ * gtm_stop_timer16 - stop single timer
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get=

_timer

Quoted 8 lines

+ *
+ * This function simply stops the GTM timer.
+ */
+void gtm_stop_timer16(struct gtm_timer *tmr)
+{

 +       struct gtm *gtm =3D tmr->gtm;
 +       int num =3D tmr - &gtm->timers[0];
 +       unsigned long flags;
Quoted 13 lines

+
+ spin_lock_irqsave(&gtm->lock, flags);
+
+ setbits8(tmr->gtcfr, GTCFR_STP(num));
+ out_be16(tmr->gtevr, 0xFFFF);
+
+ spin_unlock_irqrestore(&gtm->lock, flags);
+}
+EXPORT_SYMBOL(gtm_stop_timer16);
+
+static void __init gtm_set_shortcuts(struct device_node *np,
+ struct gtm_timer *timers,
+ struct gtm_timers_regs __iomem *reg=

s)

Quoted 3 lines

+{
+ /*
+ * Yeah, I don't like this either, but timers' registers a bit m=

essed,

Quoted 1 line

+ * so we have to provide shortcuts to write timer independent co=

de.

Quoted 1 line

+ * Alternative option is to create gt*() accessors, but that wil=

l be

Quoted 44 lines

+ * even uglier and cryptic.
+ */

 +       timers[0].gtcfr =3D &regs->gtcfr1;
 +       timers[0].gtmdr =3D &regs->gtmdr1;
 +       timers[0].gtcnr =3D &regs->gtcnr1;
 +       timers[0].gtrfr =3D &regs->gtrfr1;
 +       timers[0].gtevr =3D &regs->gtevr1;
 +
 +       timers[1].gtcfr =3D &regs->gtcfr1;
 +       timers[1].gtmdr =3D &regs->gtmdr2;
 +       timers[1].gtcnr =3D &regs->gtcnr2;
 +       timers[1].gtrfr =3D &regs->gtrfr2;
 +       timers[1].gtevr =3D &regs->gtevr2;
 +
 +       timers[2].gtcfr =3D &regs->gtcfr2;
 +       timers[2].gtmdr =3D &regs->gtmdr3;
 +       timers[2].gtcnr =3D &regs->gtcnr3;
 +       timers[2].gtrfr =3D &regs->gtrfr3;
 +       timers[2].gtevr =3D &regs->gtevr3;
 +
 +       timers[3].gtcfr =3D &regs->gtcfr2;
 +       timers[3].gtmdr =3D &regs->gtmdr4;
 +       timers[3].gtcnr =3D &regs->gtcnr4;
 +       timers[3].gtrfr =3D &regs->gtrfr4;
 +       timers[3].gtevr =3D &regs->gtevr4;
 +
 +       /* CPM2 doesn't have primary prescaler */
 +       if (!of_device_is_compatible(np, "fsl,cpm2-gtm")) {
 +               timers[0].gtpsr =3D &regs->gtpsr1;
 +               timers[1].gtpsr =3D &regs->gtpsr2;
 +               timers[2].gtpsr =3D &regs->gtpsr3;
 +               timers[3].gtpsr =3D &regs->gtpsr4;
 +       }
 +}
 +
 +static int __init gtm_init(void)
 +{
 +       struct device_node *np;
 +
 +       for_each_compatible_node(np, NULL, "fsl,gtm") {
 +               int i;
 +               struct gtm *gtm;
 +               const u32 *clock;
 +               int size;
Quoted 13 lines

+
+ gtm =3D kzalloc(sizeof(*gtm), GFP_KERNEL);
+ if (!gtm) {
+ pr_err("%s: unable to allocate memory\n",
+ np->full_name);
+ continue;
+ }
+
+ spin_lock_init(&gtm->lock);
+
+ clock =3D of_get_property(np, "clock-frequency", &size);
+ if (!clock || size !=3D sizeof(*clock)) {
+ pr_err("%s: no clock-frequency\n", np->full_name=

);

Quoted 11 lines

+ goto err;
+ }
+ gtm->clock =3D *clock;
+
+ for (i =3D 0; i < ARRAY_SIZE(gtm->timers); i++) {
+ int ret;
+ struct resource irq;
+
+ ret =3D of_irq_to_resource(np, i, &irq);
+ if (ret =3D=3D NO_IRQ) {
+ pr_err("%s: not enough interrupts specif=

ied\n",

Quoted 19 lines

+ np->full_name);
+ goto err;

 +                       }
 +                       gtm->timers[i].irq =3D irq.start;
 +                       gtm->timers[i].gtm =3D gtm;
 +               }
 +
 +               gtm->regs =3D of_iomap(np, 0);
 +               if (!gtm->regs) {
 +                       pr_err("%s: unable to iomap registers\n",
 +                              np->full_name);
 +                       goto err;
 +               }
 +
 +               gtm_set_shortcuts(np, gtm->timers, gtm->regs);
 +
 +               /* We don't want to lose the node and its ->data */
 +               of_node_get(np);
 +               np->data =3D gtm;
Quoted 9 lines

+
+ continue;
+err:
+ kfree(gtm);
+ }
+ return 0;
+}
+arch_initcall(gtm_init);
diff --git a/include/asm-powerpc/fsl_gtm.h b/include/asm-powerpc/fsl_gtm=

.h

Quoted 7 lines

new file mode 100644
index 0000000..3eafb21
--- /dev/null
+++ b/include/asm-powerpc/fsl_gtm.h
@@ -0,0 +1,108 @@
+/*
+ * Freescale General-purpose Timers Module

Quoted 8 lines

+ *
+ * Copyright (c) Freescale Semicondutor, Inc. 2006.
+ * Shlomi Gridish <[email protected]>
+ * Jerry Huang <[email protected]>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ * Anton Vorontsov <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modif=

y it

Quoted 1 line

+ * under the terms of the GNU General Public License as published by=

the

Quoted 1 line

+ * Free Software Foundation; either version 2 of the License, or (at =

your

Quoted 20 lines

+ * option) any later version.
+ */
+
+#ifndef __ASM_FSL_GTM_H
+#define __ASM_FSL_GTM_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+
+#define GTCFR_STP(x) ((x) & 1 ? 1 << 5 : 1 << 1)
+#define GTCFR_RST(x) ((x) & 1 ? 1 << 4 : 1 << 0)
+

 +#define GTMDR_ICLK_MASK                (3 << 1)
 +#define GTMDR_ICLK_ICAS                (0 << 1)
 +#define GTMDR_ICLK_ICLK                (1 << 1)
 +#define GTMDR_ICLK_SLGO                (2 << 1)
 +#define GTMDR_FRR              (1 << 3)
 +#define GTMDR_ORI              (1 << 4)
 +#define GTMDR_SPS(x)           ((x) << 8)
Quoted 3 lines

+
+struct gtm_timers_regs {
+ u8 gtcfr1; /* Timer 1, Timer 2 global config regist=

er */

Quoted 2 lines
 +       u8      res0[0x3];
 +       u8      gtcfr2;         /* Timer 3, timer 4 global config regist=

er */

Quoted 46 lines
 +       u8      res1[0xB];
 +       __be16  gtmdr1;         /* Timer 1 mode register */
 +       __be16  gtmdr2;         /* Timer 2 mode register */
 +       __be16  gtrfr1;         /* Timer 1 reference register */
 +       __be16  gtrfr2;         /* Timer 2 reference register */
 +       __be16  gtcpr1;         /* Timer 1 capture register */
 +       __be16  gtcpr2;         /* Timer 2 capture register */
 +       __be16  gtcnr1;         /* Timer 1 counter */
 +       __be16  gtcnr2;         /* Timer 2 counter */
 +       __be16  gtmdr3;         /* Timer 3 mode register */
 +       __be16  gtmdr4;         /* Timer 4 mode register */
 +       __be16  gtrfr3;         /* Timer 3 reference register */
 +       __be16  gtrfr4;         /* Timer 4 reference register */
 +       __be16  gtcpr3;         /* Timer 3 capture register */
 +       __be16  gtcpr4;         /* Timer 4 capture register */
 +       __be16  gtcnr3;         /* Timer 3 counter */
 +       __be16  gtcnr4;         /* Timer 4 counter */
 +       __be16  gtevr1;         /* Timer 1 event register */
 +       __be16  gtevr2;         /* Timer 2 event register */
 +       __be16  gtevr3;         /* Timer 3 event register */
 +       __be16  gtevr4;         /* Timer 4 event register */
 +       __be16  gtpsr1;         /* Timer 1 prescale register */
 +       __be16  gtpsr2;         /* Timer 2 prescale register */
 +       __be16  gtpsr3;         /* Timer 3 prescale register */
 +       __be16  gtpsr4;         /* Timer 4 prescale register */
 +       u8 res2[0x40];
 +} __attribute__ ((packed));
 +
 +struct gtm_timer {
 +       unsigned int irq;
 +
 +       struct gtm *gtm;
 +       bool requested;
 +       u8 __iomem *gtcfr;
 +       __be16 __iomem *gtmdr;
 +       __be16 __iomem *gtpsr;
 +       __be16 __iomem *gtcnr;
 +       __be16 __iomem *gtrfr;
 +       __be16 __iomem *gtevr;
 +};
 +
 +struct gtm {
 +       unsigned int clock;
 +       struct gtm_timers_regs __iomem *regs;
 +       struct gtm_timer timers[4];
 +       spinlock_t lock;
Quoted 1 line

+};

Consider moving the register definitions and structures inside the .c file. This is all anonymous data as far as the caller is concerned. If the structures are only access inside the driver then you gain yourself a bit of safety by moving them.

Quoted 3 lines

+
+extern struct gtm_timer *gtm_get_timer(int width);
+extern struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, int ti=

mer,

Quoted 5 lines

+ int width);
+extern void gtm_put_timer(struct gtm_timer *tmr);
+extern int gtm_reset_timer16(struct gtm_timer *tmr, unsigned long usec,
+ bool reload);
+extern int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool rel=

oad);

Quoted 5 lines

+extern void gtm_stop_timer16(struct gtm_timer *tmr);
+
+/**
+ * gtm_ack_timer16 - acknowledge timer event (free-run timers only)
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get=

_timer

Quoted 3 lines

+ * @events: events mask to ack
+ *
+ * Thus function used to acknowledge timer interrupt event, use it insi=

de the

Quoted 6 lines

+ * interrupt handler.
+ */
+static inline void gtm_ack_timer16(struct gtm_timer *tmr, u16 events) +{
+ out_be16(tmr->gtevr, events);
+}

Drop 'inline' and expect gcc to do the right thing.

Quoted 9 lines

+
+#endif /* __ASM_FSL_GTM_H */
--
1.5.5

_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-dev

--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

#3 lore raw

Re: [PATCH 1/5] [POWERPC] sysdev: implement FSL GTM support

Quoted 34 lines · Grant Likely

2008/4/18 Anton Vorontsov <[email protected]>:

Quoted 6 lines

GTM stands for General-purpose Timers Module and able to generate
timer{1,2,3,4} interrupts. These timers are used by the drivers that need time precise interrupts (like for USB transactions scheduling for the Freescale USB Host controller as found in some QE and CPM chips), or these timers could be used as wakeup events from the CPU deep-sleep mode.

Comments below.

Quoted 15 lines

diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 4cc7800..827b630 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -57,7 +57,8 @@ Table of Contents
n) 4xx/Axon EMAC ethernet nodes
o) Xilinx IP cores
p) Freescale Synchronous Serial Interface
- q) USB EHCI controllers
+ q) USB EHCI controllers
+ r) Freescale General-purpose Timers Module

VII - Marvell Discovery mv64[345]6x System Controller chips
1) The /system-controller node
@@ -2825,6 +2826,35 @@ platforms are moved over to use the flattened-device-tree model.

Quoted 8 lines
                   big-endian;
           };

+ r) Freescale General-purpose Timers Module
+
+ Required properties:
+ - compatible : should be "fsl,gtm" ("fsl,qe-gtm" in addition for QE
+ GTMs or "fsl,cpm2-gtm" for CPM2 GTMs).

Quoted 6 lines

I don't think this is specific enough. It is a very real possibility for Freescale to produce another part with a "general purpose timers module" that isn't register level compatible (and fsl,i2c is an example of what not to do). The compatible string should include the exact chip version. Newer parts can also claim compatibility with older ones.

Ok, I'll expand this to fsl,<cpu-specific>-gtm and fsl,<cpu-specific>-{qe,cpm2}-gtm.

Quoted 130 lines

Defining a 'generic' compatible value is also known as "making stuff up". :-)

Quoted 116 lines
 +      - reg : should contain gtm registers location and length (0x40).
 +      - interrupts : should contain four interrupts.
 +      - interrupt-parent : interrupt source phandle.
 +      - clock-frequency : specifies the frequency driving the timer.
 +
 +    Example:
 +
 +    timer@500 {
 +       compatible = "fsl,gtm";
 +       reg = <0x500 0x40>;
 +       interrupts = <90 8 78 8 84 8 72 8>;
 +       interrupt-parent = <&ipic>;
 +       /* filled by u-boot */
 +       clock-frequency = <0>;
 +    };
 +
 +    timer@440 {
 +       compatible = "fsl,qe-gtm", "fsl,gtm";
 +       reg = <0x440 0x40>;
 +       interrupts = <12 13 14 15>;
 +       interrupt-parent = <&qeic>;
 +       /* filled by u-boot */
 +       clock-frequency = <0>;

+ };

VII - Marvell Discovery mv64[345]6x System Controller chips
===========================================================
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 7f2f126..ad874e4 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -525,6 +525,11 @@ config FSL_LBC
help
Freescale Localbus support

+config FSL_GTM
+ bool
+ help
+ Freescale General-purpose Timers support
+
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any config MCA
bool
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 6d386d0..9d3ddd2 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o

  obj-$(CONFIG_FSL_SOC)          += fsl_soc.o
  obj-$(CONFIG_FSL_PCI)          += fsl_pci.o
  obj-$(CONFIG_FSL_LBC)          += fsl_lbc.o
 +obj-$(CONFIG_FSL_GTM)          += fsl_gtm.o
  obj-$(CONFIG_RAPIDIO)          += fsl_rio.o
  obj-$(CONFIG_TSI108_BRIDGE)    += tsi108_pci.o tsi108_dev.o
  obj-$(CONFIG_QUICC_ENGINE)     += qe_lib/
 diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c
 new file mode 100644
 index 0000000..d29df56
 --- /dev/null
 +++ b/arch/powerpc/sysdev/fsl_gtm.c
 @@ -0,0 +1,365 @@
 +/*
 + * Freescale General-purpose Timers Module
 + *
 + * Copyright (c) Freescale Semicondutor, Inc. 2006.
 + *               Shlomi Gridish <[email protected]>
 + *               Jerry Huang <[email protected]>
 + * Copyright (c) MontaVista Software, Inc. 2008.
 + *               Anton Vorontsov <[email protected]>
 + *
 + * This program is free software; you can redistribute  it and/or modify it
 + * under  the terms of  the GNU General  Public License as published by the
 + * Free Software Foundation;  either version 2 of the  License, or (at your
 + * option) any later version.
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/errno.h>
 +#include <linux/io.h>
 +#include <linux/of.h>
 +#include <linux/spinlock.h>
 +#include <linux/bitops.h>
 +#include <asm/fsl_gtm.h>
 +
 +/**
 + * gtm_get_timer - request GTM timer to use it with the rest of GTM API
 + * @width:     timer width (only 16 bits wide timers implemented so far)
 + *
 + * This function reserves GTM timer for later use. It returns gtm_timer
 + * structure to use with the rest of GTM API, you should use timer->irq
 + * to manage timer interrupt.
 + */
 +struct gtm_timer *gtm_get_timer(int width)
 +{
 +       struct device_node *np;
 +       struct gtm *gtm = NULL;
 +       int i;
 +
 +       if (width != 16)
 +               return ERR_PTR(-ENOSYS);
 +
 +       for_each_compatible_node(np, NULL, "fsl,gtm") {
 +               if (!np->data) {
 +                       WARN_ON(1);
 +                       continue;
 +               }
 +               gtm = np->data;
 +
 +               spin_lock_irq(&gtm->lock);
 +
 +               for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
 +                       if (!gtm->timers[i].requested) {
 +                               gtm->timers[i].requested = true;
 +                               spin_unlock_irq(&gtm->lock);
 +                               of_node_put(np);
 +                               return &gtm->timers[i];
Quoted 11 lines

+ }
+ }
+
+ spin_unlock_irq(&gtm->lock);
+ }
+
+ if (gtm)
+ return ERR_PTR(-EBUSY);
+ return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL(gtm_get_timer);

Quoted 5 lines

This isn't a very efficient construct. You've already located all of the relevant nodes in the gtm_init() function. Searching the device tree is not efficient, so it should be avoided and only be performed once. Can you move the extraction of data from the tree to gtm_init() and only parse the drivers list of timers in this function?

Well, yes. I can create a list, and place all the GTMs in there.

Quoted 390 lines
Quoted 388 lines

+
+/**
+ * gtm_get_specific_timer - request specific GTM timer

 + * @gtm:       specific GTM, pass here GTM's device_node->data
 + * @timer:     specific timer number, Timer1 is 0.
 + * @width:     timer width (only 16 bits wide timers implemented so far)
 + *
 + * This function reserves GTM timer for later use. It returns gtm_timer
 + * structure to use with the rest of GTM API, you should use timer->irq
 + * to manage timer interrupt.
 + */
 +struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, int timer, int width)
 +{
 +       struct gtm_timer *ret = ERR_PTR(-EBUSY);
 +
 +       if (width != 16)
 +               return ERR_PTR(-ENOSYS);
 +
 +       spin_lock_irq(&gtm->lock);
 +
 +       if (gtm->timers[timer].requested)
 +               goto out;
 +
 +       ret = &gtm->timers[timer];
 +       ret->requested = true;
 +
 +out:
 +       spin_unlock_irq(&gtm->lock);
 +       return ret;
 +}
 +EXPORT_SYMBOL(gtm_get_specific_timer);
 +
 +/**
 + * gtm_put_timer - release GTM timer
 + * @width:     timer width (only 16 bits wide timers implemented so far)
 + *
 + * This function releases GTM timer so others may request it.
 + */
 +void gtm_put_timer(struct gtm_timer *tmr)
 +{
 +       spin_lock_irq(&tmr->gtm->lock);
 +
 +       tmr->requested = false;
 +
 +       spin_unlock_irq(&tmr->gtm->lock);
 +}
 +EXPORT_SYMBOL(gtm_put_timer);
 +
 +/*
 + * This is back-end for the exported functions, it's used to reset single
 + * timer in reference mode.
 + */
 +static int gtm_reset_ref_timer16(struct gtm_timer *tmr, int frequency,
 +                                int reference_value, bool free_run)
 +{
 +       struct gtm *gtm = tmr->gtm;
 +       int num = tmr - &gtm->timers[0];
 +       unsigned int prescaler;
 +       u8 iclk = GTMDR_ICLK_ICLK;
 +       u8 psr;
 +       u8 sps;
 +       unsigned long flags;
 +       int max_prescaler = 256 * 256 * 16;
 +
 +       /* CPM2 doesn't have primary prescaler */
 +       if (!tmr->gtpsr)
 +               max_prescaler /= 256;
 +
 +       prescaler = gtm->clock / frequency;
 +       /*
 +        * We have two 8 bit prescalers -- primary and secondary (psr, sps),
 +        * plus "slow go" mode (clk / 16). So, total prescale value is
 +        * 16 * (psr + 1) * (sps + 1). Though, for CPM2 GTMs we losing psr.
 +        */
 +       if (prescaler > max_prescaler)
 +               return -EINVAL;
 +
 +       if (prescaler > max_prescaler / 16) {
 +               iclk = GTMDR_ICLK_SLGO;
 +               prescaler /= 16;
 +       }
 +
 +       if (prescaler <= 256) {
 +               psr = 0;
 +               sps = prescaler - 1;
 +       } else {
 +               psr = 256 - 1;
 +               sps = prescaler / 256 - 1;
 +       }
 +
 +       spin_lock_irqsave(&gtm->lock, flags);
 +
 +       /*
 +        * Properly reset timers: stop, reset, set up prescalers, reference
 +        * value and clear event register.
 +        */
 +       clrsetbits_8(tmr->gtcfr, ~(GTCFR_STP(num) | GTCFR_RST(num)),
 +                                GTCFR_STP(num) | GTCFR_RST(num));
 +
 +       setbits8(tmr->gtcfr, GTCFR_STP(num));
 +
 +       if (tmr->gtpsr)
 +               out_be16(tmr->gtpsr, psr);
 +       clrsetbits_be16(tmr->gtmdr, 0xFFFF, iclk | GTMDR_SPS(sps) |
 +                       GTMDR_ORI | (free_run ? GTMDR_FRR : 0));
 +       out_be16(tmr->gtcnr, 0);
 +       out_be16(tmr->gtrfr, reference_value);
 +       out_be16(tmr->gtevr, 0xFFFF);
 +
 +       /* Let it be. */
 +       clrbits8(tmr->gtcfr, GTCFR_STP(num));
 +
 +       spin_unlock_irqrestore(&gtm->lock, flags);
 +
 +       return 0;
 +}
 +/**
 + * gtm_reset_timer16 - reset 16 bit timer with arbitrary precision
 + * @tmr:       pointer to the gtm_timer structure obtained from gtm_get_timer
 + * @usec:      timer interval in microseconds
 + * @reload:    if set, the timer will reset upon expiry rather than
 + *             continue running free.
 + *
 + * This function (re)sets the GTM timer so that it counts up to the requested
 + * interval value, and fires the interrupt when the value is reached. This
 + * function will reduce the precision of the timer as needed in order for the
 + * requested timeout to fit in a 16-bit register.
 + */
 +int gtm_reset_timer16(struct gtm_timer *tmr, unsigned long usec, bool reload)
 +{
 +       /* quite obvious, frequency which is enough for µSec precision */
 +       int freq = 1000000;
 +       unsigned int bit;
 +
 +       bit = fls_long(usec);
 +       if (bit > 15) {
 +               freq >>= bit - 15;
 +               usec >>= bit - 15;
 +       }
 +
 +       if (!freq)
 +               return -EINVAL;
 +
 +       return gtm_reset_ref_timer16(tmr, freq, usec, reload);
 +}
 +EXPORT_SYMBOL(gtm_reset_timer16);
 +
 +/**
 + * gtm_reset_utimer16 - reset 16 bits timer
 + * @tmr:       pointer to the gtm_timer structure obtained from gtm_get_timer
 + * @usec:      timer interval in microseconds
 + * @reload:    if set, the timer will reset upon expiry rather than
 + *             continue running free.
 + *
 + * This function (re)sets GTM timer so that it counts up to the requested
 + * interval value, and fires the interrupt when the value is reached. If reload
 + * flag was set, timer will also reset itself upon reference value, otherwise
 + * it continues to increment.
 + */
 +int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool reload)
 +{
 +       /* quite obvious, frequency which is enough for µSec precision */
 +       const int freq = 1000000;
 +
 +       /*
 +        * We can lower the frequency (and probably power consumption) by
 +        * dividing both frequency and usec by 2 until there is no remainder.
 +        * But we won't bother with this unless savings are measured, so just
 +        * run the timer as is.
 +        */
 +
 +       return gtm_reset_ref_timer16(tmr, freq, usec, reload);
 +}
 +EXPORT_SYMBOL(gtm_reset_utimer16);
 +
 +/**
 + * gtm_stop_timer16 - stop single timer
 + * @tmr:       pointer to the gtm_timer structure obtained from gtm_get_timer
 + *
 + * This function simply stops the GTM timer.
 + */
 +void gtm_stop_timer16(struct gtm_timer *tmr)
 +{
 +       struct gtm *gtm = tmr->gtm;
 +       int num = tmr - &gtm->timers[0];
 +       unsigned long flags;
 +
 +       spin_lock_irqsave(&gtm->lock, flags);
 +
 +       setbits8(tmr->gtcfr, GTCFR_STP(num));
 +       out_be16(tmr->gtevr, 0xFFFF);
 +
 +       spin_unlock_irqrestore(&gtm->lock, flags);
 +}
 +EXPORT_SYMBOL(gtm_stop_timer16);
 +
 +static void __init gtm_set_shortcuts(struct device_node *np,
 +                                    struct gtm_timer *timers,
 +                                    struct gtm_timers_regs __iomem *regs)
 +{
 +       /*
 +        * Yeah, I don't like this either, but timers' registers a bit messed,
 +        * so we have to provide shortcuts to write timer independent code.
 +        * Alternative option is to create gt*() accessors, but that will be
 +        * even uglier and cryptic.
 +        */
 +       timers[0].gtcfr = &regs->gtcfr1;
 +       timers[0].gtmdr = &regs->gtmdr1;
 +       timers[0].gtcnr = &regs->gtcnr1;
 +       timers[0].gtrfr = &regs->gtrfr1;
 +       timers[0].gtevr = &regs->gtevr1;
 +
 +       timers[1].gtcfr = &regs->gtcfr1;
 +       timers[1].gtmdr = &regs->gtmdr2;
 +       timers[1].gtcnr = &regs->gtcnr2;
 +       timers[1].gtrfr = &regs->gtrfr2;
 +       timers[1].gtevr = &regs->gtevr2;
 +
 +       timers[2].gtcfr = &regs->gtcfr2;
 +       timers[2].gtmdr = &regs->gtmdr3;
 +       timers[2].gtcnr = &regs->gtcnr3;
 +       timers[2].gtrfr = &regs->gtrfr3;
 +       timers[2].gtevr = &regs->gtevr3;
 +
 +       timers[3].gtcfr = &regs->gtcfr2;
 +       timers[3].gtmdr = &regs->gtmdr4;
 +       timers[3].gtcnr = &regs->gtcnr4;
 +       timers[3].gtrfr = &regs->gtrfr4;
 +       timers[3].gtevr = &regs->gtevr4;
 +
 +       /* CPM2 doesn't have primary prescaler */
 +       if (!of_device_is_compatible(np, "fsl,cpm2-gtm")) {
 +               timers[0].gtpsr = &regs->gtpsr1;
 +               timers[1].gtpsr = &regs->gtpsr2;
 +               timers[2].gtpsr = &regs->gtpsr3;
 +               timers[3].gtpsr = &regs->gtpsr4;
 +       }
 +}
 +
 +static int __init gtm_init(void)
 +{
 +       struct device_node *np;
 +
 +       for_each_compatible_node(np, NULL, "fsl,gtm") {
 +               int i;
 +               struct gtm *gtm;
 +               const u32 *clock;
 +               int size;
 +
 +               gtm = kzalloc(sizeof(*gtm), GFP_KERNEL);
 +               if (!gtm) {
 +                       pr_err("%s: unable to allocate memory\n",
 +                               np->full_name);
 +                       continue;
 +               }
 +
 +               spin_lock_init(&gtm->lock);
 +
 +               clock = of_get_property(np, "clock-frequency", &size);
 +               if (!clock || size != sizeof(*clock)) {
 +                       pr_err("%s: no clock-frequency\n", np->full_name);
 +                       goto err;
 +               }
 +               gtm->clock = *clock;
 +
 +               for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
 +                       int ret;
 +                       struct resource irq;
 +
 +                       ret = of_irq_to_resource(np, i, &irq);
 +                       if (ret == NO_IRQ) {
 +                               pr_err("%s: not enough interrupts specified\n",
 +                                      np->full_name);
 +                               goto err;
 +                       }
 +                       gtm->timers[i].irq = irq.start;
 +                       gtm->timers[i].gtm = gtm;
 +               }
 +
 +               gtm->regs = of_iomap(np, 0);
 +               if (!gtm->regs) {
 +                       pr_err("%s: unable to iomap registers\n",
 +                              np->full_name);
 +                       goto err;
 +               }
 +
 +               gtm_set_shortcuts(np, gtm->timers, gtm->regs);
 +
 +               /* We don't want to lose the node and its ->data */
 +               of_node_get(np);
 +               np->data = gtm;
 +
 +               continue;
 +err:
 +               kfree(gtm);
 +       }
 +       return 0;
 +}
 +arch_initcall(gtm_init);
 diff --git a/include/asm-powerpc/fsl_gtm.h b/include/asm-powerpc/fsl_gtm.h
 new file mode 100644
 index 0000000..3eafb21
 --- /dev/null
 +++ b/include/asm-powerpc/fsl_gtm.h
 @@ -0,0 +1,108 @@
 +/*
 + * Freescale General-purpose Timers Module
 + *
 + * Copyright (c) Freescale Semicondutor, Inc. 2006.
 + *               Shlomi Gridish <[email protected]>
 + *               Jerry Huang <[email protected]>
 + * Copyright (c) MontaVista Software, Inc. 2008.
 + *               Anton Vorontsov <[email protected]>
 + *
 + * This program is free software; you can redistribute  it and/or modify it
 + * under  the terms of  the GNU General  Public License as published by the
 + * Free Software Foundation;  either version 2 of the  License, or (at your
 + * option) any later version.
 + */
 +
 +#ifndef __ASM_FSL_GTM_H
 +#define __ASM_FSL_GTM_H
 +
 +#include <linux/types.h>
 +#include <linux/spinlock.h>
 +#include <linux/io.h>
 +
 +#define GTCFR_STP(x)           ((x) & 1 ? 1 << 5 : 1 << 1)
 +#define GTCFR_RST(x)           ((x) & 1 ? 1 << 4 : 1 << 0)
 +
 +#define GTMDR_ICLK_MASK                (3 << 1)
 +#define GTMDR_ICLK_ICAS                (0 << 1)
 +#define GTMDR_ICLK_ICLK                (1 << 1)
 +#define GTMDR_ICLK_SLGO                (2 << 1)
 +#define GTMDR_FRR              (1 << 3)
 +#define GTMDR_ORI              (1 << 4)
 +#define GTMDR_SPS(x)           ((x) << 8)
 +
 +struct gtm_timers_regs {
 +       u8      gtcfr1;         /* Timer 1, Timer 2 global config register */
 +       u8      res0[0x3];
 +       u8      gtcfr2;         /* Timer 3, timer 4 global config register */
 +       u8      res1[0xB];
 +       __be16  gtmdr1;         /* Timer 1 mode register */
 +       __be16  gtmdr2;         /* Timer 2 mode register */
 +       __be16  gtrfr1;         /* Timer 1 reference register */
 +       __be16  gtrfr2;         /* Timer 2 reference register */
 +       __be16  gtcpr1;         /* Timer 1 capture register */
 +       __be16  gtcpr2;         /* Timer 2 capture register */
 +       __be16  gtcnr1;         /* Timer 1 counter */
 +       __be16  gtcnr2;         /* Timer 2 counter */
 +       __be16  gtmdr3;         /* Timer 3 mode register */
 +       __be16  gtmdr4;         /* Timer 4 mode register */
 +       __be16  gtrfr3;         /* Timer 3 reference register */
 +       __be16  gtrfr4;         /* Timer 4 reference register */
 +       __be16  gtcpr3;         /* Timer 3 capture register */
 +       __be16  gtcpr4;         /* Timer 4 capture register */
 +       __be16  gtcnr3;         /* Timer 3 counter */
 +       __be16  gtcnr4;         /* Timer 4 counter */
 +       __be16  gtevr1;         /* Timer 1 event register */
 +       __be16  gtevr2;         /* Timer 2 event register */
 +       __be16  gtevr3;         /* Timer 3 event register */
 +       __be16  gtevr4;         /* Timer 4 event register */
 +       __be16  gtpsr1;         /* Timer 1 prescale register */
 +       __be16  gtpsr2;         /* Timer 2 prescale register */
 +       __be16  gtpsr3;         /* Timer 3 prescale register */
 +       __be16  gtpsr4;         /* Timer 4 prescale register */
 +       u8 res2[0x40];
 +} __attribute__ ((packed));
 +
 +struct gtm_timer {
 +       unsigned int irq;
 +
 +       struct gtm *gtm;
 +       bool requested;
 +       u8 __iomem *gtcfr;
 +       __be16 __iomem *gtmdr;
 +       __be16 __iomem *gtpsr;
 +       __be16 __iomem *gtcnr;
 +       __be16 __iomem *gtrfr;
 +       __be16 __iomem *gtevr;
 +};
 +
 +struct gtm {
 +       unsigned int clock;
 +       struct gtm_timers_regs __iomem *regs;
 +       struct gtm_timer timers[4];
 +       spinlock_t lock;
Quoted 1 line

+};

Quoted 4 lines

Consider moving the register definitions and structures inside the .c file. This is all anonymous data as far as the caller is concerned. If the structures are only access inside the driver then you gain yourself a bit of safety by moving them.

Ok.

Quoted 23 lines
Quoted 14 lines

+
+extern struct gtm_timer *gtm_get_timer(int width);
+extern struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, int timer,
+ int width);
+extern void gtm_put_timer(struct gtm_timer *tmr);
+extern int gtm_reset_timer16(struct gtm_timer *tmr, unsigned long usec,
+ bool reload);
+extern int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool reload); +extern void gtm_stop_timer16(struct gtm_timer *tmr);
+
+/**
+ * gtm_ack_timer16 - acknowledge timer event (free-run timers only)
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
+ * @events: events mask to ack

Quoted 8 lines

+ *
+ * Thus function used to acknowledge timer interrupt event, use it inside the
+ * interrupt handler.
+ */
+static inline void gtm_ack_timer16(struct gtm_timer *tmr, u16 events) +{
+ out_be16(tmr->gtevr, events);
+}

Quoted 1 line

Drop 'inline' and expect gcc to do the right thing.

Not sure about newer gccs, but older complained about "defined but not used" functions w/o inline keyword. I'm almost sure that this is still true. I can surely use __maybe_unused, but "static inline" is pretty settled tradition, plus this function is small enough anyway.

Signature · 3 lines
Anton Vorontsov
email: [email protected]
irc://irc.freenode.net/bd2
#4 lore raw

Re: [PATCH 1/5] [POWERPC] sysdev: implement FSL GTM support

Quoted 11 lines
Quoted 7 lines
Quoted 5 lines

+static inline void gtm_ack_timer16(struct gtm_timer *tmr, u16
events)
+{
+ out_be16(tmr->gtevr, events);
+}

Drop 'inline' and expect gcc to do the right thing.

Not sure about newer gccs, but older complained about "defined but not used" functions w/o inline keyword. I'm almost sure that this is still true.

It is. So why is it unused? Because you put the code in the header file. Can't you move it to the .c file instead?

Quoted 2 lines

I can surely use __maybe_unused, but "static inline" is pretty settled tradition, plus this function is small enough anyway.

All code in header files should be inline. Code in implementation files should only be inline if you have a very good reason for doing so. Same goes for __maybe_unused.

Segher

#5 lore raw

Re: [PATCH 1/5] [POWERPC] sysdev: implement FSL GTM support

In reply to Grant Likely
Quoted 10 lines · Grant Likely
Quoted 5 lines

+ r) Freescale General-purpose Timers Module
+
+ Required properties:
+ - compatible : should be "fsl,gtm" ("fsl,qe-gtm" in addition for QE
+ GTMs or "fsl,cpm2-gtm" for CPM2 GTMs).

I don't think this is specific enough. It is a very real possibility for Freescale to produce another part with a "general purpose timers module" that isn't register level compatible (and fsl,i2c is an example of what not to do).

If that happens, we'll make up "fsl,gtm2". :-)

Quoted 5 lines

The compatible string should include the
exact chip version. Newer parts can also claim compatibility with older ones.

Defining a 'generic' compatible value is also known as "making stuff up". :-)

Nothing wrong with making stuff up as long as we do it sanely.

How about something like fsl,gtm-1.0?

Quoted 13 lines
Quoted 4 lines

+/**
+ * gtm_ack_timer16 - acknowledge timer event (free-run timers only)
+ * @tmr: pointer to the gtm_timer structure obtained from gtm_get_timer
+ * @events: events mask to ack

Quoted 8 lines

+ *
+ * Thus function used to acknowledge timer interrupt event, use it inside the
+ * interrupt handler.
+ */
+static inline void gtm_ack_timer16(struct gtm_timer *tmr, u16 events) +{
+ out_be16(tmr->gtevr, events);
+}

Quoted 1 line

Drop 'inline' and expect gcc to do the right thing.

Not in a header...

-Scott

#6 lore raw

Re: [PATCH 1/5] [POWERPC] sysdev: implement FSL GTM support

Quoted 8 lines · Scott Wood
Quoted 6 lines · Grant Likely
Quoted 5 lines

+ r) Freescale General-purpose Timers Module
+
+ Required properties:
+ - compatible : should be "fsl,gtm" ("fsl,qe-gtm" in addition for QE
+ GTMs or "fsl,cpm2-gtm" for CPM2 GTMs).

Quoted 6 lines
Quoted 4 lines

I don't think this is specific enough. It is a very real possibility for Freescale to produce another part with a "general purpose timers module" that isn't register level compatible (and fsl,i2c is an example of what not to do).

If that happens, we'll make up "fsl,gtm2". :-)

:-P

Quoted 9 lines
Quoted 5 lines

The compatible string should include the
exact chip version. Newer parts can also claim compatibility with older ones.

Defining a 'generic' compatible value is also known as "making stuff up". :-)

Nothing wrong with making stuff up as long as we do it sanely.

How about something like fsl,gtm-1.0?

The problem I have with that is that there is always the potential that some rogue hardware will appear that messes up your sane scheme. Plus there is pretty much no downside to just choosing a device that the more recent parts reference.

Example: consider 3 chips using the same i2c core; say MPC8313, MPC5200 & MPC8548. compatible lines could look like this:

    compatible = "fsl,mpc8313-i2c","fsl-i2c";
    compatible = "fsl,mpc5200-i2c","fsl-i2c";
    compatible = "fsl,mpc8548-i2c","fsl-i2c";

Or; (assuming 8313 is where it first appeared) it could look like this:

    compatible = "fsl,mpc8313-i2c";
    compatible = "fsl,mpc5200-i2c","fsl,mpc8313-i2c";
    compatible = "fsl,mpc8548-i2c","fsl,mpc8313-i2c";

To the driver it's just a different string ("fsl,mpc8313-i2c" instead of "fsl-i2c"), but with the second you *always* know what an mpc8131-i2c core is; the mpc8131 user guide tells you. Even if you are strict about your sane naming scheme, you cannot look into the future and someone will do something wonky on you.

The other benefit is it avoids the temptation to define generic compatible values for things which will *never* be generic parts. Case in point; when I did the original mpc5200 bindings I did things like "mpc52xx-<blah>". However, there probably never will be another mpc52xx part; and if there is it will look vastly different from the current 5200. So I wasted all kinds of effort trying to be generic about stuff when it is almost certainly wasted effort and additional complexity to the naming conventions.

Quoted 8 lines
Quoted 6 lines
Quoted 4 lines

+static inline void gtm_ack_timer16(struct gtm_timer *tmr, u16 events) +{
+ out_be16(tmr->gtevr, events);
+}

Drop 'inline' and expect gcc to do the right thing.

Not in a header...

Oops, yeah; not sure what I was smoking.

Cheers,
g.

Signature · 2 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
#7 lore raw

PATCH v2 2/5 QE: add support for QE USB clocks routing

In reply to Anton Vorontsov

This patch adds a function to the qe_lib to setup QE USB clocks routing. To setup clocks safely, cmxgcr register needs locking, so I just reused ucc_lock since it was used only to protect cmxgcr.

The idea behind placing clocks routing functions into the qe_lib is that later we'll hopefully switch to the generic Linux Clock API, thus, for example, FHCI driver may be used for QE and CPM chips without nasty #ifdefs.

This patch also fixes QE_USB_RESTART_TX command definition in the qe.h.

---
 arch/powerpc/sysdev/qe_lib/Kconfig  |    4 ++
 arch/powerpc/sysdev/qe_lib/Makefile |    1 +
 arch/powerpc/sysdev/qe_lib/ucc.c    |    7 ++--
 arch/powerpc/sysdev/qe_lib/usb.c    |   56 +++++++++++++++++++++++++++++++++++
 include/asm-powerpc/qe.h            |   23 +++++++++++++-
 5 files changed, 87 insertions(+), 4 deletions(-)
 create mode 100644 arch/powerpc/sysdev/qe_lib/usb.c
arch/powerpc/sysdev/qe_lib/Kconfig +4 -0
index adc6621..76ffbc4 100644
@@ -20,3 +20,7 @@ config UCC
 	bool
 	default y if UCC_FAST || UCC_SLOW
 
+config QE_USB
+	bool
+	help
+	  QE USB Host Controller support
arch/powerpc/sysdev/qe_lib/Makefile +1 -0
index 874fe1a..e9ff888 100644
@@ -6,3 +6,4 @@ obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_ic.o qe_io.o
 obj-$(CONFIG_UCC)	+= ucc.o
 obj-$(CONFIG_UCC_SLOW)	+= ucc_slow.o
 obj-$(CONFIG_UCC_FAST)	+= ucc_fast.o
+obj-$(CONFIG_QE_USB)	+= usb.o
arch/powerpc/sysdev/qe_lib/ucc.c +4 -3
index 0e348d9..d3c7f5a 100644
@@ -26,7 +26,8 @@
 #include <asm/qe.h>
 #include <asm/ucc.h>
 
-static DEFINE_SPINLOCK(ucc_lock);
+DEFINE_SPINLOCK(cmxgcr_lock);
+EXPORT_SYMBOL(cmxgcr_lock);
 
 int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
 {
@@ -35,10 +36,10 @@ int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
 	if (ucc_num > UCC_MAX_NUM - 1)
 		return -EINVAL;
 
-	spin_lock_irqsave(&ucc_lock, flags);
+	spin_lock_irqsave(&cmxgcr_lock, flags);
 	clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG,
 		ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT);
-	spin_unlock_irqrestore(&ucc_lock, flags);
+	spin_unlock_irqrestore(&cmxgcr_lock, flags);
 
 	return 0;
 }
arch/powerpc/sysdev/qe_lib/usb.c new file +56 -0

56 lines not on this page · raw message

include/asm-powerpc/qe.h +22 -1
index c3be6e2..d217288 100644
@@ -16,6 +16,7 @@
 #define _ASM_POWERPC_QE_H
 #ifdef __KERNEL__
 
+#include <linux/spinlock.h>
 #include <asm/immap_qe.h>
 
 #define QE_NUM_OF_SNUM	28
@@ -74,6 +75,13 @@ enum qe_clock {
 	QE_CLK_DUMMY
 };
 
+static inline bool qe_clock_is_brg(enum qe_clock clk)
+{
+	return clk >= QE_BRG1 && clk <= QE_BRG16;
+}
+
+extern spinlock_t cmxgcr_lock;
+
 /* Export QE common operations */
 extern void qe_reset(void);
 extern int par_io_init(struct device_node *np);
@@ -156,6 +164,9 @@ int qe_upload_firmware(const struct qe_firmware *firmware);
 /* Obtain information on the uploaded firmware */
 struct qe_firmware_info *qe_get_firmware_info(void);
 
+/* QE USB */
+int qe_usb_clock_set(enum qe_clock clk, int rate);
+
 /* Buffer descriptors */
 struct qe_bd {
 	__be16 status;
@@ -254,6 +265,16 @@ enum comm_dir {
 #define QE_CMXGCR_MII_ENET_MNG		0x00007000
 #define QE_CMXGCR_MII_ENET_MNG_SHIFT	12
 #define QE_CMXGCR_USBCS			0x0000000f
+#define QE_CMXGCR_USBCS_CLK3		0x1
+#define QE_CMXGCR_USBCS_CLK5		0x2
+#define QE_CMXGCR_USBCS_CLK7		0x3
+#define QE_CMXGCR_USBCS_CLK9		0x4
+#define QE_CMXGCR_USBCS_CLK13		0x5
+#define QE_CMXGCR_USBCS_CLK17		0x6
+#define QE_CMXGCR_USBCS_CLK19		0x7
+#define QE_CMXGCR_USBCS_CLK21		0x8
+#define QE_CMXGCR_USBCS_BRG9		0x9
+#define QE_CMXGCR_USBCS_BRG10		0xa
 
 /* QE CECR Commands.
 */
@@ -283,7 +304,7 @@ enum comm_dir {
 #define QE_HPAC_START_TX		0x0000060b
 #define QE_HPAC_START_RX		0x0000070b
 #define QE_USB_STOP_TX			0x0000000a
-#define QE_USB_RESTART_TX		0x0000000b
+#define QE_USB_RESTART_TX		0x0000000c
 #define QE_QMC_STOP_TX			0x0000000c
 #define QE_QMC_STOP_RX			0x0000000d
 #define QE_SS7_SU_FIL_RESET		0x0000000e
Signature · 1 line
1.5.5
#8 lore raw

PATCH v2 3/5 QE: prepare QE PIO code for GPIO LIB support

In reply to Anton Vorontsov

- split and export __par_io_config_pin() out of par_io_config_pin(), so we could use the prefixed version with GPIO LIB API;
- rename struct port_regs to qe_pio_regs, and place it into qe.h;
- rename #define NUM_OF_PINS to QE_PIO_PINS, and place it into qe.h.

---
 arch/powerpc/sysdev/qe_lib/qe_io.c |   94 +++++++++++++++++-------------------
 include/asm-powerpc/qe.h           |   19 +++++++
 2 files changed, 64 insertions(+), 49 deletions(-)
arch/powerpc/sysdev/qe_lib/qe_io.c +45 -49
index 93916a4..7c87460 100644
@@ -28,21 +28,7 @@
 
 #undef DEBUG
 
-#define NUM_OF_PINS	32
-
-struct port_regs {
-	__be32	cpodr;		/* Open drain register */
-	__be32	cpdata;		/* Data register */
-	__be32	cpdir1;		/* Direction register */
-	__be32	cpdir2;		/* Direction register */
-	__be32	cppar1;		/* Pin assignment register */
-	__be32	cppar2;		/* Pin assignment register */
-#ifdef CONFIG_PPC_85xx
-	u8	pad[8];
-#endif
-};
-
-static struct port_regs __iomem *par_io;
+static struct qe_pio_regs __iomem *par_io;
 static int num_par_io_ports = 0;
 
 int par_io_init(struct device_node *np)
@@ -64,69 +50,79 @@ int par_io_init(struct device_node *np)
 	return 0;
 }
 
-int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
-		      int assignment, int has_irq)
+void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, int dir,
+			 int open_drain, int assignment, int has_irq)
 {
-	u32 pin_mask1bit, pin_mask2bits, new_mask2bits, tmp_val;
-
-	if (!par_io)
-		return -1;
+	u32 pin_mask1bit;
+	u32 pin_mask2bits;
+	u32 new_mask2bits;
+	u32 tmp_val;
 
 	/* calculate pin location for single and 2 bits information */
-	pin_mask1bit = (u32) (1 << (NUM_OF_PINS - (pin + 1)));
+	pin_mask1bit = (u32) (1 << (QE_PIO_PINS - (pin + 1)));
 
 	/* Set open drain, if required */
-	tmp_val = in_be32(&par_io[port].cpodr);
+	tmp_val = in_be32(&par_io->cpodr);
 	if (open_drain)
-		out_be32(&par_io[port].cpodr, pin_mask1bit | tmp_val);
+		out_be32(&par_io->cpodr, pin_mask1bit | tmp_val);
 	else
-		out_be32(&par_io[port].cpodr, ~pin_mask1bit & tmp_val);
+		out_be32(&par_io->cpodr, ~pin_mask1bit & tmp_val);
 
 	/* define direction */
-	tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ?
-		in_be32(&par_io[port].cpdir2) :
-		in_be32(&par_io[port].cpdir1);
+	tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
+		in_be32(&par_io->cpdir2) :
+		in_be32(&par_io->cpdir1);
 
 	/* get all bits mask for 2 bit per port */
-	pin_mask2bits = (u32) (0x3 << (NUM_OF_PINS -
-				(pin % (NUM_OF_PINS / 2) + 1) * 2));
+	pin_mask2bits = (u32) (0x3 << (QE_PIO_PINS -
+				(pin % (QE_PIO_PINS / 2) + 1) * 2));
 
 	/* Get the final mask we need for the right definition */
-	new_mask2bits = (u32) (dir << (NUM_OF_PINS -
-				(pin % (NUM_OF_PINS / 2) + 1) * 2));
+	new_mask2bits = (u32) (dir << (QE_PIO_PINS -
+				(pin % (QE_PIO_PINS / 2) + 1) * 2));
 
 	/* clear and set 2 bits mask */
-	if (pin > (NUM_OF_PINS / 2) - 1) {
-		out_be32(&par_io[port].cpdir2,
+	if (pin > (QE_PIO_PINS / 2) - 1) {
+		out_be32(&par_io->cpdir2,
 			 ~pin_mask2bits & tmp_val);
 		tmp_val &= ~pin_mask2bits;
-		out_be32(&par_io[port].cpdir2, new_mask2bits | tmp_val);
+		out_be32(&par_io->cpdir2, new_mask2bits | tmp_val);
 	} else {
-		out_be32(&par_io[port].cpdir1,
+		out_be32(&par_io->cpdir1,
 			 ~pin_mask2bits & tmp_val);
 		tmp_val &= ~pin_mask2bits;
-		out_be32(&par_io[port].cpdir1, new_mask2bits | tmp_val);
+		out_be32(&par_io->cpdir1, new_mask2bits | tmp_val);
 	}
 	/* define pin assignment */
-	tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ?
-		in_be32(&par_io[port].cppar2) :
-		in_be32(&par_io[port].cppar1);
+	tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
+		in_be32(&par_io->cppar2) :
+		in_be32(&par_io->cppar1);
 
-	new_mask2bits = (u32) (assignment << (NUM_OF_PINS -
-			(pin % (NUM_OF_PINS / 2) + 1) * 2));
+	new_mask2bits = (u32) (assignment << (QE_PIO_PINS -
+			(pin % (QE_PIO_PINS / 2) + 1) * 2));
 	/* clear and set 2 bits mask */
-	if (pin > (NUM_OF_PINS / 2) - 1) {
-		out_be32(&par_io[port].cppar2,
+	if (pin > (QE_PIO_PINS / 2) - 1) {
+		out_be32(&par_io->cppar2,
 			 ~pin_mask2bits & tmp_val);
 		tmp_val &= ~pin_mask2bits;
-		out_be32(&par_io[port].cppar2, new_mask2bits | tmp_val);
+		out_be32(&par_io->cppar2, new_mask2bits | tmp_val);
 	} else {
-		out_be32(&par_io[port].cppar1,
+		out_be32(&par_io->cppar1,
 			 ~pin_mask2bits & tmp_val);
 		tmp_val &= ~pin_mask2bits;
-		out_be32(&par_io[port].cppar1, new_mask2bits | tmp_val);
+		out_be32(&par_io->cppar1, new_mask2bits | tmp_val);
 	}
+}
+EXPORT_SYMBOL(__par_io_config_pin);
+
+int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
+		      int assignment, int has_irq)
+{
+	if (!par_io || port >= num_par_io_ports)
+		return -EINVAL;
 
+	__par_io_config_pin(&par_io[port], pin, dir, open_drain, assignment,
+			    has_irq);
 	return 0;
 }
 EXPORT_SYMBOL(par_io_config_pin);
@@ -137,10 +133,10 @@ int par_io_data_set(u8 port, u8 pin, u8 val)
 
 	if (port >= num_par_io_ports)
 		return -EINVAL;
-	if (pin >= NUM_OF_PINS)
+	if (pin >= QE_PIO_PINS)
 		return -EINVAL;
 	/* calculate pin location */
-	pin_mask = (u32) (1 << (NUM_OF_PINS - 1 - pin));
+	pin_mask = (u32) (1 << (QE_PIO_PINS - 1 - pin));
 
 	tmp_val = in_be32(&par_io[port].cpdata);
 
include/asm-powerpc/qe.h +19 -0
index d217288..c4523ac 100644
@@ -84,8 +84,27 @@ extern spinlock_t cmxgcr_lock;
 
 /* Export QE common operations */
 extern void qe_reset(void);
+
+/* QE PIO */
+#define QE_PIO_PINS 32
+
+struct qe_pio_regs {
+	__be32	cpodr;		/* Open drain register */
+	__be32	cpdata;		/* Data register */
+	__be32	cpdir1;		/* Direction register */
+	__be32	cpdir2;		/* Direction register */
+	__be32	cppar1;		/* Pin assignment register */
+	__be32	cppar2;		/* Pin assignment register */
+#ifdef CONFIG_PPC_85xx
+	u8	pad[8];
+#endif
+};
+
 extern int par_io_init(struct device_node *np);
 extern int par_io_of_config(struct device_node *np);
+extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin,
+				int dir, int open_drain, int assignment,
+				int has_irq);
 extern int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
 			     int assignment, int has_irq);
 extern int par_io_data_set(u8 port, u8 pin, u8 val);
Signature · 1 line
1.5.5
#9 lore raw

Re: [PATCH 3/5] [POWERPC] QE: prepare QE PIO code for GPIO LIB support

Quoted 6 lines · Anton Vorontsov

- split and export __par_io_config_pin() out of par_io_config_pin(), so we could use the prefixed version with GPIO LIB API;
- rename struct port_regs to qe_pio_regs, and place it into qe.h;
- rename #define NUM_OF_PINS to QE_PIO_PINS, and place it into qe.h.

I don't see any mutual exclusion here. How is __par_io_config_pin() protected when there are multiple callers?

Quoted 197 lines

---

  arch/powerpc/sysdev/qe_lib/qe_io.c |   94 +++++++++++++++++-------------------
  include/asm-powerpc/qe.h           |   19 +++++++
  2 files changed, 64 insertions(+), 49 deletions(-)

diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c index 93916a4..7c87460 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -28,21 +28,7 @@

#undef DEBUG

-#define NUM_OF_PINS 32
-
-struct port_regs {

 -       __be32  cpodr;          /* Open drain register */
 -       __be32  cpdata;         /* Data register */
 -       __be32  cpdir1;         /* Direction register */
 -       __be32  cpdir2;         /* Direction register */
 -       __be32  cppar1;         /* Pin assignment register */
 -       __be32  cppar2;         /* Pin assignment register */

-#ifdef CONFIG_PPC_85xx
- u8 pad[8];
-#endif
-};
-
-static struct port_regs __iomem *par_io;
+static struct qe_pio_regs __iomem *par_io;
static int num_par_io_ports = 0;

int par_io_init(struct device_node *np)
@@ -64,69 +50,79 @@ int par_io_init(struct device_node *np)

        return 0;

}

-int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
- int assignment, int has_irq)
+void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, int dir,
+ int open_drain, int assignment, int has_irq)
{
- u32 pin_mask1bit, pin_mask2bits, new_mask2bits, tmp_val;
-
- if (!par_io)
- return -1;

 +       u32 pin_mask1bit;
 +       u32 pin_mask2bits;
 +       u32 new_mask2bits;
 +       u32 tmp_val;
        /* calculate pin location for single and 2 bits information */

- pin_mask1bit = (u32) (1 << (NUM_OF_PINS - (pin + 1)));
+ pin_mask1bit = (u32) (1 << (QE_PIO_PINS - (pin + 1)));

        /* Set open drain, if required */

- tmp_val = in_be32(&par_io[port].cpodr);
+ tmp_val = in_be32(&par_io->cpodr);
if (open_drain)
- out_be32(&par_io[port].cpodr, pin_mask1bit | tmp_val);
+ out_be32(&par_io->cpodr, pin_mask1bit | tmp_val);
else
- out_be32(&par_io[port].cpodr, ~pin_mask1bit & tmp_val);
+ out_be32(&par_io->cpodr, ~pin_mask1bit & tmp_val);

        /* define direction */

- tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ?
- in_be32(&par_io[port].cpdir2) :
- in_be32(&par_io[port].cpdir1);
+ tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
+ in_be32(&par_io->cpdir2) :
+ in_be32(&par_io->cpdir1);

        /* get all bits mask for 2 bit per port */

- pin_mask2bits = (u32) (0x3 << (NUM_OF_PINS -
- (pin % (NUM_OF_PINS / 2) + 1) * 2));
+ pin_mask2bits = (u32) (0x3 << (QE_PIO_PINS -
+ (pin % (QE_PIO_PINS / 2) + 1) * 2));

        /* Get the final mask we need for the right definition */

- new_mask2bits = (u32) (dir << (NUM_OF_PINS -
- (pin % (NUM_OF_PINS / 2) + 1) * 2));
+ new_mask2bits = (u32) (dir << (QE_PIO_PINS -
+ (pin % (QE_PIO_PINS / 2) + 1) * 2));

        /* clear and set 2 bits mask */
 -       if (pin > (NUM_OF_PINS / 2) - 1) {
 -               out_be32(&par_io[port].cpdir2,
 +       if (pin > (QE_PIO_PINS / 2) - 1) {
 +               out_be32(&par_io->cpdir2,
                         ~pin_mask2bits & tmp_val);
                tmp_val &= ~pin_mask2bits;
 -               out_be32(&par_io[port].cpdir2, new_mask2bits | tmp_val);
 +               out_be32(&par_io->cpdir2, new_mask2bits | tmp_val);
        } else {
 -               out_be32(&par_io[port].cpdir1,
 +               out_be32(&par_io->cpdir1,
                         ~pin_mask2bits & tmp_val);
                tmp_val &= ~pin_mask2bits;
 -               out_be32(&par_io[port].cpdir1, new_mask2bits | tmp_val);
 +               out_be32(&par_io->cpdir1, new_mask2bits | tmp_val);
        }
        /* define pin assignment */

- tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ?
- in_be32(&par_io[port].cppar2) :
- in_be32(&par_io[port].cppar1);
+ tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
+ in_be32(&par_io->cppar2) :
+ in_be32(&par_io->cppar1);

- new_mask2bits = (u32) (assignment << (NUM_OF_PINS -
- (pin % (NUM_OF_PINS / 2) + 1) * 2));
+ new_mask2bits = (u32) (assignment << (QE_PIO_PINS -

 +                       (pin % (QE_PIO_PINS / 2) + 1) * 2));
        /* clear and set 2 bits mask */
 -       if (pin > (NUM_OF_PINS / 2) - 1) {
 -               out_be32(&par_io[port].cppar2,
 +       if (pin > (QE_PIO_PINS / 2) - 1) {
 +               out_be32(&par_io->cppar2,
                         ~pin_mask2bits & tmp_val);
                tmp_val &= ~pin_mask2bits;
 -               out_be32(&par_io[port].cppar2, new_mask2bits | tmp_val);
 +               out_be32(&par_io->cppar2, new_mask2bits | tmp_val);
        } else {
 -               out_be32(&par_io[port].cppar1,
 +               out_be32(&par_io->cppar1,
                         ~pin_mask2bits & tmp_val);
                tmp_val &= ~pin_mask2bits;
 -               out_be32(&par_io[port].cppar1, new_mask2bits | tmp_val);
 +               out_be32(&par_io->cppar1, new_mask2bits | tmp_val);
        }

+}
+EXPORT_SYMBOL(__par_io_config_pin);
+
+int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
+ int assignment, int has_irq)
+{
+ if (!par_io || port >= num_par_io_ports)
+ return -EINVAL;

+ __par_io_config_pin(&par_io[port], pin, dir, open_drain, assignment,

 +                           has_irq);
        return 0;

}
EXPORT_SYMBOL(par_io_config_pin);
@@ -137,10 +133,10 @@ int par_io_data_set(u8 port, u8 pin, u8 val)

if (port >= num_par_io_ports)
return -EINVAL;
- if (pin >= NUM_OF_PINS)
+ if (pin >= QE_PIO_PINS)

                return -EINVAL;
        /* calculate pin location */

- pin_mask = (u32) (1 << (NUM_OF_PINS - 1 - pin));
+ pin_mask = (u32) (1 << (QE_PIO_PINS - 1 - pin));

        tmp_val = in_be32(&par_io[port].cpdata);

diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h index d217288..c4523ac 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -84,8 +84,27 @@ extern spinlock_t cmxgcr_lock;

/* Export QE common operations */
extern void qe_reset(void);
+
+/* QE PIO */
+#define QE_PIO_PINS 32
+
+struct qe_pio_regs {

 +       __be32  cpodr;          /* Open drain register */
 +       __be32  cpdata;         /* Data register */
 +       __be32  cpdir1;         /* Direction register */
 +       __be32  cpdir2;         /* Direction register */
 +       __be32  cppar1;         /* Pin assignment register */
 +       __be32  cppar2;         /* Pin assignment register */
 +#ifdef CONFIG_PPC_85xx
 +       u8      pad[8];
 +#endif
 +};
 +
  extern int par_io_init(struct device_node *np);
  extern int par_io_of_config(struct device_node *np);
 +extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin,
 +                               int dir, int open_drain, int assignment,
 +                               int has_irq);
  extern int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
                             int assignment, int has_irq);

extern int par_io_data_set(u8 port, u8 pin, u8 val);
--
1.5.5

_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Signature · 2 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
#10 lore raw

Re: [PATCH 3/5] [POWERPC] QE: prepare QE PIO code for GPIO LIB support

Quoted 11 lines · Grant Likely
Quoted 6 lines · Anton Vorontsov

- split and export __par_io_config_pin() out of par_io_config_pin(), so we could use the prefixed version with GPIO LIB API;
- rename struct port_regs to qe_pio_regs, and place it into qe.h;
- rename #define NUM_OF_PINS to QE_PIO_PINS, and place it into qe.h.

I don't see any mutual exclusion here. How is __par_io_config_pin() protected when there are multiple callers?

The idea is to not have multiple callers.

Today most callers of par_io_config_pin() is various board fixups, e.g. this in the setup_arch():

         for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
                        par_io_of_config(np);

Which calls par_io_config_pin(). But we're safe here, setup_arch called very early.

The only abuser of this is mpc832x_rdb.c, but it will be converted to the GPIO API.

Quoted 203 lines
Quoted 197 lines

---

  arch/powerpc/sysdev/qe_lib/qe_io.c |   94 +++++++++++++++++-------------------
  include/asm-powerpc/qe.h           |   19 +++++++
  2 files changed, 64 insertions(+), 49 deletions(-)

diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c index 93916a4..7c87460 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -28,21 +28,7 @@

#undef DEBUG

-#define NUM_OF_PINS 32
-
-struct port_regs {

 -       __be32  cpodr;          /* Open drain register */
 -       __be32  cpdata;         /* Data register */
 -       __be32  cpdir1;         /* Direction register */
 -       __be32  cpdir2;         /* Direction register */
 -       __be32  cppar1;         /* Pin assignment register */
 -       __be32  cppar2;         /* Pin assignment register */

-#ifdef CONFIG_PPC_85xx
- u8 pad[8];
-#endif
-};
-
-static struct port_regs __iomem *par_io;
+static struct qe_pio_regs __iomem *par_io;
static int num_par_io_ports = 0;

int par_io_init(struct device_node *np)
@@ -64,69 +50,79 @@ int par_io_init(struct device_node *np)

        return 0;

}

-int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
- int assignment, int has_irq)
+void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, int dir,
+ int open_drain, int assignment, int has_irq)
{
- u32 pin_mask1bit, pin_mask2bits, new_mask2bits, tmp_val;
-
- if (!par_io)
- return -1;

 +       u32 pin_mask1bit;
 +       u32 pin_mask2bits;
 +       u32 new_mask2bits;
 +       u32 tmp_val;
        /* calculate pin location for single and 2 bits information */

- pin_mask1bit = (u32) (1 << (NUM_OF_PINS - (pin + 1)));
+ pin_mask1bit = (u32) (1 << (QE_PIO_PINS - (pin + 1)));

        /* Set open drain, if required */

- tmp_val = in_be32(&par_io[port].cpodr);
+ tmp_val = in_be32(&par_io->cpodr);
if (open_drain)
- out_be32(&par_io[port].cpodr, pin_mask1bit | tmp_val);
+ out_be32(&par_io->cpodr, pin_mask1bit | tmp_val);
else
- out_be32(&par_io[port].cpodr, ~pin_mask1bit & tmp_val);
+ out_be32(&par_io->cpodr, ~pin_mask1bit & tmp_val);

        /* define direction */

- tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ?
- in_be32(&par_io[port].cpdir2) :
- in_be32(&par_io[port].cpdir1);
+ tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
+ in_be32(&par_io->cpdir2) :
+ in_be32(&par_io->cpdir1);

        /* get all bits mask for 2 bit per port */

- pin_mask2bits = (u32) (0x3 << (NUM_OF_PINS -
- (pin % (NUM_OF_PINS / 2) + 1) * 2));
+ pin_mask2bits = (u32) (0x3 << (QE_PIO_PINS -
+ (pin % (QE_PIO_PINS / 2) + 1) * 2));

        /* Get the final mask we need for the right definition */

- new_mask2bits = (u32) (dir << (NUM_OF_PINS -
- (pin % (NUM_OF_PINS / 2) + 1) * 2));
+ new_mask2bits = (u32) (dir << (QE_PIO_PINS -
+ (pin % (QE_PIO_PINS / 2) + 1) * 2));

        /* clear and set 2 bits mask */
 -       if (pin > (NUM_OF_PINS / 2) - 1) {
 -               out_be32(&par_io[port].cpdir2,
 +       if (pin > (QE_PIO_PINS / 2) - 1) {
 +               out_be32(&par_io->cpdir2,
                         ~pin_mask2bits & tmp_val);
                tmp_val &= ~pin_mask2bits;
 -               out_be32(&par_io[port].cpdir2, new_mask2bits | tmp_val);
 +               out_be32(&par_io->cpdir2, new_mask2bits | tmp_val);
        } else {
 -               out_be32(&par_io[port].cpdir1,
 +               out_be32(&par_io->cpdir1,
                         ~pin_mask2bits & tmp_val);
                tmp_val &= ~pin_mask2bits;
 -               out_be32(&par_io[port].cpdir1, new_mask2bits | tmp_val);
 +               out_be32(&par_io->cpdir1, new_mask2bits | tmp_val);
        }
        /* define pin assignment */

- tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ?
- in_be32(&par_io[port].cppar2) :
- in_be32(&par_io[port].cppar1);
+ tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
+ in_be32(&par_io->cppar2) :
+ in_be32(&par_io->cppar1);

- new_mask2bits = (u32) (assignment << (NUM_OF_PINS -
- (pin % (NUM_OF_PINS / 2) + 1) * 2));
+ new_mask2bits = (u32) (assignment << (QE_PIO_PINS -

 +                       (pin % (QE_PIO_PINS / 2) + 1) * 2));
        /* clear and set 2 bits mask */
 -       if (pin > (NUM_OF_PINS / 2) - 1) {
 -               out_be32(&par_io[port].cppar2,
 +       if (pin > (QE_PIO_PINS / 2) - 1) {
 +               out_be32(&par_io->cppar2,
                         ~pin_mask2bits & tmp_val);
                tmp_val &= ~pin_mask2bits;
 -               out_be32(&par_io[port].cppar2, new_mask2bits | tmp_val);
 +               out_be32(&par_io->cppar2, new_mask2bits | tmp_val);
        } else {
 -               out_be32(&par_io[port].cppar1,
 +               out_be32(&par_io->cppar1,
                         ~pin_mask2bits & tmp_val);
                tmp_val &= ~pin_mask2bits;
 -               out_be32(&par_io[port].cppar1, new_mask2bits | tmp_val);
 +               out_be32(&par_io->cppar1, new_mask2bits | tmp_val);
        }

+}
+EXPORT_SYMBOL(__par_io_config_pin);
+
+int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
+ int assignment, int has_irq)
+{
+ if (!par_io || port >= num_par_io_ports)
+ return -EINVAL;

+ __par_io_config_pin(&par_io[port], pin, dir, open_drain, assignment,

 +                           has_irq);
        return 0;

}
EXPORT_SYMBOL(par_io_config_pin);
@@ -137,10 +133,10 @@ int par_io_data_set(u8 port, u8 pin, u8 val)

if (port >= num_par_io_ports)
return -EINVAL;
- if (pin >= NUM_OF_PINS)
+ if (pin >= QE_PIO_PINS)

                return -EINVAL;
        /* calculate pin location */

- pin_mask = (u32) (1 << (NUM_OF_PINS - 1 - pin));
+ pin_mask = (u32) (1 << (QE_PIO_PINS - 1 - pin));

        tmp_val = in_be32(&par_io[port].cpdata);

diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h index d217288..c4523ac 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -84,8 +84,27 @@ extern spinlock_t cmxgcr_lock;

/* Export QE common operations */
extern void qe_reset(void);
+
+/* QE PIO */
+#define QE_PIO_PINS 32
+
+struct qe_pio_regs {

 +       __be32  cpodr;          /* Open drain register */
 +       __be32  cpdata;         /* Data register */
 +       __be32  cpdir1;         /* Direction register */
 +       __be32  cpdir2;         /* Direction register */
 +       __be32  cppar1;         /* Pin assignment register */
 +       __be32  cppar2;         /* Pin assignment register */
 +#ifdef CONFIG_PPC_85xx
 +       u8      pad[8];
 +#endif
 +};
 +
  extern int par_io_init(struct device_node *np);
  extern int par_io_of_config(struct device_node *np);
 +extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin,
 +                               int dir, int open_drain, int assignment,
 +                               int has_irq);
  extern int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
                             int assignment, int has_irq);

extern int par_io_data_set(u8 port, u8 pin, u8 val);
--
1.5.5

_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Signature · 2 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
Signature · 3 lines
Anton Vorontsov
email: [email protected]
irc://irc.freenode.net/bd2
#11 lore raw

PATCH v2 4/5 QE: implement support for the GPIO LIB API

In reply to Anton Vorontsov

This is needed to access QE GPIOs via Linux GPIO API.

---

Quoted 22 lines · Kumar Gala
Quoted 20 lines · Anton Vorontsov
Quoted 18 lines · Kumar Gala
Quoted 14 lines

index a3f9c3f..a4a195a 100644

arch/powerpc/sysdev/qe_lib/qe_io.c +2 -1
@@ -20,7 +20,8 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
-
+#include <linux/spinlock.h>
+#include <linux/of_gpio.h>
 #include <asm/io.h>
 #include <asm/qe.h>
 #include <asm/prom.h>

arch/powerpc/sysdev/qe_lib/qe_io.c int par_io_of_config(struct device_node *np) · line 216

Quoted 2 lines
arch/powerpc/sysdev/qe_lib/qe_io.c +0 -0
@@ -214,6 +215,140 @@ int par_io_of_config(struct device_node *np)
 }
 EXPORT_SYMBOL(par_io_of_config);

can we split this out into a new file since its pretty much a driver.

Quoted 5 lines
Quoted 1 line

No problem. Would you prefer this to go under drivers/gpio/ ?

Yes that would be better. We actively worked on pull drivers out of arch/ppc back in the day.

Hi David,

Do we need your Ack to go this through powerpc tree, and if so, could you provide one?

Thanks.

 Documentation/powerpc/booting-without-of.txt |   34 ++++---
 arch/powerpc/platforms/Kconfig               |    2 +
 drivers/gpio/Kconfig                         |    9 ++
 drivers/gpio/Makefile                        |    1 +
 drivers/gpio/qe.c                            |  147 ++++++++++++++++++++++++++
 5 files changed, 180 insertions(+), 13 deletions(-)
 create mode 100644 drivers/gpio/qe.c
Documentation/powerpc/booting-without-of.txt +20 -12
index 827b630..5c9cfab 100644
@@ -1721,24 +1721,32 @@ platforms are moved over to use the flattened-device-tree model.
    information.
 
    Required properties:
-   - device_type : should be "par_io".
+   - #gpio-cells : should be "2".
+   - compatible : should be "fsl,qe-pario-bank-<bank>", "fsl,qe-pario-bank"
    - reg : offset to the register set and its length.
-   - num-ports : number of Parallel I/O ports
+   - gpio-controller : node to identify gpio controllers.
 
-   Example:
-	par_io@1400 {
-		reg = <1400 100>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		device_type = "par_io";
-		num-ports = <7>;
-		ucc_pin@01 {
-			......
-		};
+   For example, two QE Par I/O banks:
+	qe_pio_a: gpio-controller@1400 {
+		#gpio-cells = <2>;
+		compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
+		reg = <0x1400 0x18>;
+		gpio-controller;
+	};
 
+	qe_pio_e: gpio-controller@1460 {
+		#gpio-cells = <2>;
+		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
+		reg = <0x1460 0x18>;
+		gpio-controller;
+	};
 
    vi) Pin configuration nodes
 
+   NOTE: pin configuration nodes are obsolete. Usually, their existance
+         is an evidence of the firmware shortcomings. Such fixups are
+         better handled by the Linux board file, not the device tree.
+
    Required properties:
    - linux,phandle : phandle of this node; likely referenced by a QE
      device.
arch/powerpc/platforms/Kconfig +2 -0
index f38c50b..f6eecd1 100644
@@ -270,6 +270,8 @@ config QUICC_ENGINE
 	bool
 	select PPC_LIB_RHEAP
 	select CRC32
+	select GENERIC_GPIO
+	select HAVE_GPIO_LIB
 	help
 	  The QUICC Engine (QE) is a new generation of communications
 	  coprocessors on Freescale embedded CPUs (akin to CPM in older chips).
drivers/gpio/Kconfig +9 -0
index bbd2834..cee56f9 100644
@@ -25,6 +25,15 @@ config DEBUG_GPIO
 
 # put expanders in the right section, in alphabetical order
 
+comment "On-chip GPIOs:"
+
+config GPIO_QE
+	bool "QUICC Engine GPIOs"
+	depends on QUICC_ENGINE
+	help
+	  Say Y here to use GPIOs on the Freescale PowerPC CPUs with
+	  QUICC Engine block.
+
 comment "I2C GPIO expanders:"
 
 config GPIO_PCA953X
drivers/gpio/Makefile +1 -0
index fdde992..fd0a41f 100644
@@ -7,3 +7,4 @@ obj-$(CONFIG_HAVE_GPIO_LIB)	+= gpiolib.o
 obj-$(CONFIG_GPIO_MCP23S08)	+= mcp23s08.o
 obj-$(CONFIG_GPIO_PCA953X)	+= pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)	+= pcf857x.o
+obj-$(CONFIG_GPIO_QE)		+= qe.o
drivers/gpio/qe.c new file +147 -0

147 lines not on this page · raw message

Signature · 1 line
1.5.5
#12 lore raw

Re: [PATCH 4/5] [POWERPC] QE: implement support for the GPIO LIB API

Quoted 7 lines · Anton Vorontsov
Quoted 6 lines · Kumar Gala
Quoted 2 lines · Anton Vorontsov

No problem. Would you prefer this to go under drivers/gpio/ ?

Yes that would be better.  We actively worked on pull drivers out of arch/ppc back in the day.

I'm not sure I see the problem here. This is precisely the kind of *non-driver* code that normally (i.e. for all other Linux platforms I've looked at) *belongs* in the arch code ... what's the objection to doing it the same way other platforms do?

And for that matter, why make it optional, via Kconfig, instead of always configuring it in, along with the GPIO interrupt support? A quick glance at one of the MPC83xx chips suggested that QE port IRQ capabilities would be very chip specific, so I'd expect that GPIO IRQ support wouldn't naturally move out of the arch tree.

- Dave

Quoted 14 lines

Hi David,

Do we need your Ack to go this through powerpc tree, and if so, could you provide one?

Thanks.

 Documentation/powerpc/booting-without-of.txt |   34 ++++--- arch/powerpc/platforms/Kconfig               |    2 + drivers/gpio/Kconfig                         |    9 ++ drivers/gpio/Makefile                        |    1 + drivers/gpio/qe.c                            |  147 ++++++++++++++++++++++++++

 5 files changed, 180 insertions(+), 13 deletions(-)

 create mode 100644 drivers/gpio/qe.c

#13 lore raw

Re: [PATCH 4/5] [POWERPC] QE: implement support for the GPIO LIB API

In reply to Anton Vorontsov
Quoted 11 lines · Anton Vorontsov

This is needed to access QE GPIOs via Linux GPIO API.

---
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 827b630..5c9cfab 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1721,24 +1721,32 @@ platforms are moved over to use the flattened-device-tree model.
information.

Quoted 4 lines

Required properties:

 -   - device_type : should be "par_io".
 +   - #gpio-cells : should be "2".
 +   - compatible : should be "fsl,qe-pario-bank-<bank>", "fsl,qe-pario-bank"

Once again; I don't like the generic compatible values. Please include the exact chip name in the string. ie: "fsl,<chip>-qe-pario".

"fsl,qe-pario-bank" is not a real thing. If you want a common compatible string that the driver can bind against, then choose one real part and add it to the compatible list for all the other parts.

Also, why is <bank> encoded in compatible? Do the different banks have different register interfaces?

Quoted 76 lines

- reg : offset to the register set and its length.
- - num-ports : number of Parallel I/O ports
+ - gpio-controller : node to identify gpio controllers.

- Example:
- par_io@1400 {

 -               reg = <1400 100>;
 -               #address-cells = <1>;
 -               #size-cells = <0>;
 -               device_type = "par_io";
 -               num-ports = <7>;
 -               ucc_pin@01 {
 -                       ......
 -               };
 +   For example, two QE Par I/O banks:
 +       qe_pio_a: gpio-controller@1400 {
 +               #gpio-cells = <2>;
 +               compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
 +               reg = <0x1400 0x18>;
 +               gpio-controller;

+ };

+ qe_pio_e: gpio-controller@1460 {

 +               #gpio-cells = <2>;
 +               compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
 +               reg = <0x1460 0x18>;
 +               gpio-controller;

+ };

vi) Pin configuration nodes

+ NOTE: pin configuration nodes are obsolete. Usually, their existance
+ is an evidence of the firmware shortcomings. Such fixups are
+ better handled by the Linux board file, not the device tree.
+
Required properties:
- linux,phandle : phandle of this node; likely referenced by a QE device.
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index f38c50b..f6eecd1 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -270,6 +270,8 @@ config QUICC_ENGINE
bool
select PPC_LIB_RHEAP
select CRC32
+ select GENERIC_GPIO
+ select HAVE_GPIO_LIB
help
The QUICC Engine (QE) is a new generation of communications coprocessors on Freescale embedded CPUs (akin to CPM in older chips).
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index bbd2834..cee56f9 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -25,6 +25,15 @@ config DEBUG_GPIO

  # put expanders in the right section, in alphabetical order

+comment "On-chip GPIOs:"
+
+config GPIO_QE

 +       bool "QUICC Engine GPIOs"
 +       depends on QUICC_ENGINE
 +       help

+ Say Y here to use GPIOs on the Freescale PowerPC CPUs with
+ QUICC Engine block.
+
comment "I2C GPIO expanders:"

config GPIO_PCA953X
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index fdde992..fd0a41f 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o

Quoted 4 lines
  obj-$(CONFIG_GPIO_MCP23S08)    += mcp23s08.o
  obj-$(CONFIG_GPIO_PCA953X)     += pca953x.o
  obj-$(CONFIG_GPIO_PCF857X)     += pcf857x.o
 +obj-$(CONFIG_GPIO_QE)          += qe.o

Since this isn't an of_platform or a platform driver; I'd put it into arch/powerpc instead.

Quoted 46 lines

diff --git a/drivers/gpio/qe.c b/drivers/gpio/qe.c new file mode 100644
index 0000000..474bc44
--- /dev/null
+++ b/drivers/gpio/qe.c
+static int __init qe_add_gpiochips(void) +{
+ int ret;
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "fsl,qe-pario-bank") {

 +               struct qe_gpio_chip *qe_gc;
 +               struct of_mm_gpio_chip *mm_gc;
 +               struct of_gpio_chip *of_gc;
 +               struct gpio_chip *gc;
 +
 +               qe_gc = kzalloc(sizeof(*qe_gc), GFP_KERNEL);
 +               if (!qe_gc) {
 +                       ret = -ENOMEM;
 +                       goto err;
 +               }
 +
 +               spin_lock_init(&qe_gc->lock);
 +
 +               mm_gc = &qe_gc->mm_gc;
 +               of_gc = &mm_gc->of_gc;
 +               gc = &of_gc->gc;
 +
 +               mm_gc->save_regs = qe_gpio_save_regs;
 +               of_gc->gpio_cells = 2;
 +               gc->ngpio = QE_PIO_PINS;
 +               gc->direction_input = qe_gpio_dir_in;
 +               gc->direction_output = qe_gpio_dir_out;
 +               gc->get = qe_gpio_get;
 +               gc->set = qe_gpio_set;
 +
 +               ret = of_mm_gpiochip_add(np, mm_gc);
 +               if (ret)
 +                       goto err;
 +       }
 +
 +       return 0;
 +err:
 +       pr_err("%s: registration failed with status %d\n", np->full_name, ret);
 +       of_node_put(np);
 +       return ret;
Quoted 2 lines

+}
+arch_initcall(qe_add_gpiochips);

Should this really be a arch_initcall()? Would it be better for platforms needing it to call it explicitly from one of the platform's machine_arch_initcall()? Otherwise it gets called for all platforms in a multiplatform kernel.

Cheers,
g.

Signature · 2 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
#14 lore raw

Re: [PATCH 4/5] [POWERPC] QE: implement support for the GPIO LIB API

Quoted 21 lines · Grant Likely
Quoted 11 lines · Anton Vorontsov

This is needed to access QE GPIOs via Linux GPIO API.

---
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 827b630..5c9cfab 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1721,24 +1721,32 @@ platforms are moved over to use the flattened-device-tree model.
information.

Quoted 4 lines

Required properties:

 -   - device_type : should be "par_io".
 +   - #gpio-cells : should be "2".
 +   - compatible : should be "fsl,qe-pario-bank-<bank>", "fsl,qe-pario-bank"

Once again; I don't like the generic compatible values. Please include the exact chip name in the string. ie: "fsl,<chip>-qe-pario".

Quoted 6 lines

"fsl,qe-pario-bank" is not a real thing. If you want a common compatible string that the driver can bind against, then choose one real part and add it to the compatible list for all the other parts.

Also, why is <bank> encoded in compatible? Do the different banks have different register interfaces?

Yes, they could. For example, interrupt pins are bank-specific.

Quoted 81 lines
Quoted 76 lines

- reg : offset to the register set and its length.
- - num-ports : number of Parallel I/O ports
+ - gpio-controller : node to identify gpio controllers.

- Example:
- par_io@1400 {

 -               reg = <1400 100>;
 -               #address-cells = <1>;
 -               #size-cells = <0>;
 -               device_type = "par_io";
 -               num-ports = <7>;
 -               ucc_pin@01 {
 -                       ......
 -               };
 +   For example, two QE Par I/O banks:
 +       qe_pio_a: gpio-controller@1400 {
 +               #gpio-cells = <2>;
 +               compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
 +               reg = <0x1400 0x18>;
 +               gpio-controller;

+ };

+ qe_pio_e: gpio-controller@1460 {

 +               #gpio-cells = <2>;
 +               compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
 +               reg = <0x1460 0x18>;
 +               gpio-controller;

+ };

vi) Pin configuration nodes

+ NOTE: pin configuration nodes are obsolete. Usually, their existance
+ is an evidence of the firmware shortcomings. Such fixups are
+ better handled by the Linux board file, not the device tree.
+
Required properties:
- linux,phandle : phandle of this node; likely referenced by a QE device.
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index f38c50b..f6eecd1 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -270,6 +270,8 @@ config QUICC_ENGINE
bool
select PPC_LIB_RHEAP
select CRC32
+ select GENERIC_GPIO
+ select HAVE_GPIO_LIB
help
The QUICC Engine (QE) is a new generation of communications coprocessors on Freescale embedded CPUs (akin to CPM in older chips).
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index bbd2834..cee56f9 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -25,6 +25,15 @@ config DEBUG_GPIO

  # put expanders in the right section, in alphabetical order

+comment "On-chip GPIOs:"
+
+config GPIO_QE

 +       bool "QUICC Engine GPIOs"
 +       depends on QUICC_ENGINE
 +       help

+ Say Y here to use GPIOs on the Freescale PowerPC CPUs with
+ QUICC Engine block.
+
comment "I2C GPIO expanders:"

config GPIO_PCA953X
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index fdde992..fd0a41f 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o

Quoted 4 lines
  obj-$(CONFIG_GPIO_MCP23S08)    += mcp23s08.o
  obj-$(CONFIG_GPIO_PCA953X)     += pca953x.o
  obj-$(CONFIG_GPIO_PCF857X)     += pcf857x.o
 +obj-$(CONFIG_GPIO_QE)          += qe.o
Quoted 2 lines

Since this isn't an of_platform or a platform driver; I'd put it into arch/powerpc instead.

Heh.

Quoted 49 lines
Quoted 46 lines

diff --git a/drivers/gpio/qe.c b/drivers/gpio/qe.c new file mode 100644
index 0000000..474bc44
--- /dev/null
+++ b/drivers/gpio/qe.c
+static int __init qe_add_gpiochips(void) +{
+ int ret;
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "fsl,qe-pario-bank") {

 +               struct qe_gpio_chip *qe_gc;
 +               struct of_mm_gpio_chip *mm_gc;
 +               struct of_gpio_chip *of_gc;
 +               struct gpio_chip *gc;
 +
 +               qe_gc = kzalloc(sizeof(*qe_gc), GFP_KERNEL);
 +               if (!qe_gc) {
 +                       ret = -ENOMEM;
 +                       goto err;
 +               }
 +
 +               spin_lock_init(&qe_gc->lock);
 +
 +               mm_gc = &qe_gc->mm_gc;
 +               of_gc = &mm_gc->of_gc;
 +               gc = &of_gc->gc;
 +
 +               mm_gc->save_regs = qe_gpio_save_regs;
 +               of_gc->gpio_cells = 2;
 +               gc->ngpio = QE_PIO_PINS;
 +               gc->direction_input = qe_gpio_dir_in;
 +               gc->direction_output = qe_gpio_dir_out;
 +               gc->get = qe_gpio_get;
 +               gc->set = qe_gpio_set;
 +
 +               ret = of_mm_gpiochip_add(np, mm_gc);
 +               if (ret)
 +                       goto err;
 +       }
 +
 +       return 0;
 +err:
 +       pr_err("%s: registration failed with status %d\n", np->full_name, ret);
 +       of_node_put(np);
 +       return ret;
Quoted 2 lines

+}
+arch_initcall(qe_add_gpiochips);

Quoted 4 lines

Should this really be a arch_initcall()? Would it be better for platforms needing it to call it explicitly from one of the platform's machine_arch_initcall()? Otherwise it gets called for all platforms in a multiplatform kernel.

Ok, I'll place it into qe_reset().

Signature · 3 lines
Anton Vorontsov
email: [email protected]
irc://irc.freenode.net/bd2
#15 lore raw

Re: [PATCH 4/5] [POWERPC] QE: implement support for the GPIO LIB API

On Mon, Apr 21, 2008 at 06:33:13PM +0400, Anton Vorontsov wrote:
[...]

Quoted 44 lines
Quoted 44 lines
Quoted 43 lines

+static int __init qe_add_gpiochips(void)
+{
+ int ret;
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "fsl,qe-pario-bank") {

 +               struct qe_gpio_chip *qe_gc;
 +               struct of_mm_gpio_chip *mm_gc;
 +               struct of_gpio_chip *of_gc;
 +               struct gpio_chip *gc;
 +
 +               qe_gc = kzalloc(sizeof(*qe_gc), GFP_KERNEL);
 +               if (!qe_gc) {
 +                       ret = -ENOMEM;
 +                       goto err;
 +               }
 +
 +               spin_lock_init(&qe_gc->lock);
 +
 +               mm_gc = &qe_gc->mm_gc;
 +               of_gc = &mm_gc->of_gc;
 +               gc = &of_gc->gc;
 +
 +               mm_gc->save_regs = qe_gpio_save_regs;
 +               of_gc->gpio_cells = 2;
 +               gc->ngpio = QE_PIO_PINS;
 +               gc->direction_input = qe_gpio_dir_in;
 +               gc->direction_output = qe_gpio_dir_out;
 +               gc->get = qe_gpio_get;
 +               gc->set = qe_gpio_set;
 +
 +               ret = of_mm_gpiochip_add(np, mm_gc);
 +               if (ret)
 +                       goto err;
 +       }
 +
 +       return 0;
 +err:
 +       pr_err("%s: registration failed with status %d\n", np->full_name, ret);
 +       of_node_put(np);
 +       return ret;

+}
+arch_initcall(qe_add_gpiochips);

Quoted 6 lines
Quoted 4 lines

Should this really be a arch_initcall()? Would it be better for platforms needing it to call it explicitly from one of the platform's machine_arch_initcall()? Otherwise it gets called for all platforms in a multiplatform kernel.

Ok, I'll place it into qe_reset().

Ugh, no, I can't. qe_reset() is called too early. And I don't like having every QE board file to call this through machine_arch_initcall... Hmm, what to do.. well, is this thaat bad to call this for every platform?..

Signature · 3 lines
Anton Vorontsov
email: [email protected]
irc://irc.freenode.net/bd2
#16 lore raw

Re: [PATCH 4/5] [POWERPC] QE: implement support for the GPIO LIB API

Quoted 11 lines · Anton Vorontsov
Quoted 6 lines
Quoted 4 lines

Should this really be a arch_initcall()? Would it be better for platforms needing it to call it explicitly from one of the platform's machine_arch_initcall()? Otherwise it gets called for all platforms in a multiplatform kernel.

Ok, I'll place it into qe_reset().

Ugh, no, I can't. qe_reset() is called too early. And I don't like having every QE board file to call this through machine_arch_initcall... Hmm, what to do.. well, is this thaat bad to call this for every platform?..

Its not great. It has a boot time impact for every platform compiled into the kernel. The problem gets worse every time another block of code uses this method. Personally I prefer platform code calling it explicitly.

Making it an of_platform device would also eliminate that problem, but you'd need a method to synchronize the driver with its users.

I'm not going to raise a big stink about it, but the issue should not be ignored.

Cheers,
g.

Quoted 8 lines

--
Anton Vorontsov
email: [email protected]
irc://irc.freenode.net/bd2

Signature · 2 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
#17 lore raw

Re: [PATCH 4/5] [POWERPC] QE: implement support for the GPIO LIB API

Quoted 19 lines · Grant Likely
Quoted 11 lines · Anton Vorontsov
Quoted 6 lines
Quoted 4 lines

Should this really be a arch_initcall()? Would it be better for platforms needing it to call it explicitly from one of the platform's machine_arch_initcall()? Otherwise it gets called for all platforms in a multiplatform kernel.

Ok, I'll place it into qe_reset().

Ugh, no, I can't. qe_reset() is called too early. And I don't like having every QE board file to call this through machine_arch_initcall... Hmm, what to do.. well, is this thaat bad to call this for every platform?..

Its not great. It has a boot time impact for every platform compiled into the kernel. The problem gets worse every time another block of code uses this method. Personally I prefer platform code calling it explicitly.

Quoted 5 lines

Making it an of_platform device would also eliminate that problem, but you'd need a method to synchronize the driver with its users.

I'm not going to raise a big stink about it, but the issue should not be ignored.

Heh.. how QE GPIO is different from FSL GTM then? Should I call fsl_gtm_init() from the board file too? For the every board? I do believe that years later someone will show up with something like this:

From: J. Random Hacker
Subject: [POWERPC] cleanup board initialization code

This patch removes vast amount of machine_arch_initcall()s that were used to solely initialize some hardware, like this:

qe_add_gpio_chips();
fsl_gtm_init();
fsl_spi_init();
...

So, instead of calling this stuff from the board files, we implement own arch_initcalls for these functions.

This causes negligible run-time overhead for the boards that aren't using that hardware, but this overhead isn't measurable anyway. Also, this patch shrinks .text size a bit, and produces nice looking diffstat.

 12 file changed, 6 insertions(+), 140 deletions(-)
Signature · 3 lines
Anton Vorontsov
email: [email protected]
irc://irc.freenode.net/bd2
#18 lore raw

Re: [PATCH 4/5] [POWERPC] QE: implement support for the GPIO LIB API

Quoted 6 lines · Anton Vorontsov

 From: J. Random Hacker
 Subject: [POWERPC] cleanup board initialization code

 This patch removes vast amount of machine_arch_initcall()s that were used to solely initialize some hardware, like this:

Quoted 7 lines

 qe_add_gpio_chips();
 fsl_gtm_init();
 fsl_spi_init();
 ...

 So, instead of calling this stuff from the board files, we implement own arch_initcalls for these functions.

The way other platforms do this is to hav SOC-specific init code, and have board-specific initcalls call the relevant SOC-specific setup.

Among other things that facilitates kernels that handle multiple SOCs (if they're closely-enough related). That may not be used by many distros (handhelds.org being at least a partial exception), but it certainly helps cut the number of configurations that need build-testing.

- Dave

#19 lore raw

Re: [PATCH 4/5] [POWERPC] QE: implement support for the GPIO LIB API

Quoted 12 lines · David Brownell
Quoted 11 lines · Anton Vorontsov

 From: J. Random Hacker
 Subject: [POWERPC] cleanup board initialization code

 This patch removes vast amount of machine_arch_initcall()s that were used to solely initialize some hardware, like this:

 qe_add_gpio_chips();
 fsl_gtm_init();
 fsl_spi_init();
 ...

Quoted 6 lines
Quoted 2 lines

 So, instead of calling this stuff from the board files, we implement own arch_initcalls for these functions.

The way other platforms do this is to hav SOC-specific init code, and have board-specific initcalls call the relevant SOC-specific setup.

I don't know about other platforms other than PowerPC and some ARM, of course. For example, PXA boards don't call any SOC specific code. Instead, looking into reworked PXA code, I can see that there are separate arch_initcalls() for the pxa25x, pxa27x, and pxa3xx SOCs. The same for s3cxxxx. So, at least not every platform out there doing this.

Yes, I can see AVR32. But there are only two boards, and when you'll have more, probably later you'd want to eliminate some repetitive code, if possible.

Here, with OF, it's quite simple because we have methods of "probing" SOC devices instead of placing init code into board files (think arch/ppc/).

Quoted 5 lines

Among other things that facilitates kernels that handle multiple SOCs (if they're closely-enough related). That may not be used by many distros (handhelds.org being at least a partial exception), but it certainly helps cut the number of configurations that need build-testing.

Is this about QE_GPIO being user-selectable? Yes, verbose Konfig option have its own drawbacks. Though, I don't actually have any objections for making it silent.

And well, I'm not objecting for placing qe gpio code under arch/, too. I'll resend this patch once again reverting its placement to arch/.

Signature · 3 lines
Anton Vorontsov
email: [email protected]
irc://irc.freenode.net/bd2
#20 lore raw

Re: [PATCH 4/5] [POWERPC] QE: implement support for the GPIO LIB API

Quoted 10 lines · Anton Vorontsov
Quoted 3 lines · David Brownell

The way other platforms do this is to hav SOC-specific init code, and have board-specific initcalls call the relevant SOC-specific setup.

I don't know about other platforms other than PowerPC and some ARM, of course. For example, PXA boards don't call any SOC specific code. Instead, looking into reworked PXA code, I can see that there are separate arch_initcalls() for the pxa25x, pxa27x, and pxa3xx SOCs.

Exactly: SOC-specific initcalls.

Quoted 7 lines
Quoted 5 lines

Among other things that facilitates kernels that handle multiple SOCs (if they're closely-enough related). That may not be used by many distros (handhelds.org being at least a partial exception), but it certainly helps cut the number of configurations that need build-testing.

Is this about QE_GPIO being user-selectable?

No. It's about "kernels that handle multiple SOCs". Like for example pxa{25,27,3x}x ... or omap{16xx,17xx,5912}.

Consider several ways to support a family of SOCs.

- One way supports only one board at a time. Testing builds after arch level changes means rebuilding kernels for each board ... quite possibly several dozen.

- Another supports several boards, but only if they use the same SOC. Testing builds here takes fewer kernels; one per SOC; better, but still routinely shortchanged.

- Yet another way supports any number of boards, using a variety of mostly-compatible SOCs. This allows test builds that support entire SOC families (e.g. OMAP1, or OMAP2/OMAP3, or PXA XScale, etc).

Test builds are a quality control thing. If they're done regularly, it's less likely you'll push code upstream that can't build in some configuration.

Quoted 2 lines

And well, I'm not objecting for placing qe gpio code under arch/, too. I'll resend this patch once again reverting its placement to arch/.

OK, good. Then I don't really have to be involved with that.

- Dave

#21 lore raw

Re: [PATCH 4/5] [POWERPC] QE: implement support for the GPIO LIB API

In reply to Anton Vorontsov
Quoted 20 lines · Anton Vorontsov
Quoted 10 lines · Grant Likely

Its not great. It has a boot time impact for every platform compiled into the kernel. The problem gets worse every time another block of code uses this method. Personally I prefer platform code calling it explicitly.

Making it an of_platform device would also eliminate that problem, but you'd need a method to synchronize the driver with its users.

I'm not going to raise a big stink about it, but the issue should not be ignored.

Heh.. how QE GPIO is different from FSL GTM then? Should I call fsl_gtm_init() from the board file too? For the every board? I do believe that years later someone will show up with something like this:

From: J. Random Hacker
Subject: [POWERPC] cleanup board initialization code

Quoted 6 lines

This patch removes vast amount of machine_arch_initcall()s that were used to solely initialize some hardware, like this:

  qe_add_gpio_chips();
  fsl_gtm_init();
  fsl_spi_init();

Or have a soc-level helper function for calling them for you; but yes.

And, no, we shouldn't have a vast array of individual initcalls because the platform code shouldn't be that large. As much as possible, multiple boards should be supported by the same platform code. I argue that most boards using the same SoC should use the same platform code. (see platforms/52xx/mpc5200_simple.c)

Individual calls has the added advantage that if a board port needs those functions to *not* be called (for whatever reason) then it has the ability to not call them.

It is for the same reason that the platform code is responsible for calling of_platform_bus_probe() instead of it being an initcall; it give the platform code control over the device registrations.

Cheers,
g.

Signature · 2 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
#22 lore raw

Re: [PATCH 4/5] [POWERPC] QE: implement support for the GPIO LIB API

In reply to Anton Vorontsov
Quoted 4 lines
Quoted 2 lines

Also, why is <bank> encoded in compatible? Do the different banks have different register interfaces?

Yes, they could. For example, interrupt pins are bank-specific.

In what way? If different banks just have different IRQ #s, there are easier ways to express this.

Segher

#23 lore raw

PATCH v2 5/5 83xx: new board support: MPC8360E-RDK

In reply to Anton Vorontsov

This is patch adds board file, device tree, and defconfig for the new board, made by Freescale Semiconductor Inc. and Logic Product Development.

Currently supported:
1. UEC{1,2,7,4};
2. I2C;
3. SPI;
4. NS16550 serial;
5. PCI and miniPCI;
6. Intel NOR StrataFlash X16 64Mbit PC28F640P30T85;
7. Graphics controller, Fujitsu MB86277.

Not supported in this patch:
1. StMICRO NAND512W3A2BN6E, 512 Mbit (supported with FSL UPM NAND driver);
2. FHCI USB (supported with FHCI driver).
3. QE Serial UCCs (tested to not work with ucc_uart driver, reason unknown, yet);
4. ADC AD7843 (tested to work, but support via device tree depends on major SPI rework, GPIO API, etc);

---
 arch/powerpc/boot/dts/mpc836x_rdk.dts           |  394 ++++++++
 arch/powerpc/configs/83xx/mpc836x_rdk_defconfig | 1092 +++++++++++++++++++++++
 arch/powerpc/platforms/83xx/Kconfig             |    8 +
 arch/powerpc/platforms/83xx/Makefile            |    1 +
 arch/powerpc/platforms/83xx/mpc836x_rdk.c       |  106 +++
 5 files changed, 1601 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/mpc836x_rdk.dts
 create mode 100644 arch/powerpc/configs/83xx/mpc836x_rdk_defconfig
 create mode 100644 arch/powerpc/platforms/83xx/mpc836x_rdk.c
arch/powerpc/boot/dts/mpc836x_rdk.dts new file +394 -0
new file mode 100644
index 0000000..39a7dcb
@@ -0,0 +1,394 @@
+/*
+ * MPC8360E RDK Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ * Copyright 2007-2008 MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <[email protected]>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "fsl,mpc8360rdk";
+
+	aliases {
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		ethernet3 = &enet3;
+		pci0 = &pci0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8360@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;
+			i-cache-line-size = <32>;
+			d-cache-size = <32768>;
+			i-cache-size = <32768>;
+			/* filled by u-boot */
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		/* filled by u-boot */
+		reg = <0 0>;
+	};
+
+	soc@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "fsl,mpc8360-immr", "fsl,immr", "fsl,soc",
+			     "simple-bus";
+		ranges = <0 0xe0000000 0x200000>;
+		reg = <0xe0000000 0x200>;
+		/* filled by u-boot */
+		bus-frequency = <0>;
+
+		wdt@200 {
+			compatible = "mpc83xx_wdt";
+			reg = <0x200 0x100>;
+		};
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <14 8>;
+			interrupt-parent = <&ipic>;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <16 8>;
+			interrupt-parent = <&ipic>;
+			dfsrr;
+		};
+
+		serial0: serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			interrupts = <9 8>;
+			interrupt-parent = <&ipic>;
+			/* filled by u-boot */
+			clock-frequency = <0>;
+		};
+
+		serial1: serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			interrupts = <10 8>;
+			interrupt-parent = <&ipic>;
+			/* filled by u-boot */
+			clock-frequency = <0>;
+		};
+
+		crypto@30000 {
+			compatible = "fsl,sec2-crypto";
+			reg = <0x30000 0x10000>;
+			interrupts = <11 8>;
+			interrupt-parent = <&ipic>;
+			num-channels = <4>;
+			channel-fifo-len = <24>;
+			exec-units-mask = <0x7e>;
+			/*
+			 * desc mask is for rev1.x, we need runtime fixup
+			 * for >=2.x
+			 */
+			descriptor-types-mask = <0x1010ebf>;
+		};
+
+		ipic: interrupt-controller@700 {
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			compatible = "fsl,pq2pro-pic", "fsl,ipic";
+			interrupt-controller;
+			reg = <0x700 0x100>;
+		};
+
+		qe_pio_b: gpio-controller@1418 {
+			#gpio-cells = <2>;
+			compatible = "fsl,qe-pario-bank";
+			reg = <0x1418 0x18>;
+			gpio-controller;
+		};
+
+		qe_pio_e: gpio-controller@1460 {
+			#gpio-cells = <2>;
+			compatible = "fsl,qe-pario-bank";
+			reg = <0x1460 0x18>;
+			gpio-controller;
+		};
+
+		qe@100000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			device_type = "qe";
+			compatible = "fsl,qe", "simple-bus";
+			ranges = <0 0x100000 0x100000>;
+			reg = <0x100000 0x480>;
+			/* filled by u-boot */
+			clock-frequency = <0>;
+			bus-frequency = <0>;
+			brg-frequency = <0>;
+
+			muram@10000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "fsl,qe-muram", "fsl,cpm-muram";
+				ranges = <0 0x10000 0xc000>;
+
+				data-only@0 {
+					compatible = "fsl,qe-muram-data",
+						     "fsl,cpm-muram-data";
+					reg = <0 0xc000>;
+				};
+			};
+
+			timer@440 {
+				compatible = "fsl,qe-gtm", "fsl,gtm";
+				reg = <0x440 0x40>;
+				interrupts = <12 13 14 15>;
+				interrupt-parent = <&qeic>;
+				/* filled by u-boot */
+				clock-frequency = <0>;
+			};
+
+			spi@4c0 {
+				cell-index = <0>;
+				compatible = "fsl,spi";
+				reg = <0x4c0 0x40>;
+				interrupts = <2>;
+				interrupt-parent = <&qeic>;
+				mode = "cpu-qe";
+			};
+
+			spi@500 {
+				cell-index = <1>;
+				compatible = "fsl,spi";
+				reg = <0x500 0x40>;
+				interrupts = <1>;
+				interrupt-parent = <&qeic>;
+				mode = "cpu-qe";
+			};
+
+			enet0: ucc@2000 {
+				device_type = "network";
+				compatible = "ucc_geth";
+				cell-index = <1>;
+				reg = <0x2000 0x200>;
+				interrupts = <32>;
+				interrupt-parent = <&qeic>;
+				rx-clock-name = "none";
+				tx-clock-name = "clk9";
+				phy-handle = <&phy2>;
+				phy-connection-type = "rgmii-rxid";
+				/* filled by u-boot */
+				local-mac-address = [ 00 00 00 00 00 00 ];
+			};
+
+			enet1: ucc@3000 {
+				device_type = "network";
+				compatible = "ucc_geth";
+				cell-index = <2>;
+				reg = <0x3000 0x200>;
+				interrupts = <33>;
+				interrupt-parent = <&qeic>;
+				rx-clock-name = "none";
+				tx-clock-name = "clk4";
+				phy-handle = <&phy4>;
+				phy-connection-type = "rgmii-rxid";
+				/* filled by u-boot */
+				local-mac-address = [ 00 00 00 00 00 00 ];
+			};
+
+			enet2: ucc@2600 {
+				device_type = "network";
+				compatible = "ucc_geth";
+				cell-index = <7>;
+				reg = <0x2600 0x200>;
+				interrupts = <42>;
+				interrupt-parent = <&qeic>;
+				rx-clock-name = "clk20";
+				tx-clock-name = "clk19";
+				phy-handle = <&phy1>;
+				phy-connection-type = "mii";
+				/* filled by u-boot */
+				local-mac-address = [ 00 00 00 00 00 00 ];
+			};
+
+			enet3: ucc@3200 {
+				device_type = "network";
+				compatible = "ucc_geth";
+				cell-index = <4>;
+				reg = <0x3200 0x200>;
+				interrupts = <35>;
+				interrupt-parent = <&qeic>;
+				rx-clock-name = "clk8";
+				tx-clock-name = "clk7";
+				phy-handle = <&phy3>;
+				phy-connection-type = "mii";
+				/* filled by u-boot */
+				local-mac-address = [ 00 00 00 00 00 00 ];
+			};
+
+			mdio@2120 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,ucc-mdio";
+				reg = <0x2120 0x18>;
+
+				phy1: ethernet-phy@1 {
+					device_type = "ethernet-phy";
+					compatible = "national,DP83848VV";
+					reg = <1>;
+				};
+
+				phy2: ethernet-phy@2 {
+					device_type = "ethernet-phy";
+					compatible = "broadcom,BCM5481UA2KMLG";
+					reg = <2>;
+				};
+
+				phy3: ethernet-phy@3 {
+					device_type = "ethernet-phy";
+					compatible = "national,DP83848VV";
+					reg = <3>;
+				};
+
+				phy4: ethernet-phy@4 {
+					device_type = "ethernet-phy";
+					compatible = "broadcom,BCM5481UA2KMLG";
+					reg = <4>;
+				};
+			};
+
+			serial2: ucc@2400 {
+				device_type = "serial";
+				compatible = "ucc_uart";
+				reg = <0x2400 0x200>;
+				cell-index = <5>;
+				port-number = <0>;
+				rx-clock-name = "brg7";
+				tx-clock-name = "brg8";
+				interrupts = <40>;
+				interrupt-parent = <&qeic>;
+				soft-uart;
+			};
+
+			serial3: ucc@3400 {
+				device_type = "serial";
+				compatible = "ucc_uart";
+				reg = <0x3400 0x200>;
+				cell-index = <6>;
+				port-number = <1>;
+				rx-clock-name = "brg13";
+				tx-clock-name = "brg14";
+				interrupts = <41>;
+				interrupt-parent = <&qeic>;
+				soft-uart;
+			};
+
+			qeic: interrupt-controller@80 {
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+				compatible = "fsl,qe-ic";
+				interrupt-controller;
+				reg = <0x80 0x80>;
+				big-endian;
+				interrupts = <32 8 33 8>;
+				interrupt-parent = <&ipic>;
+			};
+		};
+	};
+
+	localbus@e0005000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8360-localbus", "fsl,pq2pro-localbus",
+			     "simple-bus";
+		reg = <0xe0005000 0xd8>;
+		ranges = <0 0 0xff800000 0x0800000
+			  1 0 0x60000000 0x0001000
+			  2 0 0x70000000 0x4000000>;
+
+		flash@0,0 {
+			compatible = "intel,PC28F640P30T85", "cfi-flash";
+			reg = <0 0 0x800000>;
+			bank-width = <2>;
+			device-width = <1>;
+		};
+
+		display@2,0 {
+			device_type = "display";
+			compatible = "fujitsu,MB86277", "fujitsu,mint";
+			reg = <2 0 0x4000000>;
+			fujitsu,sh3;
+			little-endian;
+			/* filled by u-boot */
+			address = <0>;
+			depth = <0>;
+			width = <0>;
+			height = <0>;
+			linebytes = <0>;
+			/* linux,opened; - added by uboot */
+		};
+	};
+
+	pci0: pci@e0008500 {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		device_type = "pci";
+		compatible = "fsl,mpc8360-pci", "fsl,mpc8349-pci";
+		reg = <0xe0008500 0x100>;
+		ranges = <0x02000000 0 0x90000000 0x90000000 0 0x10000000
+			  0x42000000 0 0x80000000 0x80000000 0 0x10000000
+			  0x01000000 0 0xe0300000 0xe0300000 0 0x00100000>;
+		interrupts = <66 8>;
+		interrupt-parent = <&ipic>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = </* miniPCI0 IDSEL 0x14 AD20 */
+				 0xa000 0 0 1 &ipic 18 8
+				 0xa000 0 0 2 &ipic 19 8
+
+				 /* PCI1 IDSEL 0x15 AD21 */
+				 0xa800 0 0 1 &ipic 19 8
+				 0xa800 0 0 2 &ipic 20 8
+				 0xa800 0 0 3 &ipic 21 8
+				 0xa800 0 0 4 &ipic 18 8>;
+		/* filled by u-boot */
+		bus-range = <0 0>;
+		clock-frequency = <0>;
+	};
+};
arch/powerpc/configs/83xx/mpc836x_rdk_defconfig new file +1092 -0

1,092 lines not on this page · raw message

arch/powerpc/platforms/83xx/Kconfig +8 -0
index 13587e2..a5f72bb 100644
@@ -58,6 +58,14 @@ config MPC836x_MDS
 	help
 	  This option enables support for the MPC836x MDS Processor Board.
 
+config MPC836x_RDK
+	bool "Freescale/Logic MPC836x RDK"
+	select DEFAULT_UIMAGE
+	select QUICC_ENGINE
+	help
+	  This option enables support for the MPC836x RDK Processor Board,
+	  also known as ZOOM PowerQUICC Kit.
+
 config MPC837x_MDS
 	bool "Freescale MPC837x MDS"
 	select DEFAULT_UIMAGE
arch/powerpc/platforms/83xx/Makefile +1 -0
index 7e6dd3e..1fcda8e 100644
@@ -8,6 +8,7 @@ obj-$(CONFIG_MPC832x_RDB)	+= mpc832x_rdb.o
 obj-$(CONFIG_MPC834x_MDS)	+= mpc834x_mds.o
 obj-$(CONFIG_MPC834x_ITX)	+= mpc834x_itx.o
 obj-$(CONFIG_MPC836x_MDS)	+= mpc836x_mds.o
+obj-$(CONFIG_MPC836x_RDK)	+= mpc836x_rdk.o
 obj-$(CONFIG_MPC832x_MDS)	+= mpc832x_mds.o
 obj-$(CONFIG_MPC837x_MDS)	+= mpc837x_mds.o
 obj-$(CONFIG_SBC834x)		+= sbc834x.o
arch/powerpc/platforms/83xx/mpc836x_rdk.c new file +106 -0

106 lines not on this page · raw message

Signature · 1 line
1.5.5
#24 lore raw

Re: [PATCH 5/5] [POWERPC] 83xx: new board support: MPC8360E-RDK

Quoted 4 lines · Anton Vorontsov

This is patch adds board file, device tree, and defconfig for the new
board, made by Freescale Semiconductor Inc. and Logic Product Development.

  arch/powerpc/platforms/83xx/mpc836x_rdk.c       |  106 +++

I don't see anything exotic in here. This can be merged with one of the other non-exotic mpc83xx board files. The dts parsing takes care of the differences.

Cheers,
g.

Signature · 2 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
Quoted 1,653 lines
  5 files changed, 1601 insertions(+), 0 deletions(-)

create mode 100644 arch/powerpc/boot/dts/mpc836x_rdk.dts create mode 100644 arch/powerpc/configs/83xx/mpc836x_rdk_defconfig create mode 100644 arch/powerpc/platforms/83xx/mpc836x_rdk.c

diff --git a/arch/powerpc/boot/dts/mpc836x_rdk.dts b/arch/powerpc/boot/dts/mpc836x_rdk.dts new file mode 100644
index 0000000..39a7dcb
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc836x_rdk.dts
@@ -0,0 +1,394 @@
+/*
+ * MPC8360E RDK Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ * Copyright 2007-2008 MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+
+/ {

 +       #address-cells = <1>;
 +       #size-cells = <1>;
 +       compatible = "fsl,mpc8360rdk";
 +
 +       aliases {
 +               serial0 = &serial0;
 +               serial1 = &serial1;
 +               serial2 = &serial2;
 +               serial3 = &serial3;
 +               ethernet0 = &enet0;
 +               ethernet1 = &enet1;
 +               ethernet2 = &enet2;
 +               ethernet3 = &enet3;
 +               pci0 = &pci0;
 +       };
 +
 +       cpus {
 +               #address-cells = <1>;
 +               #size-cells = <0>;
 +
 +               PowerPC,8360@0 {
 +                       device_type = "cpu";
 +                       reg = <0>;
 +                       d-cache-line-size = <32>;
 +                       i-cache-line-size = <32>;
 +                       d-cache-size = <32768>;
 +                       i-cache-size = <32768>;
 +                       /* filled by u-boot */
 +                       timebase-frequency = <0>;
 +                       bus-frequency = <0>;
 +                       clock-frequency = <0>;
 +               };
 +       };
 +
 +       memory {
 +               device_type = "memory";
 +               /* filled by u-boot */
 +               reg = <0 0>;
 +       };
 +
 +       soc@e0000000 {
 +               #address-cells = <1>;
 +               #size-cells = <1>;
 +               device_type = "soc";
 +               compatible = "fsl,mpc8360-immr", "fsl,immr", "fsl,soc",
 +                            "simple-bus";
 +               ranges = <0 0xe0000000 0x200000>;
 +               reg = <0xe0000000 0x200>;
 +               /* filled by u-boot */
 +               bus-frequency = <0>;
 +
 +               wdt@200 {
 +                       compatible = "mpc83xx_wdt";
 +                       reg = <0x200 0x100>;
 +               };
 +
 +               i2c@3000 {
 +                       #address-cells = <1>;
 +                       #size-cells = <0>;
 +                       cell-index = <0>;
 +                       compatible = "fsl-i2c";
 +                       reg = <0x3000 0x100>;
 +                       interrupts = <14 8>;
 +                       interrupt-parent = <&ipic>;
 +                       dfsrr;
 +               };
 +
 +               i2c@3100 {
 +                       #address-cells = <1>;
 +                       #size-cells = <0>;
 +                       cell-index = <1>;
 +                       compatible = "fsl-i2c";
 +                       reg = <0x3100 0x100>;
 +                       interrupts = <16 8>;
 +                       interrupt-parent = <&ipic>;
 +                       dfsrr;
 +               };
 +
 +               serial0: serial@4500 {
 +                       device_type = "serial";
 +                       compatible = "ns16550";
 +                       reg = <0x4500 0x100>;
 +                       interrupts = <9 8>;
 +                       interrupt-parent = <&ipic>;
 +                       /* filled by u-boot */
 +                       clock-frequency = <0>;
 +               };
 +
 +               serial1: serial@4600 {
 +                       device_type = "serial";
 +                       compatible = "ns16550";
 +                       reg = <0x4600 0x100>;
 +                       interrupts = <10 8>;
 +                       interrupt-parent = <&ipic>;
 +                       /* filled by u-boot */
 +                       clock-frequency = <0>;
 +               };
 +
 +               crypto@30000 {
 +                       compatible = "fsl,sec2-crypto";
 +                       reg = <0x30000 0x10000>;
 +                       interrupts = <11 8>;
 +                       interrupt-parent = <&ipic>;
 +                       num-channels = <4>;
 +                       channel-fifo-len = <24>;
 +                       exec-units-mask = <0x7e>;
 +                       /*
 +                        * desc mask is for rev1.x, we need runtime fixup
 +                        * for >=2.x
 +                        */
 +                       descriptor-types-mask = <0x1010ebf>;
 +               };
 +
 +               ipic: interrupt-controller@700 {
 +                       #address-cells = <0>;
 +                       #interrupt-cells = <2>;
 +                       compatible = "fsl,pq2pro-pic", "fsl,ipic";
 +                       interrupt-controller;
 +                       reg = <0x700 0x100>;
 +               };
 +
 +               qe_pio_b: gpio-controller@1418 {
 +                       #gpio-cells = <2>;
 +                       compatible = "fsl,qe-pario-bank";
 +                       reg = <0x1418 0x18>;
 +                       gpio-controller;
 +               };
 +
 +               qe_pio_e: gpio-controller@1460 {
 +                       #gpio-cells = <2>;
 +                       compatible = "fsl,qe-pario-bank";
 +                       reg = <0x1460 0x18>;
 +                       gpio-controller;
 +               };
 +
 +               qe@100000 {
 +                       #address-cells = <1>;
 +                       #size-cells = <1>;
 +                       device_type = "qe";
 +                       compatible = "fsl,qe", "simple-bus";
 +                       ranges = <0 0x100000 0x100000>;
 +                       reg = <0x100000 0x480>;
 +                       /* filled by u-boot */
 +                       clock-frequency = <0>;
 +                       bus-frequency = <0>;
 +                       brg-frequency = <0>;
 +
 +                       muram@10000 {
 +                               #address-cells = <1>;
 +                               #size-cells = <1>;
 +                               compatible = "fsl,qe-muram", "fsl,cpm-muram";
 +                               ranges = <0 0x10000 0xc000>;
 +
 +                               data-only@0 {
 +                                       compatible = "fsl,qe-muram-data",
 +                                                    "fsl,cpm-muram-data";
 +                                       reg = <0 0xc000>;
 +                               };
 +                       };
 +
 +                       timer@440 {
 +                               compatible = "fsl,qe-gtm", "fsl,gtm";
 +                               reg = <0x440 0x40>;
 +                               interrupts = <12 13 14 15>;
 +                               interrupt-parent = <&qeic>;
 +                               /* filled by u-boot */
 +                               clock-frequency = <0>;
 +                       };
 +
 +                       spi@4c0 {
 +                               cell-index = <0>;
 +                               compatible = "fsl,spi";
 +                               reg = <0x4c0 0x40>;
 +                               interrupts = <2>;
 +                               interrupt-parent = <&qeic>;
 +                               mode = "cpu-qe";
 +                       };
 +
 +                       spi@500 {
 +                               cell-index = <1>;
 +                               compatible = "fsl,spi";
 +                               reg = <0x500 0x40>;
 +                               interrupts = <1>;
 +                               interrupt-parent = <&qeic>;
 +                               mode = "cpu-qe";
 +                       };
 +
 +                       enet0: ucc@2000 {
 +                               device_type = "network";
 +                               compatible = "ucc_geth";
 +                               cell-index = <1>;
 +                               reg = <0x2000 0x200>;
 +                               interrupts = <32>;
 +                               interrupt-parent = <&qeic>;
 +                               rx-clock-name = "none";
 +                               tx-clock-name = "clk9";
 +                               phy-handle = <&phy2>;
 +                               phy-connection-type = "rgmii-rxid";
 +                               /* filled by u-boot */
 +                               local-mac-address = [ 00 00 00 00 00 00 ];
 +                       };
 +
 +                       enet1: ucc@3000 {
 +                               device_type = "network";
 +                               compatible = "ucc_geth";
 +                               cell-index = <2>;
 +                               reg = <0x3000 0x200>;
 +                               interrupts = <33>;
 +                               interrupt-parent = <&qeic>;
 +                               rx-clock-name = "none";
 +                               tx-clock-name = "clk4";
 +                               phy-handle = <&phy4>;
 +                               phy-connection-type = "rgmii-rxid";
 +                               /* filled by u-boot */
 +                               local-mac-address = [ 00 00 00 00 00 00 ];
 +                       };
 +
 +                       enet2: ucc@2600 {
 +                               device_type = "network";
 +                               compatible = "ucc_geth";
 +                               cell-index = <7>;
 +                               reg = <0x2600 0x200>;
 +                               interrupts = <42>;
 +                               interrupt-parent = <&qeic>;
 +                               rx-clock-name = "clk20";
 +                               tx-clock-name = "clk19";
 +                               phy-handle = <&phy1>;
 +                               phy-connection-type = "mii";
 +                               /* filled by u-boot */
 +                               local-mac-address = [ 00 00 00 00 00 00 ];
 +                       };
 +
 +                       enet3: ucc@3200 {
 +                               device_type = "network";
 +                               compatible = "ucc_geth";
 +                               cell-index = <4>;
 +                               reg = <0x3200 0x200>;
 +                               interrupts = <35>;
 +                               interrupt-parent = <&qeic>;
 +                               rx-clock-name = "clk8";
 +                               tx-clock-name = "clk7";
 +                               phy-handle = <&phy3>;
 +                               phy-connection-type = "mii";
 +                               /* filled by u-boot */
 +                               local-mac-address = [ 00 00 00 00 00 00 ];
 +                       };
 +
 +                       mdio@2120 {
 +                               #address-cells = <1>;
 +                               #size-cells = <0>;
 +                               compatible = "fsl,ucc-mdio";
 +                               reg = <0x2120 0x18>;
 +
 +                               phy1: ethernet-phy@1 {
 +                                       device_type = "ethernet-phy";
 +                                       compatible = "national,DP83848VV";
 +                                       reg = <1>;
 +                               };
 +
 +                               phy2: ethernet-phy@2 {
 +                                       device_type = "ethernet-phy";
 +                                       compatible = "broadcom,BCM5481UA2KMLG";
 +                                       reg = <2>;
 +                               };
 +
 +                               phy3: ethernet-phy@3 {
 +                                       device_type = "ethernet-phy";
 +                                       compatible = "national,DP83848VV";
 +                                       reg = <3>;
 +                               };
 +
 +                               phy4: ethernet-phy@4 {
 +                                       device_type = "ethernet-phy";
 +                                       compatible = "broadcom,BCM5481UA2KMLG";
 +                                       reg = <4>;
 +                               };
 +                       };
 +
 +                       serial2: ucc@2400 {
 +                               device_type = "serial";
 +                               compatible = "ucc_uart";
 +                               reg = <0x2400 0x200>;
 +                               cell-index = <5>;
 +                               port-number = <0>;
 +                               rx-clock-name = "brg7";
 +                               tx-clock-name = "brg8";
 +                               interrupts = <40>;
 +                               interrupt-parent = <&qeic>;
 +                               soft-uart;
 +                       };
 +
 +                       serial3: ucc@3400 {
 +                               device_type = "serial";
 +                               compatible = "ucc_uart";
 +                               reg = <0x3400 0x200>;
 +                               cell-index = <6>;
 +                               port-number = <1>;
 +                               rx-clock-name = "brg13";
 +                               tx-clock-name = "brg14";
 +                               interrupts = <41>;
 +                               interrupt-parent = <&qeic>;
 +                               soft-uart;
 +                       };
 +
 +                       qeic: interrupt-controller@80 {
 +                               #address-cells = <0>;
 +                               #interrupt-cells = <1>;
 +                               compatible = "fsl,qe-ic";
 +                               interrupt-controller;
 +                               reg = <0x80 0x80>;
 +                               big-endian;
 +                               interrupts = <32 8 33 8>;
 +                               interrupt-parent = <&ipic>;
 +                       };
 +               };
 +       };
 +
 +       localbus@e0005000 {
 +               #address-cells = <2>;
 +               #size-cells = <1>;
 +               compatible = "fsl,mpc8360-localbus", "fsl,pq2pro-localbus",
 +                            "simple-bus";
 +               reg = <0xe0005000 0xd8>;
 +               ranges = <0 0 0xff800000 0x0800000
 +                         1 0 0x60000000 0x0001000
 +                         2 0 0x70000000 0x4000000>;
 +
 +               flash@0,0 {
 +                       compatible = "intel,PC28F640P30T85", "cfi-flash";
 +                       reg = <0 0 0x800000>;
 +                       bank-width = <2>;
 +                       device-width = <1>;
 +               };
 +
 +               display@2,0 {
 +                       device_type = "display";
 +                       compatible = "fujitsu,MB86277", "fujitsu,mint";
 +                       reg = <2 0 0x4000000>;
 +                       fujitsu,sh3;
 +                       little-endian;
 +                       /* filled by u-boot */
 +                       address = <0>;
 +                       depth = <0>;
 +                       width = <0>;
 +                       height = <0>;
 +                       linebytes = <0>;
 +                       /* linux,opened; - added by uboot */
 +               };
 +       };
 +
 +       pci0: pci@e0008500 {
 +               #address-cells = <3>;
 +               #size-cells = <2>;
 +               #interrupt-cells = <1>;
 +               device_type = "pci";
 +               compatible = "fsl,mpc8360-pci", "fsl,mpc8349-pci";
 +               reg = <0xe0008500 0x100>;
 +               ranges = <0x02000000 0 0x90000000 0x90000000 0 0x10000000
 +                         0x42000000 0 0x80000000 0x80000000 0 0x10000000
 +                         0x01000000 0 0xe0300000 0xe0300000 0 0x00100000>;
 +               interrupts = <66 8>;
 +               interrupt-parent = <&ipic>;
 +               interrupt-map-mask = <0xf800 0 0 7>;
 +               interrupt-map = </* miniPCI0 IDSEL 0x14 AD20 */
 +                                0xa000 0 0 1 &ipic 18 8
 +                                0xa000 0 0 2 &ipic 19 8
 +
 +                                /* PCI1 IDSEL 0x15 AD21 */
 +                                0xa800 0 0 1 &ipic 19 8
 +                                0xa800 0 0 2 &ipic 20 8
 +                                0xa800 0 0 3 &ipic 21 8
 +                                0xa800 0 0 4 &ipic 18 8>;
 +               /* filled by u-boot */
 +               bus-range = <0 0>;
 +               clock-frequency = <0>;

+ };
+};
diff --git a/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig b/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig new file mode 100644
index 0000000..f8bde7b
--- /dev/null
+++ b/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig
@@ -0,0 +1,1092 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.25-rc9
+# Fri Apr 18 22:25:18 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+# CONFIG_FSL_EMB_PERFMON is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Platform support
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_PPC_82xx is not set
+CONFIG_PPC_83xx=y
+# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_MPC512x is not set
+# CONFIG_PPC_MPC5121 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+CONFIG_MPC83xx=y
+# CONFIG_MPC831x_RDB is not set
+# CONFIG_MPC832x_MDS is not set
+# CONFIG_MPC832x_RDB is not set
+# CONFIG_MPC834x_MDS is not set
+# CONFIG_MPC834x_ITX is not set
+# CONFIG_MPC836x_MDS is not set
+CONFIG_MPC836x_RDK=y
+# CONFIG_MPC837x_MDS is not set
+# CONFIG_MPC837x_RDB is not set
+# CONFIG_SBC834x is not set
+CONFIG_IPIC=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_QUICC_ENGINE=y
+# CONFIG_FSL_ULI1575 is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0xc0000000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_OF_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_I2C=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+CONFIG_BROADCOM_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_NET_ETHERNET is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_E1000E_ENABLED is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_GIANFAR is not set
+CONFIG_UCC_GETH=y
+CONFIG_UGETH_NAPI=y
+# CONFIG_UGETH_MAGIC_PACKET is not set
+# CONFIG_UGETH_FILTERING is not set
+# CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_SERIAL_QE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_MPC83xx=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_HAVE_GPIO_LIB=y
+
+#
+# GPIO Support
+#
+
+#
+# On-chip GPIOs:
+#
+CONFIG_GPIO_QE=y
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_83xx_WDT=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+CONFIG_FB_MACMODES=y
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+CONFIG_UCC_SLOW=y
+CONFIG_UCC_FAST=y
+CONFIG_UCC=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_PPC_EARLY_DEBUG=y
+# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
+# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
+# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
+# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
+# CONFIG_PPC_EARLY_DEBUG_44x is not set
+# CONFIG_PPC_EARLY_DEBUG_40x is not set
+# CONFIG_PPC_EARLY_DEBUG_CPM is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+# CONFIG_CRYPTO_SEQIV is not set
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_PPC_CLOCK is not set
+CONFIG_PPC_LIB_RHEAP=y
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 13587e2..a5f72bb 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -58,6 +58,14 @@ config MPC836x_MDS
help
This option enables support for the MPC836x MDS Processor Board.

+config MPC836x_RDK

 +       bool "Freescale/Logic MPC836x RDK"
 +       select DEFAULT_UIMAGE
 +       select QUICC_ENGINE
 +       help
 +         This option enables support for the MPC836x RDK Processor Board,
 +         also known as ZOOM PowerQUICC Kit.
 +
  config MPC837x_MDS
        bool "Freescale MPC837x MDS"
        select DEFAULT_UIMAGE
 diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
 index 7e6dd3e..1fcda8e 100644
 --- a/arch/powerpc/platforms/83xx/Makefile
 +++ b/arch/powerpc/platforms/83xx/Makefile
 @@ -8,6 +8,7 @@ obj-$(CONFIG_MPC832x_RDB)       += mpc832x_rdb.o
  obj-$(CONFIG_MPC834x_MDS)      += mpc834x_mds.o
  obj-$(CONFIG_MPC834x_ITX)      += mpc834x_itx.o
  obj-$(CONFIG_MPC836x_MDS)      += mpc836x_mds.o
 +obj-$(CONFIG_MPC836x_RDK)      += mpc836x_rdk.o
  obj-$(CONFIG_MPC832x_MDS)      += mpc832x_mds.o
  obj-$(CONFIG_MPC837x_MDS)      += mpc837x_mds.o
  obj-$(CONFIG_SBC834x)          += sbc834x.o
 diff --git a/arch/powerpc/platforms/83xx/mpc836x_rdk.c b/arch/powerpc/platforms/83xx/mpc836x_rdk.c
 new file mode 100644
 index 0000000..b6c4b38
 --- /dev/null
 +++ b/arch/powerpc/platforms/83xx/mpc836x_rdk.c
 @@ -0,0 +1,106 @@
 +/*
 + * MPC8360E-RDK board file.
 + *
 + * Copyright (c) 2006  Freescale Semicondutor, Inc.
 + * Copyright (c) 2007-2008  MontaVista Software, Inc.
 + *
 + * Author: Anton Vorontsov <[email protected]>
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under  the terms of  the GNU General  Public License as published by the
 + * Free Software Foundation;  either version 2 of the  License, or (at your
 + * option) any later version.
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/pci.h>
 +#include <linux/of_platform.h>
 +#include <linux/io.h>
 +#include <asm/prom.h>
 +#include <asm/time.h>
 +#include <asm/ipic.h>
 +#include <asm/udbg.h>
 +#include <asm/qe.h>
 +#include <asm/qe_ic.h>
 +#include <sysdev/fsl_soc.h>
 +
 +#include "mpc83xx.h"
 +
 +static struct of_device_id __initdata mpc836x_rdk_ids[] = {
 +       { .compatible = "simple-bus", },
 +       {},
 +};
 +
 +static int __init mpc836x_rdk_declare_of_platform_devices(void)
 +{
 +       return of_platform_bus_probe(NULL, mpc836x_rdk_ids, NULL);
 +}
 +machine_device_initcall(mpc836x_rdk, mpc836x_rdk_declare_of_platform_devices);
 +
 +static void __init mpc836x_rdk_setup_arch(void)
 +{
 +#ifdef CONFIG_PCI
 +       struct device_node *np;
 +#endif
 +
 +       if (ppc_md.progress)
 +               ppc_md.progress("mpc836x_rdk_setup_arch()", 0);
 +
 +#ifdef CONFIG_PCI
 +       for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
 +               mpc83xx_add_bridge(np);
 +#endif
 +
 +#ifdef CONFIG_QUICC_ENGINE
 +       qe_reset();
 +#endif
 +}
 +
 +static void __init mpc836x_rdk_init_IRQ(void)
 +{
 +       struct device_node *np;
 +
 +       np = of_find_compatible_node(NULL, NULL, "fsl,ipic");
 +       if (!np)
 +               return;
 +
 +       ipic_init(np, 0);
 +
 +       /*
 +        * Initialize the default interrupt mapping priorities,
 +        * in case the boot rom changed something on us.
 +        */
 +       ipic_set_default_priority();
 +       of_node_put(np);
 +
 +#ifdef CONFIG_QUICC_ENGINE
 +       np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
 +       if (!np)
 +               return;
 +
 +       qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
 +       of_node_put(np);
 +#endif
 +}
 +
 +/*
 + * Called very early, MMU is off, device-tree isn't unflattened.
 + */
 +static int __init mpc836x_rdk_probe(void)
 +{
 +       unsigned long root = of_get_flat_dt_root();
 +
 +       return of_flat_dt_is_compatible(root, "fsl,mpc8360rdk");
 +}
 +
 +define_machine(mpc836x_rdk) {
 +       .name           = "MPC836x RDK",
 +       .probe          = mpc836x_rdk_probe,
 +       .setup_arch     = mpc836x_rdk_setup_arch,
 +       .init_IRQ       = mpc836x_rdk_init_IRQ,
 +       .get_irq        = ipic_get_irq,
 +       .restart        = mpc83xx_restart,
 +       .time_init      = mpc83xx_time_init,
 +       .calibrate_decr = generic_calibrate_decr,
 +       .progress       = udbg_progress,

+};
--
1.5.5
_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Signature · 2 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
#25 lore raw

Re: [PATCH 5/5] [POWERPC] 83xx: new board support: MPC8360E-RDK

Quoted 10 lines · Grant Likely
Quoted 4 lines · Anton Vorontsov

This is patch adds board file, device tree, and defconfig for the new
board, made by Freescale Semiconductor Inc. and Logic Product Development.

  arch/powerpc/platforms/83xx/mpc836x_rdk.c       |  106 +++

I don't see anything exotic in here. This can be merged with one of the other non-exotic mpc83xx board files. The dts parsing takes care of the differences.

Please name the board file in which you think I'll easily merge this indeed non-exotic board.

The only QE boards there are: mpc832x_{rdb,mds} and mpc836x_mds. All of them have board-specific fixups either in the machine_device_initcall()s or setup_arch()s.

Signature · 3 lines
Anton Vorontsov
email: [email protected]
irc://irc.freenode.net/bd2