|
@@ -45,8 +45,8 @@ static unsigned long rockchip_mmc_recalc(struct clk_hw *hw,
|
|
|
#define PSECS_PER_SEC 1000000000000LL
|
|
|
|
|
|
/*
|
|
|
- * Each fine delay is between 40ps-80ps. Assume each fine delay is 60ps to
|
|
|
- * simplify calculations. So 45degs could be anywhere between 33deg and 66deg.
|
|
|
+ * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
|
|
|
+ * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
|
|
|
*/
|
|
|
#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
|
|
|
|
|
@@ -84,22 +84,37 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
|
|
|
u32 raw_value;
|
|
|
u64 delay;
|
|
|
|
|
|
- /* allow 22 to be 22.5 */
|
|
|
- degrees++;
|
|
|
- /* floor to 22.5 increment */
|
|
|
- degrees -= ((degrees) * 10 % 225) / 10;
|
|
|
-
|
|
|
nineties = degrees / 90;
|
|
|
- /* 22.5 multiples */
|
|
|
- remainder = (degrees % 90) / 22;
|
|
|
-
|
|
|
+ remainder = (degrees % 90);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Due to the inexact nature of the "fine" delay, we might
|
|
|
+ * actually go non-monotonic. We don't go _too_ monotonic
|
|
|
+ * though, so we should be OK. Here are options of how we may
|
|
|
+ * work:
|
|
|
+ *
|
|
|
+ * Ideally we end up with:
|
|
|
+ * 1.0, 2.0, ..., 69.0, 70.0, ..., 89.0, 90.0
|
|
|
+ *
|
|
|
+ * On one extreme (if delay is actually 44ps):
|
|
|
+ * .73, 1.5, ..., 50.6, 51.3, ..., 65.3, 90.0
|
|
|
+ * The other (if delay is actually 77ps):
|
|
|
+ * 1.3, 2.6, ..., 88.6. 89.8, ..., 114.0, 90
|
|
|
+ *
|
|
|
+ * It's possible we might make a delay that is up to 25
|
|
|
+ * degrees off from what we think we're making. That's OK
|
|
|
+ * though because we should be REALLY far from any bad range.
|
|
|
+ */
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Convert to delay; do a little extra work to make sure we
|
|
|
+ * don't overflow 32-bit / 64-bit numbers.
|
|
|
+ */
|
|
|
delay = PSECS_PER_SEC;
|
|
|
- do_div(delay, rate);
|
|
|
- /* / 360 / 22.5 */
|
|
|
- do_div(delay, 16);
|
|
|
- do_div(delay, ROCKCHIP_MMC_DELAY_ELEMENT_PSEC);
|
|
|
-
|
|
|
delay *= remainder;
|
|
|
+ do_div(delay, 10000);
|
|
|
+ do_div(delay, (rate / 1000) * 36 * ROCKCHIP_MMC_DELAY_ELEMENT_PSEC);
|
|
|
+
|
|
|
delay_num = (u8) min(delay, 255ULL);
|
|
|
|
|
|
raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
|