LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] [POWERPC] Update linker script to properly set physical addresses
From: Kumar Gala @ 2008-04-07 13:00 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <18425.47270.756180.55444@cargo.ozlabs.ibm.com>


On Apr 7, 2008, at 1:01 AM, Paul Mackerras wrote:
> Kumar Gala writes:
>
>> We can set LOAD_OFFSET and use the AT attribute on sections and the
>> linker will properly set the physical address of the LOAD program
>> header for us.
>
> Nice...
>
>> #define KERNELBASE      ASM_CONST(CONFIG_KERNEL_START)
>> #define PAGE_OFFSET	ASM_CONST(CONFIG_PAGE_OFFSET)
>> +#define LOAD_OFFSET	ASM_CONST((CONFIG_KERNEL_START- 
>> CONFIG_PHYSICAL_START))
>
> I think this should be CONFIG_PAGE_OFFSET - CONFIG_PHYSICAL_START
> though.

Disagree (assuming I'm thinking straight first thing in the morning).

PAGE_OFFSET is virt address of the beginning of memory, where  
KERNEL_START is virt address of start of kernel text.
PHYSICAL_START is physical address of KERNEL_START.

(I tried to match x86's definitions here as per Milton's request to be  
consistent).

- k

^ permalink raw reply

* Re: [PATCH 3/4] PowerPC: Add PCI entry to 440EPx Sequoia DTS.
From: Valentine Barshak @ 2008-04-07 13:01 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: linuxppc-dev
In-Reply-To: <47F7A935.3080803@ru.mvista.com>

Sergei Shtylyov wrote:
> Valentine Barshak wrote:
> 
>> This adds PCI entry to PowerPC 440EPx Sequoia DTS.
> 
>> Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>
> 
>> --- linux-2.6.orig/arch/powerpc/boot/dts/sequoia.dts    2007-12-21 
>> 17:14:17.000000000 +0300
>> +++ linux-2.6/arch/powerpc/boot/dts/sequoia.dts    2007-12-21 
>> 17:18:32.000000000 +0300
>> @@ -324,6 +324,33 @@
>>                  has-new-stacr-staopc;
>>              };
>>          };
>> +
>> +        PCI0: pci@1ec000000 {
>> +            device_type = "pci";
>> +            #interrupt-cells = <1>;
>> +            #size-cells = <2>;
>> +            #address-cells = <3>;
>> +            compatible = "ibm,plb440epx-pci", "ibm,plb-pci";
>> +            primary;
>> +            reg = <1 eec00000 8    /* Config space access */
>> +                   1 eed00000 4    /* IACK */
>> +                   1 eed00000 4    /* Special cycle */
>> +                   1 ef400000 40>;    /* Internal registers */
>> +
>> +            /* Outbound ranges, one memory and one IO,
>> +             * later cannot be changed. Chip supports a second
>> +             * IO range but we don't use it for now
>> +             */
>> +            ranges = <02000000 0 80000000 1 80000000 0 10000000
> 
>    I wonder why the AMCC's Sequoia/Rainier manual has PCI memory mapped 
> at 0x80000000-0xbfffffff? The 0x80000000-0x8fffffff mapping was assumed 
> by arch/ppc/ code.  What/why changed here?

The addresses in the manual are relative to bus base. PCI controller is 
located on the PLB and PLB base address is 0x100000000ULL on Sequoia.
Older PPC code has ioremap64 function that did the 64 to 32-bit trick
It's been abolished. The kernel has support for 64-bit physical 
addresses on 32-bit. IMHO there's no big reason to keep doing that 
address trick. However, there are some drivers that use unsigned long 
for storing physical addresses. This is wrong, since 
pci_resource_start() returns a resource_size_t value. I think it's these 
drivers that have to be fixed instead of adding workarounds to ppc4xx code.
Thanks,
Valentine.

>    As we now both know, having PCI memory space mapped beyound 4 GB 
> makes some drivers misbehave as they use 'unsigned long' to store the 
> result of pci_resource_start() and later ioremap() this truncated value 
> -- which is 64-bit on Sequoia due to CONFIG_RESOURCE_64BIT=y that is 
> needed to store the beyond-4GB addresses.
> 
>> +                01000000 0 00000000 1 e8000000 0 00100000>;
>> +
>> +            /* Inbound 2GB range starting at 0 */
>> +            dma-ranges = <42000000 0 0 0 0 0 80000000>;
>> +
>> +            /* All PCI interrupts are routed to IRQ 67 */
>> +            interrupt-map-mask = <0000 0 0 0>;
>> +            interrupt-map = < 0000 0 0 0 &UIC2 3 8 >;
>> +        };
>>      };
> 
> WBR, Sergei

^ permalink raw reply

* Re: [RFC][PATCH] initial port of fixmap over from x86 for ppc32
From: Kumar Gala @ 2008-04-07 13:09 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, hollisb
In-Reply-To: <18425.24938.332852.315571@cargo.ozlabs.ibm.com>


On Apr 6, 2008, at 6:48 PM, Paul Mackerras wrote:
> Kumar Gala writes:
>
>> Wanted to get any feedback on this initial port of the fixmap  
>> support over
>> from x86.  There are a few TODOs:
>
> I have no objection in principle, but your patch below imports a few
> things that aren't (and won't be) needed on powerpc AFAICS -- for
> example, we don't need FIX_VDSO, since our VDSO is mapped into user
> space at the 1MB point (by default).

Agreed.

> You have FIX_PCIE_MCFG in there too (keyed off CONFIG_PCI_MMCONFIG
> which we don't have and don't want to have).  If you need to map in
> PCIe config space, what's wrong with just using ioremap?  Why do you
> need to have a fixed virtual address for it?

Ben has commented on this.  I know on the 83xx systems we have two  
PCIe PHBs that would require ioremapping 512M of virtual address space  
which we don't have if the system has any large amount of memory.

> More generally, I think we need to take an overall look at what things
> we are using fixed virtual addresses for, and why they need to be
> fixed.  If there are indeed several such things then we can introduce
> the fixmap stuff.

The list as I see it:
* kmap
* pci-e config for 4xx/83xx
* kexec/kdump (ben commented on this when Dale posted his patches for  
ppc32 support)

future:
* possible usage by HV

since we already have three users and a possible fourth it seems like  
a useful change.

- k

^ permalink raw reply

* Re: [PATCH v2] powerpc: Add irqtrace support for 32-bit powerpc
From: Johannes Berg @ 2008-04-07 13:10 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev
In-Reply-To: <1207543791.10388.468.camel@pasglop>

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


> Note that I've been wondering wether we should attempt to trace all
> those IRQ state change internally to the exception code. I've looked at
> not doing it, which simplifies things a bit.
> 
> Unfortunately, that will make us occasionally trace redundant
> enable/disable (which isn't a big problem per-se, just counters).

We already have a huge number of redundant enable/disable, about 40% of
all events on both 32 and 64-bit.

johannes

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

^ permalink raw reply

* Re: Kilauea: kernel hangs when using ARCH=powerpc
From: Josh Boyer @ 2008-04-07 13:23 UTC (permalink / raw)
  To: bernhard.weirich; +Cc: linuxppc-dev
In-Reply-To: <1207562631.6678.10.camel@hactar>

On Mon, 2008-04-07 at 12:03 +0200, Bernhard Weirich wrote:
> Hello!
> 
> When I build the kernel for my kilauea board using ARCH=ppc everything
> works fine.
> Since ppc is deprecated I'd like to switch to powerpc, but if I do so
> the kernel does not produce any output.
> There is just the last line of the prompt from the bootloader.
> In both cases I built with kilauea_defconfig
> 
> I tried the Denx ELDK (4.2) compiler 4.2.2, the toolchain generated by
> Buildroot and different kernel versions from the denx repository.
> The Kilauea board is Version 1.11b.
> 
> Any ideas what is going wrong?

You need to be sure to load the device tree blob in U-Boot, and ensure
that your bootargs environment variable contains the proper values for
console.

josh

^ permalink raw reply

* [PATCH 001/003] snd-powermac: enable headphone detection
From: Risto Suominen @ 2008-04-07 13:28 UTC (permalink / raw)
  To: perex; +Cc: LinuxPPC-dev

From: Risto Suominen <Risto.Suominen@gmail.com>

Enable port change interrupt while initialising AWACS, Screamer, and
Burgundy chipsets.

Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
---
Kernel version 2.6.25-rc8 (probably any 2.6)

--- sound/ppc/pmac.c.orig	2008-04-05 17:45:08.000000000 +0300
+++ sound/ppc/pmac.c	2008-04-07 12:18:47.503077312 +0300
@@ -214,7 +214,7 @@ static int snd_pmac_pcm_prepare(struct s
 	int rate_index;
 	long offset;
 	struct pmac_stream *astr;
-	
+
 	rec->dma_size = snd_pcm_lib_buffer_bytes(subs);
 	rec->period_size = snd_pcm_lib_period_bytes(subs);
 	rec->nperiods = rec->dma_size / rec->period_size;
@@ -643,7 +643,7 @@ static int snd_pmac_pcm_close(struct snd
 	/* reset constraints */
 	astr->cur_freqs = chip->freqs_ok;
 	astr->cur_formats = chip->formats_ok;
-	
+
 	return 0;
 }

@@ -1063,6 +1063,10 @@ static int __init snd_pmac_detect(struct
 	else {
 		struct pci_dev *pdev = NULL;

+#ifndef for_each_pci_dev
+#define for_each_pci_dev(d) \
+		while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
+#endif
 		for_each_pci_dev(pdev) {
 			struct device_node *np = pci_device_to_OF_node(pdev);
 			if (np && np == macio->of_node) {
@@ -1300,9 +1304,9 @@ int __init snd_pmac_new(struct snd_card

 	snd_pmac_sound_feature(chip, 1);

-	/* reset */
-	if (chip->model == PMAC_AWACS)
-		out_le32(&chip->awacs->control, 0x11);
+	/* reset & enable interrupts */
+	if (chip->model <= PMAC_BURGUNDY)
+		out_le32(&chip->awacs->control, chip->control_mask);

 	/* Powerbooks have odd ways of enabling inputs such as
 	   an expansion-bay CD or sound from an internal modem

^ permalink raw reply

* [PATCH 002/003] snd-powermac: AWACS and Screamer mixers for PM7500, Beige, and iMac SL
From: Risto Suominen @ 2008-04-07 13:28 UTC (permalink / raw)
  To: perex; +Cc: LinuxPPC-dev

From: Risto Suominen <Risto.Suominen@gmail.com>

Add mixer controls and correct headphone detection bits for PowerMacs
7300/7500 (AWACS) and G3 Beige (Screamer), and iMac G3 Slot-loading
(Screamer).

Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
---
Kernel version 2.6.25-rc8 (probably any 2.6)

--- sound/ppc/awacs.c.orig	2008-04-05 17:45:08.000000000 +0300
+++ sound/ppc/awacs.c	2008-04-07 11:24:08.108621048 +0300
@@ -141,7 +141,7 @@ static int snd_pmac_awacs_info_volume(st
 	uinfo->value.integer.max = 15;
 	return 0;
 }
-
+
 static int snd_pmac_awacs_get_volume(struct snd_kcontrol *kcontrol,
 				     struct snd_ctl_elem_value *ucontrol)
 {
@@ -267,7 +267,8 @@ static int snd_pmac_awacs_put_switch(str
 static void awacs_set_cuda(int reg, int val)
 {
 	struct adb_request req;
-	cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a, reg, val);
+	cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a,
+			reg, val);
 	while (! req.complete)
 		cuda_poll();
 }
@@ -289,11 +290,11 @@ static void awacs_amp_set_tone(struct aw
 /*
  * vol = 0 - 31 (attenuation), 32 = mute bit, stereo
  */
-static int awacs_amp_set_vol(struct awacs_amp *amp, int index, int
lvol, int rvol,
-			     int do_check)
+static int awacs_amp_set_vol(struct awacs_amp *amp, int index,
+			     int lvol, int rvol, int do_check)
 {
 	if (do_check && amp->amp_vol[index][0] == lvol &&
-	    amp->amp_vol[index][1] == rvol)
+			amp->amp_vol[index][1] == rvol)
 		return 0;
 	awacs_set_cuda(3 + index, lvol);
 	awacs_set_cuda(5 + index, rvol);
@@ -337,7 +338,7 @@ static int snd_pmac_awacs_info_volume_am
 	uinfo->value.integer.max = 31;
 	return 0;
 }
-
+
 static int snd_pmac_awacs_get_volume_amp(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol)
 {
@@ -361,8 +362,10 @@ static int snd_pmac_awacs_put_volume_amp
 	snd_assert(amp, return -EINVAL);
 	snd_assert(index >= 0 && index <= 1, return -EINVAL);

-	vol[0] = (31 - (ucontrol->value.integer.value[0] & 31)) |
(amp->amp_vol[index][0] & 32);
-	vol[1] = (31 - (ucontrol->value.integer.value[1] & 31)) |
(amp->amp_vol[index][1] & 32);
+	vol[0] = (31 - (ucontrol->value.integer.value[0] & 31))
+		| (amp->amp_vol[index][0] & 32);
+	vol[1] = (31 - (ucontrol->value.integer.value[1] & 31))
+		| (amp->amp_vol[index][1] & 32);
 	return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
 }

@@ -374,8 +377,10 @@ static int snd_pmac_awacs_get_switch_amp
 	struct awacs_amp *amp = chip->mixer_data;
 	snd_assert(amp, return -EINVAL);
 	snd_assert(index >= 0 && index <= 1, return -EINVAL);
-	ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32) ? 0 : 1;
-	ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32) ? 0 : 1;
+	ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32)
+					? 0 : 1;
+	ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32)
+					? 0 : 1;
 	return 0;
 }

@@ -389,8 +394,10 @@ static int snd_pmac_awacs_put_switch_amp
 	snd_assert(amp, return -EINVAL);
 	snd_assert(index >= 0 && index <= 1, return -EINVAL);

-	vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32) |
(amp->amp_vol[index][0] & 31);
-	vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32) |
(amp->amp_vol[index][1] & 31);
+	vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32)
+		| (amp->amp_vol[index][0] & 31);
+	vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32)
+		| (amp->amp_vol[index][1] & 31);
 	return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
 }

