diff --git a/fusee/fusee-primary/src/car.h b/fusee/fusee-primary/src/car.h index 9f62ad2a6..593c7a78a 100644 --- a/fusee/fusee-primary/src/car.h +++ b/fusee/fusee-primary/src/car.h @@ -48,11 +48,14 @@ enum { * Masks for TEGRA_CLK_SOURCE elements. */ enum { - CLK_SOURCE_MASK = (0b111 << 29), - CLK_SOURCE_FIRST = (0b000 << 29), + CLK_SOURCE_MASK = (0b111 << 29), + CLK_SOURCE_SDMMC1_PLLP_OUT0 = (0b000 << 29), /* Fixed 408 MHz */ + CLK_SOURCE_SDMMC4_PLLP_OUT0 = (0b000 << 29), /* Fixed 408 MHz */ + CLK_SOURCE_SDMMC4_PLLC4_OUT2_LJ = (0b001 << 29), /* 199.68 MHz */ + CLK_SOURCE_SDMMC_LEGACY_PLLP_OUT0 = (0b100 << 29), /* Fixed 408 MHz */ - CLK_DIVIDER_MASK = (0xff << 0), - CLK_DIVIDER_UNITY = (0x00 << 0), + CLK_DIVIDER_MASK = (0xff << 0), + CLK_DIVIDER_UNITY = (0x00 << 0), }; diff --git a/fusee/fusee-primary/src/sdmmc.c b/fusee/fusee-primary/src/sdmmc.c index 4deb1066d..cc57b0513 100644 --- a/fusee/fusee-primary/src/sdmmc.c +++ b/fusee/fusee-primary/src/sdmmc.c @@ -142,34 +142,52 @@ enum sdmmc_clock_dividers { MMC_CLOCK_DIVIDER_SDR12 = 31, // 16.5, from the TRM table MMC_CLOCK_DIVIDER_SDR25 = 15, // 8.5, from the table MMC_CLOCK_DIVIDER_SDR50 = 7, // 4.5, from the table - MMC_CLOCK_DIVIDER_SDR104 = 4, // 2, from the datasheet + MMC_CLOCK_DIVIDER_SDR104 = 2, // 2, from the table /* Clock dividers: MMC */ MMC_CLOCK_DIVIDER_HS26 = 30, // 16, from the TRM table MMC_CLOCK_DIVIDER_HS52 = 14, // 8, from the table - MMC_CLOCK_DIVIDER_HS200 = 2, // 1 -- NOTE THIS IS WITH RESPECT TO PLLC4_OUT2_LJ - MMC_CLOCK_DIVIDER_HS400 = 2, // 1 -- NOTE THIS IS WITH RESPECT TO PLLC4_OUT2_LJ -}; +#if 0 + // TODO: Figure out why PLLC4_OUT2_LJ doesn't work, most likely need to be enabled in hwinit + MMC_CLOCK_DIVIDER_HS200 = 0, // 1 -- NOTE THIS IS WITH RESPECT TO PLLC4_OUT2_LJ + MMC_CLOCK_DIVIDER_HS400 = 0, // 1 -- NOTE THIS IS WITH RESPECT TO PLLC4_OUT2_LJ +#else + MMC_CLOCK_DIVIDER_HS200 = 3, + MMC_CLOCK_DIVIDER_HS400 = 3, +#endif + /* Clock dividers: Legacy 12 MHz timer */ + MMC_CLOCK_DIVIDER_LEGACY = 66, // 34 - to get 12 MHz out of 408 MHz +}; /** * SDMMC clock divider constants */ enum sdmmc_clock_sources { - /* Clock dividers: SD */ - MMC_CLOCK_SOURCE_SDR12 = 0, // PLLP - MMC_CLOCK_SOURCE_SDR25 = 0, - MMC_CLOCK_SOURCE_SDR50 = 0, - MMC_CLOCK_SOURCE_SDR104 = 0, + /* Clock sources: SD */ + MMC_CLOCK_SOURCE_SDR12 = CLK_SOURCE_SDMMC1_PLLP_OUT0, // PLLP + MMC_CLOCK_SOURCE_SDR25 = CLK_SOURCE_SDMMC1_PLLP_OUT0, + MMC_CLOCK_SOURCE_SDR50 = CLK_SOURCE_SDMMC1_PLLP_OUT0, + MMC_CLOCK_SOURCE_SDR104 = CLK_SOURCE_SDMMC1_PLLP_OUT0, - /* Clock dividers: MMC */ - MMC_CLOCK_SOURCE_HS26 = 0, // PLLP - MMC_CLOCK_SOURCE_HS52 = 0, - MMC_CLOCK_SOURCE_HS200 = 1, // PLLC4_OUT2_LJ - MMC_CLOCK_SOURCE_HS400 = 1, + /* Clock sources: MMC */ + MMC_CLOCK_SOURCE_HS26 = CLK_SOURCE_SDMMC4_PLLP_OUT0, // PLLP + MMC_CLOCK_SOURCE_HS52 = CLK_SOURCE_SDMMC4_PLLP_OUT0, +#if 0 + // TODO: Figure out why PLLC4_OUT2_LJ doesn't work, most likely need to be enabled in hwinit + MMC_CLOCK_SOURCE_HS200 = CLK_SOURCE_SDMMC4_PLLC4_OUT2_LJ, // PLLC4_OUT2_LJ + MMC_CLOCK_SOURCE_HS400 = CLK_SOURCE_SDMMC4_PLLC4_OUT2_LJ, +#else + // For the time being, use PLLP_OUT0 + MMC_CLOCK_SOURCE_HS200 = CLK_SOURCE_SDMMC4_PLLP_OUT0, + MMC_CLOCK_SOURCE_HS400 = CLK_SOURCE_SDMMC4_PLLP_OUT0, +#endif + + /* Clock sources: Legacy 12 MHz timer */ + MMC_CLOCK_SOURCE_LEGACY = CLK_SOURCE_SDMMC_LEGACY_PLLP_OUT0, }; /** @@ -240,7 +258,7 @@ enum sdmmc_register_bits { MMC_CLOCK_CONTROL_CARD_CLOCK_ENABLE = (1 << 2), MMC_CLOCK_CONTROL_FREQUENCY_MASK = (0x3FF << 6), MMC_CLOCK_CONTROL_FREQUENCY_SHIFT = 8, - MMC_CLOCK_CONTROL_FREQUENCY_INIT = 0x18, // generates 400kHz from the TRM dividers + MMC_CLOCK_CONTROL_FREQUENCY_INIT = 0x1F, // generates 400kHz from the TRM dividers MMC_CLOCK_CONTROL_FREQUENCY_PASSTHROUGH = 0x00, // passes through the CAR clock unmodified /* Host control */ @@ -796,6 +814,20 @@ static int sdmmc_hardware_reset(struct mmc *mmc, uint32_t reset_flags) return 0; } +/** + * Delays for a given amount of host clock cycles. + * + * @param mmc The MMC controller whose clock cycles should be waited upon. + * @param clocks The number of clock cycles to wait. + */ +static void sdmmc_host_clock_delay(struct mmc *mmc, unsigned int clocks) +{ + // For the time being simply wait for clocks * 50 us + // This covers clocks as slow as 20 kHz and hence should always be safe + // TODO: determine the actual wait time based on clock source and divider + udelay(50 * clocks); +} + /** * Performs low-level initialization for SDMMC4, used for the eMMC. */ @@ -803,23 +835,22 @@ static int sdmmc4_set_up_clock_and_io(struct mmc *mmc) { volatile struct tegra_car *car = car_get_regs(); volatile struct tegra_padctl *padctl = padctl_get_regs(); - (void)mmc; // Put SDMMC4 in reset car->rst_dev_l_set |= 0x8000; // Configure the clock to place the device into the initial mode. - car->clk_src[CLK_SOURCE_SDMMC4] = CLK_SOURCE_FIRST | MMC_CLOCK_DIVIDER_SDR12; + car->clk_src[CLK_SOURCE_SDMMC4] = MMC_CLOCK_SOURCE_SDR12 | MMC_CLOCK_DIVIDER_SDR12; // Set the legacy divier used for detecting timeouts. - car->clk_src_y[CLK_SOURCE_SDMMC_LEGACY] = CLK_SOURCE_FIRST | MMC_CLOCK_DIVIDER_SDR12; + car->clk_src_y[CLK_SOURCE_SDMMC_LEGACY] = MMC_CLOCK_SOURCE_LEGACY | MMC_CLOCK_DIVIDER_LEGACY; // Set SDMMC4 clock enable car->clk_enb_l_set |= 0x8000; car->clk_enb_y_set |= CAR_CONTROL_SDMMC_LEGACY; - // host_clk_delay(0x64, clk_freq) -> Delay 100 host clock cycles - udelay(5000); + // Delay 100 host clock cycles + sdmmc_host_clock_delay(mmc, 100); // Take SDMMC4 out of reset car->rst_dev_l_clr |= 0x8000; @@ -1102,11 +1133,11 @@ static int sdmmc_always_fail(struct mmc *mmc) * a divider of N results in a clock that's (N/2) + 1 slower. * @param sdmmc_divisor An additional divisor applied in the SDMMC controller. */ -static void sdmmc4_configure_clock(struct mmc *mmc, int source, int car_divisor, int sdmmc_divisor) +static void sdmmc4_configure_clock(struct mmc *mmc, uint32_t source, int car_divisor, int sdmmc_divisor) { volatile struct tegra_car *car = car_get_regs(); - // Set up the CAR aspect of the clock, and wait 2uS per change per the TRM. + // Set up the CAR aspect of the clock, and wait 2us per change per the TRM. car->clk_enb_l_clr = CAR_CONTROL_SDMMC4; car->clk_src[CLK_SOURCE_SDMMC4] = source | car_divisor; udelay(2); @@ -1128,11 +1159,11 @@ static void sdmmc4_configure_clock(struct mmc *mmc, int source, int car_divisor, * a divider of N results in a clock that's (N/2) + 1 slower. * @param sdmmc_divisor An additional divisor applied in the SDMMC controller. */ -static void sdmmc1_configure_clock(struct mmc *mmc, int source, int car_divisor, int sdmmc_divisor) +static void sdmmc1_configure_clock(struct mmc *mmc, uint32_t source, int car_divisor, int sdmmc_divisor) { volatile struct tegra_car *car = car_get_regs(); - // Set up the CAR aspect of the clock, and wait 2uS per change per the TRM. + // Set up the CAR aspect of the clock, and wait 2us per change per the TRM. car->clk_enb_l_clr = CAR_CONTROL_SDMMC1; car->clk_src[CLK_SOURCE_SDMMC1] = source | car_divisor; udelay(2); @@ -1469,7 +1500,6 @@ static int sdmmc1_set_up_clock_and_io(struct mmc *mmc) volatile struct tegra_car *car = car_get_regs(); volatile struct tegra_pinmux *pinmux = pinmux_get_regs(); volatile struct tegra_padctl *padctl = padctl_get_regs(); - (void)mmc; // Set up each of the relevant pins to be connected to output drivers, // and selected for SDMMC use. @@ -1493,19 +1523,19 @@ static int sdmmc1_set_up_clock_and_io(struct mmc *mmc) car->rst_dev_l_set = CAR_CONTROL_SDMMC1; // Configure the clock to place the device into the initial mode. - car->clk_src[CLK_SOURCE_SDMMC1] = CLK_SOURCE_FIRST | MMC_CLOCK_DIVIDER_SDR12; + car->clk_src[CLK_SOURCE_SDMMC1] = MMC_CLOCK_SOURCE_SDR12 | MMC_CLOCK_DIVIDER_SDR12; // Set the legacy divier used for detecting timeouts. - car->clk_src_y[CLK_SOURCE_SDMMC_LEGACY] = CLK_SOURCE_FIRST | MMC_CLOCK_DIVIDER_SDR12; + car->clk_src_y[CLK_SOURCE_SDMMC_LEGACY] = MMC_CLOCK_SOURCE_LEGACY | MMC_CLOCK_DIVIDER_LEGACY; // Set SDMMC1 clock enable car->clk_enb_l_set = CAR_CONTROL_SDMMC1; car->clk_enb_y_set = CAR_CONTROL_SDMMC_LEGACY; - // host_clk_delay(0x64, clk_freq) -> Delay 100 host clock cycles - udelay(5000); + // Delay 100 host clock cycles + sdmmc_host_clock_delay(mmc, 100); - // Take SDMMC4 out of reset + // Take SDMMC1 out of reset car->rst_dev_l_clr |= CAR_CONTROL_SDMMC1; // Enable clock loopback. @@ -3443,7 +3473,7 @@ int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_vol return rc; } - // Default to a timeout of 1S. + // Default to a timeout of 1s. mmc->timeout = 1000000; mmc->partition_switch_time = 1000; diff --git a/fusee/fusee-primary/src/sdmmc.h b/fusee/fusee-primary/src/sdmmc.h index 97fc69f65..63538a405 100644 --- a/fusee/fusee-primary/src/sdmmc.h +++ b/fusee/fusee-primary/src/sdmmc.h @@ -157,7 +157,7 @@ struct mmc { /* Per-controller operations. */ int (*set_up_clock_and_io)(struct mmc *mmc); - void (*configure_clock)(struct mmc *mmc, int source, int car_divisor, int sdmmc_divisor); + void (*configure_clock)(struct mmc *mmc, uint32_t source, int car_divisor, int sdmmc_divisor); int (*enable_supplies)(struct mmc *mmc); int (*switch_to_low_voltage)(struct mmc *mmc); bool (*card_present)(struct mmc *mmc); diff --git a/fusee/fusee-secondary/src/car.h b/fusee/fusee-secondary/src/car.h index 9f62ad2a6..593c7a78a 100644 --- a/fusee/fusee-secondary/src/car.h +++ b/fusee/fusee-secondary/src/car.h @@ -48,11 +48,14 @@ enum { * Masks for TEGRA_CLK_SOURCE elements. */ enum { - CLK_SOURCE_MASK = (0b111 << 29), - CLK_SOURCE_FIRST = (0b000 << 29), + CLK_SOURCE_MASK = (0b111 << 29), + CLK_SOURCE_SDMMC1_PLLP_OUT0 = (0b000 << 29), /* Fixed 408 MHz */ + CLK_SOURCE_SDMMC4_PLLP_OUT0 = (0b000 << 29), /* Fixed 408 MHz */ + CLK_SOURCE_SDMMC4_PLLC4_OUT2_LJ = (0b001 << 29), /* 199.68 MHz */ + CLK_SOURCE_SDMMC_LEGACY_PLLP_OUT0 = (0b100 << 29), /* Fixed 408 MHz */ - CLK_DIVIDER_MASK = (0xff << 0), - CLK_DIVIDER_UNITY = (0x00 << 0), + CLK_DIVIDER_MASK = (0xff << 0), + CLK_DIVIDER_UNITY = (0x00 << 0), }; diff --git a/fusee/fusee-secondary/src/sdmmc.c b/fusee/fusee-secondary/src/sdmmc.c index 1f6879e3a..e34b17f60 100644 --- a/fusee/fusee-secondary/src/sdmmc.c +++ b/fusee/fusee-secondary/src/sdmmc.c @@ -141,34 +141,52 @@ enum sdmmc_clock_dividers { MMC_CLOCK_DIVIDER_SDR12 = 31, // 16.5, from the TRM table MMC_CLOCK_DIVIDER_SDR25 = 15, // 8.5, from the table MMC_CLOCK_DIVIDER_SDR50 = 7, // 4.5, from the table - MMC_CLOCK_DIVIDER_SDR104 = 4, // 2, from the datasheet + MMC_CLOCK_DIVIDER_SDR104 = 2, // 2, from the table /* Clock dividers: MMC */ MMC_CLOCK_DIVIDER_HS26 = 30, // 16, from the TRM table MMC_CLOCK_DIVIDER_HS52 = 14, // 8, from the table - MMC_CLOCK_DIVIDER_HS200 = 2, // 1 -- NOTE THIS IS WITH RESPECT TO PLLC4_OUT2_LJ - MMC_CLOCK_DIVIDER_HS400 = 2, // 1 -- NOTE THIS IS WITH RESPECT TO PLLC4_OUT2_LJ -}; +#if 0 + // TODO: Figure out why PLLC4_OUT2_LJ doesn't work, most likely need to be enabled in hwinit + MMC_CLOCK_DIVIDER_HS200 = 0, // 1 -- NOTE THIS IS WITH RESPECT TO PLLC4_OUT2_LJ + MMC_CLOCK_DIVIDER_HS400 = 0, // 1 -- NOTE THIS IS WITH RESPECT TO PLLC4_OUT2_LJ +#else + MMC_CLOCK_DIVIDER_HS200 = 3, + MMC_CLOCK_DIVIDER_HS400 = 3, +#endif + /* Clock dividers: Legacy 12 MHz timer */ + MMC_CLOCK_DIVIDER_LEGACY = 66, // 34 - to get 12 MHz out of 408 MHz +}; /** * SDMMC clock divider constants */ enum sdmmc_clock_sources { - /* Clock dividers: SD */ - MMC_CLOCK_SOURCE_SDR12 = 0, // PLLP - MMC_CLOCK_SOURCE_SDR25 = 0, - MMC_CLOCK_SOURCE_SDR50 = 0, - MMC_CLOCK_SOURCE_SDR104 = 0, + /* Clock sources: SD */ + MMC_CLOCK_SOURCE_SDR12 = CLK_SOURCE_SDMMC1_PLLP_OUT0, // PLLP + MMC_CLOCK_SOURCE_SDR25 = CLK_SOURCE_SDMMC1_PLLP_OUT0, + MMC_CLOCK_SOURCE_SDR50 = CLK_SOURCE_SDMMC1_PLLP_OUT0, + MMC_CLOCK_SOURCE_SDR104 = CLK_SOURCE_SDMMC1_PLLP_OUT0, - /* Clock dividers: MMC */ - MMC_CLOCK_SOURCE_HS26 = 0, // PLLP - MMC_CLOCK_SOURCE_HS52 = 0, - MMC_CLOCK_SOURCE_HS200 = 1, // PLLC4_OUT2_LJ - MMC_CLOCK_SOURCE_HS400 = 1, + /* Clock sources: MMC */ + MMC_CLOCK_SOURCE_HS26 = CLK_SOURCE_SDMMC4_PLLP_OUT0, // PLLP + MMC_CLOCK_SOURCE_HS52 = CLK_SOURCE_SDMMC4_PLLP_OUT0, +#if 0 + // TODO: Figure out why PLLC4_OUT2_LJ doesn't work, most likely need to be enabled in hwinit + MMC_CLOCK_SOURCE_HS200 = CLK_SOURCE_SDMMC4_PLLC4_OUT2_LJ, // PLLC4_OUT2_LJ + MMC_CLOCK_SOURCE_HS400 = CLK_SOURCE_SDMMC4_PLLC4_OUT2_LJ, +#else + // For the time being, use PLLP_OUT0 + MMC_CLOCK_SOURCE_HS200 = CLK_SOURCE_SDMMC4_PLLP_OUT0, + MMC_CLOCK_SOURCE_HS400 = CLK_SOURCE_SDMMC4_PLLP_OUT0, +#endif + + /* Clock sources: Legacy 12 MHz timer */ + MMC_CLOCK_SOURCE_LEGACY = CLK_SOURCE_SDMMC_LEGACY_PLLP_OUT0, }; /** @@ -239,7 +257,7 @@ enum sdmmc_register_bits { MMC_CLOCK_CONTROL_CARD_CLOCK_ENABLE = (1 << 2), MMC_CLOCK_CONTROL_FREQUENCY_MASK = (0x3FF << 6), MMC_CLOCK_CONTROL_FREQUENCY_SHIFT = 8, - MMC_CLOCK_CONTROL_FREQUENCY_INIT = 0x18, // generates 400kHz from the TRM dividers + MMC_CLOCK_CONTROL_FREQUENCY_INIT = 0x1F, // generates 400kHz from the TRM dividers MMC_CLOCK_CONTROL_FREQUENCY_PASSTHROUGH = 0x00, // passes through the CAR clock unmodified /* Host control */ @@ -797,6 +815,20 @@ static int sdmmc_hardware_reset(struct mmc *mmc, uint32_t reset_flags) return 0; } +/** + * Delays for a given amount of host clock cycles. + * + * @param mmc The MMC controller whose clock cycles should be waited upon. + * @param clocks The number of clock cycles to wait. + */ +static void sdmmc_host_clock_delay(struct mmc *mmc, unsigned int clocks) +{ + // For the time being simply wait for clocks * 50 us + // This covers clocks as slow as 20 kHz and hence should always be safe + // TODO: determine the actual wait time based on clock source and divider + udelay(50 * clocks); +} + /** * Performs low-level initialization for SDMMC4, used for the eMMC. */ @@ -804,23 +836,22 @@ static int sdmmc4_set_up_clock_and_io(struct mmc *mmc) { volatile struct tegra_car *car = car_get_regs(); volatile struct tegra_padctl *padctl = padctl_get_regs(); - (void)mmc; // Put SDMMC4 in reset car->rst_dev_l_set |= 0x8000; // Configure the clock to place the device into the initial mode. - car->clk_src[CLK_SOURCE_SDMMC4] = CLK_SOURCE_FIRST | MMC_CLOCK_DIVIDER_SDR12; + car->clk_src[CLK_SOURCE_SDMMC4] = MMC_CLOCK_SOURCE_SDR12 | MMC_CLOCK_DIVIDER_SDR12; // Set the legacy divier used for detecting timeouts. - car->clk_src_y[CLK_SOURCE_SDMMC_LEGACY] = CLK_SOURCE_FIRST | MMC_CLOCK_DIVIDER_SDR12; + car->clk_src_y[CLK_SOURCE_SDMMC_LEGACY] = MMC_CLOCK_SOURCE_LEGACY | MMC_CLOCK_DIVIDER_LEGACY; // Set SDMMC4 clock enable car->clk_enb_l_set |= 0x8000; car->clk_enb_y_set |= CAR_CONTROL_SDMMC_LEGACY; - // host_clk_delay(0x64, clk_freq) -> Delay 100 host clock cycles - udelay(5000); + // Delay 100 host clock cycles + sdmmc_host_clock_delay(mmc, 100); // Take SDMMC4 out of reset car->rst_dev_l_clr |= 0x8000; @@ -1103,11 +1134,11 @@ static int sdmmc_always_fail(struct mmc *mmc) * a divider of N results in a clock that's (N/2) + 1 slower. * @param sdmmc_divisor An additional divisor applied in the SDMMC controller. */ -static void sdmmc4_configure_clock(struct mmc *mmc, int source, int car_divisor, int sdmmc_divisor) +static void sdmmc4_configure_clock(struct mmc *mmc, uint32_t source, int car_divisor, int sdmmc_divisor) { volatile struct tegra_car *car = car_get_regs(); - // Set up the CAR aspect of the clock, and wait 2uS per change per the TRM. + // Set up the CAR aspect of the clock, and wait 2us per change per the TRM. car->clk_enb_l_clr = CAR_CONTROL_SDMMC4; car->clk_src[CLK_SOURCE_SDMMC4] = source | car_divisor; udelay(2); @@ -1129,11 +1160,11 @@ static void sdmmc4_configure_clock(struct mmc *mmc, int source, int car_divisor, * a divider of N results in a clock that's (N/2) + 1 slower. * @param sdmmc_divisor An additional divisor applied in the SDMMC controller. */ -static void sdmmc1_configure_clock(struct mmc *mmc, int source, int car_divisor, int sdmmc_divisor) +static void sdmmc1_configure_clock(struct mmc *mmc, uint32_t source, int car_divisor, int sdmmc_divisor) { volatile struct tegra_car *car = car_get_regs(); - // Set up the CAR aspect of the clock, and wait 2uS per change per the TRM. + // Set up the CAR aspect of the clock, and wait 2us per change per the TRM. car->clk_enb_l_clr = CAR_CONTROL_SDMMC1; car->clk_src[CLK_SOURCE_SDMMC1] = source | car_divisor; udelay(2); @@ -1470,7 +1501,6 @@ static int sdmmc1_set_up_clock_and_io(struct mmc *mmc) volatile struct tegra_car *car = car_get_regs(); volatile struct tegra_pinmux *pinmux = pinmux_get_regs(); volatile struct tegra_padctl *padctl = padctl_get_regs(); - (void)mmc; // Set up each of the relevant pins to be connected to output drivers, // and selected for SDMMC use. @@ -1494,19 +1524,19 @@ static int sdmmc1_set_up_clock_and_io(struct mmc *mmc) car->rst_dev_l_set = CAR_CONTROL_SDMMC1; // Configure the clock to place the device into the initial mode. - car->clk_src[CLK_SOURCE_SDMMC1] = CLK_SOURCE_FIRST | MMC_CLOCK_DIVIDER_SDR12; + car->clk_src[CLK_SOURCE_SDMMC1] = MMC_CLOCK_SOURCE_SDR12 | MMC_CLOCK_DIVIDER_SDR12; // Set the legacy divier used for detecting timeouts. - car->clk_src_y[CLK_SOURCE_SDMMC_LEGACY] = CLK_SOURCE_FIRST | MMC_CLOCK_DIVIDER_SDR12; + car->clk_src_y[CLK_SOURCE_SDMMC_LEGACY] = MMC_CLOCK_SOURCE_LEGACY | MMC_CLOCK_DIVIDER_LEGACY; // Set SDMMC1 clock enable car->clk_enb_l_set = CAR_CONTROL_SDMMC1; car->clk_enb_y_set = CAR_CONTROL_SDMMC_LEGACY; - // host_clk_delay(0x64, clk_freq) -> Delay 100 host clock cycles - udelay(5000); + // Delay 100 host clock cycles + sdmmc_host_clock_delay(mmc, 100); - // Take SDMMC4 out of reset + // Take SDMMC1 out of reset car->rst_dev_l_clr |= CAR_CONTROL_SDMMC1; // Enable clock loopback. @@ -3444,7 +3474,7 @@ int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_vol return rc; } - // Default to a timeout of 1S. + // Default to a timeout of 1s. mmc->timeout = 1000000; mmc->partition_switch_time = 1000; diff --git a/fusee/fusee-secondary/src/sdmmc.h b/fusee/fusee-secondary/src/sdmmc.h index 97fc69f65..63538a405 100644 --- a/fusee/fusee-secondary/src/sdmmc.h +++ b/fusee/fusee-secondary/src/sdmmc.h @@ -157,7 +157,7 @@ struct mmc { /* Per-controller operations. */ int (*set_up_clock_and_io)(struct mmc *mmc); - void (*configure_clock)(struct mmc *mmc, int source, int car_divisor, int sdmmc_divisor); + void (*configure_clock)(struct mmc *mmc, uint32_t source, int car_divisor, int sdmmc_divisor); int (*enable_supplies)(struct mmc *mmc); int (*switch_to_low_voltage)(struct mmc *mmc); bool (*card_present)(struct mmc *mmc);