LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* RE: MPC85xx PCI transfer disconnect
From: Martin, Tim @ 2006-06-02 16:45 UTC (permalink / raw)
  To: Liu Dave-r63238, linuxppc-embedded

> The 85xx cacheline is 32 bytes.

Yes, so it is. =20

> Did you enable Memory Read Multiple command of your PCI master?

Thanks for the clue.  I'm trying to figure out how to do this.  The PCI
master is a Tundra TSI148 VME-PCI bridge.  The documentation says it
supports the PCI read multiple cycle, but so far I haven't found a
register to specifically configure it.  I'll check the C/BE lines to see
if a PCI read multiple cycle is being issued.

I have confirmed that 64 bytes are being transferred before the MPC85xx
disconnects the transfer.  If the PCI master initiates a 32 byte or 64
byte read, the MPC85xx does not disconnect the transfer.

Tim

> -----Original Message-----
> From: Liu Dave-r63238 [mailto:DaveLiu@freescale.com]
> Sent: Thursday, June 01, 2006 8:52 PM
> To: Martin, Tim; linuxppc-embedded@ozlabs.org
> Subject: RE: MPC85xx PCI transfer disconnect
>=20
>=20
> > I know this is probably a question for Freescale directly,
> > but I thought I would post here to see if anyone else has
> > seen similar issues with the MPC85xx PCI under Linux.
> >
> > I'm using a Freescale MPC85xx (8541) processor and seeing an
> > extreme slowness to the PCI bus.
> >
> > I'm attemping to do 2048 byte PCI burst reads from an
> > external PCI master.  So an external chip is the PCI master
> > ("initiator") and the MPC85xx is the PCI slave ("target")
> >
> > When initiating the PCI burst read, there is a 270 ns delay
> > from the MPC85xx claiming the transaction (DEVSEL# going low)
> > to being ready (TRDY# going low).  Then 64 bytes (a single
> > cacheline) are transferred, and TRDY# goes inactive.  Next,
> > STOP# goes low, terminating the transfer.  I believe this is
> > considered a PCI DISCONNECT type 1 since IRDY# is active the
> > entire time.
> >
>=20
> The 85xx cacheline is 32 bytes.
> Did you enable Memory Read Multiple command of your PCI master?
>=20
> > What I would expect is that the entire 2048 bytes are
> > transferred in one PCI bus mastership, but instead there are
> > several re-arbitrations and long delays in between several 64
> > byte transfers.
> >
> > Additional info:
> > The PCI bus is 64bit running at 66 MHz.
> > I'm running a modified Linux 2.6.9 kernel (elinos-111).
> > The PCI CCSR piwar1 =3D 0xa0f4401d.
> >
> > Freescale has an FAQ 21021 that describes having a PCI
> > DISCONNECT 2, which sounds similar to my problem, but I've
> > already confirmed I'm doing what the FAQ suggests (enable
> > prefetching in the piwar register)
> > (http://www.freescale.com/webapp/sps/utils/SingleFaq.jsp?FAQ-2
> 1021.xml)
>=20
> Any thoughts/suggestions would be appreciated,
> Tim
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-
> embedded

^ permalink raw reply

* Re: [PATCH] hugetlb: powerpc: Actively close unused htlb regions on vma close
From: Hugh Dickins @ 2006-06-02 16:43 UTC (permalink / raw)
  To: Adam Litke; +Cc: linuxppc-dev, David Gibson, linux-kernel, linux-mm
In-Reply-To: <1149257287.9693.6.camel@localhost.localdomain>

On Fri, 2 Jun 2006, Adam Litke wrote:
> 
> On powerpc, each segment can contain pages of only one size.  When a
> hugetlb mapping is requested, a segment is located and marked for use
> with huge pages.  This is a uni-directional operation -- hugetlb
> segments are never marked for use again with normal pages.  For long
> running processes which make use of a combination of normal and hugetlb
> mappings, this behavior can unduly constrain the virtual address space.
> 
> The following patch introduces a architecture-specific vm_ops.close()
> hook.  For all architectures besides powerpc, this is a no-op.  On
> powerpc, the low and high segments are scanned to locate empty hugetlb
> segments which can be made available for normal mappings.  Comments?

Wouldn't hugetlb_free_pgd_range be a better place to do that kind of
thing, all within arch/powerpc, no need for arch_hugetlb_close_vma etc?

Hugh

^ permalink raw reply

* Re: [Alsa-devel] [RFC 0/8] snd-aoa: add snd-aoa
From: Takashi Iwai @ 2006-06-02 15:23 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <1149260165.11092.32.camel@johannes.berg>

At Fri, 02 Jun 2006 16:56:05 +0200,
Johannes Berg wrote:
> 
> On Fri, 2006-06-02 at 16:43 +0200, Takashi Iwai wrote:
> 
> > As already posted, there are small glitches, but it looks otherwise
> > good enough to merge.
> 
> Right, I'll post updates (also have a few small changes locally)
> 
> > Would you like to commit the patches as one changeset or separate?
> 
> I guess it doesn't make much sense to commit them in separate changesets
> as they depend on each other, I just split it up for making it easier to
> review.

OK.

> > Anyway, please provide a changelog and a signed-off-by line for proper
> > commit.
> 
> Obviously, but I didn't think that was necessary for review.
> 
> Also, what with further development? I have this in a git tree and will
> continue using it, should I just push patches regularly?

Please post patches to alsa-devel ML.  It's easier for us to review.


Takashi

^ permalink raw reply

* Re: [PATCH] hugetlb: powerpc: Actively close unused htlb regions on vma close
From: Dave Hansen @ 2006-06-02 15:17 UTC (permalink / raw)
  To: Adam Litke; +Cc: linuxppc-dev, David Gibson, linux-kernel, linux-mm
In-Reply-To: <1149257287.9693.6.camel@localhost.localdomain>

