/* * Driver for Aeroflex Gaisler GRLIB GRUSBHC EHCI host controller * * GRUSBHC is typically found on LEON/GRLIB SoCs * * (c) Jan Andersson * * Based on ehci-ppc-of.c which is: * (c) Valentine Barshak * and in turn based on "ehci-ppc-soc.c" by Stefan Roese * and "ohci-ppc-of.c" by Sylvain Munaut * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #define GRUSBHC_HCIVERSION 0x0100 /* Known value of cap. reg. HCIVERSION */ static const struct hc_driver ehci_grlib_hc_driver = { .description = hcd_name, .product_desc = "GRLIB GRUSBHC EHCI", .hcd_priv_size = sizeof(struct ehci_hcd), /* * generic hardware linkage */ .irq = ehci_irq, .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, /* * basic lifecycle operations */ .reset = ehci_setup, .start = ehci_run, .stop = ehci_stop, .shutdown = ehci_shutdown, /* * managing i/o requests and associated device resources */ .urb_enqueue = ehci_urb_enqueue, .urb_dequeue = ehci_urb_dequeue, .endpoint_disable = ehci_endpoint_disable, .endpoint_reset = ehci_endpoint_reset, /* * scheduling support */ .get_frame_number = ehci_get_frame, /* * root hub support */ .hub_status_data = ehci_hub_status_data, .hub_control = ehci_hub_control, #ifdef CONFIG_PM .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, #endif .relinquish_port = ehci_relinquish_port, .port_handed_over = ehci_port_handed_over, .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; static int ehci_hcd_grlib_probe(struct platform_device *op) { struct device_node *dn = op->dev.of_node; struct usb_hcd *hcd; struct ehci_hcd *ehci = NULL; struct resource res; u32 hc_capbase; int irq; int rv; if (usb_disabled()) return -ENODEV; dev_dbg(&op->dev, "initializing GRUSBHC EHCI USB Controller\n"); rv = of_address_to_resource(dn, 0, &res); if (rv) return rv; /* usb_create_hcd requires dma_mask != NULL */ op->dev.dma_mask = &op->dev.coherent_dma_mask; hcd = usb_create_hcd(&ehci_grlib_hc_driver, &op->dev, "GRUSBHC EHCI USB"); if (!hcd) return -ENOMEM; hcd->rsrc_start = res.start; hcd->rsrc_len = resource_size(&res); irq = irq_of_parse_and_map(dn, 0); if (irq == NO_IRQ) { dev_err(&op->dev, "%s: irq_of_parse_and_map failed\n", __FILE__); rv = -EBUSY; goto err_irq; } hcd->regs = devm_ioremap_resource(&op->dev, &res); if (IS_ERR(hcd->regs)) { rv = PTR_ERR(hcd->regs); goto err_ioremap; } ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs; /* determine endianness of this implementation */ hc_capbase = ehci_readl(ehci, &ehci->caps->hc_capbase); if (HC_VERSION(ehci, hc_capbase) != GRUSBHC_HCIVERSION) { ehci->big_endian_mmio = 1; ehci->big_endian_desc = 1; ehci->big_endian_capbase = 1; } rv = usb_add_hcd(hcd, irq, 0); if (rv) goto err_ioremap; device_wakeup_enable(hcd->self.controller); return 0; err_ioremap: irq_dispose_mapping(irq); err_irq: usb_put_hcd(hcd); return rv; } static int ehci_hcd_grlib_remove(struct platform_device *op) { struct usb_hcd *hcd = platform_get_drvdata(op); dev_dbg(&op->dev, "stopping GRLIB GRUSBHC EHCI USB Controller\n"); usb_remove_hcd(hcd); irq_dispose_mapping(hcd->irq); usb_put_hcd(hcd); return 0; } static const struct of_device_id ehci_hcd_grlib_of_match[] = { { .name = "GAISLER_EHCI", }, { .name = "01_026", }, {}, }; MODULE_DEVICE_TABLE(of, ehci_hcd_grlib_of_match); static struct platform_driver ehci_grlib_driver = { .probe = ehci_hcd_grlib_probe, .remove = ehci_hcd_grlib_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "grlib-ehci", .of_match_table = ehci_hcd_grlib_of_match, }, }; 7e7aac140'>plain -rw-r--r--ad1843.h1516logplain -rw-r--r--adau1373.h699logplain -rw-r--r--aess.h1668logplain -rw-r--r--ak4113.h11112logplain -rw-r--r--ak4114.h10424logplain -rw-r--r--ak4117.h9193logplain -rw-r--r--ak4531_codec.h3173logplain -rw-r--r--ak4641.h622logplain -rw-r--r--ak4xxx-adda.h3416logplain -rw-r--r--alc5623.h497logplain -rw-r--r--asequencer.h3670logplain -rw-r--r--asound.h1285logplain -rw-r--r--asoundef.h17098logplain -rw-r--r--atmel-abdac.h639logplain -rw-r--r--atmel-ac97c.h1342logplain -rw-r--r--compress_driver.h6772logplain -rw-r--r--control.h8704logplain -rw-r--r--core.h14380logplain -rw-r--r--cs35l33.h1034logplain -rw-r--r--cs35l34.h887logplain -rw-r--r--cs4231-regs.h8480logplain -rw-r--r--cs4271.h1417logplain -rw-r--r--cs42l52.h738logplain -rw-r--r--cs42l56.h1192logplain -rw-r--r--cs42l73.h507logplain -rw-r--r--cs8403.h8833logplain -rw-r--r--cs8427.h10649logplain -rw-r--r--da7213.h1178logplain -rw-r--r--da7218.h2681logplain -rw-r--r--da7219-aad.h2476logplain -rw-r--r--da7219.h1064logplain -rw-r--r--da9055.h914logplain -rw-r--r--designware_i2s.h2249logplain -rw-r--r--dmaengine_pcm.h6157logplain -rw-r--r--emu10k1.h91396logplain -rw-r--r--emu10k1_synth.h1382logplain -rw-r--r--emu8000.h4109logplain -rw-r--r--emu8000_reg.h10459logplain -rw-r--r--emux_legacy.h5503logplain -rw-r--r--emux_synth.h7649logplain -rw-r--r--es1688.h3618logplain -rw-r--r--gus.h20691logplain -rw-r--r--hda_chmap.h2621logplain -rw-r--r--hda_hwdep.h1412logplain -rw-r--r--hda_i915.h1645logplain -rw-r--r--hda_register.h9475logplain -rw-r--r--hda_regmap.h6714logplain -rw-r--r--hda_verbs.h17130logplain -rw-r--r--hdaudio.h18455logplain -rw-r--r--hdaudio_ext.h7119logplain -rw-r--r--hdmi-codec.h2290logplain -rw-r--r--hwdep.h2624logplain -rw-r--r--i2c.h3555logplain -rw-r--r--info.h7584logplain