aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorLi Yang <leoli@freescale.com>2007-07-03 05:43:16 -0400
committerKumar Gala <galak@kernel.crashing.org>2007-07-10 01:30:04 -0400
commite5a94af84715d142b1050c927a83dd8b1076774b (patch)
tree6f442560021aecf08658e26ed9a37e6928ef0fa1 /arch/powerpc
parent749e80810d26c8d522b089718f22bb92d7834a37 (diff)
[POWERPC] 83xx: USB platform code rework
Add 831x USB platform setup code and rework 834x USB platform setup code. Move USB platform code to usb.c for different boards with CPU of the same series to share the USB initialization code. Signed-off-by: Li Yang <leoli@freescale.com> Signed-off-by: Kim Phillips <kim.phillips@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/83xx/Makefile2
-rw-r--r--arch/powerpc/platforms/83xx/mpc8313_rdb.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_mds.c49
-rw-r--r--arch/powerpc/platforms/83xx/mpc83xx.h28
-rw-r--r--arch/powerpc/platforms/83xx/usb.c181
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#
4obj-y := misc.o 4obj-y := misc.o usb.o
5obj-$(CONFIG_PCI) += pci.o 5obj-$(CONFIG_PCI) += pci.o
6obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o 6obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o
7obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o 7obj-$(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
53void __init mpc8313_rdb_init_IRQ(void) 54void __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 42static int mpc834xemds_usb_cfg(void)
43 * On PB only port0 is connected using ULPI */
44static 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
135static void __init mpc834x_mds_init_IRQ(void) 96static 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);
34extern void mpc83xx_restart(char *cmd); 54extern void mpc83xx_restart(char *cmd);
35extern long mpc83xx_time_init(void); 55extern long mpc83xx_time_init(void);
56extern int mpc834x_usb_cfg(void);
57extern 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
26int 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
102int 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 */