18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Freescale 83xx USB SOC setup code 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2007 Freescale Semiconductor, Inc. 68c2ecf20Sopenharmony_ci * Author: Li Yang 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/stddef.h> 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/errno.h> 138c2ecf20Sopenharmony_ci#include <linux/of.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <asm/io.h> 168c2ecf20Sopenharmony_ci#include <asm/prom.h> 178c2ecf20Sopenharmony_ci#include <sysdev/fsl_soc.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "mpc83xx.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_MPC834x 238c2ecf20Sopenharmony_ciint mpc834x_usb_cfg(void) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci unsigned long sccr, sicrl, sicrh; 268c2ecf20Sopenharmony_ci void __iomem *immap; 278c2ecf20Sopenharmony_ci struct device_node *np = NULL; 288c2ecf20Sopenharmony_ci int port0_is_dr = 0, port1_is_dr = 0; 298c2ecf20Sopenharmony_ci const void *prop, *dr_mode; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci immap = ioremap(get_immrbase(), 0x1000); 328c2ecf20Sopenharmony_ci if (!immap) 338c2ecf20Sopenharmony_ci return -ENOMEM; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci /* Read registers */ 368c2ecf20Sopenharmony_ci /* Note: DR and MPH must use the same clock setting in SCCR */ 378c2ecf20Sopenharmony_ci sccr = in_be32(immap + MPC83XX_SCCR_OFFS) & ~MPC83XX_SCCR_USB_MASK; 388c2ecf20Sopenharmony_ci sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK; 398c2ecf20Sopenharmony_ci sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr"); 428c2ecf20Sopenharmony_ci if (np) { 438c2ecf20Sopenharmony_ci sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci prop = of_get_property(np, "phy_type", NULL); 468c2ecf20Sopenharmony_ci port1_is_dr = 1; 478c2ecf20Sopenharmony_ci if (prop && (!strcmp(prop, "utmi") || 488c2ecf20Sopenharmony_ci !strcmp(prop, "utmi_wide"))) { 498c2ecf20Sopenharmony_ci sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1; 508c2ecf20Sopenharmony_ci sicrh |= MPC834X_SICRH_USB_UTMI; 518c2ecf20Sopenharmony_ci port0_is_dr = 1; 528c2ecf20Sopenharmony_ci } else if (prop && !strcmp(prop, "serial")) { 538c2ecf20Sopenharmony_ci dr_mode = of_get_property(np, "dr_mode", NULL); 548c2ecf20Sopenharmony_ci if (dr_mode && !strcmp(dr_mode, "otg")) { 558c2ecf20Sopenharmony_ci sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1; 568c2ecf20Sopenharmony_ci port0_is_dr = 1; 578c2ecf20Sopenharmony_ci } else { 588c2ecf20Sopenharmony_ci sicrl |= MPC834X_SICRL_USB1; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci } else if (prop && !strcmp(prop, "ulpi")) { 618c2ecf20Sopenharmony_ci sicrl |= MPC834X_SICRL_USB1; 628c2ecf20Sopenharmony_ci } else { 638c2ecf20Sopenharmony_ci printk(KERN_WARNING "834x USB PHY type not supported\n"); 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci of_node_put(np); 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "fsl-usb2-mph"); 688c2ecf20Sopenharmony_ci if (np) { 698c2ecf20Sopenharmony_ci sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */ 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci prop = of_get_property(np, "port0", NULL); 728c2ecf20Sopenharmony_ci if (prop) { 738c2ecf20Sopenharmony_ci if (port0_is_dr) 748c2ecf20Sopenharmony_ci printk(KERN_WARNING 758c2ecf20Sopenharmony_ci "834x USB port0 can't be used by both DR and MPH!\n"); 768c2ecf20Sopenharmony_ci sicrl &= ~MPC834X_SICRL_USB0; 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci prop = of_get_property(np, "port1", NULL); 798c2ecf20Sopenharmony_ci if (prop) { 808c2ecf20Sopenharmony_ci if (port1_is_dr) 818c2ecf20Sopenharmony_ci printk(KERN_WARNING 828c2ecf20Sopenharmony_ci "834x USB port1 can't be used by both DR and MPH!\n"); 838c2ecf20Sopenharmony_ci sicrl &= ~MPC834X_SICRL_USB1; 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci of_node_put(np); 868c2ecf20Sopenharmony_ci } 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci /* Write back */ 898c2ecf20Sopenharmony_ci out_be32(immap + MPC83XX_SCCR_OFFS, sccr); 908c2ecf20Sopenharmony_ci out_be32(immap + MPC83XX_SICRL_OFFS, sicrl); 918c2ecf20Sopenharmony_ci out_be32(immap + MPC83XX_SICRH_OFFS, sicrh); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci iounmap(immap); 948c2ecf20Sopenharmony_ci return 0; 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_MPC834x */ 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_MPC831x 998c2ecf20Sopenharmony_ciint mpc831x_usb_cfg(void) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci u32 temp; 1028c2ecf20Sopenharmony_ci void __iomem *immap, *usb_regs; 1038c2ecf20Sopenharmony_ci struct device_node *np = NULL; 1048c2ecf20Sopenharmony_ci struct device_node *immr_node = NULL; 1058c2ecf20Sopenharmony_ci const void *prop; 1068c2ecf20Sopenharmony_ci struct resource res; 1078c2ecf20Sopenharmony_ci int ret = 0; 1088c2ecf20Sopenharmony_ci#ifdef CONFIG_USB_OTG 1098c2ecf20Sopenharmony_ci const void *dr_mode; 1108c2ecf20Sopenharmony_ci#endif 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr"); 1138c2ecf20Sopenharmony_ci if (!np) 1148c2ecf20Sopenharmony_ci return -ENODEV; 1158c2ecf20Sopenharmony_ci prop = of_get_property(np, "phy_type", NULL); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* Map IMMR space for pin and clock settings */ 1188c2ecf20Sopenharmony_ci immap = ioremap(get_immrbase(), 0x1000); 1198c2ecf20Sopenharmony_ci if (!immap) { 1208c2ecf20Sopenharmony_ci of_node_put(np); 1218c2ecf20Sopenharmony_ci return -ENOMEM; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci /* Configure clock */ 1258c2ecf20Sopenharmony_ci immr_node = of_get_parent(np); 1268c2ecf20Sopenharmony_ci if (immr_node && (of_device_is_compatible(immr_node, "fsl,mpc8315-immr") || 1278c2ecf20Sopenharmony_ci of_device_is_compatible(immr_node, "fsl,mpc8308-immr"))) 1288c2ecf20Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, 1298c2ecf20Sopenharmony_ci MPC8315_SCCR_USB_MASK, 1308c2ecf20Sopenharmony_ci MPC8315_SCCR_USB_DRCM_01); 1318c2ecf20Sopenharmony_ci else 1328c2ecf20Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, 1338c2ecf20Sopenharmony_ci MPC83XX_SCCR_USB_MASK, 1348c2ecf20Sopenharmony_ci MPC83XX_SCCR_USB_DRCM_11); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci /* Configure pin mux for ULPI. There is no pin mux for UTMI */ 1378c2ecf20Sopenharmony_ci if (prop && !strcmp(prop, "ulpi")) { 1388c2ecf20Sopenharmony_ci if (of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) { 1398c2ecf20Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SICRH_OFFS, 1408c2ecf20Sopenharmony_ci MPC8308_SICRH_USB_MASK, 1418c2ecf20Sopenharmony_ci MPC8308_SICRH_USB_ULPI); 1428c2ecf20Sopenharmony_ci } else if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr")) { 1438c2ecf20Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SICRL_OFFS, 1448c2ecf20Sopenharmony_ci MPC8315_SICRL_USB_MASK, 1458c2ecf20Sopenharmony_ci MPC8315_SICRL_USB_ULPI); 1468c2ecf20Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SICRH_OFFS, 1478c2ecf20Sopenharmony_ci MPC8315_SICRH_USB_MASK, 1488c2ecf20Sopenharmony_ci MPC8315_SICRH_USB_ULPI); 1498c2ecf20Sopenharmony_ci } else { 1508c2ecf20Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SICRL_OFFS, 1518c2ecf20Sopenharmony_ci MPC831X_SICRL_USB_MASK, 1528c2ecf20Sopenharmony_ci MPC831X_SICRL_USB_ULPI); 1538c2ecf20Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SICRH_OFFS, 1548c2ecf20Sopenharmony_ci MPC831X_SICRH_USB_MASK, 1558c2ecf20Sopenharmony_ci MPC831X_SICRH_USB_ULPI); 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci iounmap(immap); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci of_node_put(immr_node); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* Map USB SOC space */ 1648c2ecf20Sopenharmony_ci ret = of_address_to_resource(np, 0, &res); 1658c2ecf20Sopenharmony_ci if (ret) { 1668c2ecf20Sopenharmony_ci of_node_put(np); 1678c2ecf20Sopenharmony_ci return ret; 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci usb_regs = ioremap(res.start, resource_size(&res)); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci /* Using on-chip PHY */ 1728c2ecf20Sopenharmony_ci if (prop && (!strcmp(prop, "utmi_wide") || 1738c2ecf20Sopenharmony_ci !strcmp(prop, "utmi"))) { 1748c2ecf20Sopenharmony_ci u32 refsel; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci if (of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) 1778c2ecf20Sopenharmony_ci goto out; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr")) 1808c2ecf20Sopenharmony_ci refsel = CONTROL_REFSEL_24MHZ; 1818c2ecf20Sopenharmony_ci else 1828c2ecf20Sopenharmony_ci refsel = CONTROL_REFSEL_48MHZ; 1838c2ecf20Sopenharmony_ci /* Set UTMI_PHY_EN and REFSEL */ 1848c2ecf20Sopenharmony_ci out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, 1858c2ecf20Sopenharmony_ci CONTROL_UTMI_PHY_EN | refsel); 1868c2ecf20Sopenharmony_ci /* Using external UPLI PHY */ 1878c2ecf20Sopenharmony_ci } else if (prop && !strcmp(prop, "ulpi")) { 1888c2ecf20Sopenharmony_ci /* Set PHY_CLK_SEL to ULPI */ 1898c2ecf20Sopenharmony_ci temp = CONTROL_PHY_CLK_SEL_ULPI; 1908c2ecf20Sopenharmony_ci#ifdef CONFIG_USB_OTG 1918c2ecf20Sopenharmony_ci /* Set OTG_PORT */ 1928c2ecf20Sopenharmony_ci if (!of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) { 1938c2ecf20Sopenharmony_ci dr_mode = of_get_property(np, "dr_mode", NULL); 1948c2ecf20Sopenharmony_ci if (dr_mode && !strcmp(dr_mode, "otg")) 1958c2ecf20Sopenharmony_ci temp |= CONTROL_OTG_PORT; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci#endif /* CONFIG_USB_OTG */ 1988c2ecf20Sopenharmony_ci out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp); 1998c2ecf20Sopenharmony_ci } else { 2008c2ecf20Sopenharmony_ci printk(KERN_WARNING "831x USB PHY type not supported\n"); 2018c2ecf20Sopenharmony_ci ret = -EINVAL; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ciout: 2058c2ecf20Sopenharmony_ci iounmap(usb_regs); 2068c2ecf20Sopenharmony_ci of_node_put(np); 2078c2ecf20Sopenharmony_ci return ret; 2088c2ecf20Sopenharmony_ci} 2098c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_MPC831x */ 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_MPC837x 2128c2ecf20Sopenharmony_ciint mpc837x_usb_cfg(void) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci void __iomem *immap; 2158c2ecf20Sopenharmony_ci struct device_node *np = NULL; 2168c2ecf20Sopenharmony_ci const void *prop; 2178c2ecf20Sopenharmony_ci int ret = 0; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr"); 2208c2ecf20Sopenharmony_ci if (!np || !of_device_is_available(np)) { 2218c2ecf20Sopenharmony_ci of_node_put(np); 2228c2ecf20Sopenharmony_ci return -ENODEV; 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci prop = of_get_property(np, "phy_type", NULL); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci if (!prop || (strcmp(prop, "ulpi") && strcmp(prop, "serial"))) { 2278c2ecf20Sopenharmony_ci printk(KERN_WARNING "837x USB PHY type not supported\n"); 2288c2ecf20Sopenharmony_ci of_node_put(np); 2298c2ecf20Sopenharmony_ci return -EINVAL; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci /* Map IMMR space for pin and clock settings */ 2338c2ecf20Sopenharmony_ci immap = ioremap(get_immrbase(), 0x1000); 2348c2ecf20Sopenharmony_ci if (!immap) { 2358c2ecf20Sopenharmony_ci of_node_put(np); 2368c2ecf20Sopenharmony_ci return -ENOMEM; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci /* Configure clock */ 2408c2ecf20Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, MPC837X_SCCR_USB_DRCM_11, 2418c2ecf20Sopenharmony_ci MPC837X_SCCR_USB_DRCM_11); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci /* Configure pin mux for ULPI/serial */ 2448c2ecf20Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SICRL_OFFS, MPC837X_SICRL_USB_MASK, 2458c2ecf20Sopenharmony_ci MPC837X_SICRL_USB_ULPI); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci iounmap(immap); 2488c2ecf20Sopenharmony_ci of_node_put(np); 2498c2ecf20Sopenharmony_ci return ret; 2508c2ecf20Sopenharmony_ci} 2518c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_MPC837x */ 252