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(offset: get_immrbase(), size: 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, compat: "fsl-usb2-dr" ); |
39 | if (np) { |
40 | sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ |
41 | |
42 | prop = of_get_property(node: np, name: "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(node: np, name: "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(node: np); |
63 | } |
64 | np = of_find_compatible_node(NULL, NULL, compat: "fsl-usb2-mph" ); |
65 | if (np) { |
66 | sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */ |
67 | |
68 | prop = of_get_property(node: np, name: "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(node: np, name: "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(node: 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(addr: immap); |
89 | return 0; |
90 | } |
91 | |