From patchwork Tue Jun 8 16:46:02 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Millbrandt X-Patchwork-Id: 55007 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from bilbo.ozlabs.org (localhost [127.0.0.1]) by ozlabs.org (Postfix) with ESMTP id D69B510094B for ; Wed, 9 Jun 2010 03:13:46 +1000 (EST) X-Greylist: delayed 352 seconds by postgrey-1.32 at bilbo; Wed, 09 Jun 2010 03:13:37 EST Received: from dekaexchange07.deka.local (mail.dekaresearch.com [208.65.175.196]) by ozlabs.org (Postfix) with ESMTP id A29AFB7D5B for ; Wed, 9 Jun 2010 03:13:37 +1000 (EST) Received: from localhost.localdomain (10.1.1.72) by dekaexchange07.deka.local (10.1.1.12) with Microsoft SMTP Server id 8.1.240.5; Tue, 8 Jun 2010 13:08:52 -0400 From: Eric Millbrandt To: Grant Likely Subject: [PATCH 2/2] sound/soc: mpc5200_psc_ac97: Use gpio pins for cold reset. Date: Tue, 8 Jun 2010 12:46:02 -0400 Message-ID: <1276015562-28928-3-git-send-email-emillbrandt@dekaresearch.com> X-Mailer: git-send-email 1.6.3.1 In-Reply-To: <1276015562-28928-2-git-send-email-emillbrandt@dekaresearch.com> References: <1276015562-28928-1-git-send-email-emillbrandt@dekaresearch.com> <1276015562-28928-2-git-send-email-emillbrandt@dekaresearch.com> MIME-Version: 1.0 Cc: Mark Brown , linuxppc-dev@lists.ozlabs.org, Eric Millbrandt X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org The implementation of the ac97 "cold" reset is flawed. If the sync and output lines are high when reset is asserted the attached ac97 device may go into test mode. Avoid this by reconfiguring the psc to gpio mode and generating the reset manually. Signed-off-by: Eric Millbrandt --- arch/powerpc/boot/dts/lite5200.dts | 3 + arch/powerpc/boot/dts/lite5200b.dts | 3 + arch/powerpc/boot/dts/pcm030.dts | 3 + arch/powerpc/boot/dts/pcm032.dts | 3 + sound/soc/fsl/mpc5200_dma.h | 5 ++ sound/soc/fsl/mpc5200_psc_ac97.c | 83 +++++++++++++++++++++++++++++++++-- 6 files changed, 96 insertions(+), 4 deletions(-) -- 1.6.3.1 This e-mail and the information, including any attachments, it contains are intended to be a confidential communication only to the person or entity to whom it is addressed and may contain information that is privileged. If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited. If you have received this communication in error, please immediately notify the sender and destroy the original message. Thank you. Please consider the environment before printing this email. diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts index 82ff2b1..cb4e49b 100644 --- a/arch/powerpc/boot/dts/lite5200.dts +++ b/arch/powerpc/boot/dts/lite5200.dts @@ -180,6 +180,9 @@ // compatible = "fsl,mpc5200-psc-ac97"; // cell-index = <1>; // reg = <0x2200 0x100>; + // gpios = <&gpio 7 0 /* AC97_1_RES */ + // &gpio_simple 29 0 /* AC97_1_SYNC */ + // &gpio_simple 31 0>; /* AC97_1_SDATA_OUT */ // interrupts = <2 2 0>; //}; diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts index e45a63b..1fb0ac7 100644 --- a/arch/powerpc/boot/dts/lite5200b.dts +++ b/arch/powerpc/boot/dts/lite5200b.dts @@ -184,6 +184,9 @@ // compatible = "fsl,mpc5200b-psc-ac97","fsl,mpc5200-psc-ac97"; // cell-index = <1>; // reg = <0x2200 0x100>; + // gpios = <&gpio 7 0 /* AC97_1_RES */ + // &gpio_simple 29 0 /* AC97_1_SYNC */ + // &gpio_simple 31 0>; /* AC97_1_SDATA_OUT */ // interrupts = <2 2 0>; //}; diff --git a/arch/powerpc/boot/dts/pcm030.dts b/arch/powerpc/boot/dts/pcm030.dts index 8a4ec30..0085e0f 100644 --- a/arch/powerpc/boot/dts/pcm030.dts +++ b/arch/powerpc/boot/dts/pcm030.dts @@ -189,6 +189,9 @@ compatible = "mpc5200b-psc-ac97","fsl,mpc5200b-psc-ac97"; cell-index = <0>; reg = <0x2000 0x100>; + gpios = <&gpio 7 0 /* AC97_1_RES */ + &gpio_simple 29 0 /* AC97_1_SYNC */ + &gpio_simple 31 0>; /* AC97_1_SDATA_OUT */ interrupts = <2 1 0>; }; diff --git a/arch/powerpc/boot/dts/pcm032.dts b/arch/powerpc/boot/dts/pcm032.dts index 85d857a..76f86d3 100644 --- a/arch/powerpc/boot/dts/pcm032.dts +++ b/arch/powerpc/boot/dts/pcm032.dts @@ -189,6 +189,9 @@ compatible = "fsl,mpc5200b-psc-ac97","fsl,mpc5200-psc-ac97"; cell-index = <0>; reg = <0x2000 0x100>; + gpios = <&gpio 7 0 /* AC97_1_RES */ + &gpio_simple 29 0 /* AC97_1_SYNC */ + &gpio_simple 31 0>; /* AC97_1_SDATA_OUT */ interrupts = <2 1 0>; }; diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h index 22208b3..9fb0248 100644 --- a/sound/soc/fsl/mpc5200_dma.h +++ b/sound/soc/fsl/mpc5200_dma.h @@ -61,6 +61,11 @@ struct psc_dma { int id; unsigned int slots; + /* gpio pins locations for cold reset */ + int reset_gpio; + int sync_gpio; + int out_gpio; + /* per-stream data */ struct psc_dma_stream playback; struct psc_dma_stream capture; diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index e2ee220..bbbf860 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -9,8 +9,10 @@ * published by the Free Software Foundation. */ +#include #include #include +#include #include #include @@ -20,12 +22,17 @@ #include #include +#include #include #include "mpc5200_dma.h" #include "mpc5200_psc_ac97.h" #define DRV_NAME "mpc5200-psc-ac97" +#define MPC52xx_GPIO_PSC1_MASK 0x7 +#define MPC52xx_GPIO_PSC2_MASK (0x7<<4) +#define MPC52xx_AC97_PSC1 0x2 +#define MPC52xx_AC97_PSC2 (0x2<<4) /* ALSA only supports a single AC97 device so static is recommend here */ static struct psc_dma *psc_dma; @@ -100,19 +107,69 @@ static void psc_ac97_warm_reset(struct snd_ac97 *ac97) { struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; + mutex_lock(&psc_dma->mutex); + out_be32(®s->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_AWR); udelay(3); out_be32(®s->sicr, psc_dma->sicr); + + mutex_unlock(&psc_dma->mutex); } static void psc_ac97_cold_reset(struct snd_ac97 *ac97) { struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; + u32 gpio_mux; + + mutex_lock(&psc_dma->mutex); + + /* Reconfigure pin-muxing to gpio */ + switch (psc_dma->id) { + case 0: + gpio_mux = MPC52xx_GPIO_PSC1_MASK; break; + case 1: + gpio_mux = MPC52xx_GPIO_PSC2_MASK; break; + default: + dev_err(psc_dma->dev, + "Unable to determine PSC, no cold-reset will be " + "performed\n"); + return; + } + + dev_err(psc_dma->dev, "cold reset\n"); + mpc52xx_write_port_config(~gpio_mux, 1); + + /* Assert cold reset */ + gpio_direction_output(psc_dma->sync_gpio, 0); + gpio_direction_output(psc_dma->out_gpio, 0); + gpio_direction_output(psc_dma->reset_gpio, 0); + + /* Notify the PSC that a cold reset is occurring */ + out_be32(®s->sicr, 0); + udelay(2); + + /* Deassert reset */ + gpio_direction_output(psc_dma->reset_gpio, 1); + msleep(1); + + /* Restore pin-muxing */ + switch (psc_dma->id) { + case 0: + gpio_mux = MPC52xx_AC97_PSC1; break; + case 1: + gpio_mux = MPC52xx_AC97_PSC2; break; + default: + return; + } + + mpc52xx_write_port_config(gpio_mux, 0); + + /* Restore the serial interface mode to AC97 */ + out_be32(®s->sicr, psc_dma->sicr); + out_8(®s->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); + + mutex_unlock(&psc_dma->mutex); - /* Do a cold reset */ - out_8(®s->op1, MPC52xx_PSC_OP_RES); - udelay(10); - out_8(®s->op0, MPC52xx_PSC_OP_RES); msleep(1); psc_ac97_warm_reset(ac97); } @@ -287,6 +344,24 @@ static int __devinit psc_ac97_of_probe(struct of_device *op, regs = psc_dma->psc_regs; ac97.private_data = psc_dma; + psc_dma->reset_gpio = of_get_gpio_flags(op->node, 0, NULL); + psc_dma->sync_gpio = of_get_gpio_flags(op->node, 1, NULL); + psc_dma->out_gpio = of_get_gpio_flags(op->node, 2, NULL); + if ((psc_dma->reset_gpio < 0) || + (psc_dma->sync_gpio < 0) || + (psc_dma->out_gpio < 0)) { + dev_err(&op->dev, "error: cannot get GPIO pins; " + "reset=%i sync=%i out=%i\n", + psc_dma->reset_gpio, + psc_dma->sync_gpio, + psc_dma->out_gpio); + return -ENODEV; + } + + gpio_request(psc_dma->reset_gpio, "psc_dma-reset"); + gpio_request(psc_dma->sync_gpio, "psc_dma-sync"); + gpio_request(psc_dma->out_gpio, "psc_dma-out"); + for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++) psc_ac97_dai[i].private_data = psc_dma;