All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI routines
@ 2011-05-21  7:55 Daniel Hellstrom
  2011-05-21 11:33 ` [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI Sam Ravnborg
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Daniel Hellstrom @ 2011-05-21  7:55 UTC (permalink / raw)
  To: sparclinux

The LEON architecture does not have a BIOS or bootloader that
initializes PCI for us, instead Linux generic PCI layer is used
to set up resources and IRQ.

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
---
 arch/sparc/include/asm/pci_32.h   |    5 +
 arch/sparc/include/asm/pci_leon.h |   36 ++++++
 arch/sparc/include/asm/pcic.h     |    2 +-
 arch/sparc/kernel/Makefile        |    4 +
 arch/sparc/kernel/entry.S         |    2 +-
 arch/sparc/kernel/leon_pci.c      |  252 +++++++++++++++++++++++++++++++++++++
 drivers/pci/Makefile              |    1 +
 7 files changed, 300 insertions(+), 2 deletions(-)
 create mode 100644 arch/sparc/include/asm/pci_leon.h
 create mode 100644 arch/sparc/kernel/leon_pci.c

diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h
index 332ac9a..27f01cf 100644
--- a/arch/sparc/include/asm/pci_32.h
+++ b/arch/sparc/include/asm/pci_32.h
@@ -47,7 +47,12 @@ extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
 
 #endif /* __KERNEL__ */
 
+#ifndef CONFIG_SPARC_LEON
 /* generic pci stuff */
 #include <asm-generic/pci.h>
+#else
+/* LEON PCI cores need its own definitions */
+#include <asm/pci_leon.h>
+#endif
 
 #endif /* __SPARC_PCI_H */
diff --git a/arch/sparc/include/asm/pci_leon.h b/arch/sparc/include/asm/pci_leon.h
new file mode 100644
index 0000000..1341351
--- /dev/null
+++ b/arch/sparc/include/asm/pci_leon.h
@@ -0,0 +1,36 @@
+/*
+ * asm/pci_leon.h
+ *
+ * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom
+ */
+
+#ifndef _ASM_PCI_LEON_H_
+#define _ASM_PCI_LEON_H_
+
+/* On LEON PCI Memory space is mapped 1:1 with physical address space */
+
+extern void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			struct resource *res);
+
+extern void
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+			struct pci_bus_region *region);
+
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+	return PCI_IRQ_NONE;
+}
+
+/* PCI related definitions */
+struct leon_pci_info {
+	struct pci_ops *ops;
+	struct resource	io_space;
+	struct resource	mem_space;
+	int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin);
+};
+
+extern void leon_pci_init(struct platform_device *ofdev,
+				struct leon_pci_info *info);
+
+#endif /* _ASM_PCI_LEON_H_ */
diff --git a/arch/sparc/include/asm/pcic.h b/arch/sparc/include/asm/pcic.h
index 7eb5d78..aa3df47 100644
--- a/arch/sparc/include/asm/pcic.h
+++ b/arch/sparc/include/asm/pcic.h
@@ -29,7 +29,7 @@ struct linux_pcic {
 	int			pcic_imdim;
 };
 
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(CONFIG_SPARC_LEON)
 extern int pcic_present(void);
 extern int pcic_probe(void);
 extern void pci_time_init(void);
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 9cff270..ea19bcc 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -73,7 +73,11 @@ obj-$(CONFIG_SPARC64_SMP) += cpumap.o
 
 obj-y                     += dma.o
 
+ifndef CONFIG_SPARC_LEON
 obj-$(CONFIG_SPARC32_PCI) += pcic.o
+else
+obj-$(CONFIG_SPARC32_PCI) += leon_pci.o
+endif
 
 obj-$(CONFIG_SMP)         += trampoline_$(BITS).o smp_$(BITS).o
 obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o leon_smp.o
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 8341963..64353f8 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -1604,7 +1604,7 @@ restore_current:
 	retl
 	 nop
 
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(CONFIG_SPARC_LEON)
 #include <asm/pcic.h>
 
 	.align	4
diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c
new file mode 100644
index 0000000..b150dbb
--- /dev/null
+++ b/arch/sparc/kernel/leon_pci.c
@@ -0,0 +1,252 @@
+/*
+ * leon_pci.c: LEON Host PCI support
+ *
+ * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom
+ *
+ * Code is partially derived from pcic.c
+ */
+
+#include <linux/of_device.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/leon.h>
+
+/* The LEON architecture does not rely on a BIOS or bootloader to setup
+ * PCI for us. The Linux generic routines are used to setup resources,
+ * reset values of confuration-space registers settings ae preseved.
+ */
+void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
+{
+	struct pci_bus *root_bus;
+
+	root_bus = pci_scan_bus_parented(&ofdev->dev, 0, info->ops, info);
+	if (root_bus) {
+		root_bus->resource[0] = &info->io_space;
+		root_bus->resource[1] = &info->mem_space;
+		root_bus->resource[2] = NULL;
+
+		/* Init all PCI devices into PCI tree */
+		pci_bus_add_devices(root_bus);
+
+		/* Setup IRQs of all devices using custom routines */
+		pci_fixup_irqs(pci_common_swizzle, info->map_irq);
+
+		/* Assign devices with resources */
+		pci_assign_unassigned_resources();
+	}
+}
+
+/* PCI Memory and Prefetchable Memory is direct-mapped. However I/O Space is
+ * accessed through a Window which is translated to low 64KB in PCI space, the
+ * first 4KB is not used so 60KB is available.
+ *
+ * This function is used by generic code to translate resource addresses into
+ * PCI addresses.
+ */
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			     struct resource *res)
+{
+	struct leon_pci_info *info = dev->bus->sysdata;
+
+	region->start = res->start;
+	region->end = res->end;
+
+	if (res->flags & IORESOURCE_IO) {
+		region->start -= (info->io_space.start - 0x1000);
+		region->end -= (info->io_space.start - 0x1000);
+	}
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+/* see pcibios_resource_to_bus() comment */
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+			     struct pci_bus_region *region)
+{
+	struct leon_pci_info *info = dev->bus->sysdata;
+
+	res->start = region->start;
+	res->end = region->end;
+
+	if (res->flags & IORESOURCE_IO) {
+		res->start += (info->io_space.start - 0x1000);
+		res->end += (info->io_space.start - 0x1000);
+	}
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+
+void __devinit pcibios_fixup_bus(struct pci_bus *pbus)
+{
+	struct leon_pci_info *info = pbus->sysdata;
+	struct pci_dev *dev;
+	int i, has_io, has_mem;
+	u16 cmd;
+
+	/* Generic PCI bus probing sets these to point at
+	 * &io{port,mem}_resouce which is wrong for us.
+	 */
+	if (pbus->self = NULL) {
+		pbus->resource[0] = &info->io_space;
+		pbus->resource[1] = &info->mem_space;
+		pbus->resource[2] = NULL;
+	}
+
+	list_for_each_entry(dev, &pbus->devices, bus_list) {
+		/*
+		 * We can not rely on that the bootloader has enabled I/O
+		 * or memory access to PCI devices. Instead we enable it here
+		 * if the device has BARs of respective type.
+		 */
+		has_io = has_mem = 0;
+		for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+			unsigned long f = dev->resource[i].flags;
+			if (f & IORESOURCE_IO)
+				has_io = 1;
+			else if (f & IORESOURCE_MEM)
+				has_mem = 1;
+		}
+		/* ROM BARs are mapped into 32-bit memory space */
+		if (dev->resource[PCI_ROM_RESOURCE].end != 0) {
+			dev->resource[PCI_ROM_RESOURCE].flags |+							IORESOURCE_ROM_ENABLE;
+			has_mem = 1;
+		}
+		pci_bus_read_config_word(pbus, dev->devfn, PCI_COMMAND, &cmd);
+		if (has_io && !(cmd & PCI_COMMAND_IO)) {
+#ifdef CONFIG_PCI_DEBUG
+			printk(KERN_INFO "LEONPCI: Enabling I/O for dev %s\n",
+					 pci_name(dev));
+#endif
+			cmd |= PCI_COMMAND_IO;
+			pci_bus_write_config_word(pbus, dev->devfn, PCI_COMMAND,
+									cmd);
+		}
+		if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) {
+#ifdef CONFIG_PCI_DEBUG
+			printk(KERN_INFO "LEONPCI: Enabling MEMORY for dev"
+					 "%s\n", pci_name(dev));
+#endif
+			cmd |= PCI_COMMAND_MEMORY;
+			pci_bus_write_config_word(pbus, dev->devfn, PCI_COMMAND,
+									cmd);
+		}
+	}
+}
+
+/*
+ * Other archs parse arguments here.
+ */
+char * __devinit pcibios_setup(char *str)
+{
+	return str;
+}
+
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+				resource_size_t size, resource_size_t align)
+{
+	return res->start;
+}
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	return pci_enable_resources(dev, mask);
+}
+
+struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
+{
+	/*
+	 * Currently the OpenBoot nodes are not connected with the PCI device,
+	 * this is because the LEON PROM does not create PCI nodes. Eventually
+	 * this will change and the same approach as pcic.c can be used to
+	 * match PROM nodes with pci devices.
+	 */
+	return NULL;
+}
+EXPORT_SYMBOL(pci_device_to_OF_node);
+
+void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+#ifdef CONFIG_PCI_DEBUG
+	printk(KERN_DEBUG "LEONPCI: Assigning IRQ %02d to %s\n", irq,
+		pci_name(dev));
+#endif
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+/* in/out routines taken from pcic.c
+ *
+ * This probably belongs here rather than ioport.c because
+ * we do not want this crud linked into SBus kernels.
+ * Also, think for a moment about likes of floppy.c that
+ * include architecture specific parts. They may want to redefine ins/outs.
+ *
+ * We do not use horrible macros here because we want to
+ * advance pointer by sizeof(size).
+ */
+void outsb(unsigned long addr, const void *src, unsigned long count)
+{
+	while (count) {
+		count -= 1;
+		outb(*(const char *)src, addr);
+		src += 1;
+		/* addr += 1; */
+	}
+}
+EXPORT_SYMBOL(outsb);
+
+void outsw(unsigned long addr, const void *src, unsigned long count)
+{
+	while (count) {
+		count -= 2;
+		outw(*(const short *)src, addr);
+		src += 2;
+		/* addr += 2; */
+	}
+}
+EXPORT_SYMBOL(outsw);
+
+void outsl(unsigned long addr, const void *src, unsigned long count)
+{
+	while (count) {
+		count -= 4;
+		outl(*(const long *)src, addr);
+		src += 4;
+		/* addr += 4; */
+	}
+}
+EXPORT_SYMBOL(outsl);
+
+void insb(unsigned long addr, void *dst, unsigned long count)
+{
+	while (count) {
+		count -= 1;
+		*(unsigned char *)dst = inb(addr);
+		dst += 1;
+		/* addr += 1; */
+	}
+}
+EXPORT_SYMBOL(insb);
+
+void insw(unsigned long addr, void *dst, unsigned long count)
+{
+	while (count) {
+		count -= 2;
+		*(unsigned short *)dst = inw(addr);
+		dst += 2;
+		/* addr += 2; */
+	}
+}
+EXPORT_SYMBOL(insw);
+
+void insl(unsigned long addr, void *dst, unsigned long count)
+{
+	while (count) {
+		count -= 4;
+		/*
+		 * XXX I am sure we are in for an unaligned trap here.
+		 */
+		*(unsigned long *)dst = inl(addr);
+		dst += 4;
+		/* addr += 4; */
+	}
+}
+EXPORT_SYMBOL(insl);
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index c85f744..094308e 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_X86_VISWS) += setup-irq.o
 obj-$(CONFIG_MN10300) += setup-bus.o
 obj-$(CONFIG_MICROBLAZE) += setup-bus.o
 obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
+obj-$(CONFIG_SPARC_LEON) += setup-bus.o setup-irq.o
 
 #
 # ACPI Related PCI FW Functions
-- 
1.5.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI
  2011-05-21  7:55 [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI routines Daniel Hellstrom
@ 2011-05-21 11:33 ` Sam Ravnborg
  2011-05-21 12:49 ` [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI routines Julian Calaby
  2011-05-23 16:10 ` [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI Daniel Hellstrom
  2 siblings, 0 replies; 4+ messages in thread
From: Sam Ravnborg @ 2011-05-21 11:33 UTC (permalink / raw)
  To: sparclinux

On Sat, May 21, 2011 at 09:55:28AM +0200, Daniel Hellstrom wrote:
> The LEON architecture does not have a BIOS or bootloader that
> initializes PCI for us, instead Linux generic PCI layer is used
> to set up resources and IRQ.
> 
> Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
> ---
>  arch/sparc/include/asm/pci_32.h   |    5 +
>  arch/sparc/include/asm/pci_leon.h |   36 ++++++
>  arch/sparc/include/asm/pcic.h     |    2 +-
>  arch/sparc/kernel/Makefile        |    4 +
>  arch/sparc/kernel/entry.S         |    2 +-
>  arch/sparc/kernel/leon_pci.c      |  252 +++++++++++++++++++++++++++++++++++++
>  drivers/pci/Makefile              |    1 +
>  7 files changed, 300 insertions(+), 2 deletions(-)
>  create mode 100644 arch/sparc/include/asm/pci_leon.h
>  create mode 100644 arch/sparc/kernel/leon_pci.c

Hi Daniel.

Reading through this patch it looks like LEOON pci support is bolted on top
of what we have rather than trying to integrate it a bit more.

I would like to see something like:

* include/asm/pcic.h intregated in pci_32.h
* leon specifics added to pci_32.h - with minimal ifdefs

Dunno abot the rest...

If i find time I will try to come up with a proposal later tonight.

	Sam

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI routines
  2011-05-21  7:55 [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI routines Daniel Hellstrom
  2011-05-21 11:33 ` [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI Sam Ravnborg
@ 2011-05-21 12:49 ` Julian Calaby
  2011-05-23 16:10 ` [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI Daniel Hellstrom
  2 siblings, 0 replies; 4+ messages in thread
From: Julian Calaby @ 2011-05-21 12:49 UTC (permalink / raw)
  To: sparclinux

On Sat, May 21, 2011 at 21:33, Sam Ravnborg <sam@ravnborg.org> wrote:
> On Sat, May 21, 2011 at 09:55:28AM +0200, Daniel Hellstrom wrote:
>> The LEON architecture does not have a BIOS or bootloader that
>> initializes PCI for us, instead Linux generic PCI layer is used
>> to set up resources and IRQ.
>>
>> Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
>
> Hi Daniel.
>
> Reading through this patch it looks like LEOON pci support is bolted on top
> of what we have rather than trying to integrate it a bit more.
>
> I would like to see something like:
>
> * include/asm/pcic.h intregated in pci_32.h
> * leon specifics added to pci_32.h - with minimal ifdefs
>
> Dunno abot the rest...
>
> If i find time I will try to come up with a proposal later tonight.
>
>        Sam

When I looked at this earlier, I was thinking that we might want to
introduce a new KConfig variable, maybe CONFIG_LEON_PCI, to hide all
this stuff behind so we don't have to do any complicated ifdefery or
change any existing ifdefs.

Thanks,

-- 
Julian Calaby

Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/
.Plan: http://sites.google.com/site/juliancalaby/

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI
  2011-05-21  7:55 [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI routines Daniel Hellstrom
  2011-05-21 11:33 ` [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI Sam Ravnborg
  2011-05-21 12:49 ` [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI routines Julian Calaby
@ 2011-05-23 16:10 ` Daniel Hellstrom
  2 siblings, 0 replies; 4+ messages in thread
From: Daniel Hellstrom @ 2011-05-23 16:10 UTC (permalink / raw)
  To: sparclinux

Julian Calaby wrote:

>On Sat, May 21, 2011 at 21:33, Sam Ravnborg <sam@ravnborg.org> wrote:
>  
>
>>On Sat, May 21, 2011 at 09:55:28AM +0200, Daniel Hellstrom wrote:
>>    
>>
>>>The LEON architecture does not have a BIOS or bootloader that
>>>initializes PCI for us, instead Linux generic PCI layer is used
>>>to set up resources and IRQ.
>>>
>>>Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
>>>      
>>>
>>Hi Daniel.
>>
>>Reading through this patch it looks like LEOON pci support is bolted on top
>>of what we have rather than trying to integrate it a bit more.
>>
>>I would like to see something like:
>>
>>* include/asm/pcic.h intregated in pci_32.h
>>    
>>
Do we really want that? I mean drivers that include pci.h does not need 
to know about pcic.h internals. I think is is quite clear the way it is, 
pcic.h is one PCI Host controller implementation, the host 
implementation shouldn't go to the header right? This is similar to 
LEON_PCI, is a common file for LEON PCI host controllers on the LEON 
platform. PCIC is common to machines which have PCI on the SUN platform.

>>* leon specifics added to pci_32.h - with minimal ifdefs
>>    
>>
Ok, could do that. Then I propose that I remove pci_leon.h, add some of 
that stuff into pci_32.h (will still be as many ifdefs as before) and I 
will create a leon_pci.h similar to pcic.h or add LEON-PCI specific 
stuff that nowone really wants to know about 
(leon_pci_info,leon_pci_init), or I add it to leon.h instead.

>>Dunno abot the rest...
>>
>>If i find time I will try to come up with a proposal later tonight.
>>
>>       Sam
>>    
>>
>
>When I looked at this earlier, I was thinking that we might want to
>introduce a new KConfig variable, maybe CONFIG_LEON_PCI, to hide all
>this stuff behind so we don't have to do any complicated ifdefery or
>change any existing ifdefs.
>  
>
Ok, I will try to add a PCIC and a LEON_PCI config option. Then most 
ifdefs still will be there but only dependent on one thing: PCIC, 
LEON_PCI or PCI.

Does all this sound reasonable?

Daniel

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-05-23 16:10 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-21  7:55 [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI routines Daniel Hellstrom
2011-05-21 11:33 ` [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI Sam Ravnborg
2011-05-21 12:49 ` [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI routines Julian Calaby
2011-05-23 16:10 ` [PATCH 1/2 v2] sparc32,leon: added LEON-common low-level PCI Daniel Hellstrom

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.