2 * Copyright (C) ST-Ericsson SA 2010
4 * License terms: GNU General Public License (GPL), version 2
7 #include <linux/platform_device.h>
8 #include <linux/init.h>
9 #include <linux/gpio.h>
10 #include <linux/pinctrl/consumer.h>
12 #include <plat/gpio-nomadik.h>
13 #include <plat/pincfg.h>
14 #include <plat/ste_dma40.h>
16 #include <mach/devices.h>
17 #include <mach/hardware.h>
18 #include <mach/irqs.h>
21 #include "ste-dma40-db8500.h"
22 #include "board-mop500.h"
23 #include "devices-db8500.h"
24 #include "pins-db8500.h"
26 /* MSP1/3 Tx/Rx usage protection */
27 static DEFINE_SPINLOCK(msp_rxtx_lock
);
30 static int msp_rxtx_ref
;
33 struct pinctrl
*msp1_p
;
34 struct pinctrl_state
*msp1_def
;
35 struct pinctrl_state
*msp1_sleep
;
37 int msp13_i2s_init(void)
42 spin_lock_irqsave(&msp_rxtx_lock
, flags
);
43 if (msp_rxtx_ref
== 0 && !(IS_ERR(msp1_p
) || IS_ERR(msp1_def
))) {
44 retval
= pinctrl_select_state(msp1_p
, msp1_def
);
46 pr_err("could not set MSP1 defstate\n");
50 spin_unlock_irqrestore(&msp_rxtx_lock
, flags
);
55 int msp13_i2s_exit(void)
60 spin_lock_irqsave(&msp_rxtx_lock
, flags
);
61 WARN_ON(!msp_rxtx_ref
);
63 if (msp_rxtx_ref
== 0 && !(IS_ERR(msp1_p
) || IS_ERR(msp1_sleep
))) {
64 retval
= pinctrl_select_state(msp1_p
, msp1_sleep
);
66 pr_err("could not set MSP1 sleepstate\n");
68 spin_unlock_irqrestore(&msp_rxtx_lock
, flags
);
73 static struct stedma40_chan_cfg msp0_dma_rx
= {
74 .high_priority
= true,
75 .dir
= STEDMA40_PERIPH_TO_MEM
,
77 .src_dev_type
= DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX
,
78 .dst_dev_type
= STEDMA40_DEV_DST_MEMORY
,
80 .src_info
.psize
= STEDMA40_PSIZE_LOG_4
,
81 .dst_info
.psize
= STEDMA40_PSIZE_LOG_4
,
83 /* data_width is set during configuration */
86 static struct stedma40_chan_cfg msp0_dma_tx
= {
87 .high_priority
= true,
88 .dir
= STEDMA40_MEM_TO_PERIPH
,
90 .src_dev_type
= STEDMA40_DEV_DST_MEMORY
,
91 .dst_dev_type
= DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX
,
93 .src_info
.psize
= STEDMA40_PSIZE_LOG_4
,
94 .dst_info
.psize
= STEDMA40_PSIZE_LOG_4
,
96 /* data_width is set during configuration */
99 static struct msp_i2s_platform_data msp0_platform_data
= {
101 .msp_i2s_dma_rx
= &msp0_dma_rx
,
102 .msp_i2s_dma_tx
= &msp0_dma_tx
,
105 static struct stedma40_chan_cfg msp1_dma_rx
= {
106 .high_priority
= true,
107 .dir
= STEDMA40_PERIPH_TO_MEM
,
109 .src_dev_type
= DB8500_DMA_DEV30_MSP3_RX
,
110 .dst_dev_type
= STEDMA40_DEV_DST_MEMORY
,
112 .src_info
.psize
= STEDMA40_PSIZE_LOG_4
,
113 .dst_info
.psize
= STEDMA40_PSIZE_LOG_4
,
115 /* data_width is set during configuration */
118 static struct stedma40_chan_cfg msp1_dma_tx
= {
119 .high_priority
= true,
120 .dir
= STEDMA40_MEM_TO_PERIPH
,
122 .src_dev_type
= STEDMA40_DEV_DST_MEMORY
,
123 .dst_dev_type
= DB8500_DMA_DEV30_MSP1_TX
,
125 .src_info
.psize
= STEDMA40_PSIZE_LOG_4
,
126 .dst_info
.psize
= STEDMA40_PSIZE_LOG_4
,
128 /* data_width is set during configuration */
131 static struct msp_i2s_platform_data msp1_platform_data
= {
133 .msp_i2s_dma_rx
= NULL
,
134 .msp_i2s_dma_tx
= &msp1_dma_tx
,
135 .msp_i2s_init
= msp13_i2s_init
,
136 .msp_i2s_exit
= msp13_i2s_exit
,
139 static struct stedma40_chan_cfg msp2_dma_rx
= {
140 .high_priority
= true,
141 .dir
= STEDMA40_PERIPH_TO_MEM
,
143 .src_dev_type
= DB8500_DMA_DEV14_MSP2_RX
,
144 .dst_dev_type
= STEDMA40_DEV_DST_MEMORY
,
146 /* MSP2 DMA doesn't work with PSIZE == 4 on DB8500v2 */
147 .src_info
.psize
= STEDMA40_PSIZE_LOG_1
,
148 .dst_info
.psize
= STEDMA40_PSIZE_LOG_1
,
150 /* data_width is set during configuration */
153 static struct stedma40_chan_cfg msp2_dma_tx
= {
154 .high_priority
= true,
155 .dir
= STEDMA40_MEM_TO_PERIPH
,
157 .src_dev_type
= STEDMA40_DEV_DST_MEMORY
,
158 .dst_dev_type
= DB8500_DMA_DEV14_MSP2_TX
,
160 .src_info
.psize
= STEDMA40_PSIZE_LOG_4
,
161 .dst_info
.psize
= STEDMA40_PSIZE_LOG_4
,
163 .use_fixed_channel
= true,
166 /* data_width is set during configuration */
169 static struct platform_device
*db8500_add_msp_i2s(struct device
*parent
,
171 resource_size_t base
, int irq
,
172 struct msp_i2s_platform_data
*pdata
)
174 struct platform_device
*pdev
;
175 struct resource res
[] = {
176 DEFINE_RES_MEM(base
, SZ_4K
),
180 pr_info("Register platform-device 'ux500-msp-i2s', id %d, irq %d\n",
182 pdev
= platform_device_register_resndata(parent
, "ux500-msp-i2s", id
,
183 res
, ARRAY_SIZE(res
),
184 pdata
, sizeof(*pdata
));
186 pr_err("Failed to register platform-device 'ux500-msp-i2s.%d'!\n",
194 /* Platform device for ASoC MOP500 machine */
195 static struct platform_device snd_soc_mop500
= {
196 .name
= "snd-soc-mop500",
199 .platform_data
= NULL
,
203 /* Platform device for Ux500-PCM */
204 static struct platform_device ux500_pcm
= {
208 .platform_data
= NULL
,
212 static struct msp_i2s_platform_data msp2_platform_data
= {
214 .msp_i2s_dma_rx
= &msp2_dma_rx
,
215 .msp_i2s_dma_tx
= &msp2_dma_tx
,
218 static struct msp_i2s_platform_data msp3_platform_data
= {
220 .msp_i2s_dma_rx
= &msp1_dma_rx
,
221 .msp_i2s_dma_tx
= NULL
,
222 .msp_i2s_init
= msp13_i2s_init
,
223 .msp_i2s_exit
= msp13_i2s_exit
,
226 int mop500_msp_init(struct device
*parent
)
228 struct platform_device
*msp1
;
230 pr_info("%s: Register platform-device 'snd-soc-mop500'.\n", __func__
);
231 platform_device_register(&snd_soc_mop500
);
233 pr_info("Initialize MSP I2S-devices.\n");
234 db8500_add_msp_i2s(parent
, 0, U8500_MSP0_BASE
, IRQ_DB8500_MSP0
,
235 &msp0_platform_data
);
236 msp1
= db8500_add_msp_i2s(parent
, 1, U8500_MSP1_BASE
, IRQ_DB8500_MSP1
,
237 &msp1_platform_data
);
238 db8500_add_msp_i2s(parent
, 2, U8500_MSP2_BASE
, IRQ_DB8500_MSP2
,
239 &msp2_platform_data
);
240 db8500_add_msp_i2s(parent
, 3, U8500_MSP3_BASE
, IRQ_DB8500_MSP1
,
241 &msp3_platform_data
);
243 /* Get the pinctrl handle for MSP1 */
245 msp1_p
= pinctrl_get(&msp1
->dev
);
247 dev_err(&msp1
->dev
, "could not get MSP1 pinctrl\n");
249 msp1_def
= pinctrl_lookup_state(msp1_p
,
250 PINCTRL_STATE_DEFAULT
);
251 if (IS_ERR(msp1_def
)) {
253 "could not get MSP1 defstate\n");
255 msp1_sleep
= pinctrl_lookup_state(msp1_p
,
256 PINCTRL_STATE_SLEEP
);
257 if (IS_ERR(msp1_sleep
))
259 "could not get MSP1 idlestate\n");
263 pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__
);
264 platform_device_register(&ux500_pcm
);