Skip to contentSkip to conversation

Patches for Kumar's powerpc-next tree

PATCH Applied Anton Vorontsov 5 participants 26 messages May 19, 2008 – Jun 24, 2008

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

cover Patches for Kumar's powerpc-next tree

Hello Kumar,

Please consider applying these patches.

[PATCH 1/7] [POWERPC] sysdev: implement FSL GTM support ^ no changes

[PATCH 2/7] [POWERPC] QE: add support for QE USB clocks routing [PATCH 3/7] [POWERPC] QE: prepare QE PIO code for GPIO LIB support [PATCH 4/7] [POWERPC] QE: implement support for the GPIO LIB API ^ added Acked-By: Timur Tabi <[email protected]>

[PATCH 5/7] [POWERPC] 83xx: new board support: MPC8360E-RDK
[PATCH 6/7] [POWERPC] booting-without-of: add FHCI USB, FSL MCU, FSL UPM and GPIO LEDs bindings ^ no changes

[PATCH 7/7] [POWERPC] qe_lib: switch to the cpm_muram implementation ^ Added qe_* -> cpm_* defines.

Thanks,

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

PATCH 1/7 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 |   37 +++-
 arch/powerpc/Kconfig                         |    5 +
 arch/powerpc/sysdev/Makefile                 |    1 +
 arch/powerpc/sysdev/fsl_gtm.c                |  424 ++++++++++++++++++++++++++
 include/asm-powerpc/fsl_gtm.h                |   47 +++
 5 files changed, 513 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 +36 -1
index 1d2a772..fc7a235 100644
@@ -57,7 +57,10 @@ 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 Display Interface Unit
+      s) Freescale on board FPGA
+      t) Freescale General-purpose Timers Module
 
   VII - Marvell Discovery mv64[345]6x System Controller chips
     1) The /system-controller node
@@ -2870,6 +2873,38 @@ platforms are moved over to use the flattened-device-tree model.
 		reg = <0xe8000000 32>;
 	};
 
+    t) Freescale General-purpose Timers Module
+
+    Required properties:
+      - compatible : should be
+        "fsl,<chip>-gtm", "fsl,gtm" for SOC GTMs
+        "fsl,<chip>-qe-gtm", "fsl,qe-gtm", "fsl,gtm" for QE GTMs
+        "fsl,<chip>-cpm2-gtm", "fsl,cpm2-gtm", "fsl,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,mpc8360-gtm", "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,mpc8360-qe-gtm", "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 3934e26..e5d3366 100644
@@ -538,6 +538,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 2cc5052..f55e661 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 +424 -0

424 lines not on this page · raw message

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

47 lines not on this page · raw message

Signature · 1 line
1.5.5.1
#2 lore raw

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

Quoted 34 lines · Anton Vorontsov

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 |   37 +++-
arch/powerpc/Kconfig                         |    5 +
arch/powerpc/sysdev/Makefile                 |    1 +
arch/powerpc/sysdev/fsl_gtm.c                |  424 +++++++++++++++++=20=

+++++++++
include/asm-powerpc/fsl_gtm.h | 47 +++

5 files changed, 513 insertions(+), 1 deletions(-)

create mode 100644 arch/powerpc/sysdev/fsl_gtm.c
create mode 100644 include/asm-powerpc/fsl_gtm.h

arch/powerpc/Kconfig +0 -0
index 3934e26..e5d3366 100644

arch/powerpc/Kconfig config FSL_LBC · line 542

Quoted 5 lines
arch/powerpc/Kconfig +2 -0
@@ -538,6 +538,11 @@ config FSL_LBC
 	help
 	  Freescale Localbus support
 
+config FSL_GTM
+	bool

I'd prefer something like:

depends on PPC_83xx || QUICC_ENGINE || CPM2

Quoted 46 lines
arch/powerpc/Kconfig +3 -0
+	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/=20 renamed from arch/powerpc/sysdev/fsl_gtm.c +0 -0

fsl_gtm.c
new file mode 100644
index 0000000..8b35cc4

arch/powerpc/sysdev/fsl_gtm.c new file +10 -0
@@ -0,0 +1,424 @@
+/*
+ * 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 =20

modify it
+ * under the terms of the GNU General Public License as =20 published by the
+ * Free Software Foundation; either version 2 of the License, or =20=

(at your
+ * option) any later version.
+ */

arch/powerpc/sysdev/fsl_gtm.c new file +13 -0
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <asm/fsl_gtm.h>
+
+#define GTCFR_STP(x)		((x) & 1 ? 1 << 5 : 1 << 1)
+#define GTCFR_RST(x)		((x) & 1 ? 1 << 4 : 1 << 0)
+

arch/powerpc/sysdev/fsl_gtm.c

Quoted 10 lines
arch/powerpc/sysdev/fsl_gtm.c new file +10 -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 */

arch/powerpc/sysdev/fsl_gtm.c

Quoted 2 lines
arch/powerpc/sysdev/fsl_gtm.c new file +2 -0
+	u8	res0[0x3];
+	u8	gtcfr2;		/* Timer 3, timer 4 global config =

register */

Quoted 41 lines
arch/powerpc/sysdev/fsl_gtm.c new file +40 -0
+	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 {
+	unsigned int clock;
+	struct gtm_timers_regs __iomem *regs;
+	struct gtm_timer timers[4];
+	spinlock_t lock;
+	struct list_head list_node;
+};
+
+static LIST_HEAD(gtms);
+
+/**
+ * gtm_get_timer - request GTM timer to use it with the rest of GTM =20=
Quoted 2 lines

API
+ * @width: timer width (only 16 bits wide timers implemented so =

far)

Quoted 31 lines

+ *
+ * This function reserves GTM timer for later use. It returns =20 gtm_timer
+ * structure to use with the rest of GTM API, you should use timer-=20=

Quoted 1 line

irq

+ * to manage timer interrupt.
+ */

arch/powerpc/sysdev/fsl_gtm.c new file +23 -0
+struct gtm_timer *gtm_get_timer(int width)
+{
+	struct gtm *gtm =3D NULL;
+	int i;
+
+	if (width !=3D 16)
+		return ERR_PTR(-ENOSYS);
+
+	list_for_each_entry(gtm, &gtms, list_node) {
+		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);
+				return &gtm->timers[i];
+			}
+		}
+
+		spin_unlock_irq(&gtm->lock);
+	}
+
+	if (gtm)

arch/powerpc/sysdev/fsl_gtm.c

Quoted 10 lines
arch/powerpc/sysdev/fsl_gtm.c new file +10 -0
+		return ERR_PTR(-EBUSY);
+	return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL(gtm_get_timer);
+
+/**
+ * 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 10 lines

+ *
+ * This function reserves GTM timer for later use. It returns =20 gtm_timer
+ * structure to use with the rest of GTM API, you should use timer-=20=

Quoted 1 line

irq

+ * to manage timer interrupt.
+ */
+struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, int =20 timer, int width)

arch/powerpc/sysdev/fsl_gtm.c line 92

Quoted 5 lines
arch/powerpc/sysdev/fsl_gtm.c new file +5 -0
+{
+	struct gtm_timer *ret =3D ERR_PTR(-EBUSY);
+
+	if (width !=3D 16)
+		return ERR_PTR(-ENOSYS);

should we not range check timer (since it can only be 0..3)?

Quoted 8 lines
arch/powerpc/sysdev/fsl_gtm.c new file +8 -0
+
+	spin_lock_irq(&gtm->lock);
+
+	if (gtm->timers[timer].requested)
+		goto out;
+
+	ret =3D &gtm->timers[timer];
+	ret->requested =3D true;

arch/powerpc/sysdev/fsl_gtm.c

Quoted 10 lines
arch/powerpc/sysdev/fsl_gtm.c new file +10 -0
+
+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)

arch/powerpc/sysdev/fsl_gtm.c

Quoted 8 lines

+ *
+ * This function releases GTM timer so others may request it.
+ */

