From: Kumar Gala On most embedded PPC systems we either have a core CPU and chipset (MPC10x, TSI10x, Marvell, etc.) or a system-on-chip device (4xx, 8xx, 82xx, 85xx, etc.). Some of these sub-archs have been using the On Chip Peripheral (OCP) driver model. The functionality that OCP provide has been replaced by the generic driver model and platform_device. Also, some of these device may exist across a number of architectures (PPC, MIPS, ARM) such that some information that is shared between the architecture and driver needs to exist outside of either. The ppc_sys changes add a standard way for PowerPC systems to describe the devices and systems that exist in the sub-arch. Additionally, we are able to discover which system we are and manage which devices are actually registered and any platform specific fixups that may be needed. Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton --- 25-akpm/arch/ppc/syslib/Makefile | 3 - 25-akpm/arch/ppc/syslib/ppc_sys.c | 103 ++++++++++++++++++++++++++++++++++++ 25-akpm/include/asm-ppc/ppc_sys.h | 65 ++++++++++++++++++++++ 25-akpm/include/linux/fsl_devices.h | 78 +++++++++++++++++++++++++++ 4 files changed, 248 insertions(+), 1 deletion(-) diff -puN arch/ppc/syslib/Makefile~ppc32-system-platform_device-description-discovery-and-management arch/ppc/syslib/Makefile --- 25/arch/ppc/syslib/Makefile~ppc32-system-platform_device-description-discovery-and-management Tue Jan 18 15:51:30 2005 +++ 25-akpm/arch/ppc/syslib/Makefile Tue Jan 18 15:51:30 2005 @@ -92,7 +92,8 @@ obj-$(CONFIG_MPC10X_BRIDGE) += mpc10 obj-$(CONFIG_MPC10X_OPENPIC) += open_pic.o obj-$(CONFIG_40x) += dcr.o obj-$(CONFIG_BOOKE) += dcr.o -obj-$(CONFIG_85xx) += open_pic.o ppc85xx_common.o ppc85xx_setup.o +obj-$(CONFIG_85xx) += open_pic.o ppc85xx_common.o ppc85xx_setup.o \ + ppc_sys.o ifeq ($(CONFIG_85xx),y) obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o endif diff -puN /dev/null arch/ppc/syslib/ppc_sys.c --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/arch/ppc/syslib/ppc_sys.c Tue Jan 18 15:51:30 2005 @@ -0,0 +1,103 @@ +/* + * arch/ppc/syslib/ppc_sys.c + * + * PPC System library functions + * + * Maintainer: Kumar Gala + * + * Copyright 2005 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include + +int (*ppc_sys_device_fixup) (struct platform_device * pdev); + +static int ppc_sys_inited; + +void __init identify_ppc_sys_by_id(u32 id) +{ + unsigned int i = 0; + while (1) { + if ((ppc_sys_specs[i].mask & id) == ppc_sys_specs[i].value) + break; + i++; + } + + cur_ppc_sys_spec = &ppc_sys_specs[i]; + + return; +} + +void __init identify_ppc_sys_by_name(char *name) +{ + /* TODO */ + return; +} + +/* Update all memory resources by paddr, call before platform_device_register */ +void __init +ppc_sys_fixup_mem_resource(struct platform_device *pdev, phys_addr_t paddr) +{ + int i; + for (i = 0; i < pdev->num_resources; i++) { + struct resource *r = &pdev->resource[i]; + if ((r->flags & IORESOURCE_MEM) == IORESOURCE_MEM) { + r->start += paddr; + r->end += paddr; + } + } +} + +/* Get platform_data pointer out of platform device, call before platform_device_register */ +void *__init ppc_sys_get_pdata(enum ppc_sys_devices dev) +{ + return ppc_sys_platform_devices[dev].dev.platform_data; +} + +void ppc_sys_device_remove(enum ppc_sys_devices dev) +{ + unsigned int i; + + if (ppc_sys_inited) { + platform_device_unregister(&ppc_sys_platform_devices[dev]); + } else { + if (cur_ppc_sys_spec == NULL) + return; + for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) + if (cur_ppc_sys_spec->device_list[i] == dev) + cur_ppc_sys_spec->device_list[i] = -1; + } +} + +static int __init ppc_sys_init(void) +{ + unsigned int i, dev_id, ret = 0; + + BUG_ON(cur_ppc_sys_spec == NULL); + + for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) { + dev_id = cur_ppc_sys_spec->device_list[i]; + if (dev_id != -1) { + if (ppc_sys_device_fixup != NULL) + ppc_sys_device_fixup(&ppc_sys_platform_devices + [dev_id]); + if (platform_device_register + (&ppc_sys_platform_devices[dev_id])) { + ret = 1; + printk(KERN_ERR + "unable to register device %d\n", + dev_id); + } + } + } + + ppc_sys_inited = 1; + return ret; +} + +subsys_initcall(ppc_sys_init); diff -puN /dev/null include/asm-ppc/ppc_sys.h --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/include/asm-ppc/ppc_sys.h Tue Jan 18 15:51:30 2005 @@ -0,0 +1,65 @@ +/* + * include/asm-ppc/ppc_sys.h + * + * PPC system definitions and library functions + * + * Maintainer: Kumar Gala + * + * Copyright 2005 Freescale Semiconductor, Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifdef __KERNEL__ +#ifndef __ASM_PPC_SYS_H +#define __ASM_PPC_SYS_H + +#include +#include +#include + +#if defined(CONFIG_85xx) +#include +#else +#error "need definition of ppc_sys_devices" +#endif + +struct ppc_sys_spec { + /* PPC sys is matched via (ID & mask) == value, id could be + * PVR, SVR, IMMR, * etc. */ + u32 mask; + u32 value; + u32 num_devices; + char *ppc_sys_name; + enum ppc_sys_devices *device_list; +}; + +/* describes all specific chips and which devices they have on them */ +extern struct ppc_sys_spec ppc_sys_specs[]; +extern struct ppc_sys_spec *cur_ppc_sys_spec; + +/* determine which specific SOC we are */ +extern void identify_ppc_sys_by_id(u32 id) __init; +extern void identify_ppc_sys_by_name(char *name) __init; + +/* describes all devices that may exist in a given family of processors */ +extern struct platform_device ppc_sys_platform_devices[]; + +/* allow any platform_device fixup to occur before device is registered */ +extern int (*ppc_sys_device_fixup) (struct platform_device * pdev); + +/* Update all memory resources by paddr, call before platform_device_register */ +extern void ppc_sys_fixup_mem_resource(struct platform_device *pdev, + phys_addr_t paddr) __init; + +/* Get platform_data pointer out of platform device, call before platform_device_register */ +extern void *ppc_sys_get_pdata(enum ppc_sys_devices dev) __init; + +/* remove a device from the system */ +extern void ppc_sys_device_remove(enum ppc_sys_devices dev); + +#endif /* __ASM_PPC_SYS_H */ +#endif /* __KERNEL__ */ diff -puN /dev/null include/linux/fsl_devices.h --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/include/linux/fsl_devices.h Tue Jan 18 15:51:30 2005 @@ -0,0 +1,78 @@ +/* + * include/linux/fsl_devices.h + * + * Definitions for any platform device related flags or structures for + * Freescale processor devices + * + * Maintainer: Kumar Gala (kumar.gala@freescale.com) + * + * Copyright 2004 Freescale Semiconductor, Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifdef __KERNEL__ +#ifndef _FSL_DEVICE_H_ +#define _FSL_DEVICE_H_ + +#include + +/* + * Some conventions on how we handle peripherals on Freescale chips + * + * unique device: a platform_device entry in fsl_plat_devs[] plus + * associated device information in its platform_data structure. + * + * A chip is described by a set of unique devices. + * + * Each sub-arch has its own master list of unique devices and + * enumerates them by enum fsl_devices in a sub-arch specific header + * + * The platform data structure is broken into two parts. The + * first is device specific information that help identify any + * unique features of a peripheral. The second is any + * information that may be defined by the board or how the device + * is connected externally of the chip. + * + * naming conventions: + * - platform data structures: _platform_data + * - platform data device flags: FSL__DEV_ + * - platform data board flags: FSL__BRD_ + * + */ + +struct gianfar_platform_data { + /* device specific information */ + u32 device_flags; + u32 phy_reg_addr; + + /* board specific information */ + u32 board_flags; + u32 phyid; + u32 interruptPHY; + u8 mac_addr[6]; +}; + +/* Flags related to gianfar device features */ +#define FSL_GIANFAR_DEV_HAS_GIGABIT 0x00000001 +#define FSL_GIANFAR_DEV_HAS_COALESCE 0x00000002 +#define FSL_GIANFAR_DEV_HAS_RMON 0x00000004 +#define FSL_GIANFAR_DEV_HAS_MULTI_INTR 0x00000008 + +/* Flags in gianfar_platform_data */ +#define FSL_GIANFAR_BRD_HAS_PHY_INTR 0x00000001 /* if not set use a timer */ + +struct fsl_i2c_platform_data { + /* device specific information */ + u32 device_flags; +}; + +/* Flags related to I2C device features */ +#define FSL_I2C_DEV_SEPARATE_DFSRR 0x00000001 +#define FSL_I2C_DEV_CLOCK_5200 0x00000002 + +#endif /* _FSL_DEVICE_H_ */ +#endif /* __KERNEL__ */ _