diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index c4da22aaee3..fe151b54810 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -101,4 +101,10 @@ config OF_MTD depends on MTD def_bool y +config OF_SLIMBUS + def_tristate SLIMBUS + depends on SLIMBUS + help + OpenFirmware SLIMBUS accessors + endmenu # OF diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 34bef4bf7ef..c3a31c8c5ba 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_OF_PCI) += of_pci.o obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o obj-$(CONFIG_OF_SPMI) += of_spmi.o obj-$(CONFIG_OF_MTD) += of_mtd.o +obj-$(CONFIG_OF_SLIMBUS) += of_slimbus.o diff --git a/drivers/of/of_slimbus.c b/drivers/of/of_slimbus.c new file mode 100644 index 00000000000..512ca7350a0 --- /dev/null +++ b/drivers/of/of_slimbus.c @@ -0,0 +1,83 @@ +/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* OF helpers for SLIMbus */ +#include +#include +#include +#include +#include +#include + +int of_register_slim_devices(struct slim_controller *ctrl) +{ + struct device_node *node; + struct slim_boardinfo *binfo = NULL; + int n = 0; + int ret = 0; + + if (!ctrl->dev.of_node) + return -EINVAL; + + for_each_child_of_node(ctrl->dev.of_node, node) { + struct property *prop; + struct slim_device *slim; + char *name; + prop = of_find_property(node, "elemental-addr", NULL); + if (!prop || prop->length != 6) { + dev_err(&ctrl->dev, "of_slim: invalid E-addr"); + continue; + } + name = kzalloc(SLIMBUS_NAME_SIZE, GFP_KERNEL); + if (!name) { + dev_err(&ctrl->dev, "of_slim: out of memory"); + ret = -ENOMEM; + goto of_slim_err; + } + if (of_modalias_node(node, name, SLIMBUS_NAME_SIZE) < 0) { + dev_err(&ctrl->dev, "of_slim: modalias failure on %s\n", + node->full_name); + kfree(name); + continue; + } + slim = kzalloc(sizeof(struct slim_device), GFP_KERNEL); + if (!slim) { + dev_err(&ctrl->dev, "of_slim: out of memory"); + ret = -ENOMEM; + kfree(name); + goto of_slim_err; + } + memcpy(slim->e_addr, prop->value, 6); + + binfo = krealloc(binfo, (n + 1) * sizeof(struct slim_boardinfo), + GFP_KERNEL); + if (!binfo) { + dev_err(&ctrl->dev, "out of memory"); + kfree(name); + kfree(slim); + return -ENOMEM; + } + slim->name = (const char *)name; + binfo[n].bus_num = ctrl->nr; + binfo[n].slim_slave = slim; + n++; + } + return slim_register_board_info(binfo, n); +of_slim_err: + n--; + while (n >= 0) { + kfree(binfo[n].slim_slave->name); + kfree(binfo[n].slim_slave); + } + kfree(binfo); + return ret; +} diff --git a/include/linux/of_slimbus.h b/include/linux/of_slimbus.h new file mode 100644 index 00000000000..8e1dc657401 --- /dev/null +++ b/include/linux/of_slimbus.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#ifdef CONFIG_OF_SLIMBUS +/* + * of_slim_register_devices() - Register devices in the SLIMbus Device Tree + * @ctrl: slim_controller which devices should be registered to. + * + * This routine scans the SLIMbus Device Tree, allocating resources and + * creating slim_devices according to the SLIMbus Device Tree + * hierarchy. Details of this hierarchy can be found in + * Documentation/devicetree/bindings/slimbus. This routine is normally + * called from the probe routine of the driver registering as a + * slim_controller. + */ +extern int of_register_slim_devices(struct slim_controller *ctrl); +#else +static int of_register_slim_devices(struct slim_controller *ctrl) +{ + return 0; +} +#endif /* CONFIG_OF_SLIMBUS */