arch/powerpc/sysdev/fsl_gtm.c new file +5 -0
+void gtm_put_timer(struct gtm_timer *tmr)
+{
+	spin_lock_irq(&tmr->gtm->lock);
+
+	tmr->requested =3D false;

should we not stop the timer as well?

Quoted 22 lines
arch/powerpc/sysdev/fsl_gtm.c new file +7 -0
+
+	spin_unlock_irq(&tmr->gtm->lock);
+}
+EXPORT_SYMBOL(gtm_put_timer);
+
+/*
+ * This is back-end for the exported functions, it's used to reset =20=

single
+ * timer in reference mode.
+ */
+static int gtm_reset_ref_timer16(struct gtm_timer *tmr, int =20 frequency,

arch/powerpc/sysdev/fsl_gtm.c new file +8 -0
+				 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;

arch/powerpc/sysdev/fsl_gtm.c

Quoted 10 lines
arch/powerpc/sysdev/fsl_gtm.c new file +10 -0
+	unsigned long flags;
+	int max_prescaler =3D 256 * 256 * 16;
+
+	/* 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, =

sps),

arch/powerpc/sysdev/fsl_gtm.c

Quoted 2 lines
arch/powerpc/sysdev/fsl_gtm.c new file +2 -0
+	 * plus "slow go" mode (clk / 16). So, total prescale value is
+	 * 16 * (psr + 1) * (sps + 1). Though, for CPM2 GTMs we losing =

psr.

Quoted 11 lines
arch/powerpc/sysdev/fsl_gtm.c new file +11 -0
+	 */
+	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;

arch/powerpc/sysdev/fsl_gtm.c

Quoted 10 lines
arch/powerpc/sysdev/fsl_gtm.c new file +10 -0
+		sps =3D prescaler - 1;
+	} else {
+		psr =3D 256 - 1;
+		sps =3D prescaler / 256 - 1;
+	}
+
+	spin_lock_irqsave(&gtm->lock, flags);
+
+	/*
+	 * Properly reset timers: stop, reset, set up prescalers, =

reference

Quoted 32 lines
arch/powerpc/sysdev/fsl_gtm.c new file +25 -0
+	 * 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 =20

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 =20=

Quoted 6 lines

requested
+ * interval value, and fires the interrupt when the value is =20 reached. This
+ * function will reduce the precision of the timer as needed in =20 order for the
+ * requested timeout to fit in a 16-bit register.

is this save to call in interrupt context?

arch/powerpc/sysdev/fsl_gtm.c

Quoted 6 lines

+ */
+int gtm_reset_timer16(struct gtm_timer *tmr, unsigned long usec, =20 bool reload)

arch/powerpc/sysdev/fsl_gtm.c new file +2 -0
+{
+	/* quite obvious, frequency which is enough for =C2=B5Sec =

precision */

Quoted 30 lines
arch/powerpc/sysdev/fsl_gtm.c new file +19 -0
+	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;
+
+	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 =20

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 =20 requested
+ * interval value, and fires the interrupt when the value is =20 reached. If reload
+ * flag was set, timer will also reset itself upon reference value, =20=

Quoted 2 lines

otherwise
+ * it continues to increment.

is this save to call in interrupt context?

arch/powerpc/sysdev/fsl_gtm.c

Quoted 5 lines

+ */

arch/powerpc/sysdev/fsl_gtm.c new file +3 -0
+int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool reload)
+{
+	/* quite obvious, frequency which is enough for =C2=B5Sec =

precision */

arch/powerpc/sysdev/fsl_gtm.c

Quoted 4 lines
arch/powerpc/sysdev/fsl_gtm.c new file +4 -0
+	const int freq =3D 1000000;
+
+	/*
+	 * We can lower the frequency (and probably power consumption) =

by

arch/powerpc/sysdev/fsl_gtm.c

Quoted 3 lines
arch/powerpc/sysdev/fsl_gtm.c new file +1 -0
+	 * dividing both frequency and usec by 2 until there is no =20

remainder.

arch/powerpc/sysdev/fsl_gtm.c new file +1 -0
+	 * But we won't bother with this unless savings are measured, so =

=20

Quoted 41 lines

just

arch/powerpc/sysdev/fsl_gtm.c new file +10 -0
+	 * 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 =20

gtm_get_timer
+ *
+ * This function simply stops the GTM timer.
+ */

arch/powerpc/sysdev/fsl_gtm.c new file +18 -0
+void gtm_stop_timer16(struct gtm_timer *tmr)
+{
+	struct gtm *gtm =3D tmr->gtm;
+	int num =3D 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);
+
+/**
+ * gtm_ack_timer16 - acknowledge timer event (free-run timers only)
+ * @tmr:	pointer to the gtm_timer structure obtained from =20

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

inside the
+ * interrupt handler.
+ */

arch/powerpc/sysdev/fsl_gtm.c

Quoted 9 lines
arch/powerpc/sysdev/fsl_gtm.c new file +9 -0
+void gtm_ack_timer16(struct gtm_timer *tmr, u16 events)
+{
+	out_be16(tmr->gtevr, events);
+}
+EXPORT_SYMBOL(gtm_ack_timer16);
+
+static void __init gtm_set_shortcuts(struct device_node *np,
+				     struct gtm_timer *timers,
+				     struct gtm_timers_regs __iomem =

*regs)

arch/powerpc/sysdev/fsl_gtm.c

Quoted 6 lines
arch/powerpc/sysdev/fsl_gtm.c new file +3 -0
+{
+	/*
+	 * Yeah, I don't like this either, but timers' registers a bit =20=

messed,

arch/powerpc/sysdev/fsl_gtm.c new file +1 -0
+	 * so we have to provide shortcuts to write timer independent =

code.

arch/powerpc/sysdev/fsl_gtm.c

Quoted 1 line
arch/powerpc/sysdev/fsl_gtm.c new file +1 -0
+	 * Alternative option is to create gt*() accessors, but that =

will be

Quoted 41 lines
arch/powerpc/sysdev/fsl_gtm.c new file +41 -0
+	 * 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;
+	}
+}
+
+void __init fsl_gtm_init(void)
+{
+	struct device_node *np;
+
+	for_each_compatible_node(np, NULL, "fsl,gtm") {
+		int i;

arch/powerpc/sysdev/fsl_gtm.c line 381

Quoted 10 lines
arch/powerpc/sysdev/fsl_gtm.c new file +10 -0
+		struct gtm *gtm;
+		const u32 *clock;
+		int size;
+
+		gtm =3D kzalloc(sizeof(*gtm), GFP_KERNEL);
+		if (!gtm) {
+			pr_err("%s: unable to allocate memory\n",
+				np->full_name);
+			continue;
+		}

why bother with making this a dynamic alloc?

arch/powerpc/sysdev/fsl_gtm.c

Quoted 7 lines
arch/powerpc/sysdev/fsl_gtm.c new file +6 -0
+
+		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);

arch/powerpc/sysdev/fsl_gtm.c

Quoted 11 lines
arch/powerpc/sysdev/fsl_gtm.c new file +11 -0
+			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 =

specified\n",

Quoted 16 lines
arch/powerpc/sysdev/fsl_gtm.c new file +16 -0
+				       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);
+		list_add(&gtm->list_node, &gtms);

arch/powerpc/sysdev/fsl_gtm.c line 424

Quoted 10 lines
arch/powerpc/sysdev/fsl_gtm.c new file +10 -0
+
+		/* We don't want to lose the node and its ->data */
+		np->data =3D gtm;
+		of_node_get(np);
+
+		continue;
+err:
+		kfree(gtm);
+	}
+}

Shouldn't we have an arch_initcall(fsl_gtm_init);

Quoted 58 lines
include/asm-powerpc/=20 renamed from include/asm-powerpc/fsl_gtm.h +0 -0

fsl_gtm.h
new file mode 100644
index 0000000..49f1240

include/asm-powerpc/fsl_gtm.h new file +10 -0
@@ -0,0 +1,47 @@
+/*
+ * 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 =20

modify it
+ * under the terms of the GNU General Public License as =20 published by the
+ * Free Software Foundation; either version 2 of the License, or =20=

(at your
+ * option) any later version.
+ */

include/asm-powerpc/fsl_gtm.h new file +24 -0
+
+#ifndef __ASM_FSL_GTM_H
+#define __ASM_FSL_GTM_H
+
+#include <linux/types.h>
+
+struct gtm;
+
+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;
+};
+
+extern void __init fsl_gtm_init(void);
+extern struct gtm_timer *gtm_get_timer(int width);
+extern struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, =20

int timer,

include/asm-powerpc/fsl_gtm.h new file +3 -0
+						int width);
+extern void gtm_put_timer(struct gtm_timer *tmr);
+extern int gtm_reset_timer16(struct gtm_timer *tmr, unsigned long =20

usec,

include/asm-powerpc/fsl_gtm.h new file +2 -0
+			     bool reload);
+extern int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool =20=
Quoted 1 line

reload);

can you explain the difference between these two. I'm not sure I =20 understand the difference.

Quoted 7 lines
include/asm-powerpc/fsl_gtm.h new file +4 -1
+extern void gtm_stop_timer16(struct gtm_timer *tmr);
+extern void gtm_ack_timer16(struct gtm_timer *tmr, u16 events);
+
+#endif /* __ASM_FSL_GTM_H */
--=20

