From 9e1c72a4e465ceb2c4c6e2dfc0584a59bec5c2c9 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Thu, 12 Jan 2006 14:25:50 -0700 Subject: [PATCH] Remove bzImage target Since the documentation no longer tells people to 'make bzImage', and with the previous patch nothing more than 'make' is required to get the right bootable images (just like on i386 now), this removes the bzImage -> zImage target redirect on ARCH=powerpc Signed-off-by: Tom Rini Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index d3654a2..07b8e15 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -147,9 +147,6 @@ all: $(KBUILD_IMAGE) CPPFLAGS_vmlinux.lds := -Upowerpc -# All the instructions talk about "make bzImage". -bzImage: zImage - BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage .PHONY: $(BOOT_TARGETS) -- cgit v0.10.2 From 43ccf202214067f12af5d7a6e144e18bb35553a9 Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Thu, 12 Jan 2006 16:05:35 -0600 Subject: [PATCH] powerpc: Add some more pSeries hypervisor call constants Adds a few more hypervisor call constants. Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h index da7af5a..38ca9ad 100644 --- a/include/asm-powerpc/hvcall.h +++ b/include/asm-powerpc/hvcall.h @@ -6,7 +6,10 @@ #define H_Success 0 #define H_Busy 1 /* Hardware busy -- retry later */ +#define H_Closed 2 /* Resource closed */ #define H_Constrained 4 /* Resource request constrained to max allowed */ +#define H_InProgress 14 /* Kind of like busy */ +#define H_Continue 18 /* Returned from H_Join on success */ #define H_LongBusyStartRange 9900 /* Start of long busy range */ #define H_LongBusyOrder1msec 9900 /* Long busy, hint that 1msec is a good time to retry */ #define H_LongBusyOrder10msec 9901 /* Long busy, hint that 10msec is a good time to retry */ @@ -114,6 +117,8 @@ #define H_REGISTER_VTERM 0x154 #define H_FREE_VTERM 0x158 #define H_POLL_PENDING 0x1D8 +#define H_JOIN 0x298 +#define H_ENABLE_CRQ 0x2B0 #ifndef __ASSEMBLY__ -- cgit v0.10.2 From 898b5395e915210f41223caa30312994d64cba1d Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Thu, 12 Jan 2006 16:07:17 -0600 Subject: [PATCH] powerpc: Add/remove/update properties in /proc/device-tree Add support to the proc_device_tree file for removing and updating properties. Remove just removes the proc file, update changes the data pointer within the proc file. The remainder of the device-tree changes occur elsewhere. Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index fb117b7..9bdd077 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c @@ -81,6 +81,30 @@ void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop __proc_device_tree_add_prop(pde, prop); } +void proc_device_tree_remove_prop(struct proc_dir_entry *pde, + struct property *prop) +{ + remove_proc_entry(prop->name, pde); +} + +void proc_device_tree_update_prop(struct proc_dir_entry *pde, + struct property *newprop, + struct property *oldprop) +{ + struct proc_dir_entry *ent; + + for (ent = pde->subdir; ent != NULL; ent = ent->next) + if (ent->data == oldprop) + break; + if (ent == NULL) { + printk(KERN_WARNING "device-tree: property \"%s\" " + " does not exist\n", oldprop->name); + } else { + ent->data = newprop; + ent->size = newprop->length; + } +} + /* * Process a node, adding entries for its children and its properties. */ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 74488e4..aa6322d 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -146,6 +146,11 @@ struct property; extern void proc_device_tree_init(void); extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); +extern void proc_device_tree_remove_prop(struct proc_dir_entry *pde, + struct property *prop); +extern void proc_device_tree_update_prop(struct proc_dir_entry *pde, + struct property *newprop, + struct property *oldprop); #endif /* CONFIG_PROC_DEVICETREE */ extern struct proc_dir_entry *proc_symlink(const char *, -- cgit v0.10.2 From 088186ded490ced80758200cf8f906ed741df306 Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Thu, 12 Jan 2006 16:08:27 -0600 Subject: [PATCH] powerpc: Add/remove/update properties in firmware device tree Add support for updating and removing device tree properties. Since we hand out pointers to properties with gay abandon, we can't just free the property storage. Instead we move deleted, or the old copy of an updated property, to a "dead properties" list. Also note, its not feasable to kref device tree properties. we call get_property() all over the kernel in a wild variety of contexts. One consequence of this change is that we now take a read_lock(&devtree_lock) when doing get_property(). Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 02e2115..70057b6 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1627,6 +1627,11 @@ static void of_node_release(struct kref *kref) kfree(prop->value); kfree(prop); prop = next; + + if (!prop) { + prop = node->deadprops; + node->deadprops = NULL; + } } kfree(node->intrs); kfree(node->full_name); @@ -1783,13 +1788,16 @@ unsigned char *get_property(struct device_node *np, const char *name, { struct property *pp; + read_lock(&devtree_lock); for (pp = np->properties; pp != 0; pp = pp->next) if (strcmp(pp->name, name) == 0) { if (lenp != 0) *lenp = pp->length; - return pp->value; + break; } - return NULL; + read_unlock(&devtree_lock); + + return pp ? pp->value : NULL; } EXPORT_SYMBOL(get_property); @@ -1823,4 +1831,82 @@ int prom_add_property(struct device_node* np, struct property* prop) return 0; } +/* + * Remove a property from a node. Note that we don't actually + * remove it, since we have given out who-knows-how-many pointers + * to the data using get-property. Instead we just move the property + * to the "dead properties" list, so it won't be found any more. + */ +int prom_remove_property(struct device_node *np, struct property *prop) +{ + struct property **next; + int found = 0; + + write_lock(&devtree_lock); + next = &np->properties; + while (*next) { + if (*next == prop) { + /* found the node */ + *next = prop->next; + prop->next = np->deadprops; + np->deadprops = prop; + found = 1; + break; + } + next = &(*next)->next; + } + write_unlock(&devtree_lock); + + if (!found) + return -ENODEV; + +#ifdef CONFIG_PROC_DEVICETREE + /* try to remove the proc node as well */ + if (np->pde) + proc_device_tree_remove_prop(np->pde, prop); +#endif /* CONFIG_PROC_DEVICETREE */ + + return 0; +} + +/* + * Update a property in a node. Note that we don't actually + * remove it, since we have given out who-knows-how-many pointers + * to the data using get-property. Instead we just move the property + * to the "dead properties" list, and add the new property to the + * property list + */ +int prom_update_property(struct device_node *np, + struct property *newprop, + struct property *oldprop) +{ + struct property **next; + int found = 0; + + write_lock(&devtree_lock); + next = &np->properties; + while (*next) { + if (*next == oldprop) { + /* found the node */ + newprop->next = oldprop->next; + *next = newprop; + oldprop->next = np->deadprops; + np->deadprops = oldprop; + found = 1; + break; + } + next = &(*next)->next; + } + write_unlock(&devtree_lock); + + if (!found) + return -ENODEV; +#ifdef CONFIG_PROC_DEVICETREE + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_update_prop(np->pde, newprop, oldprop); +#endif /* CONFIG_PROC_DEVICETREE */ + + return 0; +} diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 329e9bf..25d8d59 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -87,6 +87,7 @@ struct device_node { char *full_name; struct property *properties; + struct property *deadprops; /* removed properties */ struct device_node *parent; struct device_node *child; struct device_node *sibling; @@ -164,6 +165,10 @@ extern int prom_n_size_cells(struct device_node* np); extern int prom_n_intr_cells(struct device_node* np); extern void prom_get_irq_senses(unsigned char *senses, int off, int max); extern int prom_add_property(struct device_node* np, struct property* prop); +extern int prom_remove_property(struct device_node *np, struct property *prop); +extern int prom_update_property(struct device_node *np, + struct property *newprop, + struct property *oldprop); #ifdef CONFIG_PPC32 /* -- cgit v0.10.2 From ecaa8b0ff326920c8a89d748382e1c1d8812676c Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Thu, 12 Jan 2006 16:09:29 -0600 Subject: [PATCH] powerpc: Add of_find_property function Add an of_find_property function that returns a struct property given a property name. Then change the get_property function to use that routine internally. Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 70057b6..d50c8df 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1779,12 +1779,8 @@ static int __init prom_reconfig_setup(void) __initcall(prom_reconfig_setup); #endif -/* - * Find a property with a given name for a given node - * and return the value. - */ -unsigned char *get_property(struct device_node *np, const char *name, - int *lenp) +struct property *of_find_property(struct device_node *np, const char *name, + int *lenp) { struct property *pp; @@ -1797,6 +1793,17 @@ unsigned char *get_property(struct device_node *np, const char *name, } read_unlock(&devtree_lock); + return pp; +} + +/* + * Find a property with a given name for a given node + * and return the value. + */ +unsigned char *get_property(struct device_node *np, const char *name, + int *lenp) +{ + struct property *pp = of_find_property(np,name,lenp); return pp ? pp->value : NULL; } EXPORT_SYMBOL(get_property); diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 25d8d59..5b2bd4e 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -136,6 +136,9 @@ extern struct device_node *of_find_all_nodes(struct device_node *prev); extern struct device_node *of_get_parent(const struct device_node *node); extern struct device_node *of_get_next_child(const struct device_node *node, struct device_node *prev); +extern struct property *of_find_property(struct device_node *np, + const char *name, + int *lenp); extern struct device_node *of_node_get(struct device_node *node); extern void of_node_put(struct device_node *node); -- cgit v0.10.2 From 610d91511f99f0a8325ad78fb7259c454b23e65a Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Thu, 12 Jan 2006 16:10:22 -0600 Subject: [PATCH] powerpc: Add support for changing properties from userspace Add support to reconfigure the device tree through the existing proc filesystem interface. Add "add_property", "remove_property", and "update_property" commands to the existing interface. Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index d886416..86cfa6e 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -350,6 +350,100 @@ static int do_remove_node(char *buf) return rv; } +static char *parse_node(char *buf, size_t bufsize, struct device_node **npp) +{ + char *handle_str; + phandle handle; + *npp = NULL; + + handle_str = buf; + + buf = strchr(buf, ' '); + if (!buf) + return NULL; + *buf = '\0'; + buf++; + + handle = simple_strtoul(handle_str, NULL, 10); + + *npp = of_find_node_by_phandle(handle); + return buf; +} + +static int do_add_property(char *buf, size_t bufsize) +{ + struct property *prop = NULL; + struct device_node *np; + unsigned char *value; + char *name, *end; + int length; + end = buf + bufsize; + buf = parse_node(buf, bufsize, &np); + + if (!np) + return -ENODEV; + + if (parse_next_property(buf, end, &name, &length, &value) == NULL) + return -EINVAL; + + prop = new_property(name, length, value, NULL); + if (!prop) + return -ENOMEM; + + prom_add_property(np, prop); + + return 0; +} + +static int do_remove_property(char *buf, size_t bufsize) +{ + struct device_node *np; + char *tmp; + struct property *prop; + buf = parse_node(buf, bufsize, &np); + + if (!np) + return -ENODEV; + + tmp = strchr(buf,' '); + if (tmp) + *tmp = '\0'; + + if (strlen(buf) == 0) + return -EINVAL; + + prop = of_find_property(np, buf, NULL); + + return prom_remove_property(np, prop); +} + +static int do_update_property(char *buf, size_t bufsize) +{ + struct device_node *np; + unsigned char *value; + char *name, *end; + int length; + struct property *newprop, *oldprop; + buf = parse_node(buf, bufsize, &np); + end = buf + bufsize; + + if (!np) + return -ENODEV; + + if (parse_next_property(buf, end, &name, &length, &value) == NULL) + return -EINVAL; + + newprop = new_property(name, length, value, NULL); + if (!newprop) + return -ENOMEM; + + oldprop = of_find_property(np, name,NULL); + if (!oldprop) + return -ENODEV; + + return prom_update_property(np, newprop, oldprop); +} + /** * ofdt_write - perform operations on the Open Firmware device tree * @@ -392,6 +486,12 @@ static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t coun rv = do_add_node(tmp, count - (tmp - kbuf)); else if (!strcmp(kbuf, "remove_node")) rv = do_remove_node(tmp); + else if (!strcmp(kbuf, "add_property")) + rv = do_add_property(tmp, count - (tmp - kbuf)); + else if (!strcmp(kbuf, "remove_property")) + rv = do_remove_property(tmp, count - (tmp - kbuf)); + else if (!strcmp(kbuf, "update_property")) + rv = do_update_property(tmp, count - (tmp - kbuf)); else rv = -EINVAL; out: -- cgit v0.10.2 From 135f0b17a7a146fa65ccd75704eecf77ee19d587 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Thu, 12 Jan 2006 16:55:58 -0700 Subject: [PATCH] powerpc/boot: Better use of defaultimage- The following reworks how defaultimage- is used. We default to zImage here and then override it on platforms that need something more (uImage in the future) or less (vmlinux on iSeries). Signed-off-by: Tom Rini Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 07b8e15..44dd82b 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -139,9 +139,9 @@ drivers-$(CONFIG_CPM2) += arch/ppc/8260_io/ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ -defaultimage-$(CONFIG_PPC32) := zImage +# Default to zImage, override when needed +defaultimage-y := zImage defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux -defaultimage-$(CONFIG_PPC_PSERIES) := zImage KBUILD_IMAGE := $(defaultimage-y) all: $(KBUILD_IMAGE) -- cgit v0.10.2 From 7e78e5e502d4f220d24c6f738f2fdb078ad33607 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 12 Jan 2006 21:04:23 -0600 Subject: [PATCH] powerpc: Updated platforms that use gianfar to match driver The gianfar driver changed how it required MDIO bus and phy id's to be passed to it. Also, it no longer passes the physical address of the MDIO bus. Instead we have a proper platform device. Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index 04bdc39..012e1e6 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c @@ -51,9 +51,6 @@ #include -static const char *GFAR_PHY_0 = "phy0:0"; -static const char *GFAR_PHY_1 = "phy0:1"; - #ifndef CONFIG_PCI unsigned long isa_io_base = 0; unsigned long isa_mem_base = 0; @@ -129,20 +126,21 @@ mpc834x_sys_setup_arch(void) mdata->irq[1] = MPC83xx_IRQ_EXT2; mdata->irq[2] = -1; mdata->irq[31] = -1; - mdata->paddr += binfo->bi_immr_base; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_0; + pdata->bus_id = 0; + pdata->phy_id = 0; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_1; + pdata->bus_id = 0; + pdata->phy_id = 1; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index c5cde97..2eceb1e 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c @@ -52,10 +52,6 @@ #include -static const char *GFAR_PHY_0 = "phy0:0"; -static const char *GFAR_PHY_1 = "phy0:1"; -static const char *GFAR_PHY_3 = "phy0:3"; - /* ************************************************************************ * * Setup the architecture @@ -102,27 +98,29 @@ mpc8540ads_setup_arch(void) mdata->irq[2] = -1; mdata->irq[3] = MPC85xx_IRQ_EXT5; mdata->irq[31] = -1; - mdata->paddr += binfo->bi_immr_base; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_0; + pdata->bus_id = 0; + pdata->phy_id = 0; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_1; + pdata->bus_id = 0; + pdata->phy_id = 1; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC); if (pdata) { pdata->board_flags = 0; - pdata->bus_id = GFAR_PHY_3; + pdata->bus_id = 0; + pdata->phy_id = 3; memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6); } diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c index 8e39a55..442c7ff 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c @@ -56,10 +56,6 @@ #include -static const char *GFAR_PHY_0 = "phy0:0"; -static const char *GFAR_PHY_1 = "phy0:1"; -static const char *GFAR_PHY_3 = "phy0:3"; - /* ************************************************************************ * * Setup the architecture @@ -99,20 +95,21 @@ mpc8560ads_setup_arch(void) mdata->irq[2] = -1; mdata->irq[3] = MPC85xx_IRQ_EXT5; mdata->irq[31] = -1; - mdata->paddr += binfo->bi_immr_base; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_0; + pdata->bus_id = 0; + pdata->phy_id = 0; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_1; + pdata->bus_id = 0; + pdata->phy_id = 1; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index 2959e3c..b332eba 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -395,9 +395,6 @@ mpc85xx_cds_pcibios_fixup(void) TODC_ALLOC(); -static const char *GFAR_PHY_0 = "phy0:0"; -static const char *GFAR_PHY_1 = "phy0:1"; - /* ************************************************************************ * * Setup the architecture @@ -461,34 +458,37 @@ mpc85xx_cds_setup_arch(void) mdata->irq[2] = -1; mdata->irq[3] = -1; mdata->irq[31] = -1; - mdata->paddr += binfo->bi_immr_base; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_0; + pdata->bus_id = 0; + pdata->phy_id = 0; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_1; + pdata->bus_id = 0; + pdata->phy_id = 1; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_0; + pdata->bus_id = 0; + pdata->phy_id = 0; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_1; + pdata->bus_id = 0; + pdata->phy_id = 1; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index 45a5b81..e777ba8 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c @@ -91,9 +91,6 @@ sbc8560_early_serial_map(void) } #endif -static const char *GFAR_PHY_25 = "phy0:25"; -static const char *GFAR_PHY_26 = "phy0:26"; - /* ************************************************************************ * * Setup the architecture @@ -136,20 +133,21 @@ sbc8560_setup_arch(void) mdata->irq[25] = MPC85xx_IRQ_EXT6; mdata->irq[26] = MPC85xx_IRQ_EXT7; mdata->irq[31] = -1; - mdata->paddr += binfo->bi_immr_base; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_25; + pdata->bus_id = 0; + pdata->phy_id = 25; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_26; + pdata->bus_id = 0; + pdata->phy_id = 26; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c index 15ce9d0..061bb7c 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.c +++ b/arch/ppc/platforms/85xx/stx_gp3.c @@ -93,9 +93,6 @@ static u8 gp3_openpic_initsenses[] __initdata = { 0x0, /* External 11: */ }; -static const char *GFAR_PHY_2 = "phy0:2"; -static const char *GFAR_PHY_4 = "phy0:4"; - /* * Setup the architecture */ @@ -130,20 +127,21 @@ gp3_setup_arch(void) mdata->irq[2] = MPC85xx_IRQ_EXT5; mdata->irq[4] = MPC85xx_IRQ_EXT5; mdata->irq[31] = -1; - mdata->paddr += binfo->bi_immr_base; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); if (pdata) { /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */ - pdata->bus_id = GFAR_PHY_2; + pdata->bus_id = 0; + pdata->phy_id = 2; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); if (pdata) { /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */ - pdata->bus_id = GFAR_PHY_4; + pdata->bus_id = 0; + pdata->phy_id = 4; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c index c6dfd8f..b436f4d 100644 --- a/arch/ppc/platforms/85xx/tqm85xx.c +++ b/arch/ppc/platforms/85xx/tqm85xx.c @@ -91,12 +91,6 @@ static u_char tqm85xx_openpic_initsenses[] __initdata = { 0x0, /* External 11: */ }; -static const char *GFAR_PHY_0 = "phy0:2"; -static const char *GFAR_PHY_1 = "phy0:1"; -#ifdef CONFIG_MPC8540 -static const char *GFAR_PHY_3 = "phy0:3"; -#endif - /* ************************************************************************ * * Setup the architecture @@ -149,20 +143,21 @@ tqm85xx_setup_arch(void) mdata->irq[2] = -1; mdata->irq[3] = MPC85xx_IRQ_EXT8; mdata->irq[31] = -1; - mdata->paddr += binfo->bi_immr_base; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_0; + pdata->bus_id = 0; + pdata->phy_id = 2; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_1; + pdata->bus_id = 0; + pdata->phy_id = 1; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } @@ -170,7 +165,8 @@ tqm85xx_setup_arch(void) pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC); if (pdata) { pdata->board_flags = 0; - pdata->bus_id = GFAR_PHY_3; + pdata->bus_id = 0; + pdata->phy_id = 3; memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6); } #endif diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index 847df44..f9b95de 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c @@ -28,7 +28,6 @@ */ struct gianfar_mdio_data mpc83xx_mdio_pdata = { - .paddr = 0x24520, }; static struct gianfar_platform_data mpc83xx_tsec1_pdata = { @@ -226,7 +225,14 @@ struct platform_device ppc_sys_platform_devices[] = { .name = "fsl-gianfar_mdio", .id = 0, .dev.platform_data = &mpc83xx_mdio_pdata, - .num_resources = 0, + .num_resources = 1, + .resource = (struct resource[]) { + { + .start = 0x24520, + .end = 0x2453f, + .flags = IORESOURCE_MEM, + }, + }, }, }; diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c index 69949d2..00e9b6f 100644 --- a/arch/ppc/syslib/mpc85xx_devices.c +++ b/arch/ppc/syslib/mpc85xx_devices.c @@ -26,7 +26,6 @@ * what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup */ struct gianfar_mdio_data mpc85xx_mdio_pdata = { - .paddr = MPC85xx_MIIM_OFFSET, }; static struct gianfar_platform_data mpc85xx_tsec1_pdata = { @@ -720,7 +719,14 @@ struct platform_device ppc_sys_platform_devices[] = { .name = "fsl-gianfar_mdio", .id = 0, .dev.platform_data = &mpc85xx_mdio_pdata, - .num_resources = 0, + .num_resources = 1, + .resource = (struct resource[]) { + { + .start = 0x24520, + .end = 0x2453f, + .flags = IORESOURCE_MEM, + }, + }, }, }; -- cgit v0.10.2 From e58c3495e6007af59382540bb21ee941e470d88d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 13 Jan 2006 14:56:25 +1100 Subject: [PATCH] powerpc: Cleanup LOADADDR etc. asm macros This patch consolidates the variety of macros used for loading 32 or 64-bit constants in assembler (LOADADDR, LOADBASE, SET_REG_TO_*). The idea is to make the set of macros consistent across 32 and 64 bit and to make it more obvious which is the appropriate one to use in a given situation. The new macros and their semantics are described in the comments in ppc_asm.h. In the process, we change several places that were unnecessarily using immediate loads on ppc64 to use the GOT/TOC. Likewise we cleanup a couple of places where we were clumsily subtracting PAGE_OFFSET with asm instructions to use assemble-time arithmetic or the toreal() macro instead. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S index cca942f..b61d86e 100644 --- a/arch/powerpc/kernel/cpu_setup_power4.S +++ b/arch/powerpc/kernel/cpu_setup_power4.S @@ -130,7 +130,7 @@ _GLOBAL(__save_cpu_setup) mfcr r7 /* Get storage ptr */ - LOADADDR(r5,cpu_state_storage) + LOAD_REG_IMMEDIATE(r5,cpu_state_storage) /* We only deal with 970 for now */ mfspr r0,SPRN_PVR @@ -164,7 +164,7 @@ _GLOBAL(__restore_cpu_setup) /* Get storage ptr (FIXME when using anton reloc as we * are running with translation disabled here */ - LOADADDR(r5,cpu_state_storage) + LOAD_REG_IMMEDIATE(r5,cpu_state_storage) /* We only deal with 970 for now */ mfspr r0,SPRN_PVR diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 036b71d..d8da2a3 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -988,7 +988,7 @@ _GLOBAL(enter_rtas) stwu r1,-INT_FRAME_SIZE(r1) mflr r0 stw r0,INT_FRAME_SIZE+4(r1) - LOADADDR(r4, rtas) + LOAD_REG_ADDR(r4, rtas) lis r6,1f@ha /* physical return address for rtas */ addi r6,r6,1f@l tophys(r6,r6) diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index aacebb3..4ba81e1 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -689,9 +689,8 @@ _GLOBAL(enter_rtas) std r6,PACASAVEDMSR(r13) /* Setup our real return addr */ - SET_REG_TO_LABEL(r4,.rtas_return_loc) - SET_REG_TO_CONST(r9,PAGE_OFFSET) - sub r4,r4,r9 + LOAD_REG_ADDR(r4,.rtas_return_loc) + clrldi r4,r4,2 /* convert to realmode address */ mtlr r4 li r0,0 @@ -706,7 +705,7 @@ _GLOBAL(enter_rtas) sync /* disable interrupts so SRR0/1 */ mtmsrd r0 /* don't get trashed */ - SET_REG_TO_LABEL(r4,rtas) + LOAD_REG_ADDR(r4, rtas) ld r5,RTASENTRY(r4) /* get the rtas->entry value */ ld r4,RTASBASE(r4) /* get the rtas->base value */ @@ -718,8 +717,7 @@ _GLOBAL(enter_rtas) _STATIC(rtas_return_loc) /* relocation is off at this point */ mfspr r4,SPRN_SPRG3 /* Get PACA */ - SET_REG_TO_CONST(r5, PAGE_OFFSET) - sub r4,r4,r5 /* RELOC the PACA base pointer */ + clrldi r4,r4,2 /* convert to realmode address */ mfmsr r6 li r0,MSR_RI @@ -728,7 +726,7 @@ _STATIC(rtas_return_loc) mtmsrd r6 ld r1,PACAR1(r4) /* Restore our SP */ - LOADADDR(r3,.rtas_restore_regs) + LOAD_REG_IMMEDIATE(r3,.rtas_restore_regs) ld r4,PACASAVEDMSR(r4) /* Restore our MSR */ mtspr SPRN_SRR0,r3 diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index b780b42..e4362df 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S @@ -39,9 +39,9 @@ _GLOBAL(load_up_fpu) * to another. Instead we call giveup_fpu in switch_to. */ #ifndef CONFIG_SMP - LOADBASE(r3, last_task_used_math) + LOAD_REG_ADDRBASE(r3, last_task_used_math) toreal(r3) - PPC_LL r4,OFF(last_task_used_math)(r3) + PPC_LL r4,ADDROFF(last_task_used_math)(r3) PPC_LCMPI 0,r4,0 beq 1f toreal(r4) @@ -77,7 +77,7 @@ _GLOBAL(load_up_fpu) #ifndef CONFIG_SMP subi r4,r5,THREAD fromreal(r4) - PPC_STL r4,OFF(last_task_used_math)(r3) + PPC_STL r4,ADDROFF(last_task_used_math)(r3) #endif /* CONFIG_SMP */ /* restore registers and return */ /* we haven't used ctr or xer or lr */ @@ -113,8 +113,8 @@ _GLOBAL(giveup_fpu) 1: #ifndef CONFIG_SMP li r5,0 - LOADBASE(r4,last_task_used_math) - PPC_STL r5,OFF(last_task_used_math)(r4) + LOAD_REG_ADDRBASE(r4,last_task_used_math) + PPC_STL r5,ADDROFF(last_task_used_math)(r4) #endif /* CONFIG_SMP */ blr diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 1c066d1..b3718f3 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -154,12 +154,12 @@ _GLOBAL(__secondary_hold) bne 100b #ifdef CONFIG_HMT - LOADADDR(r4, .hmt_init) + SET_REG_IMMEDIATE(r4, .hmt_init) mtctr r4 bctr #else #ifdef CONFIG_SMP - LOADADDR(r4, .pSeries_secondary_smp_init) + LOAD_REG_IMMEDIATE(r4, .pSeries_secondary_smp_init) mtctr r4 mr r3,r24 bctr @@ -205,9 +205,10 @@ exception_marker: #define EX_LR 72 /* - * We're short on space and time in the exception prolog, so we can't use - * the normal LOADADDR macro. Normally we just need the low halfword of the - * address, but for Kdump we need the whole low word. + * We're short on space and time in the exception prolog, so we can't + * use the normal SET_REG_IMMEDIATE macro. Normally we just need the + * low halfword of the address, but for Kdump we need the whole low + * word. */ #ifdef CONFIG_CRASH_DUMP #define LOAD_HANDLER(reg, label) \ @@ -713,7 +714,7 @@ system_reset_iSeries: lbz r23,PACAPROCSTART(r13) /* Test if this processor * should start */ sync - LOADADDR(r3,current_set) + LOAD_REG_IMMEDIATE(r3,current_set) sldi r28,r24,3 /* get current_set[cpu#] */ ldx r3,r3,r28 addi r1,r3,THREAD_SIZE @@ -746,8 +747,8 @@ iSeries_secondary_smp_loop: decrementer_iSeries_masked: li r11,1 stb r11,PACALPPACA+LPPACADECRINT(r13) - LOADBASE(r12,tb_ticks_per_jiffy) - lwz r12,OFF(tb_ticks_per_jiffy)(r12) + LOAD_REG_ADDRBASE(r12,tb_ticks_per_jiffy) + lwz r12,ADDROFF(tb_ticks_per_jiffy)(r12) mtspr SPRN_DEC,r12 /* fall through */ @@ -1412,7 +1413,7 @@ _GLOBAL(pSeries_secondary_smp_init) * physical cpu id in r24, we need to search the pacas to find * which logical id maps to our physical one. */ - LOADADDR(r13, paca) /* Get base vaddr of paca array */ + LOAD_REG_IMMEDIATE(r13, paca) /* Get base vaddr of paca array */ li r5,0 /* logical cpu id */ 1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ cmpw r6,r24 /* Compare to our id */ @@ -1446,8 +1447,8 @@ _GLOBAL(pSeries_secondary_smp_init) #ifdef CONFIG_PPC_ISERIES _STATIC(__start_initialization_iSeries) /* Clear out the BSS */ - LOADADDR(r11,__bss_stop) - LOADADDR(r8,__bss_start) + LOAD_REG_IMMEDIATE(r11,__bss_stop) + LOAD_REG_IMMEDIATE(r8,__bss_start) sub r11,r11,r8 /* bss size */ addi r11,r11,7 /* round up to an even double word */ rldicl. r11,r11,61,3 /* shift right by 3 */ @@ -1458,17 +1459,17 @@ _STATIC(__start_initialization_iSeries) 3: stdu r0,8(r8) bdnz 3b 4: - LOADADDR(r1,init_thread_union) + LOAD_REG_IMMEDIATE(r1,init_thread_union) addi r1,r1,THREAD_SIZE li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) - LOADADDR(r3,cpu_specs) - LOADADDR(r4,cur_cpu_spec) + LOAD_REG_IMMEDIATE(r3,cpu_specs) + LOAD_REG_IMMEDIATE(r4,cur_cpu_spec) li r5,0 bl .identify_cpu - LOADADDR(r2,__toc_start) + LOAD_REG_IMMEDIATE(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 @@ -1528,7 +1529,7 @@ _GLOBAL(__start_initialization_multiplatform) li r24,0 /* Switch off MMU if not already */ - LOADADDR(r4, .__after_prom_start - KERNELBASE) + LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE) add r4,r4,r30 bl .__mmu_off b .__after_prom_start @@ -1548,7 +1549,7 @@ _STATIC(__boot_from_prom) /* put a relocation offset into r3 */ bl .reloc_offset - LOADADDR(r2,__toc_start) + LOAD_REG_IMMEDIATE(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 @@ -1588,9 +1589,9 @@ _STATIC(__after_prom_start) */ bl .reloc_offset mr r26,r3 - SET_REG_TO_CONST(r27,KERNELBASE) + LOAD_REG_IMMEDIATE(r27, KERNELBASE) - LOADADDR(r3, PHYSICAL_START) /* target addr */ + LOAD_REG_IMMEDIATE(r3, PHYSICAL_START) /* target addr */ // XXX FIXME: Use phys returned by OF (r30) add r4,r27,r26 /* source addr */ @@ -1598,7 +1599,7 @@ _STATIC(__after_prom_start) /* i.e. where we are running */ /* the source addr */ - LOADADDR(r5,copy_to_here) /* # bytes of memory to copy */ + LOAD_REG_IMMEDIATE(r5,copy_to_here) /* # bytes of memory to copy */ sub r5,r5,r27 li r6,0x100 /* Start offset, the first 0x100 */ @@ -1608,11 +1609,11 @@ _STATIC(__after_prom_start) /* this includes the code being */ /* executed here. */ - LOADADDR(r0, 4f) /* Jump to the copy of this code */ + LOAD_REG_IMMEDIATE(r0, 4f) /* Jump to the copy of this code */ mtctr r0 /* that we just made/relocated */ bctr -4: LOADADDR(r5,klimit) +4: LOAD_REG_IMMEDIATE(r5,klimit) add r5,r5,r26 ld r5,0(r5) /* get the value of klimit */ sub r5,r5,r27 @@ -1694,7 +1695,7 @@ _GLOBAL(pmac_secondary_start) mtmsrd r3 /* RI on */ /* Set up a paca value for this processor. */ - LOADADDR(r4, paca) /* Get base vaddr of paca array */ + LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */ mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ add r13,r13,r4 /* for this processor. */ mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ @@ -1731,7 +1732,7 @@ _GLOBAL(__secondary_start) bl .early_setup_secondary /* Initialize the kernel stack. Just a repeat for iSeries. */ - LOADADDR(r3,current_set) + LOAD_REG_ADDR(r3, current_set) sldi r28,r24,3 /* get current_set[cpu#] */ ldx r1,r3,r28 addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD @@ -1742,8 +1743,8 @@ _GLOBAL(__secondary_start) mtlr r7 /* enable MMU and jump to start_secondary */ - LOADADDR(r3,.start_secondary_prolog) - SET_REG_TO_CONST(r4, MSR_KERNEL) + LOAD_REG_ADDR(r3, .start_secondary_prolog) + LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) #ifdef DO_SOFT_DISABLE ori r4,r4,MSR_EE #endif @@ -1792,8 +1793,8 @@ _STATIC(start_here_multiplatform) * be detached from the kernel completely. Besides, we need * to clear it now for kexec-style entry. */ - LOADADDR(r11,__bss_stop) - LOADADDR(r8,__bss_start) + LOAD_REG_IMMEDIATE(r11,__bss_stop) + LOAD_REG_IMMEDIATE(r8,__bss_start) sub r11,r11,r8 /* bss size */ addi r11,r11,7 /* round up to an even double word */ rldicl. r11,r11,61,3 /* shift right by 3 */ @@ -1831,7 +1832,7 @@ _STATIC(start_here_multiplatform) /* up the htab. This is done because we have relocated the */ /* kernel but are still running in real mode. */ - LOADADDR(r3,init_thread_union) + LOAD_REG_IMMEDIATE(r3,init_thread_union) add r3,r3,r26 /* set up a stack pointer (physical address) */ @@ -1840,14 +1841,14 @@ _STATIC(start_here_multiplatform) stdu r0,-STACK_FRAME_OVERHEAD(r1) /* set up the TOC (physical address) */ - LOADADDR(r2,__toc_start) + LOAD_REG_IMMEDIATE(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 add r2,r2,r26 - LOADADDR(r3,cpu_specs) + LOAD_REG_IMMEDIATE(r3, cpu_specs) add r3,r3,r26 - LOADADDR(r4,cur_cpu_spec) + LOAD_REG_IMMEDIATE(r4,cur_cpu_spec) add r4,r4,r26 mr r5,r26 bl .identify_cpu @@ -1863,11 +1864,11 @@ _STATIC(start_here_multiplatform) * nowhere it can be initialized differently before we reach this * code */ - LOADADDR(r27, boot_cpuid) + LOAD_REG_IMMEDIATE(r27, boot_cpuid) add r27,r27,r26 lwz r27,0(r27) - LOADADDR(r24, paca) /* Get base vaddr of paca array */ + LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */ mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */ add r13,r13,r24 /* for this processor. */ add r13,r13,r26 /* convert to physical addr */ @@ -1880,8 +1881,8 @@ _STATIC(start_here_multiplatform) mr r3,r31 bl .early_setup - LOADADDR(r3,.start_here_common) - SET_REG_TO_CONST(r4, MSR_KERNEL) + LOAD_REG_IMMEDIATE(r3, .start_here_common) + LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) mtspr SPRN_SRR0,r3 mtspr SPRN_SRR1,r4 rfid @@ -1895,7 +1896,7 @@ _STATIC(start_here_common) /* The following code sets up the SP and TOC now that we are */ /* running with translation enabled. */ - LOADADDR(r3,init_thread_union) + LOAD_REG_IMMEDIATE(r3,init_thread_union) /* set up the stack */ addi r1,r3,THREAD_SIZE @@ -1908,16 +1909,16 @@ _STATIC(start_here_common) li r3,0 bl .do_cpu_ftr_fixups - LOADADDR(r26, boot_cpuid) + LOAD_REG_IMMEDIATE(r26, boot_cpuid) lwz r26,0(r26) - LOADADDR(r24, paca) /* Get base vaddr of paca array */ + LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */ mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */ add r13,r13,r24 /* for this processor. */ mtspr SPRN_SPRG3,r13 /* ptr to current */ - LOADADDR(r4,init_task) + LOAD_REG_IMMEDIATE(r4, init_task) std r4,PACACURRENT(r13) /* Load the TOC */ @@ -1940,7 +1941,7 @@ _STATIC(start_here_common) _GLOBAL(hmt_init) #ifdef CONFIG_HMT - LOADADDR(r5, hmt_thread_data) + LOAD_REG_IMMEDIATE(r5, hmt_thread_data) mfspr r7,SPRN_PVR srwi r7,r7,16 cmpwi r7,0x34 /* Pulsar */ @@ -1961,7 +1962,7 @@ _GLOBAL(hmt_init) b 101f __hmt_secondary_hold: - LOADADDR(r5, hmt_thread_data) + LOAD_REG_IMMEDIATE(r5, hmt_thread_data) clrldi r5,r5,4 li r7,0 mfspr r6,SPRN_PIR @@ -1989,7 +1990,7 @@ __hmt_secondary_hold: #ifdef CONFIG_HMT _GLOBAL(hmt_start_secondary) - LOADADDR(r4,__hmt_secondary_hold) + LOAD_REG_IMMEDIATE(r4,__hmt_secondary_hold) clrldi r4,r4,4 mtspr SPRN_NIADORM, r4 mfspr r4, SPRN_MSRDORM diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S index 1494e2f..c16b4af 100644 --- a/arch/powerpc/kernel/idle_power4.S +++ b/arch/powerpc/kernel/idle_power4.S @@ -38,14 +38,14 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) /* We must dynamically check for the NAP feature as it * can be cleared by CPU init after the fixups are done */ - LOADBASE(r3,cur_cpu_spec) - ld r4,OFF(cur_cpu_spec)(r3) + LOAD_REG_ADDRBASE(r3,cur_cpu_spec) + ld r4,ADDROFF(cur_cpu_spec)(r3) ld r4,CPU_SPEC_FEATURES(r4) andi. r0,r4,CPU_FTR_CAN_NAP beqlr /* Now check if user or arch enabled NAP mode */ - LOADBASE(r3,powersave_nap) - lwz r4,OFF(powersave_nap)(r3) + LOAD_REG_ADDRBASE(r3,powersave_nap) + lwz r4,ADDROFF(powersave_nap)(r3) cmpwi 0,r4,0 beqlr diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 01d0d97..be98202 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -68,7 +68,7 @@ _GLOBAL(reloc_offset) mflr r0 bl 1f 1: mflr r3 - LOADADDR(r4,1b) + LOAD_REG_IMMEDIATE(r4,1b) subf r3,r4,r3 mtlr r0 blr @@ -80,7 +80,7 @@ _GLOBAL(add_reloc_offset) mflr r0 bl 1f 1: mflr r5 - LOADADDR(r4,1b) + LOAD_REG_IMMEDIATE(r4,1b) subf r5,r4,r5 add r3,r3,r5 mtlr r0 diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index ae48a00..2778cce 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -39,7 +39,7 @@ _GLOBAL(reloc_offset) mflr r0 bl 1f 1: mflr r3 - LOADADDR(r4,1b) + LOAD_REG_IMMEDIATE(r4,1b) subf r3,r4,r3 mtlr r0 blr @@ -51,7 +51,7 @@ _GLOBAL(add_reloc_offset) mflr r0 bl 1f 1: mflr r5 - LOADADDR(r4,1b) + LOAD_REG_IMMEDIATE(r4,1b) subf r5,r4,r5 add r3,r3,r5 mtlr r0 @@ -498,15 +498,15 @@ _GLOBAL(identify_cpu) */ _GLOBAL(do_cpu_ftr_fixups) /* Get CPU 0 features */ - LOADADDR(r6,cur_cpu_spec) + LOAD_REG_IMMEDIATE(r6,cur_cpu_spec) sub r6,r6,r3 ld r4,0(r6) sub r4,r4,r3 ld r4,CPU_SPEC_FEATURES(r4) /* Get the fixup table */ - LOADADDR(r6,__start___ftr_fixup) + LOAD_REG_IMMEDIATE(r6,__start___ftr_fixup) sub r6,r6,r3 - LOADADDR(r7,__stop___ftr_fixup) + LOAD_REG_IMMEDIATE(r7,__stop___ftr_fixup) sub r7,r7,r3 /* Do the fixup */ 1: cmpld r6,r7 diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h index 0dc798d..ab8688d 100644 --- a/include/asm-powerpc/ppc_asm.h +++ b/include/asm-powerpc/ppc_asm.h @@ -156,52 +156,56 @@ n: #endif /* - * LOADADDR( rn, name ) - * loads the address of 'name' into 'rn' + * LOAD_REG_IMMEDIATE(rn, expr) + * Loads the value of the constant expression 'expr' into register 'rn' + * using immediate instructions only. Use this when it's important not + * to reference other data (i.e. on ppc64 when the TOC pointer is not + * valid). * - * LOADBASE( rn, name ) - * loads the address (possibly without the low 16 bits) of 'name' into 'rn' - * suitable for base+disp addressing + * LOAD_REG_ADDR(rn, name) + * Loads the address of label 'name' into register 'rn'. Use this when + * you don't particularly need immediate instructions only, but you need + * the whole address in one register (e.g. it's a structure address and + * you want to access various offsets within it). On ppc32 this is + * identical to LOAD_REG_IMMEDIATE. + * + * LOAD_REG_ADDRBASE(rn, name) + * ADDROFF(name) + * LOAD_REG_ADDRBASE loads part of the address of label 'name' into + * register 'rn'. ADDROFF(name) returns the remainder of the address as + * a constant expression. ADDROFF(name) is a signed expression < 16 bits + * in size, so is suitable for use directly as an offset in load and store + * instructions. Use this when loading/storing a single word or less as: + * LOAD_REG_ADDRBASE(rX, name) + * ld rY,ADDROFF(name)(rX) */ #ifdef __powerpc64__ -#define LOADADDR(rn,name) \ - lis rn,name##@highest; \ - ori rn,rn,name##@higher; \ - rldicr rn,rn,32,31; \ - oris rn,rn,name##@h; \ - ori rn,rn,name##@l - -#define LOADBASE(rn,name) \ - ld rn,name@got(r2) - -#define OFF(name) 0 - -#define SET_REG_TO_CONST(reg, value) \ - lis reg,(((value)>>48)&0xFFFF); \ - ori reg,reg,(((value)>>32)&0xFFFF); \ - rldicr reg,reg,32,31; \ - oris reg,reg,(((value)>>16)&0xFFFF); \ - ori reg,reg,((value)&0xFFFF); - -#define SET_REG_TO_LABEL(reg, label) \ - lis reg,(label)@highest; \ - ori reg,reg,(label)@higher; \ - rldicr reg,reg,32,31; \ - oris reg,reg,(label)@h; \ - ori reg,reg,(label)@l; +#define LOAD_REG_IMMEDIATE(reg,expr) \ + lis (reg),(expr)@highest; \ + ori (reg),(reg),(expr)@higher; \ + rldicr (reg),(reg),32,31; \ + oris (reg),(reg),(expr)@h; \ + ori (reg),(reg),(expr)@l; + +#define LOAD_REG_ADDR(reg,name) \ + ld (reg),name@got(r2) + +#define LOAD_REG_ADDRBASE(reg,name) LOAD_REG_ADDR(reg,name) +#define ADDROFF(name) 0 /* offsets for stack frame layout */ #define LRSAVE 16 #else /* 32-bit */ -#define LOADADDR(rn,name) \ - lis rn,name@ha; \ - addi rn,rn,name@l -#define LOADBASE(rn,name) \ - lis rn,name@ha +#define LOAD_REG_IMMEDIATE(reg,expr) \ + lis (reg),(expr)@ha; \ + addi (reg),(reg),(expr)@l; + +#define LOAD_REG_ADDR(reg,name) LOAD_REG_IMMEDIATE(reg, name) -#define OFF(name) name@l +#define LOAD_REG_ADDRBASE(reg, name) lis (reg),name@ha +#define ADDROFF(name) name@l /* offsets for stack frame layout */ #define LRSAVE 4 -- cgit v0.10.2 From 3356bb9f7ba378a6e2709f9df95f4ea52111f4df Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 13 Jan 2006 10:26:42 +1100 Subject: [PATCH] powerpc: Remove lppaca structure from the PACA At present the lppaca - the structure shared with the iSeries hypervisor and phyp - is contained within the PACA, our own low-level per-cpu structure. This doesn't have to be so, the patch below removes it, making a separate array of lppaca structures. This saves approximately 500*NR_CPUS bytes of image size and kernel memory, because we don't need aligning gap between the Linux and hypervisor portions of every PACA. On the other hand it means an extra level of dereference in many accesses to the lppaca. The patch also gets rid of several places where we assign the paca address to a local variable for no particular reason. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 56399c5..840aad4 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -135,7 +135,7 @@ int main(void) DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb)); DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); - DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca)); + DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr)); DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 4ba81e1..5420363 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -511,7 +511,8 @@ restore: cmpdi 0,r5,0 beq 4f /* Check for pending interrupts (iSeries) */ - ld r3,PACALPPACA+LPPACAANYINT(r13) + ld r3,PACALPPACAPTR(r13) + ld r3,LPPACAANYINT(r3) cmpdi r3,0 beq+ 4f /* skip do_IRQ if no interrupts */ diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index b3718f3..3082684 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -255,8 +255,9 @@ exception_marker: #define EXCEPTION_PROLOG_ISERIES_2 \ mfmsr r10; \ - ld r11,PACALPPACA+LPPACASRR0(r13); \ - ld r12,PACALPPACA+LPPACASRR1(r13); \ + ld r12,PACALPPACAPTR(r13); \ + ld r11,LPPACASRR0(r12); \ + ld r12,LPPACASRR1(r12); \ ori r10,r10,MSR_RI; \ mtmsrd r10,1 @@ -635,7 +636,8 @@ data_access_slb_iSeries: std r12,PACA_EXSLB+EX_R12(r13) mfspr r10,SPRN_SPRG1 std r10,PACA_EXSLB+EX_R13(r13) - ld r12,PACALPPACA+LPPACASRR1(r13); + ld r12,PACALPPACAPTR(r13) + ld r12,LPPACASRR1(r12) b .slb_miss_realmode STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) @@ -645,7 +647,8 @@ instruction_access_slb_iSeries: mtspr SPRN_SPRG1,r13 /* save r13 */ mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ std r3,PACA_EXSLB+EX_R3(r13) - ld r3,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ + ld r3,PACALPPACAPTR(r13) + ld r3,LPPACASRR0(r3) /* get SRR0 value */ std r9,PACA_EXSLB+EX_R9(r13) mfcr r9 #ifdef __DISABLED__ @@ -657,7 +660,8 @@ instruction_access_slb_iSeries: std r12,PACA_EXSLB+EX_R12(r13) mfspr r10,SPRN_SPRG1 std r10,PACA_EXSLB+EX_R13(r13) - ld r12,PACALPPACA+LPPACASRR1(r13); + ld r12,PACALPPACAPTR(r13) + ld r12,LPPACASRR1(r12) b .slb_miss_realmode #ifdef __DISABLED__ @@ -746,7 +750,8 @@ iSeries_secondary_smp_loop: .globl decrementer_iSeries_masked decrementer_iSeries_masked: li r11,1 - stb r11,PACALPPACA+LPPACADECRINT(r13) + ld r12,PACALPPACAPTR(r13) + stb r11,LPPACADECRINT(r12) LOAD_REG_ADDRBASE(r12,tb_ticks_per_jiffy) lwz r12,ADDROFF(tb_ticks_per_jiffy)(r12) mtspr SPRN_DEC,r12 @@ -755,8 +760,9 @@ decrementer_iSeries_masked: .globl hardware_interrupt_iSeries_masked hardware_interrupt_iSeries_masked: mtcrf 0x80,r9 /* Restore regs */ - ld r11,PACALPPACA+LPPACASRR0(r13) - ld r12,PACALPPACA+LPPACASRR1(r13) + ld r12,PACALPPACAPTR(r13) + ld r11,LPPACASRR0(r12) + ld r12,LPPACASRR1(r12) mtspr SPRN_SRR0,r11 mtspr SPRN_SRR1,r12 ld r9,PACA_EXGEN+EX_R9(r13) @@ -995,7 +1001,8 @@ _GLOBAL(slb_miss_realmode) ld r3,PACA_EXSLB+EX_R3(r13) lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ #ifdef CONFIG_PPC_ISERIES - ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ + ld r11,PACALPPACAPTR(r13) + ld r11,LPPACASRR0(r11) /* get SRR0 value */ #endif /* CONFIG_PPC_ISERIES */ mtlr r10 diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 5651032..d1fffce 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -238,14 +238,10 @@ void do_IRQ(struct pt_regs *regs) irq_exit(); #ifdef CONFIG_PPC_ISERIES - { - struct paca_struct *lpaca = get_paca(); - - if (lpaca->lppaca.int_dword.fields.decr_int) { - lpaca->lppaca.int_dword.fields.decr_int = 0; - /* Signal a fake decrementer interrupt */ - timer_interrupt(regs); - } + if (get_lppaca()->int_dword.fields.decr_int) { + get_lppaca()->int_dword.fields.decr_int = 0; + /* Signal a fake decrementer interrupt */ + timer_interrupt(regs); } #endif } diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 9dda16c..1ae96a8 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c @@ -55,15 +55,13 @@ static unsigned long get_purr(void) { unsigned long sum_purr = 0; int cpu; - struct paca_struct *lpaca; for_each_cpu(cpu) { - lpaca = paca + cpu; - sum_purr += lpaca->lppaca.emulated_time_base; + sum_purr += lppaca[cpu].emulated_time_base; #ifdef PURR_DEBUG printk(KERN_INFO "get_purr for cpu (%d) has value (%ld) \n", - cpu, lpaca->lppaca.emulated_time_base); + cpu, lppaca[cpu].emulated_time_base); #endif } return sum_purr; @@ -79,12 +77,11 @@ static int lparcfg_data(struct seq_file *m, void *v) unsigned long pool_id, lp_index; int shared, entitled_capacity, max_entitled_capacity; int processors, max_processors; - struct paca_struct *lpaca = get_paca(); unsigned long purr = get_purr(); seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS); - shared = (int)(lpaca->lppaca_ptr->shared_proc); + shared = (int)(get_lppaca()->shared_proc); seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n", e2a(xItExtVpdPanel.mfgID[2]), e2a(xItExtVpdPanel.mfgID[3]), @@ -402,7 +399,7 @@ static int lparcfg_data(struct seq_file *m, void *v) (h_resource >> 0 * 8) & 0xffff); /* pool related entries are apropriate for shared configs */ - if (paca[0].lppaca.shared_proc) { + if (lppaca[0].shared_proc) { h_pic(&pool_idle_time, &pool_procs); @@ -451,7 +448,7 @@ static int lparcfg_data(struct seq_file *m, void *v) seq_printf(m, "partition_potential_processors=%d\n", partition_potential_processors); - seq_printf(m, "shared_processor_mode=%d\n", paca[0].lppaca.shared_proc); + seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc); return 0; } diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index 999bdd8..5d1b708 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c @@ -25,6 +25,28 @@ * field correctly */ extern unsigned long __toc_start; +/* + * iSeries structure which the hypervisor knows about - this structure + * should not cross a page boundary. The vpa_init/register_vpa call + * is now known to fail if the lppaca structure crosses a page + * boundary. The lppaca is also used on POWER5 pSeries boxes. The + * lppaca is 640 bytes long, and cannot readily change since the + * hypervisor knows its layout, so a 1kB alignment will suffice to + * ensure that it doesn't cross a page boundary. + */ +struct lppaca lppaca[] = { + [0 ... (NR_CPUS-1)] = { + .desc = 0xd397d781, /* "LpPa" */ + .size = sizeof(struct lppaca), + .dyn_proc_status = 2, + .decr_val = 0x00ff0000, + .fpregs_in_use = 1, + .end_of_quantum = 0xfffffffffffffffful, + .slb_count = 64, + .vmxregs_in_use = 0, + }, +}; + /* The Paca is an array with one entry per processor. Each contains an * lppaca, which contains the information shared between the * hypervisor and Linux. @@ -35,27 +57,17 @@ extern unsigned long __toc_start; * processor (not thread). */ #define PACA_INIT_COMMON(number, start, asrr, asrv) \ + .lppaca_ptr = &lppaca[number], \ .lock_token = 0x8000, \ .paca_index = (number), /* Paca Index */ \ .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \ .stab_real = (asrr), /* Real pointer to segment table */ \ .stab_addr = (asrv), /* Virt pointer to segment table */ \ .cpu_start = (start), /* Processor start */ \ - .hw_cpu_id = 0xffff, \ - .lppaca = { \ - .desc = 0xd397d781, /* "LpPa" */ \ - .size = sizeof(struct lppaca), \ - .dyn_proc_status = 2, \ - .decr_val = 0x00ff0000, \ - .fpregs_in_use = 1, \ - .end_of_quantum = 0xfffffffffffffffful, \ - .slb_count = 64, \ - .vmxregs_in_use = 0, \ - }, \ + .hw_cpu_id = 0xffff, #ifdef CONFIG_PPC_ISERIES #define PACA_INIT_ISERIES(number) \ - .lppaca_ptr = &paca[number].lppaca, \ .reg_save_ptr = &iseries_reg_save[number], #define PACA_INIT(number) \ diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 56f50e9..c4a294d 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -431,7 +431,7 @@ void timer_interrupt(struct pt_regs * regs) profile_tick(CPU_PROFILING, regs); #ifdef CONFIG_PPC_ISERIES - get_paca()->lppaca.int_dword.fields.decr_int = 0; + get_lppaca()->int_dword.fields.decr_int = 0; #endif while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu))) diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c index 35bd03c..8362fa2 100644 --- a/arch/powerpc/lib/locks.c +++ b/arch/powerpc/lib/locks.c @@ -28,15 +28,13 @@ void __spin_yield(raw_spinlock_t *lock) { unsigned int lock_value, holder_cpu, yield_count; - struct paca_struct *holder_paca; lock_value = lock->slock; if (lock_value == 0) return; holder_cpu = lock_value & 0xffff; BUG_ON(holder_cpu >= NR_CPUS); - holder_paca = &paca[holder_cpu]; - yield_count = holder_paca->lppaca.yield_count; + yield_count = lppaca[holder_cpu].yield_count; if ((yield_count & 1) == 0) return; /* virtual cpu is currently running */ rmb(); @@ -60,15 +58,13 @@ void __rw_yield(raw_rwlock_t *rw) { int lock_value; unsigned int holder_cpu, yield_count; - struct paca_struct *holder_paca; lock_value = rw->lock; if (lock_value >= 0) return; /* no write lock at present */ holder_cpu = lock_value & 0xffff; BUG_ON(holder_cpu >= NR_CPUS); - holder_paca = &paca[holder_cpu]; - yield_count = holder_paca->lppaca.yield_count; + yield_count = lppaca[holder_cpu].yield_count; if ((yield_count & 1) == 0) return; /* virtual cpu is currently running */ rmb(); diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 83442ea..be3fbfc 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -334,14 +334,12 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus, */ int iSeries_get_irq(struct pt_regs *regs) { - struct paca_struct *lpaca; /* -2 means ignore this interrupt */ int irq = -2; - lpaca = get_paca(); #ifdef CONFIG_SMP - if (lpaca->lppaca.int_dword.fields.ipi_cnt) { - lpaca->lppaca.int_dword.fields.ipi_cnt = 0; + if (get_lppaca()->int_dword.fields.ipi_cnt) { + get_lppaca()->int_dword.fields.ipi_cnt = 0; iSeries_smp_message_recv(regs); } #endif /* CONFIG_SMP */ diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S index dfe7aa1..7641fc7 100644 --- a/arch/powerpc/platforms/iseries/misc.S +++ b/arch/powerpc/platforms/iseries/misc.S @@ -44,7 +44,8 @@ _GLOBAL(local_irq_restore) /* Check pending interrupts */ /* A decrementer, IPI or PMC interrupt may have occurred * while we were in the hypervisor (which enables) */ - ld r4,PACALPPACA+LPPACAANYINT(r13) + ld r4,PACALPPACAPTR(r13) + ld r4,LPPACAANYINT(r4) cmpdi r4,0 beqlr diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index c6bbe5c..3f87901 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -538,7 +538,7 @@ static unsigned long __init build_iSeries_Memory_Map(void) */ static void __init iSeries_setup_arch(void) { - if (get_paca()->lppaca.shared_proc) { + if (get_lppaca()->shared_proc) { ppc_md.idle_loop = iseries_shared_idle; printk(KERN_INFO "Using shared processor idle loop\n"); } else { @@ -647,7 +647,7 @@ static void yield_shared_processor(void) * The decrementer stops during the yield. Force a fake decrementer * here and let the timer_interrupt code sort out the actual time. */ - get_paca()->lppaca.int_dword.fields.decr_int = 1; + get_lppaca()->int_dword.fields.decr_int = 1; process_iSeries_events(); } @@ -883,7 +883,7 @@ void dt_cpus(struct iseries_flat_dt *dt) pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); for (i = 0; i < NR_CPUS; i++) { - if (paca[i].lppaca.dyn_proc_status >= 2) + if (lppaca[i].dyn_proc_status >= 2) continue; snprintf(p, 32 - (p - buf), "@%d", i); @@ -891,7 +891,7 @@ void dt_cpus(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "cpu"); - index = paca[i].lppaca.dyn_hv_phys_proc_index; + index = lppaca[i].dyn_hv_phys_proc_index; d = &xIoHriProcessorVpd[index]; dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c index fcb094e..6f9d407 100644 --- a/arch/powerpc/platforms/iseries/smp.c +++ b/arch/powerpc/platforms/iseries/smp.c @@ -91,7 +91,7 @@ static void smp_iSeries_kick_cpu(int nr) BUG_ON((nr < 0) || (nr >= NR_CPUS)); /* Verify that our partition has a processor nr */ - if (paca[nr].lppaca.dyn_proc_status >= 2) + if (lppaca[nr].dyn_proc_status >= 2) return; /* The processor is currently spinning, waiting diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 1fe445a..8952528 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -254,11 +254,11 @@ out: void vpa_init(int cpu) { int hwcpu = get_hard_smp_processor_id(cpu); - unsigned long vpa = __pa(&paca[cpu].lppaca); + unsigned long vpa = __pa(&lppaca[cpu]); long ret; if (cpu_has_feature(CPU_FTR_ALTIVEC)) - paca[cpu].lppaca.vmxregs_in_use = 1; + lppaca[cpu].vmxregs_in_use = 1; ret = register_vpa(hwcpu, vpa); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 68b7f08..da6ceba 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -190,7 +190,7 @@ static void pseries_lpar_enable_pmcs(void) /* instruct hypervisor to maintain PMCs */ if (firmware_has_feature(FW_FEATURE_SPLPAR)) - get_paca()->lppaca.pmcregs_in_use = 1; + get_lppaca()->pmcregs_in_use = 1; } static void __init pSeries_setup_arch(void) @@ -234,7 +234,7 @@ static void __init pSeries_setup_arch(void) /* Choose an idle loop */ if (firmware_has_feature(FW_FEATURE_SPLPAR)) { vpa_init(boot_cpuid); - if (get_paca()->lppaca.shared_proc) { + if (get_lppaca()->shared_proc) { printk(KERN_INFO "Using shared processor idle loop\n"); ppc_md.idle_loop = pseries_shared_idle; } else { @@ -444,10 +444,10 @@ DECLARE_PER_CPU(unsigned long, smt_snooze_delay); static inline void dedicated_idle_sleep(unsigned int cpu) { - struct paca_struct *ppaca = &paca[cpu ^ 1]; + struct lppaca *plppaca = &lppaca[cpu ^ 1]; /* Only sleep if the other thread is not idle */ - if (!(ppaca->lppaca.idle)) { + if (!(plppaca->idle)) { local_irq_disable(); /* @@ -480,7 +480,6 @@ static inline void dedicated_idle_sleep(unsigned int cpu) static void pseries_dedicated_idle(void) { - struct paca_struct *lpaca = get_paca(); unsigned int cpu = smp_processor_id(); unsigned long start_snooze; unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay); @@ -491,7 +490,7 @@ static void pseries_dedicated_idle(void) * Indicate to the HV that we are idle. Now would be * a good time to find other work to dispatch. */ - lpaca->lppaca.idle = 1; + get_lppaca()->idle = 1; if (!need_resched()) { start_snooze = get_tb() + @@ -518,7 +517,7 @@ static void pseries_dedicated_idle(void) HMT_medium(); } - lpaca->lppaca.idle = 0; + get_lppaca()->idle = 0; ppc64_runlatch_on(); preempt_enable_no_resched(); @@ -532,7 +531,6 @@ static void pseries_dedicated_idle(void) static void pseries_shared_idle(void) { - struct paca_struct *lpaca = get_paca(); unsigned int cpu = smp_processor_id(); while (1) { @@ -540,7 +538,7 @@ static void pseries_shared_idle(void) * Indicate to the HV that we are idle. Now would be * a good time to find other work to dispatch. */ - lpaca->lppaca.idle = 1; + get_lppaca()->idle = 1; while (!need_resched() && !cpu_is_offline(cpu)) { local_irq_disable(); @@ -564,7 +562,7 @@ static void pseries_shared_idle(void) HMT_medium(); } - lpaca->lppaca.idle = 0; + get_lppaca()->idle = 0; ppc64_runlatch_on(); preempt_enable_no_resched(); @@ -588,7 +586,7 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) { /* Don't risk a hypervisor call if we're crashing */ if (!crash_shutdown) { - unsigned long vpa = __pa(&get_paca()->lppaca); + unsigned long vpa = __pa(get_lppaca()); if (unregister_vpa(hard_smp_processor_id(), vpa)) { printk("VPA deregistration of cpu %u (hw_cpu_id %d) " diff --git a/include/asm-powerpc/lppaca.h b/include/asm-powerpc/lppaca.h index ff82ea7..cd9f11f 100644 --- a/include/asm-powerpc/lppaca.h +++ b/include/asm-powerpc/lppaca.h @@ -29,7 +29,9 @@ //---------------------------------------------------------------------------- #include -struct lppaca { +/* The Hypervisor barfs if the lppaca crosses a page boundary. A 1k + * alignment is sufficient to prevent this */ +struct __attribute__((__aligned__(0x400))) lppaca { //============================================================================= // CACHE_LINE_1 0x0000 - 0x007F Contains read-only data // NOTE: The xDynXyz fields are fields that will be dynamically changed by @@ -129,5 +131,7 @@ struct lppaca { u8 pmc_save_area[256]; // PMC interrupt Area x00-xFF }; +extern struct lppaca lppaca[]; + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_LPPACA_H */ diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index a64b4d4..c9add8f 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h @@ -23,6 +23,7 @@ register struct paca_struct *local_paca asm("r13"); #define get_paca() local_paca +#define get_lppaca() (get_paca()->lppaca_ptr) struct task_struct; @@ -95,19 +96,6 @@ struct paca_struct { u64 saved_r1; /* r1 save for RTAS calls */ u64 saved_msr; /* MSR saved here by enter_rtas */ u8 proc_enabled; /* irq soft-enable flag */ - - /* - * iSeries structure which the hypervisor knows about - - * this structure should not cross a page boundary. - * The vpa_init/register_vpa call is now known to fail if the - * lppaca structure crosses a page boundary. - * The lppaca is also used on POWER5 pSeries boxes. - * The lppaca is 640 bytes long, and cannot readily change - * since the hypervisor knows its layout, so a 1kB - * alignment will suffice to ensure that it doesn't - * cross a page boundary. - */ - struct lppaca lppaca __attribute__((__aligned__(0x400))); }; extern struct paca_struct paca[]; diff --git a/include/asm-powerpc/spinlock.h b/include/asm-powerpc/spinlock.h index 7549009..26b8744 100644 --- a/include/asm-powerpc/spinlock.h +++ b/include/asm-powerpc/spinlock.h @@ -80,7 +80,7 @@ static int __inline__ __raw_spin_trylock(raw_spinlock_t *lock) #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) /* We only yield to the hypervisor if we are in shared processor mode */ -#define SHARED_PROCESSOR (get_paca()->lppaca.shared_proc) +#define SHARED_PROCESSOR (get_lppaca()->shared_proc) extern void __spin_yield(raw_spinlock_t *lock); extern void __rw_yield(raw_rwlock_t *lock); #else /* SPLPAR || ISERIES */ diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h index d9b86a1..baddc9a 100644 --- a/include/asm-powerpc/time.h +++ b/include/asm-powerpc/time.h @@ -175,11 +175,10 @@ static inline void set_dec(int val) set_dec_cpu6(val); #else #ifdef CONFIG_PPC_ISERIES - struct paca_struct *lpaca = get_paca(); int cur_dec; - if (lpaca->lppaca.shared_proc) { - lpaca->lppaca.virtual_decr = val; + if (get_lppaca()->shared_proc) { + get_lppaca()->virtual_decr = val; cur_dec = get_dec(); if (cur_dec > val) HvCall_setVirtualDecr(); -- cgit v0.10.2 From 144b9c135b963bcb7f242c7b83bff930620d3161 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 13 Jan 2006 15:37:17 +1100 Subject: [PATCH] powerpc: use lwsync in atomics, bitops, lock functions eieio is only a store - store ordering. When used to order an unlock operation loads may leak out of the critical region. This is potentially buggy, one example is if a user wants to atomically read a couple of values. We can solve this with an lwsync which orders everything except store - load. I removed the (now unused) EIEIO_ON_SMP macros and the c versions isync_on_smp and eieio_on_smp now we dont use them. I also removed some old comments that were used to identify inline spinlocks in assembly, they dont make sense now our locks are out of line. Another interesting thing was that read_unlock was using an eieio even though the rest of the spinlock code had already been converted to use lwsync. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h index 248f9ae..9ce51ba 100644 --- a/include/asm-powerpc/atomic.h +++ b/include/asm-powerpc/atomic.h @@ -36,7 +36,7 @@ static __inline__ int atomic_add_return(int a, atomic_t *v) int t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: lwarx %0,0,%2 # atomic_add_return\n\ add %0,%1,%0\n" PPC405_ERR77(0,%2) @@ -72,7 +72,7 @@ static __inline__ int atomic_sub_return(int a, atomic_t *v) int t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: lwarx %0,0,%2 # atomic_sub_return\n\ subf %0,%1,%0\n" PPC405_ERR77(0,%2) @@ -106,7 +106,7 @@ static __inline__ int atomic_inc_return(atomic_t *v) int t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: lwarx %0,0,%1 # atomic_inc_return\n\ addic %0,%0,1\n" PPC405_ERR77(0,%1) @@ -150,7 +150,7 @@ static __inline__ int atomic_dec_return(atomic_t *v) int t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: lwarx %0,0,%1 # atomic_dec_return\n\ addic %0,%0,-1\n" PPC405_ERR77(0,%1) @@ -204,7 +204,7 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v) int t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: lwarx %0,0,%1 # atomic_dec_if_positive\n\ addic. %0,%0,-1\n\ blt- 2f\n" @@ -253,7 +253,7 @@ static __inline__ long atomic64_add_return(long a, atomic64_t *v) long t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: ldarx %0,0,%2 # atomic64_add_return\n\ add %0,%1,%0\n\ stdcx. %0,0,%2 \n\ @@ -287,7 +287,7 @@ static __inline__ long atomic64_sub_return(long a, atomic64_t *v) long t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: ldarx %0,0,%2 # atomic64_sub_return\n\ subf %0,%1,%0\n\ stdcx. %0,0,%2 \n\ @@ -319,7 +319,7 @@ static __inline__ long atomic64_inc_return(atomic64_t *v) long t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: ldarx %0,0,%1 # atomic64_inc_return\n\ addic %0,%0,1\n\ stdcx. %0,0,%1 \n\ @@ -361,7 +361,7 @@ static __inline__ long atomic64_dec_return(atomic64_t *v) long t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: ldarx %0,0,%1 # atomic64_dec_return\n\ addic %0,%0,-1\n\ stdcx. %0,0,%1\n\ @@ -386,7 +386,7 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v) long t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: ldarx %0,0,%1 # atomic64_dec_if_positive\n\ addic. %0,%0,-1\n\ blt- 2f\n\ diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h index 1996eaa..bf6941a 100644 --- a/include/asm-powerpc/bitops.h +++ b/include/asm-powerpc/bitops.h @@ -112,7 +112,7 @@ static __inline__ int test_and_set_bit(unsigned long nr, unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1:" PPC_LLARX "%0,0,%3 # test_and_set_bit\n" "or %1,%0,%2 \n" PPC405_ERR77(0,%3) @@ -134,7 +134,7 @@ static __inline__ int test_and_clear_bit(unsigned long nr, unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1:" PPC_LLARX "%0,0,%3 # test_and_clear_bit\n" "andc %1,%0,%2 \n" PPC405_ERR77(0,%3) @@ -156,7 +156,7 @@ static __inline__ int test_and_change_bit(unsigned long nr, unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1:" PPC_LLARX "%0,0,%3 # test_and_change_bit\n" "xor %1,%0,%2 \n" PPC405_ERR77(0,%3) diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h index f0319d5..39e85f3 100644 --- a/include/asm-powerpc/futex.h +++ b/include/asm-powerpc/futex.h @@ -11,7 +11,7 @@ #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ __asm__ __volatile ( \ - SYNC_ON_SMP \ + LWSYNC_ON_SMP \ "1: lwarx %0,0,%2\n" \ insn \ PPC405_ERR77(0, %2) \ diff --git a/include/asm-powerpc/spinlock.h b/include/asm-powerpc/spinlock.h index 26b8744..895cb6d 100644 --- a/include/asm-powerpc/spinlock.h +++ b/include/asm-powerpc/spinlock.h @@ -46,7 +46,7 @@ static __inline__ unsigned long __spin_trylock(raw_spinlock_t *lock) token = LOCK_TOKEN; __asm__ __volatile__( -"1: lwarx %0,0,%2 # __spin_trylock\n\ +"1: lwarx %0,0,%2\n\ cmpwi 0,%0,0\n\ bne- 2f\n\ stwcx. %1,0,%2\n\ @@ -124,8 +124,8 @@ static void __inline__ __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long static __inline__ void __raw_spin_unlock(raw_spinlock_t *lock) { - __asm__ __volatile__(SYNC_ON_SMP" # __raw_spin_unlock" - : : :"memory"); + __asm__ __volatile__("# __raw_spin_unlock\n\t" + LWSYNC_ON_SMP: : :"memory"); lock->slock = 0; } @@ -167,7 +167,7 @@ static long __inline__ __read_trylock(raw_rwlock_t *rw) long tmp; __asm__ __volatile__( -"1: lwarx %0,0,%1 # read_trylock\n" +"1: lwarx %0,0,%1\n" __DO_SIGN_EXTEND " addic. %0,%0,1\n\ ble- 2f\n" @@ -192,7 +192,7 @@ static __inline__ long __write_trylock(raw_rwlock_t *rw) token = WRLOCK_TOKEN; __asm__ __volatile__( -"1: lwarx %0,0,%2 # write_trylock\n\ +"1: lwarx %0,0,%2\n\ cmpwi 0,%0,0\n\ bne- 2f\n" PPC405_ERR77(0,%1) @@ -249,8 +249,9 @@ static void __inline__ __raw_read_unlock(raw_rwlock_t *rw) long tmp; __asm__ __volatile__( - "eieio # read_unlock\n\ -1: lwarx %0,0,%1\n\ + "# read_unlock\n\t" + LWSYNC_ON_SMP +"1: lwarx %0,0,%1\n\ addic %0,%0,-1\n" PPC405_ERR77(0,%1) " stwcx. %0,0,%1\n\ @@ -262,8 +263,8 @@ static void __inline__ __raw_read_unlock(raw_rwlock_t *rw) static __inline__ void __raw_write_unlock(raw_rwlock_t *rw) { - __asm__ __volatile__(SYNC_ON_SMP" # write_unlock" - : : :"memory"); + __asm__ __volatile__("# write_unlock\n\t" + LWSYNC_ON_SMP: : :"memory"); rw->lock = 0; } diff --git a/include/asm-powerpc/synch.h b/include/asm-powerpc/synch.h index 794870a..c90d9d9 100644 --- a/include/asm-powerpc/synch.h +++ b/include/asm-powerpc/synch.h @@ -2,6 +2,8 @@ #define _ASM_POWERPC_SYNCH_H #ifdef __KERNEL__ +#include + #ifdef __powerpc64__ #define __SUBARCH_HAS_LWSYNC #endif @@ -12,20 +14,12 @@ # define LWSYNC sync #endif - -/* - * Arguably the bitops and *xchg operations don't imply any memory barrier - * or SMP ordering, but in fact a lot of drivers expect them to imply - * both, since they do on x86 cpus. - */ #ifdef CONFIG_SMP -#define EIEIO_ON_SMP "eieio\n" #define ISYNC_ON_SMP "\n\tisync" -#define SYNC_ON_SMP __stringify(LWSYNC) "\n" +#define LWSYNC_ON_SMP __stringify(LWSYNC) "\n" #else -#define EIEIO_ON_SMP #define ISYNC_ON_SMP -#define SYNC_ON_SMP +#define LWSYNC_ON_SMP #endif static inline void eieio(void) @@ -38,14 +32,5 @@ static inline void isync(void) __asm__ __volatile__ ("isync" : : : "memory"); } -#ifdef CONFIG_SMP -#define eieio_on_smp() eieio() -#define isync_on_smp() isync() -#else -#define eieio_on_smp() __asm__ __volatile__("": : :"memory") -#define isync_on_smp() __asm__ __volatile__("": : :"memory") -#endif - #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_SYNCH_H */ - diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index 9b822af..d9bf536 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h @@ -212,7 +212,7 @@ __xchg_u32(volatile void *p, unsigned long val) unsigned long prev; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: lwarx %0,0,%2 \n" PPC405_ERR77(0,%2) " stwcx. %3,0,%2 \n\ @@ -232,7 +232,7 @@ __xchg_u64(volatile void *p, unsigned long val) unsigned long prev; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: ldarx %0,0,%2 \n" PPC405_ERR77(0,%2) " stdcx. %3,0,%2 \n\ @@ -287,7 +287,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new) unsigned int prev; __asm__ __volatile__ ( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: lwarx %0,0,%2 # __cmpxchg_u32\n\ cmpw 0,%0,%3\n\ bne- 2f\n" @@ -311,7 +311,7 @@ __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) unsigned long prev; __asm__ __volatile__ ( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: ldarx %0,0,%2 # __cmpxchg_u64\n\ cmpd 0,%0,%3\n\ bne- 2f\n\ -- cgit v0.10.2 From b11fa580ac06b34944a2b46a44ebce2c284e1a76 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 13 Jan 2006 16:51:52 +1100 Subject: [PATCH] powerpc: reformat atomic_add_unless It makes my eyes hurt. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h index 9ce51ba..147a38d 100644 --- a/include/asm-powerpc/atomic.h +++ b/include/asm-powerpc/atomic.h @@ -176,19 +176,19 @@ static __inline__ int atomic_dec_return(atomic_t *v) * Atomically adds @a to @v, so long as it was not @u. * Returns non-zero if @v was not @u, and zero otherwise. */ -#define atomic_add_unless(v, a, u) \ -({ \ - int c, old; \ - c = atomic_read(v); \ - for (;;) { \ - if (unlikely(c == (u))) \ - break; \ - old = atomic_cmpxchg((v), c, c + (a)); \ - if (likely(old == c)) \ - break; \ - c = old; \ - } \ - c != (u); \ +#define atomic_add_unless(v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + for (;;) { \ + if (unlikely(c == (u))) \ + break; \ + old = atomic_cmpxchg((v), c, c + (a)); \ + if (likely(old == c)) \ + break; \ + c = old; \ + } \ + c != (u); \ }) #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) -- cgit v0.10.2 From 80f15dc703b3677d0b025bafd215f1f3664c8978 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 14 Jan 2006 10:11:39 +1100 Subject: powerpc: Provide a suitable AT_PLATFORM value The glibc folks want to use AT_PLATFORM to select between possible alternative versions of shared libraries. This commit makes the kernel supply an AT_PLATFORM string that indicates what class of processor we are running on. Processors with the same set of user-level instructions and roughly the same instruction scheduling characteristics are given the same AT_PLATFORM value; for example, 821, 823 and 860 are all reported as "ppc823", and 7447, 7447A, 7448, 7450, 7451, 7455 are all called "ppc7450". The intention is that the AT_PLATFORM values match the values that gcc accepts for the -mcpu= option. For values which are numeric (e.g. -mcpu=750), "ppc" has been prepended. This also adds a PPC_FEATURE_BOOKE bit to the AT_HWCAP value and sets it for the 440 family and the Freescale 85xx family. Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 43c74a6..cf1eea1 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -55,7 +55,8 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); #define COMMON_USER_POWER4 (COMMON_USER_PPC64 | PPC_FEATURE_POWER4) #define COMMON_USER_POWER5 (COMMON_USER_PPC64 | PPC_FEATURE_POWER5) #define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS) - +#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \ + PPC_FEATURE_BOOKE) /* We only set the spe features if the kernel was compiled with * spe support @@ -80,6 +81,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/power3", .oprofile_type = RS64, + .platform = "power3", }, { /* Power3+ */ .pvr_mask = 0xffff0000, @@ -93,6 +95,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/power3", .oprofile_type = RS64, + .platform = "power3", }, { /* Northstar */ .pvr_mask = 0xffff0000, @@ -106,6 +109,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = RS64, + .platform = "rs64", }, { /* Pulsar */ .pvr_mask = 0xffff0000, @@ -119,6 +123,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = RS64, + .platform = "rs64", }, { /* I-star */ .pvr_mask = 0xffff0000, @@ -132,6 +137,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = RS64, + .platform = "rs64", }, { /* S-star */ .pvr_mask = 0xffff0000, @@ -145,6 +151,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = RS64, + .platform = "rs64", }, { /* Power4 */ .pvr_mask = 0xffff0000, @@ -158,6 +165,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power4", .oprofile_type = POWER4, + .platform = "power4", }, { /* Power4+ */ .pvr_mask = 0xffff0000, @@ -171,6 +179,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power4", .oprofile_type = POWER4, + .platform = "power4", }, { /* PPC970 */ .pvr_mask = 0xffff0000, @@ -185,6 +194,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", .oprofile_type = POWER4, + .platform = "ppc970", }, #endif /* CONFIG_PPC64 */ #if defined(CONFIG_PPC64) || defined(CONFIG_POWER4) @@ -205,6 +215,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", .oprofile_type = POWER4, + .platform = "ppc970", }, #endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */ #ifdef CONFIG_PPC64 @@ -220,6 +231,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", .oprofile_type = POWER4, + .platform = "ppc970", }, { /* Power5 GR */ .pvr_mask = 0xffff0000, @@ -233,6 +245,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power5", .oprofile_type = POWER4, + .platform = "power5", }, { /* Power5 GS */ .pvr_mask = 0xffff0000, @@ -246,6 +259,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power5+", .oprofile_type = POWER4, + .platform = "power5+", }, { /* Cell Broadband Engine */ .pvr_mask = 0xffff0000, @@ -257,6 +271,7 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .cpu_setup = __setup_cpu_be, + .platform = "ppc-cell-be", }, { /* default match */ .pvr_mask = 0x00000000, @@ -268,6 +283,7 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, + .platform = "power4", } #endif /* CONFIG_PPC64 */ #ifdef CONFIG_PPC32 @@ -281,6 +297,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc601", }, { /* 603 */ .pvr_mask = 0xffff0000, @@ -290,7 +307,8 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_603 + .cpu_setup = __setup_cpu_603, + .platform = "ppc603", }, { /* 603e */ .pvr_mask = 0xffff0000, @@ -300,7 +318,8 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_603 + .cpu_setup = __setup_cpu_603, + .platform = "ppc603", }, { /* 603ev */ .pvr_mask = 0xffff0000, @@ -310,7 +329,8 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_603 + .cpu_setup = __setup_cpu_603, + .platform = "ppc603", }, { /* 604 */ .pvr_mask = 0xffff0000, @@ -321,7 +341,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 2, - .cpu_setup = __setup_cpu_604 + .cpu_setup = __setup_cpu_604, + .platform = "ppc604", }, { /* 604e */ .pvr_mask = 0xfffff000, @@ -332,7 +353,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_604 + .cpu_setup = __setup_cpu_604, + .platform = "ppc604", }, { /* 604r */ .pvr_mask = 0xffff0000, @@ -343,7 +365,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_604 + .cpu_setup = __setup_cpu_604, + .platform = "ppc604", }, { /* 604ev */ .pvr_mask = 0xffff0000, @@ -354,7 +377,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_604 + .cpu_setup = __setup_cpu_604, + .platform = "ppc604", }, { /* 740/750 (0x4202, don't support TAU ?) */ .pvr_mask = 0xffffffff, @@ -365,7 +389,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750 + .cpu_setup = __setup_cpu_750, + .platform = "ppc750", }, { /* 750CX (80100 and 8010x?) */ .pvr_mask = 0xfffffff0, @@ -376,7 +401,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750cx + .cpu_setup = __setup_cpu_750cx, + .platform = "ppc750", }, { /* 750CX (82201 and 82202) */ .pvr_mask = 0xfffffff0, @@ -387,7 +413,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750cx + .cpu_setup = __setup_cpu_750cx, + .platform = "ppc750", }, { /* 750CXe (82214) */ .pvr_mask = 0xfffffff0, @@ -398,7 +425,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750cx + .cpu_setup = __setup_cpu_750cx, + .platform = "ppc750", }, { /* 750CXe "Gekko" (83214) */ .pvr_mask = 0xffffffff, @@ -409,7 +437,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750cx + .cpu_setup = __setup_cpu_750cx, + .platform = "ppc750", }, { /* 745/755 */ .pvr_mask = 0xfffff000, @@ -420,7 +449,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750 + .cpu_setup = __setup_cpu_750, + .platform = "ppc750", }, { /* 750FX rev 1.x */ .pvr_mask = 0xffffff00, @@ -431,7 +461,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750 + .cpu_setup = __setup_cpu_750, + .platform = "ppc750", }, { /* 750FX rev 2.0 must disable HID0[DPM] */ .pvr_mask = 0xffffffff, @@ -442,7 +473,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750 + .cpu_setup = __setup_cpu_750, + .platform = "ppc750", }, { /* 750FX (All revs except 2.0) */ .pvr_mask = 0xffff0000, @@ -453,7 +485,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750fx + .cpu_setup = __setup_cpu_750fx, + .platform = "ppc750", }, { /* 750GX */ .pvr_mask = 0xffff0000, @@ -464,7 +497,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750fx + .cpu_setup = __setup_cpu_750fx, + .platform = "ppc750", }, { /* 740/750 (L2CR bit need fixup for 740) */ .pvr_mask = 0xffff0000, @@ -475,7 +509,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750 + .cpu_setup = __setup_cpu_750, + .platform = "ppc750", }, { /* 7400 rev 1.1 ? (no TAU) */ .pvr_mask = 0xffffffff, @@ -486,7 +521,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_7400 + .cpu_setup = __setup_cpu_7400, + .platform = "ppc7400", }, { /* 7400 */ .pvr_mask = 0xffff0000, @@ -497,7 +533,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_7400 + .cpu_setup = __setup_cpu_7400, + .platform = "ppc7400", }, { /* 7410 */ .pvr_mask = 0xffff0000, @@ -508,7 +545,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_7410 + .cpu_setup = __setup_cpu_7410, + .platform = "ppc7400", }, { /* 7450 2.0 - no doze/nap */ .pvr_mask = 0xffffffff, @@ -522,6 +560,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7450 2.1 */ .pvr_mask = 0xffffffff, @@ -535,6 +574,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7450 2.3 and newer */ .pvr_mask = 0xffff0000, @@ -548,6 +588,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7455 rev 1.x */ .pvr_mask = 0xffffff00, @@ -561,6 +602,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7455 rev 2.0 */ .pvr_mask = 0xffffffff, @@ -574,6 +616,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7455 others */ .pvr_mask = 0xffff0000, @@ -587,6 +630,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7447/7457 Rev 1.0 */ .pvr_mask = 0xffffffff, @@ -600,6 +644,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7447/7457 Rev 1.1 */ .pvr_mask = 0xffffffff, @@ -613,6 +658,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7447/7457 Rev 1.2 and later */ .pvr_mask = 0xffff0000, @@ -626,6 +672,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7447A */ .pvr_mask = 0xffff0000, @@ -639,6 +686,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7448 */ .pvr_mask = 0xffff0000, @@ -652,6 +700,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 82xx (8240, 8245, 8260 are all 603e cores) */ .pvr_mask = 0x7fff0000, @@ -661,7 +710,8 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_603 + .cpu_setup = __setup_cpu_603, + .platform = "ppc603", }, { /* All G2_LE (603e core, plus some) have the same pvr */ .pvr_mask = 0x7fff0000, @@ -671,7 +721,8 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_603 + .cpu_setup = __setup_cpu_603, + .platform = "ppc603", }, { /* e300 (a 603e core, plus some) on 83xx */ .pvr_mask = 0x7fff0000, @@ -681,7 +732,8 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_603 + .cpu_setup = __setup_cpu_603, + .platform = "ppc603", }, { /* default match, we assume split I/D cache & TB (non-601)... */ .pvr_mask = 0x00000000, @@ -691,6 +743,7 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc603", }, #endif /* CLASSIC_PPC */ #ifdef CONFIG_8xx @@ -704,6 +757,7 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 16, .dcache_bsize = 16, + .platform = "ppc823", }, #endif /* CONFIG_8xx */ #ifdef CONFIG_40x @@ -715,6 +769,7 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 16, .dcache_bsize = 16, + .platform = "ppc403", }, { /* 403GCX */ .pvr_mask = 0xffffff00, @@ -725,6 +780,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB, .icache_bsize = 16, .dcache_bsize = 16, + .platform = "ppc403", }, { /* 403G ?? */ .pvr_mask = 0xffff0000, @@ -734,6 +790,7 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 16, .dcache_bsize = 16, + .platform = "ppc403", }, { /* 405GP */ .pvr_mask = 0xffff0000, @@ -744,6 +801,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* STB 03xxx */ .pvr_mask = 0xffff0000, @@ -754,6 +812,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* STB 04xxx */ .pvr_mask = 0xffff0000, @@ -764,6 +823,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* NP405L */ .pvr_mask = 0xffff0000, @@ -774,6 +834,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* NP4GS3 */ .pvr_mask = 0xffff0000, @@ -784,6 +845,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* NP405H */ .pvr_mask = 0xffff0000, @@ -794,6 +856,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* 405GPr */ .pvr_mask = 0xffff0000, @@ -804,6 +867,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* STBx25xx */ .pvr_mask = 0xffff0000, @@ -814,6 +878,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* 405LP */ .pvr_mask = 0xffff0000, @@ -823,6 +888,7 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* Xilinx Virtex-II Pro */ .pvr_mask = 0xffff0000, @@ -833,6 +899,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* 405EP */ .pvr_mask = 0xffff0000, @@ -843,6 +910,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, #endif /* CONFIG_40x */ @@ -852,81 +920,90 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x40000850, .cpu_name = "440EP Rev. A", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = COMMON_USER, /* 440EP has an FPU */ + .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, { .pvr_mask = 0xf0000fff, .pvr_value = 0x400008d3, .cpu_name = "440EP Rev. B", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = COMMON_USER, /* 440EP has an FPU */ + .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, { /* 440GP Rev. B */ .pvr_mask = 0xf0000fff, .pvr_value = 0x40000440, .cpu_name = "440GP Rev. B", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440gp", }, { /* 440GP Rev. C */ .pvr_mask = 0xf0000fff, .pvr_value = 0x40000481, .cpu_name = "440GP Rev. C", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440gp", }, { /* 440GX Rev. A */ .pvr_mask = 0xf0000fff, .pvr_value = 0x50000850, .cpu_name = "440GX Rev. A", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, { /* 440GX Rev. B */ .pvr_mask = 0xf0000fff, .pvr_value = 0x50000851, .cpu_name = "440GX Rev. B", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, { /* 440GX Rev. C */ .pvr_mask = 0xf0000fff, .pvr_value = 0x50000892, .cpu_name = "440GX Rev. C", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, { /* 440GX Rev. F */ .pvr_mask = 0xf0000fff, .pvr_value = 0x50000894, .cpu_name = "440GX Rev. F", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, { /* 440SP Rev. A */ .pvr_mask = 0xff000fff, .pvr_value = 0x53000891, .cpu_name = "440SP Rev. A", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, { /* 440SPe Rev. A */ .pvr_mask = 0xff000fff, @@ -934,9 +1011,10 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "440SPe Rev. A", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, #endif /* CONFIG_44x */ #ifdef CONFIG_FSL_BOOKE @@ -946,10 +1024,11 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "e200z5", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ .cpu_features = CPU_FTRS_E200, - .cpu_user_features = PPC_FEATURE_32 | - PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_EFP_SINGLE | + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_UNIFIED_CACHE, .dcache_bsize = 32, + .platform = "ppc5554", }, { /* e200z6 */ .pvr_mask = 0xfff00000, @@ -957,11 +1036,12 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "e200z6", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ .cpu_features = CPU_FTRS_E200, - .cpu_user_features = PPC_FEATURE_32 | - PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_SPE_COMP | PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_UNIFIED_CACHE, .dcache_bsize = 32, + .platform = "ppc5554", }, { /* e500 */ .pvr_mask = 0xffff0000, @@ -969,14 +1049,15 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "e500", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ .cpu_features = CPU_FTRS_E500, - .cpu_user_features = PPC_FEATURE_32 | - PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_SPE_COMP | PPC_FEATURE_HAS_EFP_SINGLE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, .oprofile_cpu_type = "ppc/e500", .oprofile_type = BOOKE, + .platform = "ppc8540", }, { /* e500v2 */ .pvr_mask = 0xffff0000, @@ -984,14 +1065,16 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "e500v2", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ .cpu_features = CPU_FTRS_E500_2, - .cpu_user_features = PPC_FEATURE_32 | - PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | - PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_DOUBLE, + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_SPE_COMP | + PPC_FEATURE_HAS_EFP_SINGLE | + PPC_FEATURE_HAS_EFP_DOUBLE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, .oprofile_cpu_type = "ppc/e500", .oprofile_type = BOOKE, + .platform = "ppc8548", }, #endif #if !CLASSIC_PPC @@ -1003,6 +1086,7 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = PPC_FEATURE_32, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "powerpc", } #endif /* !CLASSIC_PPC */ #endif /* CONFIG_PPC32 */ diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index ef6ead3..03017d9 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -19,6 +19,7 @@ #define PPC_FEATURE_POWER5 0x00040000 #define PPC_FEATURE_POWER5_PLUS 0x00020000 #define PPC_FEATURE_CELL 0x00010000 +#define PPC_FEATURE_BOOKE 0x00008000 #ifdef __KERNEL__ #ifndef __ASSEMBLY__ @@ -64,6 +65,9 @@ struct cpu_spec { /* Processor specific oprofile operations */ enum powerpc_oprofile_type oprofile_type; + + /* Name of processor class, for the ELF AT_PLATFORM entry */ + char *platform; }; extern struct cpu_spec *cur_cpu_spec; diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h index 45f2af6..94d228f 100644 --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h @@ -221,20 +221,18 @@ extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *); instruction set this cpu supports. This could be done in userspace, but it's not easy, and we've already done it here. */ # define ELF_HWCAP (cur_cpu_spec->cpu_user_features) -#ifdef __powerpc64__ -# define ELF_PLAT_INIT(_r, load_addr) do { \ - _r->gpr[2] = load_addr; \ -} while (0) -#endif /* __powerpc64__ */ /* This yields a string that ld.so will use to load implementation specific libraries for optimization. This is more specific in - intent than poking at uname or /proc/cpuinfo. + intent than poking at uname or /proc/cpuinfo. */ - For the moment, we have only optimizations for the Intel generations, - but that could change... */ +#define ELF_PLATFORM (cur_cpu_spec->platform) -#define ELF_PLATFORM (NULL) +#ifdef __powerpc64__ +# define ELF_PLAT_INIT(_r, load_addr) do { \ + _r->gpr[2] = load_addr; \ +} while (0) +#endif /* __powerpc64__ */ #ifdef __KERNEL__ -- cgit v0.10.2 From 7a45fb19cef93574230827e6e2c97ad5760ddecd Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Fri, 13 Jan 2006 12:35:49 +0000 Subject: [PATCH] powerpc: oprofile cpu type names clash with other code In 2.6.15-git6 a change was commited in the oprofile support in the powerpc architecture. It introduced the powerpc_oprofile_type which contains the define G4. This causes a name clash with the existing wacom usb tablet driver. CC [M] drivers/usb/input/wacom.o drivers/usb/input/wacom.c:98: error: conflicting types for `G4' include/asm/cputable.h:37: error: previous declaration of `G4' CC [M] drivers/usb/mon/mon_text.o make[3]: *** [drivers/usb/input/wacom.o] Error 1 make[2]: *** [drivers/usb/input] Error 2 The elements of an enum declared in global scope are effectivly global identifiers themselves. As such we need to ensure the names are unique. This patch updates the later oprofile support to use unique names. Signed-off-by: Andy Whitcroft Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index cf1eea1..1069645 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -80,7 +80,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/power3", - .oprofile_type = RS64, + .oprofile_type = PPC_OPROFILE_RS64, .platform = "power3", }, { /* Power3+ */ @@ -94,7 +94,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/power3", - .oprofile_type = RS64, + .oprofile_type = PPC_OPROFILE_RS64, .platform = "power3", }, { /* Northstar */ @@ -108,7 +108,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", - .oprofile_type = RS64, + .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", }, { /* Pulsar */ @@ -122,7 +122,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", - .oprofile_type = RS64, + .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", }, { /* I-star */ @@ -136,7 +136,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", - .oprofile_type = RS64, + .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", }, { /* S-star */ @@ -150,7 +150,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", - .oprofile_type = RS64, + .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", }, { /* Power4 */ @@ -164,7 +164,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power4", - .oprofile_type = POWER4, + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power4", }, { /* Power4+ */ @@ -178,7 +178,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power4", - .oprofile_type = POWER4, + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power4", }, { /* PPC970 */ @@ -193,7 +193,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", - .oprofile_type = POWER4, + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "ppc970", }, #endif /* CONFIG_PPC64 */ @@ -214,7 +214,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", - .oprofile_type = POWER4, + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "ppc970", }, #endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */ @@ -230,7 +230,7 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", - .oprofile_type = POWER4, + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "ppc970", }, { /* Power5 GR */ @@ -244,7 +244,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power5", - .oprofile_type = POWER4, + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power5", }, { /* Power5 GS */ @@ -258,7 +258,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power5+", - .oprofile_type = POWER4, + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power5+", }, { /* Cell Broadband Engine */ @@ -559,7 +559,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7450 2.1 */ @@ -573,7 +573,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7450 2.3 and newer */ @@ -587,7 +587,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7455 rev 1.x */ @@ -601,7 +601,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7455 rev 2.0 */ @@ -615,7 +615,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7455 others */ @@ -629,7 +629,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7447/7457 Rev 1.0 */ @@ -643,7 +643,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7447/7457 Rev 1.1 */ @@ -657,7 +657,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7447/7457 Rev 1.2 and later */ @@ -671,7 +671,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7447A */ @@ -685,7 +685,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7448 */ @@ -699,7 +699,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 82xx (8240, 8245, 8260 are all 603e cores) */ @@ -1056,7 +1056,7 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 32, .num_pmcs = 4, .oprofile_cpu_type = "ppc/e500", - .oprofile_type = BOOKE, + .oprofile_type = PPC_OPROFILE_BOOKE, .platform = "ppc8540", }, { /* e500v2 */ @@ -1073,7 +1073,7 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 32, .num_pmcs = 4, .oprofile_cpu_type = "ppc/e500", - .oprofile_type = BOOKE, + .oprofile_type = PPC_OPROFILE_BOOKE, .platform = "ppc8548", }, #endif diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index 71615eb..cc2535b 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -140,19 +140,19 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) switch (cur_cpu_spec->oprofile_type) { #ifdef CONFIG_PPC64 - case RS64: + case PPC_OPROFILE_RS64: model = &op_model_rs64; break; - case POWER4: + case PPC_OPROFILE_POWER4: model = &op_model_power4; break; #else - case G4: + case PPC_OPROFILE_G4: model = &op_model_7450; break; #endif #ifdef CONFIG_FSL_BOOKE - case BOOKE: + case PPC_OPROFILE_BOOKE: model = &op_model_fsl_booke; break; #endif diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 03017d9..6421054 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -32,11 +32,11 @@ struct cpu_spec; typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); enum powerpc_oprofile_type { - INVALID = 0, - RS64 = 1, - POWER4 = 2, - G4 = 3, - BOOKE = 4, + PPC_OPROFILE_INVALID = 0, + PPC_OPROFILE_RS64 = 1, + PPC_OPROFILE_POWER4 = 2, + PPC_OPROFILE_G4 = 3, + PPC_OPROFILE_BOOKE = 4, }; struct cpu_spec { -- cgit v0.10.2 From b8e383d592daaa35c944a9083ee92c995dce66ca Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 13 Jan 2006 10:15:17 -0600 Subject: [PATCH] powerpc: Allow for ppc_md restart, power_off, and halt to be NULL On a number of embedded reference boards there isn't always a way to reset, power_off, or halt the board. Rather than having each board implement a spin loop just let the generic code do it. Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index d5c52fa..be12041 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -100,7 +100,8 @@ void machine_shutdown(void) void machine_restart(char *cmd) { machine_shutdown(); - ppc_md.restart(cmd); + if (ppc_md.restart) + ppc_md.restart(cmd); #ifdef CONFIG_SMP smp_send_stop(); #endif @@ -112,7 +113,8 @@ void machine_restart(char *cmd) void machine_power_off(void) { machine_shutdown(); - ppc_md.power_off(); + if (ppc_md.power_off) + ppc_md.power_off(); #ifdef CONFIG_SMP smp_send_stop(); #endif @@ -129,7 +131,8 @@ EXPORT_SYMBOL_GPL(pm_power_off); void machine_halt(void) { machine_shutdown(); - ppc_md.halt(); + if (ppc_md.halt) + ppc_md.halt(); #ifdef CONFIG_SMP smp_send_stop(); #endif -- cgit v0.10.2 From eed320010872a11f5255b3d076e5b4f142af553d Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 13 Jan 2006 11:19:13 -0600 Subject: [PATCH] powerpc: Add FSL SOC library and setup code Parse the flat device tree for devices on Freescale SOC's that we know about (gianfar, gianfar_mdio, i2c, mpc83xx_wdt). We need to setup platform devices and platform data for these devices to match arch/ppc usage. Also add a helper function (get_immrbase) that reports the base address of the MMIO registers on the SOC. Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 0ae8413..4c2b356 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_40x) += dcr.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_PPC_83xx) += ipic.o +obj-$(CONFIG_FSL_SOC) += fsl_soc.o diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c new file mode 100644 index 0000000..064c9de --- /dev/null +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -0,0 +1,317 @@ +/* + * FSL SoC setup code + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static phys_addr_t immrbase = -1; + +phys_addr_t get_immrbase(void) +{ + struct device_node *soc; + + if (immrbase != -1) + return immrbase; + + soc = of_find_node_by_type(NULL, "soc"); + if (soc != 0) { + unsigned int size; + void *prop = get_property(soc, "reg", &size); + immrbase = of_translate_address(soc, prop); + of_node_put(soc); + }; + + return immrbase; +} +EXPORT_SYMBOL(get_immrbase); + +static const char * gfar_tx_intr = "tx"; +static const char * gfar_rx_intr = "rx"; +static const char * gfar_err_intr = "error"; + +static int __init gfar_of_init(void) +{ + struct device_node *np; + unsigned int i; + struct platform_device *mdio_dev, *gfar_dev; + struct resource res; + int ret; + + for (np = NULL, i = 0; (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL; i++) { + int k; + struct device_node *child = NULL; + struct gianfar_mdio_data mdio_data; + + memset(&res, 0, sizeof(res)); + memset(&mdio_data, 0, sizeof(mdio_data)); + + ret = of_address_to_resource(np, 0, &res); + if (ret) + goto mdio_err; + + mdio_dev = platform_device_register_simple("fsl-gianfar_mdio", res.start, &res, 1); + if (IS_ERR(mdio_dev)) { + ret = PTR_ERR(mdio_dev); + goto mdio_err; + } + + for (k = 0; k < 32; k++) + mdio_data.irq[k] = -1; + + while ((child = of_get_next_child(np, child)) != NULL) { + if (child->n_intrs) { + u32 *id = (u32 *) get_property(child, "reg", NULL); + mdio_data.irq[*id] = child->intrs[0].line; + } + } + + ret = platform_device_add_data(mdio_dev, &mdio_data, sizeof(struct gianfar_mdio_data)); + if (ret) + goto mdio_unreg; + } + + for (np = NULL, i = 0; (np = of_find_compatible_node(np, "network", "gianfar")) != NULL; i++) { + struct resource r[4]; + struct device_node *phy, *mdio; + struct gianfar_platform_data gfar_data; + unsigned int *id; + char *model; + void *mac_addr; + phandle *ph; + + memset(r, 0, sizeof(r)); + memset(&gfar_data, 0, sizeof(gfar_data)); + + ret = of_address_to_resource(np, 0, &r[0]); + if (ret) + goto gfar_err; + + r[1].start = np->intrs[0].line; + r[1].end = np->intrs[0].line; + r[1].flags = IORESOURCE_IRQ; + + model = get_property(np, "model", NULL); + + /* If we aren't the FEC we have multiple interrupts */ + if (model && strcasecmp(model, "FEC")) { + r[1].name = gfar_tx_intr; + + r[2].name = gfar_rx_intr; + r[2].start = np->intrs[1].line; + r[2].end = np->intrs[1].line; + r[2].flags = IORESOURCE_IRQ; + + r[3].name = gfar_err_intr; + r[3].start = np->intrs[2].line; + r[3].end = np->intrs[2].line; + r[3].flags = IORESOURCE_IRQ; + } + + gfar_dev = platform_device_register_simple("fsl-gianfar", i, &r[0], np->n_intrs + 1); + + if (IS_ERR(gfar_dev)) { + ret = PTR_ERR(gfar_dev); + goto gfar_err; + } + + mac_addr = get_property(np, "address", NULL); + memcpy(gfar_data.mac_addr, mac_addr, 6); + + if (model && !strcasecmp(model, "TSEC")) + gfar_data.device_flags = + FSL_GIANFAR_DEV_HAS_GIGABIT | + FSL_GIANFAR_DEV_HAS_COALESCE | + FSL_GIANFAR_DEV_HAS_RMON | + FSL_GIANFAR_DEV_HAS_MULTI_INTR; + if (model && !strcasecmp(model, "eTSEC")) + gfar_data.device_flags = + FSL_GIANFAR_DEV_HAS_GIGABIT | + FSL_GIANFAR_DEV_HAS_COALESCE | + FSL_GIANFAR_DEV_HAS_RMON | + FSL_GIANFAR_DEV_HAS_MULTI_INTR | + FSL_GIANFAR_DEV_HAS_CSUM | + FSL_GIANFAR_DEV_HAS_VLAN | + FSL_GIANFAR_DEV_HAS_EXTENDED_HASH; + + ph = (phandle *) get_property(np, "phy-handle", NULL); + phy = of_find_node_by_phandle(*ph); + + if (phy == NULL) { + ret = -ENODEV; + goto gfar_unreg; + } + + mdio = of_get_parent(phy); + + id = (u32 *) get_property(phy, "reg", NULL); + ret = of_address_to_resource(mdio, 0, &res); + if (ret) { + of_node_put(phy); + of_node_put(mdio); + goto gfar_unreg; + } + + gfar_data.phy_id = *id; + gfar_data.bus_id = res.start; + + of_node_put(phy); + of_node_put(mdio); + + ret = platform_device_add_data(gfar_dev, &gfar_data, sizeof(struct gianfar_platform_data)); + if (ret) + goto gfar_unreg; + } + + return 0; + +mdio_unreg: + platform_device_unregister(mdio_dev); +mdio_err: + return ret; + +gfar_unreg: + platform_device_unregister(gfar_dev); +gfar_err: + return ret; +} +arch_initcall(gfar_of_init); + +static int __init fsl_i2c_of_init(void) +{ + struct device_node *np; + unsigned int i; + struct platform_device *i2c_dev; + int ret; + + for (np = NULL, i = 0; (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL; i++) { + struct resource r[2]; + struct fsl_i2c_platform_data i2c_data; + unsigned char * flags = NULL; + + memset(&r, 0, sizeof(r)); + memset(&i2c_data, 0, sizeof(i2c_data)); + + ret = of_address_to_resource(np, 0, &r[0]); + if (ret) + goto i2c_err; + + r[1].start = np->intrs[0].line; + r[1].end = np->intrs[0].line; + r[1].flags = IORESOURCE_IRQ; + + i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2); + if (IS_ERR(i2c_dev)) { + ret = PTR_ERR(i2c_dev); + goto i2c_err; + } + + i2c_data.device_flags = 0; + flags = get_property(np, "dfsrr", NULL); + if (flags) + i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR; + + flags = get_property(np, "fsl5200-clocking", NULL); + if (flags) + i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200; + + ret = platform_device_add_data(i2c_dev, &i2c_data, sizeof(struct fsl_i2c_platform_data)); + if (ret) + goto i2c_unreg; + } + + return 0; + +i2c_unreg: + platform_device_unregister(i2c_dev); +i2c_err: + return ret; +} +arch_initcall(fsl_i2c_of_init); + +#ifdef CONFIG_PPC_83xx +static int __init mpc83xx_wdt_init(void) +{ + struct resource r; + struct device_node *soc, *np; + struct platform_device *dev; + unsigned int *freq; + int ret; + + np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt"); + + if (!np) { + ret = -ENODEV; + goto mpc83xx_wdt_nodev; + } + + soc = of_find_node_by_type(NULL, "soc"); + + if (!soc) { + ret = -ENODEV; + goto mpc83xx_wdt_nosoc; + } + + freq = (unsigned int *)get_property(soc, "bus-frequency", NULL); + if (!freq) { + ret = -ENODEV; + goto mpc83xx_wdt_err; + } + + memset(&r, 0, sizeof(r)); + + ret = of_address_to_resource(np, 0, &r); + if (ret) + goto mpc83xx_wdt_err; + + dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1); + if (IS_ERR(dev)) { + ret = PTR_ERR(dev); + goto mpc83xx_wdt_err; + } + + ret = platform_device_add_data(dev, freq, sizeof(int)); + if (ret) + goto mpc83xx_wdt_unreg; + + of_node_put(soc); + of_node_put(np); + + return 0; + +mpc83xx_wdt_unreg: + platform_device_unregister(dev); +mpc83xx_wdt_err: + of_node_put(soc); +mpc83xx_wdt_nosoc: + of_node_put(np); +mpc83xx_wdt_nodev: + return ret; +} +arch_initcall(mpc83xx_wdt_init); +#endif diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h new file mode 100644 index 0000000..c433d3f --- /dev/null +++ b/arch/powerpc/sysdev/fsl_soc.h @@ -0,0 +1,8 @@ +#ifndef __PPC_FSL_SOC_H +#define __PPC_FSL_SOC_H +#ifdef __KERNEL__ + +extern phys_addr_t get_immrbase(void); + +#endif +#endif -- cgit v0.10.2 From 7d13d21ae85f64e35dcdae4d6a6286e62a38e0ab Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 13 Jan 2006 11:19:58 -0600 Subject: [PATCH] powerpc: Add MPC834x SYS board to arch/powerpc Add the first MPC83xx board that uses a flat device tree to arch/powerpc. Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/configs/mpc834x_sys_defconfig b/arch/powerpc/configs/mpc834x_sys_defconfig new file mode 100644 index 0000000..3bff761 --- /dev/null +++ b/arch/powerpc/configs/mpc834x_sys_defconfig @@ -0,0 +1,911 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.15-g461d4edf-dirty +# Fri Jan 13 11:01:47 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_DEFAULT_UIMAGE=y + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +CONFIG_PPC_83xx=y +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +# CONFIG_E500 is not set +CONFIG_6xx=y +CONFIG_83xx=y +CONFIG_PPC_FPU=y +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +# CONFIG_SMP is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +# CONFIG_KALLSYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +# CONFIG_EPOLL is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# Block layer +# +# CONFIG_LBD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_PPC_GEN550=y +# CONFIG_WANT_EARLY_SERIAL is not set + +# +# Platform support +# +CONFIG_MPC834x_SYS=y +CONFIG_MPC834x=y + +# +# Kernel options +# +# CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SOFTWARE_SUSPEND is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_PPC_I8259 is not set +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCI_LEGACY_PROC is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32768 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_GIANFAR=y +# CONFIG_GFAR_NAPI is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_83xx_WDT=y + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set +# CONFIG_NVRAM is not set +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_MPC=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_RTC_X1205_I2C is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# SN Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_BOOTX_TEXT is not set +# CONFIG_SERIAL_TEXT_DEBUG is not set +# CONFIG_PPC_EARLY_DEBUG_LPAR is not set +# CONFIG_PPC_EARLY_DEBUG_G5 is not set +# CONFIG_PPC_EARLY_DEBUG_RTAS is not set +# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set +# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# SEC2.x Options +# +CONFIG_MPC8349E_SEC2x=y + +# +# SEC2.x Test Options +# +CONFIG_MPC8349E_SEC2xTEST=y diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 16d9a90..d9a459c 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -230,8 +230,7 @@ EXPORT_SYMBOL(__down_interruptible); EXPORT_SYMBOL(cpm_install_handler); EXPORT_SYMBOL(cpm_free_handler); #endif /* CONFIG_8xx */ -#if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx) ||\ - defined(CONFIG_83xx) +#if defined(CONFIG_8xx) || defined(CONFIG_40x) EXPORT_SYMBOL(__res); #endif diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index b20812d..7675e67 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig @@ -7,6 +7,7 @@ choice config MPC834x_SYS bool "Freescale MPC834x SYS" + select DEFAULT_UIMAGE help This option enables support for the MPC 834x SYS evaluation board. diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c new file mode 100644 index 0000000..2098dd0 --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c @@ -0,0 +1,243 @@ +/* + * arch/powerpc/platforms/83xx/mpc834x_sys.c + * + * MPC834x SYS board specific routines + * + * Maintainer: Kumar Gala + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpc83xx.h" + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + +#ifdef CONFIG_PCI +extern int mpc83xx_pci2_busno; + +static int +mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */ + {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x13 */ + {0, 0, 0, 0}, + {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x15 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x16 */ + {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x17 */ + {PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x18 */ + {0, 0, 0, 0}, /* idsel 0x19 */ + {0, 0, 0, 0}, /* idsel 0x20 */ + }; + + const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; +} + +static int +mpc83xx_exclude_device(u_char bus, u_char devfn) +{ + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (mpc83xx_pci2_busno) + if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + return PCIBIOS_SUCCESSFUL; +} +#endif /* CONFIG_PCI */ + +/* ************************************************************************ + * + * Setup the architecture + * + */ +static void __init +mpc834x_sys_setup_arch(void) +{ + struct device_node *np; + + if (ppc_md.progress) + ppc_md.progress("mpc834x_sys_setup_arch()", 0); + + np = of_find_node_by_type(NULL, "cpu"); + if (np != 0) { + unsigned int *fp = (int *) get_property(np, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 50000000 / HZ; + of_node_put(np); + } + +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mpc83xx_map_irq; + ppc_md.pci_exclude_device = mpc83xx_exclude_device; +#endif + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif +} + +void __init +mpc834x_sys_init_IRQ(void) +{ + u8 senses[8] = { + 0, /* EXT 0 */ + IRQ_SENSE_LEVEL, /* EXT 1 */ + IRQ_SENSE_LEVEL, /* EXT 2 */ + 0, /* EXT 3 */ +#ifdef CONFIG_PCI + IRQ_SENSE_LEVEL, /* EXT 4 */ + IRQ_SENSE_LEVEL, /* EXT 5 */ + IRQ_SENSE_LEVEL, /* EXT 6 */ + IRQ_SENSE_LEVEL, /* EXT 7 */ +#else + 0, /* EXT 4 */ + 0, /* EXT 5 */ + 0, /* EXT 6 */ + 0, /* EXT 7 */ +#endif + }; + + ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8); + + /* Initialize the default interrupt mapping priorities, + * in case the boot rom changed something on us. + */ + ipic_set_default_priority(); +} + +#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374) +extern ulong ds1374_get_rtc_time(void); +extern int ds1374_set_rtc_time(ulong); + +static int __init +mpc834x_rtc_hookup(void) +{ + struct timespec tv; + + ppc_md.get_rtc_time = ds1374_get_rtc_time; + ppc_md.set_rtc_time = ds1374_set_rtc_time; + + tv.tv_nsec = 0; + tv.tv_sec = (ppc_md.get_rtc_time)(); + do_settimeofday(&tv); + + return 0; +} +late_initcall(mpc834x_rtc_hookup); +#endif + +static void +mpc83xx_restart(char *cmd) +{ +#define RST_OFFSET 0x00000900 +#define RST_PROT_REG 0x00000018 +#define RST_CTRL_REG 0x0000001c + __be32 __iomem *reg; + + // map reset register space + reg = ioremap(get_immrbase() + 0x900, 0xff); + + local_irq_disable(); + + /* enable software reset "RSTE" */ + out_be32(reg + (RST_PROT_REG >> 2), 0x52535445); + + /* set software hard reset */ + out_be32(reg + (RST_CTRL_REG >> 2), 0x52535445); + for(;;); +} + +static long __init +mpc83xx_time_init(void) +{ +#define SPCR_OFFSET 0x00000110 +#define SPCR_TBEN 0x00400000 + __be32 __iomem *spcr = ioremap(get_immrbase() + SPCR_OFFSET, 4); + __be32 tmp; + + tmp = in_be32(spcr); + out_be32(spcr, tmp|SPCR_TBEN); + + iounmap(spcr); + + return 0; +} +void __init +platform_init(void) +{ + /* setup the PowerPC module struct */ + ppc_md.setup_arch = mpc834x_sys_setup_arch; + + ppc_md.init_IRQ = mpc834x_sys_init_IRQ; + ppc_md.get_irq = ipic_get_irq; + + ppc_md.restart = mpc83xx_restart; + + ppc_md.time_init = mpc83xx_time_init; + ppc_md.set_rtc_time = NULL; + ppc_md.get_rtc_time = NULL; + ppc_md.calibrate_decr = generic_calibrate_decr; + + ppc_md.progress = udbg_progress; + + if (ppc_md.progress) + ppc_md.progress("mpc834x_sys_init(): exit", 0); + + return; +} + + diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.h b/arch/powerpc/platforms/83xx/mpc834x_sys.h new file mode 100644 index 0000000..e4ca39f --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.h @@ -0,0 +1,23 @@ +/* + * arch/powerppc/platforms/83xx/mpc834x_sys.h + * + * MPC834X SYS common board definitions + * + * Maintainer: Kumar Gala + * + * 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. + * + */ + +#ifndef __MACH_MPC83XX_SYS_H__ +#define __MACH_MPC83XX_SYS_H__ + +#define PIRQA MPC83xx_IRQ_EXT4 +#define PIRQB MPC83xx_IRQ_EXT5 +#define PIRQC MPC83xx_IRQ_EXT6 +#define PIRQD MPC83xx_IRQ_EXT7 + +#endif /* __MACH_MPC83XX_SYS_H__ */ diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h new file mode 100644 index 0000000..ce9e66a --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc83xx.h @@ -0,0 +1,14 @@ +#ifndef __MPC83XX_H__ +#define __MPC83XX_H__ + +#include +#include + +/* + * Declaration for the various functions exported by the + * mpc83xx_* files. Mostly for use by mpc83xx_setup + */ + +extern int add_bridge(struct device_node *dev); + +#endif /* __MPC83XX_H__ */ diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c new file mode 100644 index 0000000..469cdac --- /dev/null +++ b/arch/powerpc/platforms/83xx/pci.c @@ -0,0 +1,99 @@ +/* + * FSL SoC setup code + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +int mpc83xx_pci2_busno; + +#ifdef CONFIG_PCI +int __init add_bridge(struct device_node *dev) +{ + int len; + struct pci_controller *hose; + struct resource rsrc; + int *bus_range; + int primary = 1, has_address = 0; + phys_addr_t immr = get_immrbase(); + + DBG("Adding PCI host bridge %s\n", dev->full_name); + + /* Fetch host bridge registers address */ + has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); + + /* Get bus range if any */ + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s, assume" + " bus 0\n", dev->full_name); + } + + hose = pcibios_alloc_controller(); + if (!hose) + return -ENOMEM; + hose->arch_data = dev; + hose->set_cfg_type = 1; + + hose->first_busno = bus_range ? bus_range[0] : 0; + hose->last_busno = bus_range ? bus_range[1] : 0xff; + + /* MPC83xx supports up to two host controllers one at 0x8500 from immrbar + * the other at 0x8600, we consider the 0x8500 the primary controller + */ + /* PCI 1 */ + if ((rsrc.start & 0xfffff) == 0x8500) { + setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304); + } + /* PCI 2*/ + if ((rsrc.start & 0xfffff) == 0x8600) { + setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384); + primary = 0; + hose->bus_offset = hose->first_busno; + mpc83xx_pci2_busno = hose->first_busno; + } + + printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%08lx. " + "Firmware bus number: %d->%d\n", + rsrc.start, hose->first_busno, hose->last_busno); + + DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", + hose, hose->cfg_addr, hose->cfg_data); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + pci_process_bridge_OF_ranges(hose, dev, primary); + + return 0; +} + +#endif -- cgit v0.10.2 From 8f069b1a90bd97bf6d59a02ecabf0173d9175609 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Fri, 13 Jan 2006 14:16:12 -0200 Subject: [PATCH] powerpc/8xx: Use 8MB D-TLB's for kernel static mapping faults The following implements support for instantiation of 8MB D-TLB entries for the kernel direct virtual mapping on 8xx, thus reducing TLB space consumed for the kernel. Test used: writing 40MB from /dev/zero to file in ext2fs over RAMDISK. $ time dd if=/dev/zero of=file bs=4k count=10000 VANILLA 8MB kernel data pages real 0m11.485s real 0m11.267s user 0m0.218s user 0m0.250s sys 0m8.939s sys 0m9.108s real 0m11.518s real 0m10.978s user 0m0.203s user 0m0.222s sys 0m9.585s sys 0m9.138s real 0m11.554s real 0m10.967s user 0m0.228s user 0m0.222s sys 0m9.497s sys 0m9.127s real 0m11.633s real 0m11.286s user 0m0.214s user 0m0.196s sys 0m9.529s sys 0m9.134s and averages for both: real 11.54750 real 11.12450 Which is a 3.6% improvement in execution time. More improvement is expected for loads with larger kernel data footprint (real workloads). Signed-off-by: Marcelo Tosatti Signed-off-by: Paul Mackerras diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index de09787..3e6ca7f 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S @@ -375,6 +375,8 @@ DataStoreTLBMiss: lis r11, swapper_pg_dir@h ori r11, r11, swapper_pg_dir@l rlwimi r10, r11, 0, 2, 19 + stw r12, 16(r0) + b LoadLargeDTLB 3: lwz r11, 0(r10) /* Get the level 1 entry */ rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ @@ -430,6 +432,81 @@ DataStoreTLBMiss: InstructionTLBError: b InstructionAccess +LoadLargeDTLB: + li r12, 0 + lwz r11, 0(r10) /* Get the level 1 entry */ + rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ + beq 3f /* If zero, don't try to find a pte */ + + /* We have a pte table, so load fetch the pte from the table. + */ + ori r11, r11, 1 /* Set valid bit in physical L2 page */ + DO_8xx_CPU6(0x3b80, r3) + mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ + mfspr r10, SPRN_MD_TWC /* ....and get the pte address */ + lwz r10, 0(r10) /* Get the pte */ + + /* Insert the Guarded flag into the TWC from the Linux PTE. + * It is bit 27 of both the Linux PTE and the TWC (at least + * I got that right :-). It will be better when we can put + * this into the Linux pgd/pmd and load it in the operation + * above. + */ + rlwimi r11, r10, 0, 27, 27 + + rlwimi r12, r10, 0, 0, 9 /* extract phys. addr */ + mfspr r3, SPRN_MD_EPN + rlwinm r3, r3, 0, 0, 9 /* extract virtual address */ + tophys(r3, r3) + cmpw r3, r12 /* only use 8M page if it is a direct + kernel mapping */ + bne 1f + ori r11, r11, MD_PS8MEG + li r12, 1 + b 2f +1: + li r12, 0 /* can't use 8MB TLB, so zero r12. */ +2: + DO_8xx_CPU6(0x3b80, r3) + mtspr SPRN_MD_TWC, r11 + + /* The Linux PTE won't go exactly into the MMU TLB. + * Software indicator bits 21, 22 and 28 must be clear. + * Software indicator bits 24, 25, 26, and 27 must be + * set. All other Linux PTE bits control the behavior + * of the MMU. + */ +3: li r11, 0x00f0 + rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ + cmpwi r12, 1 + bne 4f + ori r10, r10, 0x8 + + mfspr r12, SPRN_MD_EPN + lis r3, 0xff80 /* 10-19 must be clear for 8MB TLB */ + ori r3, r3, 0x0fff + and r12, r3, r12 + DO_8xx_CPU6(0x3780, r3) + mtspr SPRN_MD_EPN, r12 + + lis r3, 0xff80 /* 10-19 must be clear for 8MB TLB */ + ori r3, r3, 0x0fff + and r10, r3, r10 +4: + DO_8xx_CPU6(0x3d80, r3) + mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ + + mfspr r10, SPRN_M_TW /* Restore registers */ + lwz r11, 0(r0) + mtcr r11 + lwz r11, 4(r0) + + lwz r12, 16(r0) +#ifdef CONFIG_8xx_CPU6 + lwz r3, 8(r0) +#endif + rfi + /* This is the data TLB error on the MPC8xx. This could be due to * many reasons, including a dirty update to a pte. We can catch that * one here, but anything else is an error. First, we track down the -- cgit v0.10.2 From 91f62a2491f45b5d46ebe5aca1fac3477355c9c1 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 14 Jan 2006 11:17:32 +1100 Subject: ppc: Remove duplicate export of get_wchan The arch/powerpc version of process.c exports get_wchan itself. When I moved ARCH=ppc over to using arch/powerpc/kernel/process.c the get_wchan export in arch/ppc/kernel/ppc_ksyms.c became redundant, so remove it. Signed-off-by: Paul Mackerras (cherry picked from 9871166ad692121d6b944159ef3f053570158ea8 commit) diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 95075f9..fb0da7c 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -270,7 +270,6 @@ EXPORT_SYMBOL(__delay); EXPORT_SYMBOL(timer_interrupt); EXPORT_SYMBOL(irq_desc); EXPORT_SYMBOL(tb_ticks_per_jiffy); -EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(console_drivers); #ifdef CONFIG_XMON EXPORT_SYMBOL(xmon); -- cgit v0.10.2 From 91dc182ca6e25ee8b648ed2fb2a41859ead34903 Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Fri, 13 Jan 2006 18:39:24 -0600 Subject: [PATCH] powerpc: special-case ibm,suspend-me RTAS call Handle the ibm,suspend-me RTAS call specially. It needs to be wrapped in a set of synchronization hypervisor calls (H_Join). When the H_Join calls are made on all CPUs, the intent is that only one will return with H_Continue, meaning that he is the "last man standing". That CPU then issues the ibm,suspend-me call. What is interesting, of course, is that the CPU running when the rtas syscall is made, may NOT be the CPU that ultimately executes the ibm,suspend-me rtas call. Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 4b9cfe4..7fe4a5c 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -36,6 +36,11 @@ struct rtas_t rtas = { .lock = SPIN_LOCK_UNLOCKED }; +struct rtas_suspend_me_data { + long waiting; + struct rtas_args *args; +}; + EXPORT_SYMBOL(rtas); DEFINE_SPINLOCK(rtas_data_buf_lock); @@ -556,6 +561,80 @@ void rtas_os_term(char *str) } while (status == RTAS_BUSY); } +static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; +#ifdef CONFIG_PPC_PSERIES +static void rtas_percpu_suspend_me(void *info) +{ + long rc; + long flags; + struct rtas_suspend_me_data *data = + (struct rtas_suspend_me_data *)info; + + /* + * We use "waiting" to indicate our state. As long + * as it is >0, we are still trying to all join up. + * If it goes to 0, we have successfully joined up and + * one thread got H_Continue. If any error happens, + * we set it to <0. + */ + local_irq_save(flags); + do { + rc = plpar_hcall_norets(H_JOIN); + smp_rmb(); + } while (rc == H_Success && data->waiting > 0); + if (rc == H_Success) + goto out; + + if (rc == H_Continue) { + data->waiting = 0; + rtas_call(ibm_suspend_me_token, 0, 1, + data->args->args); + } else { + data->waiting = -EBUSY; + printk(KERN_ERR "Error on H_Join hypervisor call\n"); + } + +out: + /* before we restore interrupts, make sure we don't + * generate a spurious soft lockup errors + */ + touch_softlockup_watchdog(); + local_irq_restore(flags); + return; +} + +static int rtas_ibm_suspend_me(struct rtas_args *args) +{ + int i; + + struct rtas_suspend_me_data data; + + data.waiting = 1; + data.args = args; + + /* Call function on all CPUs. One of us will make the + * rtas call + */ + if (on_each_cpu(rtas_percpu_suspend_me, &data, 1, 0)) + data.waiting = -EINVAL; + + if (data.waiting != 0) + printk(KERN_ERR "Error doing global join\n"); + + /* Prod each CPU. This won't hurt, and will wake + * anyone we successfully put to sleep with H_Join + */ + for_each_cpu(i) + plpar_hcall_norets(H_PROD, i); + + return data.waiting; +} +#else /* CONFIG_PPC_PSERIES */ +static int rtas_ibm_suspend_me(struct rtas_args *args) +{ + return -ENOSYS; +} +#endif asmlinkage int ppc_rtas(struct rtas_args __user *uargs) { @@ -563,6 +642,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) unsigned long flags; char *buff_copy, *errbuf = NULL; int nargs; + int rc; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -581,6 +661,17 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) nargs * sizeof(rtas_arg_t)) != 0) return -EFAULT; + if (args.token == RTAS_UNKNOWN_SERVICE) + return -EINVAL; + + /* Need to handle ibm,suspend_me call specially */ + if (args.token == ibm_suspend_me_token) { + rc = rtas_ibm_suspend_me(&args); + if (rc) + return rc; + goto copy_return; + } + buff_copy = get_errorlog_buffer(); spin_lock_irqsave(&rtas.lock, flags); @@ -604,6 +695,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) kfree(buff_copy); } + copy_return: /* Copy out args. */ if (copy_to_user(uargs->args + nargs, args.args + nargs, @@ -675,8 +767,10 @@ void __init rtas_initialize(void) * the stop-self token if any */ #ifdef CONFIG_PPC64 - if (_machine == PLATFORM_PSERIES_LPAR) + if (_machine == PLATFORM_PSERIES_LPAR) { rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); + ibm_suspend_me_token = rtas_token("ibm,suspend-me"); + } #endif rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region); -- cgit v0.10.2 From 575e321606c5673efabf28c0fa075e198980c44e Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 14 Jan 2006 00:13:49 +0000 Subject: [PATCH] powerpc: Make CHRP build again This makes CHRP build again, although it's untested because my Pegasos is currently in pieces. Signed-off-by: David Woodhouse Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 82c429d..00c52f2 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -135,12 +135,13 @@ int __init hydra_init(void) { struct device_node *np; + struct resource r; np = find_devices("mac-io"); - if (np == NULL || np->n_addrs == 0) + if (np == NULL || of_address_to_resource(np, 0, &r)) return 0; - Hydra = ioremap(np->addrs[0].address, np->addrs[0].size); - printk("Hydra Mac I/O at %lx\n", np->addrs[0].address); + Hydra = ioremap(r.start, r.end-r.start); + printk("Hydra Mac I/O at %lx\n", r.start); printk("Hydra Feature_Control was %x", in_le32(&Hydra->Feature_Control)); out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN | @@ -177,18 +178,24 @@ setup_python(struct pci_controller *hose, struct device_node *dev) { u32 __iomem *reg; u32 val; - unsigned long addr = dev->addrs[0].address; + struct resource r; - setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010); + if (of_address_to_resource(dev, 0, &r)) { + printk(KERN_ERR "No address for Python PCI controller\n"); + return; + } /* Clear the magic go-slow bit */ - reg = ioremap(dev->addrs[0].address + 0xf6000, 0x40); + reg = ioremap(r.start + 0xf6000, 0x40); + BUG_ON(!reg); val = in_be32(®[12]); if (val & PRG_CL_RESET_VALID) { out_be32(®[12], val & ~PRG_CL_RESET_VALID); in_be32(®[12]); } iounmap(reg); + + setup_indirect_pci(hose, r.start + 0xf8000, r.start + 0xf8010); } /* Marvell Discovery II based Pegasos 2 */ @@ -218,7 +225,7 @@ chrp_find_bridges(void) char *model, *machine; int is_longtrail = 0, is_mot = 0, is_pegasos = 0; struct device_node *root = find_path_device("/"); - + struct resource r; /* * The PCI host bridge nodes on some machines don't have * properties to adequately identify them, so we have to @@ -238,7 +245,7 @@ chrp_find_bridges(void) continue; ++index; /* The GG2 bridge on the LongTrail doesn't have an address */ - if (dev->n_addrs < 1 && !is_longtrail) { + if (of_address_to_resource(dev, 0, &r) && !is_longtrail) { printk(KERN_WARNING "Can't use %s: no address\n", dev->full_name); continue; @@ -255,8 +262,8 @@ chrp_find_bridges(void) printk(KERN_INFO "PCI buses %d..%d", bus_range[0], bus_range[1]); printk(" controlled by %s", dev->type); - if (dev->n_addrs > 0) - printk(" at %lx", dev->addrs[0].address); + if (!is_longtrail) + printk(" at %lx", r.start); printk("\n"); hose = pcibios_alloc_controller(); diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 4ec8ba7..2dc87aa 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -352,9 +352,10 @@ static void __init chrp_find_openpic(void) opaddr = opprop[na-1]; /* assume 32-bit */ oplen /= na * sizeof(unsigned int); } else { - if (np->n_addrs == 0) + struct resource r; + if (of_address_to_resource(np, 0, &r)) return; - opaddr = np->addrs[0].address; + opaddr = r.start; oplen = 0; } @@ -377,7 +378,7 @@ static void __init chrp_find_openpic(void) */ if (oplen < len) { printk(KERN_ERR "Insufficient addresses for distributed" - " OpenPIC (%d < %d)\n", np->n_addrs, len); + " OpenPIC (%d < %d)\n", oplen, len); len = oplen; } diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 737ee5d..36a0f97 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -37,14 +38,16 @@ static int nvram_data = NVRAM_DATA; long __init chrp_time_init(void) { struct device_node *rtcs; + struct resource r; int base; rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); if (rtcs == NULL) rtcs = find_compatible_devices("rtc", "ds1385-rtc"); - if (rtcs == NULL || rtcs->addrs == NULL) + if (rtcs == NULL || of_address_to_resource(rtcs, 0, &r)) return 0; - base = rtcs->addrs[0].address; + + base = r.start; nvram_as1 = 0; nvram_as0 = base; nvram_data = base + 1; -- cgit v0.10.2 From 36874579dbf4cafa31486d4207c6807efbbf1378 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 14 Jan 2006 00:15:19 +0000 Subject: [PATCH] powerpc: macio-adb build fix This makes macio-adb.c build again. Entirely untested. Signed-off-by: David Woodhouse Signed-off-by: Paul Mackerras diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c index cf6a6f2..314fc08 100644 --- a/drivers/macintosh/macio-adb.c +++ b/drivers/macintosh/macio-adb.c @@ -17,6 +17,7 @@ #include #include #include +#include struct preg { unsigned char r; @@ -88,24 +89,26 @@ int macio_probe(void) int macio_init(void) { struct device_node *adbs; + struct resource r; adbs = find_compatible_devices("adb", "chrp,adb0"); if (adbs == 0) return -ENXIO; #if 0 - { int i; + { int i = 0; printk("macio_adb_init: node = %p, addrs =", adbs->node); - for (i = 0; i < adbs->n_addrs; ++i) - printk(" %x(%x)", adbs->addrs[i].address, adbs->addrs[i].size); + while(!of_address_to_resource(adbs, i, &r)) + printk(" %x(%x)", r.start, r.end - r.start); printk(", intrs ="); for (i = 0; i < adbs->n_intrs; ++i) printk(" %x", adbs->intrs[i].line); printk("\n"); } #endif - - adb = ioremap(adbs->addrs->address, sizeof(struct adb_regs)); + if (of_address_to_resource(adbs, 0, &r)) + return -ENXIO; + adb = ioremap(r.start, sizeof(struct adb_regs)); out_8(&adb->ctrl.r, 0); out_8(&adb->intr.r, 0); -- cgit v0.10.2 From 66a45dd3620ee5f913ba1af3d2dca8b9bdfa2b96 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 14 Jan 2006 15:04:06 +1100 Subject: powerpc: Make COFF zImages for old 32-bit powermacs This adds code to build zImage.coff and/or zImage.initrd.coff when CONFIG_PPC32 and CONFIG_PPC_PMAC are defined. It also restructures the OF client code and adds some workarounds for OF quirks on the older machines. Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index b53d677..788dec4 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -25,8 +25,8 @@ HOSTCC := gcc BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \ $(shell $(CROSS32CC) -print-file-name=include) -fPIC BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc -BOOTLFLAGS := -T $(srctree)/$(src)/zImage.lds OBJCOPYFLAGS := contents,alloc,load,readonly,data +OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000 zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h @@ -35,7 +35,7 @@ zliblinuxheader := zlib.h zconf.h zutil.h $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) #$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h) -src-boot := string.S prom.c main.c div64.S crt0.S +src-boot := crt0.S string.S prom.c stdio.c main.c div64.S src-boot += $(zlib) src-boot := $(addprefix $(obj)/, $(src-boot)) obj-boot := $(addsuffix .o, $(basename $(src-boot))) @@ -70,7 +70,7 @@ quiet_cmd_bootas = BOOTAS $@ cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< quiet_cmd_bootld = BOOTLD $@ - cmd_bootld = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(2) + cmd_bootld = $(CROSS32LD) -T $(srctree)/$(src)/$(3) -o $@ $(2) $(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c $(call if_changed_dep,bootcc) @@ -87,12 +87,14 @@ obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section))) src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section))) gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) -hostprogs-y := addnote addRamDisk -targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ - $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ - $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ - $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ - vmlinux.initrd +hostprogs-y := addnote addRamDisk hack-coff + +targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ + zImage.coff zImage.initrd.coff \ + $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ + $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ + $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ + vmlinux.initrd extra-y := initrd.o quiet_cmd_ramdisk = RAMDISK $@ @@ -114,6 +116,10 @@ quiet_cmd_addsection = ADDSEC $@ quiet_cmd_addnote = ADDNOTE $@ cmd_addnote = $(obj)/addnote $@ +quiet_cmd_gencoff = COFF $@ + cmd_gencoff = $(OBJCOPY) $(OBJCOPY_COFF_ARGS) $@ && \ + $(obj)/hack-coff $@ + $(call gz-sec, $(required)): $(obj)/kernel-%.gz: % $(call if_changed,gzip) @@ -127,22 +133,35 @@ $(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c $(call if_changed_dep,bootcc) $(call cmd,addsection) -$(obj)/zImage.vmode: obj-boot += $(call obj-sec, $(required)) +$(obj)/zImage.vmode $(obj)/zImage.coff: obj-boot += $(call obj-sec, $(required)) $(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.lds - $(call cmd,bootld,$(obj-boot)) + $(call cmd,bootld,$(obj-boot),zImage.lds) -$(obj)/zImage.initrd.vmode: obj-boot += $(call obj-sec, $(required) $(initrd)) +$(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec, $(required) $(initrd)) $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds - $(call cmd,bootld,$(obj-boot)) + $(call cmd,bootld,$(obj-boot),zImage.lds) + +# For 32-bit powermacs, build the COFF images as well as the ELF images. +coffimage-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.coff +coffrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.initrd.coff -$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote +$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y) @cp -f $< $@ $(call if_changed,addnote) -$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote +$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote $(coffrdimg-y-y) @cp -f $< $@ $(call if_changed,addnote) +$(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff + $(call cmd,bootld,$(obj-boot),zImage.coff.lds) + $(call cmd,gencoff) + +$(obj)/zImage.initrd.coff: $(call obj-sec, $(required) $(initrd)) $(obj-boot) \ + $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff + $(call cmd,bootld,$(obj-boot),zImage.coff.lds) + $(call cmd,gencoff) + #----------------------------------------------------------- # build u-boot images #----------------------------------------------------------- diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S index d2f2ace..e0192c2 100644 --- a/arch/powerpc/boot/crt0.S +++ b/arch/powerpc/boot/crt0.S @@ -12,17 +12,23 @@ #include "ppc_asm.h" .text + /* a procedure descriptor used when booting this as a COFF file */ +_zimage_start_opd: + .long _zimage_start, 0, 0, 0 + .globl _zimage_start _zimage_start: + /* Work out the offset between the address we were linked at + and the address where we're running. */ bl 1f - -1: - mflr r0 +1: mflr r0 lis r9,1b@ha addi r9,r9,1b@l subf. r0,r9,r0 - beq 3f + beq 3f /* if running at same address as linked */ + /* The .got2 section contains a list of addresses, so add + the address offset onto each entry. */ lis r9,__got2_start@ha addi r9,r9,__got2_start@l lis r8,__got2_end@ha @@ -32,15 +38,14 @@ _zimage_start: srwi. r8,r8,2 mtctr r8 add r9,r0,r9 -2: - lwz r8,0(r9) +2: lwz r8,0(r9) add r8,r8,r0 stw r8,0(r9) addi r9,r9,4 bdnz 2b -3: - lis r9,_start@h + /* Do a cache flush for our text, in case OF didn't */ +3: lis r9,_start@h add r9,r0,r9 lis r8,_etext@ha addi r8,r8,_etext@l diff --git a/arch/powerpc/boot/hack-coff.c b/arch/powerpc/boot/hack-coff.c new file mode 100644 index 0000000..5e5a657 --- /dev/null +++ b/arch/powerpc/boot/hack-coff.c @@ -0,0 +1,84 @@ +/* + * hack-coff.c - hack the header of an xcoff file to fill in + * a few fields needed by the Open Firmware xcoff loader on + * Power Macs but not initialized by objcopy. + * + * Copyright (C) Paul Mackerras 1997. + * + * 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. + */ +#include +#include +#include +#include +#include +#include "rs6000.h" + +#define AOUT_MAGIC 0x010b + +#define get_16be(x) ((((unsigned char *)(x))[0] << 8) \ + + ((unsigned char *)(x))[1]) +#define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, \ + ((unsigned char *)(x))[1] = (v) & 0xff) +#define get_32be(x) ((((unsigned char *)(x))[0] << 24) \ + + (((unsigned char *)(x))[1] << 16) \ + + (((unsigned char *)(x))[2] << 8) \ + + ((unsigned char *)(x))[3]) + +int +main(int ac, char **av) +{ + int fd; + int i, nsect; + int aoutsz; + struct external_filehdr fhdr; + AOUTHDR aout; + struct external_scnhdr shdr; + + if (ac != 2) { + fprintf(stderr, "Usage: hack-coff coff-file\n"); + exit(1); + } + if ((fd = open(av[1], 2)) == -1) { + perror(av[2]); + exit(1); + } + if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr)) + goto readerr; + i = get_16be(fhdr.f_magic); + if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) { + fprintf(stderr, "%s: not an xcoff file\n", av[1]); + exit(1); + } + aoutsz = get_16be(fhdr.f_opthdr); + if (read(fd, &aout, aoutsz) != aoutsz) + goto readerr; + nsect = get_16be(fhdr.f_nscns); + for (i = 0; i < nsect; ++i) { + if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) + goto readerr; + if (strcmp(shdr.s_name, ".text") == 0) { + put_16be(aout.o_snentry, i+1); + put_16be(aout.o_sntext, i+1); + } else if (strcmp(shdr.s_name, ".data") == 0) { + put_16be(aout.o_sndata, i+1); + } else if (strcmp(shdr.s_name, ".bss") == 0) { + put_16be(aout.o_snbss, i+1); + } + } + put_16be(aout.magic, AOUT_MAGIC); + if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1 + || write(fd, &aout, aoutsz) != aoutsz) { + fprintf(stderr, "%s: write error\n", av[1]); + exit(1); + } + close(fd); + exit(0); + +readerr: + fprintf(stderr, "%s: read error or file too short\n", av[1]); + exit(1); +} diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index 64ec931..55ec598 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c @@ -21,8 +21,8 @@ extern void flush_cache(void *, unsigned long); /* Value picked to match that used by yaboot */ -#define PROG_START 0x01400000 -#define RAM_END (512<<20) // Fixme: use OF */ +#define PROG_START 0x01400000 /* only used on 64-bit systems */ +#define RAM_END (512<<20) /* Fixme: use OF */ #define ONE_MB 0x100000 extern char _start[]; @@ -160,6 +160,17 @@ static int is_elf64(void *hdr) elfoffset = (unsigned long)elf64ph->p_offset; vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset; vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset; + +#if defined(PROG_START) + /* + * Maintain a "magic" minimum address. This keeps some older + * firmware platforms running. + */ + + if (claim_base < PROG_START) + claim_base = PROG_START; +#endif + return 1; } @@ -206,12 +217,18 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) exit(); if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4) exit(); - stderr = stdout; - if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4) - exit(); printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp); + /* + * The first available claim_base must be above the end of the + * the loaded kernel wrapper file (_start to _end includes the + * initrd image if it is present) and rounded up to a nice + * 1 MB boundary for good measure. + */ + + claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); + vmlinuz.addr = (unsigned long)_vmlinux_start; vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); @@ -228,25 +245,6 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) exit(); } - /* - * The first available claim_base must be above the end of the - * the loaded kernel wrapper file (_start to _end includes the - * initrd image if it is present) and rounded up to a nice - * 1 MB boundary for good measure. - */ - - claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); - -#if defined(PROG_START) - /* - * Maintain a "magic" minimum address. This keeps some older - * firmware platforms running. - */ - - if (claim_base < PROG_START) - claim_base = PROG_START; -#endif - /* We need to claim the memsize plus the file offset since gzip * will expand the header (file offset), then the kernel, then * possible rubbish we don't care about. But the kernel bss must diff --git a/arch/powerpc/boot/prom.c b/arch/powerpc/boot/prom.c index 4bea2f4..fa00577 100644 --- a/arch/powerpc/boot/prom.c +++ b/arch/powerpc/boot/prom.c @@ -13,487 +13,153 @@ #include "prom.h" int (*prom)(void *); +phandle chosen_handle; +ihandle stdout; -void *chosen_handle; - -void *stdin; -void *stdout; -void *stderr; - - -int -write(void *handle, void *ptr, int nb) -{ - struct prom_args { - char *service; - int nargs; - int nret; - void *ihandle; - void *addr; - int len; - int actual; - } args; - - args.service = "write"; - args.nargs = 3; - args.nret = 1; - args.ihandle = handle; - args.addr = ptr; - args.len = nb; - args.actual = -1; - (*prom)(&args); - return args.actual; -} - -int -read(void *handle, void *ptr, int nb) +int call_prom(const char *service, int nargs, int nret, ...) { + int i; struct prom_args { - char *service; + const char *service; int nargs; int nret; - void *ihandle; - void *addr; - int len; - int actual; - } args; - - args.service = "read"; - args.nargs = 3; - args.nret = 1; - args.ihandle = handle; - args.addr = ptr; - args.len = nb; - args.actual = -1; - (*prom)(&args); - return args.actual; -} - -void -exit() -{ - struct prom_args { - char *service; - } args; - - for (;;) { - args.service = "exit"; - (*prom)(&args); - } -} - -void -pause(void) -{ - struct prom_args { - char *service; + unsigned int args[12]; } args; + va_list list; - args.service = "enter"; - (*prom)(&args); -} + args.service = service; + args.nargs = nargs; + args.nret = nret; -void * -finddevice(const char *name) -{ - struct prom_args { - char *service; - int nargs; - int nret; - const char *devspec; - void *phandle; - } args; + va_start(list, nret); + for (i = 0; i < nargs; i++) + args.args[i] = va_arg(list, unsigned int); + va_end(list); - args.service = "finddevice"; - args.nargs = 1; - args.nret = 1; - args.devspec = name; - args.phandle = (void *) -1; - (*prom)(&args); - return args.phandle; -} + for (i = 0; i < nret; i++) + args.args[nargs+i] = 0; -void * -claim(unsigned long virt, unsigned long size, unsigned long align) -{ - struct prom_args { - char *service; - int nargs; - int nret; - unsigned int virt; - unsigned int size; - unsigned int align; - void *ret; - } args; + if (prom(&args) < 0) + return -1; - args.service = "claim"; - args.nargs = 3; - args.nret = 1; - args.virt = virt; - args.size = size; - args.align = align; - (*prom)(&args); - return args.ret; + return (nret > 0)? args.args[nargs]: 0; } -int -getprop(void *phandle, const char *name, void *buf, int buflen) +int call_prom_ret(const char *service, int nargs, int nret, + unsigned int *rets, ...) { + int i; struct prom_args { - char *service; + const char *service; int nargs; int nret; - void *phandle; - const char *name; - void *buf; - int buflen; - int size; + unsigned int args[12]; } args; + va_list list; - args.service = "getprop"; - args.nargs = 4; - args.nret = 1; - args.phandle = phandle; - args.name = name; - args.buf = buf; - args.buflen = buflen; - args.size = -1; - (*prom)(&args); - return args.size; -} + args.service = service; + args.nargs = nargs; + args.nret = nret; -int -putc(int c, void *f) -{ - char ch = c; + va_start(list, rets); + for (i = 0; i < nargs; i++) + args.args[i] = va_arg(list, unsigned int); + va_end(list); - if (c == '\n') - putc('\r', f); - return write(f, &ch, 1) == 1? c: -1; -} + for (i = 0; i < nret; i++) + args.args[nargs+i] = 0; -int -putchar(int c) -{ - return putc(c, stdout); -} + if (prom(&args) < 0) + return -1; -int -fputs(char *str, void *f) -{ - int n = strlen(str); + if (rets != (void *) 0) + for (i = 1; i < nret; ++i) + rets[i-1] = args.args[nargs+i]; - return write(f, str, n) == n? 0: -1; + return (nret > 0)? args.args[nargs]: 0; } -size_t strnlen(const char * s, size_t count) +int write(void *handle, void *ptr, int nb) { - const char *sc; - - for (sc = s; count-- && *sc != '\0'; ++sc) - /* nothing */; - return sc - s; + return call_prom("write", 3, 1, handle, ptr, nb); } -extern unsigned int __div64_32(unsigned long long *dividend, - unsigned int divisor); - -/* The unnecessary pointer compare is there - * to check for type safety (n must be 64bit) +/* + * Older OF's require that when claiming a specific range of addresses, + * we claim the physical space in the /memory node and the virtual + * space in the chosen mmu node, and then do a map operation to + * map virtual to physical. */ -# define do_div(n,base) ({ \ - unsigned int __base = (base); \ - unsigned int __rem; \ - (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \ - if (((n) >> 32) == 0) { \ - __rem = (unsigned int)(n) % __base; \ - (n) = (unsigned int)(n) / __base; \ - } else \ - __rem = __div64_32(&(n), __base); \ - __rem; \ - }) +static int need_map = -1; +static ihandle chosen_mmu; +static phandle memory; -static int skip_atoi(const char **s) +/* returns true if s2 is a prefix of s1 */ +static int string_match(const char *s1, const char *s2) { - int i, c; - - for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s) - i = i*10 + c - '0'; - return i; + for (; *s2; ++s2) + if (*s1++ != *s2) + return 0; + return 1; } -#define ZEROPAD 1 /* pad with zero */ -#define SIGN 2 /* unsigned/signed long */ -#define PLUS 4 /* show plus */ -#define SPACE 8 /* space if plus */ -#define LEFT 16 /* left justified */ -#define SPECIAL 32 /* 0x */ -#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ - -static char * number(char * str, unsigned long long num, int base, int size, int precision, int type) +static int check_of_version(void) { - char c,sign,tmp[66]; - const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; - int i; + phandle oprom, chosen; + char version[64]; - if (type & LARGE) - digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - if (type & LEFT) - type &= ~ZEROPAD; - if (base < 2 || base > 36) + oprom = finddevice("/openprom"); + if (oprom == (phandle) -1) return 0; - c = (type & ZEROPAD) ? '0' : ' '; - sign = 0; - if (type & SIGN) { - if ((signed long long)num < 0) { - sign = '-'; - num = - (signed long long)num; - size--; - } else if (type & PLUS) { - sign = '+'; - size--; - } else if (type & SPACE) { - sign = ' '; - size--; + if (getprop(oprom, "model", version, sizeof(version)) <= 0) + return 0; + version[sizeof(version)-1] = 0; + printf("OF version = '%s'\r\n", version); + if (!string_match(version, "Open Firmware, 1.") + && !string_match(version, "FirmWorks,3.")) + return 0; + chosen = finddevice("/chosen"); + if (chosen == (phandle) -1) { + chosen = finddevice("/chosen@0"); + if (chosen == (phandle) -1) { + printf("no chosen\n"); + return 0; } } - if (type & SPECIAL) { - if (base == 16) - size -= 2; - else if (base == 8) - size--; - } - i = 0; - if (num == 0) - tmp[i++]='0'; - else while (num != 0) { - tmp[i++] = digits[do_div(num, base)]; + if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { + printf("no mmu\n"); + return 0; } - if (i > precision) - precision = i; - size -= precision; - if (!(type&(ZEROPAD+LEFT))) - while(size-->0) - *str++ = ' '; - if (sign) - *str++ = sign; - if (type & SPECIAL) { - if (base==8) - *str++ = '0'; - else if (base==16) { - *str++ = '0'; - *str++ = digits[33]; + memory = (ihandle) call_prom("open", 1, 1, "/memory"); + if (memory == (ihandle) -1) { + memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); + if (memory == (ihandle) -1) { + printf("no memory node\n"); + return 0; } } - if (!(type & LEFT)) - while (size-- > 0) - *str++ = c; - while (i < precision--) - *str++ = '0'; - while (i-- > 0) - *str++ = tmp[i]; - while (size-- > 0) - *str++ = ' '; - return str; + printf("old OF detected\r\n"); + return 1; } -int vsprintf(char *buf, const char *fmt, va_list args) +void *claim(unsigned long virt, unsigned long size, unsigned long align) { - int len; - unsigned long long num; - int i, base; - char * str; - const char *s; - - int flags; /* flags to number() */ - - int field_width; /* width of output field */ - int precision; /* min. # of digits for integers; max - number of chars for from string */ - int qualifier; /* 'h', 'l', or 'L' for integer fields */ - /* 'z' support added 23/7/1999 S.H. */ - /* 'z' changed to 'Z' --davidm 1/25/99 */ + int ret; + unsigned int result; + if (need_map < 0) + need_map = check_of_version(); + if (align || !need_map) + return (void *) call_prom("claim", 3, 1, virt, size, align); - for (str=buf ; *fmt ; ++fmt) { - if (*fmt != '%') { - *str++ = *fmt; - continue; - } - - /* process flags */ - flags = 0; - repeat: - ++fmt; /* this also skips first '%' */ - switch (*fmt) { - case '-': flags |= LEFT; goto repeat; - case '+': flags |= PLUS; goto repeat; - case ' ': flags |= SPACE; goto repeat; - case '#': flags |= SPECIAL; goto repeat; - case '0': flags |= ZEROPAD; goto repeat; - } - - /* get field width */ - field_width = -1; - if ('0' <= *fmt && *fmt <= '9') - field_width = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - field_width = va_arg(args, int); - if (field_width < 0) { - field_width = -field_width; - flags |= LEFT; - } - } - - /* get the precision */ - precision = -1; - if (*fmt == '.') { - ++fmt; - if ('0' <= *fmt && *fmt <= '9') - precision = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - precision = va_arg(args, int); - } - if (precision < 0) - precision = 0; - } - - /* get the conversion qualifier */ - qualifier = -1; - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { - qualifier = *fmt; - ++fmt; - } - - /* default base */ - base = 10; - - switch (*fmt) { - case 'c': - if (!(flags & LEFT)) - while (--field_width > 0) - *str++ = ' '; - *str++ = (unsigned char) va_arg(args, int); - while (--field_width > 0) - *str++ = ' '; - continue; - - case 's': - s = va_arg(args, char *); - if (!s) - s = ""; - - len = strnlen(s, precision); - - if (!(flags & LEFT)) - while (len < field_width--) - *str++ = ' '; - for (i = 0; i < len; ++i) - *str++ = *s++; - while (len < field_width--) - *str++ = ' '; - continue; - - case 'p': - if (field_width == -1) { - field_width = 2*sizeof(void *); - flags |= ZEROPAD; - } - str = number(str, - (unsigned long) va_arg(args, void *), 16, - field_width, precision, flags); - continue; - - - case 'n': - if (qualifier == 'l') { - long * ip = va_arg(args, long *); - *ip = (str - buf); - } else if (qualifier == 'Z') { - size_t * ip = va_arg(args, size_t *); - *ip = (str - buf); - } else { - int * ip = va_arg(args, int *); - *ip = (str - buf); - } - continue; - - case '%': - *str++ = '%'; - continue; - - /* integer number formats - set up the flags and "break" */ - case 'o': - base = 8; - break; - - case 'X': - flags |= LARGE; - case 'x': - base = 16; - break; - - case 'd': - case 'i': - flags |= SIGN; - case 'u': - break; - - default: - *str++ = '%'; - if (*fmt) - *str++ = *fmt; - else - --fmt; - continue; - } - if (qualifier == 'l') { - num = va_arg(args, unsigned long); - if (flags & SIGN) - num = (signed long) num; - } else if (qualifier == 'Z') { - num = va_arg(args, size_t); - } else if (qualifier == 'h') { - num = (unsigned short) va_arg(args, int); - if (flags & SIGN) - num = (signed short) num; - } else { - num = va_arg(args, unsigned int); - if (flags & SIGN) - num = (signed int) num; - } - str = number(str, num, base, field_width, precision, flags); - } - *str = '\0'; - return str-buf; -} - -int sprintf(char * buf, const char *fmt, ...) -{ - va_list args; - int i; - - va_start(args, fmt); - i=vsprintf(buf,fmt,args); - va_end(args); - return i; -} - -static char sprint_buf[1024]; - -int -printf(const char *fmt, ...) -{ - va_list args; - int n; - - va_start(args, fmt); - n = vsprintf(sprint_buf, fmt, args); - va_end(args); - write(stdout, sprint_buf, n); - return n; + ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, + align, size, virt); + if (ret != 0 || result == -1) + return (void *) -1; + ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, + align, size, virt); + /* 0x12 == coherent + read/write */ + ret = call_prom("call-method", 6, 1, "map", chosen_mmu, + 0x12, size, virt, virt); + return (void *) virt; } diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h index 96ab5ae..3e2ddd4 100644 --- a/arch/powerpc/boot/prom.h +++ b/arch/powerpc/boot/prom.h @@ -1,18 +1,34 @@ #ifndef _PPC_BOOT_PROM_H_ #define _PPC_BOOT_PROM_H_ +typedef void *phandle; +typedef void *ihandle; + extern int (*prom) (void *); -extern void *chosen_handle; +extern phandle chosen_handle; +extern ihandle stdout; -extern void *stdin; -extern void *stdout; -extern void *stderr; +int call_prom(const char *service, int nargs, int nret, ...); +int call_prom_ret(const char *service, int nargs, int nret, + unsigned int *rets, ...); extern int write(void *handle, void *ptr, int nb); -extern int read(void *handle, void *ptr, int nb); -extern void exit(void); -extern void pause(void); -extern void *finddevice(const char *); -extern void *claim(unsigned long virt, unsigned long size, unsigned long align); -extern int getprop(void *phandle, const char *name, void *buf, int buflen); +extern void *claim(unsigned long virt, unsigned long size, unsigned long aln); + +static inline void exit(void) +{ + call_prom("exit", 0, 0); +} + +static inline phandle finddevice(const char *name) +{ + return (phandle) call_prom("finddevice", 1, 1, name); +} + +static inline int getprop(void *phandle, const char *name, + void *buf, int buflen) +{ + return call_prom("getprop", 4, 1, phandle, name, buf, buflen); +} + #endif /* _PPC_BOOT_PROM_H_ */ diff --git a/arch/powerpc/boot/rs6000.h b/arch/powerpc/boot/rs6000.h new file mode 100644 index 0000000..433f450 --- /dev/null +++ b/arch/powerpc/boot/rs6000.h @@ -0,0 +1,243 @@ +/* IBM RS/6000 "XCOFF" file definitions for BFD. + Copyright (C) 1990, 1991 Free Software Foundation, Inc. + FIXME: Can someone provide a transliteration of this name into ASCII? + Using the following chars caused a compiler warning on HIUX (so I replaced + them with octal escapes), and isn't useful without an understanding of what + character set it is. + Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM + and John Gilmore of Cygnus Support. */ + +/********************** FILE HEADER **********************/ + +struct external_filehdr { + char f_magic[2]; /* magic number */ + char f_nscns[2]; /* number of sections */ + char f_timdat[4]; /* time & date stamp */ + char f_symptr[4]; /* file pointer to symtab */ + char f_nsyms[4]; /* number of symtab entries */ + char f_opthdr[2]; /* sizeof(optional hdr) */ + char f_flags[2]; /* flags */ +}; + + /* IBM RS/6000 */ +#define U802WRMAGIC 0730 /* writeable text segments **chh** */ +#define U802ROMAGIC 0735 /* readonly sharable text segments */ +#define U802TOCMAGIC 0737 /* readonly text segments and TOC */ + +#define BADMAG(x) \ + ((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \ + (x).f_magic != U802TOCMAGIC) + +#define FILHDR struct external_filehdr +#define FILHSZ 20 + + +/********************** AOUT "OPTIONAL HEADER" **********************/ + + +typedef struct +{ + unsigned char magic[2]; /* type of file */ + unsigned char vstamp[2]; /* version stamp */ + unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */ + unsigned char dsize[4]; /* initialized data " " */ + unsigned char bsize[4]; /* uninitialized data " " */ + unsigned char entry[4]; /* entry pt. */ + unsigned char text_start[4]; /* base of text used for this file */ + unsigned char data_start[4]; /* base of data used for this file */ + unsigned char o_toc[4]; /* address of TOC */ + unsigned char o_snentry[2]; /* section number of entry point */ + unsigned char o_sntext[2]; /* section number of .text section */ + unsigned char o_sndata[2]; /* section number of .data section */ + unsigned char o_sntoc[2]; /* section number of TOC */ + unsigned char o_snloader[2]; /* section number of .loader section */ + unsigned char o_snbss[2]; /* section number of .bss section */ + unsigned char o_algntext[2]; /* .text alignment */ + unsigned char o_algndata[2]; /* .data alignment */ + unsigned char o_modtype[2]; /* module type (??) */ + unsigned char o_cputype[2]; /* cpu type */ + unsigned char o_maxstack[4]; /* max stack size (??) */ + unsigned char o_maxdata[4]; /* max data size (??) */ + unsigned char o_resv2[12]; /* reserved */ +} +AOUTHDR; + +#define AOUTSZ 72 +#define SMALL_AOUTSZ (28) +#define AOUTHDRSZ 72 + +#define RS6K_AOUTHDR_OMAGIC 0x0107 /* old: text & data writeable */ +#define RS6K_AOUTHDR_NMAGIC 0x0108 /* new: text r/o, data r/w */ +#define RS6K_AOUTHDR_ZMAGIC 0x010B /* paged: text r/o, both page-aligned */ + + +/********************** SECTION HEADER **********************/ + + +struct external_scnhdr { + char s_name[8]; /* section name */ + char s_paddr[4]; /* physical address, aliased s_nlib */ + char s_vaddr[4]; /* virtual address */ + char s_size[4]; /* section size */ + char s_scnptr[4]; /* file ptr to raw data for section */ + char s_relptr[4]; /* file ptr to relocation */ + char s_lnnoptr[4]; /* file ptr to line numbers */ + char s_nreloc[2]; /* number of relocation entries */ + char s_nlnno[2]; /* number of line number entries*/ + char s_flags[4]; /* flags */ +}; + +/* + * names of "special" sections + */ +#define _TEXT ".text" +#define _DATA ".data" +#define _BSS ".bss" +#define _PAD ".pad" +#define _LOADER ".loader" + +#define SCNHDR struct external_scnhdr +#define SCNHSZ 40 + +/* XCOFF uses a special .loader section with type STYP_LOADER. */ +#define STYP_LOADER 0x1000 + +/* XCOFF uses a special .debug section with type STYP_DEBUG. */ +#define STYP_DEBUG 0x2000 + +/* XCOFF handles line number or relocation overflow by creating + another section header with STYP_OVRFLO set. */ +#define STYP_OVRFLO 0x8000 + +/********************** LINE NUMBERS **********************/ + +/* 1 line number entry for every "breakpointable" source line in a section. + * Line numbers are grouped on a per function basis; first entry in a function + * grouping will have l_lnno = 0 and in place of physical address will be the + * symbol table index of the function name. + */ +struct external_lineno { + union { + char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/ + char l_paddr[4]; /* (physical) address of line number */ + } l_addr; + char l_lnno[2]; /* line number */ +}; + + +#define LINENO struct external_lineno +#define LINESZ 6 + + +/********************** SYMBOLS **********************/ + +#define E_SYMNMLEN 8 /* # characters in a symbol name */ +#define E_FILNMLEN 14 /* # characters in a file name */ +#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ + +struct external_syment +{ + union { + char e_name[E_SYMNMLEN]; + struct { + char e_zeroes[4]; + char e_offset[4]; + } e; + } e; + char e_value[4]; + char e_scnum[2]; + char e_type[2]; + char e_sclass[1]; + char e_numaux[1]; +}; + + + +#define N_BTMASK (017) +#define N_TMASK (060) +#define N_BTSHFT (4) +#define N_TSHIFT (2) + + +union external_auxent { + struct { + char x_tagndx[4]; /* str, un, or enum tag indx */ + union { + struct { + char x_lnno[2]; /* declaration line number */ + char x_size[2]; /* str/union/array size */ + } x_lnsz; + char x_fsize[4]; /* size of function */ + } x_misc; + union { + struct { /* if ISFCN, tag, or .bb */ + char x_lnnoptr[4]; /* ptr to fcn line # */ + char x_endndx[4]; /* entry ndx past block end */ + } x_fcn; + struct { /* if ISARY, up to 4 dimen. */ + char x_dimen[E_DIMNUM][2]; + } x_ary; + } x_fcnary; + char x_tvndx[2]; /* tv index */ + } x_sym; + + union { + char x_fname[E_FILNMLEN]; + struct { + char x_zeroes[4]; + char x_offset[4]; + } x_n; + } x_file; + + struct { + char x_scnlen[4]; /* section length */ + char x_nreloc[2]; /* # relocation entries */ + char x_nlinno[2]; /* # line numbers */ + } x_scn; + + struct { + char x_tvfill[4]; /* tv fill value */ + char x_tvlen[2]; /* length of .tv */ + char x_tvran[2][2]; /* tv range */ + } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ + + struct { + unsigned char x_scnlen[4]; + unsigned char x_parmhash[4]; + unsigned char x_snhash[2]; + unsigned char x_smtyp[1]; + unsigned char x_smclas[1]; + unsigned char x_stab[4]; + unsigned char x_snstab[2]; + } x_csect; + +}; + +#define SYMENT struct external_syment +#define SYMESZ 18 +#define AUXENT union external_auxent +#define AUXESZ 18 +#define DBXMASK 0x80 /* for dbx storage mask */ +#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK) + + + +/********************** RELOCATION DIRECTIVES **********************/ + + +struct external_reloc { + char r_vaddr[4]; + char r_symndx[4]; + char r_size[1]; + char r_type[1]; +}; + + +#define RELOC struct external_reloc +#define RELSZ 10 + +#define DEFAULT_DATA_SECTION_ALIGNMENT 4 +#define DEFAULT_BSS_SECTION_ALIGNMENT 4 +#define DEFAULT_TEXT_SECTION_ALIGNMENT 4 +/* For new sections we havn't heard of before */ +#define DEFAULT_SECTION_ALIGNMENT 4 diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c new file mode 100644 index 0000000..b5aa522 --- /dev/null +++ b/arch/powerpc/boot/stdio.c @@ -0,0 +1,325 @@ +/* + * Copyright (C) Paul Mackerras 1997. + * + * 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. + */ +#include +#include +#include "string.h" +#include "stdio.h" +#include "prom.h" + +size_t strnlen(const char * s, size_t count) +{ + const char *sc; + + for (sc = s; count-- && *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} + +extern unsigned int __div64_32(unsigned long long *dividend, + unsigned int divisor); + +/* The unnecessary pointer compare is there + * to check for type safety (n must be 64bit) + */ +# define do_div(n,base) ({ \ + unsigned int __base = (base); \ + unsigned int __rem; \ + (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \ + if (((n) >> 32) == 0) { \ + __rem = (unsigned int)(n) % __base; \ + (n) = (unsigned int)(n) / __base; \ + } else \ + __rem = __div64_32(&(n), __base); \ + __rem; \ + }) + +static int skip_atoi(const char **s) +{ + int i, c; + + for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s) + i = i*10 + c - '0'; + return i; +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + +static char * number(char * str, unsigned long long num, int base, int size, int precision, int type) +{ + char c,sign,tmp[66]; + const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + + if (type & LARGE) + digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if ((signed long long)num < 0) { + sign = '-'; + num = - (signed long long)num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) { + tmp[i++] = digits[do_div(num, base)]; + } + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + *str++ = ' '; + if (sign) + *str++ = sign; + if (type & SPECIAL) { + if (base==8) + *str++ = '0'; + else if (base==16) { + *str++ = '0'; + *str++ = digits[33]; + } + } + if (!(type & LEFT)) + while (size-- > 0) + *str++ = c; + while (i < precision--) + *str++ = '0'; + while (i-- > 0) + *str++ = tmp[i]; + while (size-- > 0) + *str++ = ' '; + return str; +} + +int vsprintf(char *buf, const char *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + char * str; + const char *s; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + /* 'z' support added 23/7/1999 S.H. */ + /* 'z' changed to 'Z' --davidm 1/25/99 */ + + + for (str=buf ; *fmt ; ++fmt) { + if (*fmt != '%') { + *str++ = *fmt; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if ('0' <= *fmt && *fmt <= '9') + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if ('0' <= *fmt && *fmt <= '9') + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { + qualifier = *fmt; + ++fmt; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + *str++ = ' '; + *str++ = (unsigned char) va_arg(args, int); + while (--field_width > 0) + *str++ = ' '; + continue; + + case 's': + s = va_arg(args, char *); + if (!s) + s = ""; + + len = strnlen(s, precision); + + if (!(flags & LEFT)) + while (len < field_width--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = *s++; + while (len < field_width--) + *str++ = ' '; + continue; + + case 'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + str = number(str, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + + case 'n': + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = (str - buf); + } else if (qualifier == 'Z') { + size_t * ip = va_arg(args, size_t *); + *ip = (str - buf); + } else { + int * ip = va_arg(args, int *); + *ip = (str - buf); + } + continue; + + case '%': + *str++ = '%'; + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'X': + flags |= LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + *str++ = '%'; + if (*fmt) + *str++ = *fmt; + else + --fmt; + continue; + } + if (qualifier == 'l') { + num = va_arg(args, unsigned long); + if (flags & SIGN) + num = (signed long) num; + } else if (qualifier == 'Z') { + num = va_arg(args, size_t); + } else if (qualifier == 'h') { + num = (unsigned short) va_arg(args, int); + if (flags & SIGN) + num = (signed short) num; + } else { + num = va_arg(args, unsigned int); + if (flags & SIGN) + num = (signed int) num; + } + str = number(str, num, base, field_width, precision, flags); + } + *str = '\0'; + return str-buf; +} + +int sprintf(char * buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=vsprintf(buf,fmt,args); + va_end(args); + return i; +} + +static char sprint_buf[1024]; + +int +printf(const char *fmt, ...) +{ + va_list args; + int n; + + va_start(args, fmt); + n = vsprintf(sprint_buf, fmt, args); + va_end(args); + write(stdout, sprint_buf, n); + return n; +} diff --git a/arch/powerpc/boot/stdio.h b/arch/powerpc/boot/stdio.h index 24bd3a8..eb9e16c 100644 --- a/arch/powerpc/boot/stdio.h +++ b/arch/powerpc/boot/stdio.h @@ -7,10 +7,4 @@ extern int sprintf(char *buf, const char *fmt, ...); extern int vsprintf(char *buf, const char *fmt, va_list args); -extern int putc(int c, void *f); -extern int putchar(int c); -extern int getchar(void); - -extern int fputs(char *str, void *f); - #endif /* _PPC_BOOT_STDIO_H_ */ diff --git a/arch/powerpc/boot/zImage.coff.lds b/arch/powerpc/boot/zImage.coff.lds new file mode 100644 index 0000000..6016251 --- /dev/null +++ b/arch/powerpc/boot/zImage.coff.lds @@ -0,0 +1,46 @@ +OUTPUT_ARCH(powerpc:common) +ENTRY(_start) +SECTIONS +{ + . = (5*1024*1024); + _start = .; + .text : + { + *(.text) + *(.fixup) + } + _etext = .; + . = ALIGN(4096); + .data : + { + *(.rodata*) + *(.data*) + *(.sdata*) + __got2_start = .; + *(.got2) + __got2_end = .; + + _vmlinux_start = .; + *(.kernel:vmlinux.strip) + _vmlinux_end = .; + + _initrd_start = .; + *(.kernel:initrd) + _initrd_end = .; + } + + . = ALIGN(4096); + _edata = .; + __bss_start = .; + .bss : + { + *(.sbss) + *(.bss) + } + _end = . ; + + /DISCARD/ : + { + *(.comment) + } +} -- cgit v0.10.2 From b4e7de0f3575f4862f04921c5bd0cb5680cc8d71 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 14 Jan 2006 15:06:51 +1100 Subject: powerpc: Avoid unaligned loads and stores in boot memcpy code The 601 processor will generate an alignment exception for accesses which cross a page boundary. In the boot wrapper code, OF is still handling all exceptions, and it doesn't have an alignment exception handler that emulates the instruction and continues. This changes the memcpy and memmove routines in the boot wrapper to avoid doing unaligned accesses. If the source and destination are misaligned with respect to each other, we just copy one byte at a time. Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/boot/string.S b/arch/powerpc/boot/string.S index b1eeaed..ac3d43b 100644 --- a/arch/powerpc/boot/string.S +++ b/arch/powerpc/boot/string.S @@ -107,10 +107,12 @@ memcpy: rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */ addi r6,r3,-4 addi r4,r4,-4 - beq 2f /* if less than 8 bytes to do */ + beq 3f /* if less than 8 bytes to do */ andi. r0,r6,3 /* get dest word aligned */ mtctr r7 bne 5f + andi. r0,r4,3 /* check src word aligned too */ + bne 3f 1: lwz r7,4(r4) lwzu r8,8(r4) stw r7,4(r6) @@ -132,6 +134,11 @@ memcpy: bdnz 4b blr 5: subfic r0,r0,4 + cmpw cr1,r0,r5 + add r7,r0,r4 + andi. r7,r7,3 /* will source be word-aligned too? */ + ble cr1,3b + bne 3b /* do byte-by-byte if not */ mtctr r0 6: lbz r7,4(r4) addi r4,r4,1 @@ -149,10 +156,12 @@ backwards_memcpy: rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */ add r6,r3,r5 add r4,r4,r5 - beq 2f + beq 3f andi. r0,r6,3 mtctr r7 bne 5f + andi. r0,r4,3 + bne 3f 1: lwz r7,-4(r4) lwzu r8,-8(r4) stw r7,-4(r6) @@ -171,7 +180,12 @@ backwards_memcpy: stbu r0,-1(r6) bdnz 4b blr -5: mtctr r0 +5: cmpw cr1,r0,r5 + subf r7,r0,r4 + andi. r7,r7,3 + ble cr1,3b + bne 3b + mtctr r0 6: lbzu r7,-1(r4) stbu r7,-1(r6) bdnz 6b -- cgit v0.10.2 From d5f079000b20887bfbc84d772a27709c5665e652 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 14 Jan 2006 15:08:50 +1100 Subject: [PATCH] powerpc: Recognize /chaos bridge on old pmacs as PCI The first generation of PCI powermacs had a host bridge called /chaos which was for all intents and purposes a PCI host bridge, but has a device_type of "vci" in the device tree (presumably it's not really PCI at the hardware level or something). The OF parsing stuff in arch/powerpc/kernel/prom_parse.c currently doesn't recognize it as a PCI bridge, which means that controlfb.c can't get its device addresses. This makes prom_parse.c recognize a device_type of "vci" as indicating a PCI host bridge. With this, controlfb works again. Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 309ae1d..a8099c8 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -113,7 +113,8 @@ static unsigned int of_bus_default_get_flags(u32 *addr) static int of_bus_pci_match(struct device_node *np) { - return !strcmp(np->type, "pci"); + /* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */ + return !strcmp(np->type, "pci") || !strcmp(np->type, "vci"); } static void of_bus_pci_count_cells(struct device_node *np, -- cgit v0.10.2