Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/usb/gadget/udc/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  amd5536udc_pci.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0+
/*
 * amd5536udc_pci.c -- AMD 5536 UDC high/full speed USB device controller
 *
 * Copyright (C) 2005-2007 AMD (https://www.amd.com)
 * Author: Thomas Dahlmann
 */


/*
 * The AMD5536 UDC is part of the x86 southbridge AMD Geode CS5536.
 * It is a USB Highspeed DMA capable USB device controller. Beside ep0 it
 * provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
 *
 * Make sure that UDC is assigned to port 4 by BIOS settings (port can also
 * be used as host port) and UOC bits PAD_EN and APU are set (should be done
 * by BIOS init).
 *
 * UDC DMA requires 32-bit aligned buffers so DMA with gadget ether does not
 * work without updating NET_IP_ALIGN. Or PIO mode (module param "use_dma=0")
 * can be used with gadget ether.
 *
 * This file does pci device registration, and the core driver implementation
 * is done in amd5536udc.c
 *
 * The driver is split so as to use the core UDC driver which is based on
 * Synopsys device controller IP (different than HS OTG IP) in UDCs
 * integrated to SoC platforms.
 *
 */


/* Driver strings */
#define UDC_MOD_DESCRIPTION  "AMD 5536 UDC - USB Device Controller"

/* system */
#include <linux/device.h>
#include <linux/dmapool.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/prefetch.h>
#include <linux/pci.h>

/* udc specific */
#include "amd5536udc.h"

/* pointer to device object */
static struct udc *udc;

/* description */
static const char name[] = "amd5536udc-pci";

/* Reset all pci context */
static void udc_pci_remove(struct pci_dev *pdev)
{
 struct udc  *dev;

 dev = pci_get_drvdata(pdev);

 usb_del_gadget_udc(&udc->gadget);
 /* gadget driver must not be registered */
 if (WARN_ON(dev->driver))
  return;

 /* dma pool cleanup */
 free_dma_pools(dev);

 /* reset controller */
 writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
 free_irq(pdev->irq, dev);
 iounmap(dev->virt_addr);
 release_mem_region(pci_resource_start(pdev, 0),
      pci_resource_len(pdev, 0));
 pci_disable_device(pdev);

 udc_remove(dev);
}

/* Called by pci bus driver to init pci context */
static int udc_pci_probe(
 struct pci_dev *pdev,
 const struct pci_device_id *id
)
{
 struct udc  *dev;
 unsigned long  resource;
 unsigned long  len;
 int   retval = 0;

 /* one udc only */
 if (udc) {
  dev_dbg(&pdev->dev, "already probed\n");
  return -EBUSY;
 }

 /* init */
 dev = kzalloc(sizeof(struct udc), GFP_KERNEL);
 if (!dev)
  return -ENOMEM;

 /* pci setup */
 if (pci_enable_device(pdev) < 0) {
  retval = -ENODEV;
  goto err_pcidev;
 }

 /* PCI resource allocation */
 resource = pci_resource_start(pdev, 0);
 len = pci_resource_len(pdev, 0);

 if (!request_mem_region(resource, len, name)) {
  dev_dbg(&pdev->dev, "pci device used already\n");
  retval = -EBUSY;
  goto err_memreg;
 }

 dev->virt_addr = ioremap(resource, len);
 if (!dev->virt_addr) {
  dev_dbg(&pdev->dev, "start address cannot be mapped\n");
  retval = -EFAULT;
  goto err_ioremap;
 }

 if (!pdev->irq) {
  dev_err(&pdev->dev, "irq not set\n");
  retval = -ENODEV;
  goto err_irq;
 }

 spin_lock_init(&dev->lock);
 /* udc csr registers base */
 dev->csr = dev->virt_addr + UDC_CSR_ADDR;
 /* dev registers base */
 dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR;
 /* ep registers base */
 dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR;
 /* fifo's base */
 dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR);
 dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR);

 if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
  dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq);
  retval = -EBUSY;
  goto err_irq;
 }

 pci_set_drvdata(pdev, dev);

 /* chip revision for Hs AMD5536 */
 dev->chiprev = pdev->revision;

 pci_set_master(pdev);
 pci_try_set_mwi(pdev);

 dev->phys_addr = resource;
 dev->irq = pdev->irq;
 dev->pdev = pdev;
 dev->dev = &pdev->dev;

 /* init dma pools */
 if (use_dma) {
  retval = init_dma_pools(dev);
  if (retval != 0)
   goto err_dma;
 }

 /* general probing */
 if (udc_probe(dev)) {
  retval = -ENODEV;
  goto err_probe;
 }

 udc = dev;

 return 0;

err_probe:
 if (use_dma)
  free_dma_pools(dev);
err_dma:
 free_irq(pdev->irq, dev);
err_irq:
 iounmap(dev->virt_addr);
err_ioremap:
 release_mem_region(resource, len);
err_memreg:
 pci_disable_device(pdev);
err_pcidev:
 kfree(dev);
 return retval;
}

/* PCI device parameters */
static const struct pci_device_id pci_id[] = {
 {
  PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096),
  .class = PCI_CLASS_SERIAL_USB_DEVICE,
  .class_mask = 0xffffffff,
 },
 {},
};
MODULE_DEVICE_TABLE(pci, pci_id);

/* PCI functions */
static struct pci_driver udc_pci_driver = {
 .name =  name,
 .id_table = pci_id,
 .probe = udc_pci_probe,
 .remove = udc_pci_remove,
};
module_pci_driver(udc_pci_driver);

MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION);
MODULE_AUTHOR("Thomas Dahlmann");
MODULE_LICENSE("GPL");

Messung V0.5
C=89 H=74 G=81

¤ Dauer der Verarbeitung: 0.0 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.