1.5.5.1

#3 lore raw

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

On Tue, May 20, 2008 at 01:04:55AM -0500, Kumar Gala wrote:
[...]

Quoted 8 lines
Quoted 8 lines
arch/powerpc/Kconfig +0 -0
index 3934e26..e5d3366 100644
@@ -538,6 +538,11 @@ config FSL_LBC
 	help
 	  Freescale Localbus support
 
Quoted 6 lines

arch/powerpc/Kconfig config FSL_LBC · line 542

Quoted 2 lines
arch/powerpc/Kconfig +2 -0
+config FSL_GTM
+	bool

I'd prefer something like:

depends on PPC_83xx || QUICC_ENGINE || CPM2

Ok.

Quoted 10 lines
Quoted 10 lines
arch/powerpc/Kconfig +7 -0
+/**
+ * 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-

Quoted 1 line

irq

Quoted 11 lines

arch/powerpc/Kconfig

Quoted 9 lines

+ * to manage timer interrupt.
+ */
+struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, int timer, int width)

arch/powerpc/Kconfig +5 -0
+{
+	struct gtm_timer *ret = ERR_PTR(-EBUSY);
+
+	if (width != 16)
+		return ERR_PTR(-ENOSYS);

should we not range check timer (since it can only be 0..3)?

I thought that caller should be smart enough to not ask for bogus timers. Ok, will range check.

Quoted 20 lines
Quoted 20 lines
arch/powerpc/Kconfig +20 -0
+
+	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.
Quoted 8 lines

arch/powerpc/Kconfig

Quoted 6 lines

+ */

arch/powerpc/Kconfig +5 -0
+void gtm_put_timer(struct gtm_timer *tmr)
+{
+	spin_lock_irq(&tmr->gtm->lock);
+
+	tmr->requested = false;

should we not stop the timer as well?

Sounds reasonable. I recalling that I intended to implement that, but obviously forgot. ;-)

Quoted 85 lines
Quoted 85 lines
arch/powerpc/Kconfig +7 -0
+
+	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,

arch/powerpc/Kconfig +66 -0
+				 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

Quoted 8 lines
Quoted 6 lines

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.

is this save to call in interrupt context?

Yes. Will document.

Quoted 31 lines
Quoted 31 lines

+ */
+int gtm_reset_timer16(struct gtm_timer *tmr, unsigned long usec, bool reload)

arch/powerpc/Kconfig +21 -0
+{
+	/* 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

Quoted 8 lines
Quoted 6 lines

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.

is this save to call in interrupt context?

Yes. Will document.

Quoted 112 lines
Quoted 112 lines

+ */

arch/powerpc/Kconfig +8 -0
+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.

arch/powerpc/Kconfig +1 -0
+	 * But we won't bother with this unless savings are measured, so  

just

arch/powerpc/Kconfig +10 -0
+	 * 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.
+ */

arch/powerpc/Kconfig +18 -0
+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);
+
+/**
+ * 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
+ *
+ * Thus function used to acknowledge timer interrupt event, use it inside the
+ * interrupt handler.
+ */

arch/powerpc/Kconfig +12 -0
+void gtm_ack_timer16(struct gtm_timer *tmr, u16 events)
+{
+	out_be16(tmr->gtevr, events);
+}
+EXPORT_SYMBOL(gtm_ack_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,

arch/powerpc/Kconfig +47 -0
+	 * 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;
+	}
+}
+
+void __init fsl_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 8 lines

arch/powerpc/Kconfig

Quoted 6 lines
arch/powerpc/Kconfig +6 -0
+		gtm = kzalloc(sizeof(*gtm), GFP_KERNEL);
+		if (!gtm) {
+			pr_err("%s: unable to allocate memory\n",
+				np->full_name);
+			continue;
+		}

why bother with making this a dynamic alloc?

Because different platforms have different number of GTMs blocks. For QE machines this could be up to three GTMs, and QE-less usually implement two GTMs. Not sure about CPM2.

Quoted 37 lines
Quoted 37 lines
arch/powerpc/Kconfig +37 -0
+
+		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);
+		list_add(&gtm->list_node, &gtms);
+
+		/* We don't want to lose the node and its ->data */
+		np->data = gtm;
+		of_node_get(np);
Quoted 8 lines

arch/powerpc/Kconfig

Quoted 6 lines
arch/powerpc/Kconfig +6 -0
+
+		continue;
+err:
+		kfree(gtm);
+	}
+}

Shouldn't we have an arch_initcall(fsl_gtm_init);

There (and in the QE GPIO) was an arch_initcall, but based on Grant Likely's review it was removed in favour of platform-specific machine_initcalls.

See http://www.mail-archive.com/[email protected]/msg16469.html
There I was trying to argue, but quickly gave up. ;-) I don't have any strong preference for this anyway. I can do either way, just tell which you prefer.

Quoted 51 lines
Quoted 51 lines
include/asm-powerpc/ renamed from include/asm-powerpc/fsl_gtm.h +0 -0

fsl_gtm.h
new file mode 100644
index 0000000..49f1240

include/asm-powerpc/fsl_gtm.h new file +10 -0
@@ -0,0 +1,47 @@
+/*
+ * 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/asm-powerpc/fsl_gtm.h new file +24 -0
+
+#ifndef __ASM_FSL_GTM_H
+#define __ASM_FSL_GTM_H
+
+#include <linux/types.h>
+
+struct gtm;
+
+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;
+};
+
+extern void __init fsl_gtm_init(void);
+extern struct gtm_timer *gtm_get_timer(int width);
+extern struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm, int 

timer,

include/asm-powerpc/fsl_gtm.h new file +2 -0
+						int width);
+extern void gtm_put_timer(struct gtm_timer *tmr);
Quoted 8 lines
Quoted 5 lines

+extern int gtm_reset_timer16(struct gtm_timer *tmr, unsigned long usec,

include/asm-powerpc/fsl_gtm.h new file +2 -0
+			     bool reload);
+extern int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool  

reload);

can you explain the difference between these two. I'm not sure I understand the difference.

This is explained in the .c file with a kernel doc. Basically the difference is that timer16 could silently crop the precision, while utimer16 could not thus explicitly accepts u16 argument (max. timer interval with usec precision fits in u16).

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

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

Quoted 19 lines
Quoted 10 lines
Quoted 10 lines
arch/powerpc/sysdev/fsl_gtm.c new file +10 -0
+void __init fsl_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 8 lines

arch/powerpc/sysdev/fsl_gtm.c line 381

Quoted 6 lines
arch/powerpc/sysdev/fsl_gtm.c new file +6 -0
+		gtm = kzalloc(sizeof(*gtm), GFP_KERNEL);
+		if (!gtm) {
+			pr_err("%s: unable to allocate memory\n",
+				np->full_name);
+			continue;
+		}

why bother with making this a dynamic alloc?

Quoted 3 lines

Because different platforms have different number of GTMs blocks. For QE machines this could be up to three GTMs, and QE-less usually implement two GTMs. Not sure about CPM2.

ok, that makes sense.

Quoted 46 lines
Quoted 37 lines
Quoted 37 lines
arch/powerpc/sysdev/fsl_gtm.c new file +37 -0
+
+		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);
+		list_add(&gtm->list_node, &gtms);
+
+		/* We don't want to lose the node and its ->data */
+		np->data = gtm;
+		of_node_get(np);
Quoted 8 lines

arch/powerpc/sysdev/fsl_gtm.c line 424

Quoted 6 lines
arch/powerpc/sysdev/fsl_gtm.c new file +6 -0
+
+		continue;
+err:
+		kfree(gtm);
+	}
+}

Shouldn't we have an arch_initcall(fsl_gtm_init);

Quoted 8 lines

There (and in the QE GPIO) was an arch_initcall, but based on Grant Likely's review it was removed in favour of platform-specific machine_initcalls.

See http://www.mail-archive.com/[email protected]/msg16469.html
There I was trying to argue, but quickly gave up. ;-) I don't have any strong preference for this anyway. I can do either way, just tell which you prefer.

I'd prefer the arch_initcall(). If its the board that is going to do the Kconfig select on this that seems sufficient to say do "init" for me w/o an explicit call to it.

Quoted 62 lines
Quoted 53 lines
Quoted 53 lines
include/asm-powerpc/ renamed from include/asm-powerpc/fsl_gtm.h +0 -0

fsl_gtm.h
new file mode 100644
index 0000000..49f1240

