瀏覽代碼

[SPARC64]: Implement SUN4V PCI config space access.

Signed-off-by: David S. Miller <davem@davemloft.net>
David S. Miller 19 年之前
父節點
當前提交
7eae642f75
共有 3 個文件被更改,包括 93 次插入4 次删除
  1. 36 4
      arch/sparc64/kernel/pci_sun4v.c
  2. 9 0
      arch/sparc64/kernel/pci_sun4v.h
  3. 48 0
      arch/sparc64/kernel/pci_sun4v_asm.S

+ 36 - 4
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 = {

+ 9 - 0
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) */

+ 48 - 0
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
+