@@ -403,7 +410,7 @@ static int snd_pmac_awacs_info_tone_amp(
 	uinfo->value.integer.max = 14;
 	return 0;
 }
-
+
 static int snd_pmac_awacs_get_tone_amp(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_value *ucontrol)
 {
@@ -445,7 +452,7 @@ static int snd_pmac_awacs_info_master_am
 	uinfo->value.integer.max = 99;
 	return 0;
 }
-
+
 static int snd_pmac_awacs_get_master_amp(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol)
 {
@@ -493,14 +500,14 @@ static struct snd_kcontrol_new snd_pmac_
 	  .private_value = AMP_CH_HD,
 	},
 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	  .name = "Tone Control - Bass",
+	  .name = "Tone Control - Bass Playback Volume",
 	  .info = snd_pmac_awacs_info_tone_amp,
 	  .get = snd_pmac_awacs_get_tone_amp,
 	  .put = snd_pmac_awacs_put_tone_amp,
 	  .private_value = 0,
 	},
 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	  .name = "Tone Control - Treble",
+	  .name = "Tone Control - Treble Playback Volume",
 	  .info = snd_pmac_awacs_info_tone_amp,
 	  .get = snd_pmac_awacs_get_tone_amp,
 	  .put = snd_pmac_awacs_put_tone_amp,
@@ -544,7 +551,7 @@ static int snd_pmac_screamer_mic_boost_i
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = 1;
 	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 2;
+	uinfo->value.integer.max = 3;
 	return 0;
 }

@@ -552,16 +559,14 @@ static int snd_pmac_screamer_mic_boost_g
 					   struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	int val;
+	int val = 0;
 	unsigned long flags;

 	spin_lock_irqsave(&chip->reg_lock, flags);
 	if (chip->awacs_reg[6] & MASK_MIC_BOOST)
-		val = 2;
-	else if (chip->awacs_reg[0] & MASK_GAINLINE)
-		val = 1;
-	else
-		val = 0;
+		val |= 2;
+	if (chip->awacs_reg[0] & MASK_GAINLINE)
+		val |= 1;
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
 	ucontrol->value.integer.value[0] = val;
 	return 0;
@@ -578,11 +583,10 @@ static int snd_pmac_screamer_mic_boost_p
 	spin_lock_irqsave(&chip->reg_lock, flags);
 	val0 = chip->awacs_reg[0] & ~MASK_GAINLINE;
 	val6 = chip->awacs_reg[6] & ~MASK_MIC_BOOST;
-	if (ucontrol->value.integer.value[0] > 0) {
+	if (ucontrol->value.integer.value[0] & 1)
 		val0 |= MASK_GAINLINE;
-		if (ucontrol->value.integer.value[0] > 1)
-			val6 |= MASK_MIC_BOOST;
-	}
+	if (ucontrol->value.integer.value[0] & 2)
+		val6 |= MASK_MIC_BOOST;
 	if (val0 != chip->awacs_reg[0]) {
 		snd_pmac_awacs_write_reg(chip, 0, val0);
 		changed = 1;
@@ -599,9 +603,32 @@ static int snd_pmac_screamer_mic_boost_p
  * lists of mixer elements
  */
 static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __initdata = {
-	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
 	AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
-	AWACS_VOLUME("Capture Volume", 0, 4, 0),
+	AWACS_VOLUME("Master Capture Volume", 0, 4, 0),
+/*	AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __initdata = {
+	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
+	AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
+	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = {
+	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
+	AWACS_VOLUME("Master Playback Volume", 5, 6, 1),
+	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __initdata = {
+	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
+	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __initdata = {
+	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
 	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
 };

@@ -621,35 +648,61 @@ static struct snd_kcontrol_new snd_pmac_
 static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata =
 AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);

+static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __initdata =
+AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1);
+
 static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = {
-	AWACS_SWITCH("Mic Boost", 0, SHIFT_GAINLINE, 0),
+	AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
 };

 static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __initdata = {
 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	  .name = "Mic Boost",
+	  .name = "Mic Boost Capture Volume",
 	  .info = snd_pmac_screamer_mic_boost_info,
 	  .get = snd_pmac_screamer_mic_boost_get,
 	  .put = snd_pmac_screamer_mic_boost_put,
 	},
 };

+static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] __initdata =
+{
+	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] __initdata =
+{
+	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+	AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] __initdata =
+{
+	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+	AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
+};
+
 static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __initdata = {
 	AWACS_VOLUME("PC Speaker Playback Volume", 4, 6, 1),
 };
+
 static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __initdata =
 AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);

+static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac __initdata =
+AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
+

 /*
  * add new mixer elements to the card
  */
-static int build_mixers(struct snd_pmac *chip, int nums, struct
snd_kcontrol_new *mixers)
+static int build_mixers(struct snd_pmac *chip, int nums,
+			struct snd_kcontrol_new *mixers)
 {
 	int i, err;

 	for (i = 0; i < nums; i++) {
-		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip))) < 0)
+		if ((err = snd_ctl_add(chip->card,
+				       snd_ctl_new1(&mixers[i], chip))) < 0)
 			return err;
 	}
 	return 0;
@@ -699,8 +752,10 @@ static void snd_pmac_awacs_resume(struct
 #ifdef PMAC_AMP_AVAIL
 	if (chip->mixer_data) {
 		struct awacs_amp *amp = chip->mixer_data;
-		awacs_amp_set_vol(amp, 0, amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
-		awacs_amp_set_vol(amp, 1, amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
+		awacs_amp_set_vol(amp, 0,
+				  amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
+		awacs_amp_set_vol(amp, 1,
+				  amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
 		awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);
 		awacs_amp_set_master(amp, amp->amp_master);
 	}
@@ -708,6 +763,14 @@ static void snd_pmac_awacs_resume(struct
 }
 #endif /* CONFIG_PM */

+#define IS_PM7500 (machine_is_compatible("AAPL,7500"))
+#define IS_BEIGE (machine_is_compatible("AAPL,Gossamer"))
+#define IS_IMAC (machine_is_compatible("PowerMac2,1") \
+		|| machine_is_compatible("PowerMac2,2") \
+		|| machine_is_compatible("PowerMac4,1"))
+
+static int imac;
+
 #ifdef PMAC_SUPPORT_AUTOMUTE
 /*
  * auto-mute stuffs
@@ -750,9 +813,16 @@ static void snd_pmac_awacs_update_automu
 		} else
 #endif
 		{
-			int reg = chip->awacs_reg[1] | (MASK_HDMUTE|MASK_SPKMUTE);
+			int reg = chip->awacs_reg[1]
+				| (MASK_HDMUTE | MASK_SPKMUTE);
+			if (imac) {
+				reg &= ~MASK_SPKMUTE;
+				reg &= ~MASK_PAROUT1;
+			}
 			if (snd_pmac_awacs_detect_headphone(chip))
 				reg &= ~MASK_HDMUTE;
+			else if (imac)
+				reg |= MASK_PAROUT1;
 			else
 				reg &= ~MASK_SPKMUTE;
 			if (do_notify && reg == chip->awacs_reg[1])
@@ -778,8 +848,11 @@ static void snd_pmac_awacs_update_automu
 int __init
 snd_pmac_awacs_init(struct snd_pmac *chip)
 {
+	int pm7500 = IS_PM7500;
+	int beige = IS_BEIGE;
 	int err, vol;

+	imac = IS_IMAC;
 	/* looks like MASK_GAINLINE triggers something, so we set here
 	 * as start-up
 	 */
@@ -787,7 +860,7 @@ snd_pmac_awacs_init(struct snd_pmac *chi
 	chip->awacs_reg[1] = MASK_CMUTE | MASK_AMUTE;
 	/* FIXME: Only machines with external SRS module need MASK_PAROUT */
 	if (chip->has_iic || chip->device_id == 0x5 ||
-	    /*chip->_device_id == 0x8 || */
+	    /* chip->_device_id == 0x8 || */
 	    chip->device_id == 0xb)
 		chip->awacs_reg[1] |= MASK_PAROUT;
 	/* get default volume from nvram */
@@ -798,8 +871,10 @@ snd_pmac_awacs_init(struct snd_pmac *chi
 	chip->awacs_reg[2] = vol;
 	chip->awacs_reg[4] = vol;
 	if (chip->model == PMAC_SCREAMER) {
-		chip->awacs_reg[5] = vol; /* FIXME: screamer has loopthru vol control */
-		chip->awacs_reg[6] = MASK_MIC_BOOST; /* FIXME: maybe should be vol
<< 3 for PCMCIA speaker */
+		/* FIXME: screamer has loopthru vol control */
+		chip->awacs_reg[5] = vol;
+		/* FIXME: maybe should be vol << 3 for PCMCIA speaker */
+		chip->awacs_reg[6] = MASK_MIC_BOOST;
 		chip->awacs_reg[7] = 0;
 	}

@@ -815,7 +890,8 @@ snd_pmac_awacs_init(struct snd_pmac *chi
 			return -ENOMEM;
 		chip->mixer_data = amp;
 		chip->mixer_free = awacs_amp_free;
-		awacs_amp_set_vol(amp, 0, 63, 63, 0); /* mute and zero vol */
+		/* mute and zero vol */
+		awacs_amp_set_vol(amp, 0, 63, 63, 0);
 		awacs_amp_set_vol(amp, 1, 63, 63, 0);
 		awacs_amp_set_tone(amp, 7, 7); /* 0 dB */
 		awacs_amp_set_master(amp, 79); /* 0 dB */
@@ -826,20 +902,25 @@ snd_pmac_awacs_init(struct snd_pmac *chi
 		/* set headphone-jack detection bit */
 		switch (chip->model) {
 		case PMAC_AWACS:
-			chip->hp_stat_mask = 0x04;
+			chip->hp_stat_mask = pm7500 ? MASK_HDPCONN
+				: MASK_LOCONN;
 			break;
 		case PMAC_SCREAMER:
 			switch (chip->device_id) {
 			case 0x08:
-				/* 1 = side jack, 2 = front jack */
-				chip->hp_stat_mask = 0x03;
+			case 0x0B:
+				chip->hp_stat_mask = imac
+					? MASK_LOCONN_IMAC |
+					MASK_HDPLCONN_IMAC |
+					MASK_HDPRCONN_IMAC
+					: MASK_HDPCONN;
 				break;
 			case 0x00:
 			case 0x05:
-				chip->hp_stat_mask = 0x04;
+				chip->hp_stat_mask = MASK_LOCONN;
 				break;
 			default:
-				chip->hp_stat_mask = 0x08;
+				chip->hp_stat_mask = MASK_HDPCONN;
 				break;
 			}
 			break;
@@ -857,15 +938,37 @@ snd_pmac_awacs_init(struct snd_pmac *chi
 	if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
 				snd_pmac_awacs_mixers)) < 0)
 		return err;
-	if (chip->model == PMAC_SCREAMER)
+	if (beige)
+		;
+	else if (chip->model == PMAC_SCREAMER)
 		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2),
 				   snd_pmac_screamer_mixers2);
-	else
+	else if (!pm7500)
 		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2),
 				   snd_pmac_awacs_mixers2);
 	if (err < 0)
 		return err;
-	chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_master_sw, chip);
+	if (pm7500)
+		err = build_mixers(chip,
+				   ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500),
+				   snd_pmac_awacs_mixers_pmac7500);
+	else if (beige)
+		err = build_mixers(chip,
+				   ARRAY_SIZE(snd_pmac_screamer_mixers_beige),
+				   snd_pmac_screamer_mixers_beige);
+	else if (imac)
+		err = build_mixers(chip,
+				   ARRAY_SIZE(snd_pmac_screamer_mixers_imac),
+				   snd_pmac_screamer_mixers_imac);
+	else
+		err = build_mixers(chip,
+				   ARRAY_SIZE(snd_pmac_awacs_mixers_pmac),
+				   snd_pmac_awacs_mixers_pmac);
+	if (err < 0)
+		return err;
+	chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac)
+			? &snd_pmac_awacs_master_sw_imac
+			: &snd_pmac_awacs_master_sw, chip);
 	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
 		return err;
 #ifdef PMAC_AMP_AVAIL
