Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 1 | /* |
| 2 | * |
| 3 | * Utility functions for the Freescale MPC52xx. |
| 4 | * |
| 5 | * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com> |
| 6 | * |
| 7 | * This file is licensed under the terms of the GNU General Public License |
| 8 | * version 2. This program is licensed "as is" without any warranty of any |
| 9 | * kind, whether express or implied. |
| 10 | * |
| 11 | */ |
| 12 | |
| 13 | #undef DEBUG |
| 14 | |
Eric Millbrandt | cfa6a88 | 2010-08-06 20:49:18 -0600 | [diff] [blame] | 15 | #include <linux/gpio.h> |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 16 | #include <linux/kernel.h> |
Grant Likely | c8004a2 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 17 | #include <linux/spinlock.h> |
Grant Likely | 9fe2e79 | 2007-10-10 09:52:00 -0600 | [diff] [blame] | 18 | #include <linux/of_platform.h> |
Eric Millbrandt | cfa6a88 | 2010-08-06 20:49:18 -0600 | [diff] [blame] | 19 | #include <linux/of_gpio.h> |
Paul Gortmaker | 66b15db | 2011-05-27 10:46:24 -0400 | [diff] [blame] | 20 | #include <linux/export.h> |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 21 | #include <asm/io.h> |
| 22 | #include <asm/prom.h> |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 23 | #include <asm/mpc52xx.h> |
| 24 | |
Grant Likely | 66ffbe4 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 25 | /* MPC5200 device tree match tables */ |
Uwe Kleine-König | ce6d73c | 2014-09-10 21:56:38 +0200 | [diff] [blame] | 26 | static const struct of_device_id mpc52xx_xlb_ids[] __initconst = { |
Grant Likely | 66ffbe4 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 27 | { .compatible = "fsl,mpc5200-xlb", }, |
| 28 | { .compatible = "mpc5200-xlb", }, |
| 29 | {} |
| 30 | }; |
Uwe Kleine-König | ce6d73c | 2014-09-10 21:56:38 +0200 | [diff] [blame] | 31 | static const struct of_device_id mpc52xx_bus_ids[] __initconst = { |
Grant Likely | 66ffbe4 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 32 | { .compatible = "fsl,mpc5200-immr", }, |
| 33 | { .compatible = "fsl,mpc5200b-immr", }, |
Grant Likely | aafbf16 | 2009-02-26 23:19:36 -0700 | [diff] [blame] | 34 | { .compatible = "simple-bus", }, |
Grant Likely | 66ffbe4 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 35 | |
| 36 | /* depreciated matches; shouldn't be used in new device trees */ |
Grant Likely | aafbf16 | 2009-02-26 23:19:36 -0700 | [diff] [blame] | 37 | { .compatible = "fsl,lpb", }, |
Grant Likely | 66ffbe4 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 38 | { .type = "builtin", .compatible = "mpc5200", }, /* efika */ |
| 39 | { .type = "soc", .compatible = "mpc5200", }, /* lite5200 */ |
| 40 | {} |
| 41 | }; |
| 42 | |
Marian Balakowicz | 86b92cd | 2007-10-19 04:44:33 +1000 | [diff] [blame] | 43 | /* |
| 44 | * This variable is mapped in mpc52xx_map_wdt() and used in mpc52xx_restart(). |
| 45 | * Permanent mapping is required because mpc52xx_restart() can be called |
| 46 | * from interrupt context while node mapping (which calls ioremap()) |
| 47 | * cannot be used at such point. |
| 48 | */ |
Julia Lawall | 2701a1a | 2008-12-25 04:33:34 +0000 | [diff] [blame] | 49 | static DEFINE_SPINLOCK(mpc52xx_lock); |
Grant Likely | c8004a2 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 50 | static struct mpc52xx_gpt __iomem *mpc52xx_wdt; |
| 51 | static struct mpc52xx_cdm __iomem *mpc52xx_cdm; |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 52 | |
Grant Likely | 4de3b99 | 2007-10-09 14:45:28 -0600 | [diff] [blame] | 53 | /* |
| 54 | * Configure the XLB arbiter settings to match what Linux expects. |
| 55 | */ |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 56 | void __init |
Grant Likely | 4de3b99 | 2007-10-09 14:45:28 -0600 | [diff] [blame] | 57 | mpc5200_setup_xlb_arbiter(void) |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 58 | { |
Grant Likely | 75ca399 | 2008-01-18 09:30:37 -0700 | [diff] [blame] | 59 | struct device_node *np; |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 60 | struct mpc52xx_xlb __iomem *xlb; |
| 61 | |
Grant Likely | 66ffbe4 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 62 | np = of_find_matching_node(NULL, mpc52xx_xlb_ids); |
Grant Likely | 75ca399 | 2008-01-18 09:30:37 -0700 | [diff] [blame] | 63 | xlb = of_iomap(np, 0); |
| 64 | of_node_put(np); |
Grant Likely | 4de3b99 | 2007-10-09 14:45:28 -0600 | [diff] [blame] | 65 | if (!xlb) { |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 66 | printk(KERN_ERR __FILE__ ": " |
Wolfram Sang | f43c32e | 2008-10-08 11:36:21 -0600 | [diff] [blame] | 67 | "Error mapping XLB in mpc52xx_setup_cpu(). " |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 68 | "Expect some abnormal behavior\n"); |
Grant Likely | 4de3b99 | 2007-10-09 14:45:28 -0600 | [diff] [blame] | 69 | return; |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 70 | } |
| 71 | |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 72 | /* Configure the XLB Arbiter priorities */ |
| 73 | out_be32(&xlb->master_pri_enable, 0xff); |
| 74 | out_be32(&xlb->master_priority, 0x11111111); |
| 75 | |
Wolfram Sang | 9629095 | 2008-10-15 11:09:59 -0600 | [diff] [blame] | 76 | /* |
| 77 | * Disable XLB pipelining |
Grant Likely | 4de3b99 | 2007-10-09 14:45:28 -0600 | [diff] [blame] | 78 | * (cfr errate 292. We could do this only just before ATA PIO |
| 79 | * transaction and re-enable it afterwards ...) |
Wolfram Sang | 9629095 | 2008-10-15 11:09:59 -0600 | [diff] [blame] | 80 | * Not needed on MPC5200B. |
Grant Likely | 4de3b99 | 2007-10-09 14:45:28 -0600 | [diff] [blame] | 81 | */ |
Wolfram Sang | 9629095 | 2008-10-15 11:09:59 -0600 | [diff] [blame] | 82 | if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR) |
| 83 | out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS); |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 84 | |
Grant Likely | 4de3b99 | 2007-10-09 14:45:28 -0600 | [diff] [blame] | 85 | iounmap(xlb); |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 86 | } |
| 87 | |
Eric Millbrandt | cfa6a88 | 2010-08-06 20:49:18 -0600 | [diff] [blame] | 88 | /* |
| 89 | * This variable is mapped in mpc52xx_map_common_devices and |
| 90 | * used in mpc5200_psc_ac97_gpio_reset(). |
| 91 | */ |
| 92 | static DEFINE_SPINLOCK(gpio_lock); |
| 93 | struct mpc52xx_gpio __iomem *simple_gpio; |
| 94 | struct mpc52xx_gpio_wkup __iomem *wkup_gpio; |
| 95 | |
Grant Likely | 66ffbe4 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 96 | /** |
| 97 | * mpc52xx_declare_of_platform_devices: register internal devices and children |
| 98 | * of the localplus bus to the of_platform |
| 99 | * bus. |
| 100 | */ |
Grant Likely | ff65151 | 2011-06-21 08:45:13 +0000 | [diff] [blame] | 101 | void __init mpc52xx_declare_of_platform_devices(void) |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 102 | { |
Grant Likely | ff65151 | 2011-06-21 08:45:13 +0000 | [diff] [blame] | 103 | /* Find all the 'platform' devices and register them. */ |
| 104 | if (of_platform_populate(NULL, mpc52xx_bus_ids, NULL, NULL)) |
| 105 | pr_err(__FILE__ ": Error while populating devices from DT\n"); |
Grant Likely | 6065170 | 2006-11-27 14:16:27 -0700 | [diff] [blame] | 106 | } |
| 107 | |
Grant Likely | 66ffbe4 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 108 | /* |
Grant Likely | c8004a2 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 109 | * match tables used by mpc52xx_map_common_devices() |
Grant Likely | 66ffbe4 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 110 | */ |
Uwe Kleine-König | ce6d73c | 2014-09-10 21:56:38 +0200 | [diff] [blame] | 111 | static const struct of_device_id mpc52xx_gpt_ids[] __initconst = { |
Grant Likely | 66ffbe4 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 112 | { .compatible = "fsl,mpc5200-gpt", }, |
| 113 | { .compatible = "mpc5200-gpt", }, /* old */ |
| 114 | {} |
| 115 | }; |
Uwe Kleine-König | ce6d73c | 2014-09-10 21:56:38 +0200 | [diff] [blame] | 116 | static const struct of_device_id mpc52xx_cdm_ids[] __initconst = { |
Grant Likely | c8004a2 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 117 | { .compatible = "fsl,mpc5200-cdm", }, |
| 118 | { .compatible = "mpc5200-cdm", }, /* old */ |
| 119 | {} |
| 120 | }; |
Uwe Kleine-König | ce6d73c | 2014-09-10 21:56:38 +0200 | [diff] [blame] | 121 | static const struct of_device_id mpc52xx_gpio_simple[] __initconst = { |
Eric Millbrandt | cfa6a88 | 2010-08-06 20:49:18 -0600 | [diff] [blame] | 122 | { .compatible = "fsl,mpc5200-gpio", }, |
| 123 | {} |
| 124 | }; |
Uwe Kleine-König | ce6d73c | 2014-09-10 21:56:38 +0200 | [diff] [blame] | 125 | static const struct of_device_id mpc52xx_gpio_wkup[] __initconst = { |
Eric Millbrandt | cfa6a88 | 2010-08-06 20:49:18 -0600 | [diff] [blame] | 126 | { .compatible = "fsl,mpc5200-gpio-wkup", }, |
| 127 | {} |
| 128 | }; |
| 129 | |
Grant Likely | 66ffbe4 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 130 | |
Grant Likely | c8004a2 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 131 | /** |
| 132 | * mpc52xx_map_common_devices: iomap devices required by common code |
| 133 | */ |
Marian Balakowicz | 86b92cd | 2007-10-19 04:44:33 +1000 | [diff] [blame] | 134 | void __init |
Grant Likely | c8004a2 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 135 | mpc52xx_map_common_devices(void) |
Marian Balakowicz | 86b92cd | 2007-10-19 04:44:33 +1000 | [diff] [blame] | 136 | { |
Marian Balakowicz | 86b92cd | 2007-10-19 04:44:33 +1000 | [diff] [blame] | 137 | struct device_node *np; |
Grant Likely | c8004a2 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 138 | |
Marian Balakowicz | 86b92cd | 2007-10-19 04:44:33 +1000 | [diff] [blame] | 139 | /* mpc52xx_wdt is mapped here and used in mpc52xx_restart, |
| 140 | * possibly from a interrupt context. wdt is only implement |
| 141 | * on a gpt0, so check has-wdt property before mapping. |
| 142 | */ |
Grant Likely | 66ffbe4 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 143 | for_each_matching_node(np, mpc52xx_gpt_ids) { |
| 144 | if (of_get_property(np, "fsl,has-wdt", NULL) || |
| 145 | of_get_property(np, "has-wdt", NULL)) { |
Grant Likely | 75ca399 | 2008-01-18 09:30:37 -0700 | [diff] [blame] | 146 | mpc52xx_wdt = of_iomap(np, 0); |
| 147 | of_node_put(np); |
Grant Likely | c8004a2 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 148 | break; |
Marian Balakowicz | 86b92cd | 2007-10-19 04:44:33 +1000 | [diff] [blame] | 149 | } |
| 150 | } |
Grant Likely | c8004a2 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 151 | |
| 152 | /* Clock Distribution Module, used by PSC clock setting function */ |
| 153 | np = of_find_matching_node(NULL, mpc52xx_cdm_ids); |
| 154 | mpc52xx_cdm = of_iomap(np, 0); |
| 155 | of_node_put(np); |
Eric Millbrandt | cfa6a88 | 2010-08-06 20:49:18 -0600 | [diff] [blame] | 156 | |
| 157 | /* simple_gpio registers */ |
| 158 | np = of_find_matching_node(NULL, mpc52xx_gpio_simple); |
| 159 | simple_gpio = of_iomap(np, 0); |
| 160 | of_node_put(np); |
| 161 | |
| 162 | /* wkup_gpio registers */ |
| 163 | np = of_find_matching_node(NULL, mpc52xx_gpio_wkup); |
| 164 | wkup_gpio = of_iomap(np, 0); |
| 165 | of_node_put(np); |
Marian Balakowicz | 86b92cd | 2007-10-19 04:44:33 +1000 | [diff] [blame] | 166 | } |
| 167 | |
Grant Likely | c8004a2 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 168 | /** |
| 169 | * mpc52xx_set_psc_clkdiv: Set clock divider in the CDM for PSC ports |
| 170 | * |
| 171 | * @psc_id: id of psc port; must be 1,2,3 or 6 |
| 172 | * @clkdiv: clock divider value to put into CDM PSC register. |
| 173 | */ |
| 174 | int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv) |
| 175 | { |
| 176 | unsigned long flags; |
| 177 | u16 __iomem *reg; |
| 178 | u32 val; |
| 179 | u32 mask; |
| 180 | u32 mclken_div; |
| 181 | |
| 182 | if (!mpc52xx_cdm) |
| 183 | return -ENODEV; |
| 184 | |
| 185 | mclken_div = 0x8000 | (clkdiv & 0x1FF); |
| 186 | switch (psc_id) { |
| 187 | case 1: reg = &mpc52xx_cdm->mclken_div_psc1; mask = 0x20; break; |
| 188 | case 2: reg = &mpc52xx_cdm->mclken_div_psc2; mask = 0x40; break; |
| 189 | case 3: reg = &mpc52xx_cdm->mclken_div_psc3; mask = 0x80; break; |
| 190 | case 6: reg = &mpc52xx_cdm->mclken_div_psc6; mask = 0x10; break; |
| 191 | default: |
| 192 | return -ENODEV; |
| 193 | } |
| 194 | |
| 195 | /* Set the rate and enable the clock */ |
| 196 | spin_lock_irqsave(&mpc52xx_lock, flags); |
| 197 | out_be16(reg, mclken_div); |
| 198 | val = in_be32(&mpc52xx_cdm->clk_enables); |
| 199 | out_be32(&mpc52xx_cdm->clk_enables, val | mask); |
| 200 | spin_unlock_irqrestore(&mpc52xx_lock, flags); |
| 201 | |
| 202 | return 0; |
| 203 | } |
Eric Dujardin | 4187377 | 2008-02-23 22:51:28 -0700 | [diff] [blame] | 204 | EXPORT_SYMBOL(mpc52xx_set_psc_clkdiv); |
Grant Likely | c8004a2 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 205 | |
| 206 | /** |
Wolfgang Grandegger | df8a95f | 2009-03-11 09:36:26 -0600 | [diff] [blame] | 207 | * mpc52xx_get_xtal_freq - Get SYS_XTAL_IN frequency for a device |
| 208 | * |
| 209 | * @node: device node |
| 210 | * |
| 211 | * Returns the frequency of the external oscillator clock connected |
| 212 | * to the SYS_XTAL_IN pin, or 0 if it cannot be determined. |
| 213 | */ |
| 214 | unsigned int mpc52xx_get_xtal_freq(struct device_node *node) |
| 215 | { |
| 216 | u32 val; |
| 217 | unsigned int freq; |
| 218 | |
| 219 | if (!mpc52xx_cdm) |
| 220 | return 0; |
| 221 | |
Wolfgang Denk | 87c441e | 2009-06-17 00:30:22 -0600 | [diff] [blame] | 222 | freq = mpc5xxx_get_bus_frequency(node); |
Wolfgang Grandegger | df8a95f | 2009-03-11 09:36:26 -0600 | [diff] [blame] | 223 | if (!freq) |
| 224 | return 0; |
| 225 | |
| 226 | if (in_8(&mpc52xx_cdm->ipb_clk_sel) & 0x1) |
| 227 | freq *= 2; |
| 228 | |
| 229 | val = in_be32(&mpc52xx_cdm->rstcfg); |
| 230 | if (val & (1 << 5)) |
| 231 | freq *= 8; |
| 232 | else |
| 233 | freq *= 4; |
| 234 | if (val & (1 << 6)) |
| 235 | freq /= 12; |
| 236 | else |
| 237 | freq /= 16; |
| 238 | |
| 239 | return freq; |
| 240 | } |
| 241 | EXPORT_SYMBOL(mpc52xx_get_xtal_freq); |
| 242 | |
| 243 | /** |
Grant Likely | c8004a2 | 2008-01-24 22:25:31 -0700 | [diff] [blame] | 244 | * mpc52xx_restart: ppc_md->restart hook for mpc5200 using the watchdog timer |
| 245 | */ |
Daniel Axtens | 95ec77c | 2016-07-12 10:54:52 +1000 | [diff] [blame] | 246 | void __noreturn mpc52xx_restart(char *cmd) |
Marian Balakowicz | 86b92cd | 2007-10-19 04:44:33 +1000 | [diff] [blame] | 247 | { |
| 248 | local_irq_disable(); |
| 249 | |
| 250 | /* Turn on the watchdog and wait for it to expire. |
| 251 | * It effectively does a reset. */ |
| 252 | if (mpc52xx_wdt) { |
| 253 | out_be32(&mpc52xx_wdt->mode, 0x00000000); |
| 254 | out_be32(&mpc52xx_wdt->count, 0x000000ff); |
| 255 | out_be32(&mpc52xx_wdt->mode, 0x00009004); |
| 256 | } else |
Wolfram Sang | f43c32e | 2008-10-08 11:36:21 -0600 | [diff] [blame] | 257 | printk(KERN_ERR __FILE__ ": " |
| 258 | "mpc52xx_restart: Can't access wdt. " |
Marian Balakowicz | 86b92cd | 2007-10-19 04:44:33 +1000 | [diff] [blame] | 259 | "Restart impossible, system halted.\n"); |
| 260 | |
| 261 | while (1); |
| 262 | } |
Eric Millbrandt | cfa6a88 | 2010-08-06 20:49:18 -0600 | [diff] [blame] | 263 | |
| 264 | #define PSC1_RESET 0x1 |
| 265 | #define PSC1_SYNC 0x4 |
| 266 | #define PSC1_SDATA_OUT 0x1 |
| 267 | #define PSC2_RESET 0x2 |
| 268 | #define PSC2_SYNC (0x4<<4) |
| 269 | #define PSC2_SDATA_OUT (0x1<<4) |
| 270 | #define MPC52xx_GPIO_PSC1_MASK 0x7 |
| 271 | #define MPC52xx_GPIO_PSC2_MASK (0x7<<4) |
| 272 | |
| 273 | /** |
| 274 | * mpc5200_psc_ac97_gpio_reset: Use gpio pins to reset the ac97 bus |
| 275 | * |
| 276 | * @psc: psc number to reset (only psc 1 and 2 support ac97) |
| 277 | */ |
| 278 | int mpc5200_psc_ac97_gpio_reset(int psc_number) |
| 279 | { |
| 280 | unsigned long flags; |
| 281 | u32 gpio; |
| 282 | u32 mux; |
| 283 | int out; |
| 284 | int reset; |
| 285 | int sync; |
| 286 | |
| 287 | if ((!simple_gpio) || (!wkup_gpio)) |
| 288 | return -ENODEV; |
| 289 | |
| 290 | switch (psc_number) { |
| 291 | case 0: |
| 292 | reset = PSC1_RESET; /* AC97_1_RES */ |
| 293 | sync = PSC1_SYNC; /* AC97_1_SYNC */ |
| 294 | out = PSC1_SDATA_OUT; /* AC97_1_SDATA_OUT */ |
| 295 | gpio = MPC52xx_GPIO_PSC1_MASK; |
| 296 | break; |
| 297 | case 1: |
| 298 | reset = PSC2_RESET; /* AC97_2_RES */ |
| 299 | sync = PSC2_SYNC; /* AC97_2_SYNC */ |
| 300 | out = PSC2_SDATA_OUT; /* AC97_2_SDATA_OUT */ |
| 301 | gpio = MPC52xx_GPIO_PSC2_MASK; |
| 302 | break; |
| 303 | default: |
| 304 | pr_err(__FILE__ ": Unable to determine PSC, no ac97 " |
| 305 | "cold-reset will be performed\n"); |
| 306 | return -ENODEV; |
| 307 | } |
| 308 | |
| 309 | spin_lock_irqsave(&gpio_lock, flags); |
| 310 | |
| 311 | /* Reconfiure pin-muxing to gpio */ |
| 312 | mux = in_be32(&simple_gpio->port_config); |
| 313 | out_be32(&simple_gpio->port_config, mux & (~gpio)); |
| 314 | |
| 315 | /* enable gpio pins for output */ |
| 316 | setbits8(&wkup_gpio->wkup_gpioe, reset); |
| 317 | setbits32(&simple_gpio->simple_gpioe, sync | out); |
| 318 | |
| 319 | setbits8(&wkup_gpio->wkup_ddr, reset); |
| 320 | setbits32(&simple_gpio->simple_ddr, sync | out); |
| 321 | |
| 322 | /* Assert cold reset */ |
| 323 | clrbits32(&simple_gpio->simple_dvo, sync | out); |
| 324 | clrbits8(&wkup_gpio->wkup_dvo, reset); |
| 325 | |
Eric Millbrandt | fa32154 | 2010-09-03 13:27:38 -0400 | [diff] [blame] | 326 | /* wait for 1 us */ |
| 327 | udelay(1); |
Eric Millbrandt | cfa6a88 | 2010-08-06 20:49:18 -0600 | [diff] [blame] | 328 | |
| 329 | /* Deassert reset */ |
| 330 | setbits8(&wkup_gpio->wkup_dvo, reset); |
| 331 | |
Eric Millbrandt | fa32154 | 2010-09-03 13:27:38 -0400 | [diff] [blame] | 332 | /* wait at least 200ns */ |
| 333 | /* 7 ~= (200ns * timebase) / ns2sec */ |
| 334 | __delay(7); |
| 335 | |
Eric Millbrandt | cfa6a88 | 2010-08-06 20:49:18 -0600 | [diff] [blame] | 336 | /* Restore pin-muxing */ |
| 337 | out_be32(&simple_gpio->port_config, mux); |
| 338 | |
| 339 | spin_unlock_irqrestore(&gpio_lock, flags); |
| 340 | |
| 341 | return 0; |
| 342 | } |
| 343 | EXPORT_SYMBOL(mpc5200_psc_ac97_gpio_reset); |