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); | ||