@@ -876,35 +979,58 @@ snd_pmac_awacs_init(struct snd_pmac *chi
 		 * screamer registers.
 		 * in this case, it seems the route C is not used.
 		 */
-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
+		if ((err = build_mixers(chip,
+					ARRAY_SIZE(snd_pmac_awacs_amp_vol),
 					snd_pmac_awacs_amp_vol)) < 0)
 			return err;
 		/* overwrite */
-		chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw, chip);
+		chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw,
+						   chip);
 		if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
 			return err;
-		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw, chip);
+		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw,
+						    chip);
 		if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
 			return err;
 	} else
 #endif /* PMAC_AMP_AVAIL */
 	{
 		/* route A = headphone, route C = speaker */
-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
+		if ((err = build_mixers(chip,
+					ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
 					snd_pmac_awacs_speaker_vol)) < 0)
 			return err;
-		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_speaker_sw, chip);
+		chip->speaker_sw_ctl = snd_ctl_new1(imac
+				? &snd_pmac_awacs_speaker_sw_imac
+				: &snd_pmac_awacs_speaker_sw, chip);
 		if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
 			return err;
 	}

-	if (chip->model == PMAC_SCREAMER) {
-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mic_boost),
-					snd_pmac_screamer_mic_boost)) < 0)
+	if (beige) {
+		if ((err = build_mixers(chip,
+				ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige),
+				snd_pmac_screamer_mic_boost_beige)) < 0)
+			return err;
+	} else if (imac) {
+		if ((err = build_mixers(chip,
+				ARRAY_SIZE(snd_pmac_screamer_mic_boost_imac),
+				snd_pmac_screamer_mic_boost_imac)) < 0)
+			return err;
+	} else if (chip->model == PMAC_SCREAMER) {
+		if ((err = build_mixers(chip,
+				ARRAY_SIZE(snd_pmac_screamer_mic_boost),
+				snd_pmac_screamer_mic_boost)) < 0)
+			return err;
+	} else if (pm7500) {
+		if ((err = build_mixers(chip,
+				ARRAY_SIZE(snd_pmac_awacs_mic_boost_pmac7500),
+				snd_pmac_awacs_mic_boost_pmac7500)) < 0)
 			return err;
 	} else {
-		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
-					snd_pmac_awacs_mic_boost)) < 0)
+		if ((err = build_mixers(chip,
+				ARRAY_SIZE(snd_pmac_awacs_mic_boost),
+				snd_pmac_awacs_mic_boost)) < 0)
 			return err;
 	}

--- sound/ppc/awacs.h.orig	2008-04-05 17:45:08.000000000 +0300
+++ sound/ppc/awacs.h	2008-04-07 11:26:58.198763416 +0300
@@ -116,6 +116,11 @@ struct awacs_regs {
 #define MASK_HDMUTE	MASK_AMUTE
 #define SHIFT_HDMUTE	9
 #define MASK_PAROUT	(0x3 << 10)	/* Parallel Out (???) */
+#define MASK_PAROUT0	(0x1 << 10)	/* Parallel Out (???) */
+#define MASK_PAROUT1	(0x1 << 11)	/* Parallel Out (enable speaker) */
+#define SHIFT_PAROUT	10
+#define SHIFT_PAROUT0	10
+#define SHIFT_PAROUT1	11

 #define SAMPLERATE_48000	(0x0 << 3)	/* 48 or 44.1 kHz */
 #define SAMPLERATE_32000	(0x1 << 3)	/* 32 or 29.4 kHz */
@@ -152,8 +157,15 @@ struct awacs_regs {
 #define MASK_REVISION	(0xf << 12)	/* Revision Number */
 #define MASK_MFGID	(0xf << 8)	/* Mfg. ID */
 #define MASK_CODSTATRES	(0xf << 4)	/* bits 4 - 7 reserved */
-#define MASK_INPPORT	(0xf)		/* Input Port */
-#define MASK_HDPCONN	8		/* headphone plugged in */
+#define MASK_INSENSE	(0xf)		/* port sense bits: */
+#define MASK_HDPCONN		8	/* headphone plugged in */
+#define MASK_LOCONN		4	/* line-out plugged in */
+#define MASK_LICONN		2	/* line-in plugged in */
+#define MASK_MICCONN		1	/* microphone plugged in */
+#define MASK_LICONN_IMAC	8	/* line-in plugged in */
+#define MASK_HDPRCONN_IMAC	4	/* headphone right plugged in */
+#define MASK_HDPLCONN_IMAC	2	/* headphone left plugged in */
+#define MASK_LOCONN_IMAC	1	/* line-out plugged in */

 /* Clipping Count Reg Bit Masks */
 /* -------- ----- --- --- ----- */
@@ -163,7 +175,8 @@ struct awacs_regs {
 /* DBDMA ChannelStatus Bit Masks */
 /* ----- ------------- --- ----- */
 #define MASK_CSERR	(0x1 << 7)	/* Error */
-#define MASK_EOI	(0x1 << 6)	/* End of Input -- only for Input Channel */
+#define MASK_EOI	(0x1 << 6)	/* End of Input --
+					   only for Input Channel */
 #define MASK_CSUNUSED	(0x1f << 1)	/* bits 1-5 not used */
 #define MASK_WAIT	(0x1)		/* Wait */

^ permalink raw reply

* [PATCH 003/003] snd-powermac: Burgundy mixers for B&W and iMac
From: Risto Suominen @ 2008-04-07 13:29 UTC (permalink / raw)
  To: perex; +Cc: LinuxPPC-dev

From: Risto Suominen <Risto.Suominen@gmail.com>

Add mixer controls and correct headphone detection bits for PowerMac
G3 B&W and iMac G3 Tray-loading, both having Burgundy chipset.

Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
---
Kernel version 2.6.25-rc8 (probably any 2.6)

--- sound/ppc/burgundy.c.orig	2008-04-05 17:45:08.000000000 +0300
+++ sound/ppc/burgundy.c	2008-04-07 12:00:20.893307568 +0300
@@ -102,7 +102,8 @@ snd_pmac_burgundy_rcw(struct snd_pmac *c
 }

 static void
-snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr,
unsigned int val)
+snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr,
+		      unsigned int val)
 {
 	out_le32(&chip->awacs->codec_ctrl, addr + 0x300000 + (val & 0xff));
 	snd_pmac_burgundy_busy_wait(chip);
@@ -126,8 +127,11 @@ snd_pmac_burgundy_rcb(struct snd_pmac *c
 	return val;
 }

+#define BASE2ADDR(base)	((base) << 12)
+#define ADDR2BASE(addr)	((addr) >> 12)
+
 /*
- * Burgundy volume: 0 - 100, stereo
+ * Burgundy volume: 0 - 100, stereo, word reg
  */
 static void
 snd_pmac_burgundy_write_volume(struct snd_pmac *chip, unsigned int address,
@@ -168,13 +172,6 @@ snd_pmac_burgundy_read_volume(struct snd
 		volume[1] = 0;
 }

-
-/*
- */
-
-#define BASE2ADDR(base)	((base) << 12)
-#define ADDR2BASE(addr)	((addr) >> 12)
-
 static int snd_pmac_burgundy_info_volume(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_info *uinfo)
 {
@@ -191,8 +188,8 @@ static int snd_pmac_burgundy_get_volume(
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
 	int shift = (kcontrol->private_value >> 8) & 0xff;
-	snd_pmac_burgundy_read_volume(chip, addr, ucontrol->value.integer.value,
-				      shift);
+	snd_pmac_burgundy_read_volume(chip, addr,
+				      ucontrol->value.integer.value, shift);
 	return 0;
 }

@@ -204,24 +201,163 @@ static int snd_pmac_burgundy_put_volume(
 	int shift = (kcontrol->private_value >> 8) & 0xff;
 	long nvoices[2];

-	snd_pmac_burgundy_write_volume(chip, addr, ucontrol->value.integer.value,
-				       shift);
+	snd_pmac_burgundy_write_volume(chip, addr,
+				       ucontrol->value.integer.value, shift);
 	snd_pmac_burgundy_read_volume(chip, addr, nvoices, shift);
 	return (nvoices[0] != ucontrol->value.integer.value[0] ||
 		nvoices[1] != ucontrol->value.integer.value[1]);
 }

-#define BURGUNDY_VOLUME(xname, xindex, addr, shift) \
+#define BURGUNDY_VOLUME_W(xname, xindex, addr, shift) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
   .info = snd_pmac_burgundy_info_volume,\
   .get = snd_pmac_burgundy_get_volume,\
   .put = snd_pmac_burgundy_put_volume,\
   .private_value = ((ADDR2BASE(addr) & 0xff) | ((shift) << 8)) }

-/* lineout/speaker */
+/*
+ * Burgundy volume: 0 - 100, stereo, 2-byte reg
+ */
+static void
+snd_pmac_burgundy_write_volume_2b(struct snd_pmac *chip, unsigned int address,
+				  long *volume, int off)
+{
+	int lvolume, rvolume;
+
+	off |= off << 2;
+	lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0;
+	rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0;
+
+	snd_pmac_burgundy_wcb(chip, address + off, lvolume);
+	snd_pmac_burgundy_wcb(chip, address + off + 0x500, rvolume);
+}
+
+static void
+snd_pmac_burgundy_read_volume_2b(struct snd_pmac *chip, unsigned int address,
+				 long *volume, int off)
+{
+	volume[0] = snd_pmac_burgundy_rcb(chip, address + off);
+	if (volume[0] >= BURGUNDY_VOLUME_OFFSET)
+		volume[0] -= BURGUNDY_VOLUME_OFFSET;
+	else
+		volume[0] = 0;
+	volume[1] = snd_pmac_burgundy_rcb(chip, address + off + 0x100);
+	if (volume[1] >= BURGUNDY_VOLUME_OFFSET)
+		volume[1] -= BURGUNDY_VOLUME_OFFSET;
+	else
+		volume[1] = 0;
+}
+
+static int snd_pmac_burgundy_info_volume_2b(struct snd_kcontrol *kcontrol,
+					    struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 100;
+	return 0;
+}
+
+static int snd_pmac_burgundy_get_volume_2b(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	int off = kcontrol->private_value & 0x300;
+	snd_pmac_burgundy_read_volume_2b(chip, addr,
+			ucontrol->value.integer.value, off);
+	return 0;
+}
+
+static int snd_pmac_burgundy_put_volume_2b(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	int off = kcontrol->private_value & 0x300;
+	long nvoices[2];
+
+	snd_pmac_burgundy_write_volume_2b(chip, addr,
+			ucontrol->value.integer.value, off);
+	snd_pmac_burgundy_read_volume_2b(chip, addr, nvoices, off);
+	return (nvoices[0] != ucontrol->value.integer.value[0] ||
+		nvoices[1] != ucontrol->value.integer.value[1]);
+}
+
+#define BURGUNDY_VOLUME_2B(xname, xindex, addr, off) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
+  .info = snd_pmac_burgundy_info_volume_2b,\
+  .get = snd_pmac_burgundy_get_volume_2b,\
+  .put = snd_pmac_burgundy_put_volume_2b,\
+  .private_value = ((ADDR2BASE(addr) & 0xff) | ((off) << 8)) }
+
+/*
+ * Burgundy gain/attenuation: 0 - 15, mono/stereo, byte reg
+ */
+static int snd_pmac_burgundy_info_gain(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_info *uinfo)
+{
+	int stereo = (kcontrol->private_value >> 24) & 1;
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = stereo + 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 15;
+	return 0;
+}
+
+static int snd_pmac_burgundy_get_gain(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	int stereo = (kcontrol->private_value >> 24) & 1;
+	int atten = (kcontrol->private_value >> 25) & 1;
+	int oval;
+
+	oval = snd_pmac_burgundy_rcb(chip, addr);
+	if (atten)
+		oval = ~oval & 0xff;
+	ucontrol->value.integer.value[0] = oval & 0xf;
+	if (stereo)
+		ucontrol->value.integer.value[1] = (oval >> 4) & 0xf;
+	return 0;
+}

-static int snd_pmac_burgundy_info_switch_out(struct snd_kcontrol *kcontrol,
-					     struct snd_ctl_elem_info *uinfo)
+static int snd_pmac_burgundy_put_gain(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	int stereo = (kcontrol->private_value >> 24) & 1;
+	int atten = (kcontrol->private_value >> 25) & 1;
+	int oval, val;
+
+	oval = snd_pmac_burgundy_rcb(chip, addr);
+	if (atten)
+		oval = ~oval & 0xff;
+	val = ucontrol->value.integer.value[0];
+	if (stereo)
+		val |= ucontrol->value.integer.value[1] << 4;
+	else
+		val |= ucontrol->value.integer.value[0] << 4;
+	if (atten)
+		val = ~val & 0xff;
+	snd_pmac_burgundy_wcb(chip, addr, val);
+	return val != oval;
+}
+
+#define BURGUNDY_VOLUME_B(xname, xindex, addr, stereo, atten) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
+  .info = snd_pmac_burgundy_info_gain,\
+  .get = snd_pmac_burgundy_get_gain,\
+  .put = snd_pmac_burgundy_put_gain,\
+  .private_value = (ADDR2BASE(addr) | ((stereo) << 24) | ((atten) << 25)) }
+
+/*
+ * Burgundy switch: 0/1, mono/stereo, word reg
+ */
+static int snd_pmac_burgundy_info_switch_w(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_info *uinfo)
 {
 	int stereo = (kcontrol->private_value >> 24) & 1;
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
@@ -231,111 +367,207 @@ static int snd_pmac_burgundy_info_switch
 	return 0;
 }

-static int snd_pmac_burgundy_get_switch_out(struct snd_kcontrol *kcontrol,
-					    struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_get_switch_w(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	int lmask = kcontrol->private_value & 0xff;
-	int rmask = (kcontrol->private_value >> 8) & 0xff;
+	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+	int lmask = 1 << (kcontrol->private_value & 0xff);
+	int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff);
 	int stereo = (kcontrol->private_value >> 24) & 1;
-	int val = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
+	int val = snd_pmac_burgundy_rcw(chip, addr);
 	ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
 	if (stereo)
 		ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
 	return 0;
 }

-static int snd_pmac_burgundy_put_switch_out(struct snd_kcontrol *kcontrol,
-					    struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_put_switch_w(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	int lmask = kcontrol->private_value & 0xff;
-	int rmask = (kcontrol->private_value >> 8) & 0xff;
+	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+	int lmask = 1 << (kcontrol->private_value & 0xff);
+	int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff);
 	int stereo = (kcontrol->private_value >> 24) & 1;
 	int val, oval;
-	oval = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
-	val = oval & ~(lmask | rmask);
+	oval = snd_pmac_burgundy_rcw(chip, addr);
+	val = oval & ~(lmask | (stereo ? rmask : 0));
 	if (ucontrol->value.integer.value[0])
 		val |= lmask;
 	if (stereo && ucontrol->value.integer.value[1])
 		val |= rmask;
-	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, val);
+	snd_pmac_burgundy_wcw(chip, addr, val);
 	return val != oval;
 }

