From a22d6fb26287d94da3d942e60c16573eb4d43dd1 Mon Sep 17 00:00:00 2001 From: Michael Bohan Date: Fri, 25 May 2012 15:02:38 -0700 Subject: [PATCH] spmi: Add spmi_resource for non spmi-dev-container cases The devnode array is currently being used for non spmi-dev-container devices as a special case where the number of devnodes is 1. This obfuscates the code and also removes the ability to store the dev-container's device resource information, since in that special case the devnode array is dedicated for the child devices. Add a new spmi_resource entry used for typical spmi_devices, and treat the devnode array as the special case for spmi-dev-container. Also add a new API spmi_get_primary_dev_name() to return the name of the device assigned with the 'label' binding if it exists. Change-Id: Ibe7b12285e37bb0529024558550a96d71393bc10 Signed-off-by: Michael Bohan --- drivers/of/of_spmi.c | 212 +++++++++++++++++++++------------- drivers/spmi/spmi-resources.c | 13 ++- drivers/spmi/spmi.c | 1 + include/linux/spmi.h | 25 +++- 4 files changed, 163 insertions(+), 88 deletions(-) diff --git a/drivers/of/of_spmi.c b/drivers/of/of_spmi.c index d0ae95a6f5b..0c23db59c3e 100644 --- a/drivers/of/of_spmi.c +++ b/drivers/of/of_spmi.c @@ -42,28 +42,13 @@ static inline void of_spmi_init_resource(struct of_spmi_res_info *r_info, r_info->num_irq = 0; } -/* - * Allocate dev_node array for spmi_device - */ -static inline int of_spmi_alloc_device_store(struct of_spmi_dev_info *d_info, - uint32_t num_dev_node) -{ - d_info->b_info.num_dev_node = num_dev_node; - d_info->b_info.dev_node = kzalloc(sizeof(struct spmi_resource) * - num_dev_node, GFP_KERNEL); - if (!d_info->b_info.dev_node) - return -ENOMEM; - - return 0; -} - /* * Calculate the number of resources to allocate * * The caller is responsible for initializing the of_spmi_res_info structure. */ -static void of_spmi_sum_node_resources(struct of_spmi_res_info *r_info, - bool has_reg) +static void of_spmi_sum_resources(struct of_spmi_res_info *r_info, + bool has_reg) { struct of_irq oirq; uint64_t size; @@ -92,9 +77,75 @@ static void of_spmi_sum_node_resources(struct of_spmi_res_info *r_info, } /* - * free spmi_resource for the spmi_device + * Allocate dev_node array for spmi_device - used with spmi-dev-container */ -static void of_spmi_free_device_resources(struct of_spmi_dev_info *d_info) +static inline int of_spmi_alloc_devnode_store(struct of_spmi_dev_info *d_info, + uint32_t num_dev_node) +{ + d_info->b_info.num_dev_node = num_dev_node; + d_info->b_info.dev_node = kzalloc(sizeof(struct spmi_resource) * + num_dev_node, GFP_KERNEL); + if (!d_info->b_info.dev_node) + return -ENOMEM; + + return 0; +} + +/* + * Allocate enough memory to handle the resources associated with the + * primary node. + */ +static int of_spmi_allocate_node_resources(struct of_spmi_dev_info *d_info, + struct of_spmi_res_info *r_info) +{ + uint32_t num_irq = r_info->num_irq, num_reg = r_info->num_reg; + struct resource *res = NULL; + + if (num_irq || num_reg) { + res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL); + if (!res) + return -ENOMEM; + } + d_info->b_info.res.num_resources = num_reg + num_irq; + d_info->b_info.res.resource = res; + + return 0; +} + +/* + * Allocate enough memory to handle the resources associated with the + * spmi-dev-container nodes. + */ +static int of_spmi_allocate_devnode_resources(struct of_spmi_dev_info *d_info, + struct of_spmi_res_info *r_info, + uint32_t idx) +{ + uint32_t num_irq = r_info->num_irq, num_reg = r_info->num_reg; + struct resource *res = NULL; + + if (num_irq || num_reg) { + res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL); + if (!res) + return -ENOMEM; + } + d_info->b_info.dev_node[idx].num_resources = num_reg + num_irq; + d_info->b_info.dev_node[idx].resource = res; + + return 0; +} + +/* + * free node resources - used with primary node + */ +static void of_spmi_free_node_resources(struct of_spmi_dev_info *d_info) +{ + kfree(d_info->b_info.res.resource); +} + +/* + * free devnode resources - used with spmi-dev-container + */ +static void of_spmi_free_devnode_resources(struct of_spmi_dev_info *d_info) { int i; @@ -104,26 +155,17 @@ static void of_spmi_free_device_resources(struct of_spmi_dev_info *d_info) kfree(d_info->b_info.dev_node); } -/* - * Gather node resources and populate - */ -static void of_spmi_populate_node_resources(struct of_spmi_dev_info *d_info, - struct of_spmi_res_info *r_info, - int idx) +static void of_spmi_populate_resources(struct of_spmi_dev_info *d_info, + struct of_spmi_res_info *r_info, + struct resource *res) { uint32_t num_irq = r_info->num_irq, num_reg = r_info->num_reg; int i; - struct resource *res; const __be32 *addrp; uint64_t size; uint32_t flags; - res = d_info->b_info.dev_node[idx].resource; - d_info->b_info.dev_node[idx].of_node = r_info->node; - of_property_read_string(r_info->node, "label", - &d_info->b_info.dev_node[idx].label); - if ((num_irq || num_reg) && (res != NULL)) { for (i = 0; i < num_reg; i++, res++) { /* Addresses are always 16 bits */ @@ -141,26 +183,36 @@ static void of_spmi_populate_node_resources(struct of_spmi_dev_info *d_info, } /* - * Allocate enough memory to handle the resources associated with the - * device_node. The number of device nodes included in this allocation - * depends on whether the spmi-dev-container flag is specified or not. + * Gather primary node resources and populate. */ -static int of_spmi_allocate_node_resources(struct of_spmi_dev_info *d_info, - struct of_spmi_res_info *r_info, - uint32_t idx) +static void of_spmi_populate_node_resources(struct of_spmi_dev_info *d_info, + struct of_spmi_res_info *r_info) + { - uint32_t num_irq = r_info->num_irq, num_reg = r_info->num_reg; - struct resource *res = NULL; + struct resource *res; - if (num_irq || num_reg) { - res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL); - if (!res) - return -ENOMEM; - } - d_info->b_info.dev_node[idx].num_resources = num_reg + num_irq; - d_info->b_info.dev_node[idx].resource = res; + res = d_info->b_info.res.resource; + d_info->b_info.res.of_node = r_info->node; + of_property_read_string(r_info->node, "label", + &d_info->b_info.res.label); + of_spmi_populate_resources(d_info, r_info, res); +} - return 0; +/* + * Gather node devnode resources and populate - used with spmi-dev-container. + */ +static void of_spmi_populate_devnode_resources(struct of_spmi_dev_info *d_info, + struct of_spmi_res_info *r_info, + int idx) + +{ + struct resource *res; + + res = d_info->b_info.dev_node[idx].resource; + d_info->b_info.dev_node[idx].of_node = r_info->node; + of_property_read_string(r_info->node, "label", + &d_info->b_info.dev_node[idx].label); + of_spmi_populate_resources(d_info, r_info, res); } /* @@ -220,10 +272,10 @@ static void of_spmi_walk_dev_container(struct of_spmi_dev_info *d_info, num_dev_node++; } - rc = of_spmi_alloc_device_store(d_info, num_dev_node); + rc = of_spmi_alloc_devnode_store(d_info, num_dev_node); if (rc) { - dev_err(&ctrl->dev, "%s: unable to allocate" - " device resources\n", __func__); + dev_err(&ctrl->dev, "%s: unable to allocate devnode resources\n", + __func__); return; } @@ -232,23 +284,36 @@ static void of_spmi_walk_dev_container(struct of_spmi_dev_info *d_info, if (!of_device_is_available(node)) continue; of_spmi_init_resource(&r_info, node); - of_spmi_sum_node_resources(&r_info, 1); - rc = of_spmi_allocate_node_resources(d_info, &r_info, i); + of_spmi_sum_resources(&r_info, true); + rc = of_spmi_allocate_devnode_resources(d_info, &r_info, i); if (rc) { dev_err(&ctrl->dev, "%s: unable to allocate" " resources\n", __func__); - of_spmi_free_device_resources(d_info); + of_spmi_free_devnode_resources(d_info); return; } - of_spmi_populate_node_resources(d_info, &r_info, i); + of_spmi_populate_devnode_resources(d_info, &r_info, i); i++; } + of_spmi_init_resource(&r_info, container); + of_spmi_sum_resources(&r_info, true); + + rc = of_spmi_allocate_node_resources(d_info, &r_info); + if (rc) { + dev_err(&ctrl->dev, "%s: unable to allocate resources\n", + __func__); + of_spmi_free_node_resources(d_info); + } + + of_spmi_populate_node_resources(d_info, &r_info); + + rc = of_spmi_create_device(d_info, container); if (rc) { dev_err(&ctrl->dev, "%s: unable to create device for" " node %s\n", __func__, container->full_name); - of_spmi_free_device_resources(d_info); + of_spmi_free_devnode_resources(d_info); return; } } @@ -259,7 +324,7 @@ static void of_spmi_walk_dev_container(struct of_spmi_dev_info *d_info, * point all share the same slave_id. */ static void of_spmi_walk_slave_container(struct of_spmi_dev_info *d_info, - struct device_node *container) + struct device_node *container) { struct spmi_controller *ctrl = d_info->ctrl; struct device_node *node; @@ -280,24 +345,17 @@ static void of_spmi_walk_slave_container(struct of_spmi_dev_info *d_info, continue; } - rc = of_spmi_alloc_device_store(d_info, 1); - if (rc) { - dev_err(&ctrl->dev, "%s: unable to allocate" - " device resources\n", __func__); - goto slave_err; - } - of_spmi_init_resource(&r_info, node); - of_spmi_sum_node_resources(&r_info, 1); + of_spmi_sum_resources(&r_info, true); - rc = of_spmi_allocate_node_resources(d_info, &r_info, 0); + rc = of_spmi_allocate_node_resources(d_info, &r_info); if (rc) { dev_err(&ctrl->dev, "%s: unable to allocate" " resources\n", __func__); goto slave_err; } - of_spmi_populate_node_resources(d_info, &r_info, 0); + of_spmi_populate_node_resources(d_info, &r_info); rc = of_spmi_create_device(d_info, node); if (rc) { @@ -309,7 +367,7 @@ static void of_spmi_walk_slave_container(struct of_spmi_dev_info *d_info, return; slave_err: - of_spmi_free_device_resources(d_info); + of_spmi_free_node_resources(d_info); } int of_spmi_register_devices(struct spmi_controller *ctrl) @@ -374,31 +432,23 @@ int of_spmi_register_devices(struct spmi_controller *ctrl) if (!of_device_is_available(node)) continue; - rc = of_spmi_alloc_device_store(&d_info, 1); - if (rc) { - dev_err(&ctrl->dev, "%s: unable to allocate" - " device resources\n", __func__); - continue; - } - of_spmi_init_resource(&r_info, node); - of_spmi_sum_node_resources(&r_info, 0); - rc = of_spmi_allocate_node_resources(&d_info, - &r_info, 0); + of_spmi_sum_resources(&r_info, false); + rc = of_spmi_allocate_node_resources(&d_info, &r_info); if (rc) { dev_err(&ctrl->dev, "%s: unable to allocate" " resources\n", __func__); - of_spmi_free_device_resources(&d_info); + of_spmi_free_node_resources(&d_info); continue; } - of_spmi_populate_node_resources(&d_info, &r_info, 0); + of_spmi_populate_node_resources(&d_info, &r_info); rc = of_spmi_create_device(&d_info, node); if (rc) { dev_err(&ctrl->dev, "%s: unable to create" " device\n", __func__); - of_spmi_free_device_resources(&d_info); + of_spmi_free_node_resources(&d_info); continue; } } @@ -408,4 +458,4 @@ int of_spmi_register_devices(struct spmi_controller *ctrl) } EXPORT_SYMBOL(of_spmi_register_devices); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/spmi/spmi-resources.c b/drivers/spmi/spmi-resources.c index 390e9ec626b..97f15ae158c 100644 --- a/drivers/spmi/spmi-resources.c +++ b/drivers/spmi/spmi-resources.c @@ -41,7 +41,7 @@ struct resource *spmi_get_resource(struct spmi_device *dev, /* if a node is not specified, default to the first node */ if (!node) - node = &dev->dev_node[0]; + node = &dev->res; for (i = 0; i < node->num_resources; i++) { struct resource *r = &node->resource[i]; @@ -71,7 +71,7 @@ struct resource *spmi_get_resource_byname(struct spmi_device *dev, /* if a node is not specified, default to the first node */ if (!node) - node = &dev->dev_node[0]; + node = &dev->res; for (i = 0; i < node->num_resources; i++) { struct resource *r = &node->resource[i]; @@ -121,12 +121,15 @@ int spmi_get_irq_byname(struct spmi_device *dev, EXPORT_SYMBOL_GPL(spmi_get_irq_byname); /* - * spmi_get_devnode_byname - get a device node resource + * spmi_get_container_dev_byname - get a device node resource * @dev: spmi device handle * @label: device name to lookup * - * Given a name, find the associated spmi_resource that matches the name. - * Return NULL if the lookup fails. + * Only useable in spmi-dev-container configurations. Given a name, + * find the associated spmi_resource that matches the name. + * + * Return NULL if the spmi_device is not a dev-container, + * or if the lookup fails. */ struct spmi_resource *spmi_get_dev_container_byname(struct spmi_device *dev, const char *label) diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c index 0342b97f473..914df951f69 100644 --- a/drivers/spmi/spmi.c +++ b/drivers/spmi/spmi.c @@ -238,6 +238,7 @@ struct spmi_device *spmi_new_device(struct spmi_controller *ctrl, spmidev->dev.platform_data = (void *)info->platform_data; spmidev->num_dev_node = info->num_dev_node; spmidev->dev_node = info->dev_node; + spmidev->res = info->res; rc = spmi_add_device(spmidev); if (rc < 0) { diff --git a/include/linux/spmi.h b/include/linux/spmi.h index 299d3de73fd..f94b5c52335 100644 --- a/include/linux/spmi.h +++ b/include/linux/spmi.h @@ -116,7 +116,8 @@ struct spmi_resource { * @dev: Driver model representation of the device. * @name: Name of driver to use with this device. * @ctrl: SPMI controller managing the bus hosting this device. - * @dev_node: array of SPMI resources - one entry per device_node. + * @res: SPMI resource for the primary node + * @dev_node: array of SPMI resources when used with spmi-dev-container. * @num_dev_node: number of device_node structures. * @sid: Slave Identifier. */ @@ -124,6 +125,7 @@ struct spmi_device { struct device dev; const char *name; struct spmi_controller *ctrl; + struct spmi_resource res; struct spmi_resource *dev_node; u32 num_dev_node; u8 sid; @@ -132,10 +134,12 @@ struct spmi_device { /** * struct spmi_boardinfo: Declare board info for SPMI device bringup. + * @name: Name of driver to use with this device. * @slave_id: slave identifier. * @spmi_device: device to be registered with the SPMI framework. * @of_node: pointer to the OpenFirmware device node. - * @dev_node: one spmi_resource for each device_node. + * @res: SPMI resource for the primary node + * @dev_node: array of SPMI resources when used with spmi-dev-container. * @num_dev_node: number of device_node structures. * @platform_data: goes to spmi_device.dev.platform_data */ @@ -143,6 +147,7 @@ struct spmi_boardinfo { char name[SPMI_NAME_SIZE]; uint8_t slave_id; struct device_node *of_node; + struct spmi_resource res; struct spmi_resource *dev_node; u32 num_dev_node; const void *platform_data; @@ -452,6 +457,22 @@ extern int spmi_get_irq(struct spmi_device *dev, struct spmi_resource *node, extern int spmi_get_irq_byname(struct spmi_device *dev, struct spmi_resource *node, const char *name); +/** + * spmi_get_node_name - return device name for spmi node + * @dev: spmi device handle + * + * Get the primary node name of a spmi_device coresponding with + * with the 'label' binding. + * + * Returns NULL if no primary dev name has been assigned to this spmi_device. + */ +static inline const char *spmi_get_primary_dev_name(struct spmi_device *dev) +{ + if (dev->res.label) + return dev->res.label; + return NULL; +} + struct spmi_resource *spmi_get_dev_container_byname(struct spmi_device *dev, const char *label); #endif