linux/arch/powerpc/platforms/83xx/usb.c
<<
>>
Prefs
   1/*
   2 * Freescale 83xx USB SOC setup code
   3 *
   4 * Copyright (C) 2007 Freescale Semiconductor, Inc.
   5 * Author: Li Yang
   6 *
   7 * This program is free software; you can redistribute  it and/or modify it
   8 * under  the terms of  the GNU General  Public License as published by the
   9 * Free Software Foundation;  either version 2 of the  License, or (at your
  10 * option) any later version.
  11 */
  12
  13
  14#include <linux/stddef.h>
  15#include <linux/kernel.h>
  16#include <linux/errno.h>
  17#include <linux/of.h>
  18
  19#include <asm/io.h>
  20#include <asm/prom.h>
  21#include <sysdev/fsl_soc.h>
  22
  23#include "mpc83xx.h"
  24
  25
  26#ifdef CONFIG_PPC_MPC834x
  27int mpc834x_usb_cfg(void)
  28{
  29        unsigned long sccr, sicrl, sicrh;
  30        void __iomem *immap;
  31        struct device_node *np = NULL;
  32        int port0_is_dr = 0, port1_is_dr = 0;
  33        const void *prop, *dr_mode;
  34
  35        immap = ioremap(get_immrbase(), 0x1000);
  36        if (!immap)
  37                return -ENOMEM;
  38
  39        /* Read registers */
  40        /* Note: DR and MPH must use the same clock setting in SCCR */
  41        sccr = in_be32(immap + MPC83XX_SCCR_OFFS) & ~MPC83XX_SCCR_USB_MASK;
  42        sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK;
  43        sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI;
  44
  45        np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
  46        if (np) {
  47                sccr |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
  48
  49                prop = of_get_property(np, "phy_type", NULL);
  50                port1_is_dr = 1;
  51                if (prop && (!strcmp(prop, "utmi") ||
  52                                        !strcmp(prop, "utmi_wide"))) {
  53                        sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;
  54                        sicrh |= MPC834X_SICRH_USB_UTMI;
  55                        port0_is_dr = 1;
  56                } else if (prop && !strcmp(prop, "serial")) {
  57                        dr_mode = of_get_property(np, "dr_mode", NULL);
  58                        if (dr_mode && !strcmp(dr_mode, "otg")) {
  59                                sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;
  60                                port0_is_dr = 1;
  61                        } else {
  62                                sicrl |= MPC834X_SICRL_USB1;
  63                        }
  64                } else if (prop && !strcmp(prop, "ulpi")) {
  65                        sicrl |= MPC834X_SICRL_USB1;
  66                } else {
  67                        printk(KERN_WARNING "834x USB PHY type not supported\n");
  68                }
  69                of_node_put(np);
  70        }
  71        np = of_find_compatible_node(NULL, NULL, "fsl-usb2-mph");
  72        if (np) {
  73                sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */
  74
  75                prop = of_get_property(np, "port0", NULL);
  76                if (prop) {
  77                        if (port0_is_dr)
  78                                printk(KERN_WARNING
  79                                        "834x USB port0 can't be used by both DR and MPH!\n");
  80                        sicrl &= ~MPC834X_SICRL_USB0;
  81                }
  82                prop = of_get_property(np, "port1", NULL);
  83                if (prop) {
  84                        if (port1_is_dr)
  85                                printk(KERN_WARNING
  86                                        "834x USB port1 can't be used by both DR and MPH!\n");
  87                        sicrl &= ~MPC834X_SICRL_USB1;
  88                }
  89                of_node_put(np);
  90        }
  91
  92        /* Write back */
  93        out_be32(immap + MPC83XX_SCCR_OFFS, sccr);
  94        out_be32(immap + MPC83XX_SICRL_OFFS, sicrl);
  95        out_be32(immap + MPC83XX_SICRH_OFFS, sicrh);
  96
  97        iounmap(immap);
  98        return 0;
  99}
 100#endif /* CONFIG_PPC_MPC834x */
 101
 102#ifdef CONFIG_PPC_MPC831x
 103int mpc831x_usb_cfg(void)
 104{
 105        u32 temp;
 106        void __iomem *immap, *usb_regs;
 107        struct device_node *np = NULL;
 108        struct device_node *immr_node = NULL;
 109        const void *prop;
 110        struct resource res;
 111        int ret = 0;
 112#ifdef CONFIG_USB_OTG
 113        const void *dr_mode;
 114#endif
 115
 116        np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
 117        if (!np)
 118                return -ENODEV;
 119        prop = of_get_property(np, "phy_type", NULL);
 120
 121        /* Map IMMR space for pin and clock settings */
 122        immap = ioremap(get_immrbase(), 0x1000);
 123        if (!immap) {
 124                of_node_put(np);
 125                return -ENOMEM;
 126        }
 127
 128        /* Configure clock */
 129        immr_node = of_get_parent(np);
 130        if (immr_node && (of_device_is_compatible(immr_node, "fsl,mpc8315-immr") ||
 131                        of_device_is_compatible(immr_node, "fsl,mpc8308-immr")))
 132                clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,
 133                                MPC8315_SCCR_USB_MASK,
 134                                MPC8315_SCCR_USB_DRCM_01);
 135        else
 136                clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,
 137                                MPC83XX_SCCR_USB_MASK,
 138                                MPC83XX_SCCR_USB_DRCM_11);
 139
 140        /* Configure pin mux for ULPI.  There is no pin mux for UTMI */
 141        if (prop && !strcmp(prop, "ulpi")) {
 142                if (of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) {
 143                        clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,
 144                                        MPC8308_SICRH_USB_MASK,
 145                                        MPC8308_SICRH_USB_ULPI);
 146                } else if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr")) {
 147                        clrsetbits_be32(immap + MPC83XX_SICRL_OFFS,
 148                                        MPC8315_SICRL_USB_MASK,
 149                                        MPC8315_SICRL_USB_ULPI);
 150                        clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,
 151                                        MPC8315_SICRH_USB_MASK,
 152                                        MPC8315_SICRH_USB_ULPI);
 153                } else {
 154                        clrsetbits_be32(immap + MPC83XX_SICRL_OFFS,
 155                                        MPC831X_SICRL_USB_MASK,
 156                                        MPC831X_SICRL_USB_ULPI);
 157                        clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,
 158                                        MPC831X_SICRH_USB_MASK,
 159                                        MPC831X_SICRH_USB_ULPI);
 160                }
 161        }
 162
 163        iounmap(immap);
 164
 165        if (immr_node)
 166                of_node_put(immr_node);
 167
 168        /* Map USB SOC space */
 169        ret = of_address_to_resource(np, 0, &res);
 170        if (ret) {
 171                of_node_put(np);
 172                return ret;
 173        }
 174        usb_regs = ioremap(res.start, resource_size(&res));
 175
 176        /* Using on-chip PHY */
 177        if (prop && (!strcmp(prop, "utmi_wide") ||
 178                     !strcmp(prop, "utmi"))) {
 179                u32 refsel;
 180
 181                if (of_device_is_compatible(immr_node, "fsl,mpc8308-immr"))
 182                        goto out;
 183
 184                if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr"))
 185                        refsel = CONTROL_REFSEL_24MHZ;
 186                else
 187                        refsel = CONTROL_REFSEL_48MHZ;
 188                /* Set UTMI_PHY_EN and REFSEL */
 189                out_be32(usb_regs + FSL_USB2_CONTROL_OFFS,
 190                                CONTROL_UTMI_PHY_EN | refsel);
 191        /* Using external UPLI PHY */
 192        } else if (prop && !strcmp(prop, "ulpi")) {
 193                /* Set PHY_CLK_SEL to ULPI */
 194                temp = CONTROL_PHY_CLK_SEL_ULPI;
 195#ifdef CONFIG_USB_OTG
 196                /* Set OTG_PORT */
 197                if (!of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) {
 198                        dr_mode = of_get_property(np, "dr_mode", NULL);
 199                        if (dr_mode && !strcmp(dr_mode, "otg"))
 200                                temp |= CONTROL_OTG_PORT;
 201                }
 202#endif /* CONFIG_USB_OTG */
 203                out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp);
 204        } else {
 205                printk(KERN_WARNING "831x USB PHY type not supported\n");
 206                ret = -EINVAL;
 207        }
 208
 209out:
 210        iounmap(usb_regs);
 211        of_node_put(np);
 212        return ret;
 213}
 214#endif /* CONFIG_PPC_MPC831x */
 215
 216#ifdef CONFIG_PPC_MPC837x
 217int mpc837x_usb_cfg(void)
 218{
 219        void __iomem *immap;
 220        struct device_node *np = NULL;
 221        const void *prop;
 222        int ret = 0;
 223
 224        np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
 225        if (!np || !of_device_is_available(np))
 226                return -ENODEV;
 227        prop = of_get_property(np, "phy_type", NULL);
 228
 229        if (!prop || (strcmp(prop, "ulpi") && strcmp(prop, "serial"))) {
 230                printk(KERN_WARNING "837x USB PHY type not supported\n");
 231                of_node_put(np);
 232                return -EINVAL;
 233        }
 234
 235        /* Map IMMR space for pin and clock settings */
 236        immap = ioremap(get_immrbase(), 0x1000);
 237        if (!immap) {
 238                of_node_put(np);
 239                return -ENOMEM;
 240        }
 241
 242        /* Configure clock */
 243        clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, MPC837X_SCCR_USB_DRCM_11,
 244                        MPC837X_SCCR_USB_DRCM_11);
 245
 246        /* Configure pin mux for ULPI/serial */
 247        clrsetbits_be32(immap + MPC83XX_SICRL_OFFS, MPC837X_SICRL_USB_MASK,
 248                        MPC837X_SICRL_USB_ULPI);
 249
 250        iounmap(immap);
 251        of_node_put(np);
 252        return ret;
 253}
 254#endif /* CONFIG_PPC_MPC837x */
 255