ppc32: Make platform devices being able to assign functions
RFC PATCH 1/1 ppc32: Make platform devices being able to assign functions
The idea is to modify a .name field on a platform device, when PDs with the same names are to be used within different drivers, as <device_name> -> <device_name>:<function>
Corresponding drivers should change the .name in struct device_driver to reflect upper of course.
Signed-off-by Vitaly Bordug <[email protected]>
This is preliminary version, maybe some issues still need not be cleaned up, and there is no "generic" platform_notify for board_specific code yet, but I'd like to see opinions concerning this stuff meantime.
Signature · 1 line
Sincerely, Vitaly
arch/ppc/syslib/ppc_sys.c +101 -2
@@ -15,11 +15,24 @@*/ #include <linux/string.h> +#include <linux/bootmem.h> +#include <linux/platform_device.h> #include <asm/ppc_sys.h> int (*ppc_sys_device_fixup) (struct platform_device * pdev);static int ppc_sys_inited; +static int ppc_sys_func_inited; + +static const char *ppc_sys_func_names[] = { + [FUNC_ENABLED ] ="dummy" , + [FUNC_ETH ] ="eth" , + [FUNC_UART ] ="uart" , + [FUNC_HLDC ] ="hldc" , + [FUNC_USB ] ="usb" , + [FUNC_IRDA ] ="irda" , + [FUNC_DISABLED ] ="off" , +};void __init identify_ppc_sys_by_id (u32 id) {
@@ -38,13 +51,13 @@ void __init identify_ppc_sys_by_id(u32 ivoid __init identify_ppc_sys_by_name (char *name) {unsigned int i =0 ; -while (ppc_sys_specs[i].ppc_sys_name[0 ]) - { +while (ppc_sys_specs[i].ppc_sys_name[0 ]) {if (!strcmp (ppc_sys_specs[i].ppc_sys_name, name))break ; i++; } cur_ppc_sys_spec = &ppc_sys_specs[i]; +return ; }
@@ -128,6 +141,92 @@ void ppc_sys_device_remove(enum ppc_sys_ } } +/* +Function assignment stuff. +Intended to work as follows: +the device name defined in foo_devices.c will be concatenated with :"func", +where func is string map of respective function from platfom_device_func enum + +The FUNC_ENABLED function is intended to remove all assignments, making the device to appear +in platform bus with unmodified name. +*/ + +/* +Here we'll replace .name pointers with fixed-lenght strings +Hereby, this should be called *before* any func stuff triggeded. +*/ +void ppc_sys_device_initfunc (void ) +{ +int i; +const char *name; +static char new_names[NUM_PPC_SYS_DEVS ][BUS_ID_SIZE ]; +enum ppc_sys_devices cur_dev; + +/* If inited yet, do nothing */ +if (ppc_sys_func_inited) +return ; + +for (i =0 ; i < cur_ppc_sys_spec->num_devices; i++) { +if ((cur_dev = cur_ppc_sys_spec->device_list[i]) <0 ) +continue ; + +if (ppc_sys_platform_devices[cur_dev].name) { +/*backup name */ + name = ppc_sys_platform_devices[cur_dev].name; +strlcpy (new_names[i], name,BUS_ID_SIZE ); + ppc_sys_platform_devices[cur_dev].name = new_names[i]; + } + } + + ppc_sys_func_inited =1 ; +} + +/*The "engine" of the func stuff. Here we either concat specified function string description +to the name, or remove it if FUNC_ENABLED parameter is passed here*/ +void ppc_sys_device_setfunc (enum ppc_sys_devices dev, +enum platform_device_func func) +{ +char *s; +char *name = (char *)ppc_sys_platform_devices[dev].name; +char tmp[BUS_ID_SIZE ]; + +if (!ppc_sys_func_inited) { +printk (KERN_ERR "Unable to later function - not inited!\n" ); +return ; + } + +if (ppc_sys_inited) { +platform_device_unregister (&ppc_sys_platform_devices[dev]); + } + +if ((s = (char *)strchr (name,':' )) !=NULL ) {/* reassign */ +/* Either change the name after ':' or remove func modifications */ +if (func !=FUNC_ENABLED ) +strlcpy (s +1 , ppc_sys_func_names[func],BUS_ID_SIZE ); +else + *s =0 ; + }else if (func !=FUNC_ENABLED ) { +/* do assignment if it is not just "enable" request */ +sprintf (tmp,"%s:%s" , name, ppc_sys_func_names[func]); +strlcpy (name, tmp,BUS_ID_SIZE ); + } + +if (ppc_sys_inited) { +platform_device_register (&ppc_sys_platform_devices[dev]); + } +} + +void ppc_sys_device_set_func_all (enum platform_device_func func) +{ +enum ppc_sys_devices cur_dev; +int i; + +for (i =0 ; i < cur_ppc_sys_spec->num_devices; i++) { + cur_dev = cur_ppc_sys_spec->device_list[i]; +ppc_sys_device_setfunc (cur_dev, func); + } +} +static int __init ppc_sys_init (void ) {unsigned int i, dev_id, ret =0 ;
include/asm-ppc/mpc10x.h +1 -0
@@ -165,6 +165,7 @@ enum ppc_sys_devices {MPC10X_DMA1 ,MPC10X_UART0 ,MPC10X_UART1 , + NUM_PPC_SYS_DEVS, }; int mpc10x_bridge_init(struct pci_controller *hose,
include/asm-ppc/mpc52xx.h +1 -0
@@ -49,6 +49,7 @@ enum ppc_sys_devices { MPC52xx_ATA, MPC52xx_I2C1, MPC52xx_I2C2, + NUM_PPC_SYS_DEVS, };
include/asm-ppc/mpc8260.h +1 -0
@@ -83,6 +83,7 @@ enum ppc_sys_devices { MPC82xx_CPM_SMC2, MPC82xx_CPM_USB, MPC82xx_SEC1, + NUM_PPC_SYS_DEVS, };#ifndef __ASSEMBLY__
include/asm-ppc/mpc83xx.h +1 -0
@@ -108,6 +108,7 @@ enum ppc_sys_devices { MPC83xx_USB2_DR, MPC83xx_USB2_MPH, MPC83xx_MDIO, + NUM_PPC_SYS_DEVS, };#endif /* CONFIG_83xx */
include/asm-ppc/mpc85xx.h +1 -0
@@ -135,6 +135,7 @@ enum ppc_sys_devices { MPC85xx_eTSEC4, MPC85xx_IIC2, MPC85xx_MDIO, + NUM_PPC_SYS_DEVS, };/* Internal interrupts are all Level Sensitive, and Positive Polarity */
include/asm-ppc/mpc8xx.h +1 -0
@@ -111,6 +111,7 @@ enum ppc_sys_devices { MPC8xx_CPM_SMC1, MPC8xx_CPM_SMC2, MPC8xx_CPM_USB, + NUM_PPC_SYS_DEVS, };#ifndef BOARD_CHIP_NAME
include/asm-ppc/ppc_sys.h +6 -0
@@ -72,5 +72,11 @@ extern void *ppc_sys_get_pdata(enum ppc_/* remove a device from the system */ extern void ppc_sys_device_remove (enum ppc_sys_devices dev); +/*Function assignment stuff*/ +void ppc_sys_device_initfunc (void ); +void ppc_sys_device_setfunc (enum ppc_sys_devices dev, +enum platform_device_func func); +void ppc_sys_device_set_func_all (enum platform_device_func func); +#endif /* __ASM_PPC_SYS_H */ #endif /* __KERNEL__ */
include/linux/platform_device.h +10 -0
@@ -21,6 +21,16 @@ struct platform_device {struct resource * resource; }; +enum platform_device_func { +FUNC_ENABLED =0 , +FUNC_ETH =1 , +FUNC_UART =2 , +FUNC_HLDC =3 , +FUNC_USB =4 , +FUNC_IRDA =5 , +FUNC_DISABLED =6 , +}; +#define to_platform_device (x) container_of((x), struct platform_device, dev)extern int platform_device_register (struct platform_device *);