-#define BURGUNDY_OUTPUT_SWITCH(xname, xindex, lmask, rmask, stereo) \
+#define BURGUNDY_SWITCH_W(xname, xindex, addr, lbit, rbit, stereo) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
-  .info = snd_pmac_burgundy_info_switch_out,\
-  .get = snd_pmac_burgundy_get_switch_out,\
-  .put = snd_pmac_burgundy_put_switch_out,\
-  .private_value = ((lmask) | ((rmask) << 8) | ((stereo) << 24)) }
-
-/* line/speaker output volume */
-static int snd_pmac_burgundy_info_volume_out(struct snd_kcontrol *kcontrol,
-					     struct snd_ctl_elem_info *uinfo)
+  .info = snd_pmac_burgundy_info_switch_w,\
+  .get = snd_pmac_burgundy_get_switch_w,\
+  .put = snd_pmac_burgundy_put_switch_w,\
+  .private_value = ((lbit) | ((rbit) << 8)\
+		| (ADDR2BASE(addr) << 16) | ((stereo) << 24)) }
+
+/*
+ * Burgundy switch: 0/1, mono/stereo, byte reg, bit mask
+ */
+static int snd_pmac_burgundy_info_switch_b(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_info *uinfo)
 {
 	int stereo = (kcontrol->private_value >> 24) & 1;
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 	uinfo->count = stereo + 1;
 	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 15;
+	uinfo->value.integer.max = 1;
 	return 0;
 }

-static int snd_pmac_burgundy_get_volume_out(struct snd_kcontrol *kcontrol,
-					    struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_get_switch_b(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+	int lmask = kcontrol->private_value & 0xff;
+	int rmask = (kcontrol->private_value >> 8) & 0xff;
 	int stereo = (kcontrol->private_value >> 24) & 1;
-	int oval;
-
-	oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
-	ucontrol->value.integer.value[0] = oval & 0xf;
+	int val = snd_pmac_burgundy_rcb(chip, addr);
+	ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
 	if (stereo)
-		ucontrol->value.integer.value[1] = (oval >> 4) & 0xf;
+		ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
 	return 0;
 }

-static int snd_pmac_burgundy_put_volume_out(struct snd_kcontrol *kcontrol,
-					    struct snd_ctl_elem_value *ucontrol)
+static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+	unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
+	int lmask = kcontrol->private_value & 0xff;
+	int rmask = (kcontrol->private_value >> 8) & 0xff;
 	int stereo = (kcontrol->private_value >> 24) & 1;
-	unsigned int oval, val;
-
-	oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
-	val = ucontrol->value.integer.value[0] & 15;
-	if (stereo)
-		val |= (ucontrol->value.integer.value[1] & 15) << 4;
-	else
-		val |= val << 4;
-	val = ~val & 0xff;
+	int val, oval;
+	oval = snd_pmac_burgundy_rcb(chip, addr);
+	val = oval & ~(lmask | rmask);
+	if (ucontrol->value.integer.value[0])
+		val |= lmask;
+	if (stereo && ucontrol->value.integer.value[1])
+		val |= rmask;
 	snd_pmac_burgundy_wcb(chip, addr, val);
 	return val != oval;
 }

-#define BURGUNDY_OUTPUT_VOLUME(xname, xindex, addr, stereo) \
+#define BURGUNDY_SWITCH_B(xname, xindex, addr, lmask, rmask, stereo) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
-  .info = snd_pmac_burgundy_info_volume_out,\
-  .get = snd_pmac_burgundy_get_volume_out,\
-  .put = snd_pmac_burgundy_put_volume_out,\
-  .private_value = (ADDR2BASE(addr) | ((stereo) << 24)) }
+  .info = snd_pmac_burgundy_info_switch_b,\
+  .get = snd_pmac_burgundy_get_switch_b,\
+  .put = snd_pmac_burgundy_put_switch_b,\
+  .private_value = ((lmask) | ((rmask) << 8)\
+		| (ADDR2BASE(addr) << 16) | ((stereo) << 24)) }

