aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/mpc52xx.h1
-rw-r--r--arch/powerpc/include/asm/mpc52xx_psc.h1
-rw-r--r--arch/powerpc/kernel/setup-common.c2
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_common.c106
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c22
5 files changed, 128 insertions, 4 deletions
diff --git a/arch/powerpc/include/asm/mpc52xx.h b/arch/powerpc/include/asm/mpc52xx.h
index b664ce79a172..1f41382eda38 100644
--- a/arch/powerpc/include/asm/mpc52xx.h
+++ b/arch/powerpc/include/asm/mpc52xx.h
@@ -271,6 +271,7 @@ struct mpc52xx_intr {
271/* mpc52xx_common.c */ 271/* mpc52xx_common.c */
272extern void mpc5200_setup_xlb_arbiter(void); 272extern void mpc5200_setup_xlb_arbiter(void);
273extern void mpc52xx_declare_of_platform_devices(void); 273extern void mpc52xx_declare_of_platform_devices(void);
274extern int mpc5200_psc_ac97_gpio_reset(int psc_number);
274extern void mpc52xx_map_common_devices(void); 275extern void mpc52xx_map_common_devices(void);
275extern int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv); 276extern int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv);
276extern unsigned int mpc52xx_get_xtal_freq(struct device_node *node); 277extern unsigned int mpc52xx_get_xtal_freq(struct device_node *node);
diff --git a/arch/powerpc/include/asm/mpc52xx_psc.h b/arch/powerpc/include/asm/mpc52xx_psc.h
index ecc4fc69ac13..2966df604221 100644
--- a/arch/powerpc/include/asm/mpc52xx_psc.h
+++ b/arch/powerpc/include/asm/mpc52xx_psc.h
@@ -131,6 +131,7 @@
131#define MPC52xx_PSC_SICR_SIM_FIR (0x6 << 24) 131#define MPC52xx_PSC_SICR_SIM_FIR (0x6 << 24)
132#define MPC52xx_PSC_SICR_SIM_CODEC_24 (0x7 << 24) 132#define MPC52xx_PSC_SICR_SIM_CODEC_24 (0x7 << 24)
133#define MPC52xx_PSC_SICR_SIM_CODEC_32 (0xf << 24) 133#define MPC52xx_PSC_SICR_SIM_CODEC_32 (0xf << 24)
134#define MPC52xx_PSC_SICR_ACRB (0x8 << 24)
134#define MPC52xx_PSC_SICR_AWR (1 << 30) 135#define MPC52xx_PSC_SICR_AWR (1 << 30)
135#define MPC52xx_PSC_SICR_GENCLK (1 << 23) 136#define MPC52xx_PSC_SICR_GENCLK (1 << 23)
136#define MPC52xx_PSC_SICR_I2S (1 << 22) 137#define MPC52xx_PSC_SICR_I2S (1 << 22)
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 15ade0d7bbb2..9d4882a46647 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -96,7 +96,9 @@ struct screen_info screen_info = {
96 96
97/* Variables required to store legacy IO irq routing */ 97/* Variables required to store legacy IO irq routing */
98int of_i8042_kbd_irq; 98int of_i8042_kbd_irq;
99EXPORT_SYMBOL_GPL(of_i8042_kbd_irq);
99int of_i8042_aux_irq; 100int of_i8042_aux_irq;
101EXPORT_SYMBOL_GPL(of_i8042_aux_irq);
100 102
101#ifdef __DO_IRQ_CANON 103#ifdef __DO_IRQ_CANON
102/* XXX should go elsewhere eventually */ 104/* XXX should go elsewhere eventually */
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index a46bad0c2339..6e905314ad5d 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -12,9 +12,11 @@
12 12
13#undef DEBUG 13#undef DEBUG
14 14
15#include <linux/gpio.h>
15#include <linux/kernel.h> 16#include <linux/kernel.h>
16#include <linux/spinlock.h> 17#include <linux/spinlock.h>
17#include <linux/of_platform.h> 18#include <linux/of_platform.h>
19#include <linux/of_gpio.h>
18#include <asm/io.h> 20#include <asm/io.h>
19#include <asm/prom.h> 21#include <asm/prom.h>
20#include <asm/mpc52xx.h> 22#include <asm/mpc52xx.h>
@@ -82,6 +84,14 @@ mpc5200_setup_xlb_arbiter(void)
82 iounmap(xlb); 84 iounmap(xlb);
83} 85}
84 86
87/*
88 * This variable is mapped in mpc52xx_map_common_devices and
89 * used in mpc5200_psc_ac97_gpio_reset().
90 */
91static DEFINE_SPINLOCK(gpio_lock);
92struct mpc52xx_gpio __iomem *simple_gpio;
93struct mpc52xx_gpio_wkup __iomem *wkup_gpio;
94
85/** 95/**
86 * mpc52xx_declare_of_platform_devices: register internal devices and children 96 * mpc52xx_declare_of_platform_devices: register internal devices and children
87 * of the localplus bus to the of_platform 97 * of the localplus bus to the of_platform
@@ -109,6 +119,15 @@ static struct of_device_id mpc52xx_cdm_ids[] __initdata = {
109 { .compatible = "mpc5200-cdm", }, /* old */ 119 { .compatible = "mpc5200-cdm", }, /* old */
110 {} 120 {}
111}; 121};
122static const struct of_device_id mpc52xx_gpio_simple[] = {
123 { .compatible = "fsl,mpc5200-gpio", },
124 {}
125};
126static const struct of_device_id mpc52xx_gpio_wkup[] = {
127 { .compatible = "fsl,mpc5200-gpio-wkup", },
128 {}
129};
130
112 131
113/** 132/**
114 * mpc52xx_map_common_devices: iomap devices required by common code 133 * mpc52xx_map_common_devices: iomap devices required by common code
@@ -135,6 +154,16 @@ mpc52xx_map_common_devices(void)
135 np = of_find_matching_node(NULL, mpc52xx_cdm_ids); 154 np = of_find_matching_node(NULL, mpc52xx_cdm_ids);
136 mpc52xx_cdm = of_iomap(np, 0); 155 mpc52xx_cdm = of_iomap(np, 0);
137 of_node_put(np); 156 of_node_put(np);
157
158 /* simple_gpio registers */
159 np = of_find_matching_node(NULL, mpc52xx_gpio_simple);
160 simple_gpio = of_iomap(np, 0);
161 of_node_put(np);
162
163 /* wkup_gpio registers */
164 np = of_find_matching_node(NULL, mpc52xx_gpio_wkup);
165 wkup_gpio = of_iomap(np, 0);
166 of_node_put(np);
138} 167}
139 168
140/** 169/**
@@ -233,3 +262,80 @@ mpc52xx_restart(char *cmd)
233 262
234 while (1); 263 while (1);
235} 264}
265
266#define PSC1_RESET 0x1
267#define PSC1_SYNC 0x4
268#define PSC1_SDATA_OUT 0x1
269#define PSC2_RESET 0x2
270#define PSC2_SYNC (0x4<<4)
271#define PSC2_SDATA_OUT (0x1<<4)
272#define MPC52xx_GPIO_PSC1_MASK 0x7
273#define MPC52xx_GPIO_PSC2_MASK (0x7<<4)
274
275/**
276 * mpc5200_psc_ac97_gpio_reset: Use gpio pins to reset the ac97 bus
277 *
278 * @psc: psc number to reset (only psc 1 and 2 support ac97)
279 */
280int mpc5200_psc_ac97_gpio_reset(int psc_number)
281{
282 unsigned long flags;
283 u32 gpio;
284 u32 mux;
285 int out;
286 int reset;
287 int sync;
288
289 if ((!simple_gpio) || (!wkup_gpio))
290 return -ENODEV;
291
292 switch (psc_number) {
293 case 0:
294 reset = PSC1_RESET; /* AC97_1_RES */
295 sync = PSC1_SYNC; /* AC97_1_SYNC */
296 out = PSC1_SDATA_OUT; /* AC97_1_SDATA_OUT */
297 gpio = MPC52xx_GPIO_PSC1_MASK;
298 break;
299 case 1:
300 reset = PSC2_RESET; /* AC97_2_RES */
301 sync = PSC2_SYNC; /* AC97_2_SYNC */
302 out = PSC2_SDATA_OUT; /* AC97_2_SDATA_OUT */
303 gpio = MPC52xx_GPIO_PSC2_MASK;
304 break;
305 default:
306 pr_err(__FILE__ ": Unable to determine PSC, no ac97 "
307 "cold-reset will be performed\n");
308 return -ENODEV;
309 }
310
311 spin_lock_irqsave(&gpio_lock, flags);
312
313 /* Reconfiure pin-muxing to gpio */
314 mux = in_be32(&simple_gpio->port_config);
315 out_be32(&simple_gpio->port_config, mux & (~gpio));
316
317 /* enable gpio pins for output */
318 setbits8(&wkup_gpio->wkup_gpioe, reset);
319 setbits32(&simple_gpio->simple_gpioe, sync | out);
320
321 setbits8(&wkup_gpio->wkup_ddr, reset);
322 setbits32(&simple_gpio->simple_ddr, sync | out);
323
324 /* Assert cold reset */
325 clrbits32(&simple_gpio->simple_dvo, sync | out);
326 clrbits8(&wkup_gpio->wkup_dvo, reset);
327
328 /* wait at lease 1 us */
329 udelay(2);
330
331 /* Deassert reset */
332 setbits8(&wkup_gpio->wkup_dvo, reset);
333
334 /* Restore pin-muxing */
335 out_be32(&simple_gpio->port_config, mux);
336
337 spin_unlock_irqrestore(&gpio_lock, flags);
338
339 return 0;
340}
341EXPORT_SYMBOL(mpc5200_psc_ac97_gpio_reset);
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index e2ee220bfb7e..e7f5d50ed084 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -20,6 +20,7 @@
20 20
21#include <asm/time.h> 21#include <asm/time.h>
22#include <asm/delay.h> 22#include <asm/delay.h>
23#include <asm/mpc52xx.h>
23#include <asm/mpc52xx_psc.h> 24#include <asm/mpc52xx_psc.h>
24 25
25#include "mpc5200_dma.h" 26#include "mpc5200_dma.h"
@@ -100,19 +101,32 @@ static void psc_ac97_warm_reset(struct snd_ac97 *ac97)
100{ 101{
101 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; 102 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
102 103
104 mutex_lock(&psc_dma->mutex);
105
103 out_be32(&regs->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_AWR); 106 out_be32(&regs->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_AWR);
104 udelay(3); 107 udelay(3);
105 out_be32(&regs->sicr, psc_dma->sicr); 108 out_be32(&regs->sicr, psc_dma->sicr);
109
110 mutex_unlock(&psc_dma->mutex);
106} 111}
107 112
108static void psc_ac97_cold_reset(struct snd_ac97 *ac97) 113static void psc_ac97_cold_reset(struct snd_ac97 *ac97)
109{ 114{
110 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; 115 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
111 116
112 /* Do a cold reset */ 117 mutex_lock(&psc_dma->mutex);
113 out_8(&regs->op1, MPC52xx_PSC_OP_RES); 118 dev_dbg(psc_dma->dev, "cold reset\n");
114 udelay(10); 119
115 out_8(&regs->op0, MPC52xx_PSC_OP_RES); 120 mpc5200_psc_ac97_gpio_reset(psc_dma->id);
121
122 /* Notify the PSC that a reset has occurred */
123 out_be32(&regs->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_ACRB);
124
125 /* Re-enable RX and TX */
126 out_8(&regs->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
127
128 mutex_unlock(&psc_dma->mutex);
129
116 msleep(1); 130 msleep(1);
117 psc_ac97_warm_reset(ac97); 131 psc_ac97_warm_reset(ac97);
118} 132}