This series extends the sdcard boot menu description to include product and version information from the sd card. This makes the menu more readable and can help distinguish between cards if more than one drive is in the system.
-Kevin
Kevin O'Connor (4): sdcard: Move sdcard_set_frequency()/sdcard_set_power() in sdcard.c sdcard: Move frequency setting into sdcard_card_setup() sdcard: Move drive registration to sdcard_card_setup() sdcard: Display sdcard product name and revision in boot menu
src/hw/sdcard.c | 169 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 90 insertions(+), 79 deletions(-)
Just code movement; no code changes.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/hw/sdcard.c | 116 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 58 insertions(+), 58 deletions(-)
diff --git a/src/hw/sdcard.c b/src/hw/sdcard.c index 8e7e954..bf35277 100644 --- a/src/hw/sdcard.c +++ b/src/hw/sdcard.c @@ -293,6 +293,64 @@ sdcard_process_op(struct disk_op_s *op) * Setup ****************************************************************/
+static int +sdcard_set_power(struct sdhci_s *regs) +{ + u32 cap = readl(®s->cap_lo); + u32 volt, vbits; + if (cap & SD_CAPLO_V33) { + volt = 1<<20; + vbits = SPC_V33; + } else if (cap & SD_CAPLO_V30) { + volt = 1<<18; + vbits = SPC_V30; + } else if (cap & SD_CAPLO_V18) { + volt = 1<<7; + vbits = SPC_V18; + } else { + dprintf(1, "SD controller unsupported volt range (%x)\n", cap); + return -1; + } + writeb(®s->power_control, 0); + msleep(SDHCI_POWER_OFF_TIME); + writeb(®s->power_control, vbits | SPC_POWER_ON); + msleep(SDHCI_POWER_ON_TIME); + return volt; +} + +static int +sdcard_set_frequency(struct sdhci_s *regs, u32 khz) +{ + u16 ver = readw(®s->controller_version); + u32 cap = readl(®s->cap_lo); + u32 base_freq = (cap >> SD_CAPLO_BASECLOCK_SHIFT) & SD_CAPLO_BASECLOCK_MASK; + if (!base_freq) { + dprintf(1, "Unknown base frequency for SD controller\n"); + return -1; + } + // Set new frequency + u32 divisor = DIV_ROUND_UP(base_freq * 1000, khz); + u16 creg; + if ((ver & 0xff) <= 0x01) { + divisor = divisor > 1 ? 1 << __fls(divisor-1) : 0; + creg = (divisor & SCC_SDCLK_MASK) << SCC_SDCLK_SHIFT; + } else { + divisor = DIV_ROUND_UP(divisor, 2); + creg = (divisor & SCC_SDCLK_MASK) << SCC_SDCLK_SHIFT; + creg |= (divisor & SCC_SDCLK_HI_MASK) >> SCC_SDCLK_HI_RSHIFT; + } + dprintf(3, "sdcard_set_frequency %d %d %x\n", base_freq, khz, creg); + writew(®s->clock_control, 0); + writew(®s->clock_control, creg | SCC_INTERNAL_ENABLE); + // Wait for frequency to become active + int ret = sdcard_waitw(®s->clock_control, SCC_STABLE); + if (ret < 0) + return ret; + // Enable SD clock + writew(®s->clock_control, creg | SCC_INTERNAL_ENABLE | SCC_CLOCK_ENABLE); + return 0; +} + // Initialize an SD card static int sdcard_card_setup(struct sdhci_s *regs, int volt) @@ -357,64 +415,6 @@ sdcard_card_setup(struct sdhci_s *regs, int volt) return card_type; }
-static int -sdcard_set_power(struct sdhci_s *regs) -{ - u32 cap = readl(®s->cap_lo); - u32 volt, vbits; - if (cap & SD_CAPLO_V33) { - volt = 1<<20; - vbits = SPC_V33; - } else if (cap & SD_CAPLO_V30) { - volt = 1<<18; - vbits = SPC_V30; - } else if (cap & SD_CAPLO_V18) { - volt = 1<<7; - vbits = SPC_V18; - } else { - dprintf(1, "SD controller unsupported volt range (%x)\n", cap); - return -1; - } - writeb(®s->power_control, 0); - msleep(SDHCI_POWER_OFF_TIME); - writeb(®s->power_control, vbits | SPC_POWER_ON); - msleep(SDHCI_POWER_ON_TIME); - return volt; -} - -static int -sdcard_set_frequency(struct sdhci_s *regs, u32 khz) -{ - u16 ver = readw(®s->controller_version); - u32 cap = readl(®s->cap_lo); - u32 base_freq = (cap >> SD_CAPLO_BASECLOCK_SHIFT) & SD_CAPLO_BASECLOCK_MASK; - if (!base_freq) { - dprintf(1, "Unknown base frequency for SD controller\n"); - return -1; - } - // Set new frequency - u32 divisor = DIV_ROUND_UP(base_freq * 1000, khz); - u16 creg; - if ((ver & 0xff) <= 0x01) { - divisor = divisor > 1 ? 1 << __fls(divisor-1) : 0; - creg = (divisor & SCC_SDCLK_MASK) << SCC_SDCLK_SHIFT; - } else { - divisor = DIV_ROUND_UP(divisor, 2); - creg = (divisor & SCC_SDCLK_MASK) << SCC_SDCLK_SHIFT; - creg |= (divisor & SCC_SDCLK_HI_MASK) >> SCC_SDCLK_HI_RSHIFT; - } - dprintf(3, "sdcard_set_frequency %d %d %x\n", base_freq, khz, creg); - writew(®s->clock_control, 0); - writew(®s->clock_control, creg | SCC_INTERNAL_ENABLE); - // Wait for frequency to become active - int ret = sdcard_waitw(®s->clock_control, SCC_STABLE); - if (ret < 0) - return ret; - // Enable SD clock - writew(®s->clock_control, creg | SCC_INTERNAL_ENABLE | SCC_CLOCK_ENABLE); - return 0; -} - // Setup and configure an SD card controller static void sdcard_controller_setup(struct sdhci_s *regs, int prio)
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/hw/sdcard.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/hw/sdcard.c b/src/hw/sdcard.c index bf35277..a60fa92 100644 --- a/src/hw/sdcard.c +++ b/src/hw/sdcard.c @@ -355,9 +355,14 @@ sdcard_set_frequency(struct sdhci_s *regs, u32 khz) static int sdcard_card_setup(struct sdhci_s *regs, int volt) { + // Set controller to initialization clock rate + int ret = sdcard_set_frequency(regs, 400); + if (ret) + return ret; + msleep(SDHCI_CLOCK_ON_TIME); // Reset card u32 param[4] = { }; - int ret = sdcard_pio(regs, SC_GO_IDLE_STATE, param); + ret = sdcard_pio(regs, SC_GO_IDLE_STATE, param); if (ret) return ret; // Let card know SDHC/SDXC is supported and confirm voltage @@ -412,6 +417,10 @@ sdcard_card_setup(struct sdhci_s *regs, int volt) ret = sdcard_pio(regs, SC_SELECT_DESELECT_CARD, param); if (ret) return ret; + // Set controller to data transfer clock rate + ret = sdcard_set_frequency(regs, 25000); + if (ret) + return ret; return card_type; }
@@ -438,18 +447,11 @@ sdcard_controller_setup(struct sdhci_s *regs, int prio) int volt = sdcard_set_power(regs); if (volt < 0) return; - int ret = sdcard_set_frequency(regs, 400); - if (ret) - goto fail; - msleep(SDHCI_CLOCK_ON_TIME);
// Initialize card int card_type = sdcard_card_setup(regs, volt); if (card_type < 0) goto fail; - ret = sdcard_set_frequency(regs, 25000); - if (ret) - goto fail;
// Register drive struct sddrive_s *drive = malloc_fseg(sizeof(*drive));
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/hw/sdcard.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/src/hw/sdcard.c b/src/hw/sdcard.c index a60fa92..5b3ffb1 100644 --- a/src/hw/sdcard.c +++ b/src/hw/sdcard.c @@ -353,8 +353,9 @@ sdcard_set_frequency(struct sdhci_s *regs, u32 khz)
// Initialize an SD card static int -sdcard_card_setup(struct sdhci_s *regs, int volt) +sdcard_card_setup(struct sddrive_s *drive, int volt, int prio) { + struct sdhci_s *regs = drive->regs; // Set controller to initialization clock rate int ret = sdcard_set_frequency(regs, 400); if (ret) @@ -402,7 +403,7 @@ sdcard_card_setup(struct sdhci_s *regs, int volt) } msleep(5); // Avoid flooding log when debugging } - int card_type = (param[0] & SR_OCR_CCS) ? SF_HC : SF_SC; + drive->card_type = (param[0] & SR_OCR_CCS) ? SF_HC : SF_SC; // Select card param[0] = 0x00; ret = sdcard_pio(regs, SC_ALL_SEND_CID, param); @@ -421,7 +422,13 @@ sdcard_card_setup(struct sdhci_s *regs, int volt) ret = sdcard_set_frequency(regs, 25000); if (ret) return ret; - return card_type; + // Register drive + drive->drive.blksize = DISK_SECTOR_SIZE; + drive->drive.sectors = (u64)-1; // XXX + dprintf(1, "Found SD Card at %p\n", regs); + char *desc = znprintf(MAXDESCSIZE, "SD Card"); // XXX + boot_add_hd(&drive->drive, desc, prio); + return 0; }
// Setup and configure an SD card controller @@ -449,11 +456,6 @@ sdcard_controller_setup(struct sdhci_s *regs, int prio) return;
// Initialize card - int card_type = sdcard_card_setup(regs, volt); - if (card_type < 0) - goto fail; - - // Register drive struct sddrive_s *drive = malloc_fseg(sizeof(*drive)); if (!drive) { warn_noalloc(); @@ -461,14 +463,12 @@ sdcard_controller_setup(struct sdhci_s *regs, int prio) } memset(drive, 0, sizeof(*drive)); drive->drive.type = DTYPE_SDCARD; - drive->drive.blksize = DISK_SECTOR_SIZE; - drive->drive.sectors = (u64)-1; // XXX drive->regs = regs; - drive->card_type = card_type; - - dprintf(1, "Found SD Card at %p\n", regs); - char *desc = znprintf(MAXDESCSIZE, "SD Card"); // XXX - boot_add_hd(&drive->drive, desc, prio); + int ret = sdcard_card_setup(drive, volt, prio); + if (ret) { + free(drive); + goto fail; + } return; fail: writeb(®s->power_control, 0);
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/hw/sdcard.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/hw/sdcard.c b/src/hw/sdcard.c index 5b3ffb1..23d7432 100644 --- a/src/hw/sdcard.c +++ b/src/hw/sdcard.c @@ -409,6 +409,8 @@ sdcard_card_setup(struct sddrive_s *drive, int volt, int prio) ret = sdcard_pio(regs, SC_ALL_SEND_CID, param); if (ret) return ret; + u8 cid[16]; + memcpy(cid, param, sizeof(cid)); param[0] = isMMC ? 0x0001 << 16 : 0x00; ret = sdcard_pio(regs, SC_SEND_RELATIVE_ADDR, param); if (ret) @@ -425,8 +427,15 @@ sdcard_card_setup(struct sddrive_s *drive, int volt, int prio) // Register drive drive->drive.blksize = DISK_SECTOR_SIZE; drive->drive.sectors = (u64)-1; // XXX - dprintf(1, "Found SD Card at %p\n", regs); - char *desc = znprintf(MAXDESCSIZE, "SD Card"); // XXX + char pnm[7] = {}; + int i; + for (i=0; i < (isMMC ? 6 : 5); i++) + pnm[i] = cid[11-i]; + u8 prv = cid[11-i]; + char *desc = znprintf(MAXDESCSIZE, "%s %s v%d.%d" + , isMMC ? "MMC drive" : "SD card" + , pnm, prv>>4, prv & 0x0f); + dprintf(1, "Found sdcard at %p: %s\n", regs, desc); boot_add_hd(&drive->drive, desc, prio); return 0; }