include/asm-powerpc/fsl_gtm.h new file +10 -0
@@ -0,0 +1,47 @@
+/*
+ * 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/asm-powerpc/fsl_gtm.h new file +24 -0
+
+#ifndef __ASM_FSL_GTM_H
+#define __ASM_FSL_GTM_H
+
+#include <linux/types.h>
+
+struct gtm;
+
+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;
+};
+
+extern void __init fsl_gtm_init(void);
+extern struct gtm_timer *gtm_get_timer(int width);
+extern struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm,  

int
timer,

include/asm-powerpc/fsl_gtm.h new file +2 -0
+						int width);
+extern void gtm_put_timer(struct gtm_timer *tmr);
Quoted 8 lines
Quoted 5 lines

+extern int gtm_reset_timer16(struct gtm_timer *tmr, unsigned long usec,

include/asm-powerpc/fsl_gtm.h new file +2 -0
+			     bool reload);
+extern int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool

reload);

can you explain the difference between these two. I'm not sure I understand the difference.

Quoted 4 lines

This is explained in the .c file with a kernel doc. Basically the difference is that timer16 could silently crop the precision, while utimer16 could not thus explicitly accepts u16 argument (max. timer interval with usec precision fits in u16).

Maybe I'm confused what the utility is of cropping the precision in this way is. I'd also say that _timer16 is poorly named to convey the behavior. I'm not sure what to call it because I still dont get exactly why you'd want the precision cropped.

- k

#5 lore raw

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

On Tue, May 20, 2008 at 08:15:15AM -0500, Kumar Gala wrote:
[...]

Quoted 77 lines
Quoted 15 lines
Quoted 6 lines
Quoted 6 lines
arch/powerpc/sysdev/fsl_gtm.c new file +6 -0
+	for_each_compatible_node(np, NULL, "fsl,gtm") {
+		int i;
+		struct gtm *gtm;
+		const u32 *clock;
+		int size;
+
Quoted 8 lines

arch/powerpc/sysdev/fsl_gtm.c line 381

Quoted 6 lines
arch/powerpc/sysdev/fsl_gtm.c new file +6 -0
+		gtm = kzalloc(sizeof(*gtm), GFP_KERNEL);
+		if (!gtm) {
+			pr_err("%s: unable to allocate memory\n",
+				np->full_name);
+			continue;
+		}

why bother with making this a dynamic alloc?

Quoted 3 lines

Because different platforms have different number of GTMs blocks. For QE machines this could be up to three GTMs, and QE-less usually implement two GTMs. Not sure about CPM2.

ok, that makes sense.

Quoted 50 lines
Quoted 37 lines
Quoted 37 lines
arch/powerpc/sysdev/fsl_gtm.c new file +37 -0
+
+		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);
+		list_add(&gtm->list_node, &gtms);
+
+		/* We don't want to lose the node and its ->data */
+		np->data = gtm;
+		of_node_get(np);
Quoted 8 lines

arch/powerpc/sysdev/fsl_gtm.c line 424

Quoted 6 lines
arch/powerpc/sysdev/fsl_gtm.c new file +6 -0
+
+		continue;
+err:
+		kfree(gtm);
+	}
+}

Shouldn't we have an arch_initcall(fsl_gtm_init);

There (and in the QE GPIO) was an arch_initcall, but based on Grant Likely's review it was removed in favour of platform-specific machine_initcalls.

Quoted 5 lines

See http://www.mail-archive.com/[email protected]/msg16469.html
There I was trying to argue, but quickly gave up. ;-) I don't have any strong preference for this anyway. I can do either way, just tell which
you prefer.

Quoted 3 lines

I'd prefer the arch_initcall(). If its the board that is going to do the Kconfig select on this that seems sufficient to say do "init" for me w/o an explicit call to it.

IIRC, the argument was that we don't need unnecessary initcalls for the multi-platform kernels. With arch_initcall() GTM/QE GPIOs will be probed regardless of a board the kernel currently running at. With machine_initcalls we only probe the GTMs/QE GPIOs on the boards which actually use it.

Once again, I see pros and cons of both ways, and I don't have preference, so.. ok, I will revert the arch_initcall() for GTM and QE GPIO.

Quoted 67 lines
Quoted 62 lines
Quoted 53 lines
Quoted 53 lines
include/asm-powerpc/ renamed from include/asm-powerpc/fsl_gtm.h +0 -0

fsl_gtm.h
new file mode 100644
index 0000000..49f1240

