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        of_node_put(immr_node);
 166
 167        /* Map USB SOC space */
 168        ret = of_address_to_resource(np, 0, &res);
 169        if (ret) {
 170                of_node_put(np);
 171                return ret;
 172        }
 173        usb_regs = ioremap(res.start, resource_size(&res));
 174
 175        /* Using on-chip PHY */
 176        if (prop && (!strcmp(prop, "utmi_wide") ||
 177                     !strcmp(prop, "utmi"))) {
 178                u32 refsel;
 179
 180                if (of_device_is_compatible(immr_node, "fsl,mpc8308-immr"))
 181                        goto out;
 182
 183                if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr"))
 184                        refsel = CONTROL_REFSEL_24MHZ;
 185                else
 186                        refsel = CONTROL_REFSEL_48MHZ;
 187                /* Set UTMI_PHY_EN and REFSEL */
 188                out_be32(usb_regs + FSL_USB2_CONTROL_OFFS,
 189                                CONTROL_UTMI_PHY_EN | refsel);
 190        /* Using external UPLI PHY */
 191        } else if (prop && !strcmp(prop, "ulpi")) {
 192                /* Set PHY_CLK_SEL to ULPI */
 193                temp = CONTROL_PHY_CLK_SEL_ULPI;
 194#ifdef CONFIG_USB_OTG
 195                /* Set OTG_PORT */
 196                if (!of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) {
 197                        dr_mode = of_get_property(np, "dr_mode", NULL);
 198                        if (dr_mode && !strcmp(dr_mode, "otg"))
 199                                temp |= CONTROL_OTG_PORT;
 200                }
 201#endif /* CONFIG_USB_OTG */
 202                out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp);
 203        } else {
 204                printk(KERN_WARNING "831x USB PHY type not supported\n");
 205                ret = -EINVAL;
 206        }
 207
 208out:
 209        iounmap(usb_regs);
 210        of_node_put(np);
 211        return ret;
 212}
 213#endif /* CONFIG_PPC_MPC831x */
 214
 215#ifdef CONFIG_PPC_MPC837x
 216int mpc837x_usb_cfg(void)
 217{
 218        void __iomem *immap;
 219        struct device_node *np = NULL;
 220        const void *prop;
 221        int ret = 0;
 222
 223        np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
 224        if (!np || !of_device_is_available(np))
 225                return -ENODEV;
 226        prop = of_get_property(np, "phy_type", NULL);
 227
 228        if (!prop || (strcmp(prop, "ulpi") && strcmp(prop, "serial"))) {
 229                printk(KERN_WARNING "837x USB PHY type not supported\n");
 230                of_node_put(np);
 231                return -EINVAL;
 232        }
 233
 234        /* Map IMMR space for pin and clock settings */
 235        immap = ioremap(get_immrbase(), 0x1000);
 236        if (!immap) {
 237                of_node_put(np);
 238                return -ENOMEM;
 239        }
 240
 241        /* Configure clock */
 242        clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, MPC837X_SCCR_USB_DRCM_11,
 243                        MPC837X_SCCR_USB_DRCM_11);
 244
 245        /* Configure pin mux for ULPI/serial */
 246        clrsetbits_be32(immap + MPC83XX_SICRL_OFFS, MPC837X_SICRL_USB_MASK,
 247                        MPC837X_SICRL_USB_ULPI);
 248
 249        iounmap(immap);
 250        of_node_put(np);
 251        return ret;
 252}
 253#endif /* CONFIG_PPC_MPC837x */
 254