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/platforms/52xx/mpc52xx_common.c | 106 |
3 files changed, 108 insertions, 0 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/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); | ||