diff options
-rw-r--r-- | arch/powerpc/include/asm/mpc52xx.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/mpc52xx_psc.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup-common.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/52xx/mpc52xx_common.c | 106 | ||||
-rw-r--r-- | sound/soc/fsl/mpc5200_psc_ac97.c | 22 |
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 */ |
272 | extern void mpc5200_setup_xlb_arbiter(void); | 272 | extern void mpc5200_setup_xlb_arbiter(void); |
273 | extern void mpc52xx_declare_of_platform_devices(void); | 273 | extern void mpc52xx_declare_of_platform_devices(void); |
274 | extern int mpc5200_psc_ac97_gpio_reset(int psc_number); | ||
274 | extern void mpc52xx_map_common_devices(void); | 275 | extern void mpc52xx_map_common_devices(void); |
275 | extern int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv); | 276 | extern int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv); |
276 | extern unsigned int mpc52xx_get_xtal_freq(struct device_node *node); | 277 | extern 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 */ |
98 | int of_i8042_kbd_irq; | 98 | int of_i8042_kbd_irq; |
99 | EXPORT_SYMBOL_GPL(of_i8042_kbd_irq); | ||
99 | int of_i8042_aux_irq; | 100 | int of_i8042_aux_irq; |
101 | EXPORT_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 | */ | ||
91 | static DEFINE_SPINLOCK(gpio_lock); | ||
92 | struct mpc52xx_gpio __iomem *simple_gpio; | ||
93 | struct 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 | }; |
122 | static const struct of_device_id mpc52xx_gpio_simple[] = { | ||
123 | { .compatible = "fsl,mpc5200-gpio", }, | ||
124 | {} | ||
125 | }; | ||
126 | static 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 | */ | ||
280 | int 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 | } | ||
341 | EXPORT_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(®s->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_AWR); | 106 | out_be32(®s->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_AWR); |
104 | udelay(3); | 107 | udelay(3); |
105 | out_be32(®s->sicr, psc_dma->sicr); | 108 | out_be32(®s->sicr, psc_dma->sicr); |
109 | |||
110 | mutex_unlock(&psc_dma->mutex); | ||
106 | } | 111 | } |
107 | 112 | ||
108 | static void psc_ac97_cold_reset(struct snd_ac97 *ac97) | 113 | static 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(®s->op1, MPC52xx_PSC_OP_RES); | 118 | dev_dbg(psc_dma->dev, "cold reset\n"); |
114 | udelay(10); | 119 | |
115 | out_8(®s->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(®s->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_ACRB); | ||
124 | |||
125 | /* Re-enable RX and TX */ | ||
126 | out_8(®s->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 | } |