summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx233/ssp-imx233.c
diff options
context:
space:
mode:
authorAmaury Pouly <pamaury@rockbox.org>2011-06-30 17:31:40 +0000
committerAmaury Pouly <pamaury@rockbox.org>2011-06-30 17:31:40 +0000
commit617d1e9f6b7969aff5e45746b9c5e3cee9ce2c45 (patch)
treebf2015d298c2b6bc80189d09b73426380e08451f /firmware/target/arm/imx233/ssp-imx233.c
parent4a04c47a97517930b29f00b9d7f4d157cb69fa9b (diff)
downloadrockbox-617d1e9f6b7969aff5e45746b9c5e3cee9ce2c45.tar.gz
rockbox-617d1e9f6b7969aff5e45746b9c5e3cee9ce2c45.zip
imx233/fuze+: ssp, dma, mmc now work properly, partially implement cpu frequency changing, implement panic waiting
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30104 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/imx233/ssp-imx233.c')
-rw-r--r--firmware/target/arm/imx233/ssp-imx233.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/firmware/target/arm/imx233/ssp-imx233.c b/firmware/target/arm/imx233/ssp-imx233.c
index c6be869ce6..22824964f3 100644
--- a/firmware/target/arm/imx233/ssp-imx233.c
+++ b/firmware/target/arm/imx233/ssp-imx233.c
@@ -42,6 +42,8 @@ static int ssp_in_use = 0;
42static struct mutex ssp_mutex[2]; 42static struct mutex ssp_mutex[2];
43static struct semaphore ssp_sema[2]; 43static struct semaphore ssp_sema[2];
44static struct ssp_dma_command_t ssp_dma_cmd[2]; 44static struct ssp_dma_command_t ssp_dma_cmd[2];
45static uint32_t ssp_bus_width[2];
46static unsigned ssp_log_block_size[2];
45 47
46void INT_SSP(int ssp) 48void INT_SSP(int ssp)
47{ 49{
@@ -84,6 +86,7 @@ void imx233_ssp_init(void)
84 semaphore_init(&ssp_sema[1], 1, 0); 86 semaphore_init(&ssp_sema[1], 1, 0);
85 mutex_init(&ssp_mutex[0]); 87 mutex_init(&ssp_mutex[0]);
86 mutex_init(&ssp_mutex[1]); 88 mutex_init(&ssp_mutex[1]);
89 ssp_bus_width[0] = ssp_bus_width[1] = HW_SSP_CTRL0__BUS_WIDTH__ONE_BIT;
87} 90}
88 91
89void imx233_ssp_start(int ssp) 92void imx233_ssp_start(int ssp)
@@ -96,11 +99,12 @@ void imx233_ssp_start(int ssp)
96 /* If first block to start, start SSP clock */ 99 /* If first block to start, start SSP clock */
97 if(ssp_in_use == 0) 100 if(ssp_in_use == 0)
98 { 101 {
102 /** 2.3.1: the clk_ssp maximum frequency is 102.858 MHz */
99 /* fracdiv = 18 => clk_io = pll = 480Mhz 103 /* fracdiv = 18 => clk_io = pll = 480Mhz
100 * intdiv = 4 => clk_ssp = 120Mhz */ 104 * intdiv = 5 => clk_ssp = 96Mhz */
101 imx233_set_fractional_divisor(CLK_IO, 18); 105 imx233_set_fractional_divisor(CLK_IO, 18);
102 imx233_enable_clock(CLK_SSP, false); 106 imx233_enable_clock(CLK_SSP, false);
103 imx233_set_clock_divisor(CLK_SSP, 4); 107 imx233_set_clock_divisor(CLK_SSP, 5);
104 imx233_set_bypass_pll(CLK_SSP, false); /* use IO */ 108 imx233_set_bypass_pll(CLK_SSP, false); /* use IO */
105 imx233_enable_clock(CLK_SSP, true); 109 imx233_enable_clock(CLK_SSP, true);
106 } 110 }
@@ -127,18 +131,9 @@ void imx233_ssp_softreset(int ssp)
127 imx233_reset_block(&HW_SSP_CTRL0(ssp)); 131 imx233_reset_block(&HW_SSP_CTRL0(ssp));
128} 132}
129 133
130void imx233_ssp_set_timings(int ssp, int divide, int rate) 134void imx233_ssp_set_timings(int ssp, int divide, int rate, int timeout)
131{ 135{
132 __REG_CLR(HW_SSP_TIMING(ssp)) = 136 HW_SSP_TIMING(ssp) = divide << HW_SSP_TIMING__CLOCK_DIVIDE_BP | rate |
133 HW_SSP_TIMING__CLOCK_DIVIDE_BM | HW_SSP_TIMING__CLOCK_RATE_BM;
134 __REG_SET(HW_SSP_TIMING(ssp)) =
135 divide << HW_SSP_TIMING__CLOCK_DIVIDE_BP | rate;
136}
137
138void imx233_ssp_set_timeout(int ssp, int timeout)
139{
140 __REG_CLR(HW_SSP_TIMING(ssp)) = HW_SSP_TIMING__CLOCK_TIMEOUT_BM;
141 __REG_SET(HW_SSP_TIMING(ssp)) =
142 timeout << HW_SSP_TIMING__CLOCK_TIMEOUT_BP; 137 timeout << HW_SSP_TIMING__CLOCK_TIMEOUT_BP;
143} 138}
144 139
@@ -238,22 +233,43 @@ void imx233_ssp_set_mode(int ssp, unsigned mode)
238 } 233 }
239} 234}
240 235
241enum imx233_ssp_error_t imx233_ssp_sd_mmc_transfer(int ssp, uint8_t cmd, uint32_t cmd_arg, 236void imx233_ssp_set_bus_width(int ssp, unsigned width)
242 enum imx233_ssp_resp_t resp, void *buffer, int xfer_size, bool read, uint32_t *resp_ptr) 237{
238 switch(width)
239 {
240 case 1: ssp_bus_width[ssp - 1] = HW_SSP_CTRL0__BUS_WIDTH__ONE_BIT; break;
241 case 4: ssp_bus_width[ssp - 1] = HW_SSP_CTRL0__BUS_WIDTH__FOUR_BIT; break;
242 case 8: ssp_bus_width[ssp - 1] = HW_SSP_CTRL0__BUS_WIDTH__EIGHT_BIT; break;
243 }
244}
245
246void imx233_ssp_set_block_size(int ssp, unsigned log_block_size)
247{
248 ssp_log_block_size[ssp - 1] = log_block_size;
249}
250
251enum imx233_ssp_error_t imx233_ssp_sd_mmc_transfer(int ssp, uint8_t cmd,
252 uint32_t cmd_arg, enum imx233_ssp_resp_t resp, void *buffer, unsigned block_count,
253 bool wait4irq, bool read, uint32_t *resp_ptr)
243{ 254{
244 mutex_lock(&ssp_mutex[ssp - 1]); 255 mutex_lock(&ssp_mutex[ssp - 1]);
245 /* Enable all interrupts */ 256 /* Enable all interrupts */
246 imx233_enable_interrupt(INT_SRC_SSP_DMA(ssp), true); 257 imx233_enable_interrupt(INT_SRC_SSP_DMA(ssp), true);
247 imx233_dma_enable_channel_interrupt(APB_SSP(ssp), true); 258 imx233_dma_enable_channel_interrupt(APB_SSP(ssp), true);
248 /* Assume only one block so ignore block_count and block_size */ 259
249 ssp_dma_cmd[ssp - 1].cmd0 = cmd | HW_SSP_CMD0__APPEND_8CYC; 260 unsigned xfer_size = block_count * (1 << ssp_log_block_size[ssp - 1]);
261
262 ssp_dma_cmd[ssp - 1].cmd0 = cmd | HW_SSP_CMD0__APPEND_8CYC |
263 ssp_log_block_size[ssp - 1] << HW_SSP_CMD0__BLOCK_SIZE_BP |
264 (block_count - 1) << HW_SSP_CMD0__BLOCK_COUNT_BP;
250 ssp_dma_cmd[ssp - 1].cmd1 = cmd_arg; 265 ssp_dma_cmd[ssp - 1].cmd1 = cmd_arg;
251 /* setup all flags and run */ 266 /* setup all flags and run */
252 ssp_dma_cmd[ssp - 1].ctrl0 = xfer_size | HW_SSP_CTRL0__ENABLE | 267 ssp_dma_cmd[ssp - 1].ctrl0 = xfer_size | HW_SSP_CTRL0__ENABLE |
253 HW_SSP_CTRL0__IGNORE_CRC | 268 (buffer ? 0 : HW_SSP_CTRL0__IGNORE_CRC) |
254 (resp != SSP_NO_RESP ? HW_SSP_CTRL0__GET_RESP | HW_SSP_CTRL0__WAIT_FOR_IRQ : 0) | 269 (wait4irq ? HW_SSP_CTRL0__WAIT_FOR_IRQ : 0) |
270 (resp != SSP_NO_RESP ? HW_SSP_CTRL0__GET_RESP : 0) |
255 (resp == SSP_LONG_RESP ? HW_SSP_CTRL0__LONG_RESP : 0) | 271 (resp == SSP_LONG_RESP ? HW_SSP_CTRL0__LONG_RESP : 0) |
256 HW_SSP_CTRL0__BUS_WIDTH__ONE_BIT << HW_SSP_CTRL0__BUS_WIDTH_BP | 272 (ssp_bus_width[ssp - 1] << HW_SSP_CTRL0__BUS_WIDTH_BP) |
257 (buffer ? HW_SSP_CTRL0__DATA_XFER : 0) | 273 (buffer ? HW_SSP_CTRL0__DATA_XFER : 0) |
258 (read ? HW_SSP_CTRL0__READ : 0); 274 (read ? HW_SSP_CTRL0__READ : 0);
259 /* setup the dma parameters */ 275 /* setup the dma parameters */
@@ -263,10 +279,11 @@ enum imx233_ssp_error_t imx233_ssp_sd_mmc_transfer(int ssp, uint8_t cmd, uint32_
263 (buffer == NULL ? HW_APB_CHx_CMD__COMMAND__NO_XFER : 279 (buffer == NULL ? HW_APB_CHx_CMD__COMMAND__NO_XFER :
264 read ? HW_APB_CHx_CMD__COMMAND__WRITE : HW_APB_CHx_CMD__COMMAND__READ) | 280 read ? HW_APB_CHx_CMD__COMMAND__WRITE : HW_APB_CHx_CMD__COMMAND__READ) |
265 HW_APB_CHx_CMD__IRQONCMPLT | HW_APB_CHx_CMD__SEMAPHORE | 281 HW_APB_CHx_CMD__IRQONCMPLT | HW_APB_CHx_CMD__SEMAPHORE |
266 HW_APB_CHx_CMD__WAIT4ENDCMD | HW_APB_CHx_CMD__HALTONTERMINATE | 282 HW_APB_CHx_CMD__WAIT4ENDCMD |
267 (3 << HW_APB_CHx_CMD__CMDWORDS_BP) | 283 (3 << HW_APB_CHx_CMD__CMDWORDS_BP) |
268 (xfer_size << HW_APB_CHx_CMD__XFER_COUNT_BP); 284 (xfer_size << HW_APB_CHx_CMD__XFER_COUNT_BP);
269 285
286 imx233_dma_reset_channel(APB_SSP(ssp));
270 imx233_dma_start_command(APB_SSP(ssp), &ssp_dma_cmd[ssp - 1].dma); 287 imx233_dma_start_command(APB_SSP(ssp), &ssp_dma_cmd[ssp - 1].dma);
271 288
272 /* the SSP hardware already has a timeout but we never know; 1 sec is a maximum 289 /* the SSP hardware already has a timeout but we never know; 1 sec is a maximum
@@ -283,7 +300,7 @@ enum imx233_ssp_error_t imx233_ssp_sd_mmc_transfer(int ssp, uint8_t cmd, uint32_
283 else 300 else
284 ret = SSP_ERROR; 301 ret = SSP_ERROR;
285 302
286 if(ret == SSP_SUCCESS && resp_ptr != NULL) 303 if(resp_ptr != NULL)
287 { 304 {
288 if(resp != SSP_NO_RESP) 305 if(resp != SSP_NO_RESP)
289 *resp_ptr++ = HW_SSP_SDRESP0(ssp); 306 *resp_ptr++ = HW_SSP_SDRESP0(ssp);