+/*
+ * Burgundy mixers
+ */
 static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __initdata = {
-	BURGUNDY_VOLUME("Master Playback Volume", 0,
MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
-	BURGUNDY_VOLUME("Line Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLLINE, 16),
-	BURGUNDY_VOLUME("CD Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLCD, 16),
-	BURGUNDY_VOLUME("Mic Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLMIC, 16),
-	BURGUNDY_OUTPUT_VOLUME("PC Speaker Playback Volume", 0,
MASK_ADDR_BURGUNDY_ATTENHP, 0),
-	/*BURGUNDY_OUTPUT_VOLUME("PCM Playback Volume", 0,
MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1),*/
-	BURGUNDY_OUTPUT_VOLUME("Headphone Playback Volume", 0,
MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1),
-};	
-static struct snd_kcontrol_new snd_pmac_burgundy_master_sw __initdata =
-BURGUNDY_OUTPUT_SWITCH("Headphone Playback Switch", 0,
BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw __initdata =
-BURGUNDY_OUTPUT_SWITCH("PC Speaker Playback Switch", 0,
BURGUNDY_OUTPUT_INTERN, 0, 0);
+	BURGUNDY_VOLUME_W("Master Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
+	BURGUNDY_VOLUME_W("CD Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLCD, 16),
+	BURGUNDY_VOLUME_2B("Input Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLMIX01, 2),
+	BURGUNDY_VOLUME_2B("Mixer Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLMIX23, 0),
+	BURGUNDY_VOLUME_B("CD Gain Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_GAINCD, 1, 0),
+	BURGUNDY_SWITCH_W("Master Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTENABLES, 24, 0, 0),
+	BURGUNDY_SWITCH_W("CD Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 0, 16, 1),
+	BURGUNDY_SWITCH_W("CD Playback Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 0, 16, 1),
+/*	BURGUNDY_SWITCH_W("Loop Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_CAPTURESELECTS, 8, 24, 1),
+ *	BURGUNDY_SWITCH_B("Mixer out Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_HOSTIFAD, 0x02, 0, 0),
+ *	BURGUNDY_SWITCH_B("Mixer Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_HOSTIFAD, 0x01, 0, 0),
+ *	BURGUNDY_SWITCH_B("PCM out Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_HOSTIFEH, 0x02, 0, 0),
+ */	BURGUNDY_SWITCH_B("PCM Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0)
+};
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __initdata = {
+	BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLLINE, 16),
+	BURGUNDY_VOLUME_W("Mic Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLMIC, 16),
+	BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_GAINLINE, 1, 0),
+	BURGUNDY_VOLUME_B("Mic Gain Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
+	BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
+	BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1, 1),
+	BURGUNDY_VOLUME_B("Headphone Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENHP, 1, 1),
+	BURGUNDY_SWITCH_W("Line in Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 1, 17, 1),
+	BURGUNDY_SWITCH_W("Mic Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1),
+	BURGUNDY_SWITCH_W("Line in Playback Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 1, 17, 1),
+	BURGUNDY_SWITCH_W("Mic Playback Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1),
+	BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1)
+};
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __initdata = {
+	BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_VOLMIC, 16),
+	BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
+			MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
+	BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENMONO, 0, 1),
+	BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
+			MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
+	BURGUNDY_SWITCH_W("Line in Capture Switch", 0,
+			MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1),
+	BURGUNDY_SWITCH_W("Line in Playback Switch", 0,
+			MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1),
+/*	BURGUNDY_SWITCH_B("Line in Boost Capture Switch", 0,
+ *		MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) */
+};
+static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac __initdata =
+BURGUNDY_SWITCH_B("Master Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT,
+	BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac __initdata =
+BURGUNDY_SWITCH_B("Master Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_INTERN
+	| BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac __initdata =
+BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac __initdata =
+BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_INTERN, 0, 0);
+static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac __initdata =
+BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac __initdata =
+BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac __initdata =
+BURGUNDY_SWITCH_B("Headphone Playback Switch", 0,
+	MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+	BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1);


 #ifdef PMAC_SUPPORT_AUTOMUTE
@@ -347,19 +579,30 @@ static int snd_pmac_burgundy_detect_head
 	return (in_le32(&chip->awacs->codec_stat) & chip->hp_stat_mask) ? 1 : 0;
 }

-static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip,
int do_notify)
+static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip,
+					      int do_notify)
 {
 	if (chip->auto_mute) {
+		int imac = machine_is_compatible("iMac");
 		int reg, oreg;
-		reg = oreg = snd_pmac_burgundy_rcb(chip,
MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
-		reg &= ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT |
BURGUNDY_OUTPUT_INTERN);
+		reg = oreg = snd_pmac_burgundy_rcb(chip,
+				MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
+		reg &= imac ? ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT
+				| BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT)
+			: ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT
+				| BURGUNDY_OUTPUT_INTERN);
 		if (snd_pmac_burgundy_detect_headphone(chip))
-			reg |= BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT;
+			reg |= imac ? (BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT)
+				: (BURGUNDY_OUTPUT_LEFT
+					| BURGUNDY_OUTPUT_RIGHT);
 		else
-			reg |= BURGUNDY_OUTPUT_INTERN;
+			reg |= imac ? (BURGUNDY_OUTPUT_LEFT
+					| BURGUNDY_OUTPUT_RIGHT)
+				: (BURGUNDY_OUTPUT_INTERN);
 		if (do_notify && reg == oreg)
 			return;
-		snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg);
+		snd_pmac_burgundy_wcb(chip,
+				MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg);
 		if (do_notify) {
 			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
 				       &chip->master_sw_ctl->id);
@@ -378,6 +621,7 @@ static void snd_pmac_burgundy_update_aut
  */
 int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
 {
+	int imac = machine_is_compatible("iMac");
 	int i, err;

 	/* Checks to see the chip is alive and kicking */
@@ -386,7 +630,7 @@ int __init snd_pmac_burgundy_init(struct
 		return 1;
 	}

-	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES,
+	snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES,
 			   DEF_BURGUNDY_OUTPUTENABLES);
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
 			   DEF_BURGUNDY_MORE_OUTPUTENABLES);
@@ -396,7 +640,8 @@ int __init snd_pmac_burgundy_init(struct
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL21,
 			   DEF_BURGUNDY_INPSEL21);
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL3,
-			   DEF_BURGUNDY_INPSEL3);
+			   imac ? DEF_BURGUNDY_INPSEL3_IMAC
+			   : DEF_BURGUNDY_INPSEL3_PMAC);
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINCD,
 			   DEF_BURGUNDY_GAINCD);
 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINLINE,
@@ -422,23 +667,51 @@ int __init snd_pmac_burgundy_init(struct
 	snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLMIC,
 			   DEF_BURGUNDY_VOLMIC);

-	if (chip->hp_stat_mask == 0)
+	if (chip->hp_stat_mask == 0) {
 		/* set headphone-jack detection bit */
-		chip->hp_stat_mask = 0x04;
-
+		if (imac)
+			chip->hp_stat_mask = BURGUNDY_HPDETECT_IMAC_UPPER
+				| BURGUNDY_HPDETECT_IMAC_LOWER
+				| BURGUNDY_HPDETECT_IMAC_SIDE;
+		else
+			chip->hp_stat_mask = BURGUNDY_HPDETECT_PMAC_BACK;
+	}
 	/*
 	 * build burgundy mixers
 	 */
 	strcpy(chip->card->mixername, "PowerMac Burgundy");

 	for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) {
-		if ((err = snd_ctl_add(chip->card,
snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip))) < 0)
+		if ((err = snd_ctl_add(chip->card,
+		    snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip))) < 0)
+			return err;
+	}
+	for (i = 0; i < (imac ? ARRAY_SIZE(snd_pmac_burgundy_mixers_imac)
+			: ARRAY_SIZE(snd_pmac_burgundy_mixers_pmac)); i++) {
+		if ((err = snd_ctl_add(chip->card,
+		    snd_ctl_new1(imac ? &snd_pmac_burgundy_mixers_imac[i]
+		    : &snd_pmac_burgundy_mixers_pmac[i], chip))) < 0)
 			return err;
 	}
-	chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_master_sw, chip);
+	chip->master_sw_ctl = snd_ctl_new1(imac
+			? &snd_pmac_burgundy_master_sw_imac
+			: &snd_pmac_burgundy_master_sw_pmac, chip);
 	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
 		return err;
-	chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_speaker_sw, chip);
+	chip->master_sw_ctl = snd_ctl_new1(imac
+			? &snd_pmac_burgundy_line_sw_imac
+			: &snd_pmac_burgundy_line_sw_pmac, chip);
+	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
+		return err;
+	if (imac) {
+		chip->master_sw_ctl = snd_ctl_new1(
+				&snd_pmac_burgundy_hp_sw_imac, chip);
+		if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
+			return err;
+	}
+	chip->speaker_sw_ctl = snd_ctl_new1(imac
+			? &snd_pmac_burgundy_speaker_sw_imac
+			: &snd_pmac_burgundy_speaker_sw_pmac, chip);
 	if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
 		return err;
 #ifdef PMAC_SUPPORT_AUTOMUTE
--- sound/ppc/burgundy.h.orig	2008-04-05 17:45:08.000000000 +0300
+++ sound/ppc/burgundy.h	2008-04-05 22:02:44.000000000 +0300
@@ -22,6 +22,7 @@
 #ifndef __BURGUNDY_H
 #define __BURGUNDY_H

+#define MASK_ADDR_BURGUNDY_INPBOOST (0x10 << 12)
 #define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12)
 #define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12)

@@ -35,7 +36,10 @@
 #define MASK_ADDR_BURGUNDY_VOLCH3 (0x22 << 12)
 #define MASK_ADDR_BURGUNDY_VOLCH4 (0x23 << 12)

+#define MASK_ADDR_BURGUNDY_CAPTURESELECTS (0x2A << 12)
 #define MASK_ADDR_BURGUNDY_OUTPUTSELECTS (0x2B << 12)
+#define MASK_ADDR_BURGUNDY_VOLMIX01 (0x2D << 12)
+#define MASK_ADDR_BURGUNDY_VOLMIX23 (0x2E << 12)
 #define MASK_ADDR_BURGUNDY_OUTPUTENABLES (0x2F << 12)

 #define MASK_ADDR_BURGUNDY_MASTER_VOLUME (0x30 << 12)
@@ -45,6 +49,10 @@
 #define MASK_ADDR_BURGUNDY_ATTENSPEAKER (0x62 << 12)
 #define MASK_ADDR_BURGUNDY_ATTENLINEOUT (0x63 << 12)
 #define MASK_ADDR_BURGUNDY_ATTENHP (0x64 << 12)
+#define MASK_ADDR_BURGUNDY_ATTENMONO (0x65 << 12)
+
+#define MASK_ADDR_BURGUNDY_HOSTIFAD (0x78 << 12)
+#define MASK_ADDR_BURGUNDY_HOSTIFEH (0x79 << 12)

 #define MASK_ADDR_BURGUNDY_VOLCD (MASK_ADDR_BURGUNDY_VOLCH1)
 #define MASK_ADDR_BURGUNDY_VOLLINE (MASK_ADDR_BURGUNDY_VOLCH2)
@@ -59,21 +67,22 @@

 /* These are all default values for the burgundy */
 #define DEF_BURGUNDY_INPSEL21 (0xAA)
-#define DEF_BURGUNDY_INPSEL3 (0x0A)
+#define DEF_BURGUNDY_INPSEL3_IMAC (0x0A)
+#define DEF_BURGUNDY_INPSEL3_PMAC (0x05)

 #define DEF_BURGUNDY_GAINCD (0x33)
 #define DEF_BURGUNDY_GAINLINE (0x44)
 #define DEF_BURGUNDY_GAINMIC (0x44)
 #define DEF_BURGUNDY_GAINMODEM (0x06)

-/* Remember: lowest volume here is 0x9b */
+/* Remember: lowest volume here is 0x9B (155) */
 #define DEF_BURGUNDY_VOLCD (0xCCCCCCCC)
 #define DEF_BURGUNDY_VOLLINE (0x00000000)
 #define DEF_BURGUNDY_VOLMIC (0x00000000)
 #define DEF_BURGUNDY_VOLMODEM (0xCCCCCCCC)

-#define DEF_BURGUNDY_OUTPUTSELECTS (0x010f010f)
-#define DEF_BURGUNDY_OUTPUTENABLES (0x0A)
+#define DEF_BURGUNDY_OUTPUTSELECTS (0x010F010F)
+#define DEF_BURGUNDY_OUTPUTENABLES (0x0100000A)

 /* #define DEF_BURGUNDY_MASTER_VOLUME (0xFFFFFFFF) */ /* too loud */
 #define DEF_BURGUNDY_MASTER_VOLUME (0xDDDDDDDD)
@@ -84,12 +93,22 @@
 #define DEF_BURGUNDY_ATTENLINEOUT (0xCC)
 #define DEF_BURGUNDY_ATTENHP (0xCC)

-/* OUTPUTENABLES bits */
+/* MORE_OUTPUTENABLES bits */
 #define BURGUNDY_OUTPUT_LEFT	0x02
 #define BURGUNDY_OUTPUT_RIGHT	0x04
+#define BURGUNDY_LINEOUT_LEFT	0x08
+#define BURGUNDY_LINEOUT_RIGHT	0x10
+#define BURGUNDY_HP_LEFT	0x20
+#define BURGUNDY_HP_RIGHT	0x40
 #define BURGUNDY_OUTPUT_INTERN	0x80

-/* volume offset */
+/* Headphone detection bits */
+#define BURGUNDY_HPDETECT_PMAC_BACK	0x04
+#define BURGUNDY_HPDETECT_IMAC_SIDE	0x04
+#define BURGUNDY_HPDETECT_IMAC_UPPER	0x08
+#define BURGUNDY_HPDETECT_IMAC_LOWER	0x01
+
+/* Volume offset */
 #define BURGUNDY_VOLUME_OFFSET	155

 #endif /* __BURGUNDY_H */

^ permalink raw reply

* Re: [PATCH 3/4] PowerPC: Add PCI entry to 440EPx Sequoia DTS.
From: Sergei Shtylyov @ 2008-04-07 13:30 UTC (permalink / raw)
  To: Valentine Barshak; +Cc: linuxppc-dev
In-Reply-To: <47FA1B20.40609@ru.mvista.com>

Hello.

Valentine Barshak wrote:

>>> --- linux-2.6.orig/arch/powerpc/boot/dts/sequoia.dts    2007-12-21 
>>> 17:14:17.000000000 +0300
>>> +++ linux-2.6/arch/powerpc/boot/dts/sequoia.dts    2007-12-21 
>>> 17:18:32.000000000 +0300
>>> @@ -324,6 +324,33 @@
>>>                  has-new-stacr-staopc;
>>>              };
>>>          };
>>> +
>>> +        PCI0: pci@1ec000000 {
>>> +            device_type = "pci";
>>> +            #interrupt-cells = <1>;
>>> +            #size-cells = <2>;
>>> +            #address-cells = <3>;
>>> +            compatible = "ibm,plb440epx-pci", "ibm,plb-pci";
>>> +            primary;
>>> +            reg = <1 eec00000 8    /* Config space access */
>>> +                   1 eed00000 4    /* IACK */
>>> +                   1 eed00000 4    /* Special cycle */
>>> +                   1 ef400000 40>;    /* Internal registers */
>>> +
>>> +            /* Outbound ranges, one memory and one IO,
>>> +             * later cannot be changed. Chip supports a second
>>> +             * IO range but we don't use it for now
>>> +             */
>>> +            ranges = <02000000 0 80000000 1 80000000 0 10000000

>>    I wonder why the AMCC's Sequoia/Rainier manual has PCI memory 
>> mapped at 0x80000000-0xbfffffff? The 0x80000000-0x8fffffff mapping was 
>> assumed by arch/ppc/ code.  What/why changed here?

> The addresses in the manual are relative to bus base.

    Hm, that's hard to infer from the manual, and even from arch/ppc/ sources...

> PCI controller is 
> located on the PLB and PLB base address is 0x100000000ULL on Sequoia.

     The question is where cam one read about that. :-)

> Older PPC code has ioremap64 function that did the 64 to 32-bit trick

    Ah, seeing fixup_bigphys_addr() at last -- it has escaped me before...

> It's been abolished. The kernel has support for 64-bit physical 
> addresses on 32-bit. IMHO there's no big reason to keep doing that 
> address trick. However, there are some drivers that use unsigned long 
> for storing physical addresses. This is wrong, since 
> pci_resource_start() returns a resource_size_t value. I think it's these 
> drivers that have to be fixed instead of adding workarounds to ppc4xx code.

    Well, I'm not arguing with that. Just tried to clarify the PCI mapping 
thing for myself. :-)