include/asm-powerpc/fsl_gtm.h new file +10 -0
@@ -0,0 +1,47 @@
+/*
+ * 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/asm-powerpc/fsl_gtm.h new file +24 -0
+
+#ifndef __ASM_FSL_GTM_H
+#define __ASM_FSL_GTM_H
+
+#include <linux/types.h>
+
+struct gtm;
+
+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;
+};
+
+extern void __init fsl_gtm_init(void);
+extern struct gtm_timer *gtm_get_timer(int width);
+extern struct gtm_timer *gtm_get_specific_timer(struct gtm *gtm,  

int
timer,

include/asm-powerpc/fsl_gtm.h new file +2 -0
+						int width);
+extern void gtm_put_timer(struct gtm_timer *tmr);
Quoted 8 lines
Quoted 5 lines

+extern int gtm_reset_timer16(struct gtm_timer *tmr, unsigned long usec,

include/asm-powerpc/fsl_gtm.h new file +2 -0
+			     bool reload);
+extern int gtm_reset_utimer16(struct gtm_timer *tmr, u16 usec, bool

reload);

can you explain the difference between these two. I'm not sure I understand the difference.

Quoted 4 lines

This is explained in the .c file with a kernel doc. Basically the difference is that timer16 could silently crop the precision, while utimer16 could not thus explicitly accepts u16 argument (max. timer interval with usec precision fits in u16).

Quoted 4 lines

Maybe I'm confused what the utility is of cropping the precision in this way is. I'd also say that _timer16 is poorly named to convey the behavior. I'm not sure what to call it because I still dont get exactly why you'd want the precision cropped.

Precision matters for FHCI-like drivers, when driver, for example, schedule transactions via the GTM timers, and there timings matters a lot.

Though, timer16 crops the precision _only_ if usecs > 65535, so FHCI _can_ still use the _timer16 (because FHCI does not request intervals

Quoted 1 line

65535). But I implemented two function because:

1. I think we don't need unnecessary stuff in the ISRs (this is weak argument since I didn't measure the impact).
2. I wanted to make the API clear (seem to fail this undertaking :-), which functions will behave exactly the way you asked it (utimer16), and which functions will _silently_ crop the precision (timer16) (if asked for 1001000 usecs, it will give you ~~1001000, depending on the GTM frequency).

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

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

Quoted 18 lines
Quoted 9 lines
Quoted 4 lines
Quoted 1 line

This is explained in the .c file with a kernel doc. Basically the

difference is that timer16 could silently crop the precision, while utimer16 could not thus explicitly accepts u16 argument (max. timer interval with usec precision fits in u16).

Maybe I'm confused what the utility is of cropping the precision in this way is. I'd also say that _timer16 is poorly named to convey the behavior. I'm not sure what to call it because I still dont get exactly why you'd want the precision cropped.

Precision matters for FHCI-like drivers, when driver, for example, schedule transactions via the GTM timers, and there timings matters a lot.

Though, timer16 crops the precision _only_ if usecs > 65535, so FHCI _can_ still use the _timer16 (because FHCI does not request intervals

Quoted 1 line

65535). But I implemented two function because:

Quoted 7 lines

1. I think we don't need unnecessary stuff in the ISRs (this is weak argument since I didn't measure the impact).
2. I wanted to make the API clear (seem to fail this undertaking :-), which functions will behave exactly the way you asked it (utimer16), and which functions will _silently_ crop the precision (timer16) (if asked for 1001000 usecs, it will give you ~~1001000, depending on the GTM frequency).

I'm fine w/having both. I think they are poorly named. I'd also call them _set_timer but that's just me.

Maybe something w/the term _exact_ in the name. Is it the case w/the precise form we'd have no prescaling (if so maybe a comment in the API about that would help clarity)?

- k

#7 lore raw

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

Quoted 28 lines · Kumar Gala
Quoted 20 lines
Quoted 11 lines
Quoted 4 lines
Quoted 1 line

This is explained in the .c file with a kernel doc. Basically the

difference is that timer16 could silently crop the precision, while utimer16 could not thus explicitly accepts u16 argument (max. timer interval with usec precision fits in u16).

Maybe I'm confused what the utility is of cropping the precision in this
way is. I'd also say that _timer16 is poorly named to convey the behavior. I'm not sure what to call it because I still dont get exactly
why you'd want the precision cropped.

Precision matters for FHCI-like drivers, when driver, for example, schedule transactions via the GTM timers, and there timings matters a lot.

Though, timer16 crops the precision _only_ if usecs > 65535, so FHCI _can_ still use the _timer16 (because FHCI does not request intervals

Quoted 1 line

65535). But I implemented two function because:

Quoted 7 lines

1. I think we don't need unnecessary stuff in the ISRs (this is weak argument since I didn't measure the impact).
2. I wanted to make the API clear (seem to fail this undertaking :-), which functions will behave exactly the way you asked it (utimer16), and which functions will _silently_ crop the precision (timer16) (if asked for 1001000 usecs, it will give you ~~1001000, depending on the GTM frequency).

Quoted 6 lines

I'm fine w/having both. I think they are poorly named. I'd also call them _set_timer but that's just me.

Maybe something w/the term _exact_ in the name. Is it the case w/the precise form we'd have no prescaling (if so maybe a comment in the API about that would help clarity)?

We're always prescale [to 1000000 MHz for usec precision]. Otherwise these functions would be non-deterministic (will purely depend on the GTM frequency, so "usec" argument would not have defined boundaries).

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

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

Quoted 29 lines · Anton Vorontsov
Quoted 28 lines · Kumar Gala
Quoted 27 lines
Quoted 11 lines
Quoted 4 lines
Quoted 1 line

This is explained in the .c file with a kernel doc. Basically the

difference is that timer16 could silently crop the precision, while utimer16 could not thus explicitly accepts u16 argument (max. timer interval with usec precision fits in u16).

Maybe I'm confused what the utility is of cropping the precision in this
way is. I'd also say that _timer16 is poorly named to convey the behavior. I'm not sure what to call it because I still dont get exactly
why you'd want the precision cropped.

Precision matters for FHCI-like drivers, when driver, for example, schedule transactions via the GTM timers, and there timings matters a lot.

Though, timer16 crops the precision _only_ if usecs > 65535, so FHCI _can_ still use the _timer16 (because FHCI does not request intervals

Quoted 1 line

65535). But I implemented two function because:

1. I think we don't need unnecessary stuff in the ISRs (this is weak argument since I didn't measure the impact).
2. I wanted to make the API clear (seem to fail this undertaking :-), which functions will behave exactly the way you asked it (utimer16), and which functions will _silently_ crop the precision (timer16) (if asked for 1001000 usecs, it will give you ~~1001000, depending on the GTM frequency).

Quoted 8 lines
Quoted 6 lines

I'm fine w/having both. I think they are poorly named. I'd also call them _set_timer but that's just me.

Maybe something w/the term _exact_ in the name. Is it the case w/the precise form we'd have no prescaling (if so maybe a comment in the API about that would help clarity)?

We're always prescale [to 1000000 MHz for usec precision].

-MHz
+Hz

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

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

In reply to Kumar Gala
Quoted 4 lines · Kumar Gala
Quoted 4 lines

There (and in the QE GPIO) was an arch_initcall, but based on Grant Likely's review it was removed in favour of platform-specific machine_initcalls.

Quoted 8 lines
Quoted 4 lines

See http://www.mail-archive.com/[email protected]/msg16469.html
There I was trying to argue, but quickly gave up. ;-) I don't have any strong preference for this anyway. I can do either way, just tell which you prefer.

I'd prefer the arch_initcall(). If its the board that is going to do the Kconfig select on this that seems sufficient to say do "init" for me w/o an explicit call to it.

That's only true if the assumption is that you are not building a multiplatform kernel. I'd rather see platform code in control of registering devices.

Cheers,
g.

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

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

In reply to Kumar Gala
Quoted 39 lines · Kumar Gala
Quoted 36 lines · Anton Vorontsov

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 |   37 +++-
arch/powerpc/Kconfig                         |    5 +
arch/powerpc/sysdev/Makefile                 |    1 +
arch/powerpc/sysdev/fsl_gtm.c                |  424 +++++++++++++++++ 
+++++++++
include/asm-powerpc/fsl_gtm.h                |   47 +++
5 files changed, 513 insertions(+), 1 deletions(-)

create mode 100644 arch/powerpc/sysdev/fsl_gtm.c
create mode 100644 include/asm-powerpc/fsl_gtm.h

arch/powerpc/Kconfig +0 -0
index 3934e26..e5d3366 100644
@@ -538,6 +538,11 @@ config FSL_LBC
 	help
 	  Freescale Localbus support
 
Quoted 6 lines

arch/powerpc/Kconfig config FSL_LBC · line 542

Quoted 2 lines
arch/powerpc/Kconfig +2 -0
+config FSL_GTM
+	bool

I'd prefer something like:

depends on PPC_83xx || QUICC_ENGINE || CPM2

Btw, this is silent config, selected by the board's Kconfig (same as QE block, for example). So "depends on" here is just no-op, since select disregards dependencies. Still want this?

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

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

Quoted 46 lines · Anton Vorontsov
Quoted 45 lines · Kumar Gala
Quoted 34 lines · Anton Vorontsov

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 |   37 +++-
arch/powerpc/Kconfig                         |    5 +
arch/powerpc/sysdev/Makefile                 |    1 +
arch/powerpc/sysdev/fsl_gtm.c                |  424 +++++++++++++++ 
++
+++++++++
include/asm-powerpc/fsl_gtm.h                |   47 +++
5 files changed, 513 insertions(+), 1 deletions(-)

create mode 100644 arch/powerpc/sysdev/fsl_gtm.c
create mode 100644 include/asm-powerpc/fsl_gtm.h

arch/powerpc/Kconfig +0 -0
index 3934e26..e5d3366 100644

arch/powerpc/Kconfig config FSL_LBC · line 542

Quoted 5 lines
arch/powerpc/Kconfig +2 -0
@@ -538,6 +538,11 @@ config FSL_LBC
 	help
 	  Freescale Localbus support
 
+config FSL_GTM
+	bool

I'd prefer something like:

Quoted 5 lines
Quoted 1 line

depends on PPC_83xx || QUICC_ENGINE || CPM2

Btw, this is silent config, selected by the board's Kconfig (same as QE block, for example). So "depends on" here is just no-op, since select disregards dependencies. Still want this?

I do, its at least documentation if its not used.

- k

#12 lore raw

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

In reply to Anton Vorontsov
Quoted 3 lines · Anton Vorontsov

Btw, this is silent config, selected by the board's Kconfig (same as QE block, for example). So "depends on" here is just no-op, since select disregards dependencies. Still want this?

FYI, I have plans to modify the Kconfigs so that CONFIG_QUICC_ENGINE is user-selectable.

Signature · 2 lines
Timur Tabi
Linux kernel developer at Freescale
#13 lore raw

PATCH 2/7 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.1
#14 lore raw

Re: [PATCH 2/7] [POWERPC] QE: add support for QE USB clocks routing

Hi Anton,

Quoted 4 lines · On Mon, 19 May 2008 21:46:55 +0400 Anton Vorontsov <[email protected]>…

+++ b/arch/powerpc/sysdev/qe_lib/usb.c

+#include <linux/of.h>

Nothing in this file requires anything in linux/of.h or asm/of.h ...

Signature · 3 lines
Cheers,
Stephen Rothwell                    [email protected]
http://www.canb.auug.org.au/~sfr/
#15 lore raw

Re: [PATCH 2/7] [POWERPC] QE: add support for QE USB clocks routing

Quoted 9 lines · Stephen Rothwell

Hi Anton,

Quoted 4 lines · On Mon, 19 May 2008 21:46:55 +0400 Anton Vorontsov <[email protected]>…

+++ b/arch/powerpc/sysdev/qe_lib/usb.c

+#include <linux/of.h>

Nothing in this file requires anything in linux/of.h or asm/of.h ...

Yeah, this is left-over... Thanks for catching this.

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

PATCH 3/7 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.1
#17 lore raw

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

In reply to Anton Vorontsov

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

---
 Documentation/powerpc/booting-without-of.txt |   27 +++++
 arch/powerpc/sysdev/qe_lib/Kconfig           |    9 ++
 arch/powerpc/sysdev/qe_lib/Makefile          |    1 +
 arch/powerpc/sysdev/qe_lib/gpio.c            |  146 ++++++++++++++++++++++++++
 include/asm-powerpc/qe.h                     |    3 +
 5 files changed, 186 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/sysdev/qe_lib/gpio.c
Documentation/powerpc/booting-without-of.txt +27 -0
index fc7a235..c1044ee 100644
@@ -1738,6 +1738,33 @@ platforms are moved over to use the flattened-device-tree model.
 			......
 		};
 
+   Note that "par_io" nodes are obsolete, and should not be used for
+   the new device trees. Instead, each Par I/O bank should be represented
+   via its own gpio-controller node:
+
+   Required properties:
+   - #gpio-cells : should be "2".
+   - compatible : should be "fsl,<chip>-qe-pario-bank",
+     "fsl,mpc8323-qe-pario-bank".
+   - reg : offset to the register set and its length.
+   - gpio-controller : node to identify gpio controllers.
+
+   Example:
+	qe_pio_a: gpio-controller@1400 {
+		#gpio-cells = <2>;
+		compatible = "fsl,mpc8360-qe-pario-bank",
+			     "fsl,mpc8323-qe-pario-bank";
+		reg = <0x1400 0x18>;
+		gpio-controller;
+	};
+
+	qe_pio_e: gpio-controller@1460 {
+		#gpio-cells = <2>;
+		compatible = "fsl,mpc8360-qe-pario-bank",
+			     "fsl,mpc8323-qe-pario-bank";
+		reg = <0x1460 0x18>;
+		gpio-controller;
+	};
 
    vi) Pin configuration nodes
 
arch/powerpc/sysdev/qe_lib/Kconfig +9 -0
index 76ffbc4..4bb18f5 100644
@@ -24,3 +24,12 @@ config QE_USB
 	bool
 	help
 	  QE USB Host Controller support
+
+config QE_GPIO
+	bool "QE GPIO support"
+	depends on QUICC_ENGINE
+	select GENERIC_GPIO
+	select HAVE_GPIO_LIB
+	help
+	  Say Y here if you're going to use hardware that connects to the
+	  QE GPIOs.
arch/powerpc/sysdev/qe_lib/Makefile +1 -0
index e9ff888..f1855c1 100644
@@ -7,3 +7,4 @@ 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
+obj-$(CONFIG_QE_GPIO)	+= gpio.o
arch/powerpc/sysdev/qe_lib/gpio.c new file +146 -0

146 lines not on this page · raw message

include/asm-powerpc/qe.h +3 -0
index c4523ac..01e3c70 100644
@@ -100,8 +100,11 @@ struct qe_pio_regs {
 #endif
 };
 
+extern void __init qe_add_gpiochips(void);
 extern int par_io_init(struct device_node *np);
 extern int par_io_of_config(struct device_node *np);
+#define QE_PIO_DIR_IN	2
+#define QE_PIO_DIR_OUT	1
 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);
Signature · 1 line
1.5.5.1
Applied
#18 lore raw

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

Quoted 5 lines · Anton Vorontsov

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

---

Quoted 8 lines
Documentation/powerpc/booting-without-of.txt |   27 +++++
arch/powerpc/sysdev/qe_lib/Kconfig           |    9 ++
arch/powerpc/sysdev/qe_lib/Makefile          |    1 +
arch/powerpc/sysdev/qe_lib/gpio.c            |  146 +++++++++++++++++ 
+++++++++
include/asm-powerpc/qe.h                     |    3 +
5 files changed, 186 insertions(+), 0 deletions(-)

create mode 100644 arch/powerpc/sysdev/qe_lib/gpio.c

applied.

- k

#19 lore raw

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

Quoted 17 lines · Kumar Gala
Quoted 5 lines · Anton Vorontsov

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

---

Quoted 8 lines
Documentation/powerpc/booting-without-of.txt |   27 +++++
arch/powerpc/sysdev/qe_lib/Kconfig           |    9 ++
arch/powerpc/sysdev/qe_lib/Makefile          |    1 +
arch/powerpc/sysdev/qe_lib/gpio.c            |  146 +++++++++++++++++ 
+++++++++
include/asm-powerpc/qe.h                     |    3 +
5 files changed, 186 insertions(+), 0 deletions(-)

create mode 100644 arch/powerpc/sysdev/qe_lib/gpio.c

Quoted 1 line

applied.

I've just rebased on the pushed out powerpc-next branch, and noticed that you merged this patch from the old series.

The difference is in absence of arch_initcall() for QE GPIOs initialization, i.e. in this version boards should explicitly call qe_add_gpiochips(). So.. was this done deliberately? Or should I send you an update?

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

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

Quoted 21 lines · Anton Vorontsov
Quoted 18 lines · Kumar Gala
Quoted 13 lines · Anton Vorontsov

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

---

Documentation/powerpc/booting-without-of.txt |   27 +++++
arch/powerpc/sysdev/qe_lib/Kconfig           |    9 ++
arch/powerpc/sysdev/qe_lib/Makefile          |    1 +
arch/powerpc/sysdev/qe_lib/gpio.c            |  146 +++++++++++++++ 
++
+++++++++
include/asm-powerpc/qe.h                     |    3 +
5 files changed, 186 insertions(+), 0 deletions(-)
Quoted 1 line

create mode 100644 arch/powerpc/sysdev/qe_lib/gpio.c

Quoted 1 line

applied.

Quoted 7 lines

I've just rebased on the pushed out powerpc-next branch, and noticed that you merged this patch from the old series.

The difference is in absence of arch_initcall() for QE GPIOs initialization, i.e. in this version boards should explicitly call qe_add_gpiochips(). So.. was this done deliberately? Or should I send you an update?

just send me an update to my tree at this point.

- k

#21 lore raw

PATCH 1/1 powerpc/QE: use arch_initcall to probe QUICC Engine GPIOs

It was discussed that global arch_initcall() is preferred way to probe QE GPIOs, so let's use it.

---

On Wed, Jun 11, 2008 at 08:52:16AM -0500, Kumar Gala wrote:
[...]

Quoted 11 lines
Quoted 9 lines
Quoted 1 line

applied.

I've just rebased on the pushed out powerpc-next branch, and noticed that you merged this patch from the old series.

The difference is in absence of arch_initcall() for QE GPIOs initialization, i.e. in this version boards should explicitly call qe_add_gpiochips(). So.. was this done deliberately? Or should I send you an update?

just send me an update to my tree at this point.

Here it is.

Thanks,

 arch/powerpc/sysdev/qe_lib/gpio.c |    5 ++++-
 include/asm-powerpc/qe.h          |    1 -
 2 files changed, 4 insertions(+), 2 deletions(-)
arch/powerpc/sysdev/qe_lib/gpio.c +4 -1
index c712e24..8e5a0bc 100644
@@ -12,6 +12,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -102,7 +103,7 @@ static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 	return 0;
 }
 
-void __init qe_add_gpiochips(void)
+static int __init qe_add_gpiochips(void)
 {
 	struct device_node *np;
 
@@ -143,4 +144,6 @@ err:
 		kfree(qe_gc);
 		/* try others anyway */
 	}
