[PATCH 1/4] ppc32: platform_device conversion from OCP
Kumar Gala
galak at freescale.com
Wed Jan 19 02:35:00 EST 2005
System platform_device description, discovery and management:
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 <kumar.gala at freescale.com>
---
diff -Nru a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
--- a/arch/ppc/syslib/Makefile 2005-01-17 22:31:44 -06:00
+++ b/arch/ppc/syslib/Makefile 2005-01-17 22:31:44 -06:00
@@ -92,7 +92,8 @@
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 -Nru a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/syslib/ppc_sys.c 2005-01-17 22:31:44 -06:00
@@ -0,0 +1,103 @@
+/*
+ * arch/ppc/syslib/ppc_sys.c
+ *
+ * PPC System library functions
+ *
+ * Maintainer: Kumar Gala <kumar.gala at freescale.com>
+ *
+ * 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 <asm/ppc_sys.h>
+
+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 -Nru a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/include/asm-ppc/ppc_sys.h 2005-01-17 22:31:44 -06:00
@@ -0,0 +1,65 @@
+/*
+ * include/asm-ppc/ppc_sys.h
+ *
+ * PPC system definitions and library functions
+ *
+ * Maintainer: Kumar Gala <kumar.gala at freescale.com>
+ *
+ * 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 <linux/init.h>
+#include <linux/device.h>
+#include <linux/types.h>
+
+#if defined(CONFIG_85xx)
+#include <asm/mpc85xx.h>
+#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 -Nru a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/include/linux/fsl_devices.h 2005-01-17 22:31:44 -06:00
@@ -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 at 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 <linux/types.h>
+
+/*
+ * 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: <driver>_platform_data
+ * - platform data device flags: FSL_<driver>_DEV_<FLAG>
+ * - platform data board flags: FSL_<driver>_BRD_<FLAG>
+ *
+ */
+
+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__ */
More information about the Linuxppc-embedded
mailing list