162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Freescale 83xx USB SOC setup code 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2007 Freescale Semiconductor, Inc. 662306a36Sopenharmony_ci * Author: Li Yang 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/stddef.h> 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/errno.h> 1262306a36Sopenharmony_ci#include <linux/of.h> 1362306a36Sopenharmony_ci#include <linux/of_address.h> 1462306a36Sopenharmony_ci#include <linux/io.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <sysdev/fsl_soc.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include "mpc83xx.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ciint __init mpc831x_usb_cfg(void) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci u32 temp; 2362306a36Sopenharmony_ci void __iomem *immap, *usb_regs; 2462306a36Sopenharmony_ci struct device_node *np = NULL; 2562306a36Sopenharmony_ci struct device_node *immr_node = NULL; 2662306a36Sopenharmony_ci const void *prop; 2762306a36Sopenharmony_ci struct resource res; 2862306a36Sopenharmony_ci int ret = 0; 2962306a36Sopenharmony_ci#ifdef CONFIG_USB_OTG 3062306a36Sopenharmony_ci const void *dr_mode; 3162306a36Sopenharmony_ci#endif 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr"); 3462306a36Sopenharmony_ci if (!np) 3562306a36Sopenharmony_ci return -ENODEV; 3662306a36Sopenharmony_ci prop = of_get_property(np, "phy_type", NULL); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci /* Map IMMR space for pin and clock settings */ 3962306a36Sopenharmony_ci immap = ioremap(get_immrbase(), 0x1000); 4062306a36Sopenharmony_ci if (!immap) { 4162306a36Sopenharmony_ci of_node_put(np); 4262306a36Sopenharmony_ci return -ENOMEM; 4362306a36Sopenharmony_ci } 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci /* Configure clock */ 4662306a36Sopenharmony_ci immr_node = of_get_parent(np); 4762306a36Sopenharmony_ci if (immr_node && (of_device_is_compatible(immr_node, "fsl,mpc8315-immr") || 4862306a36Sopenharmony_ci of_device_is_compatible(immr_node, "fsl,mpc8308-immr"))) 4962306a36Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, 5062306a36Sopenharmony_ci MPC8315_SCCR_USB_MASK, 5162306a36Sopenharmony_ci MPC8315_SCCR_USB_DRCM_01); 5262306a36Sopenharmony_ci else 5362306a36Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, 5462306a36Sopenharmony_ci MPC83XX_SCCR_USB_MASK, 5562306a36Sopenharmony_ci MPC83XX_SCCR_USB_DRCM_11); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci /* Configure pin mux for ULPI. There is no pin mux for UTMI */ 5862306a36Sopenharmony_ci if (prop && !strcmp(prop, "ulpi")) { 5962306a36Sopenharmony_ci if (of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) { 6062306a36Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SICRH_OFFS, 6162306a36Sopenharmony_ci MPC8308_SICRH_USB_MASK, 6262306a36Sopenharmony_ci MPC8308_SICRH_USB_ULPI); 6362306a36Sopenharmony_ci } else if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr")) { 6462306a36Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SICRL_OFFS, 6562306a36Sopenharmony_ci MPC8315_SICRL_USB_MASK, 6662306a36Sopenharmony_ci MPC8315_SICRL_USB_ULPI); 6762306a36Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SICRH_OFFS, 6862306a36Sopenharmony_ci MPC8315_SICRH_USB_MASK, 6962306a36Sopenharmony_ci MPC8315_SICRH_USB_ULPI); 7062306a36Sopenharmony_ci } else { 7162306a36Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SICRL_OFFS, 7262306a36Sopenharmony_ci MPC831X_SICRL_USB_MASK, 7362306a36Sopenharmony_ci MPC831X_SICRL_USB_ULPI); 7462306a36Sopenharmony_ci clrsetbits_be32(immap + MPC83XX_SICRH_OFFS, 7562306a36Sopenharmony_ci MPC831X_SICRH_USB_MASK, 7662306a36Sopenharmony_ci MPC831X_SICRH_USB_ULPI); 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci iounmap(immap); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci of_node_put(immr_node); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci /* Map USB SOC space */ 8562306a36Sopenharmony_ci ret = of_address_to_resource(np, 0, &res); 8662306a36Sopenharmony_ci if (ret) { 8762306a36Sopenharmony_ci of_node_put(np); 8862306a36Sopenharmony_ci return ret; 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci usb_regs = ioremap(res.start, resource_size(&res)); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci /* Using on-chip PHY */ 9362306a36Sopenharmony_ci if (prop && (!strcmp(prop, "utmi_wide") || !strcmp(prop, "utmi"))) { 9462306a36Sopenharmony_ci u32 refsel; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci if (of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) 9762306a36Sopenharmony_ci goto out; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr")) 10062306a36Sopenharmony_ci refsel = CONTROL_REFSEL_24MHZ; 10162306a36Sopenharmony_ci else 10262306a36Sopenharmony_ci refsel = CONTROL_REFSEL_48MHZ; 10362306a36Sopenharmony_ci /* Set UTMI_PHY_EN and REFSEL */ 10462306a36Sopenharmony_ci out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, 10562306a36Sopenharmony_ci CONTROL_UTMI_PHY_EN | refsel); 10662306a36Sopenharmony_ci /* Using external UPLI PHY */ 10762306a36Sopenharmony_ci } else if (prop && !strcmp(prop, "ulpi")) { 10862306a36Sopenharmony_ci /* Set PHY_CLK_SEL to ULPI */ 10962306a36Sopenharmony_ci temp = CONTROL_PHY_CLK_SEL_ULPI; 11062306a36Sopenharmony_ci#ifdef CONFIG_USB_OTG 11162306a36Sopenharmony_ci /* Set OTG_PORT */ 11262306a36Sopenharmony_ci if (!of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) { 11362306a36Sopenharmony_ci dr_mode = of_get_property(np, "dr_mode", NULL); 11462306a36Sopenharmony_ci if (dr_mode && !strcmp(dr_mode, "otg")) 11562306a36Sopenharmony_ci temp |= CONTROL_OTG_PORT; 11662306a36Sopenharmony_ci } 11762306a36Sopenharmony_ci#endif /* CONFIG_USB_OTG */ 11862306a36Sopenharmony_ci out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp); 11962306a36Sopenharmony_ci } else { 12062306a36Sopenharmony_ci pr_warn("831x USB PHY type not supported\n"); 12162306a36Sopenharmony_ci ret = -EINVAL; 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ciout: 12562306a36Sopenharmony_ci iounmap(usb_regs); 12662306a36Sopenharmony_ci of_node_put(np); 12762306a36Sopenharmony_ci return ret; 12862306a36Sopenharmony_ci} 129