+	return 0;
 }
+arch_initcall(qe_add_gpiochips);
include/asm-powerpc/qe.h +0 -1
index 1355e72..edee15d 100644
@@ -101,7 +101,6 @@ struct qe_pio_regs {
 #endif
 };
 
-extern void __init qe_add_gpiochips(void);
 extern int par_io_init(struct device_node *np);
 extern int par_io_of_config(struct device_node *np);
 #define QE_PIO_DIR_IN	2
Signature · 1 line
1.5.5.4
Applied
#22 lore raw

Re: [PATCH] powerpc/QE: use arch_initcall to probe QUICC Engine GPIOs

Quoted 5 lines · Anton Vorontsov

It was discussed that global arch_initcall() is preferred way to probe QE GPIOs, so let's use it.

---

applied to powerpc-next.

- k

#23 lore raw

PATCH 5/7 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           |  397 ++++++++
 arch/powerpc/configs/83xx/mpc836x_rdk_defconfig | 1128 +++++++++++++++++++++++
 arch/powerpc/platforms/83xx/Kconfig             |   11 +
 arch/powerpc/platforms/83xx/Makefile            |    1 +
 arch/powerpc/platforms/83xx/mpc836x_rdk.c       |  111 +++
 5 files changed, 1648 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 +397 -0
