diff --git a/drivers/capebus/boards/Kconfig b/drivers/capebus/boards/Kconfig
new file mode 100644
index 0000000..76b0f94
--- /dev/null
+++ b/drivers/capebus/boards/Kconfig
@@ -0,0 +1,6 @@
+config CAPEBUS_BONE_CONTROLLER
+	bool "Beaglebone capebus board controller"
+	depends on CAPEBUS && ARCH_OMAP2PLUS && OF && I2C
+	default n
+	help
+	  "Select this to enable the beaglebone capebus board controller"
diff --git a/drivers/capebus/boards/Makefile b/drivers/capebus/boards/Makefile
new file mode 100644
index 0000000..9048231
--- /dev/null
+++ b/drivers/capebus/boards/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_CAPEBUS_BONE_CONTROLLER)	+= capebus-bone.o \
+					   capebus-bone-pdevs.o \
+					   capebus-bone-generic.o \
diff --git a/drivers/capebus/boards/capebus-bone-generic.c b/drivers/capebus/boards/capebus-bone-generic.c
new file mode 100644
index 0000000..b1b79eb
--- /dev/null
+++ b/drivers/capebus/boards/capebus-bone-generic.c
@@ -0,0 +1,237 @@
+/*
+ * TI Beaglebone capebus controller - Generic devices
+ *
+ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
+ * Copyright (C) 2012 Texas Instruments 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <video/da8xx-fb.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#include <asm/barrier.h>
+#include <plat/clock.h>
+#include <plat/omap_device.h>
+#include <linux/clkdev.h>
+#include <linux/input/ti_am335x_tsc.h>
+#include <linux/platform_data/ti_am335x_adc.h>
+#include <linux/mfd/ti_am335x_tscadc.h>
+
+#include <linux/capebus/capebus-bone.h>
+
+int bone_capebus_probe_prolog(struct cape_dev *dev,
+		const struct cape_device_id *id)
+{
+	char boardbuf[33];
+	char versionbuf[5];
+	const char *board_name;
+	const char *version;
+	const struct of_device_id *match;
+	struct pinctrl *pinctrl;
+
+	/* get the board name (also matches the cntrlboard before checking) */
+	board_name = bone_capebus_id_get_field(id, BONE_CAPEBUS_BOARD_NAME,
+			boardbuf, sizeof(boardbuf));
+	if (board_name == NULL)
+		return -ENODEV;
+
+	/* match compatible? */
+	match = capebus_of_match_device(dev, "board-name", board_name);
+	if (match == NULL)
+		return -ENODEV;
+
+	/* get the board version */
+	version = bone_capebus_id_get_field(id, BONE_CAPEBUS_VERSION,
+			versionbuf, sizeof(versionbuf));
+	if (version == NULL)
+		return -ENODEV;
+
+	pinctrl = devm_pinctrl_get_select_default(&dev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&dev->dev,
+			"pins are not configured from the driver\n");
+
+	dev_info(&dev->dev, "%s: V=%s '%s'\n", board_name,
+			version, match->compatible);
+
+	return 0;
+}
+EXPORT_SYMBOL(bone_capebus_probe_prolog);
+
+static const struct bone_capebus_generic_device_data gendevs[] = {
+	{
+		.name	= "leds",
+		.of_match = (const struct of_device_id []) {
+				{ .compatible = "gpio-leds", }, { },
+			},
+		.units	 = 0,	/* no limit */
+	}, {
+		.name	= "tps-bl",
+		.of_match = (const struct of_device_id []) {
+				{ .compatible = "tps65217-backlight", }, { },
+			},
+		.units	 = 0,	/* no limit */
+	}, {
+		.name	= "keys",
+		.of_match = (const struct of_device_id []) {
+				{ .compatible = "gpio-keys", }, { },
+			},
+		.units	 = 0,	/* no limit */
+	}, {
+		.name	= "tscadc",
+		.of_match = (const struct of_device_id []) {
+				{ .compatible = "ti-tscadc-dt", }, { },
+			},
+		.units	 = 1,
+	}, {
+		.name	= "lcdc",
+		.of_match = (const struct of_device_id []) {
+				{ .compatible = "da8xx-dt", }, { },
+			},
+		.units	 = 1,
+	},{
+		.name	= "i2c-dt",
+		.of_match = (const struct of_device_id []) {
+				{ .compatible = "i2c-dt", }, { },
+			},
+		.units	 = 0,
+	}, {
+		.name	= "w1-gpio",
+		.of_match = (const struct of_device_id []) {
+				{ .compatible = "w1-gpio", }, { },
+			},
+		.units	 = 0,
+	}, {
+		.name	= "pwm-backlight",
+		.of_match = (const struct of_device_id []) {
+				{ .compatible = "pwm-backlight", }, { },
+			},
+		.units	 = 0,	/* no limit */
+	}, {
+		.name	= "spi-dt",
+		.of_match = (const struct of_device_id []) {
+				{ .compatible = "spi-dt", }, { },
+			},
+		.units	 = 0,	/* no limit */
+	}
+};
+
+struct bone_capebus_generic_info *
+bone_capebus_probe_generic(struct cape_dev *dev,
+		const struct cape_device_id *id)
+{
+	struct bone_capebus_generic_info *info;
+	char boardbuf[33];
+	char versionbuf[5];
+	const char *board_name;
+	const char *version;
+	struct platform_device *pdev;
+	const struct bone_capebus_generic_device_data *dd;
+	struct bone_capebus_generic_device_entry *de;
+	int i;
+
+	/* get the board name (also matches the cntrlboard before checking) */
+	board_name = bone_capebus_id_get_field(id, BONE_CAPEBUS_BOARD_NAME,
+			boardbuf, sizeof(boardbuf));
+	/* get the board version */
+	version = bone_capebus_id_get_field(id, BONE_CAPEBUS_VERSION,
+			versionbuf, sizeof(versionbuf));
+
+	/* should never happen, but it doesn't hurt to play it safe */
+	if (board_name == NULL || version == NULL)
+		return ERR_PTR(-ENODEV);
+
+	info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
+	if (info == NULL) {
+		dev_err(&dev->dev, "Failed to allocate info\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	info->dev = dev;
+	INIT_LIST_HEAD(&info->pdev_list);
+
+	/* iterate over the supported devices */
+	for (i = 0, dd = gendevs; i < ARRAY_SIZE(gendevs); i++, dd++) {
+
+		pdev = capebus_of_platform_compatible_device_create(dev,
+			dd->of_match, dd->name, "version", version);
+
+		/* node not found (mostly harmless) */
+		if (IS_ERR(pdev) && PTR_ERR(pdev) == -ENXIO) {
+			/* TODO: deal with required nodes */
+			continue;
+		}
+
+		/* failed to create due to an error; fatal */
+		if (IS_ERR_OR_NULL(pdev)) {
+			dev_err(&dev->dev, "failed to create device %s\n",
+					dd->name);
+			goto err_fail;
+		}
+
+		de = devm_kzalloc(&dev->dev, sizeof(*de), GFP_KERNEL);
+		if (de == NULL) {
+			dev_err(&dev->dev, "failed to allocate entry for %s\n",
+					dd->name);
+			goto err_fail;
+		}
+
+		/* add it to the list */
+		de->data = dd;
+		de->pdev = pdev;
+		list_add_tail(&de->node, &info->pdev_list);
+	}
+
+	return info;
+
+err_fail:
+	bone_capebus_remove_generic(info);
+	return NULL;
+}
+EXPORT_SYMBOL(bone_capebus_probe_generic);
+
+void bone_capebus_remove_generic(struct bone_capebus_generic_info *info)
+{
+	struct list_head *lh, *lhn;
+	struct bone_capebus_generic_device_entry *de;
+
+	if (info == NULL || info->dev == NULL)
+		return;
+
+	list_for_each_safe(lh, lhn, &info->pdev_list) {
+		de = list_entry(lh, struct bone_capebus_generic_device_entry,
+				node);
+		list_del(lh);
+		platform_device_unregister(de->pdev);
+		devm_kfree(&info->dev->dev, de);
+	}
+	devm_kfree(&info->dev->dev, info);
+}
+EXPORT_SYMBOL(bone_capebus_remove_generic);
diff --git a/drivers/capebus/boards/capebus-bone-pdevs.c b/drivers/capebus/boards/capebus-bone-pdevs.c
new file mode 100644
index 0000000..a55aad6
--- /dev/null
+++ b/drivers/capebus/boards/capebus-bone-pdevs.c
@@ -0,0 +1,602 @@
+/*
+ * TI Beaglebone capebus controller - Platform adapters
+ *
+ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
+ * Copyright (C) 2012 Texas Instruments 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <video/da8xx-fb.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#include <asm/barrier.h>
+#include <plat/clock.h>
+#include <plat/omap_device.h>
+#include <linux/clkdev.h>
+#include <linux/input/ti_am335x_tsc.h>
+#include <linux/platform_data/ti_am335x_adc.h>
+#include <linux/mfd/ti_am335x_tscadc.h>
+#include <linux/i2c.h>
+#include <linux/of_i2c.h>
+#include <linux/spi/spi.h>
+
+#include <linux/capebus/capebus-bone.h>
+
+#if defined(CONFIG_FB_DA8XX) || defined(CONFIG_FB_DA8XX_MODULE)
+
+struct da8xx_priv {
+	struct da8xx_lcdc_platform_data lcd_pdata;
+	struct lcd_ctrl_config lcd_cfg;
+	struct display_panel lcd_panel;
+	struct platform_device *lcdc_pdev;
+	struct omap_hwmod *lcdc_oh;
+	struct resource lcdc_res[1];
+	int power_dn_gpio;
+};
+
+static const struct of_device_id of_da8xx_dt_match[] = {
+	{ .compatible = "da8xx-dt", },
+	{},
+};
+
+static int __devinit da8xx_dt_probe(struct platform_device *pdev)
+{
+	struct da8xx_priv *priv;
+	struct clk *disp_pll;
+	struct pinctrl *pinctrl;
+	u32 disp_pll_val;
+	const char *panel_type;
+	int ret = -EINVAL;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (priv == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate priv\n");
+		return -ENOMEM;
+	}
+	priv->power_dn_gpio = -1;
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev,
+			"pins are not configured from the driver\n");
+
+	ret = of_property_read_u32(pdev->dev.of_node, "disp-pll", &disp_pll_val);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "Failed to read disp-pll property\n");
+		return ret;
+	}
+
+	ret = of_property_read_string(pdev->dev.of_node, "panel-type", &panel_type);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "Failed to read panel-type property\n");
+		return ret;
+	}
+
+	/* conf_disp_pll(disp_pll); */
+	disp_pll = clk_get(NULL, "dpll_disp_ck");
+	if (IS_ERR(disp_pll)) {
+		dev_err(&pdev->dev, "Cannot clk_get disp_pll\n");
+		return PTR_ERR(disp_pll);
+	}
+	ret = clk_set_rate(disp_pll, disp_pll_val);
+	clk_put(disp_pll);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "Failed to set disp_pll\n");
+		return ret;
+	}
+
+	ret = of_get_named_gpio_flags(pdev->dev.of_node, "powerdn-gpio",
+			0, NULL);
+	if (IS_ERR_VALUE(ret)) {
+		dev_info(&pdev->dev, "No power down GPIO\n");
+	} else {
+		priv->power_dn_gpio = ret;
+
+		ret = devm_gpio_request(&pdev->dev, priv->power_dn_gpio, "bone-dvi-cape:DVI_PDN");
+		if (ret != 0) {
+			dev_err(&pdev->dev, "Failed to gpio_request\n");
+			return ret;
+		}
+
+		ret = gpio_direction_output(priv->power_dn_gpio, 1);
+		if (ret != 0) {
+			dev_err(&pdev->dev, "Failed to set powerdn to 1\n");
+			return ret;
+		}
+	}
+
+	/* display_panel */
+	priv->lcd_panel.panel_type	= QVGA;
+	priv->lcd_panel.max_bpp		= 16;
+	priv->lcd_panel.min_bpp		= 16;
+	priv->lcd_panel.panel_shade	= COLOR_ACTIVE;
+
+	/* lcd_ctrl_config */
+	priv->lcd_cfg.p_disp_panel	= &priv->lcd_panel;
+	priv->lcd_cfg.ac_bias		= 255;
+	priv->lcd_cfg.ac_bias_intrpt	= 0;
+	priv->lcd_cfg.dma_burst_sz	= 16;
+	priv->lcd_cfg.bpp		= 16;
+	priv->lcd_cfg.fdd		= 0x80;
+	priv->lcd_cfg.tft_alt_mode	= 0;
+	priv->lcd_cfg.stn_565_mode	= 0;
+	priv->lcd_cfg.mono_8bit_mode	= 0;
+	priv->lcd_cfg.invert_line_clock	= 1;
+	priv->lcd_cfg.invert_frm_clock	= 1;
+	priv->lcd_cfg.sync_edge		= 0;
+	priv->lcd_cfg.sync_ctrl		= 1;
+	priv->lcd_cfg.raster_order	= 0;
+
+	/* da8xx_lcdc_platform_data */
+	strcpy(priv->lcd_pdata.manu_name, "BBToys");
+	priv->lcd_pdata.controller_data = &priv->lcd_cfg;
+	strcpy(priv->lcd_pdata.type, panel_type);
+
+	priv->lcdc_oh = omap_hwmod_lookup("lcdc");
+	if (priv->lcdc_oh == NULL) {
+		dev_err(&pdev->dev, "Failed to lookup omap_hwmod lcdc\n");
+		return -ENODEV;
+	}
+
+	priv->lcdc_pdev = omap_device_build("da8xx_lcdc", 0, priv->lcdc_oh,
+			&priv->lcd_pdata,
+			sizeof(struct da8xx_lcdc_platform_data),
+			NULL, 0, 0);
+	if (priv->lcdc_pdev == NULL) {
+		dev_err(&pdev->dev, "Failed to build LCDC device\n");
+		return -ENODEV;
+	}
+
+	dev_info(&pdev->dev, "Registered bone LCDC OK.\n");
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
+}
+
+static int __devexit da8xx_dt_remove(struct platform_device *pdev)
+{
+	return -EINVAL;	/* not supporting removal yet */
+}
+
+static struct platform_driver da8xx_dt_driver = {
+	.probe		= da8xx_dt_probe,
+	.remove		= __devexit_p(da8xx_dt_remove),
+	.driver		= {
+		.name	= "da8xx-dt",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_da8xx_dt_match,
+	},
+};
+
+#endif
+
+#if defined(CONFIG_MFD_TI_AM335X_TSCADC) || defined(CONFIG_MFD_TI_AM335X_TSCADC_MODULE)
+
+struct ti_tscadc_priv {
+	struct omap_hwmod *tsc_oh;
+	struct tsc_data tsc_data;
+	struct adc_data adc_data;
+	struct mfd_tscadc_board tscadc_data;
+	struct platform_device *tscadc_pdev;
+};
+
+static const struct of_device_id of_ti_tscadc_dt_match[] = {
+	{ .compatible = "ti-tscadc-dt", },
+	{},
+};
+
+static int __devinit ti_tscadc_dt_probe(struct platform_device *pdev)
+{
+	struct ti_tscadc_priv *priv;
+	struct pinctrl *pinctrl;
+	u32 val;
+	int ret;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (priv == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate priv\n");
+		return -ENOMEM;
+	}
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev,
+			"pins are not configured from the driver\n");
+
+	ret = of_property_read_u32(pdev->dev.of_node, "tsc-wires", &val);
+	if (ret != 0) {
+		dev_info(&pdev->dev, "no tsc-wires property; disabling TSC\n");
+		val = 0;
+	}
+	priv->tsc_data.wires = val;
+
+	if (priv->tsc_data.wires > 0) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+				"tsc-x-plate-resistance", &val);
+		if (ret != 0) {
+			dev_err(&pdev->dev, "Failed to read "
+					"tsc-x-plate-resistance property\n");
+			return ret;
+		}
+		priv->tsc_data.x_plate_resistance = val;
+
+		ret = of_property_read_u32(pdev->dev.of_node,
+				"tsc-steps", &val);
+		if (ret != 0) {
+			dev_err(&pdev->dev, "Failed to read "
+					"tsc-steps property\n");
+			return ret;
+		}
+		priv->tsc_data.steps_to_configure = val;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node, "adc-channels", &val);
+	if (ret != 0) {
+		dev_info(&pdev->dev, "No adc-channels property; disabling adc\n");
+		val = 0;
+	}
+	priv->adc_data.adc_channels = val;
+
+	priv->tscadc_data.tsc_init = &priv->tsc_data;
+	priv->tscadc_data.adc_init = &priv->adc_data;
+
+	priv->tsc_oh = omap_hwmod_lookup("adc_tsc");
+	if (priv->tsc_oh == NULL) {
+		dev_err(&pdev->dev, "Could not lookup HWMOD %s\n", "adc_tsc");
+		return -ENODEV;
+	}
+
+	priv->tscadc_pdev = omap_device_build("ti_tscadc", -1, priv->tsc_oh,
+			&priv->tscadc_data, sizeof(priv->tscadc_data),
+			NULL, 0, 0);
+	if (priv->tscadc_pdev == NULL) {
+		dev_err(&pdev->dev, "Could not create tsc_adc device\n");
+		return -ENODEV;
+	}
+
+	dev_info(&pdev->dev, "TI tscadc pdev created OK\n");
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
+}
+
+static int __devexit ti_tscadc_dt_remove(struct platform_device *pdev)
+{
+	return -EINVAL;	/* not supporting removal yet */
+}
+
+static struct platform_driver ti_tscadc_dt_driver = {
+	.probe		= ti_tscadc_dt_probe,
+	.remove		= __devexit_p(ti_tscadc_dt_remove),
+	.driver		= {
+		.name	= "ti_tscadc-dt",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_ti_tscadc_dt_match,
+	},
+};
+
+#endif
+
+struct i2c_priv {
+	struct i2c_adapter *i2c_adapter;
+	phandle parent_handle;
+};
+
+static const struct of_device_id of_i2c_dt_match[] = {
+	{ .compatible = "i2c-dt", },
+	{},
+};
+
+static int __devinit i2c_dt_probe(struct platform_device *pdev)
+{
+	struct i2c_priv *priv = NULL;
+	int ret = -EINVAL;
+	struct device_node *adap_node;
+	u32 val;
+
+	if (pdev->dev.of_node == NULL) {
+		dev_err(&pdev->dev, "Only support OF case\n");
+		return -ENOMEM;
+	}
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (priv == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate priv\n");
+		return -ENOMEM;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node, "parent", &val);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "Failed to find parent property\n");
+		goto err_prop_fail;
+	}
+	priv->parent_handle = val;
+
+	adap_node = of_find_node_by_phandle(priv->parent_handle);
+	if (adap_node == NULL) {
+		dev_err(&pdev->dev, "Failed to find i2c adapter node\n");
+		ret = -EINVAL;
+		goto err_node_fail;
+	}
+
+	ret = capebus_of_platform_device_enable(adap_node);
+	if (ret != 0) {
+		dev_info(&pdev->dev, "I2C adapter platform device failed "
+				"to enable\n");
+		goto err_enable_fail;
+	}
+
+	priv->i2c_adapter = of_find_i2c_adapter_by_node(adap_node);
+	if (priv->i2c_adapter == NULL) {
+		dev_err(&pdev->dev, "Failed to find i2c adapter node\n");
+		ret = -EINVAL;
+		goto err_adap_fail;
+	}
+
+	of_i2c_register_node_devices(priv->i2c_adapter, pdev->dev.of_node);
+
+	of_node_put(adap_node);
+
+	dev_info(&pdev->dev, "Registered bone I2C OK.\n");
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
+err_adap_fail:
+	of_node_put(adap_node);
+err_enable_fail:
+	/* nothing */
+err_node_fail:
+	/* nothing */
+err_prop_fail:
+	devm_kfree(&pdev->dev, priv);
+	return ret;
+}
+
+static int __devexit i2c_dt_remove(struct platform_device *pdev)
+{
+	return -EINVAL;	/* not supporting removal yet */
+}
+
+static struct platform_driver i2c_dt_driver = {
+	.probe		= i2c_dt_probe,
+	.remove		= __devexit_p(i2c_dt_remove),
+	.driver		= {
+		.name	= "i2c-dt",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_i2c_dt_match,
+	},
+};
+
+struct spi_priv {
+	struct spi_master *master;
+	phandle parent_handle;
+};
+
+static const struct of_device_id of_spi_dt_match[] = {
+	{ .compatible = "spi-dt", },
+	{},
+};
+
+static int of_dev_node_match(struct device *dev, void *data)
+{
+        return dev->of_node == data;
+}
+
+/* must call put_device() when done with returned i2c_adapter device */
+static struct spi_master *of_find_spi_master_by_node(struct device_node *node)
+{
+	struct device *dev;
+	struct spi_master *master;
+
+	dev = class_find_device(&spi_master_class, NULL, node,
+					 of_dev_node_match);
+	if (!dev)
+		return NULL;
+
+	master = container_of(dev, struct spi_master, dev);
+
+	/* TODO: No checks what-so-ever... be careful. */
+	return master;
+}
+
+static int __devinit spi_dt_probe(struct platform_device *pdev)
+{
+	struct spi_priv *priv = NULL;
+	int ret = -EINVAL;
+	struct device_node *master_node;
+	u32 val;
+
+	if (pdev->dev.of_node == NULL) {
+		dev_err(&pdev->dev, "Only support OF case\n");
+		return -ENOMEM;
+	}
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (priv == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate priv\n");
+		return -ENOMEM;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node, "parent", &val);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "Failed to find parent property\n");
+		goto err_prop_fail;
+	}
+	priv->parent_handle = val;
+
+	master_node = of_find_node_by_phandle(priv->parent_handle);
+	if (master_node == NULL) {
+		dev_err(&pdev->dev, "Failed to find spi bus master node\n");
+		ret = -EINVAL;
+		goto err_node_fail;
+	}
+
+	ret = capebus_of_platform_device_enable(master_node);
+	if (ret != 0) {
+		dev_info(&pdev->dev, "SPI platform device failed to enable\n");
+		goto err_enable_fail;
+	}
+
+	priv->master = of_find_spi_master_by_node(master_node);
+	if (priv->master == NULL) {
+		dev_err(&pdev->dev, "Failed to find bus master node\n");
+		ret = -EINVAL;
+		goto err_master_fail;
+	}
+
+	of_register_node_spi_devices(priv->master, pdev->dev.of_node);
+
+	of_node_put(master_node);
+
+	dev_info(&pdev->dev, "Registered bone SPI OK.\n");
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
+err_master_fail:
+	of_node_put(master_node);
+err_enable_fail:
+	/* nothing */
+err_node_fail:
+	/* nothing */
+err_prop_fail:
+	devm_kfree(&pdev->dev, priv);
+	return ret;
+}
+
+static int __devexit spi_dt_remove(struct platform_device *pdev)
+{
+	return -EINVAL;	/* not supporting removal yet */
+}
+
+static struct platform_driver spi_dt_driver = {
+	.probe		= spi_dt_probe,
+	.remove		= __devexit_p(spi_dt_remove),
+	.driver		= {
+		.name	= "spi-dt",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_spi_dt_match,
+	},
+};
+
+/*
+ *
+ */
+struct bone_capebus_pdev_driver {
+	struct platform_driver *driver;
+	unsigned int registered : 1;
+	/* more? */
+};
+
+static struct bone_capebus_pdev_driver pdev_drivers[] = {
+#if defined(CONFIG_FB_DA8XX) || defined(CONFIG_FB_DA8XX_MODULE)
+	{
+		.driver		= &da8xx_dt_driver,
+	},
+#endif
+#if defined(CONFIG_MFD_TI_AM335X_TSCADC) || defined(CONFIG_MFD_TI_AM335X_TSCADC_MODULE)
+	{
+		.driver		= &ti_tscadc_dt_driver,
+	},
+#endif
+	{
+		.driver		= &i2c_dt_driver,
+	},
+	{
+		.driver		= &spi_dt_driver,
+	},
+	{
+		.driver		= NULL,
+	}
+};
+
+int bone_capebus_register_pdev_adapters(struct bone_capebus_bus *bus)
+{
+	struct bone_capebus_pdev_driver *drvp;
+	int err;
+
+	/* first check if we do it twice */
+	for (drvp = pdev_drivers; drvp->driver != NULL; drvp++)
+		if (drvp->registered)
+			return -EBUSY;
+
+	for (drvp = pdev_drivers; drvp->driver != NULL; drvp++) {
+
+		err = platform_driver_register(drvp->driver);
+		if (err != 0)
+			goto err_out;
+
+		drvp->registered = 1;
+
+		dev_info(bus->dev, "Registered %s "
+				"platform driver\n", drvp->driver->driver.name);
+	}
+
+	return 0;
+
+err_out:
+	dev_err(bus->dev, "Failed to register %s "
+			"platform driver\n", drvp->driver->driver.name);
+
+	/* unregister */
+	while (--drvp >= pdev_drivers) {
+
+		if (!drvp->registered)
+			continue;
+
+		platform_driver_unregister(drvp->driver);
+	}
+
+	return err;
+}
+
+void bone_capebus_unregister_pdev_adapters(struct bone_capebus_bus *bus)
+{
+	struct bone_capebus_pdev_driver *drvp;
+
+	/* unregister */
+	drvp = &pdev_drivers[ARRAY_SIZE(pdev_drivers)];
+	while (--drvp >= pdev_drivers) {
+
+		if (drvp->driver == NULL)	/* skip terminator */
+			continue;
+
+		if (!drvp->registered)
+			continue;
+
+		platform_driver_unregister(drvp->driver);
+
+		drvp->registered = 0;
+	}
+}
diff --git a/drivers/capebus/boards/capebus-bone.c b/drivers/capebus/boards/capebus-bone.c
new file mode 100644
index 0000000..33a6bde
--- /dev/null
+++ b/drivers/capebus/boards/capebus-bone.c
@@ -0,0 +1,931 @@
+/*
+ * TI Beaglebone capebus controller
+ *
+ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
+ * Copyright (C) 2012 Texas Instruments 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_i2c.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+
+#include <linux/capebus.h>
+#include <linux/capebus/capebus-bone.h>
+
+/* what to fill in to the cntrlboard field of the id */
+#define BONE_CAPEBUS_CNTRLBOARD		"beaglebone"
+
+/* various EEPROM definition for the bone */
+struct bone_capebus_eeprom_field {
+	const char 	*name;
+	int 		start;
+	int		size;
+	unsigned int	ascii : 1;
+	unsigned int	strip_trailing_dots : 1;
+	const char	*override;
+};
+
+static const struct bone_capebus_eeprom_field eeprom_fields[] = {
+	[BONE_CAPEBUS_HEADER] = {
+		.name		= "header",
+		.start		= 0,
+		.size		= 4,
+		.ascii		= 0,
+		.override	= "\xaa\x55\x33\xee",	/* AA 55 33 EE */
+	},
+	[BONE_CAPEBUS_EEPROM_REV] = {
+		.name		= "eeprom-format-revision",
+		.start		= 4,
+		.size		= 2,
+		.ascii		= 1,
+		.override	= "A0",
+	},
+	[BONE_CAPEBUS_BOARD_NAME] = {
+		.name		= "board-name",
+		.start		= 6,
+		.size		= 32,
+		.ascii		= 1,
+		.strip_trailing_dots = 1,
+		.override	= "Override Board Name",
+	},
+	[BONE_CAPEBUS_VERSION] = {
+		.name		= "version",
+		.start		= 38,
+		.size		= 4,
+		.ascii		= 1,
+		.override	= "00A0",
+	},
+	[BONE_CAPEBUS_MANUFACTURER] = {
+		.name		= "manufacturer",
+		.start		= 42,
+		.size		= 16,
+		.ascii		= 1,
+		.strip_trailing_dots = 1,
+		.override	= "Override Manuf",
+	},
+	[BONE_CAPEBUS_PART_NUMBER] = {
+		.name		= "part-number",
+		.start		= 58,
+		.size		= 16,
+		.ascii		= 1,
+		.override	= "Override Part#",
+	},
+	[BONE_CAPEBUS_NUMBER_OF_PINS] = {
+		.name		= "number-of-pins",
+		.start		= 74,
+		.size		= 2,
+		.ascii		= 0,
+		.override	= NULL,
+	},
+	[BONE_CAPEBUS_SERIAL_NUMBER] = {
+		.name		= "serial-number",
+		.start		= 76,
+		.size		= 12,
+		.ascii		= 1,
+		.override	= "0000000000",
+	},
+	[BONE_CAPEBUS_PIN_USAGE] = {
+		.name		= "pin-usage",
+		.start		= 88,
+		.size		= 140,
+		.ascii		= 0,
+		.override	= NULL,
+	},
+	[BONE_CAPEBUS_VDD_3V3EXP] = {
+		.name		= "vdd-3v3exp",
+		.start		= 228,
+		.size		= 2,
+		.ascii		= 0,
+		.override	= NULL,
+	},
+	[BONE_CAPEBUS_VDD_5V] = {
+		.name		= "vdd-5v",
+		.start		= 230,
+		.size		= 2,
+		.ascii		= 0,
+		.override	= NULL,
+	},
+	[BONE_CAPEBUS_SYS_5V] = {
+		.name		= "sys-5v",
+		.start		= 232,
+		.size		= 2,
+		.ascii		= 0,
+		.override	= NULL,
+	},
+	[BONE_CAPEBUS_DC_SUPPLIED] = {
+		.name		= "dc-supplied",
+		.start		= 234,
+		.size		= 2,
+		.ascii		= 0,
+		.override	= NULL,
+	},
+};
+
+char *bone_capebus_id_get_field(const struct cape_device_id *id,
+		int field, char *buf, int bufsz)
+{
+	const struct bone_capebus_eeprom_field *ee_field;
+	int len;
+
+	/* make sure the ID is valid for the bone */
+	if (bone_capebus_match_cntrlboard(id) != 0)
+		return NULL;
+
+	if ((unsigned int)field >= ARRAY_SIZE(eeprom_fields))
+		return NULL;
+
+	ee_field = &eeprom_fields[field];
+
+	/* enough space? */
+	if (bufsz < ee_field->size + ee_field->ascii)
+		return NULL;
+
+	memcpy(buf, (char *)id->data + ee_field->start, ee_field->size);
+
+	/* terminate ascii field */
+	if (ee_field->ascii)
+		buf[ee_field->size] = '\0';;
+
+	if (ee_field->strip_trailing_dots) {
+		len = strlen(buf);
+		while (len > 1 && buf[len - 1] == '.')
+			buf[--len] = '\0';
+	}
+
+	return buf;
+}
+EXPORT_SYMBOL(bone_capebus_id_get_field);
+
+int bone_capebus_match_cntrlboard(const struct cape_device_id *id)
+{
+	if (strcmp(id->cntrlboard, BONE_CAPEBUS_CNTRLBOARD) != 0)
+		return -ENODEV;
+	return 0;
+}
+EXPORT_SYMBOL(bone_capebus_match_cntrlboard);
+
+int bone_capebus_match_board(const struct cape_device_id *id,
+		const char **board_names)
+{
+	char rname[33];
+	const char *s;
+	int ret;
+	int i;
+
+	/* be safe; check for matching cntrlboard */
+	ret = bone_capebus_match_cntrlboard(id);
+	if (ret != 0)
+		return ret;
+
+	s = bone_capebus_id_get_field(id, BONE_CAPEBUS_BOARD_NAME,
+			rname, sizeof(rname));
+	if (s == NULL)
+		return -EINVAL;
+
+	i = 0;
+	while (*board_names) {
+		if (strcmp(rname, *board_names) == 0)
+			return i;
+		board_names++;
+	}
+
+	return -1;
+}
+EXPORT_SYMBOL(bone_capebus_match_board);
+
+#ifdef CONFIG_OF
+static const struct of_device_id bone_capebus_of_match[] = {
+	{
+		.compatible = "bone-capebus",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, bone_capebus_of_match);
+
+static const struct of_device_id slot_override_of_match[] = {
+	{
+		.compatible = "bone-capebus-slot-override",
+	},
+	{ },
+};
+
+#endif
+
+const struct cape_device_id *bone_capebus_get_dev_id(struct cape_slot *slot)
+{
+	struct cape_bus *bus = slot->bus;
+	struct bone_capebus_slot *bone_slot = to_bone_capebus_slot(slot);
+	struct i2c_client *client = bone_slot->client;
+	struct cape_device_id *id;
+	const u8 *p;
+	int r;
+	char board_name[32+1];
+	char version[4+1];
+	char manufacturer[16+1];
+	char part_number[16+1];
+
+	id = &bone_slot->id;
+
+	/* need to read EEPROM? */
+	if (!bone_slot->eeprom_probed) {
+
+		bone_slot->eeprom_probed = 1;
+
+		if (!bone_slot->eeprom_override) {
+			r = i2c_memory_read(bone_slot->client,
+				bone_slot->eeprom_signature, 0,
+				sizeof(bone_slot->eeprom_signature));
+			if (r != sizeof(bone_slot->eeprom_signature)) {
+				dev_err(&bus->dev,
+					"bone: Failed to read EEPROM at "
+					"slot %d (addr 0x%02x)\n",
+					slot->slotno, client->addr & 0x7f);
+				bone_slot->eeprom_failed = 1;
+				return NULL;
+			}
+		} else
+			dev_info(&bus->dev,
+				"bone: Using override eeprom data at slot %d\n",
+				slot->slotno);
+
+		p = bone_slot->eeprom_signature;
+		if (BONE_CAPEBUS_MAKE_HEADER(p) != BONE_CAPEBUS_HEADER_VALID) {
+			dev_err(&bus->dev, "bone: Invalid EEPROM signature "
+				"'%08x' at slot %d (addr 0x%02x)\n",
+				BONE_CAPEBUS_MAKE_HEADER(p),
+				slot->slotno, client->addr & 0x7f);
+			bone_slot->eeprom_failed = 1;
+			return NULL;
+		}
+
+		bone_slot->id.cntrlboard = BONE_CAPEBUS_CNTRLBOARD;
+		bone_slot->id.len = sizeof(bone_slot->eeprom_signature);
+		bone_slot->id.data = bone_slot->eeprom_signature;
+
+		bone_capebus_id_get_field(id, BONE_CAPEBUS_BOARD_NAME,
+					board_name, sizeof(board_name));
+		bone_capebus_id_get_field(id, BONE_CAPEBUS_VERSION,
+					version, sizeof(version));
+		bone_capebus_id_get_field(id, BONE_CAPEBUS_MANUFACTURER,
+					manufacturer, sizeof(manufacturer));
+		bone_capebus_id_get_field(id, BONE_CAPEBUS_PART_NUMBER,
+					part_number, sizeof(part_number));
+
+		/* board_name,version,manufacturer,part_number */
+		snprintf(bone_slot->text_id, sizeof(bone_slot->text_id) - 1,
+				"%s,%s,%s,%s", board_name, version,
+				manufacturer, part_number);
+
+		/* terminate always */
+		bone_slot->text_id[sizeof(bone_slot->text_id) - 1] = '\0';
+
+	}
+
+	/* slot has failed and we don't support hotpluging */
+	if (bone_slot->eeprom_failed)
+		return NULL;
+
+	return id;
+}
+
+const char *bone_capebus_get_text_dev_id(struct cape_slot *slot)
+{
+	struct bone_capebus_slot *bone_slot = to_bone_capebus_slot(slot);
+
+	if (bone_slot->eeprom_failed || !bone_slot->eeprom_probed)
+		return NULL;
+
+	return bone_slot->text_id;
+}
+
+struct bonedev_ee_attribute {
+	struct device_attribute devattr;
+	unsigned int field;
+};
+#define to_bonedev_ee_attribute(x) \
+	container_of((x), struct bonedev_ee_attribute, devattr)
+
+static ssize_t bonedev_ee_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct bonedev_ee_attribute *ee_attr = to_bonedev_ee_attribute(attr);
+	struct cape_dev *cdev = to_cape_dev(dev);
+	const struct cape_device_id *id = cdev->id;
+	const struct bone_capebus_eeprom_field *ee_field;
+	int i, len;
+	char *p, *s;
+	u16 val;
+
+	if (id == NULL)
+		return -EINVAL;
+
+	/* add newline for ascii fields */
+	ee_field = &eeprom_fields[ee_attr->field];
+
+	len = ee_field->size + ee_field->ascii;
+	p = kmalloc(len, GFP_KERNEL);
+	if (p == NULL)
+		return -ENOMEM;
+
+	s = bone_capebus_id_get_field(id, ee_attr->field, p, len);
+	if (s == NULL)
+		return -EINVAL;
+
+	/* add newline for ascii fields and return */
+	if (ee_field->ascii) {
+		len = sprintf(buf, "%s\n", s);
+		goto out;
+	}
+
+	/* case by case handling */
+	switch (ee_attr->field) {
+		case BONE_CAPEBUS_HEADER:
+			len = sprintf(buf, "%02x %02x %02x %02x\n",
+					s[0], s[1], s[2], s[3]);
+			break;
+
+			/* 2 bytes */
+		case BONE_CAPEBUS_NUMBER_OF_PINS:
+		case BONE_CAPEBUS_VDD_3V3EXP:
+		case BONE_CAPEBUS_VDD_5V:
+		case BONE_CAPEBUS_SYS_5V:
+		case BONE_CAPEBUS_DC_SUPPLIED:
+			/* the bone is LE */
+			val = s[0] & (s[1] << 8);
+			len = sprintf(buf, "%u\n", (unsigned int)val & 0xffff);
+			break;
+
+		case BONE_CAPEBUS_PIN_USAGE:
+
+			len = 0;
+			for (i = 0; i < ee_field->size / 2; i++) {
+				/* the bone is LE */
+				val = s[0] & (s[1] << 8);
+				sprintf(buf, "%04x\n", val);
+				buf += 5;
+				len += 5;
+				s += 2;
+			}
+
+			break;
+
+		default:
+			*buf = '\0';
+			len = 0;
+			break;
+	}
+
+out:
+	kfree(p);
+
+	return len;
+}
+
+#define BONEDEV_EE_ATTR(_name, _field) \
+	{ \
+		.devattr = __ATTR(_name, 0440, bonedev_ee_show, NULL), \
+		.field = BONE_CAPEBUS_##_field , \
+	}
+
+struct bonedev_ee_attribute ee_attrs[] = {
+	BONEDEV_EE_ATTR(header, HEADER),
+	BONEDEV_EE_ATTR(eeprom-format-revision, EEPROM_REV),
+	BONEDEV_EE_ATTR(board-name, BOARD_NAME),
+	BONEDEV_EE_ATTR(version, VERSION),
+	BONEDEV_EE_ATTR(manufacturer, MANUFACTURER),
+	BONEDEV_EE_ATTR(part-number, PART_NUMBER),
+	BONEDEV_EE_ATTR(number-of-pins, NUMBER_OF_PINS),
+	BONEDEV_EE_ATTR(serial-number, SERIAL_NUMBER),
+	BONEDEV_EE_ATTR(pin-usage, PIN_USAGE),
+	BONEDEV_EE_ATTR(vdd-3v3exp, VDD_3V3EXP),
+	BONEDEV_EE_ATTR(vdd-5v, VDD_5V),
+	BONEDEV_EE_ATTR(sys-5v, SYS_5V),
+	BONEDEV_EE_ATTR(dc-supplied, DC_SUPPLIED),
+};
+
+static struct attribute *ee_attrs_flat[] = {
+	&ee_attrs[BONE_CAPEBUS_HEADER		].devattr.attr,
+	&ee_attrs[BONE_CAPEBUS_EEPROM_REV	].devattr.attr,
+	&ee_attrs[BONE_CAPEBUS_BOARD_NAME	].devattr.attr,
+	&ee_attrs[BONE_CAPEBUS_VERSION		].devattr.attr,
+	&ee_attrs[BONE_CAPEBUS_MANUFACTURER	].devattr.attr,
+	&ee_attrs[BONE_CAPEBUS_PART_NUMBER	].devattr.attr,
+	&ee_attrs[BONE_CAPEBUS_NUMBER_OF_PINS	].devattr.attr,
+	&ee_attrs[BONE_CAPEBUS_SERIAL_NUMBER	].devattr.attr,
+	&ee_attrs[BONE_CAPEBUS_PIN_USAGE	].devattr.attr,
+	&ee_attrs[BONE_CAPEBUS_VDD_3V3EXP	].devattr.attr,
+	&ee_attrs[BONE_CAPEBUS_VDD_5V		].devattr.attr,
+	&ee_attrs[BONE_CAPEBUS_SYS_5V		].devattr.attr,
+	&ee_attrs[BONE_CAPEBUS_DC_SUPPLIED	].devattr.attr,
+	NULL,
+};
+
+static const struct attribute_group bone_ee_attrgroup = {
+	.name		= "ee-fields",
+	.is_visible 	= NULL,
+	.attrs 		= ee_attrs_flat,
+};
+
+static int bone_capebus_sysfs_register(struct cape_dev *dev)
+{
+	return sysfs_create_group(&dev->dev.kobj, &bone_ee_attrgroup);
+}
+
+static void bone_capebus_sysfs_unregister(struct cape_dev *dev)
+{
+	sysfs_remove_group(&dev->dev.kobj, &bone_ee_attrgroup);
+}
+
+static int bone_capebus_dev_probed(struct cape_dev *dev)
+{
+	return 0;
+}
+
+static void bone_capebus_dev_removed(struct cape_dev *dev)
+{
+	bone_capebus_sysfs_unregister(dev);
+}
+
+static int bone_capebus_dev_registered(struct cape_dev *dev)
+{
+	int ret;
+
+	ret = bone_capebus_sysfs_register(dev);
+	if (ret != 0) {
+		dev_err(&dev->dev, "bone_capebus sysfs registration failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct cape_bus_ops bone_capebus_ops = {
+	.get_dev_id 		= bone_capebus_get_dev_id,
+	.get_text_dev_id	= bone_capebus_get_text_dev_id,
+	.dev_probed		= bone_capebus_dev_probed,
+	.dev_removed		= bone_capebus_dev_removed,
+	.dev_registered		= bone_capebus_dev_registered,
+};
+
+static ssize_t slots_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_capebus_bus	*bus = platform_get_drvdata(pdev);
+	struct bone_capebus_slot *slot;
+	ssize_t len, sz;
+	int i;
+
+	sz = 0;
+
+	for (i = 0; i < bus->slots_nr; i++) {
+		slot = &bus->slots[i];
+
+		len = sprintf(buf, "%02x:%c%c%c%c %s\n",
+				(int)slot->eeprom_addr & 0x7f,
+				slot->eeprom_probed     ? 'P' : '-',
+				slot->eeprom_failed     ? 'F' : '-',
+				slot->eeprom_override   ? 'O' : '-',
+				(slot->cape_slot.dev && slot->cape_slot.dev->added) ? 'A' : '-',
+				slot->text_id);
+
+		buf += len;
+		sz += len;
+	}
+	return sz;
+}
+
+static ssize_t slots_store(struct device *dev, struct device_attribute *attr,
+		 const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_capebus_bus	*bus = platform_get_drvdata(pdev);
+	int slotno, err, i, len;
+	char *s, *board_name, *version, *p;
+	const struct bone_capebus_eeprom_field *ee_field, *eebrd, *eevrs;
+	struct bone_capebus_slot *slot;
+
+	eebrd = &eeprom_fields[BONE_CAPEBUS_BOARD_NAME];
+	eevrs = &eeprom_fields[BONE_CAPEBUS_VERSION];
+
+	slotno = simple_strtoul(buf, &s, 10);
+	if (slotno < 0 || slotno >= bus->slots_nr)
+		return -EINVAL;
+	slot = &bus->slots[slotno];
+	if (slot->eeprom_override || (slot->cape_slot.dev && slot->cape_slot.dev->added))
+		return -EINVAL;
+
+	board_name = kzalloc(eebrd->size + 1 + eevrs->size + 1, GFP_KERNEL);
+	if (board_name == NULL)
+		return -ENOMEM;
+	version = board_name + eebrd->size + 1;
+
+	s = strchr(s, ':');
+	if (s == NULL) {
+		kfree(board_name);
+		return -EINVAL;
+	}
+	s++;
+	p = strchr(s, ':');
+	if (p == NULL) {
+		len = strlen(s);
+		strncpy(board_name, s, eebrd->size);
+		strcpy(version, "00A0");
+	} else {
+		len = p - s;
+		if (len > eebrd->size)
+			len = p - s;
+		memcpy(board_name, s, len);
+		board_name[len] = '\0';
+		strncpy(version, p + 1, eevrs->size);
+	}
+	board_name[eebrd->size] = '\0';
+	version[eevrs->size]  = '\0';
+
+	/* strip trailing spaces, dots & newlines */
+	s = board_name + strlen(board_name);
+	while (s > board_name &&
+			(isspace(s[-1]) || s[-1] == '\n' || s[-1] == '.'))
+		*--s = '\0';
+
+	printk(KERN_INFO "Override for slot #%d, board-name '%s', version '%s'\n",
+			slotno, board_name, version);
+
+	slot->eeprom_override = 1;
+	slot->eeprom_failed = 0;
+	slot->eeprom_probed = 0;
+
+	/* zero out signature */
+	memset(slot->eeprom_signature, 0,
+			sizeof(slot->eeprom_signature));
+
+	/* create an eeprom field */
+	for (i = 0; i < ARRAY_SIZE(eeprom_fields); i++) {
+
+		ee_field = &eeprom_fields[i];
+
+		/* point to the entry */
+		p = slot->eeprom_signature + ee_field->start;
+
+		/* if no such property, assign default */
+		if (i != BONE_CAPEBUS_BOARD_NAME) {
+
+			if (ee_field->override)
+				memcpy(p, ee_field->override,
+						ee_field->size);
+			else
+				memset(p, 0, ee_field->size);
+
+			continue;
+		}
+
+		/* copy it to the eeprom signature buf */
+		len = strlen(board_name);
+		if (len > ee_field->size)
+			len = ee_field->size;
+
+		/* copy and zero out rest */
+		memcpy(p, board_name, len);
+		if (len < ee_field->size)
+			memset(p + len, 0, ee_field->size - len);
+	}
+
+	printk(KERN_INFO "calling cape_bus_scan_one_slot\n");
+	err = cape_bus_scan_one_slot(&bus->cape_bus, &slot->cape_slot);
+
+	printk(KERN_INFO "cape_bus_scan_one_slot returned %d\n", err);
+
+	/* failed to scan... */
+	if (err != 0)
+		slot->eeprom_override = 0;
+
+	kfree(board_name);
+
+	return strlen(buf);
+}
+
+static DEVICE_ATTR(slots, 0644, slots_show, slots_store);
+
+static int bone_capebus_bus_sysfs_register(struct bone_capebus_bus *bus)
+{
+	return device_create_file(bus->dev, &dev_attr_slots);
+}
+
+static void bone_capebus_bus_sysfs_unregister(struct bone_capebus_bus *bus)
+{
+	device_remove_file(bus->dev, &dev_attr_slots);
+}
+
+static int __devinit
+bone_capebus_probe(struct platform_device *pdev)
+{
+	struct bone_capebus_bus	*bus;
+	struct device_node	*pnode = pdev->dev.of_node;
+	const struct of_device_id *cntrlboard_match;
+	const struct of_device_id *dev_match;
+	struct bone_capebus_slot *slot;
+	const struct bone_capebus_eeprom_field *ee_field;
+	struct property *prop;
+	int length;
+	int r;
+	struct device_node *node;
+	struct i2c_client *client;
+	phandle handle;
+	u32 *slot_handles = NULL;
+	u32 val;
+	const char *str;
+	u8 *p;
+	int i, len;
+
+	/* we don't use platform_data */
+
+	bus = devm_kzalloc(&pdev->dev,
+			sizeof(struct bone_capebus_bus), GFP_KERNEL);
+	if (!bus) {
+		dev_err(&pdev->dev, "Failed to allocate device structure\n");
+		return -ENOMEM;
+	}
+
+	/* register the cape bus */
+	r = cape_bus_register(&bus->cape_bus, "bone", 0, &pdev->dev,
+			&bone_capebus_ops);
+	if (r != 0) {
+		dev_err(&pdev->dev, "Failed to register the cape device\n");
+		return r;
+	}
+
+	cntrlboard_match = of_match_device(of_match_ptr(bone_capebus_of_match),
+			&pdev->dev);
+	if (!cntrlboard_match) {
+		dev_err(&pdev->dev, "Failed to configure bone capebus\n");
+		return -ENODEV;
+	}
+	bus->dev = &pdev->dev;
+
+	prop = of_find_property(pnode, "slots", &length);
+	if (prop == NULL) {
+		dev_err(&pdev->dev, "Unable to find required "
+				"property 'slots'\n");
+		return -EINVAL;
+	}
+	bus->slots_nr = length / sizeof(u32);
+	bus->slots = devm_kzalloc(&pdev->dev,
+			sizeof(bus->slots[0]) * bus->slots_nr, GFP_KERNEL);
+	if (!bus->slots) {
+		dev_err(&pdev->dev, "Failed to allocate %d slot areas\n",
+				bus->slots_nr);
+		return -ENOMEM;
+	}
+	slot_handles = devm_kzalloc(&pdev->dev, length, GFP_KERNEL);
+	if (!slot_handles) {
+		dev_err(&pdev->dev, "Failed to allocate %d slot areas\n",
+				bus->slots_nr);
+		return -ENOMEM;
+	}
+	r = of_property_read_u32_array(pnode, "slots",
+			slot_handles, bus->slots_nr);
+	if (r < 0) {
+		dev_err(&pdev->dev, "Failed to read %d slot handles\n",
+				bus->slots_nr);
+		return r;
+	}
+
+	/* now we iterate over any overrides */
+	for_each_child_of_node(pnode, node) {
+
+		dev_match = of_match_node(slot_override_of_match, node);
+		if (!dev_match)
+			continue;
+
+		/* no reg property */
+		if (of_property_read_u32(node, "slot", &val) != 0) {
+			dev_warn(&pdev->dev, "override: Failed to read "
+					"slot property\n");
+			continue;
+		}
+
+		if (val >= bus->slots_nr) {
+			dev_warn(&pdev->dev, "override: invalid slot #%u\n",
+					val);
+			continue;
+		}
+
+		slot = &bus->slots[val];
+
+		if (slot->eeprom_override) {
+			dev_warn(&pdev->dev, "override: slot #%u is already "
+					"overriden\n", val);
+			continue;
+		}
+
+		slot->eeprom_override = 1;
+
+		/* zero out signature */
+		memset(slot->eeprom_signature, 0,
+				sizeof(slot->eeprom_signature));
+
+		/* for any matching field assign them */
+		for (i = 0; i < ARRAY_SIZE(eeprom_fields); i++) {
+
+			ee_field = &eeprom_fields[i];
+
+			/* point to the entry */
+			p = slot->eeprom_signature + ee_field->start;
+
+			/* if no such property, assign default */
+			if (of_property_read_string(node, ee_field->name,
+						&str) != 0) {
+
+				if (ee_field->override)
+					memcpy(p, ee_field->override,
+							ee_field->size);
+				else
+					memset(p, 0, ee_field->size);
+
+				continue;
+			}
+
+			/* copy it to the eeprom signature buf */
+			len = strlen(str);
+			if (len > ee_field->size)
+				len = ee_field->size;
+
+			/* copy and zero out rest */
+			memcpy(p, str, len);
+			if (len < ee_field->size)
+				memset(p + len, 0, ee_field->size - len);
+		}
+	}
+
+	platform_set_drvdata(pdev, bus);
+
+	/* now find the i2c clients */
+	for (i = 0; i < bus->slots_nr; i++) {
+
+		slot = &bus->slots[i];
+
+		handle = slot_handles[i];
+		node = of_find_node_by_phandle(handle);
+		if (node == NULL) {
+			dev_warn(&pdev->dev, "Failed to find node with phandle "
+					"0x%x (#%d)\n", handle, i);
+			continue;
+		}
+		dev_dbg(&pdev->dev, "Found device node for phandle "
+				"0x%x (#%d)\n", handle, i);
+
+		client = of_find_i2c_device_by_node(node);
+		if (client == NULL) {
+			dev_warn(&pdev->dev, "Invalid I2C client node with "
+					"phandle 0x%x (#%d)\n", handle, i);
+			continue;
+		}
+
+		slot->client = i2c_use_client(client);
+		/* no use for this anymore */
+		of_node_put(node);
+
+		/* save handle */
+		client = slot->client;	/* get again */
+		slot->eeprom_addr = client->addr;
+		dev_dbg(&pdev->dev, "Found i2c_client at #%d "
+				"(address = 0x%02x)\n",
+				i, slot->eeprom_addr);
+
+		r = cape_bus_register_slot(&bus->cape_bus, &slot->cape_slot, i);
+		if (r != 0) {
+			dev_err(&pdev->dev, "Failed to register slot #%d\n", i);
+			continue;
+		}
+
+		dev_info(&pdev->dev, "Registered slot #%d OK\n", i);
+	}
+
+	/* we don't need the handles anymore */
+	devm_kfree(&pdev->dev, slot_handles);
+	slot_handles = NULL;
+
+	r = bone_capebus_register_pdev_adapters(bus);
+	if (r != 0) {
+		dev_err(&pdev->dev, "Failed to register the pdev adapters\n");
+		goto err_no_pdevs;
+	}
+
+	pm_runtime_enable(bus->dev);
+	r = pm_runtime_get_sync(bus->dev);
+	if (IS_ERR_VALUE(r)) {
+		dev_err(&pdev->dev, "Failed to pm_runtime_get_sync()\n");
+		goto err_exit;
+	}
+
+	pm_runtime_put(bus->dev);
+
+	bone_capebus_bus_sysfs_register(bus);
+
+	dev_info(&pdev->dev, "initialized OK.\n");
+
+	return 0;
+
+err_exit:
+	bone_capebus_unregister_pdev_adapters(bus);
+err_no_pdevs:
+	platform_set_drvdata(pdev, NULL);
+
+	return r;
+}
+
+static int __devexit bone_capebus_remove(struct platform_device *pdev)
+{
+	struct bone_capebus_bus	*bus = platform_get_drvdata(pdev);
+	int ret;
+
+	bone_capebus_bus_sysfs_unregister(bus);
+	bone_capebus_unregister_pdev_adapters(bus);
+
+	platform_set_drvdata(pdev, NULL);
+
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	pm_runtime_put(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
+static int bone_capebus_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_capebus_bus *_dev = platform_get_drvdata(pdev);
+
+	(void)_dev;
+	return 0;
+}
+
+static int bone_capebus_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_capebus_bus *_dev = platform_get_drvdata(pdev);
+
+	(void)_dev;
+	return 0;
+}
+#endif /* CONFIG_PM_RUNTIME */
+
+static struct dev_pm_ops bone_capebus_pm_ops = {
+	SET_RUNTIME_PM_OPS(bone_capebus_runtime_suspend,
+			   bone_capebus_runtime_resume, NULL)
+};
+#define BONE_CAPEBUS_PM_OPS (&bone_capebus_pm_ops)
+#else
+#define BONE_CAPEBUS_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver bone_capebus_driver = {
+	.probe		= bone_capebus_probe,
+	.remove		= __devexit_p(bone_capebus_remove),
+	.driver		= {
+		.name	= "bone-capebus",
+		.owner	= THIS_MODULE,
+		.pm	= BONE_CAPEBUS_PM_OPS,
+		.of_match_table = of_match_ptr(bone_capebus_of_match),
+	},
+};
+
+module_platform_driver(bone_capebus_driver);
+
+MODULE_AUTHOR("Pantelis Antoniou");
+MODULE_DESCRIPTION("Beaglebone cape bus controller");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:capebus_bone");
diff --git a/include/linux/capebus/capebus-bone.h b/include/linux/capebus/capebus-bone.h
new file mode 100644
index 0000000..e394304
--- /dev/null
+++ b/include/linux/capebus/capebus-bone.h
@@ -0,0 +1,120 @@
+/*
+ * capebus-bone.h
+ *
+ * Cape bus defines and function prototypes for the beaglebone
+ *
+ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
+ * Copyright (C) 2012 Texas Instruments 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef LINUX_CAPEBUS_BONE_H
+#define LINUX_CAPEBUS_BONE_H
+
+#include <linux/list.h>
+#include <linux/capebus.h>
+
+struct bone_capebus_slot {
+	struct cape_slot	cape_slot;
+	u32			slot_handle;
+	int			eeprom_addr;
+	struct i2c_client	*client;
+	unsigned int		eeprom_probed : 1;
+	unsigned int		eeprom_failed : 1;
+	unsigned int		eeprom_override : 1;
+	struct cape_device_id	id;
+	char			text_id[256];
+	char			eeprom_signature[256];
+};
+
+#define to_bone_capebus_slot(n)	\
+	container_of(n, struct bone_capebus_slot, cape_slot)
+
+struct bone_capebus_bus {
+	struct cape_bus			cape_bus;
+	struct device			*dev;		/* pdev->dev */
+	int 				slots_nr;
+	struct bone_capebus_slot	*slots;
+};
+
+#define to_bone_capebus_bus(n)	\
+	container_of(n, struct bone_capebus_bus, cape_bus)
+
+#define BONE_CAPEBUS_HEADER		0
+#define BONE_CAPEBUS_EEPROM_REV		1
+#define BONE_CAPEBUS_BOARD_NAME		2
+#define BONE_CAPEBUS_VERSION		3
+#define BONE_CAPEBUS_MANUFACTURER	4
+#define BONE_CAPEBUS_PART_NUMBER	5
+#define BONE_CAPEBUS_NUMBER_OF_PINS	6
+#define BONE_CAPEBUS_SERIAL_NUMBER	7
+#define BONE_CAPEBUS_PIN_USAGE		8
+#define BONE_CAPEBUS_VDD_3V3EXP		9
+#define BONE_CAPEBUS_VDD_5V		10
+#define BONE_CAPEBUS_SYS_5V		11
+#define BONE_CAPEBUS_DC_SUPPLIED	12
+#define BONE_CAPEBUS_FIELDS_NR		13
+
+#define BONE_CAPEBUS_MAKE_HEADER(p)	\
+	({ \
+		const u8 *_p = (p); \
+		(((u32)_p[0] << 24) | ((u32)_p[1] << 16) | \
+		((u32)_p[2] <<  8) |  (u32)_p[3]       ); \
+	})
+
+#define BONE_CAPEBUS_HEADER_VALID	0xaa5533ee
+
+char *bone_capebus_id_get_field(const struct cape_device_id *id,
+		int field, char *buf, int bufsz);
+
+int bone_capebus_match_cntrlboard(const struct cape_device_id *id);
+
+int bone_capebus_match_board(const struct cape_device_id *id,
+		const char **board_names);
+
+/* in pdevs */
+int bone_capebus_register_pdev_adapters(struct bone_capebus_bus *bus);
+void bone_capebus_unregister_pdev_adapters(struct bone_capebus_bus *bus);
+
+/* generic cape support */
+
+struct bone_capebus_generic_device_data {
+	const char *name;
+	const struct of_device_id *of_match;
+	unsigned int units;
+};
+
+struct bone_capebus_generic_device_entry {
+	struct list_head node;
+	const struct bone_capebus_generic_device_data *data;
+	struct platform_device *pdev;
+};
+
+struct bone_capebus_generic_info {
+	struct cape_dev *dev;
+	struct list_head pdev_list;
+};
+
+int bone_capebus_probe_prolog(struct cape_dev *dev,
+		const struct cape_device_id *id);
+
+struct bone_capebus_generic_info *
+bone_capebus_probe_generic(struct cape_dev *dev,
+		const struct cape_device_id *id);
+
+void bone_capebus_remove_generic(
+		struct bone_capebus_generic_info *info);
+
+#endif
