--- /dev/null
+From: Eduardo Valentin <eduardo.valentin@indt.org.br>\r
+\r
+This patch transform mcbsp code into a very initial\r
+implementation of a platform driver.\r
+\r
+It also gets ride of ifdefs on mcbsp.c code.\r
+To do it, a platform data structure was defined.\r
+\r
+Platform devices are located in arch/arm/plat-omap/devices.c\r
+\r
+Signed-off-by: Eduardo Valentin <eduardo.valentin@indt.org.br>\r
+---\r
+ arch/arm/plat-omap/devices.c | 45 +++\r
+ arch/arm/plat-omap/mcbsp.c | 660 ++++++++++++++-----------------------\r
+ include/asm-arm/arch-omap/mcbsp.h | 73 ++++-\r
+ 3 files changed, 367 insertions(+), 411 deletions(-)\r
+\r
+diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c\r
+index 099182b..b3e0147 100644\r
+--- a/arch/arm/plat-omap/devices.c\r
++++ b/arch/arm/plat-omap/devices.c\r
+@@ -27,6 +27,7 @@\r
+ #include <asm/arch/gpio.h>\r
+ #include <asm/arch/menelaus.h>\r
+ #include <asm/arch/dsp_common.h>\r
++#include <asm/arch/mcbsp.h>\r
+ \r
+ #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)\r
+ \r
+@@ -150,6 +151,49 @@ static inline void omap_init_kp(void) {}\r
+ #endif\r
+ \r
+ /*-------------------------------------------------------------------------*/\r
++#if defined(CONFIG_OMAP_MCBSP) || defined(CONFIG_OMAP_MCBSP_MODULE)\r
++\r
++static struct platform_device omap_mcbsp_devices[OMAP_MAX_MCBSP_COUNT];\r
++static int mcbsps_configured;\r
++\r
++void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,\r
++ int size)\r
++{\r
++ int i;\r
++\r
++ if (size > OMAP_MAX_MCBSP_COUNT) {\r
++ printk(KERN_WARNING "Registered too many McBSPs platform_data."\r
++ " Using maximum (%d) available.\n",\r
++ OMAP_MAX_MCBSP_COUNT);\r
++ size = OMAP_MAX_MCBSP_COUNT;\r
++ }\r
++\r
++ for (i = 0; i < size; i++) {\r
++ struct platform_device *new_mcbsp = &omap_mcbsp_devices[i];\r
++ new_mcbsp->name = "omap-mcbsp";\r
++ new_mcbsp->id = i + 1;\r
++ new_mcbsp->dev.platform_data = &config[i];\r
++ }\r
++ mcbsps_configured = size;\r
++}\r
++\r
++static void __init omap_init_mcbsp(void)\r
++{\r
++ int i;\r
++\r
++ for (i = 0; i < mcbsps_configured; i++)\r
++ platform_device_register(&omap_mcbsp_devices[i]);\r
++}\r
++#else\r
++void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,\r
++ int size)\r
++{ }\r
++\r
++static inline void __init omap_init_mcbsp(void)\r
++{ }\r
++#endif\r
++\r
++/*-------------------------------------------------------------------------*/\r
+ \r
+ #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) \\r
+ || defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)\r
+@@ -511,6 +555,7 @@ static int __init omap_init_devices(void)\r
+ */\r
+ omap_init_dsp();\r
+ omap_init_kp();\r
++ omap_init_mcbsp();\r
+ omap_init_mmc();\r
+ omap_init_uwire();\r
+ omap_init_wdt();\r
+diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c\r
+index 053de31..5536223 100644\r
+--- a/arch/arm/plat-omap/mcbsp.c\r
++++ b/arch/arm/plat-omap/mcbsp.c\r
+@@ -15,6 +15,7 @@\r
+ #include <linux/module.h>\r
+ #include <linux/init.h>\r
+ #include <linux/device.h>\r
++#include <linux/platform_device.h>\r
+ #include <linux/wait.h>\r
+ #include <linux/completion.h>\r
+ #include <linux/interrupt.h>\r
+@@ -25,83 +26,53 @@\r
+ #include <linux/irq.h>\r
+ \r
+ #include <asm/arch/dma.h>\r
+-#include <asm/arch/mux.h>\r
+-#include <asm/arch/irqs.h>\r
+-#include <asm/arch/dsp_common.h>\r
+ #include <asm/arch/mcbsp.h>\r
+ \r
+-#ifdef CONFIG_MCBSP_DEBUG\r
+-#define DBG(x...) printk(x)\r
+-#else\r
+-#define DBG(x...) do { } while (0)\r
+-#endif\r
+-\r
+-struct omap_mcbsp {\r
+- u32 io_base;\r
+- u8 id;\r
+- u8 free;\r
+- omap_mcbsp_word_length rx_word_length;\r
+- omap_mcbsp_word_length tx_word_length;\r
+-\r
+- omap_mcbsp_io_type_t io_type; /* IRQ or poll */\r
+- /* IRQ based TX/RX */\r
+- int rx_irq;\r
+- int tx_irq;\r
+-\r
+- /* DMA stuff */\r
+- u8 dma_rx_sync;\r
+- short dma_rx_lch;\r
+- u8 dma_tx_sync;\r
+- short dma_tx_lch;\r
+-\r
+- /* Completion queues */\r
+- struct completion tx_irq_completion;\r
+- struct completion rx_irq_completion;\r
+- struct completion tx_dma_completion;\r
+- struct completion rx_dma_completion;\r
+-\r
+- /* Protect the field .free, while checking if the mcbsp is in use */\r
+- spinlock_t lock;\r
+-};\r
+-\r
+ static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];\r
+-#ifdef CONFIG_ARCH_OMAP1\r
+-static struct clk *mcbsp_dsp_ck;\r
+-static struct clk *mcbsp_api_ck;\r
+-static struct clk *mcbsp_dspxor_ck;\r
+-#endif\r
+-#ifdef CONFIG_ARCH_OMAP2\r
+-static struct clk *mcbsp1_ick;\r
+-static struct clk *mcbsp1_fck;\r
+-static struct clk *mcbsp2_ick;\r
+-static struct clk *mcbsp2_fck;\r
+-#endif\r
++\r
++#define omap_mcbsp_check_valid_id(id) (mcbsp[id].pdata && \\r
++ mcbsp[id].pdata->ops && \\r
++ mcbsp[id].pdata->ops->check && \\r
++ (mcbsp[id].pdata->ops->check(id) == 0))\r
+ \r
+ static void omap_mcbsp_dump_reg(u8 id)\r
+ {\r
+- DBG("**** MCBSP%d regs ****\n", mcbsp[id].id);\r
+- DBG("DRR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2));\r
+- DBG("DRR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1));\r
+- DBG("DXR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2));\r
+- DBG("DXR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1));\r
+- DBG("SPCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2));\r
+- DBG("SPCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1));\r
+- DBG("RCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2));\r
+- DBG("RCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1));\r
+- DBG("XCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2));\r
+- DBG("XCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1));\r
+- DBG("SRGR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2));\r
+- DBG("SRGR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1));\r
+- DBG("PCR0: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0));\r
+- DBG("***********************\n");\r
++ dev_dbg(mcbsp[id].dev, "**** McBSP%d regs ****\n", mcbsp[id].id);\r
++ dev_dbg(mcbsp[id].dev, "DRR2: 0x%04x\n",\r
++ OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2));\r
++ dev_dbg(mcbsp[id].dev, "DRR1: 0x%04x\n",\r
++ OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1));\r
++ dev_dbg(mcbsp[id].dev, "DXR2: 0x%04x\n",\r
++ OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2));\r
++ dev_dbg(mcbsp[id].dev, "DXR1: 0x%04x\n",\r
++ OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1));\r
++ dev_dbg(mcbsp[id].dev, "SPCR2: 0x%04x\n",\r
++ OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2));\r
++ dev_dbg(mcbsp[id].dev, "SPCR1: 0x%04x\n",\r
++ OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1));\r
++ dev_dbg(mcbsp[id].dev, "RCR2: 0x%04x\n",\r
++ OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2));\r
++ dev_dbg(mcbsp[id].dev, "RCR1: 0x%04x\n",\r
++ OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1));\r
++ dev_dbg(mcbsp[id].dev, "XCR2: 0x%04x\n",\r
++ OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2));\r
++ dev_dbg(mcbsp[id].dev, "XCR1: 0x%04x\n",\r
++ OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1));\r
++ dev_dbg(mcbsp[id].dev, "SRGR2: 0x%04x\n",\r
++ OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2));\r
++ dev_dbg(mcbsp[id].dev, "SRGR1: 0x%04x\n",\r
++ OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1));\r
++ dev_dbg(mcbsp[id].dev, "PCR0: 0x%04x\n",\r
++ OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0));\r
++ dev_dbg(mcbsp[id].dev, "***********************\n");\r
+ }\r
+ \r
+ static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)\r
+ {\r
+ struct omap_mcbsp *mcbsp_tx = dev_id;\r
+ \r
+- DBG("TX IRQ callback : 0x%x\n",\r
+- OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2));\r
++ dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n",\r
++ OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2));\r
+ \r
+ complete(&mcbsp_tx->tx_irq_completion);\r
+ \r
+@@ -112,8 +83,8 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)\r
+ {\r
+ struct omap_mcbsp *mcbsp_rx = dev_id;\r
+ \r
+- DBG("RX IRQ callback : 0x%x\n",\r
+- OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2));\r
++ dev_dbg(mcbsp_rx->dev, "RX IRQ callback : 0x%x\n",\r
++ OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2));\r
+ \r
+ complete(&mcbsp_rx->rx_irq_completion);\r
+ \r
+@@ -124,8 +95,8 @@ static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)\r
+ {\r
+ struct omap_mcbsp *mcbsp_dma_tx = data;\r
+ \r
+- DBG("TX DMA callback : 0x%x\n",\r
+- OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2));\r
++ dev_dbg(mcbsp_dma_tx->dev, "TX DMA callback : 0x%x\n",\r
++ OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2));\r
+ \r
+ /* We can free the channels */\r
+ omap_free_dma(mcbsp_dma_tx->dma_tx_lch);\r
+@@ -138,8 +109,8 @@ static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)\r
+ {\r
+ struct omap_mcbsp *mcbsp_dma_rx = data;\r
+ \r
+- DBG("RX DMA callback : 0x%x\n",\r
+- OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2));\r
++ dev_dbg(mcbsp_dma_rx->dev, "RX DMA callback : 0x%x\n",\r
++ OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2));\r
+ \r
+ /* We can free the channels */\r
+ omap_free_dma(mcbsp_dma_rx->dma_rx_lch);\r
+@@ -156,9 +127,16 @@ static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)\r
+ */\r
+ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)\r
+ {\r
+- u32 io_base = mcbsp[id].io_base;\r
++ u32 io_base;\r
++\r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
++ return;\r
++ }\r
+ \r
+- DBG("OMAP-McBSP: McBSP%d io_base: 0x%8x\n", id + 1, io_base);\r
++ io_base = mcbsp[id].io_base;\r
++ dev_dbg(mcbsp[id].dev, "Configuring McBSP%d io_base: 0x%8x\n",\r
++ mcbsp[id].id, io_base);\r
+ \r
+ /* We write the given config */\r
+ OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2);\r
+@@ -175,97 +153,22 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)\r
+ }\r
+ EXPORT_SYMBOL(omap_mcbsp_config);\r
+ \r
+-static int omap_mcbsp_check(unsigned int id)\r
+-{\r
+- if (cpu_is_omap730()) {\r
+- if (id > OMAP_MAX_MCBSP_COUNT - 1) {\r
+- printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n",\r
+- id + 1);\r
+- return -1;\r
+- }\r
+- return 0;\r
+- }\r
+-\r
+- if (cpu_is_omap15xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) {\r
+- if (id > OMAP_MAX_MCBSP_COUNT) {\r
+- printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n",\r
+- id + 1);\r
+- return -1;\r
+- }\r
+- return 0;\r
+- }\r
+-\r
+- return -1;\r
+-}\r
+-\r
+-#ifdef CONFIG_ARCH_OMAP1\r
+-static void omap_mcbsp_dsp_request(void)\r
+-{\r
+- if (cpu_is_omap15xx() || cpu_is_omap16xx()) {\r
+- int ret;\r
+-\r
+- ret = omap_dsp_request_mem();\r
+- if (ret < 0) {\r
+- printk(KERN_ERR "Could not get dsp memory: %i\n", ret);\r
+- return;\r
+- }\r
+-\r
+- clk_enable(mcbsp_dsp_ck);\r
+- clk_enable(mcbsp_api_ck);\r
+-\r
+- /* enable 12MHz clock to mcbsp 1 & 3 */\r
+- clk_enable(mcbsp_dspxor_ck);\r
+-\r
+- /*\r
+- * DSP external peripheral reset\r
+- * FIXME: This should be moved to dsp code\r
+- */\r
+- __raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1,\r
+- DSP_RSTCT2);\r
+- }\r
+-}\r
+-\r
+-static void omap_mcbsp_dsp_free(void)\r
+-{\r
+- if (cpu_is_omap15xx() || cpu_is_omap16xx()) {\r
+- omap_dsp_release_mem();\r
+- clk_disable(mcbsp_dspxor_ck);\r
+- clk_disable(mcbsp_dsp_ck);\r
+- clk_disable(mcbsp_api_ck);\r
+- }\r
+-}\r
+-#endif\r
+-\r
+-#ifdef CONFIG_ARCH_OMAP2\r
+-static void omap2_mcbsp2_mux_setup(void)\r
+-{\r
+- if (cpu_is_omap2420()) {\r
+- omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);\r
+- omap_cfg_reg(R14_24XX_MCBSP2_FSX);\r
+- omap_cfg_reg(W15_24XX_MCBSP2_DR);\r
+- omap_cfg_reg(V15_24XX_MCBSP2_DX);\r
+- omap_cfg_reg(V14_24XX_GPIO117);\r
+- }\r
+- /*\r
+- * Need to add MUX settings for OMAP 2430 SDP\r
+- */\r
+-}\r
+-#endif\r
+-\r
+ /*\r
+ * We can choose between IRQ based or polled IO.\r
+ * This needs to be called before omap_mcbsp_request().\r
+ */\r
+ int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type)\r
+ {\r
+- if (omap_mcbsp_check(id) < 0)\r
+- return -EINVAL;\r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
++ return -ENODEV;\r
++ }\r
+ \r
+ spin_lock(&mcbsp[id].lock);\r
+ \r
+ if (!mcbsp[id].free) {\r
+- printk(KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n",\r
+- id + 1);\r
++ dev_err(mcbsp[id].dev, "McBSP%d is currently in use\n",\r
++ mcbsp[id].id);\r
+ spin_unlock(&mcbsp[id].lock);\r
+ return -EINVAL;\r
+ }\r
+@@ -282,34 +185,20 @@ int omap_mcbsp_request(unsigned int id)\r
+ {\r
+ int err;\r
+ \r
+- if (omap_mcbsp_check(id) < 0)\r
+- return -EINVAL;\r
+-\r
+-#ifdef CONFIG_ARCH_OMAP1\r
+- /*\r
+- * On 1510, 1610 and 1710, McBSP1 and McBSP3\r
+- * are DSP public peripherals.\r
+- */\r
+- if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)\r
+- omap_mcbsp_dsp_request();\r
+-#endif\r
+-\r
+-#ifdef CONFIG_ARCH_OMAP2\r
+- if (cpu_is_omap24xx()) {\r
+- if (id == OMAP_MCBSP1) {\r
+- clk_enable(mcbsp1_ick);\r
+- clk_enable(mcbsp1_fck);\r
+- } else {\r
+- clk_enable(mcbsp2_ick);\r
+- clk_enable(mcbsp2_fck);\r
+- }\r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
++ return -ENODEV;\r
+ }\r
+-#endif\r
++\r
++ if (mcbsp[id].pdata->ops->request)\r
++ mcbsp[id].pdata->ops->request(id);\r
++\r
++ mcbsp_clk_enable(&mcbsp[id]);\r
+ \r
+ spin_lock(&mcbsp[id].lock);\r
+ if (!mcbsp[id].free) {\r
+- printk(KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n",\r
+- id + 1);\r
++ dev_err(mcbsp[id].dev, "McBSP%d is currently in use\n",\r
++ mcbsp[id].id);\r
+ spin_unlock(&mcbsp[id].lock);\r
+ return -1;\r
+ }\r
+@@ -322,9 +211,9 @@ int omap_mcbsp_request(unsigned int id)\r
+ err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler,\r
+ 0, "McBSP", (void *) (&mcbsp[id]));\r
+ if (err != 0) {\r
+- printk(KERN_ERR "OMAP-McBSP: Unable to "\r
+- "request TX IRQ %d for McBSP%d\n",\r
+- mcbsp[id].tx_irq, mcbsp[id].id);\r
++ dev_err(mcbsp[id].dev, "Unable to request TX IRQ %d "\r
++ "for McBSP%d\n", mcbsp[id].tx_irq,\r
++ mcbsp[id].id);\r
+ return err;\r
+ }\r
+ \r
+@@ -333,9 +222,9 @@ int omap_mcbsp_request(unsigned int id)\r
+ err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler,\r
+ 0, "McBSP", (void *) (&mcbsp[id]));\r
+ if (err != 0) {\r
+- printk(KERN_ERR "OMAP-McBSP: Unable to "\r
+- "request RX IRQ %d for McBSP%d\n",\r
+- mcbsp[id].rx_irq, mcbsp[id].id);\r
++ dev_err(mcbsp[id].dev, "Unable to request RX IRQ %d "\r
++ "for McBSP%d\n", mcbsp[id].rx_irq,\r
++ mcbsp[id].id);\r
+ free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));\r
+ return err;\r
+ }\r
+@@ -349,32 +238,20 @@ EXPORT_SYMBOL(omap_mcbsp_request);\r
+ \r
+ void omap_mcbsp_free(unsigned int id)\r
+ {\r
+- if (omap_mcbsp_check(id) < 0)\r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
+ return;\r
+-\r
+-#ifdef CONFIG_ARCH_OMAP1\r
+- if (cpu_class_is_omap1()) {\r
+- if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)\r
+- omap_mcbsp_dsp_free();\r
+ }\r
+-#endif\r
+-\r
+-#ifdef CONFIG_ARCH_OMAP2\r
+- if (cpu_is_omap24xx()) {\r
+- if (id == OMAP_MCBSP1) {\r
+- clk_disable(mcbsp1_ick);\r
+- clk_disable(mcbsp1_fck);\r
+- } else {\r
+- clk_disable(mcbsp2_ick);\r
+- clk_disable(mcbsp2_fck);\r
+- }\r
+- }\r
+-#endif\r
++\r
++ if (mcbsp[id].pdata->ops->free)\r
++ mcbsp[id].pdata->ops->free(id);\r
++\r
++ mcbsp_clk_disable(&mcbsp[id]);\r
+ \r
+ spin_lock(&mcbsp[id].lock);\r
+ if (mcbsp[id].free) {\r
+- printk(KERN_ERR "OMAP-McBSP: McBSP%d was not reserved\n",\r
+- id + 1);\r
++ dev_err(mcbsp[id].dev, "McBSP%d was not reserved\n",\r
++ mcbsp[id].id);\r
+ spin_unlock(&mcbsp[id].lock);\r
+ return;\r
+ }\r
+@@ -400,8 +277,10 @@ void omap_mcbsp_start(unsigned int id)\r
+ u32 io_base;\r
+ u16 w;\r
+ \r
+- if (omap_mcbsp_check(id) < 0)\r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
+ return;\r
++ }\r
+ \r
+ io_base = mcbsp[id].io_base;\r
+ \r
+@@ -435,8 +314,10 @@ void omap_mcbsp_stop(unsigned int id)\r
+ u32 io_base;\r
+ u16 w;\r
+ \r
+- if (omap_mcbsp_check(id) < 0)\r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
+ return;\r
++ }\r
+ \r
+ io_base = mcbsp[id].io_base;\r
+ \r
+@@ -457,7 +338,14 @@ EXPORT_SYMBOL(omap_mcbsp_stop);\r
+ /* polled mcbsp i/o operations */\r
+ int omap_mcbsp_pollwrite(unsigned int id, u16 buf)\r
+ {\r
+- u32 base = mcbsp[id].io_base;\r
++ u32 base;\r
++\r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
++ return -ENODEV;\r
++ }\r
++\r
++ base = mcbsp[id].io_base;\r
+ writew(buf, base + OMAP_MCBSP_REG_DXR1);\r
+ /* if frame sync error - clear the error */\r
+ if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) {\r
+@@ -479,8 +367,8 @@ int omap_mcbsp_pollwrite(unsigned int id, u16 buf)\r
+ (XRST),\r
+ base + OMAP_MCBSP_REG_SPCR2);\r
+ udelay(10);\r
+- printk(KERN_ERR\r
+- " Could not write to McBSP Register\n");\r
++ dev_err(mcbsp[id].dev, "Could not write to"\r
++ " McBSP%d Register\n", mcbsp[id].id);\r
+ return -2;\r
+ }\r
+ }\r
+@@ -492,7 +380,14 @@ EXPORT_SYMBOL(omap_mcbsp_pollwrite);\r
+ \r
+ int omap_mcbsp_pollread(unsigned int id, u16 *buf)\r
+ {\r
+- u32 base = mcbsp[id].io_base;\r
++ u32 base;\r
++\r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
++ return -ENODEV;\r
++ }\r
++\r
++ base = mcbsp[id].io_base;\r
+ /* if frame sync error - clear the error */\r
+ if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) {\r
+ /* clear error */\r
+@@ -513,8 +408,8 @@ int omap_mcbsp_pollread(unsigned int id, u16 *buf)\r
+ (RRST),\r
+ base + OMAP_MCBSP_REG_SPCR1);\r
+ udelay(10);\r
+- printk(KERN_ERR\r
+- " Could not read from McBSP Register\n");\r
++ dev_err(mcbsp[id].dev, "Could not read from"\r
++ " McBSP%d Register\n", mcbsp[id].id);\r
+ return -2;\r
+ }\r
+ }\r
+@@ -531,12 +426,15 @@ EXPORT_SYMBOL(omap_mcbsp_pollread);\r
+ void omap_mcbsp_xmit_word(unsigned int id, u32 word)\r
+ {\r
+ u32 io_base;\r
+- omap_mcbsp_word_length word_length = mcbsp[id].tx_word_length;\r
++ omap_mcbsp_word_length word_length;\r
+ \r
+- if (omap_mcbsp_check(id) < 0)\r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
+ return;\r
++ }\r
+ \r
+ io_base = mcbsp[id].io_base;\r
++ word_length = mcbsp[id].tx_word_length;\r
+ \r
+ wait_for_completion(&(mcbsp[id].tx_irq_completion));\r
+ \r
+@@ -550,11 +448,14 @@ u32 omap_mcbsp_recv_word(unsigned int id)\r
+ {\r
+ u32 io_base;\r
+ u16 word_lsb, word_msb = 0;\r
+- omap_mcbsp_word_length word_length = mcbsp[id].rx_word_length;\r
++ omap_mcbsp_word_length word_length;\r
+ \r
+- if (omap_mcbsp_check(id) < 0)\r
+- return -EINVAL;\r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
++ return -ENODEV;\r
++ }\r
+ \r
++ word_length = mcbsp[id].rx_word_length;\r
+ io_base = mcbsp[id].io_base;\r
+ \r
+ wait_for_completion(&(mcbsp[id].rx_irq_completion));\r
+@@ -569,11 +470,20 @@ EXPORT_SYMBOL(omap_mcbsp_recv_word);\r
+ \r
+ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)\r
+ {\r
+- u32 io_base = mcbsp[id].io_base;\r
+- omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length;\r
+- omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length;\r
++ u32 io_base;\r
++ omap_mcbsp_word_length tx_word_length;\r
++ omap_mcbsp_word_length rx_word_length;\r
+ u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;\r
+ \r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
++ return -ENODEV;\r
++ }\r
++\r
++ io_base = mcbsp[id].io_base;\r
++ tx_word_length = mcbsp[id].tx_word_length;\r
++ rx_word_length = mcbsp[id].rx_word_length;\r
++\r
+ if (tx_word_length != rx_word_length)\r
+ return -EINVAL;\r
+ \r
+@@ -587,7 +497,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)\r
+ udelay(10);\r
+ OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);\r
+ udelay(10);\r
+- printk(KERN_ERR "McBSP transmitter not ready\n");\r
++ dev_err(mcbsp[id].dev, "McBSP%d transmitter not "\r
++ "ready\n", mcbsp[id].id);\r
+ return -EAGAIN;\r
+ }\r
+ }\r
+@@ -607,7 +518,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)\r
+ udelay(10);\r
+ OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);\r
+ udelay(10);\r
+- printk(KERN_ERR "McBSP receiver not ready\n");\r
++ dev_err(mcbsp[id].dev, "McBSP%d receiver not "\r
++ "ready\n", mcbsp[id].id);\r
+ return -EAGAIN;\r
+ }\r
+ }\r
+@@ -623,11 +535,20 @@ EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll);\r
+ \r
+ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word)\r
+ {\r
+- u32 io_base = mcbsp[id].io_base, clock_word = 0;\r
+- omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length;\r
+- omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length;\r
++ u32 io_base, clock_word = 0;\r
++ omap_mcbsp_word_length tx_word_length;\r
++ omap_mcbsp_word_length rx_word_length;\r
+ u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;\r
+ \r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
++ return -ENODEV;\r
++ }\r
++\r
++ io_base = mcbsp[id].io_base;\r
++ tx_word_length = mcbsp[id].tx_word_length;\r
++ rx_word_length = mcbsp[id].rx_word_length;\r
++\r
+ if (tx_word_length != rx_word_length)\r
+ return -EINVAL;\r
+ \r
+@@ -641,7 +562,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word)\r
+ udelay(10);\r
+ OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);\r
+ udelay(10);\r
+- printk(KERN_ERR "McBSP transmitter not ready\n");\r
++ dev_err(mcbsp[id].dev, "McBSP%d transmitter not "\r
++ "ready\n", mcbsp[id].id);\r
+ return -EAGAIN;\r
+ }\r
+ }\r
+@@ -661,7 +583,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word)\r
+ udelay(10);\r
+ OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);\r
+ udelay(10);\r
+- printk(KERN_ERR "McBSP receiver not ready\n");\r
++ dev_err(mcbsp[id].dev, "McBSP%d receiver not "\r
++ "ready\n", mcbsp[id].id);\r
+ return -EAGAIN;\r
+ }\r
+ }\r
+@@ -692,20 +615,24 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer,\r
+ int dest_port = 0;\r
+ int sync_dev = 0;\r
+ \r
+- if (omap_mcbsp_check(id) < 0)\r
+- return -EINVAL;\r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
++ return -ENODEV;\r
++ }\r
+ \r
+ if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX",\r
+ omap_mcbsp_tx_dma_callback,\r
+ &mcbsp[id],\r
+ &dma_tx_ch)) {\r
+- printk(KERN_ERR "OMAP-McBSP: Unable to request DMA channel for"\r
+- " McBSP%d TX. Trying IRQ based TX\n", id + 1);\r
++ dev_err(mcbsp[id].dev, " Unable to request DMA channel for "\r
++ "McBSP%d TX. Trying IRQ based TX\n",\r
++ mcbsp[id].id);\r
+ return -EAGAIN;\r
+ }\r
+ mcbsp[id].dma_tx_lch = dma_tx_ch;\r
+ \r
+- DBG("TX DMA on channel %d\n", dma_tx_ch);\r
++ dev_err(mcbsp[id].dev, "McBSP%d TX DMA on channel %d\n", mcbsp[id].id,\r
++ dma_tx_ch);\r
+ \r
+ init_completion(&(mcbsp[id].tx_dma_completion));\r
+ \r
+@@ -713,7 +640,7 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer,\r
+ src_port = OMAP_DMA_PORT_TIPB;\r
+ dest_port = OMAP_DMA_PORT_EMIFF;\r
+ }\r
+- if (cpu_is_omap24xx())\r
++ if (cpu_class_is_omap2())\r
+ sync_dev = mcbsp[id].dma_tx_sync;\r
+ \r
+ omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,\r
+@@ -749,20 +676,24 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer,\r
+ int dest_port = 0;\r
+ int sync_dev = 0;\r
+ \r
+- if (omap_mcbsp_check(id) < 0)\r
+- return -EINVAL;\r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
++ return -ENODEV;\r
++ }\r
+ \r
+ if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX",\r
+ omap_mcbsp_rx_dma_callback,\r
+ &mcbsp[id],\r
+ &dma_rx_ch)) {\r
+- printk(KERN_ERR "Unable to request DMA channel for McBSP%d RX."\r
+- " Trying IRQ based RX\n", id + 1);\r
++ dev_err(mcbsp[id].dev, "Unable to request DMA channel for "\r
++ "McBSP%d RX. Trying IRQ based RX\n",\r
++ mcbsp[id].id);\r
+ return -EAGAIN;\r
+ }\r
+ mcbsp[id].dma_rx_lch = dma_rx_ch;\r
+ \r
+- DBG("RX DMA on channel %d\n", dma_rx_ch);\r
++ dev_err(mcbsp[id].dev, "McBSP%d RX DMA on channel %d\n", mcbsp[id].id,\r
++ dma_rx_ch);\r
+ \r
+ init_completion(&(mcbsp[id].rx_dma_completion));\r
+ \r
+@@ -770,7 +701,7 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer,\r
+ src_port = OMAP_DMA_PORT_TIPB;\r
+ dest_port = OMAP_DMA_PORT_EMIFF;\r
+ }\r
+- if (cpu_is_omap24xx())\r
++ if (cpu_class_is_omap2())\r
+ sync_dev = mcbsp[id].dma_rx_sync;\r
+ \r
+ omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,\r
+@@ -809,8 +740,10 @@ void omap_mcbsp_set_spi_mode(unsigned int id,\r
+ {\r
+ struct omap_mcbsp_reg_cfg mcbsp_cfg;\r
+ \r
+- if (omap_mcbsp_check(id) < 0)\r
++ if (!omap_mcbsp_check_valid_id(id)) {\r
++ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);\r
+ return;\r
++ }\r
+ \r
+ memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg));\r
+ \r
+@@ -871,182 +804,91 @@ EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);\r
+ * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.\r
+ * 730 has only 2 McBSP, and both of them are MPU peripherals.\r
+ */\r
+-struct omap_mcbsp_info {\r
+- u32 virt_base;\r
+- u8 dma_rx_sync, dma_tx_sync;\r
+- u16 rx_irq, tx_irq;\r
+-};\r
++static int __init omap_mcbsp_probe(struct platform_device *pdev)\r
++{\r
++ struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data;\r
++ int id = pdev->id - 1;\r
++ int ret = 0;\r
++ int i;\r
+ \r
+-#ifdef CONFIG_ARCH_OMAP730\r
+-static const struct omap_mcbsp_info mcbsp_730[] = {\r
+- [0] = { .virt_base = io_p2v(OMAP730_MCBSP1_BASE),\r
+- .dma_rx_sync = OMAP_DMA_MCBSP1_RX,\r
+- .dma_tx_sync = OMAP_DMA_MCBSP1_TX,\r
+- .rx_irq = INT_730_McBSP1RX,\r
+- .tx_irq = INT_730_McBSP1TX },\r
+- [1] = { .virt_base = io_p2v(OMAP730_MCBSP2_BASE),\r
+- .dma_rx_sync = OMAP_DMA_MCBSP3_RX,\r
+- .dma_tx_sync = OMAP_DMA_MCBSP3_TX,\r
+- .rx_irq = INT_730_McBSP2RX,\r
+- .tx_irq = INT_730_McBSP2TX },\r
+-};\r
+-#endif\r
+-\r
+-#ifdef CONFIG_ARCH_OMAP15XX\r
+-static const struct omap_mcbsp_info mcbsp_1510[] = {\r
+- [0] = { .virt_base = OMAP1510_MCBSP1_BASE,\r
+- .dma_rx_sync = OMAP_DMA_MCBSP1_RX,\r
+- .dma_tx_sync = OMAP_DMA_MCBSP1_TX,\r
+- .rx_irq = INT_McBSP1RX,\r
+- .tx_irq = INT_McBSP1TX },\r
+- [1] = { .virt_base = io_p2v(OMAP1510_MCBSP2_BASE),\r
+- .dma_rx_sync = OMAP_DMA_MCBSP2_RX,\r
+- .dma_tx_sync = OMAP_DMA_MCBSP2_TX,\r
+- .rx_irq = INT_1510_SPI_RX,\r
+- .tx_irq = INT_1510_SPI_TX },\r
+- [2] = { .virt_base = OMAP1510_MCBSP3_BASE,\r
+- .dma_rx_sync = OMAP_DMA_MCBSP3_RX,\r
+- .dma_tx_sync = OMAP_DMA_MCBSP3_TX,\r
+- .rx_irq = INT_McBSP3RX,\r
+- .tx_irq = INT_McBSP3TX },\r
+-};\r
+-#endif\r
+-\r
+-#if defined(CONFIG_ARCH_OMAP16XX)\r
+-static const struct omap_mcbsp_info mcbsp_1610[] = {\r
+- [0] = { .virt_base = OMAP1610_MCBSP1_BASE,\r
+- .dma_rx_sync = OMAP_DMA_MCBSP1_RX,\r
+- .dma_tx_sync = OMAP_DMA_MCBSP1_TX,\r
+- .rx_irq = INT_McBSP1RX,\r
+- .tx_irq = INT_McBSP1TX },\r
+- [1] = { .virt_base = io_p2v(OMAP1610_MCBSP2_BASE),\r
+- .dma_rx_sync = OMAP_DMA_MCBSP2_RX,\r
+- .dma_tx_sync = OMAP_DMA_MCBSP2_TX,\r
+- .rx_irq = INT_1610_McBSP2_RX,\r
+- .tx_irq = INT_1610_McBSP2_TX },\r
+- [2] = { .virt_base = OMAP1610_MCBSP3_BASE,\r
+- .dma_rx_sync = OMAP_DMA_MCBSP3_RX,\r
+- .dma_tx_sync = OMAP_DMA_MCBSP3_TX,\r
+- .rx_irq = INT_McBSP3RX,\r
+- .tx_irq = INT_McBSP3TX },\r
+-};\r
+-#endif\r
+-\r
+-#if defined(CONFIG_ARCH_OMAP24XX)\r
+-static const struct omap_mcbsp_info mcbsp_24xx[] = {\r
+- [0] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE),\r
+- .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,\r
+- .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,\r
+- .rx_irq = INT_24XX_MCBSP1_IRQ_RX,\r
+- .tx_irq = INT_24XX_MCBSP1_IRQ_TX,\r
+- },\r
+- [1] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE),\r
+- .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,\r
+- .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,\r
+- .rx_irq = INT_24XX_MCBSP2_IRQ_RX,\r
+- .tx_irq = INT_24XX_MCBSP2_IRQ_TX,\r
+- },\r
+-};\r
+-#endif\r
++ if (!pdata) {\r
++ dev_err(&pdev->dev, "McBSP device initialized without"\r
++ "platform data\n");\r
++ ret = -EINVAL;\r
++ goto exit;\r
++ }\r
+ \r
+-static int __init omap_mcbsp_init(void)\r
++ dev_dbg(&pdev->dev, "Initializing OMAP McBSP (%d).\n", pdev->id);\r
++\r
++ if (id >= OMAP_MAX_MCBSP_COUNT) {\r
++ dev_err(&pdev->dev, "Invalid McBSP device id (%d)\n", id);\r
++ ret = -EINVAL;\r
++ goto exit;\r
++ }\r
++\r
++ spin_lock_init(&mcbsp[id].lock);\r
++ mcbsp[id].id = id + 1;\r
++ mcbsp[id].free = 1;\r
++ mcbsp[id].dma_tx_lch = -1;\r
++ mcbsp[id].dma_rx_lch = -1;\r
++\r
++ mcbsp[id].io_base = pdata->virt_base;\r
++ /* Default I/O is IRQ based */\r
++ mcbsp[id].io_type = OMAP_MCBSP_IRQ_IO;\r
++ mcbsp[id].tx_irq = pdata->tx_irq;\r
++ mcbsp[id].rx_irq = pdata->rx_irq;\r
++ mcbsp[id].dma_rx_sync = pdata->dma_rx_sync;\r
++ mcbsp[id].dma_tx_sync = pdata->dma_tx_sync;\r
++\r
++ mcbsp[id].nr_clocks = ARRAY_SIZE(pdata->clocks);\r
++ for (i = 0; i < ARRAY_SIZE(pdata->clocks); i++)\r
++ mcbsp[id].clocks[i] = clk_get(&pdev->dev, pdata->clocks[i]);\r
++\r
++ mcbsp[id].pdata = pdata;\r
++ mcbsp[id].dev = &pdev->dev;\r
++ platform_set_drvdata(pdev, &mcbsp[id]);\r
++\r
++exit:\r
++ return ret;\r
++}\r
++\r
++static int omap_mcbsp_remove(struct platform_device *pdev)\r
+ {\r
+- int mcbsp_count = 0, i;\r
+- static const struct omap_mcbsp_info *mcbsp_info;\r
++ struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);\r
+ \r
+- printk(KERN_INFO "Initializing OMAP McBSP system\n");\r
++ platform_set_drvdata(pdev, NULL);\r
++ if (mcbsp) {\r
++ int i;\r
+ \r
+-#ifdef CONFIG_ARCH_OMAP1\r
+- mcbsp_dsp_ck = clk_get(0, "dsp_ck");\r
+- if (IS_ERR(mcbsp_dsp_ck)) {\r
+- printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n");\r
+- return PTR_ERR(mcbsp_dsp_ck);\r
+- }\r
+- mcbsp_api_ck = clk_get(0, "api_ck");\r
+- if (IS_ERR(mcbsp_api_ck)) {\r
+- printk(KERN_ERR "mcbsp: could not acquire api_ck handle.\n");\r
+- return PTR_ERR(mcbsp_api_ck);\r
+- }\r
+- mcbsp_dspxor_ck = clk_get(0, "dspxor_ck");\r
+- if (IS_ERR(mcbsp_dspxor_ck)) {\r
+- printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n");\r
+- return PTR_ERR(mcbsp_dspxor_ck);\r
+- }\r
+-#endif\r
+-#ifdef CONFIG_ARCH_OMAP2\r
+- mcbsp1_ick = clk_get(0, "mcbsp1_ick");\r
+- if (IS_ERR(mcbsp1_ick)) {\r
+- printk(KERN_ERR "mcbsp: could not acquire "\r
+- "mcbsp1_ick handle.\n");\r
+- return PTR_ERR(mcbsp1_ick);\r
+- }\r
+- mcbsp1_fck = clk_get(0, "mcbsp1_fck");\r
+- if (IS_ERR(mcbsp1_fck)) {\r
+- printk(KERN_ERR "mcbsp: could not acquire "\r
+- "mcbsp1_fck handle.\n");\r
+- return PTR_ERR(mcbsp1_fck);\r
+- }\r
+- mcbsp2_ick = clk_get(0, "mcbsp2_ick");\r
+- if (IS_ERR(mcbsp2_ick)) {\r
+- printk(KERN_ERR "mcbsp: could not acquire "\r
+- "mcbsp2_ick handle.\n");\r
+- return PTR_ERR(mcbsp2_ick);\r
+- }\r
+- mcbsp2_fck = clk_get(0, "mcbsp2_fck");\r
+- if (IS_ERR(mcbsp2_fck)) {\r
+- printk(KERN_ERR "mcbsp: could not acquire "\r
+- "mcbsp2_fck handle.\n");\r
+- return PTR_ERR(mcbsp2_fck);\r
+- }\r
+-#endif\r
++ if (mcbsp->pdata && mcbsp->pdata->ops &&\r
++ mcbsp->pdata->ops->free)\r
++ mcbsp->pdata->ops->free(mcbsp->id);\r
+ \r
+-#ifdef CONFIG_ARCH_OMAP730\r
+- if (cpu_is_omap730()) {\r
+- mcbsp_info = mcbsp_730;\r
+- mcbsp_count = ARRAY_SIZE(mcbsp_730);\r
+- }\r
+-#endif\r
+-#ifdef CONFIG_ARCH_OMAP15XX\r
+- if (cpu_is_omap15xx()) {\r
+- mcbsp_info = mcbsp_1510;\r
+- mcbsp_count = ARRAY_SIZE(mcbsp_1510);\r
+- }\r
+-#endif\r
+-#if defined(CONFIG_ARCH_OMAP16XX)\r
+- if (cpu_is_omap16xx()) {\r
+- mcbsp_info = mcbsp_1610;\r
+- mcbsp_count = ARRAY_SIZE(mcbsp_1610);\r
+- }\r
+-#endif\r
+-#if defined(CONFIG_ARCH_OMAP24XX)\r
+- if (cpu_is_omap24xx()) {\r
+- mcbsp_info = mcbsp_24xx;\r
+- mcbsp_count = ARRAY_SIZE(mcbsp_24xx);\r
+- omap2_mcbsp2_mux_setup();\r
+- }\r
+-#endif\r
+- for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {\r
+- if (i >= mcbsp_count) {\r
+- mcbsp[i].io_base = 0;\r
+- mcbsp[i].free = 0;\r
+- continue;\r
+- }\r
+- mcbsp[i].id = i + 1;\r
+- mcbsp[i].free = 1;\r
+- mcbsp[i].dma_tx_lch = -1;\r
+- mcbsp[i].dma_rx_lch = -1;\r
+-\r
+- mcbsp[i].io_base = mcbsp_info[i].virt_base;\r
+- /* Default I/O is IRQ based */\r
+- mcbsp[i].io_type = OMAP_MCBSP_IRQ_IO;\r
+- mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;\r
+- mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;\r
+- mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;\r
+- mcbsp[i].dma_tx_sync = mcbsp_info[i].dma_tx_sync;\r
+- spin_lock_init(&mcbsp[i].lock);\r
++ mcbsp_clk_disable(mcbsp);\r
++ mcbsp_clk_put(mcbsp);\r
++\r
++ for (i = 0; i < mcbsp->nr_clocks; i++)\r
++ mcbsp->clocks[i] = NULL;\r
++\r
++ mcbsp->free = 0;\r
++ mcbsp->dev = NULL;\r
+ }\r
+ \r
+ return 0;\r
+ }\r
+ \r
+-arch_initcall(omap_mcbsp_init);\r
++static struct platform_driver omap_mcbsp_driver = {\r
++ .probe = omap_mcbsp_probe,\r
++ .remove = omap_mcbsp_remove,\r
++ .driver = {\r
++ .name = "omap-mcbsp",\r
++ },\r
++};\r
++\r
++int __init omap_mcbsp_init(void)\r
++{\r
++ /* Register the McBSP driver */\r
++ return platform_driver_register(&omap_mcbsp_driver);\r
++}\r
++\r
++\r
+diff --git a/include/asm-arm/arch-omap/mcbsp.h b/include/asm-arm/arch-omap/mcbsp.h\r
+index b53c3b2..aa47421 100644\r
+--- a/include/asm-arm/arch-omap/mcbsp.h\r
++++ b/include/asm-arm/arch-omap/mcbsp.h\r
+@@ -24,7 +24,11 @@\r
+ #ifndef __ASM_ARCH_OMAP_MCBSP_H\r
+ #define __ASM_ARCH_OMAP_MCBSP_H\r
+ \r
++#include <linux/completion.h>\r
++#include <linux/spinlock.h>\r
++\r
+ #include <asm/hardware.h>\r
++#include <asm/arch/clock.h>\r
+ \r
+ #define OMAP730_MCBSP1_BASE 0xfffb1000\r
+ #define OMAP730_MCBSP2_BASE 0xfffb1800\r
+@@ -40,6 +44,9 @@\r
+ #define OMAP24XX_MCBSP1_BASE 0x48074000\r
+ #define OMAP24XX_MCBSP2_BASE 0x48076000\r
+ \r
++#define OMAP34XX_MCBSP1_BASE 0x48074000\r
++#define OMAP34XX_MCBSP2_BASE 0x49022000\r
++\r
+ #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730)\r
+ \r
+ #define OMAP_MCBSP_REG_DRR2 0x00\r
+@@ -74,7 +81,8 @@\r
+ #define OMAP_MCBSP_REG_XCERG 0x3A\r
+ #define OMAP_MCBSP_REG_XCERH 0x3C\r
+ \r
+-#define OMAP_MAX_MCBSP_COUNT 3\r
++#define OMAP_MAX_MCBSP_COUNT 3\r
++#define MAX_MCBSP_CLOCKS 3\r
+ \r
+ #define AUDIO_MCBSP_DATAWRITE (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1)\r
+ #define AUDIO_MCBSP_DATAREAD (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1)\r
+@@ -117,7 +125,8 @@\r
+ #define OMAP_MCBSP_REG_XCERG 0x74\r
+ #define OMAP_MCBSP_REG_XCERH 0x78\r
+ \r
+-#define OMAP_MAX_MCBSP_COUNT 2\r
++#define OMAP_MAX_MCBSP_COUNT 2\r
++#define MAX_MCBSP_CLOCKS 2\r
+ \r
+ #define AUDIO_MCBSP_DATAWRITE (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1)\r
+ #define AUDIO_MCBSP_DATAREAD (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1)\r
+@@ -298,6 +307,66 @@ struct omap_mcbsp_spi_cfg {\r
+ omap_mcbsp_word_length word_length;\r
+ };\r
+ \r
++/* Platform specific configuration */\r
++struct omap_mcbsp_ops {\r
++ void (*request)(unsigned int);\r
++ void (*free)(unsigned int);\r
++ int (*check)(unsigned int);\r
++};\r
++\r
++struct omap_mcbsp_platform_data {\r
++ u32 virt_base;\r
++ u8 dma_rx_sync, dma_tx_sync;\r
++ u16 rx_irq, tx_irq;\r
++ struct omap_mcbsp_ops *ops;\r
++ char const *clocks[MAX_MCBSP_CLOCKS];\r
++};\r
++\r
++struct omap_mcbsp {\r
++ struct device *dev;\r
++ u32 io_base;\r
++ u8 id;\r
++ u8 free;\r
++ omap_mcbsp_word_length rx_word_length;\r
++ omap_mcbsp_word_length tx_word_length;\r
++\r
++ omap_mcbsp_io_type_t io_type; /* IRQ or poll */\r
++ /* IRQ based TX/RX */\r
++ int rx_irq;\r
++ int tx_irq;\r
++\r
++ /* DMA stuff */\r
++ u8 dma_rx_sync;\r
++ short dma_rx_lch;\r
++ u8 dma_tx_sync;\r
++ short dma_tx_lch;\r
++\r
++ /* Completion queues */\r
++ struct completion tx_irq_completion;\r
++ struct completion rx_irq_completion;\r
++ struct completion tx_dma_completion;\r
++ struct completion rx_dma_completion;\r
++\r
++ /* Protect the field .free, while checking if the mcbsp is in use */\r
++ spinlock_t lock;\r
++ struct omap_mcbsp_platform_data *pdata;\r
++ int nr_clocks;\r
++ struct clk *clocks[MAX_MCBSP_CLOCKS];\r
++};\r
++\r
++#define __mcbsp_clk_op(mcbsp, op) \\r
++ do { \\r
++ int i; \\r
++ for (i = 0; i < mcbsp->nr_clocks; i++) \\r
++ clk_##op(mcbsp->clocks[i]); \\r
++ } while (0)\r
++#define mcbsp_clk_enable(mcbsp) __mcbsp_clk_op((mcbsp), enable)\r
++#define mcbsp_clk_disable(mcbsp) __mcbsp_clk_op((mcbsp), disable)\r
++#define mcbsp_clk_put(mcbsp) __mcbsp_clk_op((mcbsp), put)\r
++\r
++int omap_mcbsp_init(void);\r
++void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,\r
++ int size);\r
+ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config);\r
+ int omap_mcbsp_request(unsigned int id);\r
+ void omap_mcbsp_free(unsigned int id);\r
+-- \r
+1.5.5.1.67.gbdb8.dirty\r
+\r
+--\r
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in\r
+the body of a message to majordomo@vger.kernel.org\r
+More majordomo info at http://vger.kernel.org/majordomo-info.html\r
+\r