203 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * linux/arch/arm/mach-omap1/mcbsp.c
 | |
|  *
 | |
|  * Copyright (C) 2008 Instituto Nokia de Tecnologia
 | |
|  * Contact: Eduardo Valentin <eduardo.valentin@indt.org.br>
 | |
|  *
 | |
|  * 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.
 | |
|  *
 | |
|  * Multichannel mode not supported.
 | |
|  */
 | |
| #include <linux/module.h>
 | |
| #include <linux/init.h>
 | |
| #include <linux/clk.h>
 | |
| #include <linux/err.h>
 | |
| #include <linux/io.h>
 | |
| #include <linux/platform_device.h>
 | |
| 
 | |
| #include <mach/irqs.h>
 | |
| #include <mach/dma.h>
 | |
| #include <mach/mux.h>
 | |
| #include <mach/cpu.h>
 | |
| #include <mach/mcbsp.h>
 | |
| #include <mach/dsp_common.h>
 | |
| 
 | |
| #define DPS_RSTCT2_PER_EN	(1 << 0)
 | |
| #define DSP_RSTCT2_WD_PER_EN	(1 << 1)
 | |
| 
 | |
| static int dsp_use;
 | |
| static struct clk *api_clk;
 | |
| static struct clk *dsp_clk;
 | |
| 
 | |
| static void omap1_mcbsp_request(unsigned int id)
 | |
| {
 | |
| 	/*
 | |
| 	 * On 1510, 1610 and 1710, McBSP1 and McBSP3
 | |
| 	 * are DSP public peripherals.
 | |
| 	 */
 | |
| 	if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
 | |
| 		if (dsp_use++ == 0) {
 | |
| 			api_clk = clk_get(NULL, "api_ck");
 | |
| 			dsp_clk = clk_get(NULL, "dsp_ck");
 | |
| 			if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
 | |
| 				clk_enable(api_clk);
 | |
| 				clk_enable(dsp_clk);
 | |
| 
 | |
| 				omap_dsp_request_mem();
 | |
| 				/*
 | |
| 				 * DSP external peripheral reset
 | |
| 				 * FIXME: This should be moved to dsp code
 | |
| 				 */
 | |
| 				__raw_writew(__raw_readw(DSP_RSTCT2) | DPS_RSTCT2_PER_EN |
 | |
| 						DSP_RSTCT2_WD_PER_EN, DSP_RSTCT2);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void omap1_mcbsp_free(unsigned int id)
 | |
| {
 | |
| 	if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
 | |
| 		if (--dsp_use == 0) {
 | |
| 			omap_dsp_release_mem();
 | |
| 			if (!IS_ERR(api_clk)) {
 | |
| 				clk_disable(api_clk);
 | |
| 				clk_put(api_clk);
 | |
| 			}
 | |
| 			if (!IS_ERR(dsp_clk)) {
 | |
| 				clk_disable(dsp_clk);
 | |
| 				clk_put(dsp_clk);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static struct omap_mcbsp_ops omap1_mcbsp_ops = {
 | |
| 	.request	= omap1_mcbsp_request,
 | |
| 	.free		= omap1_mcbsp_free,
 | |
| };
 | |
| 
 | |
| #ifdef CONFIG_ARCH_OMAP730
 | |
| static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
 | |
| 	{
 | |
| 		.phys_base	= OMAP730_MCBSP1_BASE,
 | |
| 		.dma_rx_sync	= OMAP_DMA_MCBSP1_RX,
 | |
| 		.dma_tx_sync	= OMAP_DMA_MCBSP1_TX,
 | |
| 		.rx_irq		= INT_730_McBSP1RX,
 | |
| 		.tx_irq		= INT_730_McBSP1TX,
 | |
| 		.ops		= &omap1_mcbsp_ops,
 | |
| 	},
 | |
| 	{
 | |
| 		.phys_base	= OMAP730_MCBSP2_BASE,
 | |
| 		.dma_rx_sync	= OMAP_DMA_MCBSP3_RX,
 | |
| 		.dma_tx_sync	= OMAP_DMA_MCBSP3_TX,
 | |
| 		.rx_irq		= INT_730_McBSP2RX,
 | |
| 		.tx_irq		= INT_730_McBSP2TX,
 | |
| 		.ops		= &omap1_mcbsp_ops,
 | |
| 	},
 | |
| };
 | |
| #define OMAP730_MCBSP_PDATA_SZ		ARRAY_SIZE(omap730_mcbsp_pdata)
 | |
| #else
 | |
| #define omap730_mcbsp_pdata		NULL
 | |
| #define OMAP730_MCBSP_PDATA_SZ		0
 | |
| #endif
 | |
| 
 | |
| #ifdef CONFIG_ARCH_OMAP15XX
 | |
| static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
 | |
| 	{
 | |
| 		.phys_base	= OMAP1510_MCBSP1_BASE,
 | |
| 		.dma_rx_sync	= OMAP_DMA_MCBSP1_RX,
 | |
| 		.dma_tx_sync	= OMAP_DMA_MCBSP1_TX,
 | |
| 		.rx_irq		= INT_McBSP1RX,
 | |
| 		.tx_irq		= INT_McBSP1TX,
 | |
| 		.ops		= &omap1_mcbsp_ops,
 | |
| 	},
 | |
| 	{
 | |
| 		.phys_base	= OMAP1510_MCBSP2_BASE,
 | |
| 		.dma_rx_sync	= OMAP_DMA_MCBSP2_RX,
 | |
| 		.dma_tx_sync	= OMAP_DMA_MCBSP2_TX,
 | |
| 		.rx_irq		= INT_1510_SPI_RX,
 | |
| 		.tx_irq		= INT_1510_SPI_TX,
 | |
| 		.ops		= &omap1_mcbsp_ops,
 | |
| 	},
 | |
| 	{
 | |
| 		.phys_base	= OMAP1510_MCBSP3_BASE,
 | |
| 		.dma_rx_sync	= OMAP_DMA_MCBSP3_RX,
 | |
| 		.dma_tx_sync	= OMAP_DMA_MCBSP3_TX,
 | |
| 		.rx_irq		= INT_McBSP3RX,
 | |
| 		.tx_irq		= INT_McBSP3TX,
 | |
| 		.ops		= &omap1_mcbsp_ops,
 | |
| 	},
 | |
| };
 | |
| #define OMAP15XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap15xx_mcbsp_pdata)
 | |
| #else
 | |
| #define omap15xx_mcbsp_pdata		NULL
 | |
| #define OMAP15XX_MCBSP_PDATA_SZ		0
 | |
| #endif
 | |
| 
 | |
| #ifdef CONFIG_ARCH_OMAP16XX
 | |
| static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
 | |
| 	{
 | |
| 		.phys_base	= OMAP1610_MCBSP1_BASE,
 | |
| 		.dma_rx_sync	= OMAP_DMA_MCBSP1_RX,
 | |
| 		.dma_tx_sync	= OMAP_DMA_MCBSP1_TX,
 | |
| 		.rx_irq		= INT_McBSP1RX,
 | |
| 		.tx_irq		= INT_McBSP1TX,
 | |
| 		.ops		= &omap1_mcbsp_ops,
 | |
| 	},
 | |
| 	{
 | |
| 		.phys_base	= OMAP1610_MCBSP2_BASE,
 | |
| 		.dma_rx_sync	= OMAP_DMA_MCBSP2_RX,
 | |
| 		.dma_tx_sync	= OMAP_DMA_MCBSP2_TX,
 | |
| 		.rx_irq		= INT_1610_McBSP2_RX,
 | |
| 		.tx_irq		= INT_1610_McBSP2_TX,
 | |
| 		.ops		= &omap1_mcbsp_ops,
 | |
| 	},
 | |
| 	{
 | |
| 		.phys_base	= OMAP1610_MCBSP3_BASE,
 | |
| 		.dma_rx_sync	= OMAP_DMA_MCBSP3_RX,
 | |
| 		.dma_tx_sync	= OMAP_DMA_MCBSP3_TX,
 | |
| 		.rx_irq		= INT_McBSP3RX,
 | |
| 		.tx_irq		= INT_McBSP3TX,
 | |
| 		.ops		= &omap1_mcbsp_ops,
 | |
| 	},
 | |
| };
 | |
| #define OMAP16XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap16xx_mcbsp_pdata)
 | |
| #else
 | |
| #define omap16xx_mcbsp_pdata		NULL
 | |
| #define OMAP16XX_MCBSP_PDATA_SZ		0
 | |
| #endif
 | |
| 
 | |
| int __init omap1_mcbsp_init(void)
 | |
| {
 | |
| 	if (cpu_is_omap730())
 | |
| 		omap_mcbsp_count = OMAP730_MCBSP_PDATA_SZ;
 | |
| 	if (cpu_is_omap15xx())
 | |
| 		omap_mcbsp_count = OMAP15XX_MCBSP_PDATA_SZ;
 | |
| 	if (cpu_is_omap16xx())
 | |
| 		omap_mcbsp_count = OMAP16XX_MCBSP_PDATA_SZ;
 | |
| 
 | |
| 	mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
 | |
| 								GFP_KERNEL);
 | |
| 	if (!mcbsp_ptr)
 | |
| 		return -ENOMEM;
 | |
| 
 | |
| 	if (cpu_is_omap730())
 | |
| 		omap_mcbsp_register_board_cfg(omap730_mcbsp_pdata,
 | |
| 						OMAP730_MCBSP_PDATA_SZ);
 | |
| 
 | |
| 	if (cpu_is_omap15xx())
 | |
| 		omap_mcbsp_register_board_cfg(omap15xx_mcbsp_pdata,
 | |
| 						OMAP15XX_MCBSP_PDATA_SZ);
 | |
| 
 | |
| 	if (cpu_is_omap16xx())
 | |
| 		omap_mcbsp_register_board_cfg(omap16xx_mcbsp_pdata,
 | |
| 						OMAP16XX_MCBSP_PDATA_SZ);
 | |
| 
 | |
| 	return omap_mcbsp_init();
 | |
| }
 | |
| 
 | |
| arch_initcall(omap1_mcbsp_init);
 |