From a1a54456d08ff8d406b550b60f97088ac7401b8c Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Thu, 13 May 2010 09:45:35 +0300 Subject: omap iommu: Introduce iopgd_is_table MACRO A bit more strict comparison. Signed-off-by: Hiroshi DOYU --- arch/arm/plat-omap/iommu.c | 8 ++++---- arch/arm/plat-omap/iopgtable.h | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c index bc094dbacee6..341c48179ee0 100644 --- a/arch/arm/plat-omap/iommu.c +++ b/arch/arm/plat-omap/iommu.c @@ -653,7 +653,7 @@ void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, u32 **ppte) if (!*iopgd) goto out; - if (*iopgd & IOPGD_TABLE) + if (iopgd_is_table(*iopgd)) iopte = iopte_offset(iopgd, da); out: *ppgd = iopgd; @@ -670,7 +670,7 @@ static size_t iopgtable_clear_entry_core(struct iommu *obj, u32 da) if (!*iopgd) return 0; - if (*iopgd & IOPGD_TABLE) { + if (iopgd_is_table(*iopgd)) { int i; u32 *iopte = iopte_offset(iopgd, da); @@ -745,7 +745,7 @@ static void iopgtable_clear_entry_all(struct iommu *obj) if (!*iopgd) continue; - if (*iopgd & IOPGD_TABLE) + if (iopgd_is_table(*iopgd)) iopte_free(iopte_offset(iopgd, 0)); *iopgd = 0; @@ -785,7 +785,7 @@ static irqreturn_t iommu_fault_handler(int irq, void *data) iopgd = iopgd_offset(obj, da); - if (!(*iopgd & IOPGD_TABLE)) { + if (!iopgd_is_table(*iopgd)) { dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x\n", __func__, da, iopgd, *iopgd); return IRQ_NONE; diff --git a/arch/arm/plat-omap/iopgtable.h b/arch/arm/plat-omap/iopgtable.h index ab23b6a140fd..f2e6b64cca64 100644 --- a/arch/arm/plat-omap/iopgtable.h +++ b/arch/arm/plat-omap/iopgtable.h @@ -63,6 +63,8 @@ #define IOPGD_SECTION (2 << 0) #define IOPGD_SUPER (1 << 18 | 2 << 0) +#define iopgd_is_table(x) (((x) & 3) == IOPGD_TABLE) + #define IOPTE_SMALL (2 << 0) #define IOPTE_LARGE (1 << 0) -- cgit v1.2.3 From 124933599a11cab4b77a6d79d49312754e8ff88e Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Thu, 13 May 2010 09:46:44 +0300 Subject: omap iommu: Rename iopte_[p,v]addr -> iopte_page_[p,v]addr Follow Linux pagetable accessor name convention. Signed-off-by: Hiroshi DOYU --- arch/arm/plat-omap/iopgtable.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/iopgtable.h b/arch/arm/plat-omap/iopgtable.h index f2e6b64cca64..c3e93bb0911f 100644 --- a/arch/arm/plat-omap/iopgtable.h +++ b/arch/arm/plat-omap/iopgtable.h @@ -72,12 +72,12 @@ #define iopgd_index(da) (((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1)) #define iopgd_offset(obj, da) ((obj)->iopgd + iopgd_index(da)) -#define iopte_paddr(iopgd) (*iopgd & ~((1 << 10) - 1)) -#define iopte_vaddr(iopgd) ((u32 *)phys_to_virt(iopte_paddr(iopgd))) +#define iopgd_page_paddr(iopgd) (*iopgd & ~((1 << 10) - 1)) +#define iopgd_page_vaddr(iopgd) ((u32 *)phys_to_virt(iopgd_page_paddr(iopgd))) /* to find an entry in the second-level page table. */ #define iopte_index(da) (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1)) -#define iopte_offset(iopgd, da) (iopte_vaddr(iopgd) + iopte_index(da)) +#define iopte_offset(iopgd, da) (iopgd_page_vaddr(iopgd) + iopte_index(da)) static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa, u32 flags) -- cgit v1.2.3 From 993dd17e32cfb6cc058e1a4394dd113edf764186 Mon Sep 17 00:00:00 2001 From: "Kanigeri, Hari" Date: Mon, 24 May 2010 02:01:50 +0000 Subject: omap iommu: update irq mask to be specific about twl and tlb Revise the IRQ mask definitions to handle the MMU faults related to TWL fault as well as TLB miss fault. Signed-off-by: Hari Kanigeri Signed-off-by: Hiroshi Doyu --- arch/arm/mach-omap2/iommu2.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c index e82da680d908..ebbdae262f78 100644 --- a/arch/arm/mach-omap2/iommu2.c +++ b/arch/arm/mach-omap2/iommu2.c @@ -44,9 +44,13 @@ #define MMU_IRQ_EMUMISS (1 << 2) #define MMU_IRQ_TRANSLATIONFAULT (1 << 1) #define MMU_IRQ_TLBMISS (1 << 0) -#define MMU_IRQ_MASK \ - (MMU_IRQ_MULTIHITFAULT | MMU_IRQ_TABLEWALKFAULT | MMU_IRQ_EMUMISS | \ - MMU_IRQ_TRANSLATIONFAULT) + +#define __MMU_IRQ_FAULT \ + (MMU_IRQ_MULTIHITFAULT | MMU_IRQ_EMUMISS | MMU_IRQ_TRANSLATIONFAULT) +#define MMU_IRQ_MASK \ + (__MMU_IRQ_FAULT | MMU_IRQ_TABLEWALKFAULT | MMU_IRQ_TLBMISS) +#define MMU_IRQ_TWL_MASK (__MMU_IRQ_FAULT | MMU_IRQ_TABLEWALKFAULT) +#define MMU_IRQ_TLB_MISS_MASK (__MMU_IRQ_FAULT | MMU_IRQ_TLBMISS) /* MMU_CNTL */ #define MMU_CNTL_SHIFT 1 @@ -96,7 +100,7 @@ static int omap2_iommu_enable(struct iommu *obj) l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE); iommu_write_reg(obj, l, MMU_SYSCONFIG); - iommu_write_reg(obj, MMU_IRQ_MASK, MMU_IRQENABLE); + iommu_write_reg(obj, MMU_IRQ_TWL_MASK, MMU_IRQENABLE); iommu_write_reg(obj, pa, MMU_TTB); l = iommu_read_reg(obj, MMU_CNTL); -- cgit v1.2.3 From ddfa975a8cf66753a7d829bada753c3617628486 Mon Sep 17 00:00:00 2001 From: "Kanigeri, Hari" Date: Mon, 24 May 2010 02:01:51 +0000 Subject: omap iommu: add functionality to get TLB miss interrupt In order to enable TLB miss interrupt, the TWL should be disabled. This patch provides the functionality to get the MMU fault interrupt for a TLB miss in the cases where the users are working with the locked TLB entries and with TWL disabled. New interface is added to select twl and to enable TLB miss interrupt. Signed-off-by: Hari Kanigeri Signed-off-by: Ramesh Gupta Signed-off-by: Hiroshi Doyu --- arch/arm/mach-omap2/iommu2.c | 32 +++++++++++++++++++++++++++----- arch/arm/plat-omap/include/plat/iommu.h | 2 ++ arch/arm/plat-omap/iommu.c | 17 +++++++++++++++++ 3 files changed, 46 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c index ebbdae262f78..edf7cd4b6553 100644 --- a/arch/arm/mach-omap2/iommu2.c +++ b/arch/arm/mach-omap2/iommu2.c @@ -65,6 +65,26 @@ ((pgsz) == MMU_CAM_PGSZ_64K) ? 0xffff0000 : \ ((pgsz) == MMU_CAM_PGSZ_4K) ? 0xfffff000 : 0) + +static void __iommu_set_twl(struct iommu *obj, bool on) +{ + u32 l = iommu_read_reg(obj, MMU_CNTL); + + if (on) + iommu_write_reg(obj, MMU_IRQ_TWL_MASK, MMU_IRQENABLE); + else + iommu_write_reg(obj, MMU_IRQ_TLB_MISS_MASK, MMU_IRQENABLE); + + l &= ~MMU_CNTL_MASK; + if (on) + l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN); + else + l |= (MMU_CNTL_MMU_EN); + + iommu_write_reg(obj, l, MMU_CNTL); +} + + static int omap2_iommu_enable(struct iommu *obj) { u32 l, pa; @@ -100,13 +120,9 @@ static int omap2_iommu_enable(struct iommu *obj) l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE); iommu_write_reg(obj, l, MMU_SYSCONFIG); - iommu_write_reg(obj, MMU_IRQ_TWL_MASK, MMU_IRQENABLE); iommu_write_reg(obj, pa, MMU_TTB); - l = iommu_read_reg(obj, MMU_CNTL); - l &= ~MMU_CNTL_MASK; - l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN); - iommu_write_reg(obj, l, MMU_CNTL); + __iommu_set_twl(obj, true); return 0; } @@ -122,6 +138,11 @@ static void omap2_iommu_disable(struct iommu *obj) dev_dbg(obj->dev, "%s is shutting down\n", obj->name); } +static void omap2_iommu_set_twl(struct iommu *obj, bool on) +{ + __iommu_set_twl(obj, false); +} + static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra) { int i; @@ -304,6 +325,7 @@ static const struct iommu_functions omap2_iommu_ops = { .enable = omap2_iommu_enable, .disable = omap2_iommu_disable, + .set_twl = omap2_iommu_set_twl, .fault_isr = omap2_iommu_fault_isr, .tlb_read_cr = omap2_tlb_read_cr, diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h index 0752af9d099e..33c7d41cb6a5 100644 --- a/arch/arm/plat-omap/include/plat/iommu.h +++ b/arch/arm/plat-omap/include/plat/iommu.h @@ -80,6 +80,7 @@ struct iommu_functions { int (*enable)(struct iommu *obj); void (*disable)(struct iommu *obj); + void (*set_twl)(struct iommu *obj, bool on); u32 (*fault_isr)(struct iommu *obj, u32 *ra); void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr); @@ -143,6 +144,7 @@ extern void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e); extern u32 iotlb_cr_to_virt(struct cr_regs *cr); extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e); +extern void iommu_set_twl(struct iommu *obj, bool on); extern void flush_iotlb_page(struct iommu *obj, u32 da); extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end); extern void flush_iotlb_all(struct iommu *obj); diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c index 341c48179ee0..688ae66bb8fc 100644 --- a/arch/arm/plat-omap/iommu.c +++ b/arch/arm/plat-omap/iommu.c @@ -370,6 +370,23 @@ void flush_iotlb_all(struct iommu *obj) } EXPORT_SYMBOL_GPL(flush_iotlb_all); +/** + * iommu_set_twl - enable/disable table walking logic + * @obj: target iommu + * @on: enable/disable + * + * Function used to enable/disable TWL. If one wants to work + * exclusively with locked TLB entries and receive notifications + * for TLB miss then call this function to disable TWL. + */ +void iommu_set_twl(struct iommu *obj, bool on) +{ + clk_enable(obj->clk); + arch_iommu->set_twl(obj, on); + clk_disable(obj->clk); +} +EXPORT_SYMBOL_GPL(iommu_set_twl); + #if defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE) ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t bytes) -- cgit v1.2.3 From 37b298100f0ff8b954217635504c860cdb040ccf Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 24 May 2010 02:01:52 +0000 Subject: omap iommu: move iommu_disable at fault to the above layer The function prefix "omap2_iommu_" indicates that the prefixed function belongs to "omap2_iommu_ops" to provide iommu basic functionalities for the above layers. It's better to avoid the prefixed function called in the same prefixed ones internally, like nested here. Now "iommu_disable" is called just after fault_isr() in the above layer. This is a little bit more sensible to keep the consistency of module layers. Signed-off-by: Hiroshi DOYU --- arch/arm/mach-omap2/iommu2.c | 2 +- arch/arm/plat-omap/iommu.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c index edf7cd4b6553..14ee686b6492 100644 --- a/arch/arm/mach-omap2/iommu2.c +++ b/arch/arm/mach-omap2/iommu2.c @@ -172,7 +172,7 @@ static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra) printk("\n"); iommu_write_reg(obj, stat, MMU_IRQSTATUS); - omap2_iommu_disable(obj); + return stat; } diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c index 688ae66bb8fc..a202a2ce6e3d 100644 --- a/arch/arm/plat-omap/iommu.c +++ b/arch/arm/plat-omap/iommu.c @@ -800,6 +800,8 @@ static irqreturn_t iommu_fault_handler(int irq, void *data) if (!stat) return IRQ_HANDLED; + iommu_disable(obj); + iopgd = iopgd_offset(obj, da); if (!iopgd_is_table(*iopgd)) { -- cgit v1.2.3 From 0bbc6fcff6f34ee9cc388d1abc811ac09bf0ddaf Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 24 May 2010 09:35:11 +0300 Subject: omap iommu: Make omap-iommu.o built-in This is a platform device registration. Signed-off-by: Hiroshi DOYU --- arch/arm/mach-omap2/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index ea52b034e963..6c6d7c6f7aee 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -89,7 +89,10 @@ obj-$(CONFIG_OMAP3_EMU) += emu.o obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o mailbox_mach-objs := mailbox.o -obj-$(CONFIG_OMAP_IOMMU) := iommu2.o omap-iommu.o +obj-$(CONFIG_OMAP_IOMMU) += iommu2.o + +iommu-$(CONFIG_OMAP_IOMMU) := omap-iommu.o +obj-y += $(iommu-m) $(iommu-y) i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o obj-y += $(i2c-omap-m) $(i2c-omap-y) -- cgit v1.2.3 From 1fd7f467127fcaea490451052fea22f234bbb206 Mon Sep 17 00:00:00 2001 From: "Kanigeri, Hari" Date: Fri, 14 May 2010 22:55:41 +0000 Subject: omap iommu: update ducati mmu irq define name 2.6.34-rc6 kernel has the Ducati mmu irq define name changed, which is resulting in compilation error. Signed-off-by: Hari Kanigeri Signed-off-by: Hiroshi DOYU --- arch/arm/mach-omap2/omap-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c index eb9bee73e0cb..f5a1aad1a5c0 100644 --- a/arch/arm/mach-omap2/omap-iommu.c +++ b/arch/arm/mach-omap2/omap-iommu.c @@ -59,7 +59,7 @@ static struct platform_device *omap3_iommu_pdev[NR_OMAP3_IOMMU_DEVICES]; static struct iommu_device omap4_devices[] = { { .base = OMAP4_MMU1_BASE, - .irq = INT_44XX_DUCATI_MMU_IRQ, + .irq = OMAP44XX_IRQ_DUCATI_MMU, .pdata = { .name = "ducati", .nr_tlb_entries = 32, -- cgit v1.2.3 From dba638d22d5af5486a861e08ab46e57abef7049a Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 5 Jul 2010 16:31:28 +0300 Subject: omap: Separate out omap2 FS USB platform init functions We want to split old FS USB platform init code and stop doing pin multiplexing under plat-omap. First move 24xx specific init code into omap2_usb[012]_init functions. Cc: David Brownell Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/usb.c | 252 +++++++++++++++++++++++++++++------------------ 1 file changed, 157 insertions(+), 95 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c index d3bf17cd36f3..9c4929a33e52 100644 --- a/arch/arm/plat-omap/usb.c +++ b/arch/arm/plat-omap/usb.c @@ -115,15 +115,56 @@ static void omap2_usb2_enable_5pinunitll(void) omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); } +static u32 __init omap2_usb0_init(unsigned nwires, unsigned is_device) +{ + u32 syscon1 = 0; + + omap2_usb_devconf_clear(0, USB_BIDIR_TLL); + + if (nwires == 0) + return 0; + + if (is_device) + omap_cfg_reg(J20_24XX_USB0_PUEN); + + omap_cfg_reg(K18_24XX_USB0_DAT); + omap_cfg_reg(K19_24XX_USB0_TXEN); + omap_cfg_reg(J14_24XX_USB0_SE0); + if (nwires != 3) + omap_cfg_reg(J18_24XX_USB0_RCV); + + switch (nwires) { + case 3: + syscon1 = 2; + omap2_usb_devconf_set(0, USB_BIDIR); + break; + case 4: + syscon1 = 1; + omap2_usb_devconf_set(0, USB_BIDIR); + break; + case 6: + syscon1 = 3; + omap_cfg_reg(J19_24XX_USB0_VP); + omap_cfg_reg(K20_24XX_USB0_VM); + omap2_usb_devconf_set(0, USB_UNIDIR); + break; + default: + printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", + 0, nwires); + } + + return syscon1 << 16; +} + static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) { u32 syscon1 = 0; if (cpu_is_omap24xx()) - omap2_usb_devconf_clear(0, USB_BIDIR_TLL); + return omap2_usb0_init(nwires, is_device); if (nwires == 0) { - if (cpu_class_is_omap1() && !cpu_is_omap15xx()) { + if (!cpu_is_omap15xx()) { u32 l; /* pulldown D+/D- */ @@ -135,9 +176,7 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) } if (is_device) { - if (cpu_is_omap24xx()) - omap_cfg_reg(J20_24XX_USB0_PUEN); - else if (cpu_is_omap7xx()) { + if (cpu_is_omap7xx()) { omap_cfg_reg(AA17_7XX_USB_DM); omap_cfg_reg(W16_7XX_USB_PU_EN); omap_cfg_reg(W17_7XX_USB_VBUSI); @@ -147,8 +186,7 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) omap_cfg_reg(W4_USB_PUEN); } - /* internal transceiver (unavailable on 17xx, 24xx) */ - if (!cpu_class_is_omap2() && nwires == 2) { + if (nwires == 2) { u32 l; // omap_cfg_reg(P9_USB_DP); @@ -183,26 +221,18 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) return 0; } - if (cpu_is_omap24xx()) { - omap_cfg_reg(K18_24XX_USB0_DAT); - omap_cfg_reg(K19_24XX_USB0_TXEN); - omap_cfg_reg(J14_24XX_USB0_SE0); - if (nwires != 3) - omap_cfg_reg(J18_24XX_USB0_RCV); - } else { - omap_cfg_reg(V6_USB0_TXD); - omap_cfg_reg(W9_USB0_TXEN); - omap_cfg_reg(W5_USB0_SE0); - if (nwires != 3) - omap_cfg_reg(Y5_USB0_RCV); - } + omap_cfg_reg(V6_USB0_TXD); + omap_cfg_reg(W9_USB0_TXEN); + omap_cfg_reg(W5_USB0_SE0); + if (nwires != 3) + omap_cfg_reg(Y5_USB0_RCV); /* NOTE: SPEED and SUSP aren't configured here. OTG hosts * may be able to use I2C requests to set those bits along * with VBUS switching and overcurrent detection. */ - if (cpu_class_is_omap1() && nwires != 6) { + if (nwires != 6) { u32 l; l = omap_readl(USB_TRANSCEIVER_CTRL); @@ -213,21 +243,13 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) switch (nwires) { case 3: syscon1 = 2; - if (cpu_is_omap24xx()) - omap2_usb_devconf_set(0, USB_BIDIR); break; case 4: syscon1 = 1; - if (cpu_is_omap24xx()) - omap2_usb_devconf_set(0, USB_BIDIR); break; case 6: syscon1 = 3; - if (cpu_is_omap24xx()) { - omap_cfg_reg(J19_24XX_USB0_VP); - omap_cfg_reg(K20_24XX_USB0_VM); - omap2_usb_devconf_set(0, USB_UNIDIR); - } else { + { u32 l; omap_cfg_reg(AA9_USB0_VP); @@ -244,30 +266,66 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) return syscon1 << 16; } +static u32 __init omap2_usb1_init(unsigned nwires) +{ + u32 syscon1 = 0; + + omap2_usb_devconf_clear(1, USB_BIDIR_TLL); + + if (nwires == 0) + return 0; + + /* NOTE: board-specific code must set up pin muxing for usb1, + * since each signal could come out on either of two balls. + */ + + switch (nwires) { + case 2: + /* NOTE: board-specific code must override this setting if + * this TLL link is not using DP/DM + */ + syscon1 = 1; + omap2_usb_devconf_set(1, USB_BIDIR_TLL); + break; + case 3: + syscon1 = 2; + omap2_usb_devconf_set(1, USB_BIDIR); + break; + case 4: + syscon1 = 1; + omap2_usb_devconf_set(1, USB_BIDIR); + break; + case 6: + default: + printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", + 1, nwires); + } + + return syscon1 << 20; +} + static u32 __init omap_usb1_init(unsigned nwires) { u32 syscon1 = 0; - if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) { + if (cpu_is_omap24xx()) + return omap2_usb1_init(nwires); + + if (!cpu_is_omap15xx() && nwires != 6) { u32 l; l = omap_readl(USB_TRANSCEIVER_CTRL); l &= ~CONF_USB1_UNI_R; omap_writel(l, USB_TRANSCEIVER_CTRL); } - if (cpu_is_omap24xx()) - omap2_usb_devconf_clear(1, USB_BIDIR_TLL); - if (nwires == 0) return 0; /* external transceiver */ - if (cpu_class_is_omap1()) { - omap_cfg_reg(USB1_TXD); - omap_cfg_reg(USB1_TXEN); - if (nwires != 3) - omap_cfg_reg(USB1_RCV); - } + omap_cfg_reg(USB1_TXD); + omap_cfg_reg(USB1_TXEN); + if (nwires != 3) + omap_cfg_reg(USB1_RCV); if (cpu_is_omap15xx()) { omap_cfg_reg(USB1_SEO); @@ -280,10 +338,6 @@ static u32 __init omap_usb1_init(unsigned nwires) } else if (cpu_is_omap1710()) { omap_cfg_reg(R13_1710_USB1_SE0); // SUSP - } else if (cpu_is_omap24xx()) { - /* NOTE: board-specific code must set up pin muxing for usb1, - * since each signal could come out on either of two balls. - */ } else { pr_debug("usb%d cpu unrecognized\n", 1); return 0; @@ -291,27 +345,14 @@ static u32 __init omap_usb1_init(unsigned nwires) switch (nwires) { case 2: - if (!cpu_is_omap24xx()) - goto bad; - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM - */ - syscon1 = 1; - omap2_usb_devconf_set(1, USB_BIDIR_TLL); - break; + goto bad; case 3: syscon1 = 2; - if (cpu_is_omap24xx()) - omap2_usb_devconf_set(1, USB_BIDIR); break; case 4: syscon1 = 1; - if (cpu_is_omap24xx()) - omap2_usb_devconf_set(1, USB_BIDIR); break; case 6: - if (cpu_is_omap24xx()) - goto bad; syscon1 = 3; omap_cfg_reg(USB1_VP); omap_cfg_reg(USB1_VM); @@ -331,20 +372,70 @@ bad: return syscon1 << 20; } -static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) +static u32 __init omap2_usb2_init(unsigned nwires, unsigned alt_pingroup) { u32 syscon1 = 0; - if (cpu_is_omap24xx()) { - omap2_usb2_disable_5pinbitll(); - alt_pingroup = 0; + omap2_usb2_disable_5pinbitll(); + alt_pingroup = 0; + + /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */ + if (alt_pingroup || nwires == 0) + return 0; + + omap_cfg_reg(Y11_24XX_USB2_DAT); + omap_cfg_reg(AA10_24XX_USB2_SE0); + if (nwires > 2) + omap_cfg_reg(AA12_24XX_USB2_TXEN); + if (nwires > 3) + omap_cfg_reg(AA6_24XX_USB2_RCV); + + switch (nwires) { + case 2: + /* NOTE: board-specific code must override this setting if + * this TLL link is not using DP/DM + */ + syscon1 = 1; + omap2_usb_devconf_set(2, USB_BIDIR_TLL); + break; + case 3: + syscon1 = 2; + omap2_usb_devconf_set(2, USB_BIDIR); + break; + case 4: + syscon1 = 1; + omap2_usb_devconf_set(2, USB_BIDIR); + break; + case 5: + omap_cfg_reg(AA4_24XX_USB2_TLLSE0); + /* NOTE: board-specific code must override this setting if + * this TLL link is not using DP/DM. Something must also + * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED} + */ + syscon1 = 3; + omap2_usb2_enable_5pinunitll(); + break; + case 6: + default: + printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", + 2, nwires); } + return syscon1 << 24; +} + +static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) +{ + u32 syscon1 = 0; + + if (cpu_is_omap24xx()) + return omap2_usb2_init(nwires, alt_pingroup); + /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */ if (alt_pingroup || nwires == 0) return 0; - if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) { + if (!cpu_is_omap15xx() && nwires != 6) { u32 l; l = omap_readl(USB_TRANSCEIVER_CTRL); @@ -367,53 +458,24 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) if (nwires != 3) omap_cfg_reg(Y5_USB2_RCV); // FIXME omap_cfg_reg(USB2_SPEED); - } else if (cpu_is_omap24xx()) { - omap_cfg_reg(Y11_24XX_USB2_DAT); - omap_cfg_reg(AA10_24XX_USB2_SE0); - if (nwires > 2) - omap_cfg_reg(AA12_24XX_USB2_TXEN); - if (nwires > 3) - omap_cfg_reg(AA6_24XX_USB2_RCV); } else { pr_debug("usb%d cpu unrecognized\n", 1); return 0; } - // if (cpu_class_is_omap1()) omap_cfg_reg(USB2_SUSP); + // omap_cfg_reg(USB2_SUSP); switch (nwires) { case 2: - if (!cpu_is_omap24xx()) - goto bad; - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM - */ - syscon1 = 1; - omap2_usb_devconf_set(2, USB_BIDIR_TLL); - break; + goto bad; case 3: syscon1 = 2; - if (cpu_is_omap24xx()) - omap2_usb_devconf_set(2, USB_BIDIR); break; case 4: syscon1 = 1; - if (cpu_is_omap24xx()) - omap2_usb_devconf_set(2, USB_BIDIR); break; case 5: - if (!cpu_is_omap24xx()) - goto bad; - omap_cfg_reg(AA4_24XX_USB2_TLLSE0); - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM. Something must also - * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED} - */ - syscon1 = 3; - omap2_usb2_enable_5pinunitll(); - break; + goto bad; case 6: - if (cpu_is_omap24xx()) - goto bad; syscon1 = 3; if (cpu_is_omap15xx()) { omap_cfg_reg(USB2_VP); -- cgit v1.2.3 From b5e8905bcd7a794b667f6d5eabcb036f25358fdb Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 5 Jul 2010 16:31:29 +0300 Subject: omap: Move omap2 FS USB platform init code into mach-omap2/usb-fs.c Move omap2 FS USB platform init code into mach-omap2/usb-fs.c. This will allow further work later on to use omap hwmod for initializing the device. Cc: David Brownell Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Makefile | 2 + arch/arm/mach-omap2/board-2430sdp.c | 2 +- arch/arm/mach-omap2/board-apollon.c | 2 +- arch/arm/mach-omap2/board-h4.c | 2 +- arch/arm/mach-omap2/usb-fs.c | 345 ++++++++++++++++++++++++++++++++ arch/arm/plat-omap/include/plat/board.h | 8 + arch/arm/plat-omap/include/plat/usb.h | 7 + arch/arm/plat-omap/usb.c | 267 ++++++------------------ 8 files changed, 429 insertions(+), 206 deletions(-) create mode 100644 arch/arm/mach-omap2/usb-fs.c (limited to 'arch') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 6c6d7c6f7aee..3b384188e28e 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -149,6 +149,8 @@ obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o obj-$(CONFIG_MACH_SBC3530) += board-omap3stalker.o \ hsmmc.o # Platform specific device init code +usbfs-$(CONFIG_ARCH_OMAP_OTG) := usb-fs.o +obj-y += $(usbfs-m) $(usbfs-y) obj-y += usb-musb.o obj-$(CONFIG_MACH_OMAP2_TUSB6010) += usb-tusb6010.o obj-y += usb-ehci.o diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index a11a575745e4..ec920c90a526 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -226,7 +226,7 @@ static void __init omap_2430sdp_init(void) platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices)); omap_serial_init(); omap2_hsmmc_init(mmc); - omap_usb_init(&sdp2430_usb_config); + omap2_usbfs_init(&sdp2430_usb_config); usb_musb_init(&musb_board_data); board_smc91x_init(); diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index aa69fb999748..987b24d400a8 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -306,7 +306,7 @@ static void __init apollon_usb_init(void) omap_cfg_reg(P21_242X_GPIO12); gpio_request(12, "USB suspend"); gpio_direction_output(12, 0); - omap_usb_init(&apollon_usb_config); + omap2_usbfs_init(&apollon_usb_config); } static void __init omap_apollon_init(void) diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 0665f2c8dc8e..54a231c7465e 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -362,7 +362,7 @@ static void __init omap_h4_init(void) ARRAY_SIZE(h4_i2c_board_info)); platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices)); - omap_usb_init(&h4_usb_config); + omap2_usbfs_init(&h4_usb_config); omap_serial_init(); } diff --git a/arch/arm/mach-omap2/usb-fs.c b/arch/arm/mach-omap2/usb-fs.c new file mode 100644 index 000000000000..f63e5766b6bc --- /dev/null +++ b/arch/arm/mach-omap2/usb-fs.c @@ -0,0 +1,345 @@ +/* + * Platform level USB initialization for FS USB OTG controller on omap1 and 24xx + * + * Copyright (C) 2004 Texas Instruments, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#define INT_USB_IRQ_GEN INT_24XX_USB_IRQ_GEN +#define INT_USB_IRQ_NISO INT_24XX_USB_IRQ_NISO +#define INT_USB_IRQ_ISO INT_24XX_USB_IRQ_ISO +#define INT_USB_IRQ_HGEN INT_24XX_USB_IRQ_HGEN +#define INT_USB_IRQ_OTG INT_24XX_USB_IRQ_OTG + +#if defined(CONFIG_ARCH_OMAP2) + +#ifdef CONFIG_USB_GADGET_OMAP + +static struct resource udc_resources[] = { + /* order is significant! */ + { /* registers */ + .start = UDC_BASE, + .end = UDC_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, { /* general IRQ */ + .start = INT_USB_IRQ_GEN, + .flags = IORESOURCE_IRQ, + }, { /* PIO IRQ */ + .start = INT_USB_IRQ_NISO, + .flags = IORESOURCE_IRQ, + }, { /* SOF IRQ */ + .start = INT_USB_IRQ_ISO, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 udc_dmamask = ~(u32)0; + +static struct platform_device udc_device = { + .name = "omap_udc", + .id = -1, + .dev = { + .dma_mask = &udc_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(udc_resources), + .resource = udc_resources, +}; + +static inline void udc_device_init(struct omap_usb_config *pdata) +{ + pdata->udc_device = &udc_device; +} + +#else + +static inline void udc_device_init(struct omap_usb_config *pdata) +{ +} + +#endif + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) + +/* The dmamask must be set for OHCI to work */ +static u64 ohci_dmamask = ~(u32)0; + +static struct resource ohci_resources[] = { + { + .start = OMAP_OHCI_BASE, + .end = OMAP_OHCI_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_USB_IRQ_HGEN, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device ohci_device = { + .name = "ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(ohci_resources), + .resource = ohci_resources, +}; + +static inline void ohci_device_init(struct omap_usb_config *pdata) +{ + pdata->ohci_device = &ohci_device; +} + +#else + +static inline void ohci_device_init(struct omap_usb_config *pdata) +{ +} + +#endif + +#if defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG) + +static struct resource otg_resources[] = { + /* order is significant! */ + { + .start = OTG_BASE, + .end = OTG_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, { + .start = INT_USB_IRQ_OTG, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device otg_device = { + .name = "omap_otg", + .id = -1, + .num_resources = ARRAY_SIZE(otg_resources), + .resource = otg_resources, +}; + +static inline void otg_device_init(struct omap_usb_config *pdata) +{ + pdata->otg_device = &otg_device; +} + +#else + +static inline void otg_device_init(struct omap_usb_config *pdata) +{ +} + +#endif + +static void omap2_usb_devconf_clear(u8 port, u32 mask) +{ + u32 r; + + r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); + r &= ~USBTXWRMODEI(port, mask); + omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); +} + +static void omap2_usb_devconf_set(u8 port, u32 mask) +{ + u32 r; + + r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); + r |= USBTXWRMODEI(port, mask); + omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); +} + +static void omap2_usb2_disable_5pinbitll(void) +{ + u32 r; + + r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); + r &= ~(USBTXWRMODEI(2, USB_BIDIR_TLL) | USBT2TLL5PI); + omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); +} + +static void omap2_usb2_enable_5pinunitll(void) +{ + u32 r; + + r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); + r |= USBTXWRMODEI(2, USB_UNIDIR_TLL) | USBT2TLL5PI; + omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); +} + +static u32 __init omap2_usb0_init(unsigned nwires, unsigned is_device) +{ + u32 syscon1 = 0; + + omap2_usb_devconf_clear(0, USB_BIDIR_TLL); + + if (nwires == 0) + return 0; + + if (is_device) + omap_cfg_reg(J20_24XX_USB0_PUEN); + + omap_cfg_reg(K18_24XX_USB0_DAT); + omap_cfg_reg(K19_24XX_USB0_TXEN); + omap_cfg_reg(J14_24XX_USB0_SE0); + if (nwires != 3) + omap_cfg_reg(J18_24XX_USB0_RCV); + + switch (nwires) { + case 3: + syscon1 = 2; + omap2_usb_devconf_set(0, USB_BIDIR); + break; + case 4: + syscon1 = 1; + omap2_usb_devconf_set(0, USB_BIDIR); + break; + case 6: + syscon1 = 3; + omap_cfg_reg(J19_24XX_USB0_VP); + omap_cfg_reg(K20_24XX_USB0_VM); + omap2_usb_devconf_set(0, USB_UNIDIR); + break; + default: + printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", + 0, nwires); + } + + return syscon1 << 16; +} + +static u32 __init omap2_usb1_init(unsigned nwires) +{ + u32 syscon1 = 0; + + omap2_usb_devconf_clear(1, USB_BIDIR_TLL); + + if (nwires == 0) + return 0; + + /* NOTE: board-specific code must set up pin muxing for usb1, + * since each signal could come out on either of two balls. + */ + + switch (nwires) { + case 2: + /* NOTE: board-specific code must override this setting if + * this TLL link is not using DP/DM + */ + syscon1 = 1; + omap2_usb_devconf_set(1, USB_BIDIR_TLL); + break; + case 3: + syscon1 = 2; + omap2_usb_devconf_set(1, USB_BIDIR); + break; + case 4: + syscon1 = 1; + omap2_usb_devconf_set(1, USB_BIDIR); + break; + case 6: + default: + printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", + 1, nwires); + } + + return syscon1 << 20; +} + +static u32 __init omap2_usb2_init(unsigned nwires, unsigned alt_pingroup) +{ + u32 syscon1 = 0; + + omap2_usb2_disable_5pinbitll(); + alt_pingroup = 0; + + /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */ + if (alt_pingroup || nwires == 0) + return 0; + + omap_cfg_reg(Y11_24XX_USB2_DAT); + omap_cfg_reg(AA10_24XX_USB2_SE0); + if (nwires > 2) + omap_cfg_reg(AA12_24XX_USB2_TXEN); + if (nwires > 3) + omap_cfg_reg(AA6_24XX_USB2_RCV); + + switch (nwires) { + case 2: + /* NOTE: board-specific code must override this setting if + * this TLL link is not using DP/DM + */ + syscon1 = 1; + omap2_usb_devconf_set(2, USB_BIDIR_TLL); + break; + case 3: + syscon1 = 2; + omap2_usb_devconf_set(2, USB_BIDIR); + break; + case 4: + syscon1 = 1; + omap2_usb_devconf_set(2, USB_BIDIR); + break; + case 5: + omap_cfg_reg(AA4_24XX_USB2_TLLSE0); + /* NOTE: board-specific code must override this setting if + * this TLL link is not using DP/DM. Something must also + * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED} + */ + syscon1 = 3; + omap2_usb2_enable_5pinunitll(); + break; + case 6: + default: + printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", + 2, nwires); + } + + return syscon1 << 24; +} + +void __init omap2_usbfs_init(struct omap_usb_config *pdata) +{ + if (!cpu_is_omap24xx()) + return; + + pdata->usb0_init = omap2_usb0_init; + pdata->usb1_init = omap2_usb1_init; + pdata->usb2_init = omap2_usb2_init; + udc_device_init(pdata); + ohci_device_init(pdata); + otg_device_init(pdata); + omap_otg_init(pdata); +} + +#endif diff --git a/arch/arm/plat-omap/include/plat/board.h b/arch/arm/plat-omap/include/plat/board.h index 5cd622039da0..3cf4fa25ab3d 100644 --- a/arch/arm/plat-omap/include/plat/board.h +++ b/arch/arm/plat-omap/include/plat/board.h @@ -85,6 +85,14 @@ struct omap_usb_config { * 6 == 6 wire unidirectional (or TLL) */ u8 pins[3]; + + struct platform_device *udc_device; + struct platform_device *ohci_device; + struct platform_device *otg_device; + + u32 (*usb0_init)(unsigned nwires, unsigned is_device); + u32 (*usb1_init)(unsigned nwires); + u32 (*usb2_init)(unsigned nwires, unsigned alt_pingroup); }; struct omap_lcd_config { diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h index 98eef5360e6d..9f792244e77c 100644 --- a/arch/arm/plat-omap/include/plat/usb.h +++ b/arch/arm/plat-omap/include/plat/usb.h @@ -81,7 +81,14 @@ extern void usb_ohci_init(const struct ohci_hcd_omap_platform_data *pdata); #endif +void omap_otg_init(struct omap_usb_config *config); void omap_usb_init(struct omap_usb_config *pdata); +void omap2_usbfs_init(struct omap_usb_config *pdata); +#else +static inline omap2_usbfs_init(struct omap_usb_config *pdata) +{ +} +#endif /*-------------------------------------------------------------------------*/ diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c index 9c4929a33e52..27b471ce11a0 100644 --- a/arch/arm/plat-omap/usb.c +++ b/arch/arm/plat-omap/usb.c @@ -38,25 +38,12 @@ #include #include -#ifdef CONFIG_ARCH_OMAP1 - #define INT_USB_IRQ_GEN IH2_BASE + 20 #define INT_USB_IRQ_NISO IH2_BASE + 30 #define INT_USB_IRQ_ISO IH2_BASE + 29 #define INT_USB_IRQ_HGEN INT_USB_HHC_1 #define INT_USB_IRQ_OTG IH2_BASE + 8 -#else - -#define INT_USB_IRQ_GEN INT_24XX_USB_IRQ_GEN -#define INT_USB_IRQ_NISO INT_24XX_USB_IRQ_NISO -#define INT_USB_IRQ_ISO INT_24XX_USB_IRQ_ISO -#define INT_USB_IRQ_HGEN INT_24XX_USB_IRQ_HGEN -#define INT_USB_IRQ_OTG INT_24XX_USB_IRQ_OTG - -#endif - - /* These routines should handle the standard chip-specific modes * for usb0/1/2 ports, covering basic mux and transceiver setup. * @@ -79,90 +66,10 @@ #if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_ARCH_OMAP15XX) -static void omap2_usb_devconf_clear(u8 port, u32 mask) -{ - u32 r; - - r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - r &= ~USBTXWRMODEI(port, mask); - omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); -} - -static void omap2_usb_devconf_set(u8 port, u32 mask) -{ - u32 r; - - r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - r |= USBTXWRMODEI(port, mask); - omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); -} - -static void omap2_usb2_disable_5pinbitll(void) -{ - u32 r; - - r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - r &= ~(USBTXWRMODEI(2, USB_BIDIR_TLL) | USBT2TLL5PI); - omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); -} - -static void omap2_usb2_enable_5pinunitll(void) -{ - u32 r; - - r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - r |= USBTXWRMODEI(2, USB_UNIDIR_TLL) | USBT2TLL5PI; - omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); -} - -static u32 __init omap2_usb0_init(unsigned nwires, unsigned is_device) -{ - u32 syscon1 = 0; - - omap2_usb_devconf_clear(0, USB_BIDIR_TLL); - - if (nwires == 0) - return 0; - - if (is_device) - omap_cfg_reg(J20_24XX_USB0_PUEN); - - omap_cfg_reg(K18_24XX_USB0_DAT); - omap_cfg_reg(K19_24XX_USB0_TXEN); - omap_cfg_reg(J14_24XX_USB0_SE0); - if (nwires != 3) - omap_cfg_reg(J18_24XX_USB0_RCV); - - switch (nwires) { - case 3: - syscon1 = 2; - omap2_usb_devconf_set(0, USB_BIDIR); - break; - case 4: - syscon1 = 1; - omap2_usb_devconf_set(0, USB_BIDIR); - break; - case 6: - syscon1 = 3; - omap_cfg_reg(J19_24XX_USB0_VP); - omap_cfg_reg(K20_24XX_USB0_VM); - omap2_usb_devconf_set(0, USB_UNIDIR); - break; - default: - printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", - 0, nwires); - } - - return syscon1 << 16; -} - static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) { u32 syscon1 = 0; - if (cpu_is_omap24xx()) - return omap2_usb0_init(nwires, is_device); - if (nwires == 0) { if (!cpu_is_omap15xx()) { u32 l; @@ -266,51 +173,10 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) return syscon1 << 16; } -static u32 __init omap2_usb1_init(unsigned nwires) -{ - u32 syscon1 = 0; - - omap2_usb_devconf_clear(1, USB_BIDIR_TLL); - - if (nwires == 0) - return 0; - - /* NOTE: board-specific code must set up pin muxing for usb1, - * since each signal could come out on either of two balls. - */ - - switch (nwires) { - case 2: - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM - */ - syscon1 = 1; - omap2_usb_devconf_set(1, USB_BIDIR_TLL); - break; - case 3: - syscon1 = 2; - omap2_usb_devconf_set(1, USB_BIDIR); - break; - case 4: - syscon1 = 1; - omap2_usb_devconf_set(1, USB_BIDIR); - break; - case 6: - default: - printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", - 1, nwires); - } - - return syscon1 << 20; -} - static u32 __init omap_usb1_init(unsigned nwires) { u32 syscon1 = 0; - if (cpu_is_omap24xx()) - return omap2_usb1_init(nwires); - if (!cpu_is_omap15xx() && nwires != 6) { u32 l; @@ -372,65 +238,10 @@ bad: return syscon1 << 20; } -static u32 __init omap2_usb2_init(unsigned nwires, unsigned alt_pingroup) -{ - u32 syscon1 = 0; - - omap2_usb2_disable_5pinbitll(); - alt_pingroup = 0; - - /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */ - if (alt_pingroup || nwires == 0) - return 0; - - omap_cfg_reg(Y11_24XX_USB2_DAT); - omap_cfg_reg(AA10_24XX_USB2_SE0); - if (nwires > 2) - omap_cfg_reg(AA12_24XX_USB2_TXEN); - if (nwires > 3) - omap_cfg_reg(AA6_24XX_USB2_RCV); - - switch (nwires) { - case 2: - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM - */ - syscon1 = 1; - omap2_usb_devconf_set(2, USB_BIDIR_TLL); - break; - case 3: - syscon1 = 2; - omap2_usb_devconf_set(2, USB_BIDIR); - break; - case 4: - syscon1 = 1; - omap2_usb_devconf_set(2, USB_BIDIR); - break; - case 5: - omap_cfg_reg(AA4_24XX_USB2_TLLSE0); - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM. Something must also - * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED} - */ - syscon1 = 3; - omap2_usb2_enable_5pinunitll(); - break; - case 6: - default: - printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", - 2, nwires); - } - - return syscon1 << 24; -} - static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) { u32 syscon1 = 0; - if (cpu_is_omap24xx()) - return omap2_usb2_init(nwires, alt_pingroup); - /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */ if (alt_pingroup || nwires == 0) return 0; @@ -498,6 +309,10 @@ bad: return syscon1 << 24; } +#else +#define omap_usb0_init NULL +#define omap_usb1_init NULL +#define omap_usb2_init NULL #endif /*-------------------------------------------------------------------------*/ @@ -535,6 +350,17 @@ static struct platform_device udc_device = { .resource = udc_resources, }; +static inline void udc_device_init(struct omap_usb_config *pdata) +{ + pdata->udc_device = &udc_device; +} + +#else + +static inline void udc_device_init(struct omap_usb_config *pdata) +{ +} + #endif #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) @@ -565,6 +391,17 @@ static struct platform_device ohci_device = { .resource = ohci_resources, }; +static inline void ohci_device_init(struct omap_usb_config *pdata) +{ + pdata->ohci_device = &ohci_device; +} + +#else + +static inline void ohci_device_init(struct omap_usb_config *pdata) +{ +} + #endif #if defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG) @@ -588,6 +425,17 @@ static struct platform_device otg_device = { .resource = otg_resources, }; +static inline void otg_device_init(struct omap_usb_config *pdata) +{ + pdata->otg_device = &otg_device; +} + +#else + +static inline void otg_device_init(struct omap_usb_config *pdata) +{ +} + #endif /*-------------------------------------------------------------------------*/ @@ -622,9 +470,9 @@ omap_otg_init(struct omap_usb_config *config) /* pin muxing and transceiver pinouts */ if (config->pins[0] > 2) /* alt pingroup 2 */ alt_pingroup = 1; - syscon |= omap_usb0_init(config->pins[0], is_usb0_device(config)); - syscon |= omap_usb1_init(config->pins[1]); - syscon |= omap_usb2_init(config->pins[2], alt_pingroup); + syscon |= config->usb0_init(config->pins[0], is_usb0_device(config)); + syscon |= config->usb1_init(config->pins[1]); + syscon |= config->usb2_init(config->pins[2], alt_pingroup); pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1)); omap_writel(syscon, OTG_SYSCON_1); @@ -672,15 +520,17 @@ omap_otg_init(struct omap_usb_config *config) #ifdef CONFIG_USB_GADGET_OMAP if (config->otg || config->register_dev) { + struct platform_device *udc_device = config->udc_device; + syscon &= ~DEV_IDLE_EN; - udc_device.dev.platform_data = config; + udc_device->dev.platform_data = config; /* IRQ numbers for omap7xx */ if(cpu_is_omap7xx()) { udc_resources[1].start = INT_7XX_USB_GENI; udc_resources[2].start = INT_7XX_USB_NON_ISO; udc_resources[3].start = INT_7XX_USB_ISO; } - status = platform_device_register(&udc_device); + status = platform_device_register(udc_device); if (status) pr_debug("can't register UDC device, %d\n", status); } @@ -688,11 +538,13 @@ omap_otg_init(struct omap_usb_config *config) #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) if (config->otg || config->register_host) { + struct platform_device *ohci_device = config->ohci_device; + syscon &= ~HST_IDLE_EN; - ohci_device.dev.platform_data = config; + ohci_device->dev.platform_data = config; if (cpu_is_omap7xx()) ohci_resources[1].start = INT_7XX_USB_HHC_1; - status = platform_device_register(&ohci_device); + status = platform_device_register(ohci_device); if (status) pr_debug("can't register OHCI device, %d\n", status); } @@ -700,11 +552,13 @@ omap_otg_init(struct omap_usb_config *config) #ifdef CONFIG_USB_OTG if (config->otg) { + struct platform_device *otg_device = config->otg_device; + syscon &= ~OTG_IDLE_EN; - otg_device.dev.platform_data = config; + otg_device->dev.platform_data = config; if (cpu_is_omap7xx()) otg_resources[1].start = INT_7XX_USB_OTG; - status = platform_device_register(&otg_device); + status = platform_device_register(otg_device); if (status) pr_debug("can't register OTG device, %d\n", status); } @@ -716,7 +570,7 @@ omap_otg_init(struct omap_usb_config *config) } #else -static inline void omap_otg_init(struct omap_usb_config *config) {} +void omap_otg_init(struct omap_usb_config *config) {} #endif /*-------------------------------------------------------------------------*/ @@ -737,9 +591,9 @@ static void __init omap_1510_usb_init(struct omap_usb_config *config) unsigned int val; u16 w; - omap_usb0_init(config->pins[0], is_usb0_device(config)); - omap_usb1_init(config->pins[1]); - omap_usb2_init(config->pins[2], 0); + config->usb0_init(config->pins[0], is_usb0_device(config)); + config->usb1_init(config->pins[1]); + config->usb2_init(config->pins[2], 0); val = omap_readl(MOD_CONF_CTRL_0) & ~(0x3f << 1); val |= (config->hmc_mode << 1); @@ -807,7 +661,14 @@ static inline void omap_1510_usb_init(struct omap_usb_config *config) {} void __init omap_usb_init(struct omap_usb_config *pdata) { - if (cpu_is_omap7xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) + pdata->usb0_init = omap_usb0_init; + pdata->usb1_init = omap_usb1_init; + pdata->usb2_init = omap_usb2_init; + udc_device_init(pdata); + ohci_device_init(pdata); + otg_device_init(pdata); + + if (cpu_is_omap7xx() || cpu_is_omap16xx()) omap_otg_init(pdata); else if (cpu_is_omap15xx()) omap_1510_usb_init(pdata); -- cgit v1.2.3 From 98093839307cbf1a0d5cb50b495d14a78b755ed9 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 5 Jul 2010 16:31:29 +0300 Subject: omap: Enable interface clock for omap2 FS USB Looks like this code was only working on boards that had the usb_l4_ick enabled in the bootloader. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/usb-fs.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-omap2/usb-fs.c b/arch/arm/mach-omap2/usb-fs.c index f63e5766b6bc..a4455190b216 100644 --- a/arch/arm/mach-omap2/usb-fs.c +++ b/arch/arm/mach-omap2/usb-fs.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include @@ -330,9 +332,16 @@ static u32 __init omap2_usb2_init(unsigned nwires, unsigned alt_pingroup) void __init omap2_usbfs_init(struct omap_usb_config *pdata) { + struct clk *ick; + if (!cpu_is_omap24xx()) return; + ick = clk_get(NULL, "usb_l4_ick"); + if (IS_ERR(ick)) + return; + + clk_enable(ick); pdata->usb0_init = omap2_usb0_init; pdata->usb1_init = omap2_usb1_init; pdata->usb2_init = omap2_usb2_init; @@ -340,6 +349,8 @@ void __init omap2_usbfs_init(struct omap_usb_config *pdata) ohci_device_init(pdata); otg_device_init(pdata); omap_otg_init(pdata); + clk_disable(ick); + clk_put(ick); } #endif -- cgit v1.2.3 From dd0cdd888251d0d62df417d6859e74e57146c13f Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 5 Jul 2010 16:31:30 +0300 Subject: omap: Move omap1 USB platform init code into mach-omap1/usb.c Move omap1 FS USB platform init code into mach-omap1/usb.c Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/Makefile | 3 + arch/arm/mach-omap1/board-ams-delta.c | 2 +- arch/arm/mach-omap1/board-generic.c | 4 +- arch/arm/mach-omap1/board-h2.c | 2 +- arch/arm/mach-omap1/board-h3.c | 2 +- arch/arm/mach-omap1/board-htcherald.c | 2 +- arch/arm/mach-omap1/board-innovator.c | 4 +- arch/arm/mach-omap1/board-nokia770.c | 2 +- arch/arm/mach-omap1/board-osk.c | 2 +- arch/arm/mach-omap1/board-palmte.c | 2 +- arch/arm/mach-omap1/board-palmtt.c | 2 +- arch/arm/mach-omap1/board-palmz71.c | 2 +- arch/arm/mach-omap1/board-sx1.c | 2 +- arch/arm/mach-omap1/board-voiceblue.c | 2 +- arch/arm/mach-omap1/usb.c | 530 +++++++++++++++++++++++++++++++++ arch/arm/plat-omap/include/plat/usb.h | 42 ++- arch/arm/plat-omap/usb.c | 535 ---------------------------------- 17 files changed, 589 insertions(+), 551 deletions(-) create mode 100644 arch/arm/mach-omap1/usb.c (limited to 'arch') diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index ea231c7a550a..facfaeb1ae5c 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -23,6 +23,9 @@ obj-y += $(i2c-omap-m) $(i2c-omap-y) led-y := leds.o +usb-fs-$(CONFIG_USB) := usb.o +obj-y += $(usb-fs-m) $(usb-fs-y) + # Specific board support obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o board-h2-mmc.o obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index fdd1dd53fa9c..c6a81ff8c0d8 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -235,7 +235,7 @@ static void __init ams_delta_init(void) /* Clear latch2 (NAND, LCD, modem enable) */ ams_delta_latch2_write(~0, 0); - omap_usb_init(&ams_delta_usb_config); + omap1_usb_init(&ams_delta_usb_config); platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices)); #ifdef CONFIG_AMS_DELTA_FIQ diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c index e1195a3467b8..e9ed8bff1ce3 100644 --- a/arch/arm/mach-omap1/board-generic.c +++ b/arch/arm/mach-omap1/board-generic.c @@ -72,12 +72,12 @@ static void __init omap_generic_init(void) omap_cfg_reg(UART3_TX); omap_cfg_reg(UART3_RX); - omap_usb_init(&generic1510_usb_config); + omap1_usb_init(&generic1510_usb_config); } #endif #if defined(CONFIG_ARCH_OMAP16XX) if (!cpu_is_omap1510()) { - omap_usb_init(&generic1610_usb_config); + omap1_usb_init(&generic1610_usb_config); } #endif diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index d1100e4f65ac..5f30188ade99 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -452,7 +452,7 @@ static void __init h2_init(void) omap_serial_init(); omap_register_i2c_bus(1, 100, h2_i2c_board_info, ARRAY_SIZE(h2_i2c_board_info)); - omap_usb_init(&h2_usb_config); + omap1_usb_init(&h2_usb_config); h2_mmc_init(); } diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index a53ab8297d25..0be1d3b8181d 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -405,7 +405,7 @@ static void __init h3_init(void) omap_serial_init(); omap_register_i2c_bus(1, 100, h3_i2c_board_info, ARRAY_SIZE(h3_i2c_board_info)); - omap_usb_init(&h3_usb_config); + omap1_usb_init(&h3_usb_config); h3_mmc_init(); } diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c index 8e313b4b99a9..736e4c2064f6 100644 --- a/arch/arm/mach-omap1/board-htcherald.c +++ b/arch/arm/mach-omap1/board-htcherald.c @@ -287,7 +287,7 @@ static void __init htcherald_init(void) htcherald_disable_watchdog(); htcherald_usb_enable(); - omap_usb_init(&htcherald_usb_config); + omap1_usb_init(&htcherald_usb_config); } static void __init htcherald_init_irq(void) diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index 5d12fd35681b..3c04e90fb85a 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c @@ -422,13 +422,13 @@ static void __init innovator_init(void) #ifdef CONFIG_ARCH_OMAP15XX if (cpu_is_omap1510()) { - omap_usb_init(&innovator1510_usb_config); + omap1_usb_init(&innovator1510_usb_config); innovator_config[1].data = &innovator1510_lcd_config; } #endif #ifdef CONFIG_ARCH_OMAP16XX if (cpu_is_omap1610()) { - omap_usb_init(&h2_usb_config); + omap1_usb_init(&h2_usb_config); innovator_config[1].data = &innovator1610_lcd_config; } #endif diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index 71e1a3fad0ea..c9e9e37c5676 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -386,7 +386,7 @@ static void __init omap_nokia770_init(void) hwa742_dev_init(); ads7846_dev_init(); mipid_dev_init(); - omap_usb_init(&nokia770_usb_config); + omap1_usb_init(&nokia770_usb_config); nokia770_mmc_init(); } diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index 80d862001def..b28c46a9ecce 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -560,7 +560,7 @@ static void __init osk_init(void) l |= (3 << 1); omap_writel(l, USB_TRANSCEIVER_CTRL); - omap_usb_init(&osk_usb_config); + omap1_usb_init(&osk_usb_config); /* irq for tps65010 chip */ /* bootloader effectively does: omap_cfg_reg(U19_1610_MPUIO1); */ diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index 569b4c9085cd..51d5c4dc7967 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c @@ -359,7 +359,7 @@ static void __init omap_palmte_init(void) spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info)); palmte_misc_gpio_setup(); omap_serial_init(); - omap_usb_init(&palmte_usb_config); + omap1_usb_init(&palmte_usb_config); omap_register_i2c_bus(1, 100, NULL, 0); } diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c index 6ad49a2cc1a0..c0bcfc6119db 100644 --- a/arch/arm/mach-omap1/board-palmtt.c +++ b/arch/arm/mach-omap1/board-palmtt.c @@ -307,7 +307,7 @@ static void __init omap_palmtt_init(void) spi_register_board_info(palmtt_boardinfo,ARRAY_SIZE(palmtt_boardinfo)); omap_serial_init(); - omap_usb_init(&palmtt_usb_config); + omap1_usb_init(&palmtt_usb_config); omap_register_i2c_bus(1, 100, NULL, 0); } diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c index 6641de9257ef..f431b44a71e3 100644 --- a/arch/arm/mach-omap1/board-palmz71.c +++ b/arch/arm/mach-omap1/board-palmz71.c @@ -325,7 +325,7 @@ omap_palmz71_init(void) spi_register_board_info(palmz71_boardinfo, ARRAY_SIZE(palmz71_boardinfo)); - omap_usb_init(&palmz71_usb_config); + omap1_usb_init(&palmz71_usb_config); omap_serial_init(); omap_register_i2c_bus(1, 100, NULL, 0); palmz71_gpio_setup(0); diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c index 2fb1e5f8e2ec..7b21190a914a 100644 --- a/arch/arm/mach-omap1/board-sx1.c +++ b/arch/arm/mach-omap1/board-sx1.c @@ -392,7 +392,7 @@ static void __init omap_sx1_init(void) omap_board_config_size = ARRAY_SIZE(sx1_config); omap_serial_init(); omap_register_i2c_bus(1, 100, NULL, 0); - omap_usb_init(&sx1_usb_config); + omap1_usb_init(&sx1_usb_config); sx1_mmc_init(); /* turn on USB power */ diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index 87b9436fe7c0..78107543d59b 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c @@ -198,7 +198,7 @@ static void __init voiceblue_init(void) omap_board_config = voiceblue_config; omap_board_config_size = ARRAY_SIZE(voiceblue_config); omap_serial_init(); - omap_usb_init(&voiceblue_usb_config); + omap1_usb_init(&voiceblue_usb_config); omap_register_i2c_bus(1, 100, NULL, 0); /* There is a good chance board is going up, so enable power LED diff --git a/arch/arm/mach-omap1/usb.c b/arch/arm/mach-omap1/usb.c new file mode 100644 index 000000000000..19de03b074e3 --- /dev/null +++ b/arch/arm/mach-omap1/usb.c @@ -0,0 +1,530 @@ +/* + * Platform level USB initialization for FS USB OTG controller on omap1 and 24xx + * + * Copyright (C) 2004 Texas Instruments, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +/* These routines should handle the standard chip-specific modes + * for usb0/1/2 ports, covering basic mux and transceiver setup. + * + * Some board-*.c files will need to set up additional mux options, + * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup. + */ + +/* TESTED ON: + * - 1611B H2 (with usb1 mini-AB) using standard Mini-B or OTG cables + * - 5912 OSK OHCI (with usb0 standard-A), standard A-to-B cables + * - 5912 OSK UDC, with *nonstandard* A-to-A cable + * - 1510 Innovator UDC with bundled usb0 cable + * - 1510 Innovator OHCI with bundled usb1/usb2 cable + * - 1510 Innovator OHCI with custom usb0 cable, feeding 5V VBUS + * - 1710 custom development board using alternate pin group + * - 1710 H3 (with usb1 mini-AB) using standard Mini-B or OTG cables + */ + +#define INT_USB_IRQ_GEN IH2_BASE + 20 +#define INT_USB_IRQ_NISO IH2_BASE + 30 +#define INT_USB_IRQ_ISO IH2_BASE + 29 +#define INT_USB_IRQ_HGEN INT_USB_HHC_1 +#define INT_USB_IRQ_OTG IH2_BASE + 8 + +#ifdef CONFIG_USB_GADGET_OMAP + +static struct resource udc_resources[] = { + /* order is significant! */ + { /* registers */ + .start = UDC_BASE, + .end = UDC_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, { /* general IRQ */ + .start = INT_USB_IRQ_GEN, + .flags = IORESOURCE_IRQ, + }, { /* PIO IRQ */ + .start = INT_USB_IRQ_NISO, + .flags = IORESOURCE_IRQ, + }, { /* SOF IRQ */ + .start = INT_USB_IRQ_ISO, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 udc_dmamask = ~(u32)0; + +static struct platform_device udc_device = { + .name = "omap_udc", + .id = -1, + .dev = { + .dma_mask = &udc_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(udc_resources), + .resource = udc_resources, +}; + +static inline void udc_device_init(struct omap_usb_config *pdata) +{ + /* IRQ numbers for omap7xx */ + if(cpu_is_omap7xx()) { + udc_resources[1].start = INT_7XX_USB_GENI; + udc_resources[2].start = INT_7XX_USB_NON_ISO; + udc_resources[3].start = INT_7XX_USB_ISO; + } + pdata->udc_device = &udc_device; +} + +#else + +static inline void udc_device_init(struct omap_usb_config *pdata) +{ +} + +#endif + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) + +/* The dmamask must be set for OHCI to work */ +static u64 ohci_dmamask = ~(u32)0; + +static struct resource ohci_resources[] = { + { + .start = OMAP_OHCI_BASE, + .end = OMAP_OHCI_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_USB_IRQ_HGEN, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device ohci_device = { + .name = "ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(ohci_resources), + .resource = ohci_resources, +}; + +static inline void ohci_device_init(struct omap_usb_config *pdata) +{ + if (cpu_is_omap7xx()) + ohci_resources[1].start = INT_7XX_USB_HHC_1; + pdata->ohci_device = &ohci_device; +} + +#else + +static inline void ohci_device_init(struct omap_usb_config *pdata) +{ +} + +#endif + +#if defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG) + +static struct resource otg_resources[] = { + /* order is significant! */ + { + .start = OTG_BASE, + .end = OTG_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, { + .start = INT_USB_IRQ_OTG, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device otg_device = { + .name = "omap_otg", + .id = -1, + .num_resources = ARRAY_SIZE(otg_resources), + .resource = otg_resources, +}; + +static inline void otg_device_init(struct omap_usb_config *pdata) +{ + if (cpu_is_omap7xx()) + otg_resources[1].start = INT_7XX_USB_OTG; + pdata->otg_device = &otg_device; +} + +#else + +static inline void otg_device_init(struct omap_usb_config *pdata) +{ +} + +#endif + +u32 __init omap1_usb0_init(unsigned nwires, unsigned is_device) +{ + u32 syscon1 = 0; + + if (nwires == 0) { + if (!cpu_is_omap15xx()) { + u32 l; + + /* pulldown D+/D- */ + l = omap_readl(USB_TRANSCEIVER_CTRL); + l &= ~(3 << 1); + omap_writel(l, USB_TRANSCEIVER_CTRL); + } + return 0; + } + + if (is_device) { + if (cpu_is_omap7xx()) { + omap_cfg_reg(AA17_7XX_USB_DM); + omap_cfg_reg(W16_7XX_USB_PU_EN); + omap_cfg_reg(W17_7XX_USB_VBUSI); + omap_cfg_reg(W18_7XX_USB_DMCK_OUT); + omap_cfg_reg(W19_7XX_USB_DCRST); + } else + omap_cfg_reg(W4_USB_PUEN); + } + + if (nwires == 2) { + u32 l; + + // omap_cfg_reg(P9_USB_DP); + // omap_cfg_reg(R8_USB_DM); + + if (cpu_is_omap15xx()) { + /* This works on 1510-Innovator */ + return 0; + } + + /* NOTES: + * - peripheral should configure VBUS detection! + * - only peripherals may use the internal D+/D- pulldowns + * - OTG support on this port not yet written + */ + + /* Don't do this for omap7xx -- it causes USB to not work correctly */ + if (!cpu_is_omap7xx()) { + l = omap_readl(USB_TRANSCEIVER_CTRL); + l &= ~(7 << 4); + if (!is_device) + l |= (3 << 1); + omap_writel(l, USB_TRANSCEIVER_CTRL); + } + + return 3 << 16; + } + + /* alternate pin config, external transceiver */ + if (cpu_is_omap15xx()) { + printk(KERN_ERR "no usb0 alt pin config on 15xx\n"); + return 0; + } + + omap_cfg_reg(V6_USB0_TXD); + omap_cfg_reg(W9_USB0_TXEN); + omap_cfg_reg(W5_USB0_SE0); + if (nwires != 3) + omap_cfg_reg(Y5_USB0_RCV); + + /* NOTE: SPEED and SUSP aren't configured here. OTG hosts + * may be able to use I2C requests to set those bits along + * with VBUS switching and overcurrent detection. + */ + + if (nwires != 6) { + u32 l; + + l = omap_readl(USB_TRANSCEIVER_CTRL); + l &= ~CONF_USB2_UNI_R; + omap_writel(l, USB_TRANSCEIVER_CTRL); + } + + switch (nwires) { + case 3: + syscon1 = 2; + break; + case 4: + syscon1 = 1; + break; + case 6: + syscon1 = 3; + { + u32 l; + + omap_cfg_reg(AA9_USB0_VP); + omap_cfg_reg(R9_USB0_VM); + l = omap_readl(USB_TRANSCEIVER_CTRL); + l |= CONF_USB2_UNI_R; + omap_writel(l, USB_TRANSCEIVER_CTRL); + } + break; + default: + printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", + 0, nwires); + } + + return syscon1 << 16; +} + +u32 __init omap1_usb1_init(unsigned nwires) +{ + u32 syscon1 = 0; + + if (!cpu_is_omap15xx() && nwires != 6) { + u32 l; + + l = omap_readl(USB_TRANSCEIVER_CTRL); + l &= ~CONF_USB1_UNI_R; + omap_writel(l, USB_TRANSCEIVER_CTRL); + } + if (nwires == 0) + return 0; + + /* external transceiver */ + omap_cfg_reg(USB1_TXD); + omap_cfg_reg(USB1_TXEN); + if (nwires != 3) + omap_cfg_reg(USB1_RCV); + + if (cpu_is_omap15xx()) { + omap_cfg_reg(USB1_SEO); + omap_cfg_reg(USB1_SPEED); + // SUSP + } else if (cpu_is_omap1610() || cpu_is_omap5912()) { + omap_cfg_reg(W13_1610_USB1_SE0); + omap_cfg_reg(R13_1610_USB1_SPEED); + // SUSP + } else if (cpu_is_omap1710()) { + omap_cfg_reg(R13_1710_USB1_SE0); + // SUSP + } else { + pr_debug("usb%d cpu unrecognized\n", 1); + return 0; + } + + switch (n