On Fri, 2006-06-02 at 09:08 -0500, Adam Litke wrote:
>  #define HAVE_ARCH_UNMAPPED_AREA
>  #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
> +#define ARCH_HAS_HUGETLB_CLOSE_VMA
>  
>  #endif
>  
> diff -upN reference/include/linux/hugetlb.h
> current/include/linux/hugetlb.h
> --- reference/include/linux/hugetlb.h
> +++ current/include/linux/hugetlb.h
> @@ -85,6 +85,12 @@ pte_t huge_ptep_get_and_clear(struct mm_
>  void hugetlb_prefault_arch_hook(struct mm_struct *mm);
>  #endif
>  
> +#ifndef ARCH_HAS_HUGETLB_CLOSE_VMA
> +#define arch_hugetlb_close_vma(x)      0
> +#else
> +void arch_hugetlb_close_vma(struct vm_area_struct *vma);
> +#endif

Please don't do this ARCH_HAS stuff.  Use Kconfig at the very least.
You could also have an arch-specific htlb vma init function that could
be used for other things in the future. 

> @@ -297,7 +297,6 @@ void hugetlb_free_pgd_range(struct mmu_g
>         start = addr;
>         pgd = pgd_offset((*tlb)->mm, addr);
>         do {
> -               BUG_ON(! in_hugepage_area((*tlb)->mm->context, addr));
>                 next = pgd_addr_end(addr, end);
>                 if (pgd_none_or_clear_bad(pgd))
>                         continue;

Why does this BUG() go away?

> +/*
> + * Called when tearing down a hugetlb vma.  See if we can free up any
> + * htlb areas so normal pages can be mapped there again.
> + */
> +void arch_hugetlb_close_vma(struct vm_area_struct *vma)
> +{
> +       struct mm_struct *mm = vma->vm_mm;
> +       unsigned long i;
> +       struct slb_flush_info fi;
> +       u16 inuse, hiflush, loflush;
> +
> +       if (!mm)
> +               return;

Why is this check necessary?  Do kernel threads use vmas? ;)

> +       inuse = mm->context.low_htlb_areas;
> +       for (i = 0; i < NUM_LOW_AREAS; i++)
> +               if (prepare_low_area_for_htlb(mm, i) == 0)
> +                       inuse &= ~(1 << i);

Why check _all_ the areas?  Shouldn't the check just be for the current
VMA's area?  Also, prepare_low_area_for_htlb() is a pretty silly
function name, especially for its use here.  Especially because you are
tearing down a htlb area.  low_area_contains_vma() is a bit more apt.  

My first thought about what this function is that it should probably be
asking the question, "is the VMA that I'm closing right now that last
one in this segment?"

> +       loflush = inuse ^ mm->context.low_htlb_areas;
> +       mm->context.low_htlb_areas = inuse;

This bit fiddling should really be done in some helper functions.  It
isn't immediately and completely obvious what this is doing.  

> +       inuse = mm->context.high_htlb_areas;

Are you re-using "inuse"?  How about a different variable name for a
different use?

> +       for (i = 0; i < NUM_HIGH_AREAS; i++)
> +               if (prepare_high_area_for_htlb(mm, i) == 0)
> +                       inuse &= ~(1 << i);
> +       hiflush = inuse ^ mm->context.high_htlb_areas;
> +       mm->context.high_htlb_areas = inuse;

This, combined with the other loop, completely rebuild the mm->context's
view into htlb state, right?  Isn't that a bit excessive?

> +       /* the context changes must make it to memory before the flush,
> +        * so that further SLB misses do the right thing. */
> +       mb();
> +       fi.mm = mm;
> +       if ((fi.newareas = loflush))
> +               on_each_cpu(flush_low_segments, &fi, 0, 1);
> +       if ((fi.newareas = hiflush))
> +               on_each_cpu(flush_high_segments, &fi, 0, 1);
> +}

Yikes!  Think about a pathological program here.  It mmap()s 1 htlb
area, then unmaps it quickly, over and over.  What will that perform
like here?  

-- Dave

^ permalink raw reply

* [PATCH] hugetlb: powerpc: Actively close unused htlb regions on vma close
From: Adam Litke @ 2006-06-02 14:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linux-mm, linux-kernel, David Gibson

[PATCH] powerpc: Close hugetlb regions when unmapping VMAs

On powerpc, each segment can contain pages of only one size.  When a
hugetlb mapping is requested, a segment is located and marked for use
with huge pages.  This is a uni-directional operation -- hugetlb
segments are never marked for use again with normal pages.  For long
running processes which make use of a combination of normal and hugetlb
mappings, this behavior can unduly constrain the virtual address space.

The following patch introduces a architecture-specific vm_ops.close()
hook.  For all architectures besides powerpc, this is a no-op.  On
powerpc, the low and high segments are scanned to locate empty hugetlb
segments which can be made available for normal mappings.  Comments?

Signed-off-by: Adam Litke <agl@us.ibm.com>
---
 arch/powerpc/mm/hugetlbpage.c |   39 ++++++++++++++++++++++++++++++++++++++-
 include/asm-powerpc/pgtable.h |    1 +
 include/linux/hugetlb.h       |    6 ++++++
 mm/hugetlb.c                  |    1 +
 4 files changed, 46 insertions(+), 1 deletion(-)
diff -upN reference/arch/powerpc/mm/hugetlbpage.c current/arch/powerpc/mm/hugetlbpage.c
--- reference/arch/powerpc/mm/hugetlbpage.c
+++ current/arch/powerpc/mm/hugetlbpage.c
@@ -297,7 +297,6 @@ void hugetlb_free_pgd_range(struct mmu_g
 	start = addr;
 	pgd = pgd_offset((*tlb)->mm, addr);
 	do {
-		BUG_ON(! in_hugepage_area((*tlb)->mm->context, addr));
 		next = pgd_addr_end(addr, end);
 		if (pgd_none_or_clear_bad(pgd))
 			continue;
@@ -494,6 +493,44 @@ static int open_high_hpage_areas(struct 
 	return 0;
 }
 
+/*
+ * Called when tearing down a hugetlb vma.  See if we can free up any
+ * htlb areas so normal pages can be mapped there again.
+ */
+void arch_hugetlb_close_vma(struct vm_area_struct *vma)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long i;
+	struct slb_flush_info fi;
+	u16 inuse, hiflush, loflush;
+
+	if (!mm)
+		return;
+
+	inuse = mm->context.low_htlb_areas;
+	for (i = 0; i < NUM_LOW_AREAS; i++)
+		if (prepare_low_area_for_htlb(mm, i) == 0)
+			inuse &= ~(1 << i);
+	loflush = inuse ^ mm->context.low_htlb_areas;
+	mm->context.low_htlb_areas = inuse;
+
+	inuse = mm->context.high_htlb_areas;
+	for (i = 0; i < NUM_HIGH_AREAS; i++)
+		if (prepare_high_area_for_htlb(mm, i) == 0)
+			inuse &= ~(1 << i);
+	hiflush = inuse ^ mm->context.high_htlb_areas;
+	mm->context.high_htlb_areas = inuse;
+
+	/* the context changes must make it to memory before the flush,
+	 * so that further SLB misses do the right thing. */
+	mb();
+	fi.mm = mm;
+	if ((fi.newareas = loflush))
+		on_each_cpu(flush_low_segments, &fi, 0, 1);
+	if ((fi.newareas = hiflush))
+		on_each_cpu(flush_high_segments, &fi, 0, 1);
+}
+
 int prepare_hugepage_range(unsigned long addr, unsigned long len)
 {
 	int err = 0;
diff -upN reference/include/asm-powerpc/pgtable.h current/include/asm-powerpc/pgtable.h
--- reference/include/asm-powerpc/pgtable.h
+++ current/include/asm-powerpc/pgtable.h
@@ -155,6 +155,7 @@ extern unsigned long empty_zero_page[PAG
 
 #define HAVE_ARCH_UNMAPPED_AREA
 #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+#define ARCH_HAS_HUGETLB_CLOSE_VMA
 
 #endif
 
diff -upN reference/include/linux/hugetlb.h current/include/linux/hugetlb.h
--- reference/include/linux/hugetlb.h
+++ current/include/linux/hugetlb.h
@@ -85,6 +85,12 @@ pte_t huge_ptep_get_and_clear(struct mm_
 void hugetlb_prefault_arch_hook(struct mm_struct *mm);
 #endif
 
+#ifndef ARCH_HAS_HUGETLB_CLOSE_VMA
+#define arch_hugetlb_close_vma(x)	0
+#else
+void arch_hugetlb_close_vma(struct vm_area_struct *vma);
+#endif
+
 #else /* !CONFIG_HUGETLB_PAGE */
 
 static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
diff -upN reference/mm/hugetlb.c current/mm/hugetlb.c
--- reference/mm/hugetlb.c
+++ current/mm/hugetlb.c
@@ -399,6 +399,7 @@ static struct page *hugetlb_nopage(struc
 
 struct vm_operations_struct hugetlb_vm_ops = {
 	.nopage = hugetlb_nopage,
+	.close = arch_hugetlb_close_vma,
 };
 
 static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page,

-- 
Adam Litke - (agl at us.ibm.com)
IBM Linux Technology Center

^ permalink raw reply

* 8xx spi completion sometime doesn't generate an interrupt
From: Antonio Di Bacco @ 2006-06-02 15:08 UTC (permalink / raw)
  To: linuxppc-embedded

As far I understood the spi bus device of mpc8xx works independently from the 
attached device (in my case a dataflash m25pe80). Thus I don't understand why 
sometime when I start an SPI transfer I don't receive an interrupt for the 
completion of this operation. I wait 50 ms for this interrupt and sometime it 
doesn't happen. Anyone had a similar problem?

Bye,
Antonio.

^ permalink raw reply

* [PATCH] fix make rpm for powerpc
From: Mike Wolf @ 2006-06-02 14:53 UTC (permalink / raw)
  To: linux-kernel; +Cc: linuxppc-dev

The default target for most powerpc platforms is zImage.  The
zImage however is in arch/powerpc/boot and the mkspec script
was set up to get the kernel from the top level of the kernel 
tree.  This patch copies vmlinux to arch/powerpc/boot and then
copies the kernel to the tmp directory so the rpm can be made.

Signed-off-by: Mike Wolf <mjw@us.ibm.com>


=============

--- linux.orig/scripts/package/mkspec	2006-05-21 23:22:53.000000000 -0500
+++ linux/scripts/package/mkspec	2006-05-22 15:13:56.000000000 -0500
@@ -73,8 +73,13 @@
 echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/efi/vmlinuz-$KERNELRELEASE"
 echo 'ln -s '"efi/vmlinuz-$KERNELRELEASE" '$RPM_BUILD_ROOT'"/boot/"
 echo "%else"
+echo "%ifarch ppc64"
+echo "cp vmlinux arch/powerpc/boot"
+echo "cp arch/powerpc/boot/"'$KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE"
+echo "%else"
 echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE"
 echo "%endif"
+echo "%endif"
 
 echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE"
 

^ permalink raw reply

* Re: [Alsa-devel] [RFC 0/8] snd-aoa: add snd-aoa
From: Johannes Berg @ 2006-06-02 14:56 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <s5hodxb4o00.wl%tiwai@suse.de>

[-- Attachment #1: Type: text/plain, Size: 749 bytes --]

On Fri, 2006-06-02 at 16:43 +0200, Takashi Iwai wrote:

> As already posted, there are small glitches, but it looks otherwise
> good enough to merge.

Right, I'll post updates (also have a few small changes locally)

> Would you like to commit the patches as one changeset or separate?

I guess it doesn't make much sense to commit them in separate changesets
as they depend on each other, I just split it up for making it easier to
review.

> Anyway, please provide a changelog and a signed-off-by line for proper
> commit.

Obviously, but I didn't think that was necessary for review.

Also, what with further development? I have this in a git tree and will
continue using it, should I just push patches regularly?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: [PATCH/2.6.17-rc4 1/10] Powerpc: Add general support for mpc7 448h pc2 (Taiga) platform
From: Kumar Gala @ 2006-06-02 14:50 UTC (permalink / raw)
  To: Zang Roy-r61911
  Cc: Alexandre.Bounine, Liu Dave-r63238, linuxppc-dev list,
	Paul Mackerras, Yang Xin-Xin-r48390
In-Reply-To: <9FCDBA58F226D911B202000BDBAD4673066CF774@zch01exm40.ap.freescale.net>


On Jun 2, 2006, at 3:20 AM, Zang Roy-r61911 wrote:

>
>> How much RAM do you have ? Maybe you are running out of
>> virtual space ?
>>
>> Ben.
>>
>>
>
> 512MBytes

If I understand things, there is a 16M region for PCI config space.   
You could look at just doing the ioremap for each chunk when its  
needed via the low level calls.

- kumar

^ permalink raw reply

* Re: [Alsa-devel] [RFC 3/8] snd-aoa: add soundbus
From: Takashi Iwai @ 2006-06-02 14:45 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: linuxppc-dev, Johannes Berg, alsa-devel
In-Reply-To: <jeu073aad1.fsf@sykes.suse.de>

At Fri, 02 Jun 2006 16:41:14 +0200,
Andreas Schwab wrote:
> 
> Takashi Iwai <tiwai@suse.de> writes:
> 
> > At Fri, 02 Jun 2006 16:07:05 +0200,
> > Johannes Berg wrote:
> >> 
> >> On Fri, 2006-06-02 at 15:53 +0200, Takashi Iwai wrote:
> >> > > +	if (strlen(sdev->modalias)) {
> >> > > +		length = snprintf (buf, 34, "%s\n", sdev->modalias);
> >> > 
> >> > sizeof(sdev->modalias) + 2?  But still strange if modalias has no
> >> > nul-end.
> >> 
> >> Hm, how would I handle that if modalias has no nul?
> >
> > Well, I'm not sure whether modalias is always nul-terminated.
> 
> If modalias is not nul-terminated then strlen will already fail.

Oh yes.  It should be simply
	if (*sdev->modalias) {
		...

> > Otherwise (if not nul-terminated), I'd implement like:
> >
> > 	strlcpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1);
> > 	strcpy(buf, "\n");
> 
> strcat?

Argh, yes.


Takashi

^ permalink raw reply

* Re: [Alsa-devel] [RFC 3/8] snd-aoa: add soundbus
From: Johannes Berg @ 2006-06-02 14:44 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Takashi Iwai, linuxppc-dev, alsa-devel
In-Reply-To: <jeu073aad1.fsf@sykes.suse.de>

[-- Attachment #1: Type: text/plain, Size: 199 bytes --]

On Fri, 2006-06-02 at 16:41 +0200, Andreas Schwab wrote:

> If modalias is not nul-terminated then strlen will already fail.

Yeah, I'll just have to make sure elsewhere that it is.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: [Alsa-devel] [RFC 0/8] snd-aoa: add snd-aoa
From: Takashi Iwai @ 2006-06-02 14:43 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <20060601115844.343214000@sipsolutions.net>

At Thu, 01 Jun 2006 13:58:44 +0200,
Johannes Berg wrote:
> 
> The following patches would add snd-aoa to the Linux source tree. I'm
> posting them here in the spirit of getting review fairly early, it works
> fine for those machines it handles and even implements headphone/line-out
> detection now.
> 
> One thing that still needs to be done is fix this on the mac-mini where
> apparently some things are missing from the device-tree, and on the
> PowerMac7,2/7,3 where the device tree has a bug that prevents the i2sbus
> module from working properly.
> 
> Other than that, it replaces snd-powermac for all layout-id machines, and
> handles many more already, so once those two issues are fixed I'll also add
> a patch to this patchset that removes support for any machines with a
> layout-id from snd-powermac to allow snd-aoa and snd-powermac to coexist
> nicely.
> 
> Any comments are appreciated.

As already posted, there are small glitches, but it looks otherwise
good enough to merge.

Would you like to commit the patches as one changeset or separate?
Anyway, please provide a changelog and a signed-off-by line for proper
commit.


thanks,

Takashi

^ permalink raw reply

* Re: [Alsa-devel] [RFC 3/8] snd-aoa: add soundbus
From: Andreas Schwab @ 2006-06-02 14:41 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: linuxppc-dev, Johannes Berg, alsa-devel
In-Reply-To: <s5hslmn4p00.wl%tiwai@suse.de>

Takashi Iwai <tiwai@suse.de> writes:

> At Fri, 02 Jun 2006 16:07:05 +0200,
> Johannes Berg wrote:
>> 
>> On Fri, 2006-06-02 at 15:53 +0200, Takashi Iwai wrote:
>> > > +	if (strlen(sdev->modalias)) {
>> > > +		length = snprintf (buf, 34, "%s\n", sdev->modalias);
>> > 
>> > sizeof(sdev->modalias) + 2?  But still strange if modalias has no
>> > nul-end.
>> 
>> Hm, how would I handle that if modalias has no nul?
>
> Well, I'm not sure whether modalias is always nul-terminated.

If modalias is not nul-terminated then strlen will already fail.

> Otherwise (if not nul-terminated), I'd implement like:
>
> 	strlcpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1);
> 	strcpy(buf, "\n");

strcat?

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply

* Re: [Alsa-devel] [RFC 5/8] snd-aoa: add codecs
From: Takashi Iwai @ 2006-06-02 14:31 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <20060601115848.075177000@sipsolutions.net>

At Thu, 01 Jun 2006 13:58:49 +0200,
Johannes Berg wrote:
> 
> --- /dev/null
> +++ b/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h
> @@ -0,0 +1,209 @@
> +/*
> + This is the program used to generate below table.
> +
> +#include <stdio.h>
> +#include <math.h>
> +int main() {
> +  int dB2;
> +  printf("/" "* This file is only included exactly once!\n");
> +  printf(" *\n");
> +  printf(" * If they'd only tell us that generating this table was\n");
> +  printf(" * as easy as calculating\n");
> +  printf(" *      hwvalue = 1048576.0*exp(0.057564628*dB*2)\n");
> +  printf(" * :) *" "/\n");
> +  printf("static int tas_gaintable[] = {\n");
> +  printf("	0x000000, /" "* -infinity dB *" "/\n");
> +  for (dB2=-140;dB2<=36;dB2++)
> +    printf("	0x%.6x, /" "* %-02.1f dB *" "/\n", (int)(1048576.0*exp(0.057564628*dB2)), dB2/2.0);
> +  printf("};\n\n");
> +}

FYI:  We're currently implementing a dB conversion.  So, this will be 
unneeded in future.

But I'll included this as it is now at committing, and fix the dB
things later.


Takashi

^ permalink raw reply

* Re: [Alsa-devel] [RFC 4/8] snd-aoa: add i2sbus
From: Takashi Iwai @ 2006-06-02 14:23 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <20060601115847.420788000@sipsolutions.net>

At Thu, 01 Jun 2006 13:58:48 +0200,
Johannes Berg wrote:
> 
> --- /dev/null
> +++ b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
> +static int clock_and_divisors(int mclk, int sclk, int rate, int *out)
> +{
> +	/* sclk must be derived from mclk! */
> +	if (mclk % sclk)
> +		return -1;
> +	/* derive sclk register value */
> +	if (i2s_sf_sclkdiv(mclk / sclk, out))
> +		return -1;
> +
> +	if (I2S_CLOCK_SPEED_18MHz % rate == 0) {
> +		if ((I2S_CLOCK_SPEED_18MHz / rate) % mclk == 0) {

Equivalent with "I2S_CLOCK_SPEED_18MHZ % (rate * mclk) == 0" ?

> +static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
> +{
(snip)
> +	list_for_each_entry(cii, &sdev->codec_list, list) {
> +		if (cii->codec->open) {
> +			err = cii->codec->open(cii, pi->substream);
> +			if (err) {
> +				result = err;
> +				goto out_unlock;

What happens if the first code is opened but fail the secondary?
No need to close the first?

> +static snd_pcm_uframes_t i2sbus_pcm_pointer(struct i2sbus_dev *i2sdev, int in)
> +{
> +	struct pcm_info *pi;
> +	u32 fc;
> +
> +	get_pcm_info(i2sdev, in, &pi, NULL);
> +
> +	fc = in_le32(&i2sdev->intfregs->frame_count);
> +	fc = fc - pi->frame_count;
> +
> +	return (bytes_to_frames(pi->substream->runtime,
> +			       pi->current_period *
> +			       snd_pcm_lib_period_bytes(pi->substream)) + fc) % pi->substream->runtime->buffer_size;
> +}
> +
> +static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in)
> +{
> +	struct pcm_info *pi;
> +	u32 fc;
> +	u32 delta;
> +
> +	spin_lock(&i2sdev->low_lock);
> +	get_pcm_info(i2sdev, in, &pi, NULL);
> +	if (!pi->substream) {
> +		printk(KERN_INFO "i2sbus: got %s irq while not active!\n",
> +		       in ? "rx" : "tx");
> +		goto out_unlock;
> +	}
> +
> +	fc = in_le32(&i2sdev->intfregs->frame_count);
> +	/* a counter overflow does not change the calculation. */
> +	delta = fc - pi->frame_count;
> +
> +	/* update current_period */
> +	while (delta >= pi->substream->runtime->period_size) {
> +		pi->current_period++;
> +		delta = delta - pi->substream->runtime->period_size;
> +	}
> +
> +	if (unlikely(delta)) {
> +		/* Some interrupt came late, so check the dbdma.
> +		 * This special case exists to syncronize the frame_count with the
> +		 * dbdma transfers, but is hit every once in a while. */
> +		int period;
> +
> +		period = (in_le32(&pi->dbdma->cmdptr) - pi->dbdma_ring.bus_cmd_start) / sizeof(struct dbdma_cmd);
> +		pi->current_period = pi->current_period % pi->substream->runtime->periods;
> +
> +		while (pi->current_period != period) {
> +			pi->current_period = (pi->current_period + 1) % pi->substream->runtime->periods;
> +			/* Set delta to zero, as the frame_count value is too high (otherwise the code path
> +			 * will not be executed).
> +			 * This is to correct the fact that the frame_count is too low at the beginning
> +			 * due to the dbdma's buffer. */
> +			delta = 0;

Too long lines...

> +/* FIXME: this function needs an error handling strategy with labels */
> +int
> +i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
> +		    struct codec_info *ci, void *data)
> +{
> +	int err, in = 0, out = 0;
> +	struct transfer_info *tmp;
> +	struct i2sbus_dev *i2sdev = soundbus_dev_to_i2sbus_dev(dev);
> +	struct codec_info_item *cii;
> +
> +	if (!dev->pcmname || dev->pcmid == -1) {
> +		printk(KERN_ERR "i2sbus: pcm name and id must be set!\n");

No error return?

> +	/* well, we really should support scatter/gather DMA */
> +	/* FIXME FIXME FIXME: If this fails, we BUG() when the alsa layer
> +	 * later tries to allocate memory. Apparently we should be setting
> +	 * some device pointer for that ...
> +	 */
> +	snd_pcm_lib_preallocate_pages_for_all(
> +		dev->pcm, SNDRV_DMA_TYPE_DEV,
> +		snd_dma_pci_data(macio_get_pci_dev(i2sdev->macio)),
> +		64 * 1024, 64 * 1024);

Is the comment true?  Yes, you have to set the device pointer via
snd_pcm_lib_preallocate*().  But it must be OK even if preallocate
fails.

> --- /dev/null
> +++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
> +static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
> +				       struct dbdma_command_mem *r,
> +				       int numcmds)
> +{
> +	/* one more for rounding */
> +	r->size = (numcmds+1) * sizeof(struct dbdma_cmd);
> +	/* We use the PCI APIs for now until the generic one gets fixed
> +	 * enough or until we get some macio-specific versions
> +	 */
> +	r->space = pci_alloc_consistent(macio_get_pci_dev(i2sdev->macio),
> +					r->size,
> +					&r->bus_addr);

Better to use dma_alloc_coherent().  pci_alloc_consistent() implies
GFP_ATOMIC.

> +static irqreturn_t i2sbus_bus_intr(int irq, void *devid, struct pt_regs *regs)
> +{
> +	struct i2sbus_dev *dev = devid;
> +	u32 intreg;
> +
> +	spin_lock(&dev->low_lock);
> +	intreg = in_le32(&dev->intfregs->intr_ctl);
> +
> +	printk(KERN_INFO "i2sbus: interrupt, intr reg is 0x%x!\n", intreg);

Should this be really always printed?


Takashi

^ permalink raw reply

* Re: [Alsa-devel] [RFC 3/8] snd-aoa: add soundbus
From: Takashi Iwai @ 2006-06-02 14:21 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <1149257225.11092.22.camel@johannes.berg>

At Fri, 02 Jun 2006 16:07:05 +0200,
Johannes Berg wrote:
> 
> On Fri, 2006-06-02 at 15:53 +0200, Takashi Iwai wrote:
> > > +	if (strlen(sdev->modalias)) {
> > > +		length = snprintf (buf, 34, "%s\n", sdev->modalias);
> > 
> > sizeof(sdev->modalias) + 2?  But still strange if modalias has no
> > nul-end.
> 
> Hm, how would I handle that if modalias has no nul?

Well, I'm not sure whether modalias is always nul-terminated.
If yes (I hope so), the above could be simply sprintf().

Otherwise (if not nul-terminated), I'd implement like:

	strlcpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1);
	strcpy(buf, "\n");
	lenth = strlen(buf);

Takashi

^ permalink raw reply

* Re: [Alsa-devel] [RFC 3/8] snd-aoa: add soundbus
From: Johannes Berg @ 2006-06-02 14:07 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <s5hu0734qay.wl%tiwai@suse.de>

[-- Attachment #1: Type: text/plain, Size: 562 bytes --]

On Fri, 2006-06-02 at 15:53 +0200, Takashi Iwai wrote:
> > +		int l;
> > +		length += sprintf (buf, "%s\n", compat);
> > +		buf += length;
> 
> This seems wrong.  The above should be

Heh, no idea where I copied that from but I sure didn't write it myself.
Should be more careful next time I guess :)

> > +	if (strlen(sdev->modalias)) {
> > +		length = snprintf (buf, 34, "%s\n", sdev->modalias);
> 
> sizeof(sdev->modalias) + 2?  But still strange if modalias has no
> nul-end.

Hm, how would I handle that if modalias has no nul?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: [Alsa-devel] [RFC 3/8] snd-aoa: add soundbus
From: Takashi Iwai @ 2006-06-02 13:53 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <20060601115846.852128000@sipsolutions.net>

At Thu, 01 Jun 2006 13:58:47 +0200,
Johannes Berg wrote:
> 
> --- /dev/null
> +++ b/sound/aoa/soundbus/sysfs.c
> +static ssize_t
> +compatible_show (struct device *dev, struct device_attribute *attr, char *buf)
> +{
> +	struct of_device *of;
> +	char *compat;
> +	int cplen;
> +	int length = 0;
> +
> +	of = &to_soundbus_device (dev)->ofdev;
> +	compat = (char *) get_property(of->node, "compatible", &cplen);
> +	if (!compat) {
> +		*buf = '\0';
> +		return 0;
> +	}
> +	while (cplen > 0) {
> +		int l;
> +		length += sprintf (buf, "%s\n", compat);
> +		buf += length;

This seems wrong.  The above should be

	l = sprintf(buf + length, "%s\n", compat);
	length += l;
	buf += l;

> +		l = strlen (compat) + 1;
> +		compat += l;
> +		cplen -= l;
> +	}
> +
> +	return length;
> +}
> +
> +static ssize_t modalias_show (struct device *dev, struct device_attribute *attr,
> +			      char *buf)
> +{
> +	struct soundbus_dev *sdev = to_soundbus_device(dev);
> +	struct of_device *of = &sdev->ofdev;
> +	int length;
> +
> +	if (strlen(sdev->modalias)) {
> +		length = snprintf (buf, 34, "%s\n", sdev->modalias);

sizeof(sdev->modalias) + 2?  But still strange if modalias has no
nul-end.

> +	} else {
> +		length = sprintf (buf, "of:N%sT%s\n", of->node->name, of->node->type);
> +	}

Remove braces for single-line if (and too long).


Takashi

^ permalink raw reply

* Re: [Alsa-devel] [RFC 2/8] snd-aoa: add aoa core
From: Johannes Berg @ 2006-06-02 13:46 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <s5hverj4qsd.wl%tiwai@suse.de>

[-- Attachment #1: Type: text/plain, Size: 1764 bytes --]

On Fri, 2006-06-02 at 15:42 +0200, Takashi Iwai wrote:
> > +static void attach_codec_to_fabric(struct aoa_codec *c)
> 
> Doesn't this need to return an error?
> I'm afraid that module count is unblanced in the error path of
> aoa_corec_[un]register().

Not sure, I'll have to take a look.

> > +		printk("snd-aoa: fabric didn't like codec %s\n", c->name);
> 
> Add KERN_* prefix.

Uh, right.

> > +	rt->implementation_private = 0;
> > +	INIT_WORK(&rt->headphone_notify.work, pmf_handle_notify, &rt->headphone_notify);
> > +	INIT_WORK(&rt->line_in_notify.work, pmf_handle_notify, &rt->line_in_notify);
> > +	INIT_WORK(&rt->line_out_notify.work, pmf_handle_notify, &rt->line_out_notify);
> 
> Too long lines.

Heh, I knew I'd get this at lots of places, I'll work on it.

> > +	pmf_gpio_all_amps_off(rt);
> > +	rt->implementation_private = 0;
> > +	if (rt->headphone_notify.gpio_private)
> > +		pmf_unregister_irq_client(rt->headphone_notify.gpio_private);
> > +	if (rt->line_in_notify.gpio_private)
> > +		pmf_unregister_irq_client(rt->line_in_notify.gpio_private);
> > +	if (rt->line_out_notify.gpio_private)
> > +		pmf_unregister_irq_client(rt->line_out_notify.gpio_private);
> 
> Don't need kfree(gpio_private)?

Indeed, forgot that.

> > +	strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver)-1);
> > +	strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname)-1);
> > +	strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname)-1);
> > +	strlcpy(alsa_card->mixername, name, sizeof(alsa_card->mixername)-1);
> 
> Pass sizeof() without -1.  strlcpy() takes the size of the buffer
> including nul-terminator.

Yeah, I was confused about the API. Will fix those too.

Thanks,
johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: [Alsa-devel] [RFC 2/8] snd-aoa: add aoa core
From: Takashi Iwai @ 2006-06-02 13:42 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <20060601115845.923706000@sipsolutions.net>

At Thu, 01 Jun 2006 13:58:46 +0200,
Johannes Berg wrote:
> 
> --- /dev/null
> +++ b/sound/aoa/core/snd-aoa-core.c
> @@ -0,0 +1,153 @@
> +/*
> + * Apple Onboard Audio driver core
> + *
> + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
> + *
> + * GPL v2, can be found in COPYING.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/list.h>
> +#include "../aoa.h"
> +#include "snd-aoa-alsa.h"
> +
> +MODULE_DESCRIPTION("Apple Onboard Audio Sound Driver");
> +MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
> +MODULE_LICENSE("GPL");
> +
> +/* We allow only one fabric. This simplifies things,
> + * and more don't really make that much sense */
> +static struct aoa_fabric *fabric;
> +static LIST_HEAD(codec_list);
> +
> +static void attach_codec_to_fabric(struct aoa_codec *c)

Doesn't this need to return an error?
I'm afraid that module count is unblanced in the error path of
aoa_corec_[un]register().

> +{
> +	int err;
> +
> +	if (!try_module_get(c->owner))
> +		return;
> +	/* found_codec has to be assigned */
> +	err = -ENOENT;
> +	if (fabric->found_codec)
> +		err = fabric->found_codec(c);
> +	if (err) {
> +		module_put(c->owner);
> +		printk("snd-aoa: fabric didn't like codec %s\n", c->name);

Add KERN_* prefix.

> +		return;
> +	}
> +	c->fabric = fabric;
> +
> +	err = 0;
> +	if (c->init)
> +		err = c->init(c);
> +	if (err) {
> +		printk("snd-aoa: codec %s didn't init\n", c->name);

Ditto.

> --- /dev/null
> +++ b/sound/aoa/core/snd-aoa-gpio-pmf.c
(snip)
> +static void pmf_gpio_init(struct gpio_runtime *rt)
> +{
> +	pmf_gpio_all_amps_off(rt);
> +	rt->implementation_private = 0;
> +	INIT_WORK(&rt->headphone_notify.work, pmf_handle_notify, &rt->headphone_notify);
> +	INIT_WORK(&rt->line_in_notify.work, pmf_handle_notify, &rt->line_in_notify);
> +	INIT_WORK(&rt->line_out_notify.work, pmf_handle_notify, &rt->line_out_notify);

Too long lines.

> +	mutex_init(&rt->headphone_notify.mutex);
> +	mutex_init(&rt->line_in_notify.mutex);
> +	mutex_init(&rt->line_out_notify.mutex);
> +}
> +
> +static void pmf_gpio_exit(struct gpio_runtime *rt)
> +{
> +	pmf_gpio_all_amps_off(rt);
> +	rt->implementation_private = 0;
> +	if (rt->headphone_notify.gpio_private)
> +		pmf_unregister_irq_client(rt->headphone_notify.gpio_private);
> +	if (rt->line_in_notify.gpio_private)
> +		pmf_unregister_irq_client(rt->line_in_notify.gpio_private);
> +	if (rt->line_out_notify.gpio_private)
> +		pmf_unregister_irq_client(rt->line_out_notify.gpio_private);

Don't need kfree(gpio_private)?

> --- /dev/null
> +++ b/sound/aoa/core/snd-aoa-alsa.c
(snip)
> +int aoa_alsa_init(char *name, struct module *mod)
> +{
> +	struct snd_card *alsa_card;
> +	int err;
> +
> +	if (aoa_card)
> +		/* cannot be EEXIST due to usage in aoa_fabric_register */
> +		return -EBUSY;
> +
> +	alsa_card = snd_card_new(index, name, mod, sizeof(struct aoa_card));
> +	if (!alsa_card)
> +		return -ENOMEM;
> +	aoa_card = alsa_card->private_data;
> +	aoa_card->alsa_card = alsa_card;
> +	strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver)-1);
> +	strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname)-1);
> +	strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname)-1);
> +	strlcpy(alsa_card->mixername, name, sizeof(alsa_card->mixername)-1);

Pass sizeof() without -1.  strlcpy() takes the size of the buffer
including nul-terminator.


Takashi

^ permalink raw reply

* Re: [PATCH] [2.6.18] U4 DART improvements
From: Segher Boessenkool @ 2006-06-02 12:44 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc-dev, paulus
In-Reply-To: <20060602040426.GA28528@pb15.lixom.net>

Hi Olof,

Looks good.  One request:

> +static inline void dart_tlb_invalidate_one(unsigned long bus_rpn)
> +{
> +	unsigned int reg;
> +	unsigned int l, limit;
> +
> +	reg = DART_CNTL_U4_ENABLE | DART_CNTL_U4_IONE |
> +		(bus_rpn & DART_CNTL_U4_IONE_MASK);
> +	DART_OUT(DART_CNTL, reg);
> +	mb();

Could you please comment the memory barriers, to say exactly _why_ a
certain barrier is needed?  I can't see why wmb() wouldn't work here,
for example (note I'm not saying it would -- I just don't see why it
wouldn't).

Same goes for every single memory barrier in the whole kernel source
code, but I have to start somewhere, heh.


Segher

^ permalink raw reply

* snd-aoa: using feature calls for GPIOs
From: Johannes Berg @ 2006-06-01 18:42 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list

Hi,

The following patch ought to add the possibility of using feature calls
for the GPIOs instead of platform functions. Note that it doesn't
actually hook up the new gpio functions, that needs to be done in the
fabric.

However, the whole thing doesn't work for me yet. In fact, as soon as I
try using this patch, I need to reboot my computer to make the tas react
again to i2c commands. Very strange.

I looked into snd-powermac, and it does very weird things with the
GPIOs. I notice, for example, the following code:
        base = (u32 *)get_property(node, "audio-gpio-active-state", NULL);
        if (base) {
                gp->active_state = *base;
                gp->active_val = (*base) ? 0x5 : 0x4;
                gp->inactive_val = (*base) ? 0x4 : 0x5;

As far as I can see that's bogus. The 0x4/0x5 values aren't ever
actually written to the register, they are just the software values
Darwin uses for unmute/mute (or was it reset/run?).

I don't see where this comes from, looking at Darwin gives you that all
GPIO writes in PlatformInterfaceGPIO_Mapped are either 0 or 1 depending
on the activestate value and using assertGPIO/negateGPIO. I think the
4/5 comes from confusing the kGPIO_* values with what is actually
written to the register.

Also, snd-powermac says: "Try to find the active state, default to 0 !".
That isn't what Darwin does, it defaults to 1.

Anyway, I'm sure I'm doing something stupid in there and just can't find
it, I even 'disassembled' all the platform functions I have to see what
happens in them, and they also write 0 or 1 just like the code below...
Maybe I got some offsets wrong?

--- snd-aoa.orig/aoa.h	2006-06-01 20:29:56.252070199 +0200
+++ snd-aoa/aoa.h	2006-06-01 20:31:03.972070199 +0200
@@ -125,6 +125,7 @@ extern int aoa_snd_ctl_add(struct snd_kc
 
 /* GPIO stuff */
 extern struct gpio_methods *pmf_gpio_methods;
+extern struct gpio_methods *ftr_gpio_methods;
 /* extern struct gpio_methods *map_gpio_methods; */
 
 #endif /* __AOA_H */
--- snd-aoa.orig/core/Makefile	2006-06-01 20:29:56.252070199 +0200
+++ snd-aoa/core/Makefile	2006-06-01 20:31:03.972070199 +0200
@@ -1,4 +1,5 @@
 obj-$(CONFIG_SND_AOA) += snd-aoa.o
 snd-aoa-objs := snd-aoa-core.o \
 		snd-aoa-alsa.o \
-		snd-aoa-gpio-pmf.o
+		snd-aoa-gpio-pmf.o \
+		snd-aoa-gpio-feature.o
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ snd-aoa/core/snd-aoa-gpio-feature.c	2006-06-01 20:31:03.992070199 +0200
@@ -0,0 +1,322 @@
+/*
+ * Apple Onboard Audio feature call GPIO control
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#include <asm/pmac_feature.h>
+#include <linux/interrupt.h>
+#include "../aoa.h"
+
+static int headphone_mute_gpio;
+static int amp_mute_gpio;
+static int lineout_mute_gpio;
+static int hw_reset_gpio;
+static int lineout_detect_gpio;
+static int headphone_detect_gpio;
+static int linein_detect_gpio;
+
+static int headphone_mute_gpio_activestate;
+static int amp_mute_gpio_activestate;
+static int lineout_mute_gpio_activestate;
+static int hw_reset_gpio_activestate;
+static int lineout_detect_gpio_activestate;
+static int headphone_detect_gpio_activestate;
+static int linein_detect_gpio_activestate;
+
+static int lineout_detect_irq;
+static int linein_detect_irq;
+static int headphone_detect_irq;
+
+static void get_gpio(char *name, int *gpioptr, int *gpioactiveptr)
+{
+	struct device_node *np;
+	u32 *reg;
+
+	*gpioptr = -1;
+
+	np = of_find_node_by_name(NULL, name);
+	if (!np)
+		return;
+
+	reg = (u32 *)get_property(np, "reg", NULL);
+	if (!reg)
+		return;
+
+	*gpioptr = *reg;
+
+	/* this is a hack, usually the GPIOs 'reg' property
+	 * should have the offset based from the GPIO space
+	 * which is at 0x50, but apparently not always... */
+	if (*gpioptr < 0x50)
+		*gpioptr += 0x50;
+
+	reg = (u32 *)get_property(np, "audio-gpio-active-state", NULL);
+	if (!reg)
+		*gpioactiveptr = 1;
+	else
+		*gpioactiveptr = *reg;
+
+	printk(KERN_DEBUG "gpio %s = %d (active = %d)\n", name, *gpioptr, *gpioactiveptr);
+}
+
+static void get_irq(char *name, int *irqptr)
+{
+	struct device_node *np;
+
+	*irqptr = -1;
+	np = of_find_node_by_name(NULL, name);
+	if (!np)
+		return;
+	if (np->n_intrs != 1)
+		return;
+	*irqptr = np->intrs[0].line;
+
+	printk(KERN_DEBUG "got %s irq = %d\n", name, *irqptr);
+}
+
+#define SWITCH_GPIO(name, on)					\
+	((on)?(name##_gpio_activestate==0?0:1):(name##_gpio_activestate==0?1:0))
+
+#define FTR_GPIO(name, bit)					\
+static void ftr_gpio_set_##name(struct gpio_runtime *rt, int on)\
+{								\
+	if (unlikely(!rt)) return;				\
+								\
+	if (name##_mute_gpio < 0)				\
+		return;						\
+								\
+	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL,		\
+			  name##_mute_gpio,			\
+			  SWITCH_GPIO(name##_mute, on));	\
+								\
+	rt->implementation_private &= ~(1<<bit);		\
+	rt->implementation_private |= (!!on << bit);		\
+}								\
+static int ftr_gpio_get_##name(struct gpio_runtime *rt)		\
+{								\
+	if (unlikely(!rt)) return 0;				\
+	return (rt->implementation_private>>bit)&1;		\
+}
+
+FTR_GPIO(headphone, 0);
+FTR_GPIO(amp, 1);
+FTR_GPIO(lineout, 2);
+
+static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
+{
+	if (unlikely(!rt)) return;
+	if (hw_reset_gpio < 0)
+		return;
+
+	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL,
+			  hw_reset_gpio, SWITCH_GPIO(hw_reset, on));
+}
+
+static void ftr_gpio_all_amps_off(struct gpio_runtime *rt)
+{
+	int saved;
+
+	if (unlikely(!rt)) return;
+	saved = rt->implementation_private;
+	ftr_gpio_set_headphone(rt, 0);
+	ftr_gpio_set_amp(rt, 0);
+	ftr_gpio_set_lineout(rt, 0);
+	rt->implementation_private = saved;
+}
+
+static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt)
+{
+	int s;
+
+	if (unlikely(!rt)) return;
+	s = rt->implementation_private;
+	ftr_gpio_set_headphone(rt, (s>>0)&1);
+	ftr_gpio_set_amp(rt, (s>>1)&1);
+	ftr_gpio_set_lineout(rt, (s>>2)&1);
+}
+
+static void ftr_handle_notify(void *data)
+{
+	struct gpio_notification *notif = data;
+
+	mutex_lock(&notif->mutex);
+	if (notif->notify)
+		notif->notify(notif->data);
+	mutex_unlock(&notif->mutex);
+}
+
+static void ftr_gpio_init(struct gpio_runtime *rt)
+{
+	get_gpio("headphone-mute", &headphone_mute_gpio,
+				   &headphone_mute_gpio_activestate);
+	get_gpio("amp-mute", &amp_mute_gpio,
+			     &amp_mute_gpio_activestate);
+	get_gpio("lineout-mute", &lineout_mute_gpio,
+				 &lineout_mute_gpio_activestate);
+	get_gpio("hw-reset", &hw_reset_gpio,
+			     &hw_reset_gpio_activestate);
+	get_gpio("headphone-detect", &headphone_detect_gpio,
+				     &headphone_detect_gpio_activestate);
+	get_gpio("lineout-detect", &lineout_detect_gpio,
+				   &lineout_detect_gpio_activestate);
+	get_gpio("linein-detect", &linein_detect_gpio,
+				  &linein_detect_gpio_activestate);
+
+	get_irq("headphone-detect", &headphone_detect_irq);
+	get_irq("lineout-detect", &lineout_detect_irq);
+	get_irq("linein-detect", &linein_detect_irq);
+
+	ftr_gpio_all_amps_off(rt);
+	rt->implementation_private = 0;
+	INIT_WORK(&rt->headphone_notify.work, ftr_handle_notify, &rt->headphone_notify);
+	INIT_WORK(&rt->line_in_notify.work, ftr_handle_notify, &rt->line_in_notify);
+	INIT_WORK(&rt->line_out_notify.work, ftr_handle_notify, &rt->line_out_notify);
+	mutex_init(&rt->headphone_notify.mutex);
+	mutex_init(&rt->line_in_notify.mutex);
+	mutex_init(&rt->line_out_notify.mutex);
+}
+
+static void ftr_gpio_exit(struct gpio_runtime *rt)
+{
+	ftr_gpio_all_amps_off(rt);
+	rt->implementation_private = 0;
+	if (rt->headphone_notify.notify)
+		free_irq(headphone_detect_irq, &rt->headphone_notify);
+	if (rt->line_in_notify.gpio_private)
+		free_irq(linein_detect_irq, &rt->line_in_notify);
+	if (rt->line_out_notify.gpio_private)
+		free_irq(lineout_detect_irq, &rt->line_out_notify);
+	cancel_delayed_work(&rt->headphone_notify.work);
+	cancel_delayed_work(&rt->line_in_notify.work);
+	cancel_delayed_work(&rt->line_out_notify.work);
+	flush_scheduled_work();
+	mutex_destroy(&rt->headphone_notify.mutex);
+	mutex_destroy(&rt->line_in_notify.mutex);
+	mutex_destroy(&rt->line_out_notify.mutex);
+}
+
+irqreturn_t ftr_handle_notify_irq(int xx, void *data, struct pt_regs *regs)
+{
+	struct gpio_notification *notif = data;
+
+	schedule_work(&notif->work);
+
+	return IRQ_HANDLED;
+}
+
+static int ftr_set_notify(struct gpio_runtime *rt,
+			  enum notify_type type,
+			  notify_func_t notify,
+			  void *data)
+{
+	struct gpio_notification *notif;
+	notify_func_t old;
+	int irq;
+	char *name;
+	int err = -EBUSY;
+
+	switch (type) {
+	case AOA_NOTIFY_HEADPHONE:
+		notif = &rt->headphone_notify;
+		name = "headphone-detect";
+		irq = headphone_detect_irq;
+		break;
+	case AOA_NOTIFY_LINE_IN:
+		notif = &rt->line_in_notify;
+		name = "linein-detect";
+		irq = linein_detect_irq;
+		break;
+	case AOA_NOTIFY_LINE_OUT:
+		notif = &rt->line_out_notify;
+		name = "lineout-detect";
+		irq = lineout_detect_irq;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (irq == -1)
+		return -ENODEV;
+
+	mutex_lock(&notif->mutex);
+
+	old = notif->notify;
+
+	if (!old && !notify) {
+		err = 0;
+		goto out_unlock;
+	}
+
+	if (old && notify) {
+		if (old == notify && notif->data == data)
+			err = 0;
+		goto out_unlock;
+	}
+
+	if (old && !notify) {
+		free_irq(irq, notif);
+	}
+	if (!old && notify) {
+		request_irq(irq, ftr_handle_notify_irq, 0, name, notif);
+	}
+	notif->notify = notify;
+	notif->data = data;
+
+	err = 0;
+ out_unlock:
+	mutex_unlock(&notif->mutex);
+	return err;
+}
+
+static int ftr_get_detect(struct gpio_runtime *rt,
+			  enum notify_type type)
+{
+	int gpio, ret, active;
+
+	switch (type) {
+	case AOA_NOTIFY_HEADPHONE:
+		gpio = headphone_detect_gpio;
+		active = headphone_detect_gpio_activestate;
+		break;
+	case AOA_NOTIFY_LINE_IN:
+		gpio = linein_detect_gpio;
+		active = linein_detect_gpio_activestate;
+		break;
+	case AOA_NOTIFY_LINE_OUT:
+		gpio = lineout_detect_gpio;
+		active = lineout_detect_gpio_activestate;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (gpio == -1)
+		return -ENODEV;
+
+	ret = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio, 0);
+	if (ret < 0)
+		return ret;
+	return ((ret >> 1) & 1) == active;
+}
+
+static struct gpio_methods methods = {
+	.init			= ftr_gpio_init,
+	.exit			= ftr_gpio_exit,
+	.all_amps_off		= ftr_gpio_all_amps_off,
+	.all_amps_restore	= ftr_gpio_all_amps_restore,
+	.set_headphone		= ftr_gpio_set_headphone,
+	.set_speakers		= ftr_gpio_set_amp,
+	.set_lineout		= ftr_gpio_set_lineout,
+	.set_hw_reset		= ftr_gpio_set_hw_reset,
+	.get_headphone		= ftr_gpio_get_headphone,
+	.get_speakers		= ftr_gpio_get_amp,
+	.get_lineout		= ftr_gpio_get_lineout,
+	.set_notify		= ftr_set_notify,
+	.get_detect		= ftr_get_detect,
+};
+
+struct gpio_methods *ftr_gpio_methods = &methods;
+EXPORT_SYMBOL_GPL(ftr_gpio_methods);

^ permalink raw reply

* MPC880 cannot use SCC4 together with FECs
From: Antonio Di Bacco @ 2006-06-02  9:21 UTC (permalink / raw)
  To: linuxppc-embedded

This is a question for a Freescale guy or anyone that already used the MPC880.
I'm using an MPC880, both the FECs are used and SMC1, SMC2 and SCC3 are 
currently being used too. Now I need to use the SCC4 as an asynchronous 
serial port (only two pins) but my hardware engineer is saying that is not 
possible because pins are missing. I cannot believe this, they told me that 
RXD4 could use pins: PA11 or PD8 or PE25 but actually PA11 is used by the 
first FEC for MII1-TXD0,
PD8 for MDC and PE25 for second FEC MII2-TXD3.

Is this correct?

Bye,
Antonio.
 

^ permalink raw reply

* USB on MPC8349 with MPH controller
From: almoeli @ 2006-06-02  8:55 UTC (permalink / raw)
  To: linuxppc-embedded

Hi,

im using kernel 2.6.16.18 with the ehci-fsl and a patch from this list
to get USB working.
So SCCR and SICRL register are set correctly.
The external connected PHY is a SMSC 3300-EZK which has an ULPI interface.
If I configure the USB controller of the MPC8349 to use the DR
controller, port 1 can be used with low, full and high speed devices
without any errors.
But if the USB controller is switched to MPH, the port 0 and port 1
cannot read the device descriptor.
Error message is:

fsl-usb2-mph: devpath1 ep0in 3strikes
fsl-usb2-mph: devpath1 ep0in 3strikes
fsl-usb2-mph: devpath1 ep0in 3strikes
usb1-1: device decriptor read/64, error -71

Does anyone know this problem or knows a solution?

Oliver

^ permalink raw reply

* RE: [PATCH/2.6.17-rc4 1/10] Powerpc: Add general support for mpc7 448h pc2 (Taiga) platform
From: Liu Dave-r63238 @ 2006-06-02  8:33 UTC (permalink / raw)
  To: 'Benjamin Herrenschmidt', Zang Roy-r61911
  Cc: linuxppc-dev list, Paul Mackerras, Alexandre.Bounine,
	Yang Xin-Xin-r48390

> > I had hoped to get the pci configure base address by ioremap, but 
> > failed. the tsi108 register locates at 0xc000,0000 
> ~0xC001,0000. It is 
> > OK to access them by ioremap. While pci configure access need to 
> > ioremap 0xfb00,0000 ~0xfc00,0000. I traced my code, when I 
> do ioremap, 
> > there is no bat match, I get the virtual address from 
> ioremap_bot. the 
> > init ioremap_bot is 0xfe000000. When I do tsi108_csr_vir_base = 
> > ioremap(0xfb000000,0x1000000), the ioremap_bot is 
> 0xfdffe000 ( I get 
> > the serial port ioremap steal some space), tsi108_csr_vir_base = 
> > 0xfdfee000, I can not access the configure space with this address.
> 
> What happens if you try ?
> 
> > While if I use bat0 or bat1 to map my tsi108 register space, the 
> > ioremap_bot will keep to 0xfe000000 until I do 
> tsi108_csr_vir_base = 
> > ioremap(0xfb000000,0x1000000) then I get  tsi108_csr_vir_base = 
> > 0xfd000000. Everything is OK.
> 
> Both should work fine
> 
> Ben.
> 

The smallest BAT size of 74xx is 128KB, but the MPC7448_HPC2_NVRAM_SIZE
Is 0x8000 (32KB) you set in your code. I suggest you set the
MPC7448_HPC2_NVRAM_SIZE is 0x20000, try it.

Dave

^ permalink raw reply


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