diff options
-rw-r--r-- | arch/powerpc/platforms/83xx/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/83xx/mpc8313_rdb.c | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/83xx/mpc834x_mds.c | 49 | ||||
-rw-r--r-- | arch/powerpc/platforms/83xx/mpc83xx.h | 28 | ||||
-rw-r--r-- | arch/powerpc/platforms/83xx/usb.c | 181 |
5 files changed, 213 insertions, 48 deletions
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile index 31a91b53f528..5a98f885779f 100644 --- a/arch/powerpc/platforms/83xx/Makefile +++ b/arch/powerpc/platforms/83xx/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the PowerPC 83xx linux kernel. | 2 | # Makefile for the PowerPC 83xx linux kernel. |
3 | # | 3 | # |
4 | obj-y := misc.o | 4 | obj-y := misc.o usb.o |
5 | obj-$(CONFIG_PCI) += pci.o | 5 | obj-$(CONFIG_PCI) += pci.o |
6 | obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o | 6 | obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o |
7 | obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o | 7 | obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o |
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c index 4dee22ad14b4..3edfe170a03b 100644 --- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c | |||
@@ -48,6 +48,7 @@ static void __init mpc8313_rdb_setup_arch(void) | |||
48 | 48 | ||
49 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 49 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
50 | #endif | 50 | #endif |
51 | mpc831x_usb_cfg(); | ||
51 | } | 52 | } |
52 | 53 | ||
53 | void __init mpc8313_rdb_init_IRQ(void) | 54 | void __init mpc8313_rdb_init_IRQ(void) |
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c index 8607441c3953..4c9ff9cadfe4 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c | |||
@@ -39,55 +39,16 @@ | |||
39 | #include "mpc83xx.h" | 39 | #include "mpc83xx.h" |
40 | 40 | ||
41 | #define BCSR5_INT_USB 0x02 | 41 | #define BCSR5_INT_USB 0x02 |
42 | /* Note: This is only for PB, not for PB+PIB | 42 | static int mpc834xemds_usb_cfg(void) |
43 | * On PB only port0 is connected using ULPI */ | ||
44 | static int mpc834x_usb_cfg(void) | ||
45 | { | 43 | { |
46 | unsigned long sccr, sicrl; | 44 | struct device_node *np; |
47 | void __iomem *immap; | ||
48 | void __iomem *bcsr_regs = NULL; | 45 | void __iomem *bcsr_regs = NULL; |
49 | u8 bcsr5; | 46 | u8 bcsr5; |
50 | struct device_node *np = NULL; | ||
51 | int port0_is_dr = 0; | ||
52 | |||
53 | if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr")) != NULL) | ||
54 | port0_is_dr = 1; | ||
55 | if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph")) != NULL){ | ||
56 | if (port0_is_dr) { | ||
57 | printk(KERN_WARNING | ||
58 | "There is only one USB port on PB board! \n"); | ||
59 | return -1; | ||
60 | } else if (!port0_is_dr) | ||
61 | /* No usb port enabled */ | ||
62 | return -1; | ||
63 | } | ||
64 | |||
65 | immap = ioremap(get_immrbase(), 0x1000); | ||
66 | if (!immap) | ||
67 | return -1; | ||
68 | |||
69 | /* Configure clock */ | ||
70 | sccr = in_be32(immap + MPC83XX_SCCR_OFFS); | ||
71 | if (port0_is_dr) | ||
72 | sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ | ||
73 | else | ||
74 | sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */ | ||
75 | out_be32(immap + MPC83XX_SCCR_OFFS, sccr); | ||
76 | |||
77 | /* Configure Pin */ | ||
78 | sicrl = in_be32(immap + MPC83XX_SICRL_OFFS); | ||
79 | /* set port0 only */ | ||
80 | if (port0_is_dr) | ||
81 | sicrl |= MPC83XX_SICRL_USB0; | ||
82 | else | ||
83 | sicrl &= ~(MPC83XX_SICRL_USB0); | ||
84 | out_be32(immap + MPC83XX_SICRL_OFFS, sicrl); | ||
85 | |||
86 | iounmap(immap); | ||
87 | 47 | ||
48 | mpc834x_usb_cfg(); | ||
88 | /* Map BCSR area */ | 49 | /* Map BCSR area */ |
89 | np = of_find_node_by_name(NULL, "bcsr"); | 50 | np = of_find_node_by_name(NULL, "bcsr"); |
90 | if (np != 0) { | 51 | if (np) { |
91 | struct resource res; | 52 | struct resource res; |
92 | 53 | ||
93 | of_address_to_resource(np, 0, &res); | 54 | of_address_to_resource(np, 0, &res); |
@@ -129,7 +90,7 @@ static void __init mpc834x_mds_setup_arch(void) | |||
129 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 90 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
130 | #endif | 91 | #endif |
131 | 92 | ||
132 | mpc834x_usb_cfg(); | 93 | mpc834xemds_usb_cfg(); |
133 | } | 94 | } |
134 | 95 | ||
135 | static void __init mpc834x_mds_init_IRQ(void) | 96 | static void __init mpc834x_mds_init_IRQ(void) |
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h index f5c5034a8461..589ee55730f3 100644 --- a/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/arch/powerpc/platforms/83xx/mpc83xx.h | |||
@@ -7,6 +7,7 @@ | |||
7 | 7 | ||
8 | /* System Clock Control Register */ | 8 | /* System Clock Control Register */ |
9 | #define MPC83XX_SCCR_OFFS 0xA08 | 9 | #define MPC83XX_SCCR_OFFS 0xA08 |
10 | #define MPC83XX_SCCR_USB_MASK 0x00f00000 | ||
10 | #define MPC83XX_SCCR_USB_MPHCM_11 0x00c00000 | 11 | #define MPC83XX_SCCR_USB_MPHCM_11 0x00c00000 |
11 | #define MPC83XX_SCCR_USB_MPHCM_01 0x00400000 | 12 | #define MPC83XX_SCCR_USB_MPHCM_01 0x00400000 |
12 | #define MPC83XX_SCCR_USB_MPHCM_10 0x00800000 | 13 | #define MPC83XX_SCCR_USB_MPHCM_10 0x00800000 |
@@ -16,12 +17,31 @@ | |||
16 | 17 | ||
17 | /* system i/o configuration register low */ | 18 | /* system i/o configuration register low */ |
18 | #define MPC83XX_SICRL_OFFS 0x114 | 19 | #define MPC83XX_SICRL_OFFS 0x114 |
19 | #define MPC83XX_SICRL_USB0 0x40000000 | 20 | #define MPC834X_SICRL_USB_MASK 0x60000000 |
20 | #define MPC83XX_SICRL_USB1 0x20000000 | 21 | #define MPC834X_SICRL_USB0 0x40000000 |
22 | #define MPC834X_SICRL_USB1 0x20000000 | ||
23 | #define MPC831X_SICRL_USB_MASK 0x00000c00 | ||
24 | #define MPC831X_SICRL_USB_ULPI 0x00000800 | ||
21 | 25 | ||
22 | /* system i/o configuration register high */ | 26 | /* system i/o configuration register high */ |
23 | #define MPC83XX_SICRH_OFFS 0x118 | 27 | #define MPC83XX_SICRH_OFFS 0x118 |
24 | #define MPC83XX_SICRH_USB_UTMI 0x00020000 | 28 | #define MPC834X_SICRH_USB_UTMI 0x00020000 |
29 | #define MPC831X_SICRH_USB_MASK 0x000000e0 | ||
30 | #define MPC831X_SICRH_USB_ULPI 0x000000a0 | ||
31 | |||
32 | /* USB Control Register */ | ||
33 | #define FSL_USB2_CONTROL_OFFS 0x500 | ||
34 | #define CONTROL_UTMI_PHY_EN 0x00000200 | ||
35 | #define CONTROL_REFSEL_48MHZ 0x00000080 | ||
36 | #define CONTROL_PHY_CLK_SEL_ULPI 0x00000400 | ||
37 | #define CONTROL_OTG_PORT 0x00000020 | ||
38 | |||
39 | /* USB PORTSC Registers */ | ||
40 | #define FSL_USB2_PORTSC1_OFFS 0x184 | ||
41 | #define FSL_USB2_PORTSC2_OFFS 0x188 | ||
42 | #define PORTSCX_PTW_16BIT 0x10000000 | ||
43 | #define PORTSCX_PTS_UTMI 0x00000000 | ||
44 | #define PORTSCX_PTS_ULPI 0x80000000 | ||
25 | 45 | ||
26 | /* | 46 | /* |
27 | * Declaration for the various functions exported by the | 47 | * Declaration for the various functions exported by the |
@@ -33,5 +53,7 @@ extern int mpc83xx_exclude_device(struct pci_controller *hose, | |||
33 | u_char bus, u_char devfn); | 53 | u_char bus, u_char devfn); |
34 | extern void mpc83xx_restart(char *cmd); | 54 | extern void mpc83xx_restart(char *cmd); |
35 | extern long mpc83xx_time_init(void); | 55 | extern long mpc83xx_time_init(void); |
56 | extern int mpc834x_usb_cfg(void); | ||
57 | extern int mpc831x_usb_cfg(void); | ||
36 | 58 | ||
37 | #endif /* __MPC83XX_H__ */ | 59 | #endif /* __MPC83XX_H__ */ |
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c new file mode 100644 index 000000000000..e7fdf013cd39 --- /dev/null +++ b/arch/powerpc/platforms/83xx/usb.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * Freescale 83xx USB SOC setup code | ||
3 | * | ||
4 | * Copyright (C) 2007 Freescale Semiconductor, Inc. | ||
5 | * Author: Li Yang | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | |||
14 | #include <linux/stddef.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/errno.h> | ||
17 | |||
18 | #include <asm/io.h> | ||
19 | #include <asm/prom.h> | ||
20 | #include <sysdev/fsl_soc.h> | ||
21 | |||
22 | #include "mpc83xx.h" | ||
23 | |||
24 | |||
25 | #ifdef CONFIG_MPC834x | ||
26 | int mpc834x_usb_cfg(void) | ||
27 | { | ||
28 | unsigned long sccr, sicrl, sicrh; | ||
29 | void __iomem *immap; | ||
30 | struct device_node *np = NULL; | ||
31 | int port0_is_dr = 0, port1_is_dr = 0; | ||
32 | const void *prop, *dr_mode; | ||
33 | |||
34 | immap = ioremap(get_immrbase(), 0x1000); | ||
35 | if (!immap) | ||
36 | return -ENOMEM; | ||
37 | |||
38 | /* Read registers */ | ||
39 | /* Note: DR and MPH must use the same clock setting in SCCR */ | ||
40 | sccr = in_be32(immap + MPC83XX_SCCR_OFFS) & ~MPC83XX_SCCR_USB_MASK; | ||
41 | sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK; | ||
42 | sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI; | ||
43 | |||
44 | np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr"); | ||
45 | if (np) { | ||
46 | sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ | ||
47 | |||
48 | prop = of_get_property(np, "phy_type", NULL); | ||
49 | if (prop && (!strcmp(prop, "utmi") || | ||
50 | !strcmp(prop, "utmi_wide"))) { | ||
51 | sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1; | ||
52 | sicrh |= MPC834X_SICRH_USB_UTMI; | ||
53 | port1_is_dr = 1; | ||
54 | } else if (prop && !strcmp(prop, "serial")) { | ||
55 | dr_mode = of_get_property(np, "dr_mode", NULL); | ||
56 | if (dr_mode && !strcmp(dr_mode, "otg")) { | ||
57 | sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1; | ||
58 | port1_is_dr = 1; | ||
59 | } else { | ||
60 | sicrl |= MPC834X_SICRL_USB0; | ||
61 | } | ||
62 | } else if (prop && !strcmp(prop, "ulpi")) { | ||
63 | sicrl |= MPC834X_SICRL_USB0; | ||
64 | } else { | ||
65 | printk(KERN_WARNING "834x USB PHY type not supported\n"); | ||
66 | } | ||
67 | port0_is_dr = 1; | ||
68 | of_node_put(np); | ||
69 | } | ||
70 | np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph"); | ||
71 | if (np) { | ||
72 | sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */ | ||
73 | |||
74 | prop = of_get_property(np, "port0", NULL); | ||
75 | if (prop) { | ||
76 | if (port0_is_dr) | ||
77 | printk(KERN_WARNING | ||
78 | "834x USB port0 can't be used by both DR and MPH!\n"); | ||
79 | sicrl |= MPC834X_SICRL_USB0; | ||
80 | } | ||
81 | prop = of_get_property(np, "port1", NULL); | ||
82 | if (prop) { | ||
83 | if (port1_is_dr) | ||
84 | printk(KERN_WARNING | ||
85 | "834x USB port1 can't be used by both DR and MPH!\n"); | ||
86 | sicrl |= MPC834X_SICRL_USB1; | ||
87 | } | ||
88 | of_node_put(np); | ||
89 | } | ||
90 | |||
91 | /* Write back */ | ||
92 | out_be32(immap + MPC83XX_SCCR_OFFS, sccr); | ||
93 | out_be32(immap + MPC83XX_SICRL_OFFS, sicrl); | ||
94 | out_be32(immap + MPC83XX_SICRH_OFFS, sicrh); | ||
95 | |||
96 | iounmap(immap); | ||
97 | return 0; | ||
98 | } | ||
99 | #endif /* CONFIG_MPC834x */ | ||
100 | |||
101 | #ifdef CONFIG_PPC_MPC831x | ||
102 | int mpc831x_usb_cfg(void) | ||
103 | { | ||
104 | u32 temp; | ||
105 | void __iomem *immap, *usb_regs; | ||
106 | struct device_node *np = NULL; | ||
107 | const void *prop; | ||
108 | struct resource res; | ||
109 | int ret = 0; | ||
110 | #ifdef CONFIG_USB_OTG | ||
111 | const void *dr_mode; | ||
112 | #endif | ||
113 | |||
114 | np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr"); | ||
115 | if (!np) | ||
116 | return -ENODEV; | ||
117 | prop = of_get_property(np, "phy_type", NULL); | ||
118 | |||
119 | /* Map IMMR space for pin and clock settings */ | ||
120 | immap = ioremap(get_immrbase(), 0x1000); | ||
121 | if (!immap) { | ||
122 | of_node_put(np); | ||
123 | return -ENOMEM; | ||
124 | } | ||
125 | |||
126 | /* Configure clock */ | ||
127 | temp = in_be32(immap + MPC83XX_SCCR_OFFS); | ||
128 | temp &= ~MPC83XX_SCCR_USB_MASK; | ||
129 | temp |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ | ||
130 | out_be32(immap + MPC83XX_SCCR_OFFS, temp); | ||
131 | |||
132 | /* Configure pin mux for ULPI. There is no pin mux for UTMI */ | ||
133 | if (!strcmp(prop, "ulpi")) { | ||
134 | temp = in_be32(immap + MPC83XX_SICRL_OFFS); | ||
135 | temp &= ~MPC831X_SICRL_USB_MASK; | ||
136 | temp |= MPC831X_SICRL_USB_ULPI; | ||
137 | out_be32(immap + MPC83XX_SICRL_OFFS, temp); | ||
138 | |||
139 | temp = in_be32(immap + MPC83XX_SICRH_OFFS); | ||
140 | temp &= ~MPC831X_SICRH_USB_MASK; | ||
141 | temp |= MPC831X_SICRH_USB_ULPI; | ||
142 | out_be32(immap + MPC83XX_SICRH_OFFS, temp); | ||
143 | } | ||
144 | |||
145 | iounmap(immap); | ||
146 | |||
147 | /* Map USB SOC space */ | ||
148 | ret = of_address_to_resource(np, 0, &res); | ||
149 | if (ret) { | ||
150 | of_node_put(np); | ||
151 | return ret; | ||
152 | } | ||
153 | usb_regs = ioremap(res.start, res.end - res.start + 1); | ||
154 | |||
155 | /* Using on-chip PHY */ | ||
156 | if (!strcmp(prop, "utmi_wide") || | ||
157 | !strcmp(prop, "utmi")) { | ||
158 | /* Set UTMI_PHY_EN, REFSEL to 48MHZ */ | ||
159 | out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, | ||
160 | CONTROL_UTMI_PHY_EN | CONTROL_REFSEL_48MHZ); | ||
161 | /* Using external UPLI PHY */ | ||
162 | } else if (!strcmp(prop, "ulpi")) { | ||
163 | /* Set PHY_CLK_SEL to ULPI */ | ||
164 | temp = CONTROL_PHY_CLK_SEL_ULPI; | ||
165 | #ifdef CONFIG_USB_OTG | ||
166 | /* Set OTG_PORT */ | ||
167 | dr_mode = of_get_property(np, "dr_mode", NULL); | ||
168 | if (dr_mode && !strcmp(dr_mode, "otg")) | ||
169 | temp |= CONTROL_OTG_PORT; | ||
170 | #endif /* CONFIG_USB_OTG */ | ||
171 | out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp); | ||
172 | } else { | ||
173 | printk(KERN_WARNING "831x USB PHY type not supported\n"); | ||
174 | ret = -EINVAL; | ||
175 | } | ||
176 | |||
177 | iounmap(usb_regs); | ||
178 | of_node_put(np); | ||
179 | return ret; | ||
180 | } | ||
181 | #endif /* CONFIG_PPC_MPC831x */ | ||