1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2011 by Amaury Pouly
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
26 #include "ssp-imx233.h"
27 #include "pinctrl-imx233.h"
28 #include "partitions-imx233.h"
31 * This code assumes a single eMMC internal flash
37 #error You need to configure the ssp to use
42 /** When set, this values restrict the windows of the read and writes */
43 static unsigned mmc_window_start
;
44 static unsigned mmc_window_end
;
45 static bool mmc_window_enable
= true;
46 static long mmc_last_activity
= -1;
47 static bool mmc_is_active
= false;
48 static unsigned mmc_size
= 0;
49 static int mmc_first_drive
= 0;
51 static struct mutex mmc_mutex
;
53 void imx233_mmc_disable_window(void)
55 mmc_window_enable
= false;
60 mutex_init(&mmc_mutex
);
62 imx233_ssp_start(MMC_SSP
);
63 imx233_ssp_softreset(MMC_SSP
);
64 imx233_ssp_set_mode(MMC_SSP
, HW_SSP_CTRL1__SSP_MODE__SD_MMC
);
66 /** Sansa Fuze+ has an internal eMMC 8-bit wide flash, power gate is pin PWM3
67 * and power up time is 20ms */
68 imx233_pinctrl_acquire_pin(1, 29, "emmc power");
69 imx233_set_pin_function(1, 29, PINCTRL_FUNCTION_GPIO
);
70 imx233_enable_gpio_output(1, 29, true);
71 imx233_set_gpio_output(1, 29, false);
74 imx233_ssp_setup_ssp2_sd_mmc_pins(true, 8, PINCTRL_DRIVE_8mA
);
77 * gives bitrate of 96000 / 240 / 1 = 400kHz */
78 imx233_ssp_set_timings(MMC_SSP
, 240, 0, 0xffff);
79 imx233_ssp_sd_mmc_power_up_sequence(MMC_SSP
);
80 imx233_ssp_set_bus_width(MMC_SSP
, 1);
81 imx233_ssp_set_block_size(MMC_SSP
, 9);
82 /* go to idle state */
83 int ret
= imx233_ssp_sd_mmc_transfer(MMC_SSP
, 0, 0, SSP_NO_RESP
, NULL
, 0, false, false, NULL
);
86 /* send op cond until the card respond with busy bit set; it must complete within 1sec */
87 unsigned timeout
= current_tick
+ HZ
;
91 ret
= imx233_ssp_sd_mmc_transfer(MMC_SSP
, 1, 0x40ff8000, SSP_SHORT_RESP
, NULL
, 0, false, false, &ocr
);
92 if(ret
== 0 && ocr
& (1 << 31))
94 }while(!TIME_AFTER(current_tick
, timeout
));
100 ret
= imx233_ssp_sd_mmc_transfer(MMC_SSP
, 2, 0, SSP_LONG_RESP
, NULL
, 0, false, false, cid
);
105 ret
= imx233_ssp_sd_mmc_transfer(MMC_SSP
, 3, MMC_RCA
<< 16, SSP_SHORT_RESP
, NULL
, 0, false, false, &status
);
109 ret
= imx233_ssp_sd_mmc_transfer(MMC_SSP
, 7, MMC_RCA
<< 16, SSP_SHORT_RESP
, NULL
, 0, false, false, &status
);
112 /* Check TRAN state */
113 ret
= imx233_ssp_sd_mmc_transfer(MMC_SSP
, 13, MMC_RCA
<< 16, SSP_SHORT_RESP
, NULL
, 0, false, false, &status
);
116 if(((status
>> 9) & 0xf) != 4)
118 /* Switch to 8-bit bus */
119 ret
= imx233_ssp_sd_mmc_transfer(MMC_SSP
, 6, 0x3b70200, SSP_SHORT_RESP
, NULL
, 0, true, false, &status
);
125 imx233_ssp_set_bus_width(MMC_SSP
, 8);
126 /* Switch to high speed mode */
127 ret
= imx233_ssp_sd_mmc_transfer(MMC_SSP
, 6, 0x3b90100, SSP_SHORT_RESP
, NULL
, 0, true, false, &status
);
134 * gives bitrate of 96 / 2 / 1 = 48MHz */
135 imx233_ssp_set_timings(MMC_SSP
, 2, 0, 0xffff);
137 /* read extended CSD */
139 uint8_t ext_csd
[512];
140 ret
= imx233_ssp_sd_mmc_transfer(MMC_SSP
, 8, 0, SSP_SHORT_RESP
, ext_csd
, 1, true, true, &status
);
143 uint32_t *sec_count
= (void *)&ext_csd
[212];
144 mmc_size
= *sec_count
;
147 mmc_window_start
= 0;
148 mmc_window_end
= INT_MAX
;
149 #ifdef SANSA_FUZEPLUS
150 if(imx233_partitions_is_window_enabled())
152 /* WARNING: mmc_first_drive is not set yet at this point */
154 ret
= mmc_read_sectors(IF_MD2(0,) 0, 1, mbr
);
156 panicf("cannot read MBR: %d", ret
);
157 ret
= imx233_partitions_compute_window(mbr
, &mmc_window_start
, &mmc_window_end
);
159 panicf("cannot compute partitions window: %d", ret
);
160 mmc_size
= mmc_window_end
- mmc_window_start
;
167 int mmc_num_drives(int first_drive
)
169 mmc_first_drive
= first_drive
;
173 #ifdef STORAGE_GET_INFO
174 void mmc_get_info(IF_MD2(int drive
,) struct storage_info
*info
)
176 #ifdef HAVE_MULTIDRIVE
179 info
->sector_size
= 512;
180 info
->num_sectors
= mmc_size
;
181 info
->vendor
= "Rockbox";
182 info
->product
= "Internal Storage";
183 info
->revision
= "0.00";
187 static int transfer_sectors(IF_MD2(int drive
,) unsigned long start
, int count
, void *buf
, bool read
)
191 start
+= mmc_window_start
;
192 if((start
+ count
) > mmc_window_end
)
194 /* get mutex (needed because we do multiple commands for count > 0) */
195 mutex_lock(&mmc_mutex
);
199 mmc_last_activity
= current_tick
;
200 mmc_is_active
= true;
204 int this_count
= MIN(count
, IMX233_MAX_SSP_XFER_SIZE
/ 512);
207 ret
= imx233_ssp_sd_mmc_transfer(MMC_SSP
, read
? 17 : 24, start
,
208 SSP_SHORT_RESP
, buf
, this_count
, false, read
, &resp
);
212 ret
= imx233_ssp_sd_mmc_transfer(MMC_SSP
, 23, this_count
, SSP_SHORT_RESP
, NULL
,
213 0, false, false, &resp
);
215 ret
= imx233_ssp_sd_mmc_transfer(MMC_SSP
, read
? 18 : 25, start
,
216 SSP_SHORT_RESP
, buf
, this_count
, false, read
, &resp
);
220 buf
+= this_count
* 512;
221 }while(count
!= 0 && ret
== SSP_SUCCESS
);
223 mmc_is_active
= false;
225 mutex_unlock(&mmc_mutex
);
230 int mmc_read_sectors(IF_MD2(int drive
,) unsigned long start
, int count
, void *buf
)
232 return transfer_sectors(IF_MD2(drive
,) start
, count
, buf
, true);
235 int mmc_write_sectors(IF_MD2(int drive
,) unsigned long start
, int count
, const void* buf
)
237 return transfer_sectors(IF_MD2(drive
,) start
, count
, (void *)buf
, false);
240 bool mmc_present(IF_MD(int drive
))
246 bool mmc_removable(IF_MD(int drive
))
256 void mmc_sleepnow(void)
260 bool mmc_disk_is_active(void)
262 return mmc_is_active
;
265 bool mmc_usb_active(void)
267 return mmc_disk_is_active();
270 int mmc_soft_reset(void)
284 void mmc_spindown(int seconds
)
289 long mmc_last_disk_activity(void)
291 return mmc_last_activity
;
294 int mmc_spinup_time(void)
299 void mmc_enable(bool enable
)