Path: blob/master/arch/powerpc/platforms/83xx/usb.c
10819 views
/*1* Freescale 83xx USB SOC setup code2*3* Copyright (C) 2007 Freescale Semiconductor, Inc.4* Author: Li Yang5*6* This program is free software; you can redistribute it and/or modify it7* under the terms of the GNU General Public License as published by the8* Free Software Foundation; either version 2 of the License, or (at your9* option) any later version.10*/111213#include <linux/stddef.h>14#include <linux/kernel.h>15#include <linux/errno.h>16#include <linux/of.h>1718#include <asm/io.h>19#include <asm/prom.h>20#include <sysdev/fsl_soc.h>2122#include "mpc83xx.h"232425#ifdef CONFIG_PPC_MPC834x26int mpc834x_usb_cfg(void)27{28unsigned long sccr, sicrl, sicrh;29void __iomem *immap;30struct device_node *np = NULL;31int port0_is_dr = 0, port1_is_dr = 0;32const void *prop, *dr_mode;3334immap = ioremap(get_immrbase(), 0x1000);35if (!immap)36return -ENOMEM;3738/* Read registers */39/* Note: DR and MPH must use the same clock setting in SCCR */40sccr = in_be32(immap + MPC83XX_SCCR_OFFS) & ~MPC83XX_SCCR_USB_MASK;41sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK;42sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI;4344np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");45if (np) {46sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */4748prop = of_get_property(np, "phy_type", NULL);49port1_is_dr = 1;50if (prop && (!strcmp(prop, "utmi") ||51!strcmp(prop, "utmi_wide"))) {52sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;53sicrh |= MPC834X_SICRH_USB_UTMI;54port0_is_dr = 1;55} else if (prop && !strcmp(prop, "serial")) {56dr_mode = of_get_property(np, "dr_mode", NULL);57if (dr_mode && !strcmp(dr_mode, "otg")) {58sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;59port0_is_dr = 1;60} else {61sicrl |= MPC834X_SICRL_USB1;62}63} else if (prop && !strcmp(prop, "ulpi")) {64sicrl |= MPC834X_SICRL_USB1;65} else {66printk(KERN_WARNING "834x USB PHY type not supported\n");67}68of_node_put(np);69}70np = of_find_compatible_node(NULL, NULL, "fsl-usb2-mph");71if (np) {72sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */7374prop = of_get_property(np, "port0", NULL);75if (prop) {76if (port0_is_dr)77printk(KERN_WARNING78"834x USB port0 can't be used by both DR and MPH!\n");79sicrl &= ~MPC834X_SICRL_USB0;80}81prop = of_get_property(np, "port1", NULL);82if (prop) {83if (port1_is_dr)84printk(KERN_WARNING85"834x USB port1 can't be used by both DR and MPH!\n");86sicrl &= ~MPC834X_SICRL_USB1;87}88of_node_put(np);89}9091/* Write back */92out_be32(immap + MPC83XX_SCCR_OFFS, sccr);93out_be32(immap + MPC83XX_SICRL_OFFS, sicrl);94out_be32(immap + MPC83XX_SICRH_OFFS, sicrh);9596iounmap(immap);97return 0;98}99#endif /* CONFIG_PPC_MPC834x */100101#ifdef CONFIG_PPC_MPC831x102int mpc831x_usb_cfg(void)103{104u32 temp;105void __iomem *immap, *usb_regs;106struct device_node *np = NULL;107struct device_node *immr_node = NULL;108const void *prop;109struct resource res;110int ret = 0;111#ifdef CONFIG_USB_OTG112const void *dr_mode;113#endif114115np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");116if (!np)117return -ENODEV;118prop = of_get_property(np, "phy_type", NULL);119120/* Map IMMR space for pin and clock settings */121immap = ioremap(get_immrbase(), 0x1000);122if (!immap) {123of_node_put(np);124return -ENOMEM;125}126127/* Configure clock */128immr_node = of_get_parent(np);129if (immr_node && (of_device_is_compatible(immr_node, "fsl,mpc8315-immr") ||130of_device_is_compatible(immr_node, "fsl,mpc8308-immr")))131clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,132MPC8315_SCCR_USB_MASK,133MPC8315_SCCR_USB_DRCM_01);134else135clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,136MPC83XX_SCCR_USB_MASK,137MPC83XX_SCCR_USB_DRCM_11);138139/* Configure pin mux for ULPI. There is no pin mux for UTMI */140if (prop && !strcmp(prop, "ulpi")) {141if (of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) {142clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,143MPC8308_SICRH_USB_MASK,144MPC8308_SICRH_USB_ULPI);145} else if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr")) {146clrsetbits_be32(immap + MPC83XX_SICRL_OFFS,147MPC8315_SICRL_USB_MASK,148MPC8315_SICRL_USB_ULPI);149clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,150MPC8315_SICRH_USB_MASK,151MPC8315_SICRH_USB_ULPI);152} else {153clrsetbits_be32(immap + MPC83XX_SICRL_OFFS,154MPC831X_SICRL_USB_MASK,155MPC831X_SICRL_USB_ULPI);156clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,157MPC831X_SICRH_USB_MASK,158MPC831X_SICRH_USB_ULPI);159}160}161162iounmap(immap);163164if (immr_node)165of_node_put(immr_node);166167/* Map USB SOC space */168ret = of_address_to_resource(np, 0, &res);169if (ret) {170of_node_put(np);171return ret;172}173usb_regs = ioremap(res.start, res.end - res.start + 1);174175/* Using on-chip PHY */176if (prop && (!strcmp(prop, "utmi_wide") ||177!strcmp(prop, "utmi"))) {178u32 refsel;179180if (of_device_is_compatible(immr_node, "fsl,mpc8308-immr"))181goto out;182183if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr"))184refsel = CONTROL_REFSEL_24MHZ;185else186refsel = CONTROL_REFSEL_48MHZ;187/* Set UTMI_PHY_EN and REFSEL */188out_be32(usb_regs + FSL_USB2_CONTROL_OFFS,189CONTROL_UTMI_PHY_EN | refsel);190/* Using external UPLI PHY */191} else if (prop && !strcmp(prop, "ulpi")) {192/* Set PHY_CLK_SEL to ULPI */193temp = CONTROL_PHY_CLK_SEL_ULPI;194#ifdef CONFIG_USB_OTG195/* Set OTG_PORT */196if (!of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) {197dr_mode = of_get_property(np, "dr_mode", NULL);198if (dr_mode && !strcmp(dr_mode, "otg"))199temp |= CONTROL_OTG_PORT;200}201#endif /* CONFIG_USB_OTG */202out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp);203} else {204printk(KERN_WARNING "831x USB PHY type not supported\n");205ret = -EINVAL;206}207208out:209iounmap(usb_regs);210of_node_put(np);211return ret;212}213#endif /* CONFIG_PPC_MPC831x */214215#ifdef CONFIG_PPC_MPC837x216int mpc837x_usb_cfg(void)217{218void __iomem *immap;219struct device_node *np = NULL;220const void *prop;221int ret = 0;222223np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");224if (!np || !of_device_is_available(np))225return -ENODEV;226prop = of_get_property(np, "phy_type", NULL);227228if (!prop || (strcmp(prop, "ulpi") && strcmp(prop, "serial"))) {229printk(KERN_WARNING "837x USB PHY type not supported\n");230of_node_put(np);231return -EINVAL;232}233234/* Map IMMR space for pin and clock settings */235immap = ioremap(get_immrbase(), 0x1000);236if (!immap) {237of_node_put(np);238return -ENOMEM;239}240241/* Configure clock */242clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, MPC837X_SCCR_USB_DRCM_11,243MPC837X_SCCR_USB_DRCM_11);244245/* Configure pin mux for ULPI/serial */246clrsetbits_be32(immap + MPC83XX_SICRL_OFFS, MPC837X_SICRL_USB_MASK,247MPC837X_SICRL_USB_ULPI);248249iounmap(immap);250of_node_put(np);251return ret;252}253#endif /* CONFIG_PPC_MPC837x */254255256