diff options
author | Amaury Pouly <pamaury@rockbox.org> | 2011-06-30 17:31:40 +0000 |
---|---|---|
committer | Amaury Pouly <pamaury@rockbox.org> | 2011-06-30 17:31:40 +0000 |
commit | 617d1e9f6b7969aff5e45746b9c5e3cee9ce2c45 (patch) | |
tree | bf2015d298c2b6bc80189d09b73426380e08451f /firmware/target/arm/imx233/ssp-imx233.c | |
parent | 4a04c47a97517930b29f00b9d7f4d157cb69fa9b (diff) | |
download | rockbox-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.c | 61 |
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; | |||
42 | static struct mutex ssp_mutex[2]; | 42 | static struct mutex ssp_mutex[2]; |
43 | static struct semaphore ssp_sema[2]; | 43 | static struct semaphore ssp_sema[2]; |
44 | static struct ssp_dma_command_t ssp_dma_cmd[2]; | 44 | static struct ssp_dma_command_t ssp_dma_cmd[2]; |
45 | static uint32_t ssp_bus_width[2]; | ||
46 | static unsigned ssp_log_block_size[2]; | ||
45 | 47 | ||
46 | void INT_SSP(int ssp) | 48 | void 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 | ||
89 | void imx233_ssp_start(int ssp) | 92 | void 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 | ||
130 | void imx233_ssp_set_timings(int ssp, int divide, int rate) | 134 | void 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 | |||
138 | void 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 | ||
241 | enum imx233_ssp_error_t imx233_ssp_sd_mmc_transfer(int ssp, uint8_t cmd, uint32_t cmd_arg, | 236 | void 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 | |||
246 | void imx233_ssp_set_block_size(int ssp, unsigned log_block_size) | ||
247 | { | ||
248 | ssp_log_block_size[ssp - 1] = log_block_size; | ||
249 | } | ||
250 | |||
251 | enum 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); |