--- kernel-2.6.27.orig/Documentation/arm/OMAP/ssi/board-ssi.c.example
+++ kernel-2.6.27/Documentation/arm/OMAP/ssi/board-ssi.c.example
@@ -0,0 +1,216 @@
+/*
+ * board-ssi.c.example
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifdef CONFIG_OMAP_SSI
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/ssi_driver_if.h>
+#include <mach/ssi/ssi_sys_reg.h>
+#include <mach/ssi/ssi_ssr_reg.h>
+#include <mach/ssi/ssi_sst_reg.h>
+
+#include "clock.h"
+
+struct ssi_internal_clk {
+	struct clk clk;
+	struct clk **childs;
+	int n_childs;
+	struct platform_device *pdev;
+};
+
+static struct ssi_internal_clk ssi_clock;
+
+static void ssi_pdev_release(struct device *dev)
+{
+}
+
+static struct ssi_port_pd ssi_ports[] = {
+	[0] = {
+		.tx_mode = SSI_MODE_FRAME,
+		.tx_frame_size = SSI_FRAMESIZE_DEFAULT,
+		.divisor = SSI_DIVISOR_DEFAULT,
+		.tx_ch = SSI_CHANNELS_DEFAULT,
+		.arb_mode = SSI_ARBMODE_ROUNDROBIN,
+		.rx_mode = SSI_MODE_FRAME,
+		.rx_frame_size = SSI_FRAMESIZE_DEFAULT,
+		.rx_ch = SSI_CHANNELS_DEFAULT,
+		.timeout = SSI_TIMEOUT_DEFAULT,
+		.n_irq = 0,
+		},
+};
+
+static struct ssi_platform_data ssi_p_d = {
+	.clk_name = "ssi_clk",
+	.num_ports = ARRAY_SIZE(ssi_ports),
+	.ports = ssi_ports,
+};
+
+static struct resource ssi_resources[] = {
+	[0] = {
+		.start = SSI_IOMEM_BASE_ADDR,
+		.end = SSI_IOMEM_BASE_ADDR + SSI_IOMEM_SIZE,
+		.name = SSI_IOMEM_NAME,
+		.flags = IORESOURCE_MEM,
+		},
+	[1] = 	{
+		.start = SSI_P1_MPU_IRQ0,
+		.end = SSI_P1_MPU_IRQ0,
+		.name = SSI_P1_MPU_IRQ0_NAME,
+		.flags = IORESOURCE_IRQ,
+		},
+	[2] = 	{
+		.start = SSI_P1_MPU_IRQ1,
+		.end = SSI_P1_MPU_IRQ1,
+		.name = SSI_P1_MPU_IRQ1_NAME,
+		.flags = IORESOURCE_IRQ,
+		},
+	[3] = 	{
+		.start = SSI_P2_MPU_IRQ0,
+		.end = SSI_P2_MPU_IRQ0,
+		.name = SSI_P2_MPU_IRQ0_NAME,
+		.flags = IORESOURCE_IRQ,
+		},
+	[4] = 	{
+		.start = SSI_P2_MPU_IRQ1,
+		.end = SSI_P2_MPU_IRQ1,
+		.name = SSI_P2_MPU_IRQ1_NAME,
+		.flags = IORESOURCE_IRQ,
+		},
+	[5] = 	{
+		.start = SSI_GDD_MPU_IRQ,
+		.end = SSI_GDD_MPU_IRQ,
+		.name = SSI_GDD_MPU_IRQ_NAME,
+		.flags = IORESOURCE_IRQ,
+		},
+};
+
+static struct platform_device ssi_pdev = {
+	.name = "omap_ssi",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(ssi_resources),
+	.resource = ssi_resources,
+	.dev = 	{
+		.release = ssi_pdev_release,
+		.platform_data = &ssi_p_d,
+		},
+};
+
+static void set_ssi_mode(struct platform_device *pdev, u32 mode)
+{
+	void __iomem *base = (void __iomem *)pdev->resource[0].start;
+	int port;
+	int num_ports = ((struct ssi_platform_data *)
+					(pdev->dev.platform_data))->num_ports;
+
+	for (port = 0; port < num_ports; port++) {
+		outl(mode, OMAP2_IO_ADDRESS(base + SSI_SST_MODE_REG(port)));
+		outl(mode, OMAP2_IO_ADDRESS(base + SSI_SSR_MODE_REG(port)));
+	}
+}
+
+static int ssi_clk_init(struct ssi_internal_clk *ssi_clk)
+{
+	const char *clk_names[] = { "ssi_ick", "ssi_ssr_fck" };
+	int i;
+	int j;
+
+	ssi_clk->n_childs = ARRAY_SIZE(clk_names);
+	ssi_clk->childs = kzalloc(ssi_clk->n_childs * sizeof(*ssi_clk->childs),
+								GFP_KERNEL);
+	if (!ssi_clk->childs)
+		return -ENOMEM;
+
+	for (i = 0; i < ssi_clk->n_childs; i++) {
+		ssi_clk->childs[i] = clk_get(NULL, clk_names[i]);
+		if (IS_ERR(ssi_clk->childs[i])) {
+			pr_err("Unable to get SSI clock: %s", clk_names[i]);
+			for (j = i - 1; j >= 0; j--)
+				clk_put(ssi_clk->childs[j]);
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+static int ssi_clk_enable(struct clk *clk)
+{
+	struct ssi_internal_clk *ssi_clk =
+				container_of(clk, struct ssi_internal_clk, clk);
+	int err = 0;
+	int i;
+	int j;
+
+	for (i = 0; ((i < ssi_clk->n_childs) && (err >= 0)); i++)
+		err = omap2_clk_enable(ssi_clk->childs[i]);
+
+	if (unlikely(err < 0)) {
+		pr_err("Error on SSI clk %d\n", i);
+		for (j = i - 1; j >= 0; j--)
+			omap2_clk_disable(ssi_clk->childs[j]);
+	} else {
+		if (ssi_clk->clk.usecount == 1)
+			set_ssi_mode(ssi_clk->pdev, SSI_MODE_FRAME);
+	}
+
+	return err;
+}
+
+static void ssi_clk_disable(struct clk *clk)
+{
+	struct ssi_internal_clk *ssi_clk =
+				container_of(clk, struct ssi_internal_clk, clk);
+
+	int i;
+
+	if (ssi_clk->clk.usecount == 0)
+		set_ssi_mode(ssi_clk->pdev, SSI_MODE_SLEEP);
+
+	for (i = 0; i < ssi_clk->n_childs; i++)
+		omap2_clk_disable(ssi_clk->childs[i]);
+}
+
+static struct ssi_internal_clk ssi_clock = {
+	.clk = {
+		.name = "ssi_clk",
+		.id = -1,
+		.enable = ssi_clk_enable,
+		.disable = ssi_clk_disable,
+	},
+	.pdev = &ssi_pdev,
+};
+
+void __init ssi_init(void)
+{
+	int err;
+
+	ssi_clk_init(&ssi_clock);
+	clk_register(&ssi_clock.clk);
+
+	err = platform_device_register(&ssi_pdev);
+	if (err < 0)
+		pr_err("Unable to register SSI platform device: %d\n", err);
+}
+#endif