new file mode 100644
index 0000000..3402d26
@@ -0,0 +1,397 @@
+/*
+ * 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,mpc8360-qe-pario-bank",
+				     "fsl,mpc8323-qe-pario-bank";
+			reg = <0x1418 0x18>;
+			gpio-controller;
+		};
+
+		qe_pio_e: gpio-controller@1460 {
+			#gpio-cells = <2>;
+			compatible = "fsl,mpc8360-qe-pario-bank",
+				     "fsl,mpc8323-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,mpc8360-qe-gtm",
+					     "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 +1128 -0

1,128 lines not on this page · raw message

arch/powerpc/platforms/83xx/Kconfig +11 -0
index 13587e2..9cb9e04 100644
@@ -58,6 +58,17 @@ 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
+	select QE_GPIO
+	select FSL_GTM
+	select FSL_LBC
+	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 +111 -0

111 lines not on this page · raw message

Signature · 1 line
1.5.5.1
#24 lore raw

PATCH 6/7 booting-without-of: add FHCI USB, FSL MCU, FSL UPM and GPIO LEDs bindings

In reply to Anton Vorontsov

This patch adds few bindings for the new drivers to be submitted through appropriate maintainers.

---
 Documentation/powerpc/booting-without-of.txt |  125 ++++++++++++++++++++++++++
 1 files changed, 125 insertions(+), 0 deletions(-)
Documentation/powerpc/booting-without-of.txt +125 -0
index c1044ee..4e15c13 100644
@@ -61,6 +61,10 @@ Table of Contents
       r) Freescale Display Interface Unit
       s) Freescale on board FPGA
       t) Freescale General-purpose Timers Module
+      u) Freescale QUICC Engine USB Controller
+      v) LEDs on GPIOs
+      w) Freescale MCU with MPC8349E-mITX compatible firmware
+      x) Freescale Localbus UPM programmed to work with NAND flash
 
   VII - Marvell Discovery mv64[345]6x System Controller chips
     1) The /system-controller node
@@ -2932,6 +2936,127 @@ platforms are moved over to use the flattened-device-tree model.
     	clock-frequency = <0>;
     };
 
+    u) Freescale QUICC Engine USB Controller
+
+    Required properties:
+      - compatible : should be "fsl,<chip>-qe-usb", "fsl,mpc8323-qe-usb";
+      - reg : the first two cells should contain gtm registers location and
+        length, the next two two cells should contain PRAM location and
+        length.
+      - interrupts : should contain USB interrupt.
+      - interrupt-parent : interrupt source phandle.
+      - fsl,fullspeed-clock : specifies the full speed USB clock source in
+        "clk<num>" or "brg<num>" format.
+      - fsl,lowspeed-clock : specifies the low speed USB clock source in
+        "clk<num>" or "brg<num>" format.
+      - fsl,usb-mode : should be "host".
+      - linux,hub-power-budget : optional, USB power budget for the root hub
+        in mA.
+      - gpios : should specify GPIOs in this order: USBOE, USBTP, USBTN, USBRP,
+        USBRN, SPEED (optional), and POWER (optional).
+
+    Example:
+
+	usb@6c0 {
+		compatible = "fsl,mpc8360-qe-usb", "fsl,mpc8323-qe-usb";
+		reg = <0x6c0 0x40 0x8b00 0x100>;
+		interrupts = <11>;
+		interrupt-parent = <&qeic>;
+		fsl,fullspeed-clock = "clk21";
+		fsl,usb-mode = "host";
+		gpios = <&qe_pio_b  2 0 /* USBOE */
+			 &qe_pio_b  3 0 /* USBTP */
+			 &qe_pio_b  8 0 /* USBTN */
+			 &qe_pio_b  9 0 /* USBRP */
+			 &qe_pio_b 11 0 /* USBRN */
+			 &qe_pio_e 20 0 /* SPEED */
+			 &qe_pio_e 21 0 /* POWER */>;
+	};
+
+    v) LEDs on GPIOs
+
+    Required properties:
+      - compatible : should be "linux,gpio-led".
+      - linux,name : LED name.
+      - linux,active-low : property should be present if LED wired as
+        active-low.
+      - linux,default-trigger : Linux default trigger for this LED.
+      - linux,brightness : default brightness.
+      - gpios : should specify LED GPIO.
+
+    Example:
+
+	led@0 {
+		compatible = "linux,gpio-led";
+		linux,name = "pwr";
+		linux,brightness = <1>;
+		linux,active-low;
+		gpios = <&mcu_pio 0>;
+	};
+
+	led@1 {
+	        compatible = "linux,gpio-led";
+	        linux,name = "hdd";
+	        linux,default-trigger = "ide-disk";
+		linux,active-low;
+		gpios = <&mcu_pio 1>;
+	};
+
+    w) Freescale MCU with MPC8349E-mITX compatible firmware
+
+    Required properties:
+      - compatible : "fsl,<mcu-chip>-<board>", "fsl,mcu-mpc8349emitx";
+      - reg : should specify I2C address (0x0a).
+      - #address-cells : should be 0.
+      - #size-cells : should be 0.
+      - #gpio-cells : should be 2.
+      - gpio-controller : should be present;
+
+    Example:
+
+	mcu_pio: mcu@0a {
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#gpio-cells = <2>;
+		compatible = "fsl,mc9s08qg8-mpc8349emitx",
+			     "fsl,mcu-mpc8349emitx";
+		reg = <0x0a>;
+		gpio-controller;
+	};
+
+    x) Freescale Localbus UPM programmed to work with NAND flash
+
+      Required properties:
+      - #address-cells : should be 0;
+      - #size-cells : should be 0;
+      - compatible : "fsl,upm-nand".
+      - reg : should specify localbus chip select and size used for the chip.
+      - fsl,upm-addr-offset : UPM pattern offset for the address latch.
+      - fsl,upm-cmd-offset : UPM pattern offset for the command latch.
+      - gpios : may specify optional GPIO connected to the Ready-Not-Busy pin.
+
+      Example:
+
+	upm@1,0 {
+		#address-cells = <0>;
+		#size-cells = <0>;
+		compatible = "fsl,upm-nand";
+		reg = <1 0 1>;
+		fsl,upm-addr-offset = <16>;
+		fsl,upm-cmd-offset = <8>;
+		gpios = <&qe_pio_e 18 0>;
+
+		flash {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "stmicro,NAND512W3A2BN6E";
+
+			partition@0 {
+				...
+			};
+		};
+	};
+
 VII - Marvell Discovery mv64[345]6x System Controller chips
 ===========================================================
 
Signature · 1 line
1.5.5.1
#25 lore raw

PATCH 7/7 qe_lib: switch to the cpm_muram implementation

In reply to Anton Vorontsov

This is very trivial patch. We're transitioning to the cpm_muram_* calls. That's it.

Less trivial changes:
- BD_SC_* defines were defined in the cpm.h and qe.h, so to avoid redefines we remove BD_SC from the qe.h and use cpm.h along with cpm_muram_* prototypes;
- qe_muram_dump was unused and thus removed;
- added some code to the cpm_common.c to support legacy QE bindings (data-only node name).
- For convenience, define qe_* calls to cpm_*. So drivers need not to be changed.

---
 arch/powerpc/sysdev/Makefile          |    1 +
 arch/powerpc/sysdev/cpm_common.c      |   16 +++++-
 arch/powerpc/sysdev/qe_lib/qe.c       |   92 ---------------------------------
 arch/powerpc/sysdev/qe_lib/ucc_fast.c |    8 ++--
 arch/powerpc/sysdev/qe_lib/ucc_slow.c |   18 +++---
 include/asm-powerpc/cpm.h             |    1 +
 include/asm-powerpc/qe.h              |   36 +++----------
 7 files changed, 36 insertions(+), 136 deletions(-)
arch/powerpc/sysdev/Makefile +1 -0
index f55e661..620aca6 100644
@@ -41,6 +41,7 @@ endif
 ifeq ($(ARCH),powerpc)
 obj-$(CONFIG_CPM)		+= cpm_common.o
 obj-$(CONFIG_CPM2)		+= cpm2.o cpm2_pic.o
+obj-$(CONFIG_QUICC_ENGINE)	+= cpm_common.o
 obj-$(CONFIG_PPC_DCR)		+= dcr.o
 obj-$(CONFIG_8xx)		+= mpc8xx_pic.o cpm1.o
 obj-$(CONFIG_UCODE_PATCH)	+= micropatch.o
arch/powerpc/sysdev/cpm_common.c +13 -3
index cb7df2d..9b75d16 100644
@@ -85,9 +85,13 @@ int __init cpm_muram_init(void)
 
 	np = of_find_compatible_node(NULL, NULL, "fsl,cpm-muram-data");
 	if (!np) {
-		printk(KERN_ERR "Cannot find CPM muram data node");
-		ret = -ENODEV;
-		goto out;
+		/* try legacy bindings */
+		np = of_find_node_by_name(NULL, "data-only");
+		if (!np) {
+			printk(KERN_ERR "Cannot find CPM muram data node");
+			ret = -ENODEV;
+			goto out;
+		}
 	}
 
 	muram_pbase = of_translate_address(np, zero);