>>    As we now both know, having PCI memory space mapped beyound 4 GB 
>> makes some drivers misbehave as they use 'unsigned long' to store the 
>> result of pci_resource_start() and later ioremap() this truncated 
>> value -- which is 64-bit on Sequoia due to CONFIG_RESOURCE_64BIT=y 
>> that is needed to store the beyond-4GB addresses.

    Luckily, this one concerns the memory resources, as the I/O resources are 
actually limited to 'unsigned long' anyway...

WBR, Sergei

^ permalink raw reply

* Re: [PATCH] PowerPC: MPIC ack interrupts at mpic_teardown_this_cpu()
From: Olof Johansson @ 2008-04-07 14:24 UTC (permalink / raw)
  To: Valentine Barshak; +Cc: linuxppc-dev
In-Reply-To: <20080403190943.GA16446@ru.mvista.com>

On Thu, Apr 03, 2008 at 11:09:43PM +0400, Valentine Barshak wrote:
> We really need to ack interrupts at mpic_teardown, since
> not all platforms reset mpic at kernel start-up. For example,
> kexec'ed kernel hangs on P.A. Semi if mpic_eoi() isn't called.
> 
> Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>

I have applied this to pasemi.git for-2.6.26 with the following comment
added before the mpic_eoi call:

        /* We need to EOI the IPI since not all platforms reset the MPIC
         * on boot and new interrupts wouldn't get delivered otherwise.
         */
	mpic_eoi(mpic);


Thanks,

-Olof

^ permalink raw reply

* Please pull 'for-2.6.26' branch of pasemi.git
From: Olof Johansson @ 2008-04-07 14:30 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev, pasemi-linux

Paul,

Please pull from 'for-2.6.26' branch of

  master.kernel.org:/pub/scm/linux/kernel/git/olof/pasemi.git for-2.6.26

to receive the following updates. The pasemi_mac ones have been
discussed on netdev and acked by Jeff.

 arch/powerpc/platforms/pasemi/iommu.c |   19 ++++++++----------
 arch/powerpc/sysdev/mpic.c            |    9 +++-----
 drivers/net/pasemi_mac.c              |   35 ++++++++++++++++++++++++++++++++--
 3 files changed, 46 insertions(+), 17 deletions(-)

Nate Case (1):
      pasemi_mac: Netpoll support

Olof Johansson (2):
      pasemi_mac: Jumbo frame bugfixes
      [POWERPC] pasemi: Minor iommu cleanup

Valentine Barshak (1):
      [POWERPC] kexec: MPIC ack interrupts at mpic_teardown_this_cpu()

^ permalink raw reply

* [PATCH] [POWERPC] Remove unused __max_memory variable
From: Olof Johansson @ 2008-04-07 15:33 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev

Remove the __max_memory variable, it is not referenced anywhere
in the tree besides some code in arch/ppc.


Signed-off-by: Olof Johansson <olof@lixom.net>

diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 5f55399..82edd63 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -72,9 +72,6 @@
 #warning TASK_SIZE is smaller than it needs to be.
 #endif
 
-/* max amount of RAM to use */
-unsigned long __max_memory;
-
 void free_initmem(void)
 {
 	unsigned long addr;

^ permalink raw reply related

* Booting a Xilinx board
From: Guillaume Dargaud @ 2008-04-07 15:33 UTC (permalink / raw)
  To: linuxppc-dev

Hello all,
sorry if this is an elementary question for most of you, but could you tell 
me where I'm going wrong in trying to boot a kernel 2.6.24 on a Xilinx ml405 
board ?

- I generate an ext2 partition with buildroot, cointaining busybox and 
uclibc.

- I copy it to my CF card:
sudo dd if=binaries/genepy/rootfs.test.ext2 of=/dev/sdc2

- I compile the git Xilinx kernel, with proper xparameters file from the BSP 
and proper .config options to match the design, using the cross compiler 
created by buildroot.

- I generate a sysace file from that kernel and put it on the 1st partition:
xmd -tcl genace.tcl -jprog -board ml405 -target ppc_hw -hw 
implementation/system.bit -elf 
~/kernels/linux-2.6.24/arch/ppc/boot/images/zImage.elf -ace Kernel26.ace

When I boot I get the following:

loaded at:     00400000 0050719C
board data at: 00505120 0050519C
relocated to:  00404054 004040D0
zimage at:     00404E40 0050484E
avail ram:     00508000 08000000

Linux/PPC load: console=ttyS0,9600 ip=on root=/dev/sysace/disc0/part2 rw
Uncompressing Linux...done.
Now booting the kernel

And then it stops.
I'm sure I've overlooked something obvious...
Thanks
-- 
Guillaume Dargaud
http://www.gdargaud.net/

^ permalink raw reply

* Re: MVL Linux on MPC8560 Booting goes into infinite loop in early_init memset_io ( )
From: Scott Wood @ 2008-04-07 16:04 UTC (permalink / raw)
  To: Deepak Gaur; +Cc: linuxppc-embedded
In-Reply-To: <20080407064547.M56295@cdotd.ernet.in>

Deepak Gaur wrote:
> Hi all,
> 
> While booting MVL linux

Have you talked to MV support?  For community support, it's best to use 
the latest upstream sources (and arch/powerpc, not arch/ppc).

BTW, it's generally bad form to post the same question repeatedly.  If 
you have new information regarding your problem, just post a followup in 
the same thread containing the new information.

> arch/ppc/kernel/setup.c
> ----------------------------------------
> unsigned long
> early_init(int r3, int r4, int r5)
> {
>         unsigned long phys;
>         unsigned long offset = reloc_offset();
> 
>         /* Default */
>         phys = offset + KERNELBASE;
> 
>         /* First zero the BSS -- use memset, some arches don't have
>          * caches on yet */
>        
>         memset_io(PTRRELOC(&__bss_start), 0, _end - __bss_start);
> 
>         __bss_start is 0xc039b00 and __bss_stop = _end =c03c7d90  _end
> 
> 
>         Please anyone give me some pointers to understand this i.e use of PTRRELOC

The kernel hasn't been remapped yet, so the pointer is adjusted manually.

> and REASON BEHIND clearing area from __bss_start to _end - __bss_start even though lot of
> symbols and functions are defined here(as per System.map)

That's what the BSS is for -- symbols that are cleared at runtime so as 
to eliminate the need to store them in the image.  There should be no 
functions in there.

-Scott

^ permalink raw reply

* Re: MPC8343 - "unable to handle paging request @ 0"
From: Scott Wood @ 2008-04-07 16:10 UTC (permalink / raw)
  To: André Schwarz; +Cc: linuxppc-dev
In-Reply-To: <47F73625.9040903@matrix-vision.de>

On Sat, Apr 05, 2008 at 10:19:49AM +0200, André Schwarz wrote:
> Kernel starts and crashes with "unable to handle kernel paging request @  
> 00000000".
>
> After turning debug on in some files I can see that the initrd memory  
> gets reserved and the dtb is parsed correctly.
> PCI memory/io spaces are set up fine.
>
> At first I thought this is a problem with the device tree since the call  
> trace always points to "of_"-functions and "strcmp".

Could you provide this call trace?

-Scott

^ permalink raw reply

* Re: [PATCH] Freescale QUICC Engine USB Host Controller
From: Laurent Pinchart @ 2008-04-07 16:11 UTC (permalink / raw)
  To: avorontsov
  Cc: Scott Wood, linuxppc-dev, linux-usb, David Brownell, Timur Tabi
In-Reply-To: <20080403143052.GA5955@polina.dev.rtsoft.ru>

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

Hi Anton,

On Thursday 03 April 2008 16:30, Anton Vorontsov wrote:
> On Thu, Apr 03, 2008 at 03:45:47PM +0200, Laurent Pinchart wrote:
> > Hi Anton,
> > 
> > On Tuesday 11 March 2008 20:17, Anton Vorontsov wrote:
> > > This is patch adds support for the FHCI USB controller, as found in the
> > > Freescale MPC836x and MPC832x processors. It can support Full or Low
> > > speed modes. 
> > > 
> > > Quite a lot hardware is doing by itself (SOF generation, CRC generation
> > > and checking), though scheduling and retransmission is on the software
> > > shoulders.
> > > 
> > > This controller does not integrate the root hub, so this driver also
> > > fakes an one-port hub. External hub is required to support more than
> > > one device.
> > 
> > Would it be possible to use the driver for CPM2-based devices ?
> 
> Probably. But no one had tried this yet.
> 
> > The only difference I found between the CPM2 and QE USB controllers is the
> > SOF handling. The QE USB controller increments the frame number itself,
> > while the CPM USB controller requires the host to increment the frame
> > number. 
> > 
> > At first sight the driver depends on qe_lib for:
> > 
> > - muram allocation (qe_muram_alloc/free, qe_muram_offset/addr)
> 
> Yeah, I already posted a patch to deal with it, see
> http://ozlabs.org/pipermail/linuxppc-dev/2008-March/053249.html
> (btw... Scott, Timur did you have a chance to look into this?)

Hope this will get into 2.6.26. I replaced all occurences of qe_muram_* by 
cpm_muram_* in the driver for now.

> > - GPIO access (qe_gpio_set_dedicated)
> 
> This is because of David Brownell. ;-) Specifically, unwillingness to
> accept that set_dedicated is portable for some scope of GPIO controllers,
> as well as GPIO users.

Both sides have their arguments. As the FHCI driver is tied to CPM2/QE 
platforms anyway, a quick-and-dirty workaround is possible. I currently use 
hardcoded cpm2_set_pin calls.

> > - clock routing (qe_clock_source, qe_usb_clock_set)
> 
> Well, there is Linux CLK API (somewhat similar to GPIO API), but PowerPC
> doesn't use it yet. Neither I can tell if CLK API is suitable for our
> needs, or if it needs to be extended. Quick&dirty workarounds are
> still possible though, but clk api is the right way to go.

The current clock API doesn't seem to handle clock routing, so I'm not sure 
what the best way to handle that is.

> > - QE commands execution (qe_issue_cmd)
> 
> No proper solution yet.
> 
> > It shouldn't be too difficult to abstract those operation in a fashion
> > similar to the cpm_uart driver.
> 
> Yup, but we still have ucc_serial (QE) and cpm_uart (CPM1/2) drivers as
> separate matters though. ;-) I didn't look for the reasons of this split
> but I assume there are and they're strong enough.
> 
> > Have you already worked on CPM2 support,
> 
> Nope, I don't have CPM2 board to work on.

I had a first go at hacking the FHCI driver to make it run on a CPM2 platform. 
Results so far are quite good. After getting rid of qe-specific APIs as 
explained above, and adding SOF token generation support, I've been able to 
access a mass storage device. The driver hasn't been stress-tested yet 
though.

I ran into an issue with IDLE and RESET interrupts. When the device is first 
plugged into the USB port, the idle interrupt kicks in and the driver detects 
the device properly. When the device is then removed, the reset interrupt is 
generated and the driver handles device removal properly. Right after the 
reset interrupt, idle interrupts are generated every milliseconds for around 
175ms. The status register always reports a non-idle condition when read in 
the interrupt handler. The flow of idle interrupts then stops, and no idle 
interrupt is generated when I replug the device. I've checked the interrupts 
mask register to make sure idle interrupts were enabled.

Have you noticed a similar behaviour when you tested the driver on your 
QE-based platform ? I suspected a debouncing issue, but I should then get 
idle conditions once every other time when reading the status register.

Best regards,

-- 
Laurent Pinchart
CSE Semaphore Belgium

Chaussee de Bruxelles, 732A
B-1410 Waterloo
Belgium

T +32 (2) 387 42 59
F +32 (2) 387 42 75

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: [PATCH v2] powerpc: Add irqtrace support for 32-bit powerpc
From: Dale Farnsworth @ 2008-04-07 16:16 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Johannes Berg
In-Reply-To: <1207543791.10388.468.camel@pasglop>

On Mon, Apr 07, 2008 at 02:49:51PM +1000, Benjamin Herrenschmidt wrote:
> I think I found one:
> 
>  .../...
> 
> > -	mr	r6,r3
> >  	rlwinm	r12,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
> >  	/* disable interrupts so current_thread_info()->flags can't change */
> >  	LOAD_MSR_KERNEL(r10,MSR_KERNEL)	/* doesn't include MSR_EE */
> >  	SYNC
> >  	MTMSRD(r10)
> > +#ifdef CONFIG_TRACE_IRQFLAGS
> > +	stwu	r1,-16(r1)
> > +	stw	r3,12(r1)
> > +	bl      trace_hardirqs_off
> > +	lwz	r3,12(r1)
> > +	addi	r1,r1,16
> > +	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
> > +#endif
> 
> Here, r12 is clobbered, though it's used two lines later:

Ah yes. r12 is volatile, isn't it.  :-)  Good catch.

> > +	mr	r6,r3
> >  	lwz	r9,TI_FLAGS(r12)
> 
> Here.
> 
> You can probably just move the rlwinm down as you moved the mr.

I'll follow up with a revised patch that does exactly that.

> Note that I've been wondering wether we should attempt to trace all
> those IRQ state change internally to the exception code. I've looked at
> not doing it, which simplifies things a bit.
> 
> Unfortunately, that will make us occasionally trace redundant
> enable/disable (which isn't a big problem per-se, just counters).
> 
> The idea is that I only kept the trace of disable in transfer_to_handler
> and I modified the enable tracing in restore: moved it lower down, and
> made it test for _MSR(r1):MSR_EE. I added a trace_irq_off just before
> the preempt_schedule_irq() as well.
> 
> Anyway, let me know what you think.

The main purpose I did this code was to measure
interrupt-disabled intervals.  There, the redundant trace calls aren't
really an issue.

It all depends on how important you view the counters.  I think that
if we're going to go to the trouble to maintain counters, we should
make them accurate.  I admit that it took me quite a while to get the
counts correct. :-)  I think having an accurate measure of the redundant
interrupt disable/enables is useful.  And, after doing the code, I'd
prefer to see it stay.  :-)

Thanks,
-Dale

^ permalink raw reply

* Re: [RFC][PATCH] initial port of fixmap over from x86 for ppc32
From: Scott Wood @ 2008-04-07 16:20 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, Paul Mackerras, hollisb
In-Reply-To: <279F1861-9605-46FD-A917-DF5B95B8C4F6@kernel.crashing.org>

On Mon, Apr 07, 2008 at 08:09:57AM -0500, Kumar Gala wrote:
> On Apr 6, 2008, at 6:48 PM, Paul Mackerras wrote:
>> More generally, I think we need to take an overall look at what things
>> we are using fixed virtual addresses for, and why they need to be
>> fixed.  If there are indeed several such things then we can introduce
>> the fixmap stuff.
>
> The list as I see it:
> * kmap
> * pci-e config for 4xx/83xx
> * kexec/kdump (ben commented on this when Dale posted his patches for  
> ppc32 support)
>
> future:
> * possible usage by HV
>
> since we already have three users and a possible fourth it seems like a 
> useful change.

Another possible use is a BAT/TLB1 mapping for SoC registers (or anything
else on the board which is frequently accessed), which can be reused by
ioremap() to avoid wasting normal TLB entries, and to facilitate early
debugging.

-Scott

^ permalink raw reply

* Re: [PATCH v2] powerpc: Add irqtrace support for 32-bit powerpc
From: Dale Farnsworth @ 2008-04-07 16:21 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev
In-Reply-To: <1207573809.12481.6.camel@johannes.berg>

On Mon, Apr 07, 2008 at 03:10:09PM +0200, Johannes Berg wrote:
> > Note that I've been wondering wether we should attempt to trace all
> > those IRQ state change internally to the exception code. I've looked at
> > not doing it, which simplifies things a bit.
> > 
> > Unfortunately, that will make us occasionally trace redundant
> > enable/disable (which isn't a big problem per-se, just counters).
> 
> We already have a huge number of redundant enable/disable, about 40% of
> all events on both 32 and 64-bit.

Yes, but there is a big difference between the large number of actual
redundant enables and disables we now have, and introducing miscounts
of them in the measurement code.  That we have so many might mean that
we shouldn't bother to count them at all, but I don't think it's an
excuse for not counting them accurately.

-Dale

^ permalink raw reply

* Re: a question about use dtb to bootting linux kernel on MPC83xx platform
From: Scott Wood @ 2008-04-07 16:38 UTC (permalink / raw)
  To: 旭 罗; +Cc: linuxppc-dev
In-Reply-To: <959437.18740.qm@web15907.mail.cnb.yahoo.com>

On Mon, Apr 07, 2008 at 09:35:17AM +0800, 旭 罗 wrote:
>     I am Linux software engineer. These days I was debugging a MPC8313 system. In  the debugging process, some source code in the kernel makes me puzzled. So I  have find your email address in the source code. I think you can give me some  advises to solve the problem.
>   
>         My version is  linux-2.6.23.9 and I use the device tree(dtb) to  booting the kernel. In my bootloader I use the following code to jump to the  kernel.
>  (*image)((bd_t *)dtb_entry,  (unsigned int)image, 0, 0, 0); 
>   
>  The dtb_entry is the address of dtb  file which in the SDRAM, the image
> is the kernel entry point. I flashed some LEDs in my board. So I can make
> sure the program run to the machine_init() which is defined in the
> /arch/powerpc/kernel/setup_32.c In order to trace the problem I search the
> source code. I can find that these information is printed by the start
> function which is defined in the /arch/powerpc/boot/main.c.
>  Fourth more I have found that the  kernel call the platform_init which is
>  defined in the /arch/powerpc/boot/cuboot-83xx.c. looking the file head I
>  have known you are the author for this file. Could you told me how the
>  kernel call the platform_init function and I hope you can show me the
>  booting process of the MPC83xx linux or you could give me some document
>  about it.

As I said when you e-mailed me privately a few days ago, cuImage is for
older u-boots that pass in a bd_t, not a device tree. You should be booting
uImage instead.

-Scott

^ permalink raw reply

* RE: Booting a Xilinx board
From: Stephen Neuendorffer @ 2008-04-07 16:44 UTC (permalink / raw)
  To: Guillaume Dargaud, linuxppc-dev
In-Reply-To: <10a101c898c4$c183ee40$f52f9e86@LPSC0173W>


Generally, speaking the easiest way to debug such errors is to examine
__log_buf using XMD.

Steve

> -----Original Message-----
> From: =
linuxppc-dev-bounces+stephen.neuendorffer=3Dxilinx.com@ozlabs.org
[mailto:linuxppc-dev-
> bounces+stephen.neuendorffer=3Dxilinx.com@ozlabs.org] On Behalf Of
Guillaume Dargaud
> Sent: Monday, April 07, 2008 8:34 AM
> To: linuxppc-dev@ozlabs.org
> Subject: Booting a Xilinx board
>=20
> Hello all,
> sorry if this is an elementary question for most of you, but could you
tell
> me where I'm going wrong in trying to boot a kernel 2.6.24 on a Xilinx
ml405
> board ?
>=20
> - I generate an ext2 partition with buildroot, cointaining busybox and
> uclibc.
>=20
> - I copy it to my CF card:
> sudo dd if=3Dbinaries/genepy/rootfs.test.ext2 of=3D/dev/sdc2
>=20
> - I compile the git Xilinx kernel, with proper xparameters file from
the BSP
> and proper .config options to match the design, using the cross
compiler
> created by buildroot.
>=20
> - I generate a sysace file from that kernel and put it on the 1st
partition:
> xmd -tcl genace.tcl -jprog -board ml405 -target ppc_hw -hw
> implementation/system.bit -elf
> ~/kernels/linux-2.6.24/arch/ppc/boot/images/zImage.elf -ace
Kernel26.ace
>=20
> When I boot I get the following:
>=20
> loaded at:     00400000 0050719C
> board data at: 00505120 0050519C
> relocated to:  00404054 004040D0
> zimage at:     00404E40 0050484E
> avail ram:     00508000 08000000
>=20
> Linux/PPC load: console=3DttyS0,9600 ip=3Don =
root=3D/dev/sysace/disc0/part2
rw
> Uncompressing Linux...done.
> Now booting the kernel
>=20
> And then it stops.
> I'm sure I've overlooked something obvious...
> Thanks
> --
> Guillaume Dargaud
> http://www.gdargaud.net/
>=20
>=20
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH 6/13] devres: implement managed iomap interface
From: Sergei Shtylyov @ 2008-04-07 16:46 UTC (permalink / raw)
  To: Tejun Heo; +Cc: linuxppc-dev, gregkh, linux-kernel, linux-ide, jgarzik, alan
In-Reply-To: <11684073371547-git-send-email-htejun@gmail.com>

Tejun Heo wrote:

> +/**
> + * devm_ioremap - Managed ioremap()
> + * @dev: Generic device to remap IO address for
> + * @offset: BUS offset to map
> + * @size: Size of map
> + *
> + * Managed ioremap().  Map is automatically unmapped on driver detach.
> + */
> +void __iomem *devm_ioremap(struct device *dev, unsigned long offset,
> +			   unsigned long size)
> +{
> +	void __iomem **ptr, *addr;
> +
> +	ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
> +	if (!ptr)
> +		return NULL;
> +
> +	addr = ioremap(offset, size);
> +	if (addr) {
> +		*ptr = addr;
> +		devres_add(dev, ptr);
> +	} else
> +		devres_free(ptr);
> +
> +	return addr;
> +}
> +EXPORT_SYMBOL(devm_ioremap);
> +
> +/**
> + * devm_ioremap_nocache - Managed ioremap_nocache()
> + * @dev: Generic device to remap IO address for
> + * @offset: BUS offset to map
> + * @size: Size of map
> + *
> + * Managed ioremap_nocache().  Map is automatically unmapped on driver
> + * detach.
> + */
> +void __iomem *devm_ioremap_nocache(struct device *dev, unsigned long offset,
> +				   unsigned long size)
> +{
> +	void __iomem **ptr, *addr;
> +
> +	ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
> +	if (!ptr)
> +		return NULL;
> +
> +	addr = ioremap_nocache(offset, size);
> +	if (addr) {
> +		*ptr = addr;
> +		devres_add(dev, ptr);
> +	} else
> +		devres_free(ptr);
> +
> +	return addr;
> +}
> +EXPORT_SYMBOL(devm_ioremap_nocache);

    A very late comment but nevertheless... :-)
    Those functions are going to break on 32-bit platforms with extended 
