* [RFC/PATCH 6/6] powerpc: pci32: 4xx embedded platforms want to reassign all PCI resources
From: Benjamin Herrenschmidt @ 2007-12-05 0:53 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1196815980.72143.899704305870.qpush@grosgo>
This makes 4xx embedded platforms re-assign all PCI resources as we
pretty much never care about what the various firmwares have done on
these, it's generally not compatible with the way the kernel will map
the bridges.
We still need to also enable bus renumbering on some of them, but I
will do that from a separate patch after I've fixed 4xx PCIe to handle
all bus numbers.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/platforms/40x/ep405.c | 2 ++
arch/powerpc/platforms/40x/kilauea.c | 3 +++
arch/powerpc/platforms/40x/walnut.c | 3 +++
arch/powerpc/platforms/44x/bamboo.c | 4 ++++
arch/powerpc/platforms/44x/ebony.c | 3 +++
arch/powerpc/platforms/44x/katmai.c | 3 +++
arch/powerpc/platforms/44x/sequoia.c | 5 ++++-
arch/powerpc/platforms/44x/taishan.c | 2 ++
8 files changed, 24 insertions(+), 1 deletion(-)
Index: linux-work/arch/powerpc/platforms/44x/bamboo.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/44x/bamboo.c 2007-12-05 11:22:15.000000000 +1100
+++ linux-work/arch/powerpc/platforms/44x/bamboo.c 2007-12-05 11:23:35.000000000 +1100
@@ -21,6 +21,8 @@
#include <asm/udbg.h>
#include <asm/time.h>
#include <asm/uic.h>
+#include <asm/pci-bridge.h>
+
#include "44x.h"
static struct of_device_id bamboo_of_bus[] = {
@@ -48,6 +50,8 @@ static int __init bamboo_probe(void)
if (!of_flat_dt_is_compatible(root, "amcc,bamboo"))
return 0;
+ ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+
return 1;
}
Index: linux-work/arch/powerpc/platforms/40x/ep405.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/40x/ep405.c 2007-12-05 11:22:15.000000000 +1100
+++ linux-work/arch/powerpc/platforms/40x/ep405.c 2007-12-05 11:23:35.000000000 +1100
@@ -102,6 +102,8 @@ static void __init ep405_setup_arch(void
{
/* Find & init the BCSR CPLD */
ep405_init_bcsr();
+
+ ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
}
static int __init ep405_probe(void)
Index: linux-work/arch/powerpc/platforms/40x/kilauea.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/40x/kilauea.c 2007-12-05 11:22:15.000000000 +1100
+++ linux-work/arch/powerpc/platforms/40x/kilauea.c 2007-12-05 11:24:41.000000000 +1100
@@ -19,6 +19,7 @@
#include <asm/udbg.h>
#include <asm/time.h>
#include <asm/uic.h>
+#include <asm/pci-bridge.h>
static struct of_device_id kilauea_of_bus[] = {
{ .compatible = "ibm,plb4", },
@@ -45,6 +46,8 @@ static int __init kilauea_probe(void)
if (!of_flat_dt_is_compatible(root, "amcc,kilauea"))
return 0;
+ ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+
return 1;
}
Index: linux-work/arch/powerpc/platforms/40x/walnut.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/40x/walnut.c 2007-12-05 11:22:15.000000000 +1100
+++ linux-work/arch/powerpc/platforms/40x/walnut.c 2007-12-05 11:24:47.000000000 +1100
@@ -24,6 +24,7 @@
#include <asm/udbg.h>
#include <asm/time.h>
#include <asm/uic.h>
+#include <asm/pci-bridge.h>
static struct of_device_id walnut_of_bus[] = {
{ .compatible = "ibm,plb3", },
@@ -51,6 +52,8 @@ static int __init walnut_probe(void)
if (!of_flat_dt_is_compatible(root, "ibm,walnut"))
return 0;
+ ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+
return 1;
}
Index: linux-work/arch/powerpc/platforms/44x/ebony.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/44x/ebony.c 2007-12-05 11:22:15.000000000 +1100
+++ linux-work/arch/powerpc/platforms/44x/ebony.c 2007-12-05 11:24:13.000000000 +1100
@@ -24,6 +24,7 @@
#include <asm/udbg.h>
#include <asm/time.h>
#include <asm/uic.h>
+#include <asm/pci-bridge.h>
#include "44x.h"
@@ -55,6 +56,8 @@ static int __init ebony_probe(void)
if (!of_flat_dt_is_compatible(root, "ibm,ebony"))
return 0;
+ ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+
return 1;
}
Index: linux-work/arch/powerpc/platforms/44x/katmai.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/44x/katmai.c 2007-12-05 11:22:15.000000000 +1100
+++ linux-work/arch/powerpc/platforms/44x/katmai.c 2007-12-05 11:24:00.000000000 +1100
@@ -21,6 +21,7 @@
#include <asm/udbg.h>
#include <asm/time.h>
#include <asm/uic.h>
+#include <asm/pci-bridge.h>
#include "44x.h"
@@ -49,6 +50,8 @@ static int __init katmai_probe(void)
if (!of_flat_dt_is_compatible(root, "amcc,katmai"))
return 0;
+ ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+
return 1;
}
Index: linux-work/arch/powerpc/platforms/44x/sequoia.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/44x/sequoia.c 2007-12-05 11:22:15.000000000 +1100
+++ linux-work/arch/powerpc/platforms/44x/sequoia.c 2007-12-05 11:24:53.000000000 +1100
@@ -21,7 +21,8 @@
#include <asm/udbg.h>
#include <asm/time.h>
#include <asm/uic.h>
-#include "44x.h"
+#include <asm/pci-bridge.h>
+
static struct of_device_id sequoia_of_bus[] = {
{ .compatible = "ibm,plb4", },
@@ -48,6 +49,8 @@ static int __init sequoia_probe(void)
if (!of_flat_dt_is_compatible(root, "amcc,sequoia"))
return 0;
+ ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+
return 1;
}
Index: linux-work/arch/powerpc/platforms/44x/taishan.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/44x/taishan.c 2007-12-05 11:22:15.000000000 +1100
+++ linux-work/arch/powerpc/platforms/44x/taishan.c 2007-12-05 11:23:35.000000000 +1100
@@ -60,6 +60,8 @@ static int __init taishan_probe(void)
if (!of_flat_dt_is_compatible(root, "ibm,taishan"))
return 0;
+ ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+
return 1;
}
^ permalink raw reply
* [RFC/PATCH 5/6] powerpc: pci32: Remove obsolete PowerMac bus number hack
From: Benjamin Herrenschmidt @ 2007-12-05 0:53 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1196815980.72143.899704305870.qpush@grosgo>
The 32 bits PCI code carries an old hack that was only useful for G5
machines. Nowdays, the 32 bits kernel doesn't support any of those
machines anymore so the hack is basically never used, remove it.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/pci_32.c | 11 -----------
1 file changed, 11 deletions(-)
Index: linux-work/arch/powerpc/kernel/pci_32.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci_32.c 2007-12-05 11:36:30.000000000 +1100
+++ linux-work/arch/powerpc/kernel/pci_32.c 2007-12-05 11:36:36.000000000 +1100
@@ -922,17 +922,6 @@ long sys_pciconfig_iobase(long which, un
struct pci_controller* hose;
long result = -EOPNOTSUPP;
- /* Argh ! Please forgive me for that hack, but that's the
- * simplest way to get existing XFree to not lockup on some
- * G5 machines... So when something asks for bus 0 io base
- * (bus 0 is HT root), we return the AGP one instead.
- */
-#ifdef CONFIG_PPC_PMAC
- if (machine_is(powermac) && machine_is_compatible("MacRISC4"))
- if (bus == 0)
- bus = 0xf0;
-#endif /* CONFIG_PPC_PMAC */
-
hose = pci_bus_to_hose(bus);
if (!hose)
return -ENODEV;
^ permalink raw reply
* [RFC/PATCH 4/6] powerpc: pci32: Add flags modifying the PCI code behaviour
From: Benjamin Herrenschmidt @ 2007-12-05 0:53 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1196815980.72143.899704305870.qpush@grosgo>
This adds to the 32 bits PCI code some flags, replacing the old
pci_assign_all_busses global, that allow to control various
aspects of the PCI probing, such as whether to re-assign all
resources or not, or to not try to assign anything at all.
This also adds the flag x86 already has to avoid ISA alignment
on bridges that don't have ISA forwarding enabled (no legacy
devices on the top level bus) and sets it for PowerMacs.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/pci_32.c | 42 ++++++++++++++++++++++++------
arch/powerpc/kernel/pci_64.c | 1
arch/powerpc/kernel/rtas_pci.c | 6 ++--
arch/powerpc/platforms/52xx/mpc52xx_pci.c | 2 -
arch/powerpc/platforms/82xx/pq2.c | 2 -
arch/powerpc/platforms/83xx/pci.c | 2 -
arch/powerpc/platforms/chrp/pci.c | 2 -
arch/powerpc/platforms/powermac/pci.c | 6 ++--
arch/powerpc/sysdev/fsl_pci.c | 2 -
arch/powerpc/sysdev/grackle.c | 2 -
include/asm-powerpc/pci-bridge.h | 20 ++++++++++++++
include/asm-powerpc/pci.h | 9 ++++--
12 files changed, 74 insertions(+), 22 deletions(-)
Index: linux-work/arch/powerpc/kernel/pci_32.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci_32.c 2007-12-05 11:10:45.000000000 +1100
+++ linux-work/arch/powerpc/kernel/pci_32.c 2007-12-05 11:16:34.000000000 +1100
@@ -35,6 +35,9 @@ unsigned long isa_io_base = 0;
unsigned long pci_dram_offset = 0;
int pcibios_assign_bus_offset = 1;
+/* Default PCI flags is 0 */
+unsigned int ppc_pci_flags;
+
void pcibios_make_OF_bus_map(void);
static void pcibios_fixup_resources(struct pci_dev* dev);
@@ -48,7 +51,7 @@ static u8* pci_to_OF_bus_map;
/* By default, we don't re-assign bus numbers. We do this only on
* some pmacs
*/
-int pci_assign_all_buses;
+static int pci_assign_all_buses;
LIST_HEAD(hose_list);
@@ -174,6 +177,14 @@ void pcibios_bus_to_resource(struct pci_
}
EXPORT_SYMBOL(pcibios_bus_to_resource);
+static int skip_isa_ioresource_align(struct pci_dev *dev)
+{
+ if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
+ !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA))
+ return 1;
+ return 0;
+}
+
/*
* We need to avoid collisions with `mirrored' VGA ports
* and other strange ISA hardware, so we always want the
@@ -195,6 +206,8 @@ void pcibios_align_resource(void *data,
if (res->flags & IORESOURCE_IO) {
resource_size_t start = res->start;
+ if (skip_isa_ioresource_align(dev))
+ return;
if (start & 0x300) {
start = (start + 0x3ff) & ~0x3ff;
res->start = start;
@@ -251,8 +264,13 @@ pcibios_allocate_bus_resources(struct li
continue;
if (bus->parent == NULL)
pr = (res->flags & IORESOURCE_IO)?
- &ioport_resource: &iomem_resource;
+ &ioport_resource : &iomem_resource;
else {
+ /* Don't bother with non-root busses when
+ * re-assigning all resources.
+ */
+ if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)
+ continue;
pr = pci_find_parent_resource(bus->self, res);
if (pr == res) {
/* this happens when the generic PCI
@@ -720,6 +738,9 @@ pcibios_init(void)
printk(KERN_INFO "PCI: Probing PCI hardware\n");
+ if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_BUS)
+ pci_assign_all_buses = 1;
+
/* Scan all of the recorded PCI controllers. */
list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
if (pci_assign_all_buses)
@@ -746,13 +767,18 @@ pcibios_init(void)
if (ppc_md.pcibios_fixup)
ppc_md.pcibios_fixup();
- /* Allocate and assign resources */
+ /* Allocate and assign resources. If we re-assign everything, then
+ * we skip the allocate phase
+ */
pcibios_allocate_bus_resources(&pci_root_buses);
- pcibios_allocate_resources(0);
- pcibios_allocate_resources(1);
-
- DBG("PCI: Assigning unassigned resouces...\n");
- pci_assign_unassigned_resources();
+ if (!(ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)) {
+ pcibios_allocate_resources(0);
+ pcibios_allocate_resources(1);
+ }
+ if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+ DBG("PCI: Assigning unassigned resouces...\n");
+ pci_assign_unassigned_resources();
+ }
/* Call machine dependent post-init code */
if (ppc_md.pcibios_after_init)
Index: linux-work/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci_64.c 2007-12-05 11:10:43.000000000 +1100
+++ linux-work/arch/powerpc/kernel/pci_64.c 2007-12-05 11:10:45.000000000 +1100
@@ -41,7 +41,6 @@
#endif
unsigned long pci_probe_only = 1;
-int pci_assign_all_buses = 0;
static void fixup_resource(struct resource *res, struct pci_dev *dev);
static void do_bus_setup(struct pci_bus *bus);
Index: linux-work/arch/powerpc/platforms/52xx/mpc52xx_pci.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/52xx/mpc52xx_pci.c 2007-09-28 11:42:05.000000000 +1000
+++ linux-work/arch/powerpc/platforms/52xx/mpc52xx_pci.c 2007-12-05 11:10:45.000000000 +1100
@@ -363,7 +363,7 @@ mpc52xx_add_bridge(struct device_node *n
pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
- pci_assign_all_buses = 1;
+ ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
if (of_address_to_resource(node, 0, &rsrc) != 0) {
printk(KERN_ERR "Can't get %s resources\n", node->full_name);
Index: linux-work/arch/powerpc/platforms/82xx/pq2.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/82xx/pq2.c 2007-10-15 11:19:35.000000000 +1000
+++ linux-work/arch/powerpc/platforms/82xx/pq2.c 2007-12-05 11:10:45.000000000 +1100
@@ -53,7 +53,7 @@ static void __init pq2_pci_add_bridge(st
if (of_address_to_resource(np, 0, &r) || r.end - r.start < 0x10b)
goto err;
- pci_assign_all_buses = 1;
+ ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
hose = pcibios_alloc_controller(np);
if (!hose)
Index: linux-work/arch/powerpc/platforms/83xx/pci.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/83xx/pci.c 2007-10-15 11:19:35.000000000 +1000
+++ linux-work/arch/powerpc/platforms/83xx/pci.c 2007-12-05 11:10:45.000000000 +1100
@@ -54,7 +54,7 @@ int __init mpc83xx_add_bridge(struct dev
" bus 0\n", dev->full_name);
}
- pci_assign_all_buses = 1;
+ ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
hose = pcibios_alloc_controller(dev);
if (!hose)
return -ENOMEM;
Index: linux-work/arch/powerpc/platforms/chrp/pci.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/chrp/pci.c 2007-10-15 11:19:35.000000000 +1000
+++ linux-work/arch/powerpc/platforms/chrp/pci.c 2007-12-05 11:10:45.000000000 +1100
@@ -198,7 +198,7 @@ static void __init setup_peg2(struct pci
printk ("RTAS supporting Pegasos OF not found, please upgrade"
" your firmware\n");
}
- pci_assign_all_buses = 1;
+ ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
/* keep the reference to the root node */
}
Index: linux-work/arch/powerpc/platforms/powermac/pci.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/powermac/pci.c 2007-10-15 11:19:35.000000000 +1000
+++ linux-work/arch/powerpc/platforms/powermac/pci.c 2007-12-05 11:10:45.000000000 +1100
@@ -725,7 +725,7 @@ static void __init setup_bandit(struct p
static int __init setup_uninorth(struct pci_controller *hose,
struct resource *addr)
{
- pci_assign_all_buses = 1;
+ ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
has_uninorth = 1;
hose->ops = ¯isc_pci_ops;
hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);
@@ -1043,6 +1043,8 @@ void __init pmac_pci_init(void)
pci_probe_only = 1;
#else /* CONFIG_PPC64 */
+ ppc_pci_flags = PPC_PCI_CAN_SKIP_ISA_ALIGN;
+
init_p2pbridge();
init_second_ohare();
fixup_nec_usb2();
@@ -1051,7 +1053,7 @@ void __init pmac_pci_init(void)
* some offset between bus number and domains for now when we
* assign all busses should help for now
*/
- if (pci_assign_all_buses)
+ if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_BUS)
pcibios_assign_bus_offset = 0x10;
#endif
}
Index: linux-work/arch/powerpc/sysdev/fsl_pci.c
===================================================================
--- linux-work.orig/arch/powerpc/sysdev/fsl_pci.c 2007-10-25 13:15:47.000000000 +1000
+++ linux-work/arch/powerpc/sysdev/fsl_pci.c 2007-12-05 11:10:45.000000000 +1100
@@ -202,7 +202,7 @@ int __init fsl_add_bridge(struct device_
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", dev->full_name);
- pci_assign_all_buses = 1;
+ ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
hose = pcibios_alloc_controller(dev);
if (!hose)
return -ENOMEM;
Index: linux-work/arch/powerpc/sysdev/grackle.c
===================================================================
--- linux-work.orig/arch/powerpc/sysdev/grackle.c 2007-09-28 11:42:05.000000000 +1000
+++ linux-work/arch/powerpc/sysdev/grackle.c 2007-12-05 11:10:45.000000000 +1100
@@ -57,7 +57,7 @@ void __init setup_grackle(struct pci_con
{
setup_indirect_pci(hose, 0xfec00000, 0xfee00000, 0);
if (machine_is_compatible("PowerMac1,1"))
- pci_assign_all_buses = 1;
+ ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
if (machine_is_compatible("AAPL,PowerBook1998"))
grackle_set_loop_snoop(hose, 1);
#if 0 /* Disabled for now, HW problems ??? */
Index: linux-work/include/asm-powerpc/pci-bridge.h
===================================================================
--- linux-work.orig/include/asm-powerpc/pci-bridge.h 2007-12-05 11:10:43.000000000 +1100
+++ linux-work/include/asm-powerpc/pci-bridge.h 2007-12-05 11:34:44.000000000 +1100
@@ -11,6 +11,26 @@
struct device_node;
struct pci_controller;
+extern unsigned int ppc_pci_flags;
+enum {
+ /* Force re-assigning all resources (ignore firmware
+ * setup completely)
+ */
+ PPC_PCI_REASSIGN_ALL_RSRC = 0x00000001,
+
+ /* Re-assign all bus numbers */
+ PPC_PCI_REASSIGN_ALL_BUS = 0x00000002,
+
+ /* Do not try to assign, just use existing setup */
+ PPC_PCI_PROBE_ONLY = 0x00000004,
+
+ /* Don't bother with ISA alignment unless the bridge has
+ * ISA forwarding enabled
+ */
+ PPC_PCI_CAN_SKIP_ISA_ALIGN = 0x00000008,
+};
+
+
/*
* Structure of a PCI controller (host bridge)
*/
Index: linux-work/arch/powerpc/kernel/rtas_pci.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/rtas_pci.c 2007-10-15 11:19:35.000000000 +1000
+++ linux-work/arch/powerpc/kernel/rtas_pci.c 2007-12-05 11:10:45.000000000 +1100
@@ -311,10 +311,12 @@ void __init find_and_init_phbs(void)
if (prop)
pci_probe_only = *prop;
+#ifdef CONFIG_PPC32 /* Will be made generic soon */
prop = of_get_property(of_chosen,
"linux,pci-assign-all-buses", NULL);
- if (prop)
- pci_assign_all_buses = *prop;
+ if (prop && *prop)
+ ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+#endif /* CONFIG_PPC32 */
}
}
Index: linux-work/include/asm-powerpc/pci.h
===================================================================
--- linux-work.orig/include/asm-powerpc/pci.h 2007-12-05 11:22:55.000000000 +1100
+++ linux-work/include/asm-powerpc/pci.h 2007-12-05 11:31:41.000000000 +1100
@@ -38,9 +38,12 @@ struct pci_dev;
* Set this to 1 if you want the kernel to re-assign all PCI
* bus numbers
*/
-extern int pci_assign_all_buses;
-#define pcibios_assign_all_busses() (pci_assign_all_buses)
-
+#ifdef CONFIG_PPC64
+#define pcibios_assign_all_busses() 0
+#else
+#define pcibios_assign_all_busses() (ppc_pci_flags & \
+ PPC_PCI_REASSIGN_ALL_BUS)
+#endif
#define pcibios_scan_all_fns(a, b) 0
static inline void pcibios_set_master(struct pci_dev *dev)
^ permalink raw reply
* [RFC/PATCH 3/6] powerpc: pci32: Remove PowerMac P2P bridge IO hack
From: Benjamin Herrenschmidt @ 2007-12-05 0:53 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1196815980.72143.899704305870.qpush@grosgo>
The 32 bits PowerPC PCI code has a hack for use by some PowerMacs
to try to re-open PCI<->PCI bridge IO resources that were closed
by the firmware. This is no longer necessary as the generic code
will now do that for us.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/pci_32.c | 215 -------------------------------------------
1 file changed, 1 insertion(+), 214 deletions(-)
Index: linux-work/arch/powerpc/kernel/pci_32.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci_32.c 2007-12-04 17:02:13.000000000 +1100
+++ linux-work/arch/powerpc/kernel/pci_32.c 2007-12-04 17:02:31.000000000 +1100
@@ -711,217 +711,6 @@ void pcibios_make_OF_bus_map(void)
}
#endif /* CONFIG_PPC_OF */
-#ifdef CONFIG_PPC_PMAC
-/*
- * This set of routines checks for PCI<->PCI bridges that have closed
- * IO resources and have child devices. It tries to re-open an IO
- * window on them.
- *
- * This is a _temporary_ fix to workaround a problem with Apple's OF
- * closing IO windows on P2P bridges when the OF drivers of cards
- * below this bridge don't claim any IO range (typically ATI or
- * Adaptec).
- *
- * A more complete fix would be to use drivers/pci/setup-bus.c, which
- * involves a working pcibios_fixup_pbus_ranges(), some more care about
- * ordering when creating the host bus resources, and maybe a few more
- * minor tweaks
- */
-
-/* Initialize bridges with base/limit values we have collected */
-static void __init
-do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga)
-{
- struct pci_dev *bridge = bus->self;
- struct pci_controller* hose = (struct pci_controller *)bridge->sysdata;
- u32 l;
- u16 w;
- struct resource res;
-
- if (bus->resource[0] == NULL)
- return;
- res = *(bus->resource[0]);
-
- DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge));
- res.start -= ((unsigned long) hose->io_base_virt - isa_io_base);
- res.end -= ((unsigned long) hose->io_base_virt - isa_io_base);
- DBG(" IO window: %016llx-%016llx\n", res.start, res.end);
-
- /* Set up the top and bottom of the PCI I/O segment for this bus. */
- pci_read_config_dword(bridge, PCI_IO_BASE, &l);
- l &= 0xffff000f;
- l |= (res.start >> 8) & 0x00f0;
- l |= res.end & 0xf000;
- pci_write_config_dword(bridge, PCI_IO_BASE, l);
-
- if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
- l = (res.start >> 16) | (res.end & 0xffff0000);
- pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l);
- }
-
- pci_read_config_word(bridge, PCI_COMMAND, &w);
- w |= PCI_COMMAND_IO;
- pci_write_config_word(bridge, PCI_COMMAND, w);
-
-#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */
- if (enable_vga) {
- pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w);
- w |= PCI_BRIDGE_CTL_VGA;
- pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w);
- }
-#endif
-}
-
-/* This function is pretty basic and actually quite broken for the
- * general case, it's enough for us right now though. It's supposed
- * to tell us if we need to open an IO range at all or not and what
- * size.
- */
-static int __init
-check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga)
-{
- struct pci_dev *dev;
- int i;
- int rc = 0;
-
-#define push_end(res, mask) do { \
- BUG_ON((mask+1) & mask); \
- res->end = (res->end + mask) | mask; \
-} while (0)
-
- list_for_each_entry(dev, &bus->devices, bus_list) {
- u16 class = dev->class >> 8;
-
- if (class == PCI_CLASS_DISPLAY_VGA ||
- class == PCI_CLASS_NOT_DEFINED_VGA)
- *found_vga = 1;
- if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate)
- rc |= check_for_io_childs(dev->subordinate, res, found_vga);
- if (class == PCI_CLASS_BRIDGE_CARDBUS)
- push_end(res, 0xfff);
-
- for (i=0; i<PCI_NUM_RESOURCES; i++) {
- struct resource *r;
- unsigned long r_size;
-
- if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI
- && i >= PCI_BRIDGE_RESOURCES)
- continue;
- r = &dev->resource[i];
- r_size = r->end - r->start;
- if (r_size < 0xfff)
- r_size = 0xfff;
- if (r->flags & IORESOURCE_IO && (r_size) != 0) {
- rc = 1;
- push_end(res, r_size);
- }
- }
- }
-
- return rc;
-}
-
-/* Here we scan all P2P bridges of a given level that have a closed
- * IO window. Note that the test for the presence of a VGA card should
- * be improved to take into account already configured P2P bridges,
- * currently, we don't see them and might end up configuring 2 bridges
- * with VGA pass through enabled
- */
-static void __init
-do_fixup_p2p_level(struct pci_bus *bus)
-{
- struct pci_bus *b;
- int i, parent_io;
- int has_vga = 0;
-
- for (parent_io=0; parent_io<4; parent_io++)
- if (bus->resource[parent_io]
- && bus->resource[parent_io]->flags & IORESOURCE_IO)
- break;
- if (parent_io >= 4)
- return;
-
- list_for_each_entry(b, &bus->children, node) {
- struct pci_dev *d = b->self;
- struct pci_controller* hose = (struct pci_controller *)d->sysdata;
- struct resource *res = b->resource[0];
- struct resource tmp_res;
- unsigned long max;
- int found_vga = 0;
-
- memset(&tmp_res, 0, sizeof(tmp_res));
- tmp_res.start = bus->resource[parent_io]->start;
-
- /* We don't let low addresses go through that closed P2P bridge, well,
- * that may not be necessary but I feel safer that way
- */
- if (tmp_res.start == 0)
- tmp_res.start = 0x1000;
-
- if (!list_empty(&b->devices) && res && res->flags == 0 &&
- res != bus->resource[parent_io] &&
- (d->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
- check_for_io_childs(b, &tmp_res, &found_vga)) {
- u8 io_base_lo;
-
- printk(KERN_INFO "Fixing up IO bus %s\n", b->name);
-
- if (found_vga) {
- if (has_vga) {
- printk(KERN_WARNING "Skipping VGA, already active"
- " on bus segment\n");
- found_vga = 0;
- } else
- has_vga = 1;
- }
- pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo);
-
- if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32)
- max = ((unsigned long) hose->io_base_virt
- - isa_io_base) + 0xffffffff;
- else
- max = ((unsigned long) hose->io_base_virt
- - isa_io_base) + 0xffff;
-
- *res = tmp_res;
- res->flags = IORESOURCE_IO;
- res->name = b->name;
-
- /* Find a resource in the parent where we can allocate */
- for (i = 0 ; i < 4; i++) {
- struct resource *r = bus->resource[i];
- if (!r)
- continue;
- if ((r->flags & IORESOURCE_IO) == 0)
- continue;
- DBG("Trying to allocate from %016llx, size %016llx from parent"
- " res %d: %016llx -> %016llx\n",
- res->start, res->end, i, r->start, r->end);
-
- if (allocate_resource(r, res, res->end + 1, res->start, max,
- res->end + 1, NULL, NULL) < 0) {
- DBG("Failed !\n");
- continue;
- }
- do_update_p2p_io_resource(b, found_vga);
- break;
- }
- }
- do_fixup_p2p_level(b);
- }
-}
-
-static void
-pcibios_fixup_p2p_bridges(void)
-{
- struct pci_bus *b;
-
- list_for_each_entry(b, &pci_root_buses, node)
- do_fixup_p2p_level(b);
-}
-
-#endif /* CONFIG_PPC_PMAC */
-
static int __init
pcibios_init(void)
{
@@ -961,9 +750,7 @@ pcibios_init(void)
pcibios_allocate_bus_resources(&pci_root_buses);
pcibios_allocate_resources(0);
pcibios_allocate_resources(1);
-#ifdef CONFIG_PPC_PMAC
- pcibios_fixup_p2p_bridges();
-#endif /* CONFIG_PPC_PMAC */
+
DBG("PCI: Assigning unassigned resouces...\n");
pci_assign_unassigned_resources();
^ permalink raw reply
* [RFC/PATCH 2/6] powerpc: pci32: use generic pci_assign_unassign_resources
From: Benjamin Herrenschmidt @ 2007-12-05 0:53 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1196815980.72143.899704305870.qpush@grosgo>
This makes the 32 bits PowerPC PCI code use the generic code to assign
resources to devices that had unassigned or conflicting resources.
This allow to remove the local implementation that was incomplete and
could not assign for example a PCI<->PCI bridge from scratch, which is
needed on various embedded platforms.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/pci_32.c | 191 +++----------------------------------------
1 file changed, 17 insertions(+), 174 deletions(-)
Index: linux-work/arch/powerpc/kernel/pci_32.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci_32.c 2007-12-04 17:02:12.000000000 +1100
+++ linux-work/arch/powerpc/kernel/pci_32.c 2007-12-04 17:02:13.000000000 +1100
@@ -37,10 +37,6 @@ int pcibios_assign_bus_offset = 1;
void pcibios_make_OF_bus_map(void);
-static int pci_relocate_bridge_resource(struct pci_bus *bus, int i);
-static int probe_resource(struct pci_bus *parent, struct resource *pr,
- struct resource *res, struct resource **conflict);
-static void update_bridge_base(struct pci_bus *bus, int i);
static void pcibios_fixup_resources(struct pci_dev* dev);
static void fixup_broken_pcnet32(struct pci_dev* dev);
static int reparent_resources(struct resource *parent, struct resource *res);
@@ -134,7 +130,7 @@ pcibios_fixup_resources(struct pci_dev *
if (offset != 0) {
res->start = (res->start + offset) & mask;
res->end = (res->end + offset) & mask;
- DBG("Fixup res %d (%lx) of dev %s: %llx -> %llx\n",
+ DBG("PCI: Fixup res %d (0x%lx) of dev %s: %llx -> %llx\n",
i, res->flags, pci_name(dev),
(u64)res->start - offset, (u64)res->start);
}
@@ -267,9 +263,12 @@ pcibios_allocate_bus_resources(struct li
}
}
- DBG("PCI: bridge rsrc %llx..%llx (%lx), parent %p\n",
+ DBG("PCI: dev %s (bus 0x%02x) bridge rsrc %d: %016llx..%016llx "
+ "(f:0x%08lx), parent %p\n",
+ bus->self ? pci_name(bus->self) : "PHB", bus->number, i,
(u64)res->start, (u64)res->end, res->flags, pr);
- if (pr) {
+
+ if (pr && !(pr->flags & IORESOURCE_UNSET)) {
if (request_resource(pr, res) == 0)
continue;
/*
@@ -280,10 +279,11 @@ pcibios_allocate_bus_resources(struct li
if (reparent_resources(pr, res) == 0)
continue;
}
- printk(KERN_ERR "PCI: Cannot allocate resource region "
- "%d of PCI bridge %d\n", i, bus->number);
- if (pci_relocate_bridge_resource(bus, i))
- bus->resource[i] = NULL;
+ printk(KERN_WARNING
+ "PCI: Cannot allocate resource region "
+ "%d of PCI bridge %d, will remap\n",
+ i, bus->number);
+ res->flags |= IORESOURCE_UNSET;
}
pcibios_allocate_bus_resources(&bus->children);
}
@@ -324,112 +324,6 @@ reparent_resources(struct resource *pare
return 0;
}
-/*
- * A bridge has been allocated a range which is outside the range
- * of its parent bridge, so it needs to be moved.
- */
-static int __init
-pci_relocate_bridge_resource(struct pci_bus *bus, int i)
-{
- struct resource *res, *pr, *conflict;
- resource_size_t try, size;
- struct pci_bus *parent = bus->parent;
- int j;
-
- if (parent == NULL) {
- /* shouldn't ever happen */
- printk(KERN_ERR "PCI: can't move host bridge resource\n");
- return -1;
- }
- res = bus->resource[i];
- if (res == NULL)
- return -1;
- pr = NULL;
- for (j = 0; j < 4; j++) {
- struct resource *r = parent->resource[j];
- if (!r)
- continue;
- if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
- continue;
- if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) {
- pr = r;
- break;
- }
- if (res->flags & IORESOURCE_PREFETCH)
- pr = r;
- }
- if (pr == NULL)
- return -1;
- size = res->end - res->start;
- if (pr->start > pr->end || size > pr->end - pr->start)
- return -1;
- try = pr->end;
- for (;;) {
- res->start = try - size;
- res->end = try;
- if (probe_resource(bus->parent, pr, res, &conflict) == 0)
- break;
- if (conflict->start <= pr->start + size)
- return -1;
- try = conflict->start - 1;
- }
- if (request_resource(pr, res)) {
- DBG(KERN_ERR "PCI: huh? couldn't move to %llx..%llx\n",
- (u64)res->start, (u64)res->end);
- return -1; /* "can't happen" */
- }
- update_bridge_base(bus, i);
- printk(KERN_INFO "PCI: bridge %d resource %d moved to %llx..%llx\n",
- bus->number, i, (unsigned long long)res->start,
- (unsigned long long)res->end);
- return 0;
-}
-
-static int __init
-probe_resource(struct pci_bus *parent, struct resource *pr,
- struct resource *res, struct resource **conflict)
-{
- struct pci_bus *bus;
- struct pci_dev *dev;
- struct resource *r;
- int i;
-
- for (r = pr->child; r != NULL; r = r->sibling) {
- if (r->end >= res->start && res->end >= r->start) {
- *conflict = r;
- return 1;
- }
- }
- list_for_each_entry(bus, &parent->children, node) {
- for (i = 0; i < 4; ++i) {
- if ((r = bus->resource[i]) == NULL)
- continue;
- if (!r->flags || r->start > r->end || r == res)
- continue;
- if (pci_find_parent_resource(bus->self, r) != pr)
- continue;
- if (r->end >= res->start && res->end >= r->start) {
- *conflict = r;
- return 1;
- }
- }
- }
- list_for_each_entry(dev, &parent->devices, bus_list) {
- for (i = 0; i < 6; ++i) {
- r = &dev->resource[i];
- if (!r->flags || (r->flags & IORESOURCE_UNSET))
- continue;
- if (pci_find_parent_resource(dev, r) != pr)
- continue;
- if (r->end >= res->start && res->end >= r->start) {
- *conflict = r;
- return 1;
- }
- }
- }
- return 0;
-}
-
void __init
update_bridge_resource(struct pci_dev *dev, struct resource *res)
{
@@ -486,24 +380,16 @@ update_bridge_resource(struct pci_dev *d
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
-static void __init
-update_bridge_base(struct pci_bus *bus, int i)
-{
- struct resource *res = bus->resource[i];
- struct pci_dev *dev = bus->self;
- update_bridge_resource(dev, res);
-}
-
static inline void alloc_resource(struct pci_dev *dev, int idx)
{
struct resource *pr, *r = &dev->resource[idx];
- DBG("PCI:%s: Resource %d: %016llx-%016llx (f=%lx)\n",
+ DBG("PCI: Allocating %s: Resource %d: %016llx..%016llx (f=%lx)\n",
pci_name(dev), idx, (u64)r->start, (u64)r->end, r->flags);
pr = pci_find_parent_resource(dev, r);
- if (!pr || request_resource(pr, r) < 0) {
- printk(KERN_WARNING "PCI: Remapping resource region %d"
- " of device %s\n", idx, pci_name(dev));
+ if (!pr || (pr->flags & IORESOURCE_UNSET) || request_resource(pr, r) < 0) {
+ printk(KERN_WARNING "PCI: Cannot allocate resource region %d"
+ " of device %s, will remap\n", idx, pci_name(dev));
if (pr)
DBG("PCI: parent is %p: %016llx-%016llx (f=%lx)\n",
pr, (u64)pr->start, (u64)pr->end, pr->flags);
@@ -552,50 +438,6 @@ pcibios_allocate_resources(int pass)
}
}
-static void __init
-pcibios_assign_resources(void)
-{
- struct pci_dev *dev = NULL;
- int idx;
- struct resource *r;
-
- for_each_pci_dev(dev) {
- int class = dev->class >> 8;
-
- /* Don't touch classless devices and host bridges */
- if (!class || class == PCI_CLASS_BRIDGE_HOST)
- continue;
-
- for (idx = 0; idx < 6; idx++) {
- r = &dev->resource[idx];
-
- /*
- * We shall assign a new address to this resource,
- * either because the BIOS (sic) forgot to do so
- * or because we have decided the old address was
- * unusable for some reason.
- */
- if ((r->flags & IORESOURCE_UNSET) && r->end &&
- (!ppc_md.pcibios_enable_device_hook ||
- !ppc_md.pcibios_enable_device_hook(dev, 1))) {
- int rc;
-
- r->flags &= ~IORESOURCE_UNSET;
- rc = pci_assign_resource(dev, idx);
- BUG_ON(rc);
- }
- }
-
-#if 0 /* don't assign ROMs */
- r = &dev->resource[PCI_ROM_RESOURCE];
- r->end -= r->start;
- r->start = 0;
- if (r->end)
- pci_assign_resource(dev, PCI_ROM_RESOURCE);
-#endif
- }
-}
-
#ifdef CONFIG_PPC_OF
/*
* Functions below are used on OpenFirmware machines.
@@ -1122,7 +964,8 @@ pcibios_init(void)
#ifdef CONFIG_PPC_PMAC
pcibios_fixup_p2p_bridges();
#endif /* CONFIG_PPC_PMAC */
- pcibios_assign_resources();
+ DBG("PCI: Assigning unassigned resouces...\n");
+ pci_assign_unassigned_resources();
/* Call machine dependent post-init code */
if (ppc_md.pcibios_after_init)
^ permalink raw reply
* [RFC/PATCH 1/6] powerpc: pci32: remove bogus alignment message
From: Benjamin Herrenschmidt @ 2007-12-05 0:53 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1196815980.72143.899704305870.qpush@grosgo>
There's a stale & bogus piece of code in 32 bits PCI code that
complains about ISA related alignment issues. Just remove it.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/pci_32.c | 6 ------
1 file changed, 6 deletions(-)
Index: linux-work/arch/powerpc/kernel/pci_32.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci_32.c 2007-12-04 16:59:57.000000000 +1100
+++ linux-work/arch/powerpc/kernel/pci_32.c 2007-12-04 16:59:57.000000000 +1100
@@ -199,12 +199,6 @@ void pcibios_align_resource(void *data,
if (res->flags & IORESOURCE_IO) {
resource_size_t start = res->start;
- if (size > 0x100) {
- printk(KERN_ERR "PCI: I/O Region %s/%d too large"
- " (%lld bytes)\n", pci_name(dev),
- dev->resource - res, (unsigned long long)size);
- }
-
if (start & 0x300) {
start = (start + 0x3ff) & ~0x3ff;
res->start = start;
^ permalink raw reply
* [RFC/PATCH 0/6] powerpc: 32 bits PCI updates
From: Benjamin Herrenschmidt @ 2007-12-05 0:53 UTC (permalink / raw)
To: linuxppc-dev
This serie of patches converts the 32 bits PCI code to use the generic
pci_assign_unassigned_resources() instead of its own assignment code
which was unable to deal with unassigned PCI<->PCI bridges among
other issues.
We also add flags to control the behaviour of the PCI code, such as
letting some platforms force a full re-assignment (similar to what
pci-auto used to provide in arch/ppc) and remove a whole bunch of
hackish code that is made obsolete by that change.
This also brings us one step closer to a merge of the PCI code with
ppc64 as we are now in a shape where most of that resource management
code will be able to move to pci-common.c and be used by 64 bits.
32 bits platforms with 64 bits resources support will also need my
separate patch to fix the generic setup-bus.c for that situation.
Note that the patch that updates 4xx platforms to enable full resource
assignments applied on top of my 4xx series for which I'll post a new
version soon. You can apply the other ones and ignore this one if you
want to test on some other platform without the other patch serie.
^ permalink raw reply
* Re: [PATCH v2 2/4] [libata] pata_of_platform: OF-Platform PATA device driver
From: Paul Mundt @ 2007-12-05 0:48 UTC (permalink / raw)
To: Olof Johansson; +Cc: linux-ide, Arnd Bergmann, Jeff Garzik, linuxppc-dev
In-Reply-To: <20071204200121.GA6782@lixom.net>
On Tue, Dec 04, 2007 at 02:01:21PM -0600, Olof Johansson wrote:
> On Tue, Dec 04, 2007 at 10:49:21PM +0300, Anton Vorontsov wrote:
> > tristate "Generic platform device PATA support"
> > - depends on EMBEDDED || ARCH_RPC
> > + depends on EMBEDDED || ARCH_PPC
>
> It needs to be || PPC, not || ARCH_PPC.
>
Wrong. It needs to be EMBEDDED || ARCH_RPC || PPC.
ARCH_RPC is not a typo, it's an ARM platform. Please grep first :-)
^ permalink raw reply
* Re: [PATCH 2/2] [POWERPC] pasemi: Register i2c_board_info
From: Paul Mackerras @ 2007-12-05 0:41 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, David Woodhouse
In-Reply-To: <20071204193220.GC5758@lixom.net>
Olof Johansson writes:
> Yep, I realized that after (re)asking Paul to pull though, and didn't
> want to do a third request before he's done it. :)
>
> If he doesn't pull in the next few days I might just keep adding new
> patches as they come in though, and add it back.
I haven't pulled yet; sounds like I need to wait a few more days
first. :)
Paul.
^ permalink raw reply
* [PATCH 11/11] ibm_newemac: Update file headers copyright notices
From: Benjamin Herrenschmidt @ 2007-12-05 0:14 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
This updates the copyright notices of the new EMAC driver to
avoid confusion as who is to be blamed for new bugs.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/net/ibm_newemac/core.c | 5 +++++
drivers/net/ibm_newemac/core.h | 5 +++++
drivers/net/ibm_newemac/debug.c | 5 +++++
drivers/net/ibm_newemac/debug.h | 5 +++++
drivers/net/ibm_newemac/emac.h | 5 +++++
drivers/net/ibm_newemac/mal.c | 5 +++++
drivers/net/ibm_newemac/mal.h | 5 +++++
drivers/net/ibm_newemac/phy.c | 5 +++++
drivers/net/ibm_newemac/phy.h | 5 +++++
drivers/net/ibm_newemac/rgmii.c | 5 +++++
drivers/net/ibm_newemac/rgmii.h | 5 +++++
drivers/net/ibm_newemac/tah.c | 5 +++++
drivers/net/ibm_newemac/tah.h | 5 +++++
drivers/net/ibm_newemac/zmii.c | 5 +++++
drivers/net/ibm_newemac/zmii.h | 5 +++++
15 files changed, 75 insertions(+)
Index: linux-work/drivers/net/ibm_newemac/core.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/core.c 2007-11-30 15:35:50.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/core.c 2007-11-30 16:03:30.000000000 +1100
@@ -3,6 +3,11 @@
*
* Driver for PowerPC 4xx on-chip ethernet controller.
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* Copyright (c) 2004, 2005 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
Index: linux-work/drivers/net/ibm_newemac/core.h
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/core.h 2007-11-30 15:35:50.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/core.h 2007-11-30 16:03:23.000000000 +1100
@@ -3,6 +3,11 @@
*
* Driver for PowerPC 4xx on-chip ethernet controller.
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* Copyright (c) 2004, 2005 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
Index: linux-work/drivers/net/ibm_newemac/debug.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/debug.c 2007-11-30 15:35:50.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/debug.c 2007-11-30 16:03:18.000000000 +1100
@@ -3,6 +3,11 @@
*
* Driver for PowerPC 4xx on-chip ethernet controller, debug print routines.
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* Copyright (c) 2004, 2005 Zultys Technologies
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
Index: linux-work/drivers/net/ibm_newemac/debug.h
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/debug.h 2007-11-30 15:35:50.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/debug.h 2007-11-30 16:03:15.000000000 +1100
@@ -3,6 +3,11 @@
*
* Driver for PowerPC 4xx on-chip ethernet controller, debug print routines.
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* Copyright (c) 2004, 2005 Zultys Technologies
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
Index: linux-work/drivers/net/ibm_newemac/emac.h
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/emac.h 2007-11-30 15:35:50.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/emac.h 2007-11-30 16:03:09.000000000 +1100
@@ -3,6 +3,11 @@
*
* Register definitions for PowerPC 4xx on-chip ethernet contoller
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* Copyright (c) 2004, 2005 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
Index: linux-work/drivers/net/ibm_newemac/mal.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/mal.c 2007-11-30 15:35:51.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/mal.c 2007-11-30 16:03:02.000000000 +1100
@@ -3,6 +3,11 @@
*
* Memory Access Layer (MAL) support
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* Copyright (c) 2004, 2005 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
Index: linux-work/drivers/net/ibm_newemac/mal.h
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/mal.h 2007-11-30 15:35:51.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/mal.h 2007-11-30 16:02:55.000000000 +1100
@@ -3,6 +3,11 @@
*
* Memory Access Layer (MAL) support
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* Copyright (c) 2004, 2005 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
Index: linux-work/drivers/net/ibm_newemac/phy.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/phy.c 2007-11-30 15:35:51.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/phy.c 2007-11-30 16:02:47.000000000 +1100
@@ -8,6 +8,11 @@
* This file should be shared with other drivers or eventually
* merged as the "low level" part of miilib
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* (c) 2003, Benjamin Herrenscmidt (benh@kernel.crashing.org)
* (c) 2004-2005, Eugene Surovegin <ebs@ebshome.net>
*
Index: linux-work/drivers/net/ibm_newemac/phy.h
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/phy.h 2007-11-30 15:35:51.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/phy.h 2007-11-30 16:02:32.000000000 +1100
@@ -3,6 +3,11 @@
*
* Driver for PowerPC 4xx on-chip ethernet controller, PHY support
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* Benjamin Herrenschmidt <benh@kernel.crashing.org>
* February 2003
*
Index: linux-work/drivers/net/ibm_newemac/rgmii.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/rgmii.c 2007-11-30 15:35:51.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/rgmii.c 2007-11-30 16:02:23.000000000 +1100
@@ -3,6 +3,11 @@
*
* Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support.
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* Copyright (c) 2004, 2005 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
Index: linux-work/drivers/net/ibm_newemac/rgmii.h
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/rgmii.h 2007-11-30 15:35:51.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/rgmii.h 2007-11-30 16:02:19.000000000 +1100
@@ -3,6 +3,11 @@
*
* Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support.
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* Based on ocp_zmii.h/ibm_emac_zmii.h
* Armin Kuster akuster@mvista.com
*
Index: linux-work/drivers/net/ibm_newemac/tah.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/tah.c 2007-11-30 15:35:51.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/tah.c 2007-11-30 16:02:11.000000000 +1100
@@ -3,6 +3,11 @@
*
* Driver for PowerPC 4xx on-chip ethernet controller, TAH support.
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* Copyright 2004 MontaVista Software, Inc.
* Matt Porter <mporter@kernel.crashing.org>
*
Index: linux-work/drivers/net/ibm_newemac/tah.h
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/tah.h 2007-11-30 15:35:51.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/tah.h 2007-11-30 16:02:06.000000000 +1100
@@ -3,6 +3,11 @@
*
* Driver for PowerPC 4xx on-chip ethernet controller, TAH support.
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* Copyright 2004 MontaVista Software, Inc.
* Matt Porter <mporter@kernel.crashing.org>
*
Index: linux-work/drivers/net/ibm_newemac/zmii.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/zmii.c 2007-11-30 15:35:51.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/zmii.c 2007-11-30 16:01:53.000000000 +1100
@@ -3,6 +3,11 @@
*
* Driver for PowerPC 4xx on-chip ethernet controller, ZMII bridge support.
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* Copyright (c) 2004, 2005 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
Index: linux-work/drivers/net/ibm_newemac/zmii.h
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/zmii.h 2007-11-30 15:35:51.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/zmii.h 2007-11-30 16:01:33.000000000 +1100
@@ -3,6 +3,11 @@
*
* Driver for PowerPC 4xx on-chip ethernet controller, ZMII bridge support.
*
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * Based on the arch/ppc version of the driver:
+ *
* Copyright (c) 2004, 2005 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
^ permalink raw reply
* [PATCH 10/11] ibm_newemac: Call dev_set_drvdata() before tah_reset()
From: Benjamin Herrenschmidt @ 2007-12-05 0:14 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
From: Valentine Barshak <vbarshak@ru.mvista.com>
The patch moves dev_set_drvdata(&ofdev->dev, dev) up before tah_reset(ofdev)
is called to avoid a NULL pointer dereference, since tah_reset uses drvdata.
Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
diff -pruN linux-2.6.orig/drivers/net/ibm_newemac/tah.c linux-2.6/drivers/net/ibm_newemac/tah.c
--- linux-2.6.orig/drivers/net/ibm_newemac/tah.c 2007-11-23 21:27:57.000000000 +0300
+++ linux-2.6/drivers/net/ibm_newemac/tah.c 2007-11-23 21:35:12.000000000 +0300
@@ -116,13 +116,14 @@ static int __devinit tah_probe(struct of
goto err_free;
}
+ dev_set_drvdata(&ofdev->dev, dev);
+
/* Initialize TAH and enable IPv4 checksum verification, no TSO yet */
tah_reset(ofdev);
printk(KERN_INFO
"TAH %s initialized\n", ofdev->node->full_name);
wmb();
- dev_set_drvdata(&ofdev->dev, dev);
return 0;
^ permalink raw reply
* [PATCH 9/11] ibm_newemac: Fix typo reading TAH channel info
From: Benjamin Herrenschmidt @ 2007-12-05 0:14 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
From: Valentine Barshak <vbarshak@ru.mvista.com>
This patch fixes a typo in ibm_newemac/core.c
(tah_port should be used instead of tah_ph)
Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/net/ibm_newemac/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: linux-work/drivers/net/ibm_newemac/core.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/core.c 2007-11-26 09:43:04.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/core.c 2007-11-26 09:43:05.000000000 +1100
@@ -2442,7 +2442,7 @@ static int __devinit emac_init_config(st
if (emac_read_uint_prop(np, "tah-device", &dev->tah_ph, 0))
dev->tah_ph = 0;
if (emac_read_uint_prop(np, "tah-channel", &dev->tah_port, 0))
- dev->tah_ph = 0;
+ dev->tah_port = 0;
if (emac_read_uint_prop(np, "mdio-device", &dev->mdio_ph, 0))
dev->mdio_ph = 0;
if (emac_read_uint_prop(np, "zmii-device", &dev->zmii_ph, 0))
^ permalink raw reply
* [PATCH 8/11] ibm_newemac: Correct opb_bus_freq value
From: Benjamin Herrenschmidt @ 2007-12-05 0:14 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
From: Valentine Barshak <vbarshak@ru.mvista.com>
The EMAC4_MR1_OBCI(freq) macro expects freg in MHz,
while opb_bus_freq is kept in Hz. Correct this.
Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
diff -pruN linux-2.6.orig/drivers/net/ibm_newemac/core.c linux-2.6/drivers/net/ibm_newemac/core.c
--- linux-2.6.orig/drivers/net/ibm_newemac/core.c 2007-11-23 21:27:57.000000000 +0300
+++ linux-2.6/drivers/net/ibm_newemac/core.c 2007-11-23 21:47:53.000000000 +0300
@@ -402,7 +402,7 @@ static u32 __emac_calc_base_mr1(struct e
static u32 __emac4_calc_base_mr1(struct emac_instance *dev, int tx_size, int rx_size)
{
u32 ret = EMAC_MR1_VLE | EMAC_MR1_IST | EMAC4_MR1_TR |
- EMAC4_MR1_OBCI(dev->opb_bus_freq);
+ EMAC4_MR1_OBCI(dev->opb_bus_freq / 1000000);
DBG2(dev, "__emac4_calc_base_mr1" NL);
^ permalink raw reply
* [PATCH 7/11] ibm_newemac: Skip EMACs that are marked unused by the firmware
From: Benjamin Herrenschmidt @ 2007-12-05 0:14 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
From: Hugh Blemings <hugh@blemings.org>
Depending on how the 44x processors are wired, some EMAC cells
might not be useable (and not connected to a PHY). However, some
device-trees may choose to still expose them (since their registers
are present in the MMIO space) but with an "unused" property in them.
Signed-off-by: Hugh Blemings <hugh@blemings.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/net/ibm_newemac/core.c | 4 ++++
1 file changed, 4 insertions(+)
Index: linux-work/drivers/net/ibm_newemac/core.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/core.c 2007-11-20 14:47:02.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/core.c 2007-11-20 14:47:05.000000000 +1100
@@ -2550,6 +2550,10 @@ static int __devinit emac_probe(struct o
struct device_node **blist = NULL;
int err, i;
+ /* Skip unused/unwired EMACS */
+ if (of_get_property(np, "unused", NULL))
+ return -ENODEV;
+
/* Find ourselves in the bootlist if we are there */
for (i = 0; i < EMAC_BOOT_LIST_SIZE; i++)
if (emac_boot_list[i] == np)
^ permalink raw reply
* [PATCH 6/11] ibm_newemac: Cleanup/fix support for STACR register variants
From: Benjamin Herrenschmidt @ 2007-12-05 0:14 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
There are a few variants of the STACR register that affect more than
just the "AXON" version of EMAC. Replace the current test of various
chip models with tests for generic properties in the device-tree.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Stefan Roese <sr@denx.de>
---
arch/powerpc/boot/dts/sequoia.dts | 4 ++++
drivers/net/ibm_newemac/core.c | 23 +++++++++++++----------
drivers/net/ibm_newemac/core.h | 6 +++---
3 files changed, 20 insertions(+), 13 deletions(-)
Index: linux-work/arch/powerpc/boot/dts/sequoia.dts
===================================================================
--- linux-work.orig/arch/powerpc/boot/dts/sequoia.dts 2007-11-20 14:47:01.000000000 +1100
+++ linux-work/arch/powerpc/boot/dts/sequoia.dts 2007-11-20 14:47:02.000000000 +1100
@@ -274,6 +274,8 @@
zmii-channel = <0>;
rgmii-device = <&RGMII0>;
rgmii-channel = <0>;
+ has-inverted-stacr-oc;
+ has-new-stacr-staopc;
};
EMAC1: ethernet@ef600f00 {
@@ -302,6 +304,8 @@
zmii-channel = <1>;
rgmii-device = <&RGMII0>;
rgmii-channel = <1>;
+ has-inverted-stacr-oc;
+ has-new-stacr-staopc;
};
};
};
Index: linux-work/drivers/net/ibm_newemac/core.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/core.c 2007-11-20 14:46:58.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/core.c 2007-11-20 14:47:02.000000000 +1100
@@ -711,7 +711,7 @@ static int __emac_mdio_read(struct emac_
r = EMAC_STACR_BASE(dev->opb_bus_freq);
if (emac_has_feature(dev, EMAC_FTR_STACR_OC_INVERT))
r |= EMAC_STACR_OC;
- if (emac_has_feature(dev, EMAC_FTR_HAS_AXON_STACR))
+ if (emac_has_feature(dev, EMAC_FTR_HAS_NEW_STACR))
r |= EMACX_STACR_STAC_READ;
else
r |= EMAC_STACR_STAC_READ;
@@ -783,7 +783,7 @@ static void __emac_mdio_write(struct ema
r = EMAC_STACR_BASE(dev->opb_bus_freq);
if (emac_has_feature(dev, EMAC_FTR_STACR_OC_INVERT))
r |= EMAC_STACR_OC;
- if (emac_has_feature(dev, EMAC_FTR_HAS_AXON_STACR))
+ if (emac_has_feature(dev, EMAC_FTR_HAS_NEW_STACR))
r |= EMACX_STACR_STAC_WRITE;
else
r |= EMAC_STACR_STAC_WRITE;
@@ -2480,16 +2480,19 @@ static int __devinit emac_init_config(st
/* Check EMAC version */
if (of_device_is_compatible(np, "ibm,emac4"))
dev->features |= EMAC_FTR_EMAC4;
- if (of_device_is_compatible(np, "ibm,emac-axon")
- || of_device_is_compatible(np, "ibm,emac-440epx"))
- dev->features |= EMAC_FTR_HAS_AXON_STACR
- | EMAC_FTR_STACR_OC_INVERT;
- if (of_device_is_compatible(np, "ibm,emac-440spe"))
+
+ /* Fixup some feature bits based on the device tree */
+ if (of_get_property(np, "has-inverted-stacr-oc", NULL))
dev->features |= EMAC_FTR_STACR_OC_INVERT;
+ if (of_get_property(np, "has-new-stacr-staopc", NULL))
+ dev->features |= EMAC_FTR_HAS_NEW_STACR;
- /* Fixup some feature bits based on the device tree and verify
- * we have support for them compiled in
- */
+ /* CAB lacks the appropriate properties */
+ if (of_device_is_compatible(np, "ibm,emac-axon"))
+ dev->features |= EMAC_FTR_HAS_NEW_STACR |
+ EMAC_FTR_STACR_OC_INVERT;
+
+ /* Enable TAH/ZMII/RGMII features as found */
if (dev->tah_ph != 0) {
#ifdef CONFIG_IBM_NEW_EMAC_TAH
dev->features |= EMAC_FTR_HAS_TAH;
Index: linux-work/drivers/net/ibm_newemac/core.h
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/core.h 2007-11-20 14:46:51.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/core.h 2007-11-20 14:47:02.000000000 +1100
@@ -293,9 +293,9 @@ struct emac_instance {
*/
#define EMAC_FTR_HAS_RGMII 0x00000020
/*
- * Set if we have axon-type STACR
+ * Set if we have new type STACR with STAOPC
*/
-#define EMAC_FTR_HAS_AXON_STACR 0x00000040
+#define EMAC_FTR_HAS_NEW_STACR 0x00000040
/* Right now, we don't quite handle the always/possible masks on the
@@ -307,7 +307,7 @@ enum {
EMAC_FTRS_POSSIBLE =
#ifdef CONFIG_IBM_NEW_EMAC_EMAC4
- EMAC_FTR_EMAC4 | EMAC_FTR_HAS_AXON_STACR |
+ EMAC_FTR_EMAC4 | EMAC_FTR_HAS_NEW_STACR |
EMAC_FTR_STACR_OC_INVERT |
#endif
#ifdef CONFIG_IBM_NEW_EMAC_TAH
^ permalink raw reply
* [PATCH 5/11] ibm_newemac: Cleanup/Fix RGMII MDIO support detection
From: Benjamin Herrenschmidt @ 2007-12-05 0:14 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
More than just "AXON" version of EMAC RGMII supports MDIO, so replace
the current test with a generic property in the device-tree that
indicates such support.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Stefan Roese <sr@denx.de>
---
arch/powerpc/boot/dts/sequoia.dts | 1 +
drivers/net/ibm_newemac/rgmii.c | 20 +++++++++++---------
drivers/net/ibm_newemac/rgmii.h | 5 +++--
3 files changed, 15 insertions(+), 11 deletions(-)
Index: linux-work/drivers/net/ibm_newemac/rgmii.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/rgmii.c 2007-11-12 10:55:54.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/rgmii.c 2007-11-12 10:56:56.000000000 +1100
@@ -140,7 +140,7 @@ void rgmii_get_mdio(struct of_device *of
RGMII_DBG2(dev, "get_mdio(%d)" NL, input);
- if (dev->type != RGMII_AXON)
+ if (!(dev->flags & EMAC_RGMII_FLAG_HAS_MDIO))
return;
mutex_lock(&dev->lock);
@@ -161,7 +161,7 @@ void rgmii_put_mdio(struct of_device *of
RGMII_DBG2(dev, "put_mdio(%d)" NL, input);
- if (dev->type != RGMII_AXON)
+ if (!(dev->flags & EMAC_RGMII_FLAG_HAS_MDIO))
return;
fer = in_be32(&p->fer);
@@ -250,11 +250,13 @@ static int __devinit rgmii_probe(struct
goto err_free;
}
- /* Check for RGMII type */
+ /* Check for RGMII flags */
+ if (of_get_property(ofdev->node, "has-mdio", NULL))
+ dev->flags |= EMAC_RGMII_FLAG_HAS_MDIO;
+
+ /* CAB lacks the right properties, fix this up */
if (of_device_is_compatible(ofdev->node, "ibm,rgmii-axon"))
- dev->type = RGMII_AXON;
- else
- dev->type = RGMII_STANDARD;
+ dev->flags |= EMAC_RGMII_FLAG_HAS_MDIO;
DBG2(dev, " Boot FER = 0x%08x, SSR = 0x%08x\n",
in_be32(&dev->base->fer), in_be32(&dev->base->ssr));
@@ -263,9 +265,9 @@ static int __devinit rgmii_probe(struct
out_be32(&dev->base->fer, 0);
printk(KERN_INFO
- "RGMII %s %s initialized\n",
- dev->type == RGMII_STANDARD ? "standard" : "axon",
- ofdev->node->full_name);
+ "RGMII %s initialized with%s MDIO support\n",
+ ofdev->node->full_name,
+ (dev->flags & EMAC_RGMII_FLAG_HAS_MDIO) ? "" : "out");
wmb();
dev_set_drvdata(&ofdev->dev, dev);
Index: linux-work/drivers/net/ibm_newemac/rgmii.h
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/rgmii.h 2007-11-12 10:55:54.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/rgmii.h 2007-11-12 10:56:56.000000000 +1100
@@ -35,8 +35,9 @@ struct rgmii_regs {
struct rgmii_instance {
struct rgmii_regs __iomem *base;
- /* Type of RGMII bridge */
- int type;
+ /* RGMII bridge flags */
+ int flags;
+#define EMAC_RGMII_FLAG_HAS_MDIO 0x00000001
/* Only one EMAC whacks us at a time */
struct mutex lock;
Index: linux-work/arch/powerpc/boot/dts/sequoia.dts
===================================================================
--- linux-work.orig/arch/powerpc/boot/dts/sequoia.dts 2007-11-12 10:58:38.000000000 +1100
+++ linux-work/arch/powerpc/boot/dts/sequoia.dts 2007-11-12 10:58:47.000000000 +1100
@@ -245,6 +245,7 @@
device_type = "rgmii-interface";
compatible = "ibm,rgmii-440epx", "ibm,rgmii";
reg = <ef601000 8>;
+ has-mdio;
};
EMAC0: ethernet@ef600e00 {
^ permalink raw reply
* [PATCH 4/11] ibm_newemac: Workaround reset timeout when no link
From: Benjamin Herrenschmidt @ 2007-12-05 0:14 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
With some PHYs, when the link goes away, the EMAC reset fails due
to the loss of the RX clock I believe.
The old EMAC driver worked around that using some internal chip-specific
clock force bits that are different on various 44x implementations.
This is an attempt at doing it differently, by avoiding the reset when
there is no link, but forcing loopback mode instead. It seems to work
on my Taishan 440GX based board so far.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Stefan Roese <sr@denx.de>
---
drivers/net/ibm_newemac/core.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
Index: linux-work/drivers/net/ibm_newemac/core.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/core.c 2007-11-20 14:46:51.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/core.c 2007-11-20 14:46:58.000000000 +1100
@@ -464,26 +464,34 @@ static int emac_configure(struct emac_in
{
struct emac_regs __iomem *p = dev->emacp;
struct net_device *ndev = dev->ndev;
- int tx_size, rx_size;
+ int tx_size, rx_size, link = netif_carrier_ok(dev->ndev);
u32 r, mr1 = 0;
DBG(dev, "configure" NL);
- if (emac_reset(dev) < 0)
+ if (!link) {
+ out_be32(&p->mr1, in_be32(&p->mr1)
+ | EMAC_MR1_FDE | EMAC_MR1_ILE);
+ udelay(100);
+ } else if (emac_reset(dev) < 0)
return -ETIMEDOUT;
if (emac_has_feature(dev, EMAC_FTR_HAS_TAH))
tah_reset(dev->tah_dev);
- DBG(dev, " duplex = %d, pause = %d, asym_pause = %d\n",
- dev->phy.duplex, dev->phy.pause, dev->phy.asym_pause);
+ DBG(dev, " link = %d duplex = %d, pause = %d, asym_pause = %d\n",
+ link, dev->phy.duplex, dev->phy.pause, dev->phy.asym_pause);
/* Default fifo sizes */
tx_size = dev->tx_fifo_size;
rx_size = dev->rx_fifo_size;
+ /* No link, force loopback */
+ if (!link)
+ mr1 = EMAC_MR1_FDE | EMAC_MR1_ILE;
+
/* Check for full duplex */
- if (dev->phy.duplex == DUPLEX_FULL)
+ else if (dev->phy.duplex == DUPLEX_FULL)
mr1 |= EMAC_MR1_FDE | EMAC_MR1_MWSW_001;
/* Adjust fifo sizes, mr1 and timeouts based on link speed */
@@ -1165,9 +1173,9 @@ static void emac_link_timer(struct work_
link_poll_interval = PHY_POLL_LINK_ON;
} else {
if (netif_carrier_ok(dev->ndev)) {
- emac_reinitialize(dev);
netif_carrier_off(dev->ndev);
netif_tx_disable(dev->ndev);
+ emac_reinitialize(dev);
emac_print_link_status(dev);
}
link_poll_interval = PHY_POLL_LINK_OFF;
^ permalink raw reply
* [PATCH 3/11] ibm_newemac: Fix ZMII refcounting bug
From: Benjamin Herrenschmidt @ 2007-12-05 0:14 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
When using ZMII for MDIO only (such as 440GX with RGMII for data and ZMII for
MDIO), the ZMII code would fail to properly refcount, thus triggering a
BUG_ON().
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Stefan Roese <sr@denx.de>
---
drivers/net/ibm_newemac/zmii.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
Index: linux-work/drivers/net/ibm_newemac/zmii.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/zmii.c 2007-11-08 15:45:32.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/zmii.c 2007-11-08 15:46:21.000000000 +1100
@@ -83,12 +83,14 @@ int __devinit zmii_attach(struct of_devi
ZMII_DBG(dev, "init(%d, %d)" NL, input, *mode);
- if (!zmii_valid_mode(*mode))
+ if (!zmii_valid_mode(*mode)) {
/* Probably an EMAC connected to RGMII,
* but it still may need ZMII for MDIO so
* we don't fail here.
*/
+ dev->users++;
return 0;
+ }
mutex_lock(&dev->lock);
^ permalink raw reply
* [PATCH 2/11] ibm_newemac: Add ET1011c PHY support
From: Benjamin Herrenschmidt @ 2007-12-05 0:14 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
From: Stefan Roese <sr@denx.de>
This adds support for the Agere ET1011c PHY as found on the AMCC Taishan
board.
Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/net/ibm_newemac/phy.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
Index: linux-work/drivers/net/ibm_newemac/phy.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/phy.c 2007-12-03 11:58:16.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/phy.c 2007-12-03 11:59:53.000000000 +1100
@@ -327,6 +327,42 @@ static int m88e1111_init(struct mii_phy
return 0;
}
+static int et1011c_init(struct mii_phy *phy)
+{
+ u16 reg_short;
+
+ reg_short = (u16)(phy_read(phy, 0x16));
+ reg_short &= ~(0x7);
+ reg_short |= 0x6; /* RGMII Trace Delay*/
+ phy_write(phy, 0x16, reg_short);
+
+ reg_short = (u16)(phy_read(phy, 0x17));
+ reg_short &= ~(0x40);
+ phy_write(phy, 0x17, reg_short);
+
+ phy_write(phy, 0x1c, 0x74f0);
+ return 0;
+}
+
+static struct mii_phy_ops et1011c_phy_ops = {
+ .init = et1011c_init,
+ .setup_aneg = genmii_setup_aneg,
+ .setup_forced = genmii_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = genmii_read_link
+};
+
+static struct mii_phy_def et1011c_phy_def = {
+ .phy_id = 0x0282f000,
+ .phy_id_mask = 0x0fffff00,
+ .name = "ET1011C Gigabit Ethernet",
+ .ops = &et1011c_phy_ops
+};
+
+
+
+
+
static struct mii_phy_ops m88e1111_phy_ops = {
.init = m88e1111_init,
.setup_aneg = genmii_setup_aneg,
@@ -344,6 +380,7 @@ static struct mii_phy_def m88e1111_phy_d
};
static struct mii_phy_def *mii_phy_table[] = {
+ &et1011c_phy_def,
&cis8201_phy_def,
&bcm5248_phy_def,
&m88e1111_phy_def,
^ permalink raw reply
* [PATCH 1/11] ibm_newemac: Add BCM5248 and Marvell 88E1111 PHY support
From: Benjamin Herrenschmidt @ 2007-12-05 0:14 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
From: Stefan Roese <sr@denx.de>
This patch adds BCM5248 and Marvell 88E1111 PHY support to NEW EMAC driver.
These PHY chips are used on PowerPC 440EPx boards.
The PHY code is based on the previous work by Stefan Roese <sr@denx.de>
Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/net/ibm_newemac/phy.c | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
Index: linux-work/drivers/net/ibm_newemac/phy.c
===================================================================
--- linux-work.orig/drivers/net/ibm_newemac/phy.c 2007-12-03 11:50:26.000000000 +1100
+++ linux-work/drivers/net/ibm_newemac/phy.c 2007-12-03 11:58:16.000000000 +1100
@@ -306,8 +306,47 @@ static struct mii_phy_def cis8201_phy_de
.ops = &cis8201_phy_ops
};
+static struct mii_phy_def bcm5248_phy_def = {
+
+ .phy_id = 0x0143bc00,
+ .phy_id_mask = 0x0ffffff0,
+ .name = "BCM5248 10/100 SMII Ethernet",
+ .ops = &generic_phy_ops
+};
+
+static int m88e1111_init(struct mii_phy *phy)
+{
+ pr_debug("%s: Marvell 88E1111 Ethernet\n", __FUNCTION__);
+ phy_write(phy, 0x14, 0x0ce3);
+ phy_write(phy, 0x18, 0x4101);
+ phy_write(phy, 0x09, 0x0e00);
+ phy_write(phy, 0x04, 0x01e1);
+ phy_write(phy, 0x00, 0x9140);
+ phy_write(phy, 0x00, 0x1140);
+
+ return 0;
+}
+
+static struct mii_phy_ops m88e1111_phy_ops = {
+ .init = m88e1111_init,
+ .setup_aneg = genmii_setup_aneg,
+ .setup_forced = genmii_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = genmii_read_link
+};
+
+static struct mii_phy_def m88e1111_phy_def = {
+
+ .phy_id = 0x01410CC0,
+ .phy_id_mask = 0x0ffffff0,
+ .name = "Marvell 88E1111 Ethernet",
+ .ops = &m88e1111_phy_ops,
+};
+
static struct mii_phy_def *mii_phy_table[] = {
&cis8201_phy_def,
+ &bcm5248_phy_def,
+ &m88e1111_phy_def,
&genmii_phy_def,
NULL
};
^ permalink raw reply
* Re: [PATCH 5/7] powerpc: Replace ppc_md.power_off with pm_power_off
From: Mark A. Greer @ 2007-12-05 0:07 UTC (permalink / raw)
To: Grant Likely; +Cc: Paul Mackerras, linuxppc-dev
In-Reply-To: <fa686aa40712041205o39ba4e3epcbc008ea47bd83cc@mail.gmail.com>
On Tue, Dec 04, 2007 at 01:05:46PM -0700, Grant Likely wrote:
> On 12/4/07, Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> >
> > On Tue, 2007-12-04 at 11:01 -0700, Mark A. Greer wrote:
> > > On Tue, Dec 04, 2007 at 06:23:09PM +1100, Benjamin Herrenschmidt wrote:
> > > >
> > > > On Mon, 2007-12-03 at 22:48 -0700, Mark A. Greer wrote:
> > > > > From: Mark A. Greer <mgreer@mvista.com>
> > > > >
> > > > > The ppc_md.power_off hook performs the same function that the
> > > > > pm_power_off hook is supposed to. However, it is powerpc-specific
> > > > > and prevents kernel drivers (e.g., IPMI) from changing how a platform
> > > > > is powered off. So, get rid of ppc_md.power_off and replace it with
> > > > > pm_power_off.
> > > >
> > > > I'm less happy with that one... probably aesthetics :-)
> > > >
> > > > Can't we just have the generic code call pm_power_off and ppc_md and
> > > > which ever powers the machine off wins ?
> > >
> > > Yes, that would be easy to do. Seems like duplication though.
> > > If you are sure you're okay with the duplication, I'll do that.
> >
> > Let's ask Paulus what he thinks.
>
> We could simply have the setup code copy the ppc_md.power_off pointer
> into pm_power_off; that we retain the nice assignment in
> define_machine(), but eliminate the duplicated calls.
Hmm, yeah, that would look nice--nicer than what I have. The only
issue I have with it is that we still have duplication and potential
for reassigning the wrong one (e.g., reassigning ppc_md.power_off instead
of pm_power_off in maple/setup.c:maple_use_rtas_reboot_and_halt_if_present()).
We could call both in machine_power_off but that's messy too (IMHO).
Paul, do you have an opinion?
Mark
^ permalink raw reply
* Re: [PATCH] [XILINX][HWICAP] Xilinx Internal Configuration Access Port device driver.
From: Grant Likely @ 2007-12-05 0:05 UTC (permalink / raw)
To: Stephen Neuendorffer; +Cc: linuxppc-dev
In-Reply-To: <20071204235725.61AD6A08071@mail81-dub.bigfish.com>
On 12/4/07, Stephen Neuendorffer <stephen.neuendorffer@xilinx.com> wrote:
> Supports static platform_device and static device tree configuration.
> This is a standalone driver that does not depend on EDK generated
> files. However, it is also somewhat different in functionality from
> the standard EDK driver.
>
> 1) The EDK driver doesn't support readback, which this driver does.
> 2) The EDK driver supports fine granularity reading and writing, which
> this driver does not. The fine granularity support is heavily
> architecture independent, which makes it difficult to make the driver
> forward compatible. The fine granularity support is also complex and
> probably better handled in user space anyway.
>
> Signed-off-by: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com>
> ---
>
> Grant,
>
> No comments last time... It would be nice if this merged with 2.6.25, I think.
Sorry Steve, I must have missed it. I'll review and comment.
Cheers,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply
* [PATCH] [XILINX][HWICAP] Xilinx Internal Configuration Access Port device driver.
From: Stephen Neuendorffer @ 2007-12-04 23:57 UTC (permalink / raw)
To: grant.likely, linuxppc-dev
Supports static platform_device and static device tree configuration.
This is a standalone driver that does not depend on EDK generated
files. However, it is also somewhat different in functionality from
the standard EDK driver.
1) The EDK driver doesn't support readback, which this driver does.
2) The EDK driver supports fine granularity reading and writing, which
this driver does not. The fine granularity support is heavily
architecture independent, which makes it difficult to make the driver
forward compatible. The fine granularity support is also complex and
probably better handled in user space anyway.
Signed-off-by: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com>
---
Grant,
No comments last time... It would be nice if this merged with 2.6.25, I think.
Steve
drivers/char/Kconfig | 5 +
drivers/char/Makefile | 1 +
drivers/char/xilinx_hwicap/Makefile | 7 +
drivers/char/xilinx_hwicap/xhwicap_srp.c | 414 ++++++++++++++++++++
drivers/char/xilinx_hwicap/xilinx_hwicap.c | 565 ++++++++++++++++++++++++++++
drivers/char/xilinx_hwicap/xilinx_hwicap.h | 539 ++++++++++++++++++++++++++
6 files changed, 1531 insertions(+), 0 deletions(-)
create mode 100644 drivers/char/xilinx_hwicap/Makefile
create mode 100644 drivers/char/xilinx_hwicap/xhwicap_srp.c
create mode 100644 drivers/char/xilinx_hwicap/xilinx_hwicap.c
create mode 100644 drivers/char/xilinx_hwicap/xilinx_hwicap.h
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index bf18d75..72295cc 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -573,6 +573,11 @@ config HVC_DRIVER
It will automatically be selected if one of the back-end console drivers
is selected.
+config XILINX_HWICAP
+ tristate "Xilinx OPB HWICAP Support"
+ depends on XILINX_VIRTEX
+ help
+ This option enables support for Xilinx Internal Configuration Access Port (ICAP) driver.
config HVC_CONSOLE
bool "pSeries Hypervisor Virtual Console support"
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 07304d5..8cfcbb0 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_EFI_RTC) += efirtc.o
obj-$(CONFIG_SGI_DS1286) += ds1286.o
obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
obj-$(CONFIG_DS1302) += ds1302.o
+obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap/
ifeq ($(CONFIG_GENERIC_NVRAM),y)
obj-$(CONFIG_NVRAM) += generic_nvram.o
else
diff --git a/drivers/char/xilinx_hwicap/Makefile b/drivers/char/xilinx_hwicap/Makefile
new file mode 100644
index 0000000..818f4e1
--- /dev/null
+++ b/drivers/char/xilinx_hwicap/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Xilinx OPB hwicap driver
+#
+
+obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap_m.o
+
+xilinx_hwicap_m-y := xilinx_hwicap.o xhwicap_srp.o
diff --git a/drivers/char/xilinx_hwicap/xhwicap_srp.c b/drivers/char/xilinx_hwicap/xhwicap_srp.c
new file mode 100644
index 0000000..388eefe
--- /dev/null
+++ b/drivers/char/xilinx_hwicap/xhwicap_srp.c
@@ -0,0 +1,414 @@
+/*****************************************************************************
+ *
+ * Author: Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
+ * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
+ * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
+ * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
+ * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
+ * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
+ * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
+ * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
+ * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
+ * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
+ * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
+ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * Xilinx products are not intended for use in life support appliances,
+ * devices, or systems. Use in such applications is expressly prohibited.
+ *
+ * (c) Copyright 2003-2007 Xilinx Inc.
+ * All rights reserved.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *****************************************************************************/
+
+#include "xilinx_hwicap.h"
+
+#define XHI_BUFFER_START 0
+
+/****************************************************************************/
+/**
+ *
+ * Stores data in the storage buffer at the specified address.
+ *
+ * @param InstancePtr - a pointer to the XHwIcap instance to be worked on.
+ *
+ * @param Address - bram word address
+ *
+ * @param Data - data to be stored at address
+ *
+ * @return None.
+ *
+ * @note None.
+ *
+*****************************************************************************/
+void XHwIcap_StorageBufferWrite(struct xhwicap_drvdata *InstancePtr,
+ u32 Address, u32 Data)
+{
+ /* Write data to storage buffer. */
+ XHwIcap_mSetBram(InstancePtr->baseAddress, Address, Data);
+}
+
+/****************************************************************************/
+/**
+ *
+ * Read data from the specified address in the storage buffer..
+ *
+ * @param InstancePtr - a pointer to the XHwIcap instance to be worked on.
+ *
+ * @param Address - bram word address
+ *
+ * @return Data.
+ *
+ * @note None.
+ *
+*****************************************************************************/
+u32 XHwIcap_StorageBufferRead(struct xhwicap_drvdata *InstancePtr, u32 Address)
+{
+ u32 Data;
+
+ /* Read data from address. Multiply Address by 4 since 4 bytes per
+ * word.*/
+ Data = XHwIcap_mGetBram(InstancePtr->baseAddress, Address);
+ return Data;
+
+}
+
+/****************************************************************************/
+/**
+ *
+ * Reads bytes from the device (ICAP) and puts it in the storage buffer.
+ *
+ * @param InstancePtr - a pointer to the XHwIcap instance to be worked on.
+ *
+ * @param Offset - The storage buffer start address.
+ *
+ * @param NumInts - The number of words (32 bit) to read from the
+ * device (ICAP).
+ *
+ *@return int - 0 or -EBUSY or -EINVAL
+ *
+ * @note None.
+ *
+*****************************************************************************/
+int XHwIcap_DeviceRead(struct xhwicap_drvdata *InstancePtr, u32 Offset,
+ u32 NumInts)
+{
+
+ s32 Retries = 0;
+
+ if (XHwIcap_mGetDoneReg(InstancePtr->baseAddress) == XHI_NOT_FINISHED) {
+ return -EBUSY;
+ }
+
+ if ((Offset + NumInts) <= XHI_MAX_BUFFER_INTS) {
+ /* setSize NumInts*4 to get bytes. */
+ XHwIcap_mSetSizeReg((InstancePtr->baseAddress), (NumInts << 2));
+ XHwIcap_mSetOffsetReg((InstancePtr->baseAddress), Offset);
+ XHwIcap_mSetRncReg((InstancePtr->baseAddress), XHI_READBACK);
+
+ while (XHwIcap_mGetDoneReg(InstancePtr->baseAddress) ==
+ XHI_NOT_FINISHED) {
+ Retries++;
+ if (Retries > XHI_MAX_RETRIES) {
+ return -EBUSY;
+ }
+ }
+ } else {
+ return -EINVAL;
+ }
+ return 0;
+
+};
+
+/****************************************************************************/
+/**
+ *
+ * Writes bytes from the storage buffer and puts it in the device (ICAP).
+ *
+ * @param InstancePtr - a pointer to the XHwIcap instance to be worked on.
+ *
+ * @param Offset - The storage buffer start address.
+ *
+ * @param NumInts - The number of words (32 bit) to read from the
+ * device (ICAP).
+ *
+ *@return int - 0 or -EBUSY or -EINVAL
+ *
+ * @note None.
+ *
+*****************************************************************************/
+int XHwIcap_DeviceWrite(struct xhwicap_drvdata *InstancePtr, u32 Offset,
+ u32 NumInts)
+{
+
+ s32 Retries = 0;
+
+ if (XHwIcap_mGetDoneReg(InstancePtr->baseAddress) == XHI_NOT_FINISHED) {
+ return -EBUSY;
+ }
+
+ if ((Offset + NumInts) <= XHI_MAX_BUFFER_INTS) {
+ /* setSize NumInts*4 to get bytes. */
+ XHwIcap_mSetSizeReg((InstancePtr->baseAddress), NumInts << 2);
+ XHwIcap_mSetOffsetReg((InstancePtr->baseAddress), Offset);
+ XHwIcap_mSetRncReg((InstancePtr->baseAddress), XHI_CONFIGURE);
+
+ while (XHwIcap_mGetDoneReg(InstancePtr->baseAddress) ==
+ XHI_NOT_FINISHED) {
+ Retries++;
+ if (Retries > XHI_MAX_RETRIES) {
+ return -EBUSY;
+ }
+ }
+ } else {
+ return -EINVAL;
+ }
+ return 0;
+
+};
+
+/****************************************************************************/
+/**
+ *
+ * Sends a DESYNC command to the ICAP port.
+ *
+ * @param InstancePtr - a pointer to the XHwIcap instance to be worked on.
+ *
+ *@return int - 0 or -EBUSY or -EINVAL
+ *
+ * @note None.
+ *
+*****************************************************************************/
+int XHwIcap_CommandDesync(struct xhwicap_drvdata *InstancePtr)
+{
+ int status;
+
+ XHwIcap_StorageBufferWrite(InstancePtr, 0,
+ (XHwIcap_Type1Write(XHI_CMD) | 1));
+ XHwIcap_StorageBufferWrite(InstancePtr, 1, XHI_CMD_DESYNCH);
+ XHwIcap_StorageBufferWrite(InstancePtr, 2, XHI_NOOP_PACKET);
+ XHwIcap_StorageBufferWrite(InstancePtr, 3, XHI_NOOP_PACKET);
+
+ /* send four words */
+ status = XHwIcap_DeviceWrite(InstancePtr, 0, 4);
+ if (status) {
+ return status;
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+/**
+ *
+ * Sends a CAPTURE command to the ICAP port. This command caputres all
+ * of the flip flop states so they will be available during readback.
+ * One can use this command instead of enabling the CAPTURE block in the
+ * design.
+ *
+ * @param InstancePtr - a pointer to the XHwIcap instance to be worked on.
+ *
+ * @return int - 0 or -EBUSY or -EINVAL
+ *
+ * @note None.
+ *
+*****************************************************************************/
+int XHwIcap_CommandCapture(struct xhwicap_drvdata *InstancePtr)
+{
+ int status;
+
+ /* DUMMY and SYNC */
+ XHwIcap_StorageBufferWrite(InstancePtr, 0, XHI_DUMMY_PACKET);
+ XHwIcap_StorageBufferWrite(InstancePtr, 1, XHI_SYNC_PACKET);
+ XHwIcap_StorageBufferWrite(InstancePtr, 2,
+ (XHwIcap_Type1Write(XHI_CMD) | 1));
+ XHwIcap_StorageBufferWrite(InstancePtr, 3, XHI_CMD_GCAPTURE);
+ XHwIcap_StorageBufferWrite(InstancePtr, 4, XHI_DUMMY_PACKET);
+ XHwIcap_StorageBufferWrite(InstancePtr, 5, XHI_DUMMY_PACKET);
+
+ /* send six words */
+ status = XHwIcap_DeviceWrite(InstancePtr, 0, 6);
+ if (status) { /* send six words */
+ return status;
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+/**
+ *
+ * This function returns the value of the specified configuration
+ * register.
+ *
+ * @param InstancePtr - a pointer to the XHwIcap instance to be worked
+ * on.
+ *
+ * @param ConfigReg - A constant which represents the configuration
+ * register value to be returned. Constants specified in xhwicap_i.h. Examples:
+ * XHI_IDCODE, XHI_FLR.
+ *
+ * @return The value of the specified configuration register.
+ *
+ *
+*****************************************************************************/
+
+u32 XHwIcap_GetConfigReg(struct xhwicap_drvdata *InstancePtr, u32 ConfigReg)
+{
+ u32 Packet;
+ int status;
+
+ /* Write bitstream to bram */
+ Packet = XHwIcap_Type1Read(ConfigReg) | 1;
+ XHwIcap_StorageBufferWrite(InstancePtr, 0, XHI_DUMMY_PACKET);
+ XHwIcap_StorageBufferWrite(InstancePtr, 1, XHI_SYNC_PACKET);
+ XHwIcap_StorageBufferWrite(InstancePtr, 2, Packet);
+ XHwIcap_StorageBufferWrite(InstancePtr, 3, XHI_NOOP_PACKET);
+ XHwIcap_StorageBufferWrite(InstancePtr, 4, XHI_NOOP_PACKET);
+
+ /* Transfer Bitstream from Bram to ICAP */
+ status = XHwIcap_DeviceWrite(InstancePtr, 0, 5);
+ if (status) {
+ return status;
+ }
+
+ /* Now readback one word into bram position
+ * XHI_EX_BITSTREAM_LENGTH*/
+ status = XHwIcap_DeviceRead(InstancePtr, 5, 1);
+ if (status) {
+ return status;
+ }
+
+ /* Return the Register value */
+ return XHwIcap_StorageBufferRead(InstancePtr, 5);
+}
+
+/****************************************************************************
+ *
+ * Loads a partial bitstream from system memory.
+ *
+ * @param InstancePtr - a pointer to the XHwIcap instance to be worked on.
+ *
+ * @param Data - Address of the data representing the partial bitstream
+ *
+ * @param Size - the size of the partial bitstream in 32 bit words.
+ *
+ * @return 0, -EFBIG or -EINVAL.
+ *
+ * @note None.
+ *
+*****************************************************************************/
+int XHwIcap_SetConfiguration(struct xhwicap_drvdata *InstancePtr, u32 *Data,
+ u32 Size)
+{
+ int status;
+ s32 BufferCount = 0;
+ s32 NumWrites = 0;
+ bool Dirty = 0;
+ u32 I;
+
+ /* Loop through all the data */
+ for (I = 0, BufferCount = 0; I < Size; I++) {
+
+ /* Copy data to bram */
+ XHwIcap_StorageBufferWrite(InstancePtr, BufferCount, Data[I]);
+ Dirty = 1;
+
+ if (BufferCount == XHI_MAX_BUFFER_INTS - 1) {
+ /* Write data to ICAP */
+ status = XHwIcap_DeviceWrite(InstancePtr, XHI_BUFFER_START,
+ XHI_MAX_BUFFER_INTS);
+ if (status != 0) {
+ /* abort. */
+ XHwIcap_mReset(InstancePtr->baseAddress); return status;
+ }
+
+ BufferCount = 0;
+ NumWrites++;
+ Dirty = 0;
+ } else {
+ BufferCount++;
+ }
+ }
+
+ /* Write unwritten data to ICAP */
+ if (Dirty) {
+ /* Write data to ICAP */
+ status = XHwIcap_DeviceWrite(InstancePtr, XHI_BUFFER_START,
+ BufferCount);
+ if (status != 0) {
+ /* abort. */
+ XHwIcap_mReset(InstancePtr->baseAddress);
+ }
+ return status;
+ }
+
+ return 0;
+};
+
+/****************************************************************************
+ *
+ * Reads Configuration Data from the device.
+ *
+ * @param InstancePtr - a pointer to the XHwIcap instance to be worked on.
+ *
+ * @param Data - Address of the data representing the partial bitstream
+ *
+ * @param Size - the size of the partial bitstream in 32 bit words.
+ *
+ * @return 0, -EFBIG or -EINVAL.
+ *
+ * @note None.
+ *
+*****************************************************************************/
+int XHwIcap_GetConfiguration(struct xhwicap_drvdata *InstancePtr, u32 *Data,
+ u32 Size)
+{
+ int status;
+ s32 BufferCount = 0;
+ s32 NumReads = 0;
+ u32 I;
+
+ /* Loop through all the data */
+ for (I = 0, BufferCount = XHI_MAX_BUFFER_INTS; I < Size; I++) {
+ if (BufferCount == XHI_MAX_BUFFER_INTS) {
+ u32 intsRemaining = Size - I;
+ u32 intsToRead =
+ intsRemaining <
+ XHI_MAX_BUFFER_INTS ? intsRemaining :
+ XHI_MAX_BUFFER_INTS;
+
+ /* Read data from ICAP */
+
+ status =
+ XHwIcap_DeviceRead(InstancePtr, XHI_BUFFER_START,
+ intsToRead);
+ if (status != 0) {
+ /* abort. */
+ XHwIcap_mReset(InstancePtr->baseAddress);
+ return status;
+ }
+
+ BufferCount = 0;
+ NumReads++;
+ }
+
+ /* Copy data from bram */
+ Data[I] = XHwIcap_StorageBufferRead(InstancePtr, BufferCount);
+ BufferCount++;
+ }
+
+ return 0;
+};
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
new file mode 100644
index 0000000..d42538e
--- /dev/null
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -0,0 +1,565 @@
+/*****************************************************************************
+ *
+ * Author: Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
+ * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
+ * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
+ * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
+ * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
+ * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
+ * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
+ * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
+ * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
+ * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
+ * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
+ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * Xilinx products are not intended for use in life support appliances,
+ * devices, or systems. Use in such applications is expressly prohibited.
+ *
+ * (c) Copyright 2002 Xilinx Inc., Systems Engineering Group
+ * (c) Copyright 2004 Xilinx Inc., Systems Engineering Group
+ * (c) Copyright 2007 Xilinx Inc.
+ * All rights reserved.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *****************************************************************************/
+
+/*
+ * xilinx_hwicap.c
+ *
+ * This is the code behind /dev/xilinx_icap/'x' -- it allows a user-space
+ * application to use the Xilinx ICAP subsystem.
+ *
+ * A /dev/xilinx_icap/'x' device node represents an arbitrary device
+ * on port 'x'. The following operations are possible:
+ *
+ * open do nothing, set up default IEEE 1284 protocol to be COMPAT
+ * release release port and unregister device (if necessary)
+ * write Write a bitstream to the configuration processor.
+ * read Read a data stream from the configuration processor.
+ *
+ * Note that in order to use the read interface, it is first necessary
+ * to write a request packet to the write interface. i.e., it is not
+ * possible to simply readback the bitstream (or any configuration
+ * bits) from a device without specifically requesting them first.
+ * The code to craft such packets is intended to be part of the
+ * user-space application code that uses this device. The simplest
+ * way to use this interface is simply:
+ *
+ * cp foo.bit /dev/xilinx_icap
+ *
+ * Note that unless foo.bit is an appropriately constructed partial
+ * bitstream, this has a high likelyhood of overwriting the design
+ * currently programmed in the FPGA.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/fcntl.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <linux/sysctl.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#ifdef CONFIG_OF
+/* For open firmware. */
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#endif
+
+#include "xilinx_hwicap.h"
+
+#define DRIVER_NAME "xilinx_icap"
+
+#define XHWICAP_REGS (0x10000)
+
+/* dynamically allocate device number */
+static int xhwicap_major = 0;
+static int xhwicap_minor = 0;
+static int xhwicap_no_minors = 4;
+module_param(xhwicap_major, int, S_IRUGO);
+module_param(xhwicap_minor, int, S_IRUGO);
+module_param(xhwicap_no_minors, int, S_IRUGO);
+
+static struct class *icap_class;
+
+int xhwicap_initialize_xhwicap(struct xhwicap_drvdata *drvdata)
+{
+
+ u32 DeviceIdCode;
+ u32 Packet;
+ int Status;
+
+ dev_dbg(drvdata->dev, "Reset...\n");
+
+ /* Abort any current transaction, to make sure we have the ICAP in */
+ /* a good state. */
+ XHwIcap_mReset(drvdata->baseAddress);
+
+ /* Read the IDCODE from ICAP if specified. */
+ {
+ dev_dbg(drvdata->dev, "Reading IDCODE...\n");
+
+ /* Write bitstream to bram */
+ Packet = XHwIcap_Type1Read(XHI_IDCODE) | 1;
+ XHwIcap_StorageBufferWrite(drvdata, 0, XHI_DUMMY_PACKET);
+ XHwIcap_StorageBufferWrite(drvdata, 1, XHI_SYNC_PACKET);
+ XHwIcap_StorageBufferWrite(drvdata, 2, Packet);
+ XHwIcap_StorageBufferWrite(drvdata, 3, XHI_NOOP_PACKET);
+ XHwIcap_StorageBufferWrite(drvdata, 4, XHI_NOOP_PACKET);
+
+ /* Transfer Bitstream from Bram to ICAP */
+ Status = XHwIcap_DeviceWrite(drvdata, 0, 5);
+ if (Status) {
+ return Status;
+ }
+
+ /* Now readback one word into bram position
+ * XHI_EX_BITSTREAM_LENGTH*/
+ Status = XHwIcap_DeviceRead(drvdata, 5, 1);
+ if (Status) {
+ return Status;
+ }
+
+ /* Return the Register value */
+ DeviceIdCode = XHwIcap_StorageBufferRead(drvdata, 5);
+
+ /* Mask out the version section of the DeviceIdCode */
+ DeviceIdCode = DeviceIdCode & 0x0FFFFFFF;
+
+ dev_dbg(drvdata->dev, "Desync...\n");
+ Status = XHwIcap_CommandDesync(drvdata);
+
+ if (Status) {
+ return Status;
+ }
+ }
+
+ /* Abort any current transaction, to make sure we have the ICAP in */
+ /* a good state. */
+ XHwIcap_mReset(drvdata->baseAddress);
+
+ dev_info(drvdata->dev, "Device IDCODE = %x\n", DeviceIdCode);
+
+ return 0;
+}
+
+static ssize_t
+xhwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+ struct xhwicap_drvdata *drvdata = file->private_data;
+ ssize_t bytes_to_read = 0;
+ u32 *kbuf;
+ u32 words;
+ u32 bytes_remaining;
+ int Status;
+
+ if (drvdata->read_buffer_in_use) {
+ /* If there are leftover bytes in the buffer, just */
+ /* return them and don't try to read more from the */
+ /* ICAP device. */
+ bytes_to_read =
+ (count <
+ drvdata->read_buffer_in_use) ? count : drvdata->
+ read_buffer_in_use;
+
+ /* Return the data currently in the read buffer. */
+ if (copy_to_user(buf, drvdata->read_buffer, bytes_to_read)) {
+ return -EFAULT;
+ }
+ drvdata->read_buffer_in_use -= bytes_to_read;
+ memcpy(drvdata->read_buffer + bytes_to_read,
+ drvdata->read_buffer, 4 - bytes_to_read);
+ } else {
+ /* Get new data from the ICAP, and return was was requested. */
+ kbuf = (u32 *) get_zeroed_page(GFP_KERNEL);
+ if (!kbuf)
+ return -ENOMEM;
+
+ /* The ICAP device is only able to read complete */
+ /* words. If a number of bytes that do not correspond */
+ /* to complete words is requested, then we read enough */
+ /* words to get the required number of bytes, and then */
+ /* save the remaining bytes for the next read. */
+
+ /* Determine the number of words to read, rounding up */
+ /* if necessary. */
+ words = ((count + 3) >> 2);
+ bytes_to_read = words << 2;
+
+ if (bytes_to_read > PAGE_SIZE) {
+ bytes_to_read = PAGE_SIZE;
+ }
+ /* Ensure we only read a complete number of words. */
+ /* BUG: should be count & 3? */
+ bytes_remaining = bytes_to_read & 3;
+ bytes_to_read &= ~3;
+ words = bytes_to_read >> 2;
+
+ Status = XHwIcap_GetConfiguration(drvdata, kbuf, words);
+ /* If we didn't read correctly, then bail out. */
+ if (Status) {
+ free_page((unsigned long)kbuf);
+ return -EFAULT;
+ }
+ /* If we fail to return the data to the user, then bail out. */
+ if (copy_to_user(buf, kbuf, bytes_to_read)) {
+ free_page((unsigned long)kbuf);
+ return -EFAULT;
+ }
+ memcpy(kbuf, drvdata->read_buffer, bytes_remaining);
+ drvdata->read_buffer_in_use = bytes_remaining;
+ free_page((unsigned long)kbuf);
+ }
+ return bytes_to_read;
+}
+
+static ssize_t xhwicap_write(struct file *file, const char *buf,
+ size_t count, loff_t *ppos)
+{
+ struct xhwicap_drvdata *drvdata = file->private_data;
+ ssize_t written = 0;
+ ssize_t left = count;
+ u32 *kbuf;
+ int len;
+ int Status;
+
+ left += drvdata->write_buffer_in_use;
+
+ /* only write multiples of 4 bytes. */
+ if (left < 4)
+ return 0;
+
+ kbuf = (u32 *) __get_free_page(GFP_KERNEL);
+ if (!kbuf)
+ return -ENOMEM;
+
+ while (left > 3) {
+ /* only write multiples of 4 bytes, so there might */
+ /* be as many as 3 bytes left (at the end). */
+ len = left;
+
+ if (len > PAGE_SIZE)
+ len = PAGE_SIZE;
+ len &= ~3;
+
+ if (drvdata->write_buffer_in_use) {
+ memcpy(kbuf, drvdata->write_buffer,
+ drvdata->write_buffer_in_use);
+ if (copy_from_user
+ ((((char *)kbuf) + (drvdata->write_buffer_in_use)),
+ buf + written,
+ len - (drvdata->write_buffer_in_use))) {
+ free_page((unsigned long)kbuf);
+ return -EFAULT;
+ }
+ } else {
+ if (copy_from_user(kbuf, buf + written, len)) {
+ free_page((unsigned long)kbuf);
+ return -EFAULT;
+ }
+ }
+
+ Status = XHwIcap_SetConfiguration(drvdata, kbuf, len >> 2);
+
+ if (Status) {
+ free_page((unsigned long)kbuf);
+ return -EFAULT;
+ }
+ if (drvdata->write_buffer_in_use) {
+ len -= drvdata->write_buffer_in_use;
+ left -= drvdata->write_buffer_in_use;
+ drvdata->write_buffer_in_use = 0;
+ }
+ written += len;
+ left -= len;
+ }
+ if ((left > 0) && (left < 4)) {
+ if (!copy_from_user(drvdata->write_buffer, buf + written, left)) {
+ drvdata->write_buffer_in_use = left;
+ written += left;
+ left = 0;
+ }
+ }
+
+ free_page((unsigned long)kbuf);
+ return written;
+}
+
+static int xhwicap_open(struct inode *inode, struct file *file)
+{
+ struct xhwicap_drvdata *drvdata;
+ int status;
+
+ drvdata = container_of(inode->i_cdev, struct xhwicap_drvdata, cdev);
+
+ status = xhwicap_initialize_xhwicap(drvdata);
+ if (status) {
+ dev_err(drvdata->dev, "Failed to open file");
+ return -status;
+ }
+
+ drvdata->flags = 0;
+ file->private_data = drvdata;
+ drvdata->write_buffer_in_use = 0;
+ drvdata->read_buffer_in_use = 0;
+
+ return 0;
+}
+
+static int xhwicap_release(struct inode *inode, struct file *file)
+{
+ struct xhwicap_drvdata *drvdata = file->private_data;
+ int i;
+ int Status;
+
+ if (drvdata->write_buffer_in_use) {
+ /* Flush write buffer. */
+ for (i = drvdata->write_buffer_in_use; i < 4; i++) {
+ drvdata->write_buffer[i] = 0;
+ }
+ Status =
+ XHwIcap_SetConfiguration(drvdata,
+ (u32 *) drvdata->write_buffer, 1);
+ if (Status) {
+ return Status;
+ }
+ }
+
+ Status = XHwIcap_CommandDesync(drvdata);
+ if (Status) {
+ return Status;
+ }
+
+ return 0;
+}
+
+static struct file_operations xhwicap_fops = {
+ .owner = THIS_MODULE,
+ .write = xhwicap_write,
+ .read = xhwicap_read,
+ .open = xhwicap_open,
+ .release = xhwicap_release,
+};
+
+static int __init xhwicap_drv_probe(struct device *dev)
+{
+ dev_t devt;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct xhwicap_drvdata *drvdata = NULL;
+ struct resource *regs_res;
+ int retval = 0;
+
+ if (!dev) {
+ return -EINVAL;
+ }
+
+ dev_info(dev, "Xilinx icap port driver\n");
+
+ devt = MKDEV(xhwicap_major, xhwicap_minor + pdev->id);
+
+ drvdata = kmalloc(sizeof(struct xhwicap_drvdata), GFP_KERNEL);
+ if (!drvdata) {
+ dev_err(dev, "Couldn't allocate device private record\n");
+ return -ENOMEM;
+ }
+ memset((void *)drvdata, 0, sizeof(struct xhwicap_drvdata));
+ dev_set_drvdata(dev, (void *)drvdata);
+
+ /* Map the control registers in */
+ regs_res = platform_get_resource(to_platform_device(dev),
+ IORESOURCE_MEM, 0);
+ if (!regs_res) {
+ dev_err(dev, "Couldn't get registers resource\n");
+ retval = -EFAULT;
+ goto failed1;
+ }
+
+ drvdata->mem_start = regs_res->start;
+ drvdata->mem_end = regs_res->end;
+ drvdata->mem_size = regs_res->end - regs_res->start + 1;
+
+ if (drvdata->mem_size < XHWICAP_REGS) {
+ dev_err(dev, "Couldn't get registers resource\n");
+ retval = -EFAULT;
+ goto failed1;
+ }
+
+ if (!request_mem_region(drvdata->mem_start, drvdata->mem_size, DRIVER_NAME)) {
+ dev_err(dev, "Couldn't lock memory region at %p\n",
+ (void *)regs_res->start);
+ retval = -EBUSY;
+ goto failed1;
+ }
+
+ drvdata->devt = devt;
+ drvdata->dev = dev;
+ drvdata->baseAddress = ioremap(drvdata->mem_start, drvdata->mem_size);
+ if (!drvdata->baseAddress) {
+ dev_err(dev, "ioremap() failed\n");
+ goto failed2;
+ }
+
+ dev_info(dev, "ioremap %lx to %p with size %x\n",
+ (unsigned long int)drvdata->mem_start,
+ drvdata->baseAddress, drvdata->mem_size);
+
+ cdev_init(&drvdata->cdev, &xhwicap_fops);
+ drvdata->cdev.owner = THIS_MODULE;
+ retval = cdev_add(&drvdata->cdev, devt, 1);
+ if (retval) {
+ dev_err(dev, "cdev_add() failed\n");
+ goto failed3;
+ }
+ /* devfs_mk_cdev(devt, S_IFCHR|S_IRUGO|S_IWUGO, DRIVER_NAME); */
+ class_device_create(icap_class, NULL, devt, NULL, DRIVER_NAME);
+ return 0; /* success */
+
+ failed3:
+ iounmap(drvdata->baseAddress);
+
+ failed2:
+ release_mem_region(regs_res->start, drvdata->mem_size);
+
+ failed1:
+ kfree(drvdata);
+
+ return retval;
+}
+
+static int __exit xhwicap_drv_remove(struct device *dev)
+{
+ struct xhwicap_drvdata *drvdata;
+
+ if (!dev)
+ return -EINVAL;
+
+ drvdata = (struct xhwicap_drvdata *)dev_get_drvdata(dev);
+
+ class_device_destroy(icap_class, drvdata->devt);
+ cdev_del(&drvdata->cdev);
+ iounmap(drvdata->baseAddress);
+ release_mem_region(drvdata->mem_start, drvdata->mem_size);
+ kfree(drvdata);
+ dev_set_drvdata(dev, NULL);
+
+ return 0; /* success */
+}
+
+static struct device_driver xhwicap_module_driver = {
+ .name = DRIVER_NAME,
+ .bus = &platform_bus_type,
+
+ .probe = xhwicap_drv_probe,
+ .remove = xhwicap_drv_remove,
+};
+
+static int __init xhwicap_module_init(void)
+{
+ dev_t devt;
+ int retval;
+
+ icap_class = class_create(THIS_MODULE, "xilinx_config");
+
+ if (xhwicap_major) {
+ devt = MKDEV(xhwicap_major, xhwicap_minor);
+ retval = register_chrdev_region(devt, xhwicap_no_minors,
+ DRIVER_NAME);
+ } else {
+ retval =
+ alloc_chrdev_region(&devt, xhwicap_minor, xhwicap_no_minors,
+ DRIVER_NAME);
+ xhwicap_major = MAJOR(devt);
+ }
+ if (retval < 0) {
+ xhwicap_major = 0;
+ return retval;
+ }
+
+ retval = driver_register(&xhwicap_module_driver);
+
+ if (retval) {
+ unregister_chrdev_region(devt, xhwicap_no_minors);
+ }
+
+ return retval;
+}
+
+static void __exit xhwicap_module_cleanup(void)
+{
+ dev_t devt = MKDEV(xhwicap_major, xhwicap_minor);
+
+ class_destroy(icap_class);
+
+ driver_unregister(&xhwicap_module_driver);
+
+ unregister_chrdev_region(devt, xhwicap_no_minors);
+}
+
+module_init(xhwicap_module_init);
+module_exit(xhwicap_module_cleanup);
+
+#ifdef CONFIG_OF
+
+static int __init xilinx_hwicap_of_init(void)
+{
+ struct device_node *np;
+ unsigned int i;
+ struct platform_device *pdev;
+ int ret;
+
+ for (np = NULL, i = 0;
+ (np = of_find_compatible_node(np, NULL, "xlnx,opb-hwicap")) != NULL;
+ i++) {
+ struct resource r;
+
+ memset(&r, 0, sizeof(r));
+
+ ret = of_address_to_resource(np, 0, &r);
+ if (ret)
+ goto err;
+ pdev =
+ platform_device_register_simple(DRIVER_NAME, i, &r, 1);
+
+ if (IS_ERR(pdev)) {
+ ret = PTR_ERR(pdev);
+ goto err;
+ }
+ }
+
+ return 0;
+err:
+ return ret;
+}
+
+module_init(xilinx_hwicap_of_init);
+
+#endif
+
+MODULE_AUTHOR("Xilinx, Inc; Xilinx Research Labs Group");
+MODULE_DESCRIPTION("Xilinx ICAP Port Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h
new file mode 100644
index 0000000..80e3fe0
--- /dev/null
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h
@@ -0,0 +1,539 @@
+/*****************************************************************************
+ *
+ * Author: Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
+ * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
+ * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
+ * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
+ * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
+ * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
+ * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
+ * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
+ * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
+ * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
+ * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
+ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * Xilinx products are not intended for use in life support appliances,
+ * devices, or systems. Use in such applications is expressly prohibited.
+ *
+ * (c) Copyright 2003-2007 Xilinx Inc.
+ * All rights reserved.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *****************************************************************************/
+
+#ifndef XILINX_HWICAP_H_ /* prevent circular inclusions */
+#define XILINX_HWICAP_H_ /* by using protection macros */
+
+#include <linux/types.h>
+#include <linux/cdev.h>
+#include <linux/version.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+
+struct xhwicap_drvdata {
+ u32 flags;
+ u32 write_buffer_in_use; /* Always in [0,3] */
+ u8 write_buffer[4];
+ u32 read_buffer_in_use; /* Always in [0,3] */
+ u8 read_buffer[4];
+ u32 mem_start; /* phys. address of the control registers */
+ u32 mem_end; /* phys. address of the control registers */
+ u32 mem_size;
+ void __iomem *baseAddress;/* virt. address of the control registers */
+
+ struct device *dev;
+ struct cdev cdev; /* Char device structure */
+ dev_t devt;
+};
+
+/***************************** Include Files ********************************/
+
+#define virtex2 0
+#define virtex4 1
+
+#ifdef CONFIG_XILINX_VIRTEX_4_FX
+#define XHI_FAMILY virtex4
+#else
+#define XHI_FAMILY virtex2
+#endif
+
+/************************** Constant Definitions ****************************/
+
+#define XHI_PAD_FRAMES 0x1
+
+/* Mask for calculating configuration packet headers */
+#define XHI_WORD_COUNT_MASK_TYPE_1 0x7FFUL
+#define XHI_WORD_COUNT_MASK_TYPE_2 0x1FFFFFUL
+#define XHI_TYPE_MASK 0x7
+#define XHI_REGISTER_MASK 0xF
+#define XHI_OP_MASK 0x3
+
+#define XHI_TYPE_SHIFT 29
+#define XHI_REGISTER_SHIFT 13
+#define XHI_OP_SHIFT 27
+
+#define XHI_TYPE_1 1
+#define XHI_TYPE_2 2
+#define XHI_OP_WRITE 2
+#define XHI_OP_READ 1
+
+/* Address Block Types */
+#define XHI_FAR_CLB_BLOCK 0
+#define XHI_FAR_BRAM_BLOCK 1
+#define XHI_FAR_BRAM_INT_BLOCK 2
+
+/* Addresses of the Configuration Registers */
+#define XHI_CRC 0
+#define XHI_FAR 1
+#define XHI_FDRI 2
+#define XHI_FDRO 3
+#define XHI_CMD 4
+#define XHI_CTL 5
+#define XHI_MASK 6
+#define XHI_STAT 7
+#define XHI_LOUT 8
+#define XHI_COR 9
+#define XHI_MFWR 10
+
+#if XHI_FAMILY == virtex4
+
+#define XHI_CBC 11
+#define XHI_IDCODE 12
+#define XHI_AXSS 13
+#define XHI_NUM_REGISTERS 14
+
+#else
+
+#define XHI_FLR 11
+#define XHI_KEY 12
+#define XHI_CBC 13
+#define XHI_IDCODE 14
+#define XHI_NUM_REGISTERS 15
+
+#endif
+
+/* Configuration Commands */
+#define XHI_CMD_NULL 0
+#define XHI_CMD_WCFG 1
+#define XHI_CMD_MFW 2
+#define XHI_CMD_DGHIGH 3
+#define XHI_CMD_RCFG 4
+#define XHI_CMD_START 5
+#define XHI_CMD_RCAP 6
+#define XHI_CMD_RCRC 7
+#define XHI_CMD_AGHIGH 8
+#define XHI_CMD_SWITCH 9
+#define XHI_CMD_GRESTORE 10
+#define XHI_CMD_SHUTDOWN 11
+#define XHI_CMD_GCAPTURE 12
+#define XHI_CMD_DESYNCH 13
+
+/* Packet constants */
+#define XHI_SYNC_PACKET 0xAA995566UL
+#define XHI_DUMMY_PACKET 0xFFFFFFFFUL
+#define XHI_NOOP_PACKET (XHI_TYPE_1 << XHI_TYPE_SHIFT)
+#define XHI_TYPE_2_READ ((XHI_TYPE_2 << XHI_TYPE_SHIFT) | \
+ (XHI_OP_READ << XHI_OP_SHIFT))
+
+#define XHI_TYPE_2_WRITE ((XHI_TYPE_2 << XHI_TYPE_SHIFT) | \
+ (XHI_OP_WRITE << XHI_OP_SHIFT))
+
+#define XHI_TYPE2_CNT_MASK 0x07FFFFFF
+
+#define XHI_TYPE_1_PACKET_MAX_WORDS 2047UL
+#define XHI_TYPE_1_HEADER_BYTES 4
+#define XHI_TYPE_2_HEADER_BYTES 8
+
+/* Indicates how many bytes will fit in a buffer. (1 BRAM) */
+#define XHI_MAX_BUFFER_BYTES 2048
+#define XHI_MAX_BUFFER_INTS 512
+
+/* Number of frames in different tile types */
+#if XHI_FAMILY == virtex4
+
+#define XHI_GCLK_FRAMES 3
+#define XHI_IOB_FRAMES 30
+#define XHI_DSP_FRAMES 21
+#define XHI_CLB_FRAMES 22
+#define XHI_BRAM_FRAMES 64
+#define XHI_BRAM_INT_FRAMES 20
+
+#else
+
+#define XHI_GCLK_FRAMES 4
+#define XHI_IOB_FRAMES 4
+#define XHI_IOI_FRAMES 22
+#define XHI_CLB_FRAMES 22
+#define XHI_BRAM_FRAMES 64
+#define XHI_BRAM_INT_FRAMES 22
+
+#endif
+
+/* Device Resources */
+#define CLB 0
+#define DSP 1
+#define BRAM 2
+#define BRAM_INT 3
+#define IOB 4
+#define IOI 5
+#define CLK 6
+#define MGT 7
+
+#define BLOCKTYPE0 0
+#define BLOCKTYPE1 1
+#define BLOCKTYPE2 2
+
+/* The number of words reserved for the header in the storage buffer. */
+/* MAY CHANGE FOR V4 */
+#define XHI_HEADER_BUFFER_WORDS 20
+#define XHI_HEADER_BUFFER_BYTES (XHI_HEADER_BUFFER_WORDS << 2)
+
+/* CLB major frames start at 3 for the first column (since we are using
+ * column numbers that start at 1, when the column is added to this offset,
+ * that first one will be 3 as required. */
+#define XHI_CLB_MAJOR_FRAME_OFFSET 2
+
+/* File access and error constants */
+#define XHI_DEVICE_READ_ERROR -1
+#define XHI_DEVICE_WRITE_ERROR -2
+#define XHI_BUFFER_OVERFLOW_ERROR -3
+
+#define XHI_DEVICE_READ 0x1
+#define XHI_DEVICE_WRITE 0x0
+
+/* Constants for checking transfer status */
+#define XHI_CYCLE_DONE 0
+#define XHI_CYCLE_EXECUTING 1
+
+/* Constant to use for CRC check when CRC has been disabled */
+#define XHI_DISABLED_AUTO_CRC 0x0000DEFCUL
+
+/* Major Row Offset */
+#define XHI_CLB_MAJOR_ROW_OFFSET 96+(32*XHI_HEADER_BUFFER_WORDS)-1
+
+/* Number of times to poll the done regsiter */
+#define XHI_MAX_RETRIES 1000
+
+/************************** Constant Definitions ****************************/
+
+/* XHwIcap register offsets */
+
+/* Size of transfer, read & write */
+#define XHI_SIZE_REG_OFFSET 0x800L
+/* Offset into bram, read & write */
+#define XHI_BRAM_OFFSET_REG_OFFSET 0x804L
+/* Read not Configure, direction of transfer. Write only */
+#define XHI_RNC_REG_OFFSET 0x808L
+/* Indicates transfer complete. Read only */
+#define XHI_STATUS_REG_OFFSET 0x80CL
+
+/* Constants for setting the RNC register */
+#define XHI_CONFIGURE 0x0UL
+#define XHI_READBACK 0x1UL
+
+/* Constants for the Done register */
+#define XHI_NOT_FINISHED 0x0UL
+#define XHI_FINISHED 0x1UL
+
+/**************************** Type Definitions ******************************/
+
+/***************** Macros (Inline Functions) Definitions ********************/
+
+/****************************************************************************/
+/**
+*
+* Get the contents of the size register.
+*
+* The size register holds the number of 32 bit words to transfer between
+* bram and the icap (or icap to bram).
+*
+* @param BaseAddress is the base address of the device
+*
+* @return A 32-bit value representing the contents of the size
+* register.
+*
+* @note
+*
+* u32 XHwIcap_mGetSizeReg(u32 BaseAddress);
+*
+*****************************************************************************/
+#define XHwIcap_mGetSizeReg(BaseAddress) \
+ (in_be32((u32 *)((BaseAddress) + XHI_SIZE_REG_OFFSET)))
+
+/****************************************************************************/
+/**
+*
+* Get the contents of the bram offset register.
+*
+* The bram offset register holds the starting bram address to transfer
+* data from during configuration or write data to during readback.
+*
+* @param BaseAddress is the base address of the device
+*
+* @return A 32-bit value representing the contents of the bram offset
+* register.
+*
+* @note
+*
+* u32 XHwIcap_mGetOffsetReg(u32 BaseAddress);
+*
+*****************************************************************************/
+#define XHwIcap_mGetOffsetReg(BaseAddress) \
+ (in_be32((u32 *)((BaseAddress + XHI_BRAM_OFFSET_REG_OFFSET))))
+
+/****************************************************************************/
+/**
+*
+* Get the contents of the done register.
+*
+* The done register is set to zero during configuration or readback.
+* When the current configuration or readback completes the done register
+* is set to one.
+*
+* @param BaseAddress is the base address of the device
+*
+* @return A 32-bit value with bit 1 representing done or not
+*
+* @note
+*
+* u32 XHwIcap_mGetDoneReg(u32 BaseAddress);
+*
+*****************************************************************************/
+
+#define XHwIcap_mGetDoneReg(BaseAddress) \
+ (in_be32((u32 *)((BaseAddress + XHI_STATUS_REG_OFFSET))) & 1)
+
+/****************************************************************************/
+/**
+*
+* Get the contents of the status register.
+*
+* The status register contains the ICAP status and the done bit.
+*
+* D8 - cfgerr
+* D7 - dalign
+* D6 - rip
+* D5 - in_abort_l
+* D4 - Always 1
+* D3 - Always 1
+* D2 - Always 1
+* D1 - Always 1
+* D0 - Done bit
+*
+* @param BaseAddress is the base address of the device
+*
+* @return A 32-bit value representing the contents of the status register
+*
+* @note
+*
+* u32 XHwIcap_mGetStatusReg(u32 BaseAddress);
+*
+*****************************************************************************/
+
+#define XHwIcap_mGetStatusReg(BaseAddress) \
+ (in_be32((u32 *)((BaseAddress + XHI_STATUS_REG_OFFSET))))
+
+#define XHwIcap_mReset(BaseAddress) \
+ (out_be32((u32 *)((BaseAddress + XHI_STATUS_REG_OFFSET)), 0xFEFE))
+
+/****************************************************************************/
+/**
+* Reads data from the storage buffer bram.
+*
+* A bram is used as a configuration memory cache. One frame of data can
+* be stored in this "storage buffer".
+*
+* @param BaseAddress - contains the base address of the component.
+*
+* @param Offset - The offset into which the data should be read.
+*
+* @return The value of the specified offset in the bram.
+*
+* @note
+*
+* u32 XHwIcap_mGetBram(u32 BaseAddress, u32 Offset);
+*
+*****************************************************************************/
+#define XHwIcap_mGetBram(BaseAddress, Offset) \
+ (in_be32((u32 *)((BaseAddress+(Offset<<2)))))
+
+/****************************************************************************/
+/**
+* Set the size register.
+*
+* The size register holds the number of 8 bit bytes to transfer between
+* bram and the icap (or icap to bram).
+*
+* @param BaseAddress - contains the base address of the device.
+*
+* @param Data - The size in bytes.
+*
+* @return None.
+*
+* @note
+*
+* void XHwIcap_mSetSizeReg(u32 BaseAddress, u32 Data);
+*
+*****************************************************************************/
+#define XHwIcap_mSetSizeReg(BaseAddress, Data) \
+ (out_be32((u32 *)((BaseAddress) + XHI_SIZE_REG_OFFSET), (Data)))
+
+/****************************************************************************/
+/**
+* Set the bram offset register.
+*
+* The bram offset register holds the starting bram address to transfer
+* data from during configuration or write data to during readback.
+*
+* @param BaseAddress contains the base address of the device.
+*
+* @param Data is the value to be written to the data register.
+*
+* @return None.
+*
+* @note
+*
+* void XHwIcap_mSetOffsetReg(u32 BaseAddress, u32 Data);
+*
+*****************************************************************************/
+#define XHwIcap_mSetOffsetReg(BaseAddress, Data) \
+ (out_be32((u32 *)((BaseAddress) + XHI_BRAM_OFFSET_REG_OFFSET), (Data)))
+
+/****************************************************************************/
+/**
+* Set the RNC (Readback not Configure) register.
+*
+* The RNC register determines the direction of the data transfer. It
+* controls whether a configuration or readback take place. Writing to
+* this register initiates the transfer. A value of 1 initiates a
+* readback while writing a value of 0 initiates a configuration.
+*
+* @param BaseAddress contains the base address of the device.
+*
+* @param Data is the value to be written to the data register.
+*
+* @return None.
+*
+* @note
+*
+* void XHwIcap_mSetRncReg(u32 BaseAddress, u32 Data);
+*
+*****************************************************************************/
+#define XHwIcap_mSetRncReg(BaseAddress, Data) \
+ (out_be32((u32 *)((BaseAddress) + XHI_RNC_REG_OFFSET), (Data)))
+
+/****************************************************************************/
+/**
+* Write data to the storage buffer bram.
+*
+* A bram is used as a configuration memory cache. One frame of data can
+* be stored in this "storage buffer".
+*
+* @param BaseAddress - contains the base address of the component.
+*
+* @param Offset - The offset into which the data should be written.
+*
+* @param Data - The value to be written to the bram offset.
+*
+* @return None.
+*
+* @note
+*
+* void XHwIcap_mSetBram(u32 BaseAddress, u32 Offset, u32 Data);
+*
+*****************************************************************************/
+#define XHwIcap_mSetBram(BaseAddress, Offset, Data) \
+ (out_be32((u32 *)((BaseAddress+(Offset<<2))), (Data)))
+
+/****************************************************************************/
+/**
+*
+* Generates a Type 1 packet header that reads back the requested configuration
+* register.
+*
+* @param Register is the address of the register to be read back.
+* Register constants are defined in this file.
+*
+* @return Type 1 packet header to read the specified register
+*
+* @note None.
+*
+*****************************************************************************/
+#define XHwIcap_Type1Read(Register) \
+ ((XHI_TYPE_1 << XHI_TYPE_SHIFT) | (Register << XHI_REGISTER_SHIFT) | \
+ (XHI_OP_READ << XHI_OP_SHIFT))
+
+/****************************************************************************/
+/**
+*
+* Generates a Type 1 packet header that writes to the requested
+* configuration register.
+*
+* @param Register is the address of the register to be written to.
+* Register constants are defined in this file.
+*
+* @return Type 1 packet header to write the specified register
+*
+* @note None.
+*
+*****************************************************************************/
+#define XHwIcap_Type1Write(Register) \
+ ((XHI_TYPE_1 << XHI_TYPE_SHIFT) | (Register << XHI_REGISTER_SHIFT) | \
+ (XHI_OP_WRITE << XHI_OP_SHIFT))
+
+/************************** Function Prototypes *****************************/
+
+/* These functions are the ones defined in the lower level
+ * Self-Reconfiguration Platform (SRP) API.
+ */
+
+/* Initializes a XHwIcap instance.. */
+int XHwIcap_Initialize(struct xhwicap_drvdata *InstancePtr, u16 DeviceId,
+ u32 DeviceIdCode);
+
+/* Reads integers from the device into the storage buffer. */
+int XHwIcap_DeviceRead(struct xhwicap_drvdata *InstancePtr, u32 Offset,
+ u32 NumInts);
+
+/* Writes integers to the device from the storage buffer. */
+int XHwIcap_DeviceWrite(struct xhwicap_drvdata *InstancePtr, u32 Offset,
+ u32 NumInts);
+
+/* Writes word to the storage buffer. */
+void XHwIcap_StorageBufferWrite(struct xhwicap_drvdata *InstancePtr,
+ u32 Address, u32 Data);
+
+/* Reads word from the storage buffer. */
+u32 XHwIcap_StorageBufferRead(struct xhwicap_drvdata *InstancePtr, u32 Address);
+
+/* Loads a partial bitstream from system memory. */
+int XHwIcap_SetConfiguration(struct xhwicap_drvdata *InstancePtr, u32 *Data,
+ u32 Size);
+
+/* Loads a partial bitstream from system memory. */
+int XHwIcap_GetConfiguration(struct xhwicap_drvdata *InstancePtr, u32 *Data,
+ u32 Size);
+
+/* Sends a DESYNC command to the ICAP */
+int XHwIcap_CommandDesync(struct xhwicap_drvdata *InstancePtr);
+
+/* Sends a CAPTURE command to the ICAP */
+int XHwIcap_CommandCapture(struct xhwicap_drvdata *InstancePtr);
+
+/* Returns the value of the specified configuration register */
+u32 XHwIcap_GetConfigReg(struct xhwicap_drvdata *InstancePtr, u32 ConfigReg);
+
+#endif
--
1.5.3.4-dirty
^ permalink raw reply related
* Re: ucc_uart: add support for Freescale QUICCEngine UART
From: Arnd Bergmann @ 2007-12-04 23:56 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Timur Tabi
In-Reply-To: <4755E701.3040908@freescale.com>
On Wednesday 05 December 2007, Timur Tabi wrote:
> Arnd Bergmann wrote:
>=20
> > You can argue that the QS is really a DMA device, but in that case you
> > should convert the driver to use the DMA mapping interfaces correctly,
> > which I would consider overkill.
>=20
> I'm confused. =A0I'm already calling dma_alloc_coherent() and getting a d=
ma_addr_t=20
> back. =A0Why do I need to use mapping functions to convert between virtua=
l and=20
> physical/bus addresses?
No, I'm sorry but I'm the one who was confused. The problem I saw was that
you return something offset from "bd_phys" as a dma_addr_t. This would be
a lot easier if you had called it bd_bus or bd_dma instead of bd_phys, but
your code looks absolutely correct upon closer inspection.
Arnd <><
^ permalink raw reply
* Re: Fix Firmware class name collision
From: Scott Wood @ 2007-12-04 23:52 UTC (permalink / raw)
To: Timur Tabi; +Cc: PowerPC dev list, Greg Kroah-Hartman, Markus Rechberger
In-Reply-To: <4755E6AC.9020808@freescale.com>
Timur Tabi wrote:
>
> In other words, the only thing you get is the first letter of the device name.
> You used to get the whole name. The physical address obviously isn't very helpful.
The physical address certainly is useful when you have more than one
device of the same name.
> Now, there are two solutions:
>
> 1) Change the PowerPC device names from physical_address.device_name to
> device_name.physical_address (so that e0102400.ucc becomes ucc.e0102400)
So then you'd get "firmware-ucc.e01024". What if there's another ucc at
e0102480? For devices with longer names, you'd have even less
precision in the address.
-Scott
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox