1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Freescale 83xx USB SOC setup code 4 * 5 * Copyright (C) 2007 Freescale Semiconductor, Inc. 6 * Author: Li Yang 7 */ 8 9 #include <linux/stddef.h> 10 #include <linux/kernel.h> 11 #include <linux/errno.h> 12 #include <linux/of.h> 13 #include <linux/of_address.h> 14 #include <linux/io.h> 15 16 #include <sysdev/fsl_soc.h> 17 18 #include "mpc83xx.h" 19 20 int __init mpc834x_usb_cfg(void) 21 { 22 unsigned long sccr, sicrl, sicrh; 23 void __iomem *immap; 24 struct device_node *np = NULL; 25 int port0_is_dr = 0, port1_is_dr = 0; 26 const void *prop, *dr_mode; 27 28 immap = ioremap(get_immrbase(), 0x1000); 29 if (!immap) 30 return -ENOMEM; 31 32 /* Read registers */ 33 /* Note: DR and MPH must use the same clock setting in SCCR */ 34 sccr = in_be32(immap + MPC83XX_SCCR_OFFS) & ~MPC83XX_SCCR_USB_MASK; 35 sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK; 36 sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI; 37 38 np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr"); 39 if (np) { 40 sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ 41 42 prop = of_get_property(np, "phy_type", NULL); 43 port1_is_dr = 1; 44 if (prop && 45 (!strcmp(prop, "utmi") || !strcmp(prop, "utmi_wide"))) { 46 sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1; 47 sicrh |= MPC834X_SICRH_USB_UTMI; 48 port0_is_dr = 1; 49 } else if (prop && !strcmp(prop, "serial")) { 50 dr_mode = of_get_property(np, "dr_mode", NULL); 51 if (dr_mode && !strcmp(dr_mode, "otg")) { 52 sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1; 53 port0_is_dr = 1; 54 } else { 55 sicrl |= MPC834X_SICRL_USB1; 56 } 57 } else if (prop && !strcmp(prop, "ulpi")) { 58 sicrl |= MPC834X_SICRL_USB1; 59 } else { 60 pr_warn("834x USB PHY type not supported\n"); 61 } 62 of_node_put(np); 63 } 64 np = of_find_compatible_node(NULL, NULL, "fsl-usb2-mph"); 65 if (np) { 66 sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */ 67 68 prop = of_get_property(np, "port0", NULL); 69 if (prop) { 70 if (port0_is_dr) 71 pr_warn("834x USB port0 can't be used by both DR and MPH!\n"); 72 sicrl &= ~MPC834X_SICRL_USB0; 73 } 74 prop = of_get_property(np, "port1", NULL); 75 if (prop) { 76 if (port1_is_dr) 77 pr_warn("834x USB port1 can't be used by both DR and MPH!\n"); 78 sicrl &= ~MPC834X_SICRL_USB1; 79 } 80 of_node_put(np); 81 } 82 83 /* Write back */ 84 out_be32(immap + MPC83XX_SCCR_OFFS, sccr); 85 out_be32(immap + MPC83XX_SICRL_OFFS, sicrl); 86 out_be32(immap + MPC83XX_SICRH_OFFS, sicrh); 87 88 iounmap(immap); 89 return 0; 90 } 91