physical address (well, that's starting with Pentiums which had 36-bit PAE :-) 
AND devices mapped beyond 4 GB (e.g. PowerPC 44x).  You should have used 
resource_size_t for the 'offset' parameter. As this most probably means that 
libata is broken on such platforms, I'm going to submit a patch...

WBR, Sergei

^ permalink raw reply

* RE: Booting a Xilinx board
From: John Linn @ 2008-04-07 16:59 UTC (permalink / raw)
  To: Stephen Neuendorffer, Guillaume Dargaud, linuxppc-dev
In-Reply-To: <20080407164421.44D46CC0050@mail102-sin.bigfish.com>

You can also get our support file from the http git web site and then
use the default ML405 kernel configuration just as a baseline to get the
kernel running.  The support file has a bit stream that supports the 405
def kernel configuration.

Thanks,
John

-----Original Message-----
From: linuxppc-dev-bounces+john.linn=3Dxilinx.com@ozlabs.org
[mailto:linuxppc-dev-bounces+john.linn=3Dxilinx.com@ozlabs.org] On =
Behalf
Of Stephen Neuendorffer
Sent: Monday, April 07, 2008 10:44 AM
To: Guillaume Dargaud; linuxppc-dev@ozlabs.org
Subject: RE: Booting a Xilinx board


Generally, speaking the easiest way to debug such errors is to examine
__log_buf using XMD.

Steve

> -----Original Message-----
> From: =
linuxppc-dev-bounces+stephen.neuendorffer=3Dxilinx.com@ozlabs.org
[mailto:linuxppc-dev-
> bounces+stephen.neuendorffer=3Dxilinx.com@ozlabs.org] On Behalf Of
Guillaume Dargaud
> Sent: Monday, April 07, 2008 8:34 AM
> To: linuxppc-dev@ozlabs.org
> Subject: Booting a Xilinx board
>=20
> Hello all,
> sorry if this is an elementary question for most of you, but could you
tell
> me where I'm going wrong in trying to boot a kernel 2.6.24 on a Xilinx
ml405
> board ?
>=20
> - I generate an ext2 partition with buildroot, cointaining busybox and
> uclibc.
>=20
> - I copy it to my CF card:
> sudo dd if=3Dbinaries/genepy/rootfs.test.ext2 of=3D/dev/sdc2
>=20
> - I compile the git Xilinx kernel, with proper xparameters file from
the BSP
> and proper .config options to match the design, using the cross
compiler
> created by buildroot.
>=20
> - I generate a sysace file from that kernel and put it on the 1st
partition:
> xmd -tcl genace.tcl -jprog -board ml405 -target ppc_hw -hw
> implementation/system.bit -elf
> ~/kernels/linux-2.6.24/arch/ppc/boot/images/zImage.elf -ace
Kernel26.ace
>=20
> When I boot I get the following:
>=20
> loaded at:     00400000 0050719C
> board data at: 00505120 0050519C
> relocated to:  00404054 004040D0
> zimage at:     00404E40 0050484E
> avail ram:     00508000 08000000
>=20
> Linux/PPC load: console=3DttyS0,9600 ip=3Don =
root=3D/dev/sysace/disc0/part2
rw
> Uncompressing Linux...done.
> Now booting the kernel
>=20
> And then it stops.
> I'm sure I've overlooked something obvious...
> Thanks
> --
> Guillaume Dargaud
> http://www.gdargaud.net/
>=20
>=20
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev


_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* [PATCH v3] powerpc: Add irqtrace support for 32-bit powerpc
From: Dale Farnsworth @ 2008-04-07 17:14 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Johannes Berg
In-Reply-To: <20080404213932.GA15847@farnsworth.org>

Add the low level irq tracing hooks for 32-bit powerpc needed
to enable full lockdep functionality.

Dale Farnsworth <dale@farnsworth.org>
---
This version fixes the clobbering of r12 by the call to
trace_hardirqs_off() that was pointed out by BenH.

Johannes, I'd appreciate your trying this version if/when
you get the chance.

 arch/powerpc/Kconfig           |    1 -
 arch/powerpc/kernel/entry_32.S |   92 ++++++++++++++++++++++++++++++++++++++--
 arch/powerpc/kernel/setup_32.c |    2 +
 include/asm-powerpc/hw_irq.h   |   20 ++++----
 include/asm-powerpc/system.h   |    3 +-
 5 files changed, 101 insertions(+), 17 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 6dbf123..99d8e18 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -55,7 +55,6 @@ config STACKTRACE_SUPPORT
 
 config TRACE_IRQFLAGS_SUPPORT
 	bool
-	depends on PPC64
 	default y
 
 config LOCKDEP_SUPPORT
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 69a91bd..ad30d38 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -144,6 +144,47 @@ transfer_to_handler:
 	.globl transfer_to_handler_cont
 transfer_to_handler_cont:
 3:
+#ifdef CONFIG_TRACE_IRQFLAGS
+	lis	r11,reenable_mmu@h
+	ori	r11,r11,reenable_mmu@l
+	mtspr	SPRN_SRR0,r11
+	mtspr	SPRN_SRR1,r10
+	SYNC
+	RFI
+reenable_mmu:				/* re-enable mmu so we can */
+	mflr	r9			/* call C code, if necessary */
+	mfmsr	r10
+	lwz	r11,_MSR(r1)
+	xor	r10,r10,r11
+	andi.	r10,r10,MSR_EE		/* Did EE change? */
+	beq	1f
+	stwu	r1,-48(r1)		/* Yes, it must have been cleared */
+	stw	r9,52(r1)
+	stw	r0,16(r1)
+	stw	r3,20(r1)
+	stw	r4,24(r1)
+	stw	r5,28(r1)
+	stw	r6,32(r1)
+	stw	r7,36(r1)
+	stw	r8,40(r1)
+	bl	trace_hardirqs_off
+	lwz	r0,16(r1)
+	lwz	r3,20(r1)
+	lwz	r4,24(r1)
+	lwz	r5,28(r1)
+	lwz	r6,32(r1)
+	lwz	r7,36(r1)
+	lwz	r8,40(r1)
+	lwz	r9,52(r1)
+	addi	r1,r1,48
+1:
+	tovirt(r9,r9)
+	lwz	r11,0(r9)		/* virtual address of handler */
+	lwz	r9,4(r9)		/* where to go when done */
+	mtctr	r11
+	mtlr	r9
+	bctr				/* jump to handler */
+#else /* CONFIG_TRACE_IRQFLAGS */
 	mflr	r9
 	lwz	r11,0(r9)		/* virtual address of handler */
 	lwz	r9,4(r9)		/* where to go when done */
@@ -152,6 +193,7 @@ transfer_to_handler_cont:
 	mtlr	r9
 	SYNC
 	RFI				/* jump to handler, enable MMU */
+#endif /* CONFIG_TRACE_IRQFLAGS */
 
 #ifdef CONFIG_6xx
 4:	rlwinm	r12,r12,0,~_TLF_NAPPING
@@ -220,12 +262,20 @@ ret_from_syscall:
 #ifdef SHOW_SYSCALLS
 	bl	do_show_syscall_exit
 #endif
-	mr	r6,r3
-	rlwinm	r12,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
 	/* disable interrupts so current_thread_info()->flags can't change */
 	LOAD_MSR_KERNEL(r10,MSR_KERNEL)	/* doesn't include MSR_EE */
 	SYNC
 	MTMSRD(r10)
+#ifdef CONFIG_TRACE_IRQFLAGS
+	stwu	r1,-16(r1)
+	stw	r3,12(r1)
+	bl      trace_hardirqs_off
+	lwz	r3,12(r1)
+	addi	r1,r1,16
+	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
+#endif
+	mr	r6,r3
+	rlwinm	r12,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
 	lwz	r9,TI_FLAGS(r12)
 	li	r8,-_LAST_ERRNO
 	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK)
@@ -237,6 +287,13 @@ ret_from_syscall:
 	oris	r11,r11,0x1000	/* Set SO bit in CR */
 	stw	r11,_CCR(r1)
 syscall_exit_cont:
+#ifdef CONFIG_TRACE_IRQFLAGS
+	stwu	r1,-16(r1)
+	stw	r3,12(r1)
+	bl      trace_hardirqs_on
+	lwz	r3,12(r1)
+	addi	r1,r1,16
+#endif
 #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
 	/* If the process has its own DBCR0 value, load it up.  The single
 	   step bit tells us that dbcr0 should be loaded. */
@@ -337,7 +394,10 @@ syscall_exit_work:
 4:	/* Anything which requires enabling interrupts? */
 	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
 	beq	ret_from_except
-
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl      trace_hardirqs_on
+	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
+#endif
 	/* Re-enable interrupts */
 	ori	r10,r10,MSR_EE
 	SYNC
@@ -646,13 +706,22 @@ ret_from_except_full:
 
 	.globl	ret_from_except
 ret_from_except:
+#ifdef CONFIG_TRACE_IRQFLAGS
+	mfmsr	r3
+#endif
 	/* Hard-disable interrupts so that current_thread_info()->flags
 	 * can't change between when we test it and when we return
 	 * from the interrupt. */
 	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
 	SYNC			/* Some chip revs have problems here... */
 	MTMSRD(r10)		/* disable interrupts */
-
+#ifdef CONFIG_TRACE_IRQFLAGS
+	andi.	r3,r3,MSR_EE
+	beq	1f
+	bl	trace_hardirqs_off
+	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
+1:
+#endif
 	lwz	r3,_MSR(r1)	/* Returning to user mode? */
 	andi.	r0,r3,MSR_PR
 	beq	resume_kernel
@@ -709,6 +778,9 @@ restore:
 	stw	r6,icache_44x_need_flush@l(r4)
 1:
 #endif  /* CONFIG_44x */
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_on
+#endif
 	lwz	r0,GPR0(r1)
 	lwz	r2,GPR2(r1)
 	REST_4GPRS(3, r1)
@@ -900,6 +972,10 @@ do_work:			/* r10 contains MSR_KERNEL here */
 	beq	do_user_signal
 
 do_resched:			/* r10 contains MSR_KERNEL here */
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_on
+	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
+#endif
 	ori	r10,r10,MSR_EE
 	SYNC
 	MTMSRD(r10)		/* hard-enable interrupts */
@@ -908,6 +984,10 @@ recheck:
 	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
 	SYNC
 	MTMSRD(r10)		/* disable interrupts */
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_off
+	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
+#endif
 	rlwinm	r9,r1,0,0,(31-THREAD_SHIFT)
 	lwz	r9,TI_FLAGS(r9)
 	andi.	r0,r9,_TIF_NEED_RESCHED
@@ -915,6 +995,10 @@ recheck:
 	andi.	r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK
 	beq	restore_user
 do_user_signal:			/* r10 contains MSR_KERNEL here */
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_on
+	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
+#endif
 	ori	r10,r10,MSR_EE
 	SYNC
 	MTMSRD(r10)		/* hard-enable interrupts */
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index cd870a8..725dd18 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -120,6 +120,8 @@ unsigned long __init early_init(unsigned long dt_ptr)
  */
 void __init machine_init(unsigned long dt_ptr, unsigned long phys)
 {
+	lockdep_init();
+
 	/* Enable early debugging if any specified (see udbg.h) */
 	udbg_early_init();
 
diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
index ad8c9f7..a5f347a 100644
--- a/include/asm-powerpc/hw_irq.h
+++ b/include/asm-powerpc/hw_irq.h
@@ -63,13 +63,13 @@ extern void iseries_handle_interrupts(void);
 
 #if defined(CONFIG_BOOKE)
 #define SET_MSR_EE(x)	mtmsr(x)
-#define local_irq_restore(flags)	__asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
+#define raw_local_irq_restore(flags)	__asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
 #else
 #define SET_MSR_EE(x)	mtmsr(x)
-#define local_irq_restore(flags)	mtmsr(flags)
+#define raw_local_irq_restore(flags)	mtmsr(flags)
 #endif
 
-static inline void local_irq_disable(void)
+static inline void raw_local_irq_disable(void)
 {
 #ifdef CONFIG_BOOKE
 	__asm__ __volatile__("wrteei 0": : :"memory");
@@ -81,7 +81,7 @@ static inline void local_irq_disable(void)
 #endif
 }
 
-static inline void local_irq_enable(void)
+static inline void raw_local_irq_enable(void)
 {
 #ifdef CONFIG_BOOKE
 	__asm__ __volatile__("wrteei 1": : :"memory");
@@ -93,7 +93,7 @@ static inline void local_irq_enable(void)
 #endif
 }
 
-static inline void local_irq_save_ptr(unsigned long *flags)
+static inline void raw_local_irq_save_ptr(unsigned long *flags)
 {
 	unsigned long msr;
 	msr = mfmsr();
@@ -106,12 +106,12 @@ static inline void local_irq_save_ptr(unsigned long *flags)
 	__asm__ __volatile__("": : :"memory");
 }
 
-#define local_save_flags(flags)	((flags) = mfmsr())
-#define local_irq_save(flags)	local_irq_save_ptr(&flags)
-#define irqs_disabled()		((mfmsr() & MSR_EE) == 0)
+#define raw_local_save_flags(flags)	((flags) = mfmsr())
+#define raw_local_irq_save(flags)	raw_local_irq_save_ptr(&flags)
+#define raw_irqs_disabled()		((mfmsr() & MSR_EE) == 0)
+#define raw_irqs_disabled_flags(flags)	(((flags) & MSR_EE) == 0)
 
-#define hard_irq_enable()	local_irq_enable()
-#define hard_irq_disable()	local_irq_disable()
+#define hard_irq_disable()		raw_local_irq_disable()
 
 #endif /* CONFIG_PPC64 */
 
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
index 29552ff..e040a48 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -5,8 +5,7 @@
 #define _ASM_POWERPC_SYSTEM_H
 
 #include <linux/kernel.h>
-
-#include <asm/hw_irq.h>
+#include <linux/irqflags.h>
 
 /*
  * Memory barrier.
-- 
1.5.4

^ permalink raw reply related

* [PATCH 0/9 v2] powerpc: mv64x60 and prpmc2800 DTS cleanups
From: Dale Farnsworth @ 2008-04-07 18:32 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev

This series of patches again attempts to clean up and document
the Marvell MV64x60 device tree.  It supersedes Mark Greer's
series posted on 11 December 2007.  See:
http://ozlabs.org/pipermail/linuxppc-dev/2007-December/047986.html

These apply on the powerpc-next branch, and I'd like to get them
into 2.6.26.

This revision changes the name of the mv64360 dts node to
"system-controller", and as a result changes the text added
to Documentation/powerpc/booting-without-of.txt

I believe all comments on the previous version of this series
have been addressed.

Thanks,
-Dale

^ 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