1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143 |
- /* Copyright (C) 2013 by John Cronin <jncronin@tysos.org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- /* Provides an interface to the EMMC controller and commands for interacting
- * with an sd card */
- /* References:
- *
- * PLSS - SD Group Physical Layer Simplified Specification ver 3.00
- * HCSS - SD Group Host Controller Simplified Specification ver 3.00
- *
- * Broadcom BCM2835 Peripherals Guide
- */
- #include <stdint.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <assert.h>
- #include "mmio.h"
- #include "block.h"
- #include "timer.h"
- #include "util.h"
- //#define EMMC_DEBUG
- // Configuration options
- // Enable 1.8V support
- #define SD_1_8V_SUPPORT
- // Enable 4-bit support
- #define SD_4BIT_DATA
- // SD Clock Frequencies (in Hz)
- #define SD_CLOCK_ID 400000
- #define SD_CLOCK_NORMAL 25000000
- #define SD_CLOCK_HIGH 50000000
- #define SD_CLOCK_100 100000000
- #define SD_CLOCK_208 208000000
- // Enable SDXC maximum performance mode
- // Requires 150 mA power so disabled on the RPi for now
- //#define SDXC_MAXIMUM_PERFORMANCE
- // Enable SDMA support
- //#define SDMA_SUPPORT
- // SDMA buffer address
- #define SDMA_BUFFER 0x6000
- #define SDMA_BUFFER_PA (SDMA_BUFFER + 0xC0000000)
- // Enable card interrupts
- //#define SD_CARD_INTERRUPTS
- // Enable EXPERIMENTAL (and possibly DANGEROUS) SD write support
- #define SD_WRITE_SUPPORT
- // The particular SDHCI implementation
- #define SDHCI_IMPLEMENTATION_GENERIC 0
- #define SDHCI_IMPLEMENTATION_BCM_2708 1
- #define SDHCI_IMPLEMENTATION SDHCI_IMPLEMENTATION_BCM_2708
- static char driver_name[] = "emmc";
- static char device_name[] = "emmc0"; // We use a single device name as there is only
- // one card slot in the RPi
- static uint32_t hci_ver = 0;
- static uint32_t capabilities_0 = 0;
- static uint32_t capabilities_1 = 0;
- struct sd_scr
- {
- uint32_t scr[2];
- uint32_t sd_bus_widths;
- int sd_version;
- };
- struct emmc_block_dev
- {
- struct block_device bd;
- uint32_t card_supports_sdhc;
- uint32_t card_supports_18v;
- uint32_t card_ocr;
- uint32_t card_rca;
- uint32_t last_interrupt;
- uint32_t last_error;
- struct sd_scr *scr;
- int failed_voltage_switch;
- uint32_t last_cmd_reg;
- uint32_t last_cmd;
- uint32_t last_cmd_success;
- uint32_t last_r0;
- uint32_t last_r1;
- uint32_t last_r2;
- uint32_t last_r3;
- void *buf;
- int blocks_to_transfer;
- size_t block_size;
- int use_sdma;
- int card_removal;
- uint32_t base_clock;
- };
- #define EMMC_BASE 0x3f300000
- #define EMMC_ARG2 0
- #define EMMC_BLKSIZECNT 4
- #define EMMC_ARG1 8
- #define EMMC_CMDTM 0xC
- #define EMMC_RESP0 0x10
- #define EMMC_RESP1 0x14
- #define EMMC_RESP2 0x18
- #define EMMC_RESP3 0x1C
- #define EMMC_DATA 0x20
- #define EMMC_STATUS 0x24
- #define EMMC_CONTROL0 0x28
- #define EMMC_CONTROL1 0x2C
- #define EMMC_INTERRUPT 0x30
- #define EMMC_IRPT_MASK 0x34
- #define EMMC_IRPT_EN 0x38
- #define EMMC_CONTROL2 0x3C
- #define EMMC_CAPABILITIES_0 0x40
- #define EMMC_CAPABILITIES_1 0x44
- #define EMMC_FORCE_IRPT 0x50
- #define EMMC_BOOT_TIMEOUT 0x70
- #define EMMC_DBG_SEL 0x74
- #define EMMC_EXRDFIFO_CFG 0x80
- #define EMMC_EXRDFIFO_EN 0x84
- #define EMMC_TUNE_STEP 0x88
- #define EMMC_TUNE_STEPS_STD 0x8C
- #define EMMC_TUNE_STEPS_DDR 0x90
- #define EMMC_SPI_INT_SPT 0xF0
- #define EMMC_SLOTISR_VER 0xFC
- #define SD_CMD_INDEX(a) ((a) << 24)
- #define SD_CMD_TYPE_NORMAL 0x0
- #define SD_CMD_TYPE_SUSPEND (1 << 22)
- #define SD_CMD_TYPE_RESUME (2 << 22)
- #define SD_CMD_TYPE_ABORT (3 << 22)
- #define SD_CMD_TYPE_MASK (3 << 22)
- #define SD_CMD_ISDATA (1 << 21)
- #define SD_CMD_IXCHK_EN (1 << 20)
- #define SD_CMD_CRCCHK_EN (1 << 19)
- #define SD_CMD_RSPNS_TYPE_NONE 0 // For no response
- #define SD_CMD_RSPNS_TYPE_136 (1 << 16) // For response R2 (with CRC), R3,4 (no CRC)
- #define SD_CMD_RSPNS_TYPE_48 (2 << 16) // For responses R1, R5, R6, R7 (with CRC)
- #define SD_CMD_RSPNS_TYPE_48B (3 << 16) // For responses R1b, R5b (with CRC)
- #define SD_CMD_RSPNS_TYPE_MASK (3 << 16)
- #define SD_CMD_MULTI_BLOCK (1 << 5)
- #define SD_CMD_DAT_DIR_HC 0
- #define SD_CMD_DAT_DIR_CH (1 << 4)
- #define SD_CMD_AUTO_CMD_EN_NONE 0
- #define SD_CMD_AUTO_CMD_EN_CMD12 (1 << 2)
- #define SD_CMD_AUTO_CMD_EN_CMD23 (2 << 2)
- #define SD_CMD_BLKCNT_EN (1 << 1)
- #define SD_CMD_DMA 1
- #define SD_ERR_CMD_TIMEOUT 0
- #define SD_ERR_CMD_CRC 1
- #define SD_ERR_CMD_END_BIT 2
- #define SD_ERR_CMD_INDEX 3
- #define SD_ERR_DATA_TIMEOUT 4
- #define SD_ERR_DATA_CRC 5
- #define SD_ERR_DATA_END_BIT 6
- #define SD_ERR_CURRENT_LIMIT 7
- #define SD_ERR_AUTO_CMD12 8
- #define SD_ERR_ADMA 9
- #define SD_ERR_TUNING 10
- #define SD_ERR_RSVD 11
- #define SD_ERR_MASK_CMD_TIMEOUT (1 << (16 + SD_ERR_CMD_TIMEOUT))
- #define SD_ERR_MASK_CMD_CRC (1 << (16 + SD_ERR_CMD_CRC))
- #define SD_ERR_MASK_CMD_END_BIT (1 << (16 + SD_ERR_CMD_END_BIT))
- #define SD_ERR_MASK_CMD_INDEX (1 << (16 + SD_ERR_CMD_INDEX))
- #define SD_ERR_MASK_DATA_TIMEOUT (1 << (16 + SD_ERR_CMD_TIMEOUT))
- #define SD_ERR_MASK_DATA_CRC (1 << (16 + SD_ERR_CMD_CRC))
- #define SD_ERR_MASK_DATA_END_BIT (1 << (16 + SD_ERR_CMD_END_BIT))
- #define SD_ERR_MASK_CURRENT_LIMIT (1 << (16 + SD_ERR_CMD_CURRENT_LIMIT))
- #define SD_ERR_MASK_AUTO_CMD12 (1 << (16 + SD_ERR_CMD_AUTO_CMD12))
- #define SD_ERR_MASK_ADMA (1 << (16 + SD_ERR_CMD_ADMA))
- #define SD_ERR_MASK_TUNING (1 << (16 + SD_ERR_CMD_TUNING))
- #define SD_COMMAND_COMPLETE 1
- #define SD_TRANSFER_COMPLETE (1 << 1)
- #define SD_BLOCK_GAP_EVENT (1 << 2)
- #define SD_DMA_INTERRUPT (1 << 3)
- #define SD_BUFFER_WRITE_READY (1 << 4)
- #define SD_BUFFER_READ_READY (1 << 5)
- #define SD_CARD_INSERTION (1 << 6)
- #define SD_CARD_REMOVAL (1 << 7)
- #define SD_CARD_INTERRUPT (1 << 8)
- #define SD_RESP_NONE SD_CMD_RSPNS_TYPE_NONE
- #define SD_RESP_R1 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
- #define SD_RESP_R1b (SD_CMD_RSPNS_TYPE_48B | SD_CMD_CRCCHK_EN)
- #define SD_RESP_R2 (SD_CMD_RSPNS_TYPE_136 | SD_CMD_CRCCHK_EN)
- #define SD_RESP_R3 SD_CMD_RSPNS_TYPE_48
- #define SD_RESP_R4 SD_CMD_RSPNS_TYPE_136
- #define SD_RESP_R5 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
- #define SD_RESP_R5b (SD_CMD_RSPNS_TYPE_48B | SD_CMD_CRCCHK_EN)
- #define SD_RESP_R6 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
- #define SD_RESP_R7 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
- #define SD_DATA_READ (SD_CMD_ISDATA | SD_CMD_DAT_DIR_CH)
- #define SD_DATA_WRITE (SD_CMD_ISDATA | SD_CMD_DAT_DIR_HC)
- #define SD_CMD_RESERVED(a) 0xffffffff
- #define SUCCESS(a) (a->last_cmd_success)
- #define FAIL(a) (a->last_cmd_success == 0)
- #define TIMEOUT(a) (FAIL(a) && (a->last_error == 0))
- #define CMD_TIMEOUT(a) (FAIL(a) && (a->last_error & (1 << 16)))
- #define CMD_CRC(a) (FAIL(a) && (a->last_error & (1 << 17)))
- #define CMD_END_BIT(a) (FAIL(a) && (a->last_error & (1 << 18)))
- #define CMD_INDEX(a) (FAIL(a) && (a->last_error & (1 << 19)))
- #define DATA_TIMEOUT(a) (FAIL(a) && (a->last_error & (1 << 20)))
- #define DATA_CRC(a) (FAIL(a) && (a->last_error & (1 << 21)))
- #define DATA_END_BIT(a) (FAIL(a) && (a->last_error & (1 << 22)))
- #define CURRENT_LIMIT(a) (FAIL(a) && (a->last_error & (1 << 23)))
- #define ACMD12_ERROR(a) (FAIL(a) && (a->last_error & (1 << 24)))
- #define ADMA_ERROR(a) (FAIL(a) && (a->last_error & (1 << 25)))
- #define TUNING_ERROR(a) (FAIL(a) && (a->last_error & (1 << 26)))
- #define SD_VER_UNKNOWN 0
- #define SD_VER_1 1
- #define SD_VER_1_1 2
- #define SD_VER_2 3
- #define SD_VER_3 4
- #define SD_VER_4 5
- static char *sd_versions[] = { "unknown", "1.0 and 1.01", "1.10",
- "2.00", "3.0x", "4.xx" };
- #ifdef EMMC_DEBUG
- static char *err_irpts[] = { "CMD_TIMEOUT", "CMD_CRC", "CMD_END_BIT", "CMD_INDEX",
- "DATA_TIMEOUT", "DATA_CRC", "DATA_END_BIT", "CURRENT_LIMIT",
- "AUTO_CMD12", "ADMA", "TUNING", "RSVD" };
- #endif
- int sd_read(struct block_device *, uint8_t *, size_t buf_size, uint32_t);
- int sd_write(struct block_device *, uint8_t *, size_t buf_size, uint32_t);
- static uint32_t sd_commands[] = {
- SD_CMD_INDEX(0),
- SD_CMD_RESERVED(1),
- SD_CMD_INDEX(2) | SD_RESP_R2,
- SD_CMD_INDEX(3) | SD_RESP_R6,
- SD_CMD_INDEX(4),
- SD_CMD_INDEX(5) | SD_RESP_R4,
- SD_CMD_INDEX(6) | SD_RESP_R1,
- SD_CMD_INDEX(7) | SD_RESP_R1b,
- SD_CMD_INDEX(8) | SD_RESP_R7,
- SD_CMD_INDEX(9) | SD_RESP_R2,
- SD_CMD_INDEX(10) | SD_RESP_R2,
- SD_CMD_INDEX(11) | SD_RESP_R1,
- SD_CMD_INDEX(12) | SD_RESP_R1b | SD_CMD_TYPE_ABORT,
- SD_CMD_INDEX(13) | SD_RESP_R1,
- SD_CMD_RESERVED(14),
- SD_CMD_INDEX(15),
- SD_CMD_INDEX(16) | SD_RESP_R1,
- SD_CMD_INDEX(17) | SD_RESP_R1 | SD_DATA_READ,
- SD_CMD_INDEX(18) | SD_RESP_R1 | SD_DATA_READ | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
- SD_CMD_INDEX(19) | SD_RESP_R1 | SD_DATA_READ,
- SD_CMD_INDEX(20) | SD_RESP_R1b,
- SD_CMD_RESERVED(21),
- SD_CMD_RESERVED(22),
- SD_CMD_INDEX(23) | SD_RESP_R1,
- SD_CMD_INDEX(24) | SD_RESP_R1 | SD_DATA_WRITE,
- SD_CMD_INDEX(25) | SD_RESP_R1 | SD_DATA_WRITE | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
- SD_CMD_RESERVED(26),
- SD_CMD_INDEX(27) | SD_RESP_R1 | SD_DATA_WRITE,
- SD_CMD_INDEX(28) | SD_RESP_R1b,
- SD_CMD_INDEX(29) | SD_RESP_R1b,
- SD_CMD_INDEX(30) | SD_RESP_R1 | SD_DATA_READ,
- SD_CMD_RESERVED(31),
- SD_CMD_INDEX(32) | SD_RESP_R1,
- SD_CMD_INDEX(33) | SD_RESP_R1,
- SD_CMD_RESERVED(34),
- SD_CMD_RESERVED(35),
- SD_CMD_RESERVED(36),
- SD_CMD_RESERVED(37),
- SD_CMD_INDEX(38) | SD_RESP_R1b,
- SD_CMD_RESERVED(39),
- SD_CMD_RESERVED(40),
- SD_CMD_RESERVED(41),
- SD_CMD_RESERVED(42) | SD_RESP_R1,
- SD_CMD_RESERVED(43),
- SD_CMD_RESERVED(44),
- SD_CMD_RESERVED(45),
- SD_CMD_RESERVED(46),
- SD_CMD_RESERVED(47),
- SD_CMD_RESERVED(48),
- SD_CMD_RESERVED(49),
- SD_CMD_RESERVED(50),
- SD_CMD_RESERVED(51),
- SD_CMD_RESERVED(52),
- SD_CMD_RESERVED(53),
- SD_CMD_RESERVED(54),
- SD_CMD_INDEX(55) | SD_RESP_R1,
- SD_CMD_INDEX(56) | SD_RESP_R1 | SD_CMD_ISDATA,
- SD_CMD_RESERVED(57),
- SD_CMD_RESERVED(58),
- SD_CMD_RESERVED(59),
- SD_CMD_RESERVED(60),
- SD_CMD_RESERVED(61),
- SD_CMD_RESERVED(62),
- SD_CMD_RESERVED(63)
- };
- static uint32_t sd_acommands[] = {
- SD_CMD_RESERVED(0),
- SD_CMD_RESERVED(1),
- SD_CMD_RESERVED(2),
- SD_CMD_RESERVED(3),
- SD_CMD_RESERVED(4),
- SD_CMD_RESERVED(5),
- SD_CMD_INDEX(6) | SD_RESP_R1,
- SD_CMD_RESERVED(7),
- SD_CMD_RESERVED(8),
- SD_CMD_RESERVED(9),
- SD_CMD_RESERVED(10),
- SD_CMD_RESERVED(11),
- SD_CMD_RESERVED(12),
- SD_CMD_INDEX(13) | SD_RESP_R1,
- SD_CMD_RESERVED(14),
- SD_CMD_RESERVED(15),
- SD_CMD_RESERVED(16),
- SD_CMD_RESERVED(17),
- SD_CMD_RESERVED(18),
- SD_CMD_RESERVED(19),
- SD_CMD_RESERVED(20),
- SD_CMD_RESERVED(21),
- SD_CMD_INDEX(22) | SD_RESP_R1 | SD_DATA_READ,
- SD_CMD_INDEX(23) | SD_RESP_R1,
- SD_CMD_RESERVED(24),
- SD_CMD_RESERVED(25),
- SD_CMD_RESERVED(26),
- SD_CMD_RESERVED(27),
- SD_CMD_RESERVED(28),
- SD_CMD_RESERVED(29),
- SD_CMD_RESERVED(30),
- SD_CMD_RESERVED(31),
- SD_CMD_RESERVED(32),
- SD_CMD_RESERVED(33),
- SD_CMD_RESERVED(34),
- SD_CMD_RESERVED(35),
- SD_CMD_RESERVED(36),
- SD_CMD_RESERVED(37),
- SD_CMD_RESERVED(38),
- SD_CMD_RESERVED(39),
- SD_CMD_RESERVED(40),
- SD_CMD_INDEX(41) | SD_RESP_R3,
- SD_CMD_INDEX(42) | SD_RESP_R1,
- SD_CMD_RESERVED(43),
- SD_CMD_RESERVED(44),
- SD_CMD_RESERVED(45),
- SD_CMD_RESERVED(46),
- SD_CMD_RESERVED(47),
- SD_CMD_RESERVED(48),
- SD_CMD_RESERVED(49),
- SD_CMD_RESERVED(50),
- SD_CMD_INDEX(51) | SD_RESP_R1 | SD_DATA_READ,
- SD_CMD_RESERVED(52),
- SD_CMD_RESERVED(53),
- SD_CMD_RESERVED(54),
- SD_CMD_RESERVED(55),
- SD_CMD_RESERVED(56),
- SD_CMD_RESERVED(57),
- SD_CMD_RESERVED(58),
- SD_CMD_RESERVED(59),
- SD_CMD_RESERVED(60),
- SD_CMD_RESERVED(61),
- SD_CMD_RESERVED(62),
- SD_CMD_RESERVED(63)
- };
- // The actual command indices
- #define GO_IDLE_STATE 0
- #define ALL_SEND_CID 2
- #define SEND_RELATIVE_ADDR 3
- #define SET_DSR 4
- #define IO_SET_OP_COND 5
- #define SWITCH_FUNC 6
- #define SELECT_CARD 7
- #define DESELECT_CARD 7
- #define SELECT_DESELECT_CARD 7
- #define SEND_IF_COND 8
- #define SEND_CSD 9
- #define SEND_CID 10
- #define VOLTAGE_SWITCH 11
- #define STOP_TRANSMISSION 12
- #define SEND_STATUS 13
- #define GO_INACTIVE_STATE 15
- #define SET_BLOCKLEN 16
- #define READ_SINGLE_BLOCK 17
- #define READ_MULTIPLE_BLOCK 18
- #define SEND_TUNING_BLOCK 19
- #define SPEED_CLASS_CONTROL 20
- #define SET_BLOCK_COUNT 23
- #define WRITE_BLOCK 24
- #define WRITE_MULTIPLE_BLOCK 25
- #define PROGRAM_CSD 27
- #define SET_WRITE_PROT 28
- #define CLR_WRITE_PROT 29
- #define SEND_WRITE_PROT 30
- #define ERASE_WR_BLK_START 32
- #define ERASE_WR_BLK_END 33
- #define ERASE 38
- #define LOCK_UNLOCK 42
- #define APP_CMD 55
- #define GEN_CMD 56
- #define IS_APP_CMD 0x80000000
- #define ACMD(a) (a | IS_APP_CMD)
- #define SET_BUS_WIDTH (6 | IS_APP_CMD)
- #define SD_STATUS (13 | IS_APP_CMD)
- #define SEND_NUM_WR_BLOCKS (22 | IS_APP_CMD)
- #define SET_WR_BLK_ERASE_COUNT (23 | IS_APP_CMD)
- #define SD_SEND_OP_COND (41 | IS_APP_CMD)
- #define SET_CLR_CARD_DETECT (42 | IS_APP_CMD)
- #define SEND_SCR (51 | IS_APP_CMD)
- #define SD_RESET_CMD (1 << 25)
- #define SD_RESET_DAT (1 << 26)
- #define SD_RESET_ALL (1 << 24)
- #define SD_GET_CLOCK_DIVIDER_FAIL 0xffffffff
- // Get the current base clock rate in Hz
- #if SDHCI_IMPLEMENTATION == SDHCI_IMPLEMENTATION_BCM_2708
- #include "mbox.h"
- #endif
- static void sd_power_off()
- {
- /* Power off the SD card */
- uint32_t control0 = mmio_read(EMMC_BASE + EMMC_CONTROL0);
- control0 &= ~(1 << 8); // Set SD Bus Power bit off in Power Control Register
- mmio_write(EMMC_BASE + EMMC_CONTROL0, control0);
- }
- static volatile uint32_t mailbuffer[8] __attribute__ ((aligned (16)));
- static volatile uint32_t mb_addr[8] __attribute__ ((aligned (16)));
- static uint32_t sd_get_base_clock_hz()
- {
- uint32_t base_clock;
- #if SDHCI_IMPLEMENTATION == SDHCI_IMPLEMENTATION_GENERIC
- capabilities_0 = mmio_read(EMMC_BASE + EMMC_CAPABILITIES_0);
- base_clock = ((capabilities_0 >> 8) & 0xff) * 1000000;
- #elif SDHCI_IMPLEMENTATION == SDHCI_IMPLEMENTATION_BCM_2708
- //uint32_t mb_addr = 0x40007000; // 0x7000 in L2 cache coherent mode
-
- //volatile uint32_t *mailbuffer = (uint32_t *)mb_addr;
- /* Get the base clock rate */
- // set up the buffer
- mailbuffer[0] = 8 * 4; // size of this message
- mailbuffer[1] = 0; // this is a request
- // next comes the first tag
- mailbuffer[2] = 0x00030002; // get clock rate tag
- mailbuffer[3] = 0x8; // value buffer size
- mailbuffer[4] = 0x4; // is a request, value length = 4
- mailbuffer[5] = 0x1; // clock id + space to return clock id
- mailbuffer[6] = 0; // space to return rate (in Hz)
- // closing tag
- mailbuffer[7] = 0;
- // send the message
- mbox_write(MBOX_PROP, (uint32_t)mailbuffer);
- // read the response
- mbox_read(MBOX_PROP);
- if(mailbuffer[1] != MBOX_SUCCESS)
- {
- printf("EMMC: property mailbox did not return a valid response.\r\n");
- return 0;
- }
- if(mailbuffer[5] != 0x1)
- {
- printf("EMMC: property mailbox did not return a valid clock id.\r\n");
- return 0;
- }
- base_clock = mailbuffer[6];
- #else
- printf("EMMC: get_base_clock_hz() is not implemented for this "
- "architecture.\r\n");
- return 0;
- #endif
- #ifdef EMMC_DEBUG
- printf("EMMC: base clock rate is %i Hz\r\n", base_clock);
- #endif
- return base_clock;
- }
- #if SDHCI_IMPLEMENTATION == SDHCI_IMPLEMENTATION_BCM_2708
- static int bcm_2708_power_off()
- {
- //uint32_t mb_addr = 0x40007000; // 0x7000 in L2 cache coherent mode
- volatile uint32_t *mailbuffer = (uint32_t *)mb_addr;
- /* Power off the SD card */
- // set up the buffer
- mailbuffer[0] = 8 * 4; // size of this message
- mailbuffer[1] = 0; // this is a request
- // next comes the first tag
- mailbuffer[2] = 0x00028001; // set power state tag
- mailbuffer[3] = 0x8; // value buffer size
- mailbuffer[4] = 0x8; // is a request, value length = 8
- mailbuffer[5] = 0x0; // device id and device id also returned here
- mailbuffer[6] = 0x2; // set power off, wait for stable and returns state
- // closing tag
- mailbuffer[7] = 0;
- // send the message
- mbox_write(MBOX_PROP, (uint32_t)mb_addr);
- // read the response
- mbox_read(MBOX_PROP);
- if(mailbuffer[1] != MBOX_SUCCESS)
- {
- printf("EMMC: bcm_2708_power_off(): property mailbox did not return a valid response.\r\n");
- return -1;
- }
- if(mailbuffer[5] != 0x0)
- {
- printf("EMMC: property mailbox did not return a valid device id.\r\n");
- return -1;
- }
- if((mailbuffer[6] & 0x3) != 0)
- {
- #ifdef EMMC_DEBUG
- printf("EMMC: bcm_2708_power_off(): device did not power off successfully (%08x).\r\n", mailbuffer[6]);
- #endif
- return 1;
- }
- return 0;
- }
- static int bcm_2708_power_on()
- {
- //uint32_t mb_addr = 0x40007000; // 0x7000 in L2 cache coherent mode
- //volatile uint32_t mb_addr[8] __attribute__ ((aligned (16)));
-
- volatile uint32_t *mailbuffer = (uint32_t *)mb_addr;
- /* Power on the SD card */
- // set up the buffer
- mailbuffer[0] = 8 * 4; // size of this message
- mailbuffer[1] = 0; // this is a request
- // next comes the first tag
- mailbuffer[2] = 0x00028001; // set power state tag
- mailbuffer[3] = 0x8; // value buffer size
- mailbuffer[4] = 0x8; // is a request, value length = 8
- mailbuffer[5] = 0x0; // device id and device id also returned here
- mailbuffer[6] = 0x3; // set power off, wait for stable and returns state
- // closing tag
- mailbuffer[7] = 0;
- // send the message
- mbox_write(MBOX_PROP, (uint32_t)mb_addr);
- // read the response
- mbox_read(MBOX_PROP);
- if(mailbuffer[1] != MBOX_SUCCESS)
- {
- printf("EMMC: bcm_2708_power_on(): property mailbox did not return a valid response.\r\n");
- return -1;
- }
- if(mailbuffer[5] != 0x0)
- {
- printf("EMMC: property mailbox did not return a valid device id.\r\n");
- return -1;
- }
- if((mailbuffer[6] & 0x3) != 1)
- {
- #ifdef EMMC_DEBUG
- printf("EMMC: bcm_2708_power_on(): device did not power on successfully (%08x).\r\n", mailbuffer[6]);
- #endif
- return 1;
- }
- return 0;
- }
- static int bcm_2708_power_cycle()
- {
- if(bcm_2708_power_off() < 0)
- return -1;
- usleep(5000);
- return bcm_2708_power_on();
- }
- #endif
- // Set the clock dividers to generate a target value
- static uint32_t sd_get_clock_divider(uint32_t base_clock, uint32_t target_rate)
- {
- // TODO: implement use of preset value registers
- uint32_t targetted_divisor = 0;
- if(target_rate > base_clock)
- targetted_divisor = 1;
- else
- {
- targetted_divisor = base_clock / target_rate;
- uint32_t mod = base_clock % target_rate;
- if(mod)
- targetted_divisor--;
- }
- // Decide on the clock mode to use
- // Currently only 10-bit divided clock mode is supported
- if(hci_ver >= 2)
- {
- // HCI version 3 or greater supports 10-bit divided clock mode
- // This requires a power-of-two divider
- // Find the first bit set
- int divisor = -1;
- for(int first_bit = 31; first_bit >= 0; first_bit--)
- {
- uint32_t bit_test = (1 << first_bit);
- if(targetted_divisor & bit_test)
- {
- divisor = first_bit;
- targetted_divisor &= ~bit_test;
- if(targetted_divisor)
- {
- // The divisor is not a power-of-two, increase it
- divisor++;
- }
- break;
- }
- }
- if(divisor == -1)
- divisor = 31;
- if(divisor >= 32)
- divisor = 31;
- if(divisor != 0)
- divisor = (1 << (divisor - 1));
- if(divisor >= 0x400)
- divisor = 0x3ff;
- uint32_t freq_select = divisor & 0xff;
- uint32_t upper_bits = (divisor >> 8) & 0x3;
- uint32_t ret = (freq_select << 8) | (upper_bits << 6) | (0 << 5);
- #ifdef EMMC_DEBUG
- int denominator = 1;
- if(divisor != 0)
- denominator = divisor * 2;
- int actual_clock = base_clock / denominator;
- printf("EMMC: base_clock: %i, target_rate: %i, divisor: %08x, "
- "actual_clock: %i, ret: %08x\r\n", base_clock, target_rate,
- divisor, actual_clock, ret);
- #endif
- return ret;
- }
- else
- {
- printf("EMMC: unsupported host version\r\n");
- return SD_GET_CLOCK_DIVIDER_FAIL;
- }
- }
- // Switch the clock rate whilst running
- static int sd_switch_clock_rate(uint32_t base_clock, uint32_t target_rate)
- {
- // Decide on an appropriate divider
- uint32_t divider = sd_get_clock_divider(base_clock, target_rate);
- if(divider == SD_GET_CLOCK_DIVIDER_FAIL)
- {
- printf("EMMC: couldn't get a valid divider for target rate %i Hz\r\n",
- target_rate);
- return -1;
- }
- // Wait for the command inhibit (CMD and DAT) bits to clear
- while(mmio_read(EMMC_BASE + EMMC_STATUS) & 0x3)
- usleep(1000);
- // Set the SD clock off
- uint32_t control1 = mmio_read(EMMC_BASE + EMMC_CONTROL1);
- control1 &= ~(1 << 2);
- mmio_write(EMMC_BASE + EMMC_CONTROL1, control1);
- usleep(2000);
- // Write the new divider
- control1 &= ~0xffe0; // Clear old setting + clock generator select
- control1 |= divider;
- mmio_write(EMMC_BASE + EMMC_CONTROL1, control1);
- usleep(2000);
- // Enable the SD clock
- control1 |= (1 << 2);
- mmio_write(EMMC_BASE + EMMC_CONTROL1, control1);
- usleep(2000);
- #ifdef EMMC_DEBUG
- printf("EMMC: successfully set clock rate to %i Hz\r\n", target_rate);
- #endif
- return 0;
- }
- // Reset the CMD line
- static int sd_reset_cmd()
- {
- uint32_t control1 = mmio_read(EMMC_BASE + EMMC_CONTROL1);
- control1 |= SD_RESET_CMD;
- mmio_write(EMMC_BASE + EMMC_CONTROL1, control1);
- TIMEOUT_WAIT((mmio_read(EMMC_BASE + EMMC_CONTROL1) & SD_RESET_CMD) == 0, 1000000);
- if((mmio_read(EMMC_BASE + EMMC_CONTROL1) & SD_RESET_CMD) != 0)
- {
- printf("EMMC: CMD line did not reset properly\r\n");
- return -1;
- }
- return 0;
- }
- // Reset the CMD line
- static int sd_reset_dat()
- {
- uint32_t control1 = mmio_read(EMMC_BASE + EMMC_CONTROL1);
- control1 |= SD_RESET_DAT;
- mmio_write(EMMC_BASE + EMMC_CONTROL1, control1);
- TIMEOUT_WAIT((mmio_read(EMMC_BASE + EMMC_CONTROL1) & SD_RESET_DAT) == 0, 1000000);
- if((mmio_read(EMMC_BASE + EMMC_CONTROL1) & SD_RESET_DAT) != 0)
- {
- printf("EMMC: DAT line did not reset properly\r\n");
- return -1;
- }
- return 0;
- }
- static void sd_issue_command_int(struct emmc_block_dev *dev, uint32_t cmd_reg, uint32_t argument, useconds_t timeout)
- {
- dev->last_cmd_reg = cmd_reg;
- dev->last_cmd_success = 0;
- // This is as per HCSS 3.7.1.1/3.7.2.2
- // Check Command Inhibit
- while(mmio_read(EMMC_BASE + EMMC_STATUS) & 0x1)
- usleep(1000);
- // Is the command with busy?
- if((cmd_reg & SD_CMD_RSPNS_TYPE_MASK) == SD_CMD_RSPNS_TYPE_48B)
- {
- // With busy
- // Is is an abort command?
- if((cmd_reg & SD_CMD_TYPE_MASK) != SD_CMD_TYPE_ABORT)
- {
- // Not an abort command
- // Wait for the data line to be free
- while(mmio_read(EMMC_BASE + EMMC_STATUS) & 0x2)
- usleep(1000);
- }
- }
- // Is this a DMA transfer?
- int is_sdma = 0;
- if((cmd_reg & SD_CMD_ISDATA) && (dev->use_sdma))
- {
- #ifdef EMMC_DEBUG
- printf("SD: performing SDMA transfer, current INTERRUPT: %08x\r\n",
- mmio_read(EMMC_BASE + EMMC_INTERRUPT));
- #endif
- is_sdma = 1;
- }
- if(is_sdma)
- {
- // Set system address register (ARGUMENT2 in RPi)
- // We need to define a 4 kiB aligned buffer to use here
- // Then convert its virtual address to a bus address
- mmio_write(EMMC_BASE + EMMC_ARG2, SDMA_BUFFER_PA);
- }
- // Set block size and block count
- // For now, block size = 512 bytes, block count = 1,
- // host SDMA buffer boundary = 4 kiB
- if(dev->blocks_to_transfer > 0xffff)
- {
- printf("SD: blocks_to_transfer too great (%i)\r\n",
- dev->blocks_to_transfer);
- dev->last_cmd_success = 0;
- return;
- }
- uint32_t blksizecnt = dev->block_size | (dev->blocks_to_transfer << 16);
- mmio_write(EMMC_BASE + EMMC_BLKSIZECNT, blksizecnt);
- // Set argument 1 reg
- mmio_write(EMMC_BASE + EMMC_ARG1, argument);
- if(is_sdma)
- {
- // Set Transfer mode register
- cmd_reg |= SD_CMD_DMA;
- }
- // Set command reg
- mmio_write(EMMC_BASE + EMMC_CMDTM, cmd_reg);
- usleep(2000);
- // Wait for command complete interrupt
- TIMEOUT_WAIT(mmio_read(EMMC_BASE + EMMC_INTERRUPT) & 0x8001, timeout);
- uint32_t irpts = mmio_read(EMMC_BASE + EMMC_INTERRUPT);
- // Clear command complete status
- mmio_write(EMMC_BASE + EMMC_INTERRUPT, 0xffff0001);
- // Test for errors
- if((irpts & 0xffff0001) != 0x1)
- {
- #ifdef EMMC_DEBUG
- printf("SD: error occured whilst waiting for command complete interrupt\r\n");
- #endif
- dev->last_error = irpts & 0xffff0000;
- dev->last_interrupt = irpts;
- return;
- }
- usleep(2000);
- // Get response data
- switch(cmd_reg & SD_CMD_RSPNS_TYPE_MASK)
- {
- case SD_CMD_RSPNS_TYPE_48:
- case SD_CMD_RSPNS_TYPE_48B:
- dev->last_r0 = mmio_read(EMMC_BASE + EMMC_RESP0);
- break;
- case SD_CMD_RSPNS_TYPE_136:
- dev->last_r0 = mmio_read(EMMC_BASE + EMMC_RESP0);
- dev->last_r1 = mmio_read(EMMC_BASE + EMMC_RESP1);
- dev->last_r2 = mmio_read(EMMC_BASE + EMMC_RESP2);
- dev->last_r3 = mmio_read(EMMC_BASE + EMMC_RESP3);
- break;
- }
- // If with data, wait for the appropriate interrupt
- if((cmd_reg & SD_CMD_ISDATA) && (is_sdma == 0))
- {
- uint32_t wr_irpt;
- int is_write = 0;
- if(cmd_reg & SD_CMD_DAT_DIR_CH)
- wr_irpt = (1 << 5); // read
- else
- {
- is_write = 1;
- wr_irpt = (1 << 4); // write
- }
- int cur_block = 0;
- uint32_t *cur_buf_addr = (uint32_t *)dev->buf;
- while(cur_block < dev->blocks_to_transfer)
- {
- #ifdef EMMC_DEBUG
- if(dev->blocks_to_transfer > 1)
- printf("SD: multi block transfer, awaiting block %i ready\r\n",
- cur_block);
- #endif
- TIMEOUT_WAIT(mmio_read(EMMC_BASE + EMMC_INTERRUPT) & (wr_irpt | 0x8000), timeout);
- irpts = mmio_read(EMMC_BASE + EMMC_INTERRUPT);
- mmio_write(EMMC_BASE + EMMC_INTERRUPT, 0xffff0000 | wr_irpt);
- if((irpts & (0xffff0000 | wr_irpt)) != wr_irpt)
- {
- #ifdef EMMC_DEBUG
- printf("SD: error occured whilst waiting for data ready interrupt\r\n");
- #endif
- dev->last_error = irpts & 0xffff0000;
- dev->last_interrupt = irpts;
- return;
- }
- // Transfer the block
- size_t cur_byte_no = 0;
- while(cur_byte_no < dev->block_size)
- {
- if(is_write)
- {
- uint32_t data = read_word((uint8_t *)cur_buf_addr, 0);
- //printf("emmc write_word %lx\r\n",data);
- mmio_write(EMMC_BASE + EMMC_DATA, data);
- }
- else
- {
- uint32_t data = mmio_read(EMMC_BASE + EMMC_DATA);
- write_word(data, (uint8_t *)cur_buf_addr, 0);
- }
- cur_byte_no += 4;
- cur_buf_addr++;
- }
- #ifdef EMMC_DEBUG
- printf("SD: block %i transfer complete\r\n", cur_block);
- #endif
- cur_block++;
- }
- }
- // Wait for transfer complete (set if read/write transfer or with busy)
- if((((cmd_reg & SD_CMD_RSPNS_TYPE_MASK) == SD_CMD_RSPNS_TYPE_48B) ||
- (cmd_reg & SD_CMD_ISDATA)) && (is_sdma == 0))
- {
- // First check command inhibit (DAT) is not already 0
- if((mmio_read(EMMC_BASE + EMMC_STATUS) & 0x2) == 0)
- mmio_write(EMMC_BASE + EMMC_INTERRUPT, 0xffff0002);
- else
- {
- TIMEOUT_WAIT(mmio_read(EMMC_BASE + EMMC_INTERRUPT) & 0x8002, timeout);
- irpts = mmio_read(EMMC_BASE + EMMC_INTERRUPT);
- mmio_write(EMMC_BASE + EMMC_INTERRUPT, 0xffff0002);
- // Handle the case where both data timeout and transfer complete
- // are set - transfer complete overrides data timeout: HCSS 2.2.17
- if(((irpts & 0xffff0002) != 0x2) && ((irpts & 0xffff0002) != 0x100002))
- {
- #ifdef EMMC_DEBUG
- printf("SD: error occured whilst waiting for transfer complete interrupt\r\n");
- #endif
- dev->last_error = irpts & 0xffff0000;
- dev->last_interrupt = irpts;
- return;
- }
- mmio_write(EMMC_BASE + EMMC_INTERRUPT, 0xffff0002);
- }
- }
- else if (is_sdma)
- {
- // For SDMA transfers, we have to wait for either transfer complete,
- // DMA int or an error
- // First check command inhibit (DAT) is not already 0
- if((mmio_read(EMMC_BASE + EMMC_STATUS) & 0x2) == 0)
- mmio_write(EMMC_BASE + EMMC_INTERRUPT, 0xffff000a);
- else
- {
- TIMEOUT_WAIT(mmio_read(EMMC_BASE + EMMC_INTERRUPT) & 0x800a, timeout);
- irpts = mmio_read(EMMC_BASE + EMMC_INTERRUPT);
- mmio_write(EMMC_BASE + EMMC_INTERRUPT, 0xffff000a);
- // Detect errors
- if((irpts & 0x8000) && ((irpts & 0x2) != 0x2))
- {
- #ifdef EMMC_DEBUG
- printf("SD: error occured whilst waiting for transfer complete interrupt\r\n");
- #endif
- dev->last_error = irpts & 0xffff0000;
- dev->last_interrupt = irpts;
- return;
- }
- // Detect DMA interrupt without transfer complete
- // Currently not supported - all block sizes should fit in the
- // buffer
- if((irpts & 0x8) && ((irpts & 0x2) != 0x2))
- {
- #ifdef EMMC_DEBUG
- printf("SD: error: DMA interrupt occured without transfer complete\r\n");
- #endif
- dev->last_error = irpts & 0xffff0000;
- dev->last_interrupt = irpts;
- return;
- }
- // Detect transfer complete
- if(irpts & 0x2)
- {
- #ifdef EMMC_DEBUG
- printf("SD: SDMA transfer complete");
- #endif
- // Transfer the data to the user buffer
- memcpy(dev->buf, (const void *)SDMA_BUFFER, dev->block_size);
- }
- else
- {
- // Unknown error
- #ifdef EMMC_DEBUG
- if(irpts == 0)
- printf("SD: timeout waiting for SDMA transfer to complete\r\n");
- else
- printf("SD: unknown SDMA transfer error\r\n");
- printf("SD: INTERRUPT: %08x, STATUS %08x\r\n", irpts,
- mmio_read(EMMC_BASE + EMMC_STATUS));
- #endif
- if((irpts == 0) && ((mmio_read(EMMC_BASE + EMMC_STATUS) & 0x3) == 0x2))
- {
- // The data transfer is ongoing, we should attempt to stop
- // it
- #ifdef EMMC_DEBUG
- printf("SD: aborting transfer\r\n");
- #endif
- mmio_write(EMMC_BASE + EMMC_CMDTM, sd_commands[STOP_TRANSMISSION]);
- #ifdef EMMC_DEBUG
- // pause to let us read the screen
- usleep(2000000);
- #endif
- }
- dev->last_error = irpts & 0xffff0000;
- dev->last_interrupt = irpts;
- return;
- }
- }
- }
- // Return success
- dev->last_cmd_success = 1;
- }
- static void sd_handle_card_interrupt(struct emmc_block_dev *dev)
- {
- // Handle a card interrupt
- #ifdef EMMC_DEBUG
- uint32_t status = mmio_read(EMMC_BASE + EMMC_STATUS);
- printf("SD: card interrupt\r\n");
- printf("SD: controller status: %08x\r\n", status);
- #endif
- // Get the card status
- if(dev->card_rca)
- {
- sd_issue_command_int(dev, sd_commands[SEND_STATUS], dev->card_rca << 16,
- 500000);
- if(FAIL(dev))
- {
- #ifdef EMMC_DEBUG
- printf("SD: unable to get card status\r\n");
- #endif
- }
- else
- {
- #ifdef EMMC_DEBUG
- printf("SD: card status: %08x\r\n", dev->last_r0);
- #endif
- }
- }
- else
- {
- #ifdef EMMC_DEBUG
- printf("SD: no card currently selected\r\n");
- #endif
- }
- }
- static void sd_handle_interrupts(struct emmc_block_dev *dev)
- {
- uint32_t irpts = mmio_read(EMMC_BASE + EMMC_INTERRUPT);
- uint32_t reset_mask = 0;
- if(irpts & SD_COMMAND_COMPLETE)
- {
- #ifdef EMMC_DEBUG
- printf("SD: spurious command complete interrupt\r\n");
- #endif
- reset_mask |= SD_COMMAND_COMPLETE;
- }
- if(irpts & SD_TRANSFER_COMPLETE)
- {
- #ifdef EMMC_DEBUG
- printf("SD: spurious transfer complete interrupt\r\n");
- #endif
- reset_mask |= SD_TRANSFER_COMPLETE;
- }
- if(irpts & SD_BLOCK_GAP_EVENT)
- {
- #ifdef EMMC_DEBUG
- printf("SD: spurious block gap event interrupt\r\n");
- #endif
- reset_mask |= SD_BLOCK_GAP_EVENT;
- }
- if(irpts & SD_DMA_INTERRUPT)
- {
- #ifdef EMMC_DEBUG
- printf("SD: spurious DMA interrupt\r\n");
- #endif
- reset_mask |= SD_DMA_INTERRUPT;
- }
- if(irpts & SD_BUFFER_WRITE_READY)
- {
- #ifdef EMMC_DEBUG
- printf("SD: spurious buffer write ready interrupt\r\n");
- #endif
- reset_mask |= SD_BUFFER_WRITE_READY;
- sd_reset_dat();
- }
- if(irpts & SD_BUFFER_READ_READY)
- {
- #ifdef EMMC_DEBUG
- printf("SD: spurious buffer read ready interrupt\r\n");
- #endif
- reset_mask |= SD_BUFFER_READ_READY;
- sd_reset_dat();
- }
- if(irpts & SD_CARD_INSERTION)
- {
- #ifdef EMMC_DEBUG
- printf("SD: card insertion detected\r\n");
- #endif
- reset_mask |= SD_CARD_INSERTION;
- }
- if(irpts & SD_CARD_REMOVAL)
- {
- #ifdef EMMC_DEBUG
- printf("SD: card removal detected\r\n");
- #endif
- reset_mask |= SD_CARD_REMOVAL;
- dev->card_removal = 1;
- }
- if(irpts & SD_CARD_INTERRUPT)
- {
- #ifdef EMMC_DEBUG
- printf("SD: card interrupt detected\r\n");
- #endif
- sd_handle_card_interrupt(dev);
- reset_mask |= SD_CARD_INTERRUPT;
- }
- if(irpts & 0x8000)
- {
- #ifdef EMMC_DEBUG
- printf("SD: spurious error interrupt: %08x\r\n", irpts);
- #endif
- reset_mask |= 0xffff0000;
- }
- mmio_write(EMMC_BASE + EMMC_INTERRUPT, reset_mask);
- }
- static void sd_issue_command(struct emmc_block_dev *dev, uint32_t command, uint32_t argument, useconds_t timeout)
- {
- // First, handle any pending interrupts
- sd_handle_interrupts(dev);
- // Stop the command issue if it was the card remove interrupt that was
- // handled
- if(dev->card_removal)
- {
- printf("SD: card removal detected\r\n");
- dev->last_cmd_success = 0;
- return;
- }
- // Now run the appropriate commands by calling sd_issue_command_int()
- if(command & IS_APP_CMD)
- {
- command &= 0xff;
- #ifdef EMMC_DEBUG
- printf("SD: issuing command ACMD%i\r\n", command);
- #endif
- if(sd_acommands[command] == SD_CMD_RESERVED(0))
- {
- printf("SD: invalid command ACMD%i\r\n", command);
- dev->last_cmd_success = 0;
- return;
- }
- dev->last_cmd = APP_CMD;
- uint32_t rca = 0;
- if(dev->card_rca)
- rca = dev->card_rca << 16;
- sd_issue_command_int(dev, sd_commands[APP_CMD], rca, timeout);
- if(dev->last_cmd_success)
- {
- dev->last_cmd = command | IS_APP_CMD;
- sd_issue_command_int(dev, sd_acommands[command], argument, timeout);
- }
- }
- else
- {
- #ifdef EMMC_DEBUG
- printf("SD: issuing command CMD%i\r\n", command);
- #endif
- if(sd_commands[command] == SD_CMD_RESERVED(0))
- {
- printf("SD: invalid command CMD%i\r\n", command);
- dev->last_cmd_success = 0;
- return;
- }
- dev->last_cmd = command;
- sd_issue_command_int(dev, sd_commands[command], argument, timeout);
- }
- #ifdef EMMC_DEBUG
- if(FAIL(dev))
- {
- printf("SD: error issuing command: %i interrupts %08x: ", command, dev->last_interrupt);
- if(dev->last_error == 0)
- printf("TIMEOUT");
- else
- {
- for(int i = 0; i < SD_ERR_RSVD; i++)
- {
- if(dev->last_error & (1 << (i + 16)))
- {
- printf(err_irpts[i]);
- printf(" ");
- }
- }
- }
- printf("\r\n");
- }
- else
- printf("SD: command completed successfully\r\n");
- #endif
- }
- int sd_card_init(struct block_device **dev)
- {
- // Check the sanity of the sd_commands and sd_acommands structures
- if(sizeof(sd_commands) != (64 * sizeof(uint32_t)))
- {
- printf("EMMC: fatal error, sd_commands of incorrect size: %i"
- " expected %i\r\n", sizeof(sd_commands),
- 64 * sizeof(uint32_t));
- return -1;
- }
- if(sizeof(sd_acommands) != (64 * sizeof(uint32_t)))
- {
- printf("EMMC: fatal error, sd_acommands of incorrect size: %i"
- " expected %i\r\n", sizeof(sd_acommands),
- 64 * sizeof(uint32_t));
- return -1;
- }
- #if SDHCI_IMPLEMENTATION == SDHCI_IMPLEMENTATION_BCM_2708
- // Power cycle the card to ensure its in its startup state
- if(bcm_2708_power_cycle() != 0)
- {
- printf("EMMC: BCM2708 controller did not power cycle successfully\r\n");
- return -1;
- }
- #ifdef EMMC_DEBUG
- printf("EMMC: BCM2708 controller power-cycled\r\n");
- #endif
- #endif
- // Read the controller version
- uint32_t ver = mmio_read(EMMC_BASE + EMMC_SLOTISR_VER);
- uint32_t vendor = ver >> 24;
- uint32_t sdversion = (ver >> 16) & 0xff;
- uint32_t slot_status = ver & 0xff;
- printf("EMMC: vendor %x, sdversion %x, slot_status %x\r\n", vendor, sdversion, slot_status);
- hci_ver = sdversion;
- if(hci_ver < 2)
- {
- printf("EMMC: only SDHCI versions >= 3.0 are supported\r\n");
- return -1;
- }
- // Reset the controller
- #ifdef EMMC_DEBUG
- printf("EMMC: resetting controller\r\n");
- #endif
- uint32_t control1 = mmio_read(EMMC_BASE + EMMC_CONTROL1);
- control1 |= (1 << 24);
- // Disable clock
- control1 &= ~(1 << 2);
- control1 &= ~(1 << 0);
- mmio_write(EMMC_BASE + EMMC_CONTROL1, control1);
- TIMEOUT_WAIT((mmio_read(EMMC_BASE + EMMC_CONTROL1) & (0x7 << 24)) == 0, 1000000);
- if((mmio_read(EMMC_BASE + EMMC_CONTROL1) & (0x7 << 24)) != 0)
- {
- printf("EMMC: controller did not reset properly\r\n");
- return -1;
- }
- #ifdef EMMC_DEBUG
- printf("EMMC: control0: %08x, control1: %08x, control2: %08x\r\n",
- mmio_read(EMMC_BASE + EMMC_CONTROL0),
- mmio_read(EMMC_BASE + EMMC_CONTROL1),
- mmio_read(EMMC_BASE + EMMC_CONTROL2));
- #endif
- // Read the capabilities registers
- capabilities_0 = mmio_read(EMMC_BASE + EMMC_CAPABILITIES_0);
- capabilities_1 = mmio_read(EMMC_BASE + EMMC_CAPABILITIES_1);
- #ifdef EMMC_DEBUG
- printf("EMMC: capabilities: %08x%08x\r\n", capabilities_1, capabilities_0);
- #endif
- // Check for a valid card
- #ifdef EMMC_DEBUG
- printf("EMMC: checking for an inserted card\r\n");
- #endif
- TIMEOUT_WAIT(mmio_read(EMMC_BASE + EMMC_STATUS) & (1 << 16), 500000);
- uint32_t status_reg = mmio_read(EMMC_BASE + EMMC_STATUS);
- if((status_reg & (1 << 16)) == 0)
- {
- printf("EMMC: no card inserted\r\n");
- return -1;
- }
- #ifdef EMMC_DEBUG
- printf("EMMC: status: %08x\r\n", status_reg);
- #endif
- // Clear control2
- mmio_write(EMMC_BASE + EMMC_CONTROL2, 0);
- // Get the base clock rate
- uint32_t base_clock = sd_get_base_clock_hz();
- if(base_clock == 0)
- {
- printf("EMMC: assuming clock rate to be 100MHz\r\n");
- base_clock = 100000000;
- }
- // Set clock rate to something slow
- #ifdef EMMC_DEBUG
- printf("EMMC: setting clock rate\r\n");
- #endif
- control1 = mmio_read(EMMC_BASE + EMMC_CONTROL1);
- control1 |= 1; // enable clock
- // Set to identification frequency (400 kHz)
- uint32_t f_id = sd_get_clock_divider(base_clock, SD_CLOCK_ID);
- if(f_id == SD_GET_CLOCK_DIVIDER_FAIL)
- {
- printf("EMMC: unable to get a valid clock divider for ID frequency\r\n");
- return -1;
- }
- control1 |= f_id;
- control1 |= (7 << 16); // data timeout = TMCLK * 2^10
- mmio_write(EMMC_BASE + EMMC_CONTROL1, control1);
- TIMEOUT_WAIT(mmio_read(EMMC_BASE + EMMC_CONTROL1) & 0x2, 0x1000000);
- if((mmio_read(EMMC_BASE + EMMC_CONTROL1) & 0x2) == 0)
- {
- printf("EMMC: controller's clock did not stabilise within 1 second\r\n");
- return -1;
- }
- #ifdef EMMC_DEBUG
- printf("EMMC: control0: %08x, control1: %08x\r\n",
- mmio_read(EMMC_BASE + EMMC_CONTROL0),
- mmio_read(EMMC_BASE + EMMC_CONTROL1));
- #endif
- // Enable the SD clock
- #ifdef EMMC_DEBUG
- printf("EMMC: enabling SD clock\r\n");
- #endif
- usleep(2000);
- control1 = mmio_read(EMMC_BASE + EMMC_CONTROL1);
- control1 |= 4;
- mmio_write(EMMC_BASE + EMMC_CONTROL1, control1);
- usleep(2000);
- #ifdef EMMC_DEBUG
- printf("EMMC: SD clock enabled\r\n");
- #endif
- // Mask off sending interrupts to the ARM
- mmio_write(EMMC_BASE + EMMC_IRPT_EN, 0);
- // Reset interrupts
- mmio_write(EMMC_BASE + EMMC_INTERRUPT, 0xffffffff);
- // Have all interrupts sent to the INTERRUPT register
- uint32_t irpt_mask = 0xffffffff & (~SD_CARD_INTERRUPT);
- #ifdef SD_CARD_INTERRUPTS
- irpt_mask |= SD_CARD_INTERRUPT;
- #endif
- mmio_write(EMMC_BASE + EMMC_IRPT_MASK, irpt_mask);
- #ifdef EMMC_DEBUG
- printf("EMMC: interrupts disabled\r\n");
- #endif
- usleep(2000);
- // Prepare the device structure
- struct emmc_block_dev *ret;
- if(*dev == NULL)
- ret = (struct emmc_block_dev *)malloc(sizeof(struct emmc_block_dev));
- else
- ret = (struct emmc_block_dev *)*dev;
- assert(ret);
- memset(ret, 0, sizeof(struct emmc_block_dev));
- ret->bd.driver_name = driver_name;
- ret->bd.device_name = device_name;
- ret->bd.block_size = 512;
- ret->bd.read = sd_read;
- #ifdef SD_WRITE_SUPPORT
- ret->bd.write = sd_write;
- #endif
- ret->bd.supports_multiple_block_read = 1; // FIXME
- ret->bd.supports_multiple_block_write = 1; // FIXME
- ret->base_clock = base_clock;
- #ifdef EMMC_DEBUG
- printf("EMMC: device structure created\r\n");
- #endif
- // Send CMD0 to the card (reset to idle state)
- sd_issue_command(ret, GO_IDLE_STATE, 0, 500000);
- if(FAIL(ret))
- {
- printf("SD: no CMD0 response\r\n");
- return -1;
- }
- // Send CMD8 to the card
- // Voltage supplied = 0x1 = 2.7-3.6V (standard)
- // Check pattern = 10101010b (as per PLSS 4.3.13) = 0xAA
- #ifdef EMMC_DEBUG
- printf("SD: note a timeout error on the following command (CMD8) is normal "
- "and expected if the SD card version is less than 2.0\r\n");
- #endif
- sd_issue_command(ret, SEND_IF_COND, 0x1aa, 500000);
- int v2_later = 0;
- if(TIMEOUT(ret))
- v2_later = 0;
- else if(CMD_TIMEOUT(ret))
- {
- if(sd_reset_cmd() == -1)
- return -1;
- mmio_write(EMMC_BASE + EMMC_INTERRUPT, SD_ERR_MASK_CMD_TIMEOUT);
- v2_later = 0;
- }
- else if(FAIL(ret))
- {
- printf("SD: failure sending CMD8 (%08x)\r\n", ret->last_interrupt);
- return -1;
- }
- else
- {
- if((ret->last_r0 & 0xfff) != 0x1aa)
- {
- printf("SD: unusable card\r\n");
- #ifdef EMMC_DEBUG
- printf("SD: CMD8 response %08x\r\n", ret->last_r0);
- #endif
- return -1;
- }
- else
- v2_later = 1;
- }
- // Here we are supposed to check the response to CMD5 (HCSS 3.6)
- // It only returns if the card is a SDIO card
- #ifdef EMMC_DEBUG
- printf("SD: note that a timeout error on the following command (CMD5) is "
- "normal and expected if the card is not a SDIO card.\r\n");
- #endif
- sd_issue_command(ret, IO_SET_OP_COND, 0, 10000);
- if(!TIMEOUT(ret))
- {
- if(CMD_TIMEOUT(ret))
- {
- if(sd_reset_cmd() == -1)
- return -1;
- mmio_write(EMMC_BASE + EMMC_INTERRUPT, SD_ERR_MASK_CMD_TIMEOUT);
- }
- else
- {
- printf("SD: SDIO card detected - not currently supported\r\n");
- #ifdef EMMC_DEBUG
- printf("SD: CMD5 returned %08x\r\n", ret->last_r0);
- #endif
- return -1;
- }
- }
- // Call an inquiry ACMD41 (voltage window = 0) to get the OCR
- #ifdef EMMC_DEBUG
- printf("SD: sending inquiry ACMD41\r\n");
- #endif
- sd_issue_command(ret, ACMD(41), 0, 500000);
- if(FAIL(ret))
- {
- printf("SD: inquiry ACMD41 failed\r\n");
- return -1;
- }
- #ifdef EMMC_DEBUG
- printf("SD: inquiry ACMD41 returned %08x\r\n", ret->last_r0);
- #endif
- // Call initialization ACMD41
- int card_is_busy = 1;
- while(card_is_busy)
- {
- uint32_t v2_flags = 0;
- if(v2_later)
- {
- // Set SDHC support
- v2_flags |= (1 << 30);
- // Set 1.8v support
- #ifdef SD_1_8V_SUPPORT
- if(!ret->failed_voltage_switch)
- v2_flags |= (1 << 24);
- #endif
- // Enable SDXC maximum performance
- #ifdef SDXC_MAXIMUM_PERFORMANCE
- v2_flags |= (1 << 28);
- #endif
- }
- sd_issue_command(ret, ACMD(41), 0x00ff8000 | v2_flags, 500000);
- if(FAIL(ret))
- {
- printf("SD: error issuing ACMD41\r\n");
- return -1;
- }
- if((ret->last_r0 >> 31) & 0x1)
- {
- // Initialization is complete
- ret->card_ocr = (ret->last_r0 >> 8) & 0xffff;
- ret->card_supports_sdhc = (ret->last_r0 >> 30) & 0x1;
- #ifdef SD_1_8V_SUPPORT
- if(!ret->failed_voltage_switch)
- ret->card_supports_18v = (ret->last_r0 >> 24) & 0x1;
- #endif
- card_is_busy = 0;
- }
- else
- {
- // Card is still busy
- #ifdef EMMC_DEBUG
- printf("SD: card is busy, retrying\r\n");
- #endif
- usleep(500000);
- }
- }
- #ifdef EMMC_DEBUG
- printf("SD: card identified: OCR: %04x, 1.8v support: %i, SDHC support: %i\r\n",
- ret->card_ocr, ret->card_supports_18v, ret->card_supports_sdhc);
- #endif
- // At this point, we know the card is definitely an SD card, so will definitely
- // support SDR12 mode which runs at 25 MHz
- sd_switch_clock_rate(base_clock, SD_CLOCK_NORMAL);
- // A small wait before the voltage switch
- usleep(5000);
- // Switch to 1.8V mode if possible
- if(ret->card_supports_18v)
- {
- #ifdef EMMC_DEBUG
- printf("SD: switching to 1.8V mode\r\n");
- #endif
- // As per HCSS 3.6.1
- // Send VOLTAGE_SWITCH
- sd_issue_command(ret, VOLTAGE_SWITCH, 0, 500000);
- if(FAIL(ret))
- {
- #ifdef EMMC_DEBUG
- printf("SD: error issuing VOLTAGE_SWITCH\r\n");
- #endif
- ret->failed_voltage_switch = 1;
- sd_power_off();
- return sd_card_init((struct block_device **)&ret);
- }
- // Disable SD clock
- control1 = mmio_read(EMMC_BASE + EMMC_CONTROL1);
- control1 &= ~(1 << 2);
- mmio_write(EMMC_BASE + EMMC_CONTROL1, control1);
- // Check DAT[3:0]
- status_reg = mmio_read(EMMC_BASE + EMMC_STATUS);
- uint32_t dat30 = (status_reg >> 20) & 0xf;
- if(dat30 != 0)
- {
- #ifdef EMMC_DEBUG
- printf("SD: DAT[3:0] did not settle to 0\r\n");
- #endif
- ret->failed_voltage_switch = 1;
- sd_power_off();
- return sd_card_init((struct block_device **)&ret);
- }
- // Set 1.8V signal enable to 1
- uint32_t control0 = mmio_read(EMMC_BASE + EMMC_CONTROL0);
- control0 |= (1 << 8);
- mmio_write(EMMC_BASE + EMMC_CONTROL0, control0);
- // Wait 5 ms
- usleep(5000);
- // Check the 1.8V signal enable is set
- control0 = mmio_read(EMMC_BASE + EMMC_CONTROL0);
- if(((control0 >> 8) & 0x1) == 0)
- {
- #ifdef EMMC_DEBUG
- printf("SD: controller did not keep 1.8V signal enable high\r\n");
- #endif
- ret->failed_voltage_switch = 1;
- sd_power_off();
- return sd_card_init((struct block_device **)&ret);
- }
- // Re-enable the SD clock
- control1 = mmio_read(EMMC_BASE + EMMC_CONTROL1);
- control1 |= (1 << 2);
- mmio_write(EMMC_BASE + EMMC_CONTROL1, control1);
- // Wait 1 ms
- usleep(10000);
- // Check DAT[3:0]
- status_reg = mmio_read(EMMC_BASE + EMMC_STATUS);
- dat30 = (status_reg >> 20) & 0xf;
- if(dat30 != 0xf)
- {
- #ifdef EMMC_DEBUG
- printf("SD: DAT[3:0] did not settle to 1111b (%01x)\r\n", dat30);
- #endif
- ret->failed_voltage_switch = 1;
- sd_power_off();
- return sd_card_init((struct block_device **)&ret);
- }
- #ifdef EMMC_DEBUG
- printf("SD: voltage switch complete\r\n");
- #endif
- }
- // Send CMD2 to get the cards CID
- sd_issue_command(ret, ALL_SEND_CID, 0, 500000);
- if(FAIL(ret))
- {
- printf("SD: error sending ALL_SEND_CID\r\n");
- return -1;
- }
- uint32_t card_cid_0 = ret->last_r0;
- uint32_t card_cid_1 = ret->last_r1;
- uint32_t card_cid_2 = ret->last_r2;
- uint32_t card_cid_3 = ret->last_r3;
- #ifdef EMMC_DEBUG
- printf("SD: card CID: %08x%08x%08x%08x\r\n", card_cid_3, card_cid_2, card_cid_1, card_cid_0);
- #endif
- uint32_t *dev_id = (uint32_t *)malloc(4 * sizeof(uint32_t));
- dev_id[0] = card_cid_0;
- dev_id[1] = card_cid_1;
- dev_id[2] = card_cid_2;
- dev_id[3] = card_cid_3;
- ret->bd.device_id = (uint8_t *)dev_id;
- ret->bd.dev_id_len = 4 * sizeof(uint32_t);
- // Send CMD3 to enter the data state
- sd_issue_command(ret, SEND_RELATIVE_ADDR, 0, 500000);
- if(FAIL(ret))
- {
- printf("SD: error sending SEND_RELATIVE_ADDR\r\n");
- free(ret);
- return -1;
- }
- uint32_t cmd3_resp = ret->last_r0;
- #ifdef EMMC_DEBUG
- printf("SD: CMD3 response: %08x\r\n", cmd3_resp);
- #endif
- ret->card_rca = (cmd3_resp >> 16) & 0xffff;
- uint32_t crc_error = (cmd3_resp >> 15) & 0x1;
- uint32_t illegal_cmd = (cmd3_resp >> 14) & 0x1;
- uint32_t error = (cmd3_resp >> 13) & 0x1;
- uint32_t status = (cmd3_resp >> 9) & 0xf;
- uint32_t ready = (cmd3_resp >> 8) & 0x1;
- if(crc_error)
- {
- printf("SD: CRC error\r\n");
- free(ret);
- free(dev_id);
- return -1;
- }
- if(illegal_cmd)
- {
- printf("SD: illegal command\r\n");
- free(ret);
- free(dev_id);
- return -1;
- }
- if(error)
- {
- printf("SD: generic error\r\n");
- free(ret);
- free(dev_id);
- return -1;
- }
- if(!ready)
- {
- printf("SD: not ready for data\r\n");
- free(ret);
- free(dev_id);
- return -1;
- }
- #ifdef EMMC_DEBUG
- printf("SD: RCA: %04x\r\n", ret->card_rca);
- #endif
- // Now select the card (toggles it to transfer state)
- sd_issue_command(ret, SELECT_CARD, ret->card_rca << 16, 500000);
- if(FAIL(ret))
- {
- printf("SD: error sending CMD7\r\n");
- free(ret);
- return -1;
- }
- uint32_t cmd7_resp = ret->last_r0;
- status = (cmd7_resp >> 9) & 0xf;
- if((status != 3) && (status != 4))
- {
- printf("SD: invalid status (%i)\r\n", status);
- free(ret);
- free(dev_id);
- return -1;
- }
- // If not an SDHC card, ensure BLOCKLEN is 512 bytes
- if(!ret->card_supports_sdhc)
- {
- sd_issue_command(ret, SET_BLOCKLEN, 512, 500000);
- if(FAIL(ret))
- {
- printf("SD: error sending SET_BLOCKLEN\r\n");
- free(ret);
- return -1;
- }
- }
- ret->block_size = 512;
- uint32_t controller_block_size = mmio_read(EMMC_BASE + EMMC_BLKSIZECNT);
- controller_block_size &= (~0xfff);
- controller_block_size |= 0x200;
- mmio_write(EMMC_BASE + EMMC_BLKSIZECNT, controller_block_size);
- // Get the cards SCR register
- ret->scr = (struct sd_scr *)malloc(sizeof(struct sd_scr));
- ret->buf = &ret->scr->scr[0];
- ret->block_size = 8;
- ret->blocks_to_transfer = 1;
- sd_issue_command(ret, SEND_SCR, 0, 500000);
- ret->block_size = 512;
- if(FAIL(ret))
- {
- printf("SD: error sending SEND_SCR\r\n");
- free(ret->scr);
- free(ret);
- return -1;
- }
- // Determine card version
- // Note that the SCR is big-endian
- uint32_t scr0 = byte_swap(ret->scr->scr[0]);
- ret->scr->sd_version = SD_VER_UNKNOWN;
- uint32_t sd_spec = (scr0 >> (56 - 32)) & 0xf;
- uint32_t sd_spec3 = (scr0 >> (47 - 32)) & 0x1;
- uint32_t sd_spec4 = (scr0 >> (42 - 32)) & 0x1;
- ret->scr->sd_bus_widths = (scr0 >> (48 - 32)) & 0xf;
- if(sd_spec == 0)
- ret->scr->sd_version = SD_VER_1;
- else if(sd_spec == 1)
- ret->scr->sd_version = SD_VER_1_1;
- else if(sd_spec == 2)
- {
- if(sd_spec3 == 0)
- ret->scr->sd_version = SD_VER_2;
- else if(sd_spec3 == 1)
- {
- if(sd_spec4 == 0)
- ret->scr->sd_version = SD_VER_3;
- else if(sd_spec4 == 1)
- ret->scr->sd_version = SD_VER_4;
- }
- }
- #ifdef EMMC_DEBUG
- printf("SD: &scr: %08x\r\n", &ret->scr->scr[0]);
- printf("SD: SCR[0]: %08x, SCR[1]: %08x\r\n", ret->scr->scr[0], ret->scr->scr[1]);;
- printf("SD: SCR: %08x%08x\r\n", byte_swap(ret->scr->scr[0]), byte_swap(ret->scr->scr[1]));
- printf("SD: SCR: version %s, bus_widths %01x\r\n", sd_versions[ret->scr->sd_version],
- ret->scr->sd_bus_widths);
- #endif
- if(ret->scr->sd_bus_widths & 0x4)
- {
- // Set 4-bit transfer mode (ACMD6)
- // See HCSS 3.4 for the algorithm
- #ifdef SD_4BIT_DATA
- #ifdef EMMC_DEBUG
- printf("SD: switching to 4-bit data mode\r\n");
- #endif
- // Disable card interrupt in host
- uint32_t old_irpt_mask = mmio_read(EMMC_BASE + EMMC_IRPT_MASK);
- uint32_t new_iprt_mask = old_irpt_mask & ~(1 << 8);
- mmio_write(EMMC_BASE + EMMC_IRPT_MASK, new_iprt_mask);
- // Send ACMD6 to change the card's bit mode
- sd_issue_command(ret, SET_BUS_WIDTH, 0x2, 500000);
- if(FAIL(ret))
- printf("SD: switch to 4-bit data mode failed\r\n");
- else
- {
- // Change bit mode for Host
- uint32_t control0 = mmio_read(EMMC_BASE + EMMC_CONTROL0);
- control0 |= 0x2;
- mmio_write(EMMC_BASE + EMMC_CONTROL0, control0);
- // Re-enable card interrupt in host
- mmio_write(EMMC_BASE + EMMC_IRPT_MASK, old_irpt_mask);
- #ifdef EMMC_DEBUG
- printf("SD: switch to 4-bit complete\r\n");
- #endif
- }
- #endif
- }
- printf("SD: found a valid version %s SD card\r\n", sd_versions[ret->scr->sd_version]);
- #ifdef EMMC_DEBUG
- printf("SD: setup successful (status %i)\r\n", status);
- #endif
- // Reset interrupt register
- mmio_write(EMMC_BASE + EMMC_INTERRUPT, 0xffffffff);
- *dev = (struct block_device *)ret;
- return 0;
- }
- static int sd_ensure_data_mode(struct emmc_block_dev *edev)
- {
- if(edev->card_rca == 0)
- {
- // Try again to initialise the card
- int ret = sd_card_init((struct block_device **)&edev);
- if(ret != 0)
- return ret;
- }
- #ifdef EMMC_DEBUG
- printf("SD: ensure_data_mode() obtaining status register for card_rca %08x: \r\n",
- edev->card_rca);
- #endif
- sd_issue_command(edev, SEND_STATUS, edev->card_rca << 16, 500000);
- if(FAIL(edev))
- {
- printf("SD: ensure_data_mode() error sending CMD13\r\n");
- edev->card_rca = 0;
- return -1;
- }
- uint32_t status = edev->last_r0;
- uint32_t cur_state = (status >> 9) & 0xf;
- #ifdef EMMC_DEBUG
- printf("status %i\r\n", cur_state);
- #endif
- if(cur_state == 3)
- {
- // Currently in the stand-by state - select it
- sd_issue_command(edev, SELECT_CARD, edev->card_rca << 16, 500000);
- if(FAIL(edev))
- {
- printf("SD: ensure_data_mode() no response from CMD17\r\n");
- edev->card_rca = 0;
- return -1;
- }
- }
- else if(cur_state == 5)
- {
- // In the data transfer state - cancel the transmission
- sd_issue_command(edev, STOP_TRANSMISSION, 0, 500000);
- if(FAIL(edev))
- {
- printf("SD: ensure_data_mode() no response from CMD12\r\n");
- edev->card_rca = 0;
- return -1;
- }
- // Reset the data circuit
- sd_reset_dat();
- }
- else if(cur_state != 4)
- {
- // Not in the transfer state - re-initialise
- int ret = sd_card_init((struct block_device **)&edev);
- if(ret != 0)
- return ret;
- }
- // Check again that we're now in the correct mode
- if(cur_state != 4)
- {
- #ifdef EMMC_DEBUG
- printf("SD: ensure_data_mode() rechecking status: ");
- #endif
- sd_issue_command(edev, SEND_STATUS, edev->card_rca << 16, 500000);
- if(FAIL(edev))
- {
- printf("SD: ensure_data_mode() no response from CMD13\r\n");
- edev->card_rca = 0;
- return -1;
- }
- status = edev->last_r0;
- cur_state = (status >> 9) & 0xf;
- #ifdef EMMC_DEBUG
- printf("%i\r\n", cur_state);
- #endif
- if(cur_state != 4)
- {
- printf("SD: unable to initialise SD card to "
- "data mode (state %i)\r\n", cur_state);
- edev->card_rca = 0;
- return -1;
- }
- }
- return 0;
- }
- #ifdef SDMA_SUPPORT
- // We only support DMA transfers to buffers aligned on a 4 kiB boundary
- static int sd_suitable_for_dma(void *buf)
- {
- if((uintptr_t)buf & 0xfff)
- return 0;
- else
- return 1;
- }
- #endif
- static int sd_do_data_command(struct emmc_block_dev *edev, int is_write, uint8_t *buf, size_t buf_size, uint32_t block_no)
- {
- // PLSS table 4.20 - SDSC cards use byte addresses rather than block addresses
- if(!edev->card_supports_sdhc)
- block_no *= 512;
- // This is as per HCSS 3.7.2.1
- if(buf_size < edev->block_size)
- {
- printf("SD: do_data_command() called with buffer size (%i) less than "
- "block size (%i)\r\n", buf_size, edev->block_size);
- return -1;
- }
- edev->blocks_to_transfer = buf_size / edev->block_size;
- if(buf_size % edev->block_size)
- {
- printf("SD: do_data_command() called with buffer size (%i) not an "
- "exact multiple of block size (%i)\r\n", buf_size, edev->block_size);
- return -1;
- }
- edev->buf = buf;
- // Decide on the command to use
- int command;
- if(is_write)
- {
- if(edev->blocks_to_transfer > 1) {
- command = WRITE_MULTIPLE_BLOCK;
- printf("SD: WRITE_MULTIPLE_BLOCK\r\n");
- }
- else {
- command = WRITE_BLOCK;
- printf("SD: WRITE_BLOCK\r\n");
- }
- }
- else
- {
- if(edev->blocks_to_transfer > 1)
- command = READ_MULTIPLE_BLOCK;
- else
- command = READ_SINGLE_BLOCK;
- }
- int retry_count = 0;
- int max_retries = 3;
- while(retry_count < max_retries)
- {
- #ifdef SDMA_SUPPORT
- // use SDMA for the first try only
- if((retry_count == 0) && sd_suitable_for_dma(buf))
- edev->use_sdma = 1;
- else
- {
- #ifdef EMMC_DEBUG
- printf("SD: retrying without SDMA\r\n");
- #endif
- edev->use_sdma = 0;
- }
- #else
- edev->use_sdma = 0;
- #endif
- sd_issue_command(edev, command, block_no, 5000000);
- if(SUCCESS(edev))
- break;
- else
- {
- printf("SD: error sending CMD%i, ", command);
- printf("error = %08x. ", edev->last_error);
- retry_count++;
- if(retry_count < max_retries)
- printf("Retrying...\r\n");
- else
- printf("Giving up.\r\n");
- }
- }
- if(retry_count == max_retries)
- {
- edev->card_rca = 0;
- return -1;
- }
- return 0;
- }
- int sd_read(struct block_device *dev, uint8_t *buf, size_t buf_size, uint32_t block_no)
- {
- // Check the status of the card
- struct emmc_block_dev *edev = (struct emmc_block_dev *)dev;
- if(sd_ensure_data_mode(edev) != 0)
- return -1;
- #ifdef EMMC_DEBUG
- printf("SD: read() card ready, reading from block %u\r\n", block_no);
- #endif
- if(sd_do_data_command(edev, 0, buf, buf_size, block_no) < 0)
- return -1;
- #ifdef EMMC_DEBUG
- printf("SD: data read successful\r\n");
- #endif
- return buf_size;
- }
- #ifdef SD_WRITE_SUPPORT
- int sd_write(struct block_device *dev, uint8_t *buf, size_t buf_size, uint32_t block_no)
- {
- // Check the status of the card
- struct emmc_block_dev *edev = (struct emmc_block_dev *)dev;
- if(sd_ensure_data_mode(edev) != 0)
- return -1;
- #ifdef EMMC_DEBUG
- printf("SD: write() card ready, writing to block %u\r\n", block_no);
- #endif
- if(sd_do_data_command(edev, 1, buf, buf_size, block_no) < 0)
- return -1;
- #ifdef EMMC_DEBUG
- printf("SD: data write successful\r\n");
- #endif
- return buf_size;
- }
- #endif
|