aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mx5
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-05-20 18:43:18 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-05-20 18:43:18 -0400
commit9bfe99a8f95122f83f3c894b1071b61e2b6d4990 (patch)
treee322752b04deb314b579cae2c5c9993453775823 /arch/arm/mach-mx5
parentf72caf7e496465182eeda842ac66a5e75404ddf1 (diff)
parent54c1f6367c2836a85e821a010085ed04ab2235bc (diff)
Merge branch 'for-rmk' of git://git.pengutronix.de/git/imx/linux-2.6 into devel-stable
Diffstat (limited to 'arch/arm/mach-mx5')
-rw-r--r--arch/arm/mach-mx5/board-mx51_babbage.c167
-rw-r--r--arch/arm/mach-mx5/clock-mx51.c45
-rw-r--r--arch/arm/mach-mx5/devices.c109
-rw-r--r--arch/arm/mach-mx5/devices.h4
4 files changed, 323 insertions, 2 deletions
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index ee67a71db80d..ed885f9d7b73 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -12,11 +12,16 @@
12 12
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/gpio.h>
16#include <linux/delay.h>
17#include <linux/io.h>
18#include <linux/fsl_devices.h>
15 19
16#include <mach/common.h> 20#include <mach/common.h>
17#include <mach/hardware.h> 21#include <mach/hardware.h>
18#include <mach/imx-uart.h> 22#include <mach/imx-uart.h>
19#include <mach/iomux-mx51.h> 23#include <mach/iomux-mx51.h>
24#include <mach/mxc_ehci.h>
20 25
21#include <asm/irq.h> 26#include <asm/irq.h>
22#include <asm/setup.h> 27#include <asm/setup.h>
@@ -26,6 +31,18 @@
26 31
27#include "devices.h" 32#include "devices.h"
28 33
34#define BABBAGE_USB_HUB_RESET (0*32 + 7) /* GPIO_1_7 */
35#define BABBAGE_USBH1_STP (0*32 + 27) /* GPIO_1_27 */
36#define BABBAGE_PHY_RESET (1*32 +5) /* GPIO_2_5 */
37
38/* USB_CTRL_1 */
39#define MX51_USB_CTRL_1_OFFSET 0x10
40#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25)
41
42#define MX51_USB_PLLDIV_12_MHZ 0x00
43#define MX51_USB_PLL_DIV_19_2_MHZ 0x01
44#define MX51_USB_PLL_DIV_24_MHZ 0x02
45
29static struct platform_device *devices[] __initdata = { 46static struct platform_device *devices[] __initdata = {
30 &mxc_fec_device, 47 &mxc_fec_device,
31}; 48};
@@ -46,6 +63,22 @@ static struct pad_desc mx51babbage_pads[] = {
46 MX51_PAD_EIM_D26__UART3_TXD, 63 MX51_PAD_EIM_D26__UART3_TXD,
47 MX51_PAD_EIM_D27__UART3_RTS, 64 MX51_PAD_EIM_D27__UART3_RTS,
48 MX51_PAD_EIM_D24__UART3_CTS, 65 MX51_PAD_EIM_D24__UART3_CTS,
66
67 /* USB HOST1 */
68 MX51_PAD_USBH1_CLK__USBH1_CLK,
69 MX51_PAD_USBH1_DIR__USBH1_DIR,
70 MX51_PAD_USBH1_NXT__USBH1_NXT,
71 MX51_PAD_USBH1_DATA0__USBH1_DATA0,
72 MX51_PAD_USBH1_DATA1__USBH1_DATA1,
73 MX51_PAD_USBH1_DATA2__USBH1_DATA2,
74 MX51_PAD_USBH1_DATA3__USBH1_DATA3,
75 MX51_PAD_USBH1_DATA4__USBH1_DATA4,
76 MX51_PAD_USBH1_DATA5__USBH1_DATA5,
77 MX51_PAD_USBH1_DATA6__USBH1_DATA6,
78 MX51_PAD_USBH1_DATA7__USBH1_DATA7,
79
80 /* USB HUB reset line*/
81 MX51_PAD_GPIO_1_7__GPIO1_7,
49}; 82};
50 83
51/* Serial ports */ 84/* Serial ports */
@@ -66,15 +99,149 @@ static inline void mxc_init_imx_uart(void)
66} 99}
67#endif /* SERIAL_IMX */ 100#endif /* SERIAL_IMX */
68 101
102static int gpio_usbh1_active(void)
103{
104 struct pad_desc usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO_1_27;
105 struct pad_desc phyreset_gpio = MX51_PAD_EIM_D21__GPIO_2_5;
106 int ret;
107
108 /* Set USBH1_STP to GPIO and toggle it */
109 mxc_iomux_v3_setup_pad(&usbh1stp_gpio);
110 ret = gpio_request(BABBAGE_USBH1_STP, "usbh1_stp");
111
112 if (ret) {
113 pr_debug("failed to get MX51_PAD_USBH1_STP__GPIO_1_27: %d\n", ret);
114 return ret;
115 }
116 gpio_direction_output(BABBAGE_USBH1_STP, 0);
117 gpio_set_value(BABBAGE_USBH1_STP, 1);
118 msleep(100);
119 gpio_free(BABBAGE_USBH1_STP);
120
121 /* De-assert USB PHY RESETB */
122 mxc_iomux_v3_setup_pad(&phyreset_gpio);
123 ret = gpio_request(BABBAGE_PHY_RESET, "phy_reset");
124
125 if (ret) {
126 pr_debug("failed to get MX51_PAD_EIM_D21__GPIO_2_5: %d\n", ret);
127 return ret;
128 }
129 gpio_direction_output(BABBAGE_PHY_RESET, 1);
130 return 0;
131}
132
133static inline void babbage_usbhub_reset(void)
134{
135 int ret;
136
137 /* Bring USB hub out of reset */
138 ret = gpio_request(BABBAGE_USB_HUB_RESET, "GPIO1_7");
139 if (ret) {
140 printk(KERN_ERR"failed to get GPIO_USB_HUB_RESET: %d\n", ret);
141 return;
142 }
143 gpio_direction_output(BABBAGE_USB_HUB_RESET, 0);
144
145 /* USB HUB RESET - De-assert USB HUB RESET_N */
146 msleep(1);
147 gpio_set_value(BABBAGE_USB_HUB_RESET, 0);
148 msleep(1);
149 gpio_set_value(BABBAGE_USB_HUB_RESET, 1);
150}
151
152/* This function is board specific as the bit mask for the plldiv will also
153be different for other Freescale SoCs, thus a common bitmask is not
154possible and cannot get place in /plat-mxc/ehci.c.*/
155static int initialize_otg_port(struct platform_device *pdev)
156{
157 u32 v;
158 void __iomem *usb_base;
159 u32 usbother_base;
160
161 usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
162 usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
163
164 /* Set the PHY clock to 19.2MHz */
165 v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
166 v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
167 v |= MX51_USB_PLL_DIV_19_2_MHZ;
168 __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
169 iounmap(usb_base);
170 return 0;
171}
172
173static int initialize_usbh1_port(struct platform_device *pdev)
174{
175 u32 v;
176 void __iomem *usb_base;
177 u32 usbother_base;
178
179 usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
180 usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
181
182 /* The clock for the USBH1 ULPI port will come externally from the PHY. */
183 v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
184 __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
185 iounmap(usb_base);
186 return 0;
187}
188
189static struct mxc_usbh_platform_data dr_utmi_config = {
190 .init = initialize_otg_port,
191 .portsc = MXC_EHCI_UTMI_16BIT,
192 .flags = MXC_EHCI_INTERNAL_PHY,
193};
194
195static struct fsl_usb2_platform_data usb_pdata = {
196 .operating_mode = FSL_USB2_DR_DEVICE,
197 .phy_mode = FSL_USB2_PHY_UTMI_WIDE,
198};
199
200static struct mxc_usbh_platform_data usbh1_config = {
201 .init = initialize_usbh1_port,
202 .portsc = MXC_EHCI_MODE_ULPI,
203 .flags = (MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_ITC_NO_THRESHOLD),
204};
205
206static int otg_mode_host;
207
208static int __init babbage_otg_mode(char *options)
209{
210 if (!strcmp(options, "host"))
211 otg_mode_host = 1;
212 else if (!strcmp(options, "device"))
213 otg_mode_host = 0;
214 else
215 pr_info("otg_mode neither \"host\" nor \"device\". "
216 "Defaulting to device\n");
217 return 0;
218}
219__setup("otg_mode=", babbage_otg_mode);
220
69/* 221/*
70 * Board specific initialization. 222 * Board specific initialization.
71 */ 223 */
72static void __init mxc_board_init(void) 224static void __init mxc_board_init(void)
73{ 225{
226 struct pad_desc usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
227
74 mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads, 228 mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
75 ARRAY_SIZE(mx51babbage_pads)); 229 ARRAY_SIZE(mx51babbage_pads));
76 mxc_init_imx_uart(); 230 mxc_init_imx_uart();
77 platform_add_devices(devices, ARRAY_SIZE(devices)); 231 platform_add_devices(devices, ARRAY_SIZE(devices));
232
233 if (otg_mode_host)
234 mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
235 else {
236 initialize_otg_port(NULL);
237 mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
238 }
239
240 gpio_usbh1_active();
241 mxc_register_device(&mxc_usbh1_device, &usbh1_config);
242 /* setback USBH1_STP to be function */
243 mxc_iomux_v3_setup_pad(&usbh1stp);
244 babbage_usbhub_reset();
78} 245}
79 246
80static void __init mx51_babbage_timer_init(void) 247static void __init mx51_babbage_timer_init(void)
diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
index 1ee6ce4087b8..d9f612d3370e 100644
--- a/arch/arm/mach-mx5/clock-mx51.c
+++ b/arch/arm/mach-mx5/clock-mx51.c
@@ -37,6 +37,7 @@ static struct clk lp_apm_clk;
37static struct clk periph_apm_clk; 37static struct clk periph_apm_clk;
38static struct clk ahb_clk; 38static struct clk ahb_clk;
39static struct clk ipg_clk; 39static struct clk ipg_clk;
40static struct clk usboh3_clk;
40 41
41#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */ 42#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */
42 43
@@ -570,6 +571,35 @@ static int _clk_uart_set_parent(struct clk *clk, struct clk *parent)
570 return 0; 571 return 0;
571} 572}
572 573
574static unsigned long clk_usboh3_get_rate(struct clk *clk)
575{
576 u32 reg, prediv, podf;
577 unsigned long parent_rate;
578
579 parent_rate = clk_get_rate(clk->parent);
580
581 reg = __raw_readl(MXC_CCM_CSCDR1);
582 prediv = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK) >>
583 MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET) + 1;
584 podf = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK) >>
585 MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET) + 1;
586
587 return parent_rate / (prediv * podf);
588}
589
590static int _clk_usboh3_set_parent(struct clk *clk, struct clk *parent)
591{
592 u32 reg, mux;
593
594 mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
595 &lp_apm_clk);
596 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK;
597 reg |= mux << MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET;
598 __raw_writel(reg, MXC_CCM_CSCMR1);
599
600 return 0;
601}
602
573static unsigned long get_high_reference_clock_rate(struct clk *clk) 603static unsigned long get_high_reference_clock_rate(struct clk *clk)
574{ 604{
575 return external_high_reference; 605 return external_high_reference;
@@ -691,6 +721,12 @@ static struct clk uart_root_clk = {
691 .set_parent = _clk_uart_set_parent, 721 .set_parent = _clk_uart_set_parent,
692}; 722};
693 723
724static struct clk usboh3_clk = {
725 .parent = &pll2_sw_clk,
726 .get_rate = clk_usboh3_get_rate,
727 .set_parent = _clk_usboh3_set_parent,
728};
729
694static struct clk ahb_max_clk = { 730static struct clk ahb_max_clk = {
695 .parent = &ahb_clk, 731 .parent = &ahb_clk,
696 .enable_reg = MXC_CCM_CCGR0, 732 .enable_reg = MXC_CCM_CCGR0,
@@ -779,6 +815,12 @@ static struct clk_lookup lookups[] = {
779 _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk) 815 _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
780 _REGISTER_CLOCK(NULL, "gpt", gpt_clk) 816 _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
781 _REGISTER_CLOCK("fec.0", NULL, fec_clk) 817 _REGISTER_CLOCK("fec.0", NULL, fec_clk)
818 _REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
819 _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", ahb_clk)
820 _REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
821 _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", ahb_clk)
822 _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
823 _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
782}; 824};
783 825
784static void clk_tree_init(void) 826static void clk_tree_init(void)
@@ -819,6 +861,9 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
819 clk_enable(&cpu_clk); 861 clk_enable(&cpu_clk);
820 clk_enable(&main_bus_clk); 862 clk_enable(&main_bus_clk);
821 863
864 /* set the usboh3_clk parent to pll2_sw_clk */
865 clk_set_parent(&usboh3_clk, &pll2_sw_clk);
866
822 /* System timer */ 867 /* System timer */
823 mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), 868 mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
824 MX51_MXC_INT_GPT); 869 MX51_MXC_INT_GPT);
diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c
index d6fd3961ade9..7130449aacdc 100644
--- a/arch/arm/mach-mx5/devices.c
+++ b/arch/arm/mach-mx5/devices.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright 2009 Amit Kucheria <amit.kucheria@canonical.com> 2 * Copyright 2009 Amit Kucheria <amit.kucheria@canonical.com>
3 * Copyright (C) 2010 Freescale Semiconductor, Inc.
3 * 4 *
4 * The code contained herein is licensed under the GNU General Public 5 * The code contained herein is licensed under the GNU General Public
5 * License. You may obtain a copy of the GNU General Public License 6 * License. You may obtain a copy of the GNU General Public License
@@ -10,8 +11,11 @@
10 */ 11 */
11 12
12#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/dma-mapping.h>
15#include <linux/gpio.h>
13#include <mach/hardware.h> 16#include <mach/hardware.h>
14#include <mach/imx-uart.h> 17#include <mach/imx-uart.h>
18#include <mach/irqs.h>
15 19
16static struct resource uart0[] = { 20static struct resource uart0[] = {
17 { 21 {
@@ -89,8 +93,109 @@ struct platform_device mxc_fec_device = {
89 .resource = mxc_fec_resources, 93 .resource = mxc_fec_resources,
90}; 94};
91 95
92/* Dummy definition to allow compiling in AVIC and TZIC simultaneously */ 96static u64 usb_dma_mask = DMA_BIT_MASK(32);
97
98static struct resource usbotg_resources[] = {
99 {
100 .start = MX51_OTG_BASE_ADDR,
101 .end = MX51_OTG_BASE_ADDR + 0x1ff,
102 .flags = IORESOURCE_MEM,
103 },
104 {
105 .start = MX51_MXC_INT_USB_OTG,
106 .flags = IORESOURCE_IRQ,
107 },
108};
109
110/* OTG gadget device */
111struct platform_device mxc_usbdr_udc_device = {
112 .name = "fsl-usb2-udc",
113 .id = -1,
114 .num_resources = ARRAY_SIZE(usbotg_resources),
115 .resource = usbotg_resources,
116 .dev = {
117 .dma_mask = &usb_dma_mask,
118 .coherent_dma_mask = DMA_BIT_MASK(32),
119 },
120};
121
122struct platform_device mxc_usbdr_host_device = {
123 .name = "mxc-ehci",
124 .id = 0,
125 .num_resources = ARRAY_SIZE(usbotg_resources),
126 .resource = usbotg_resources,
127 .dev = {
128 .dma_mask = &usb_dma_mask,
129 .coherent_dma_mask = DMA_BIT_MASK(32),
130 },
131};
132
133static struct resource usbh1_resources[] = {
134 {
135 .start = MX51_OTG_BASE_ADDR + 0x200,
136 .end = MX51_OTG_BASE_ADDR + 0x200 + 0x1ff,
137 .flags = IORESOURCE_MEM,
138 },
139 {
140 .start = MX51_MXC_INT_USB_H1,
141 .flags = IORESOURCE_IRQ,
142 },
143};
144
145struct platform_device mxc_usbh1_device = {
146 .name = "mxc-ehci",
147 .id = 1,
148 .num_resources = ARRAY_SIZE(usbh1_resources),
149 .resource = usbh1_resources,
150 .dev = {
151 .dma_mask = &usb_dma_mask,
152 .coherent_dma_mask = DMA_BIT_MASK(32),
153 },
154};
155
156static struct resource mxc_wdt_resources[] = {
157 {
158 .start = MX51_WDOG_BASE_ADDR,
159 .end = MX51_WDOG_BASE_ADDR + SZ_16K - 1,
160 .flags = IORESOURCE_MEM,
161 },
162};
163
164struct platform_device mxc_wdt = {
165 .name = "imx2-wdt",
166 .id = 0,
167 .num_resources = ARRAY_SIZE(mxc_wdt_resources),
168 .resource = mxc_wdt_resources,
169};
170
171static struct mxc_gpio_port mxc_gpio_ports[] = {
172 {
173 .chip.label = "gpio-0",
174 .base = MX51_IO_ADDRESS(MX51_GPIO1_BASE_ADDR),
175 .irq = MX51_MXC_INT_GPIO1_LOW,
176 .virtual_irq_start = MXC_GPIO_IRQ_START
177 },
178 {
179 .chip.label = "gpio-1",
180 .base = MX51_IO_ADDRESS(MX51_GPIO2_BASE_ADDR),
181 .irq = MX51_MXC_INT_GPIO2_LOW,
182 .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 1
183 },
184 {
185 .chip.label = "gpio-2",
186 .base = MX51_IO_ADDRESS(MX51_GPIO3_BASE_ADDR),
187 .irq = MX51_MXC_INT_GPIO3_LOW,
188 .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 2
189 },
190 {
191 .chip.label = "gpio-3",
192 .base = MX51_IO_ADDRESS(MX51_GPIO4_BASE_ADDR),
193 .irq = MX51_MXC_INT_GPIO4_LOW,
194 .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 3
195 },
196};
197
93int __init mxc_register_gpios(void) 198int __init mxc_register_gpios(void)
94{ 199{
95 return 0; 200 return mxc_gpio_init(mxc_gpio_ports, ARRAY_SIZE(mxc_gpio_ports));
96} 201}
diff --git a/arch/arm/mach-mx5/devices.h b/arch/arm/mach-mx5/devices.h
index f339ab8c19be..c879ae71cd5b 100644
--- a/arch/arm/mach-mx5/devices.h
+++ b/arch/arm/mach-mx5/devices.h
@@ -2,3 +2,7 @@ extern struct platform_device mxc_uart_device0;
2extern struct platform_device mxc_uart_device1; 2extern struct platform_device mxc_uart_device1;
3extern struct platform_device mxc_uart_device2; 3extern struct platform_device mxc_uart_device2;
4extern struct platform_device mxc_fec_device; 4extern struct platform_device mxc_fec_device;
5extern struct platform_device mxc_usbdr_host_device;
6extern struct platform_device mxc_usbh1_device;
7extern struct platform_device mxc_usbdr_udc_device;
8extern struct platform_device mxc_wdt;