diff options
Diffstat (limited to 'drivers/usb/musb/tusb6010.c')
| -rw-r--r-- | drivers/usb/musb/tusb6010.c | 199 |
1 files changed, 89 insertions, 110 deletions
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 1f405616e6c..159ef4be1ef 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -17,18 +17,21 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/init.h> +#include <linux/err.h> #include <linux/prefetch.h> #include <linux/usb.h> #include <linux/irq.h> +#include <linux/io.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> +#include <linux/usb/usb_phy_generic.h> #include "musb_core.h" struct tusb6010_glue { struct device *dev; struct platform_device *musb; + struct platform_device *phy; }; static void tusb_musb_set_vbus(struct musb *musb, int is_on); @@ -40,7 +43,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on); * Checks the revision. We need to use the DMA register as 3.0 does not * have correct versions for TUSB_PRCM_REV or TUSB_INT_CTRL_REV. */ -u8 tusb_get_revision(struct musb *musb) +static u8 tusb_get_revision(struct musb *musb) { void __iomem *tbase = musb->ctrl_base; u32 die_id; @@ -56,14 +59,13 @@ u8 tusb_get_revision(struct musb *musb) return rev; } -EXPORT_SYMBOL_GPL(tusb_get_revision); -static int tusb_print_revision(struct musb *musb) +static void tusb_print_revision(struct musb *musb) { void __iomem *tbase = musb->ctrl_base; u8 rev; - rev = tusb_get_revision(musb); + rev = musb->tusb_revision; pr_info("tusb: %s%i.%i %s%i.%i %s%i.%i %s%i.%i %s%i %s%i.%i\n", "prcm", @@ -82,8 +84,6 @@ static int tusb_print_revision(struct musb *musb) TUSB_DIDR1_HI_CHIP_REV(musb_readl(tbase, TUSB_DIDR1_HI)), "rev", TUSB_REV_MAJOR(rev), TUSB_REV_MINOR(rev)); - - return tusb_get_revision(musb); } #define WBUS_QUIRK_MASK (TUSB_PHY_OTG_CTRL_TESTM2 | TUSB_PHY_OTG_CTRL_TESTM1 \ @@ -152,7 +152,7 @@ tusb_fifo_write_unaligned(void __iomem *fifo, const u8 *buf, u16 len) } static inline void tusb_fifo_read_unaligned(void __iomem *fifo, - void __iomem *buf, u16 len) + void *buf, u16 len) { u32 val; int i; @@ -196,7 +196,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf) /* Best case is 32bit-aligned destination address */ if ((0x02 & (unsigned long) buf) == 0) { if (len >= 4) { - writesl(fifo, buf, len >> 2); + iowrite32_rep(fifo, buf, len >> 2); buf += (len & ~0x03); len &= 0x03; } @@ -243,7 +243,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf) /* Best case is 32bit-aligned destination address */ if ((0x02 & (unsigned long) buf) == 0) { if (len >= 4) { - readsl(fifo, buf, len >> 2); + ioread32_rep(fifo, buf, len >> 2); buf += (len & ~0x03); len &= 0x03; } @@ -277,7 +277,7 @@ static struct musb *the_musb; * mode), or low power Default-B sessions, something else supplies power. * Caller must take care of locking. */ -static int tusb_draw_power(struct otg_transceiver *x, unsigned mA) +static int tusb_draw_power(struct usb_phy *x, unsigned mA) { struct musb *musb = the_musb; void __iomem *tbase = musb->ctrl_base; @@ -293,7 +293,7 @@ static int tusb_draw_power(struct otg_transceiver *x, unsigned mA) * The actual current usage would be very board-specific. For now, * it's simpler to just use an aggregate (also board-specific). */ - if (x->default_a || mA < (musb->min_power << 1)) + if (x->otg->default_a || mA < (musb->min_power << 1)) mA = 0; reg = musb_readl(tbase, TUSB_PRCM_MNGMT); @@ -347,7 +347,7 @@ static void tusb_allow_idle(struct musb *musb, u32 wakeup_enables) u32 reg; if ((wakeup_enables & TUSB_PRCM_WBUS) - && (tusb_get_revision(musb) == TUSB_REV_30)) + && (musb->tusb_revision == TUSB_REV_30)) tusb_wbus_quirk(musb, 1); tusb_set_clock_source(musb, 0); @@ -420,7 +420,7 @@ static void musb_do_idle(unsigned long _musb) && (musb->idle_timeout == 0 || time_after(jiffies, musb->idle_timeout))) { dev_dbg(musb->controller, "Nothing connected %s, turning off VBUS\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); } /* FALLTHROUGH */ case OTG_STATE_A_IDLE: @@ -436,14 +436,13 @@ static void musb_do_idle(unsigned long _musb) if (is_host_active(musb) && (musb->port1_status >> 16)) goto done; - if (is_peripheral_enabled(musb) && !musb->gadget_driver) { + if (!musb->gadget_driver) { wakeups = 0; } else { wakeups = TUSB_PRCM_WHOSTDISCON | TUSB_PRCM_WBUS | TUSB_PRCM_WVBUS; - if (is_otg_enabled(musb)) - wakeups |= TUSB_PRCM_WID; + wakeups |= TUSB_PRCM_WID; } tusb_allow_idle(musb, wakeups); } @@ -476,7 +475,7 @@ static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout) if (musb->is_active || ((musb->a_wait_bcon == 0) && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) { dev_dbg(musb->controller, "%s active, deleting timer\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); del_timer(&musb_idle_timer); last_timer = jiffies; return; @@ -493,7 +492,7 @@ static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout) last_timer = timeout; dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), (unsigned long)jiffies_to_msecs(timeout - jiffies)); mod_timer(&musb_idle_timer, timeout); } @@ -510,6 +509,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on) void __iomem *tbase = musb->ctrl_base; u32 conf, prcm, timer; u8 devctl; + struct usb_otg *otg = musb->xceiv->otg; /* HDRC controls CPEN, but beware current surges during device * connect. They can trigger transient overcurrent conditions @@ -522,7 +522,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on) if (is_on) { timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE); - musb->xceiv->default_a = 1; + otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; devctl |= MUSB_DEVCTL_SESSION; @@ -548,11 +548,11 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on) musb->xceiv->state = OTG_STATE_A_IDLE; } musb->is_active = 0; - musb->xceiv->default_a = 1; + otg->default_a = 1; MUSB_HST_MODE(musb); } else { musb->is_active = 0; - musb->xceiv->default_a = 0; + otg->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; MUSB_DEV_MODE(musb); } @@ -568,7 +568,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on) musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); dev_dbg(musb->controller, "VBUS %s, devctl %02x otg %3x conf %08x prcm %08x\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), musb_readb(musb->mregs, MUSB_DEVCTL), musb_readl(tbase, TUSB_DEV_OTG_STAT), conf, prcm); @@ -580,21 +580,12 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on) * * Note that if a mini-A cable is plugged in the ID line will stay down as * the weak ID pull-up is not able to pull the ID up. - * - * REVISIT: It would be possible to add support for changing between host - * and peripheral modes in non-OTG configurations by reconfiguring hardware - * and then setting musb->board_mode. For now, only support OTG mode. */ static int tusb_musb_set_mode(struct musb *musb, u8 musb_mode) { void __iomem *tbase = musb->ctrl_base; u32 otg_stat, phy_otg_ctrl, phy_otg_ena, dev_conf; - if (musb->board_mode != MUSB_OTG) { - ERR("Changing mode currently only supported in OTG mode\n"); - return -EINVAL; - } - otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); phy_otg_ctrl = musb_readl(tbase, TUSB_PHY_OTG_CTRL); phy_otg_ena = musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE); @@ -644,17 +635,15 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) { u32 otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); unsigned long idle_timeout = 0; + struct usb_otg *otg = musb->xceiv->otg; /* ID pin */ if ((int_src & TUSB_INT_SRC_ID_STATUS_CHNG)) { int default_a; - if (is_otg_enabled(musb)) - default_a = !(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS); - else - default_a = is_host_enabled(musb); + default_a = !(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS); dev_dbg(musb->controller, "Default-%c\n", default_a ? 'A' : 'B'); - musb->xceiv->default_a = default_a; + otg->default_a = default_a; tusb_musb_set_vbus(musb, default_a); /* Don't allow idling immediately */ @@ -666,8 +655,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) { /* B-dev state machine: no vbus ~= disconnect */ - if ((is_otg_enabled(musb) && !musb->xceiv->default_a) - || !is_host_enabled(musb)) { + if (!otg->default_a) { /* ? musb_root_disconnect(musb); */ musb->port1_status &= ~(USB_PORT_STAT_CONNECTION @@ -687,13 +675,13 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) musb->is_active = 0; } dev_dbg(musb->controller, "vbus change, %s, otg %03x\n", - otg_state_string(musb->xceiv->state), otg_stat); + usb_otg_state_string(musb->xceiv->state), otg_stat); idle_timeout = jiffies + (1 * HZ); schedule_work(&musb->irq_work); } else /* A-dev state machine */ { dev_dbg(musb->controller, "vbus change, %s, otg %03x\n", - otg_state_string(musb->xceiv->state), otg_stat); + usb_otg_state_string(musb->xceiv->state), otg_stat); switch (musb->xceiv->state) { case OTG_STATE_A_IDLE: @@ -742,7 +730,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) u8 devctl; dev_dbg(musb->controller, "%s timer, %03x\n", - otg_state_string(musb->xceiv->state), otg_stat); + usb_otg_state_string(musb->xceiv->state), otg_stat); switch (musb->xceiv->state) { case OTG_STATE_A_WAIT_VRISE: @@ -807,7 +795,7 @@ static irqreturn_t tusb_musb_interrupt(int irq, void *__hci) u32 reg; u32 i; - if (tusb_get_revision(musb) == TUSB_REV_30) + if (musb->tusb_revision == TUSB_REV_30) tusb_wbus_quirk(musb, 0); /* there are issues re-locking the PLL on wakeup ... */ @@ -1021,10 +1009,11 @@ static int tusb_musb_start(struct musb *musb) goto err; } - ret = tusb_print_revision(musb); - if (ret < 2) { + musb->tusb_revision = tusb_get_revision(musb); + tusb_print_revision(musb); + if (musb->tusb_revision < 2) { printk(KERN_ERR "tusb: Unsupported TUSB6010 revision %i\n", - ret); + musb->tusb_revision); goto err; } @@ -1075,10 +1064,9 @@ static int tusb_musb_init(struct musb *musb) void __iomem *sync = NULL; int ret; - usb_nop_xceiv_register(); - musb->xceiv = otg_get_transceiver(); - if (!musb->xceiv) - return -ENODEV; + musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); + if (IS_ERR_OR_NULL(musb->xceiv)) + return -EPROBE_DEFER; pdev = to_platform_device(musb->controller); @@ -1116,10 +1104,8 @@ static int tusb_musb_init(struct musb *musb) } musb->isr = tusb_musb_interrupt; - if (is_peripheral_enabled(musb)) { - musb->xceiv->set_power = tusb_draw_power; - the_musb = musb; - } + musb->xceiv->set_power = tusb_draw_power; + the_musb = musb; setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); @@ -1128,8 +1114,7 @@ done: if (sync) iounmap(sync); - otg_put_transceiver(musb->xceiv); - usb_nop_xceiv_unregister(); + usb_put_phy(musb->xceiv); } return ret; } @@ -1144,8 +1129,7 @@ static int tusb_musb_exit(struct musb *musb) iounmap(musb->sync_va); - otg_put_transceiver(musb->xceiv); - usb_nop_xceiv_unregister(); + usb_put_phy(musb->xceiv); return 0; } @@ -1163,14 +1147,19 @@ static const struct musb_platform_ops tusb_ops = { .set_vbus = tusb_musb_set_vbus, }; -static u64 tusb_dmamask = DMA_BIT_MASK(32); +static const struct platform_device_info tusb_dev_info = { + .name = "musb-hdrc", + .id = PLATFORM_DEVID_AUTO, + .dma_mask = DMA_BIT_MASK(32), +}; -static int __init tusb_probe(struct platform_device *pdev) +static int tusb_probe(struct platform_device *pdev) { - struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; + struct resource musb_resources[3]; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); struct platform_device *musb; struct tusb6010_glue *glue; - + struct platform_device_info pinfo; int ret = -ENOMEM; glue = kzalloc(sizeof(*glue), GFP_KERNEL); @@ -1179,67 +1168,68 @@ static int __init tusb_probe(struct platform_device *pdev) goto err0; } - musb = platform_device_alloc("musb-hdrc", -1); - if (!musb) { - dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err1; - } - - musb->dev.parent = &pdev->dev; - musb->dev.dma_mask = &tusb_dmamask; - musb->dev.coherent_dma_mask = tusb_dmamask; - glue->dev = &pdev->dev; - glue->musb = musb; pdata->platform_ops = &tusb_ops; + usb_phy_generic_register(); platform_set_drvdata(pdev, glue); - ret = platform_device_add_resources(musb, pdev->resource, - pdev->num_resources); - if (ret) { - dev_err(&pdev->dev, "failed to add resources\n"); - goto err2; - } - - ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); - if (ret) { - dev_err(&pdev->dev, "failed to add platform_data\n"); - goto err2; - } - - ret = platform_device_add(musb); - if (ret) { - dev_err(&pdev->dev, "failed to register musb device\n"); - goto err1; + memset(musb_resources, 0x00, sizeof(*musb_resources) * + ARRAY_SIZE(musb_resources)); + + musb_resources[0].name = pdev->resource[0].name; + musb_resources[0].start = pdev->resource[0].start; + musb_resources[0].end = pdev->resource[0].end; + musb_resources[0].flags = pdev->resource[0].flags; + + musb_resources[1].name = pdev->resource[1].name; + musb_resources[1].start = pdev->resource[1].start; + musb_resources[1].end = pdev->resource[1].end; + musb_resources[1].flags = pdev->resource[1].flags; + + musb_resources[2].name = pdev->resource[2].name; + musb_resources[2].start = pdev->resource[2].start; + musb_resources[2].end = pdev->resource[2].end; + musb_resources[2].flags = pdev->resource[2].flags; + + pinfo = tusb_dev_info; + pinfo.parent = &pdev->dev; + pinfo.res = musb_resources; + pinfo.num_res = ARRAY_SIZE(musb_resources); + pinfo.data = pdata; + pinfo.size_data = sizeof(*pdata); + + glue->musb = musb = platform_device_register_full(&pinfo); + if (IS_ERR(musb)) { + ret = PTR_ERR(musb); + dev_err(&pdev->dev, "failed to register musb device: %d\n", ret); + goto err3; } return 0; -err2: - platform_device_put(musb); - -err1: +err3: kfree(glue); err0: return ret; } -static int __exit tusb_remove(struct platform_device *pdev) +static int tusb_remove(struct platform_device *pdev) { struct tusb6010_glue *glue = platform_get_drvdata(pdev); - platform_device_del(glue->musb); - platform_device_put(glue->musb); + platform_device_unregister(glue->musb); + usb_phy_generic_unregister(glue->phy); kfree(glue); return 0; } static struct platform_driver tusb_driver = { - .remove = __exit_p(tusb_remove), + .probe = tusb_probe, + .remove = tusb_remove, .driver = { .name = "musb-tusb", }, @@ -1248,15 +1238,4 @@ static struct platform_driver tusb_driver = { MODULE_DESCRIPTION("TUSB6010 MUSB Glue Layer"); MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); MODULE_LICENSE("GPL v2"); - -static int __init tusb_init(void) -{ - return platform_driver_probe(&tusb_driver, tusb_probe); -} -subsys_initcall(tusb_init); - -static void __exit tusb_exit(void) -{ - platform_driver_unregister(&tusb_driver); -} -module_exit(tusb_exit); +module_platform_driver(tusb_driver); |
