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