@@ -189,6 +193,12 @@ void __iomem *cpm_muram_addr(unsigned long offset)
 }
 EXPORT_SYMBOL(cpm_muram_addr);
 
+unsigned long cpm_muram_offset(void __iomem *addr)
+{
+	return addr - (void __iomem *)muram_vbase;
+}
+EXPORT_SYMBOL(cpm_muram_offset);
+
 /**
  * cpm_muram_dma - turn a muram virtual address into a DMA address
  * @offset: virtual address from cpm_muram_addr() to convert
arch/powerpc/sysdev/qe_lib/qe.c +0 -92

104 lines not on this page · raw message

arch/powerpc/sysdev/qe_lib/ucc_fast.c +4 -4
index bcf88e6..559678d 100644
@@ -267,7 +267,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 
 	/* Allocate memory for Tx Virtual Fifo */
 	uccf->ucc_fast_tx_virtual_fifo_base_offset =
-	    qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
+	    cpm_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
 	if (IS_ERR_VALUE(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
 		printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO\n",
 			__func__);
@@ -278,7 +278,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
 
 	/* Allocate memory for Rx Virtual Fifo */
 	uccf->ucc_fast_rx_virtual_fifo_base_offset =
-		qe_muram_alloc(uf_info->urfs +
+		cpm_muram_alloc(uf_info->urfs +
 			   UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR,
 			   UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
 	if (IS_ERR_VALUE(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
@@ -350,10 +350,10 @@ void ucc_fast_free(struct ucc_fast_private * uccf)
 		return;
 
 	if (uccf->ucc_fast_tx_virtual_fifo_base_offset)
-		qe_muram_free(uccf->ucc_fast_tx_virtual_fifo_base_offset);
+		cpm_muram_free(uccf->ucc_fast_tx_virtual_fifo_base_offset);
 
 	if (uccf->ucc_fast_rx_virtual_fifo_base_offset)
-		qe_muram_free(uccf->ucc_fast_rx_virtual_fifo_base_offset);
+		cpm_muram_free(uccf->ucc_fast_rx_virtual_fifo_base_offset);
 
 	kfree(uccf);
 }
arch/powerpc/sysdev/qe_lib/ucc_slow.c +9 -9
index a578bc7..49e6949 100644
@@ -187,7 +187,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 
 	/* Get PRAM base */
 	uccs->us_pram_offset =
-		qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM);
+		cpm_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM);
 	if (IS_ERR_VALUE(uccs->us_pram_offset)) {
 		printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __func__);
 		ucc_slow_free(uccs);
@@ -197,7 +197,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 	qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, id, us_info->protocol,
 		     uccs->us_pram_offset);
 
-	uccs->us_pram = qe_muram_addr(uccs->us_pram_offset);
+	uccs->us_pram = cpm_muram_addr(uccs->us_pram_offset);
 
 	/* Set UCC to slow type */
 	ret = ucc_set_type(us_info->ucc_num, UCC_SPEED_TYPE_SLOW);
@@ -213,7 +213,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 
 	/* Allocate BDs. */
 	uccs->rx_base_offset =
-		qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd),
+		cpm_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd),
 				QE_ALIGNMENT_OF_BD);
 	if (IS_ERR_VALUE(uccs->rx_base_offset)) {
 		printk(KERN_ERR "%s: cannot allocate %u RX BDs\n", __func__,
@@ -224,7 +224,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 	}
 
 	uccs->tx_base_offset =
-		qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd),
+		cpm_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd),
 			QE_ALIGNMENT_OF_BD);
 	if (IS_ERR_VALUE(uccs->tx_base_offset)) {
 		printk(KERN_ERR "%s: cannot allocate TX BDs", __func__);
@@ -234,7 +234,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 	}
 
 	/* Init Tx bds */
-	bd = uccs->confBd = uccs->tx_bd = qe_muram_addr(uccs->tx_base_offset);
+	bd = uccs->confBd = uccs->tx_bd = cpm_muram_addr(uccs->tx_base_offset);
 	for (i = 0; i < us_info->tx_bd_ring_len - 1; i++) {
 		/* clear bd buffer */
 		out_be32(&bd->buf, 0);
@@ -247,7 +247,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
 	out_be32((u32 *) bd, cpu_to_be32(T_W));
 
 	/* Init Rx bds */
-	bd = uccs->rx_bd = qe_muram_addr(uccs->rx_base_offset);
+	bd = uccs->rx_bd = cpm_muram_addr(uccs->rx_base_offset);
 	for (i = 0; i < us_info->rx_bd_ring_len - 1; i++) {
 		/* set bd status and length */
 		out_be32((u32*)bd, 0);
@@ -362,13 +362,13 @@ void ucc_slow_free(struct ucc_slow_private * uccs)
 		return;
 
 	if (uccs->rx_base_offset)
-		qe_muram_free(uccs->rx_base_offset);
+		cpm_muram_free(uccs->rx_base_offset);
 
 	if (uccs->tx_base_offset)
-		qe_muram_free(uccs->tx_base_offset);
+		cpm_muram_free(uccs->tx_base_offset);
 
 	if (uccs->us_pram) {
-		qe_muram_free(uccs->us_pram_offset);
+		cpm_muram_free(uccs->us_pram_offset);
 		uccs->us_pram = NULL;
 	}
 
include/asm-powerpc/cpm.h +1 -0
index ede38ff..63a5533 100644
@@ -96,6 +96,7 @@ unsigned long cpm_muram_alloc(unsigned long size, unsigned long align);
 int cpm_muram_free(unsigned long offset);
 unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size);
 void __iomem *cpm_muram_addr(unsigned long offset);
+unsigned long cpm_muram_offset(void __iomem *addr);
 dma_addr_t cpm_muram_dma(void __iomem *addr);
 int cpm_command(u32 command, u8 opcode);
 
include/asm-powerpc/qe.h +8 -28
index 01e3c70..80807fd 100644
@@ -17,6 +17,7 @@
 #ifdef __KERNEL__
 
 #include <linux/spinlock.h>
+#include <asm/cpm.h>
 #include <asm/immap_qe.h>
 
 #define QE_NUM_OF_SNUM	28
@@ -119,20 +120,13 @@ unsigned int qe_get_brg_clk(void);
 int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
 int qe_get_snum(void);
 void qe_put_snum(u8 snum);
-unsigned long qe_muram_alloc(int size, int align);
-int qe_muram_free(unsigned long offset);
-unsigned long qe_muram_alloc_fixed(unsigned long offset, int size);
-void qe_muram_dump(void);
-
-static inline void __iomem *qe_muram_addr(unsigned long offset)
-{
-	return (void __iomem *)&qe_immr->muram[offset];
-}
-
-static inline unsigned long qe_muram_offset(void __iomem *addr)
-{
-	return addr - (void __iomem *)qe_immr->muram;
-}
+/* we actually use cpm_muram implementation, define this for convenience */
+#define qe_muram_init cpm_muram_init
+#define qe_muram_alloc cpm_muram_alloc
+#define qe_muram_alloc_fixed cpm_muram_alloc_fixed
+#define qe_muram_free cpm_muram_free
+#define qe_muram_addr cpm_muram_addr
+#define qe_muram_offset cpm_muram_offset
 
 /* Structure that defines QE firmware binary files.
  *
@@ -199,20 +193,6 @@ struct qe_bd {
 #define BD_STATUS_MASK	0xffff0000
 #define BD_LENGTH_MASK	0x0000ffff
 
-#define BD_SC_EMPTY	0x8000	/* Receive is empty */
-#define BD_SC_READY	0x8000	/* Transmit is ready */
-#define BD_SC_WRAP	0x2000	/* Last buffer descriptor */
-#define BD_SC_INTRPT	0x1000	/* Interrupt on change */
-#define BD_SC_LAST	0x0800	/* Last buffer in frame */
-#define BD_SC_CM	0x0200	/* Continous mode */
-#define BD_SC_ID	0x0100	/* Rec'd too many idles */
-#define BD_SC_P		0x0100	/* xmt preamble */
-#define BD_SC_BR	0x0020	/* Break received */
-#define BD_SC_FR	0x0010	/* Framing error */
-#define BD_SC_PR	0x0008	/* Parity error */
-#define BD_SC_OV	0x0002	/* Overrun */
-#define BD_SC_CD	0x0001	/* ?? */
-
 /* Alignment */
 #define QE_INTR_TABLE_ALIGN	16	/* ??? */
 #define QE_ALIGNMENT_OF_BD	8
Signature · 1 line
1.5.5.1