From 7eae642f75e0f7fbce7c37b2dfe0641ff1e9ebfd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 9 Feb 2006 22:20:01 -0800 Subject: [SPARC64]: Implement SUN4V PCI config space access. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_sun4v.c | 40 +++++++++++++++++++++++++++---- arch/sparc64/kernel/pci_sun4v.h | 9 +++++++ arch/sparc64/kernel/pci_sun4v_asm.S | 48 +++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 1d61353e2644..abd9bfb245cb 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -74,15 +74,47 @@ struct pci_iommu_ops pci_sun4v_iommu_ops = { static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, int where, int size, u32 *value) { - /* XXX Implement me! XXX */ - return 0; + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned long devhandle = pbm->devhandle; + unsigned int bus = bus_dev->number; + unsigned int device = PCI_SLOT(devfn); + unsigned int func = PCI_FUNC(devfn); + unsigned long ret; + + ret = pci_sun4v_config_get(devhandle, + HV_PCI_DEVICE_BUILD(bus, device, func), + where, size); + switch (size) { + case 1: + *value = ret & 0xff; + break; + case 2: + *value = ret & 0xffff; + break; + case 4: + *value = ret & 0xffffffff; + break; + }; + + + return PCIBIOS_SUCCESSFUL; } static int pci_sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, int where, int size, u32 value) { - /* XXX Implement me! XXX */ - return 0; + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned long devhandle = pbm->devhandle; + unsigned int bus = bus_dev->number; + unsigned int device = PCI_SLOT(devfn); + unsigned int func = PCI_FUNC(devfn); + unsigned long ret; + + ret = pci_sun4v_config_put(devhandle, + HV_PCI_DEVICE_BUILD(bus, device, func), + where, size, value); + + return PCIBIOS_SUCCESSFUL; } static struct pci_ops pci_sun4v_ops = { diff --git a/arch/sparc64/kernel/pci_sun4v.h b/arch/sparc64/kernel/pci_sun4v.h index d3ac7ece4b31..5c7ed2ca1505 100644 --- a/arch/sparc64/kernel/pci_sun4v.h +++ b/arch/sparc64/kernel/pci_sun4v.h @@ -16,5 +16,14 @@ extern unsigned long pci_sun4v_iommu_map(unsigned long devhandle, extern unsigned long pci_sun4v_iommu_demap(unsigned long devhandle, unsigned long tsbid, unsigned long num_ttes); +extern unsigned long pci_sun4v_config_get(unsigned long devhandle, + unsigned long pci_device, + unsigned long config_offset, + unsigned long size); +extern int pci_sun4v_config_put(unsigned long devhandle, + unsigned long pci_device, + unsigned long config_offset, + unsigned long size, + unsigned long data); #endif /* !(_PCI_SUN4V_H) */ diff --git a/arch/sparc64/kernel/pci_sun4v_asm.S b/arch/sparc64/kernel/pci_sun4v_asm.S index fd2fe0edf168..2f1147146abe 100644 --- a/arch/sparc64/kernel/pci_sun4v_asm.S +++ b/arch/sparc64/kernel/pci_sun4v_asm.S @@ -54,3 +54,51 @@ pci_sun4v_iommu_demap: ta HV_FAST_TRAP retl mov %o1, %o0 + + /* %o0: devhandle + * %o1: pci_device + * %o2: pci_config_offset + * %o3: size + * + * returns %o0: data + * + * If there is an error, the data will be returned + * as all 1's. + */ + .globl pci_sun4v_config_get +pci_sun4v_config_get: + mov %o3, %o4 + mov %o2, %o3 + mov %o1, %o2 + mov %o0, %o1 + mov HV_FAST_PCI_CONFIG_GET, %o0 + ta HV_FAST_TRAP + brnz,a,pn %o1, 1f + mov -1, %o2 +1: retl + mov %o2, %o0 + + /* %o0: devhandle + * %o1: pci_device + * %o2: pci_config_offset + * %o3: size + * %o4: data + * + * returns %o0: status + * + * status will be zero if the operation completed + * successfully, else -1 if not + */ + .globl pci_sun4v_config_put +pci_sun4v_config_put: + mov %o3, %o4 + mov %o2, %o3 + mov %o1, %o2 + mov %o0, %o1 + mov HV_FAST_PCI_CONFIG_PUT, %o0 + ta HV_FAST_TRAP + brnz,a,pn %o1, 1f + mov -1, %o1 +1: retl + mov %o1, %o0 + -- cgit v1.2.3-59-g8ed1b