From 57f0f512b273f60d52568b8c6b77e17f5636edc0 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Wed, 5 Aug 2015 17:04:01 -0300 Subject: Initial import --- arch/cris/arch-v32/drivers/pci/Makefile | 5 ++ arch/cris/arch-v32/drivers/pci/bios.c | 99 +++++++++++++++++++++++++++++++++ arch/cris/arch-v32/drivers/pci/dma.c | 50 +++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 arch/cris/arch-v32/drivers/pci/Makefile create mode 100644 arch/cris/arch-v32/drivers/pci/bios.c create mode 100644 arch/cris/arch-v32/drivers/pci/dma.c (limited to 'arch/cris/arch-v32/drivers/pci') diff --git a/arch/cris/arch-v32/drivers/pci/Makefile b/arch/cris/arch-v32/drivers/pci/Makefile new file mode 100644 index 000000000..bff7482f2 --- /dev/null +++ b/arch/cris/arch-v32/drivers/pci/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for Etrax cardbus driver +# + +obj-$(CONFIG_ETRAX_CARDBUS) += bios.o dma.o diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c new file mode 100644 index 000000000..64a5fb937 --- /dev/null +++ b/arch/cris/arch-v32/drivers/pci/bios.c @@ -0,0 +1,99 @@ +#include +#include +#include + +void pcibios_fixup_bus(struct pci_bus *b) +{ +} + +void pcibios_set_master(struct pci_dev *dev) +{ + u8 lat; + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); +} + +int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, + enum pci_mmap_state mmap_state, int write_combine) +{ + unsigned long prot; + + /* Leave vm_pgoff as-is, the PCI space address is the physical + * address on this platform. + */ + prot = pgprot_val(vma->vm_page_prot); + vma->vm_page_prot = __pgprot(prot); + + /* Write-combine setting is ignored, it is changed via the mtrr + * interfaces on this platform. + */ + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) + return -EAGAIN; + + return 0; +} + +resource_size_t +pcibios_align_resource(void *data, const struct resource *res, + resource_size_t size, resource_size_t align) +{ + resource_size_t start = res->start; + + if ((res->flags & IORESOURCE_IO) && (start & 0x300)) + start = (start + 0x3ff) & ~0x3ff; + + return start; +} + +int pcibios_enable_resources(struct pci_dev *dev, int mask) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for(idx=0; idx<6; idx++) { + /* Only set up the requested stuff */ + if (!(mask & (1<resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (dev->resource[PCI_ROM_RESOURCE].start) + cmd |= PCI_COMMAND_MEMORY; + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +int pcibios_enable_irq(struct pci_dev *dev) +{ + dev->irq = EXT_INTR_VECT; + return 0; +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + int err; + + if ((err = pcibios_enable_resources(dev, mask)) < 0) + return err; + + if (!dev->msi_enabled) + pcibios_enable_irq(dev); + return 0; +} diff --git a/arch/cris/arch-v32/drivers/pci/dma.c b/arch/cris/arch-v32/drivers/pci/dma.c new file mode 100644 index 000000000..ee55578d9 --- /dev/null +++ b/arch/cris/arch-v32/drivers/pci/dma.c @@ -0,0 +1,50 @@ +/* + * Dynamic DMA mapping support. + * + * On cris there is no hardware dynamic DMA address translation, + * so consistent alloc/free are merely page allocation/freeing. + * The rest of the dynamic DMA mapping interface is implemented + * in asm/pci.h. + * + * Borrowed from i386. + */ + +#include +#include +#include +#include +#include +#include + +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp) +{ + void *ret; + int order = get_order(size); + /* ignore region specifiers */ + gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); + + if (dma_alloc_from_coherent(dev, size, dma_handle, &ret)) + return ret; + + if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) + gfp |= GFP_DMA; + + ret = (void *)__get_free_pages(gfp, order); + + if (ret != NULL) { + memset(ret, 0, size); + *dma_handle = virt_to_phys(ret); + } + return ret; +} + +void dma_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + int order = get_order(size); + + if (!dma_release_from_coherent(dev, order, vaddr)) + free_pages((unsigned long)vaddr, order); +} + -- cgit v1.2.3-54-g00ecf