u8                      width;
 
        u32                     max;
+       u32                     offset;
 
        u32                     flags;
 
 #define _SUNXI_CCU_DIV_TABLE(_shift, _width, _table)                   \
        _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, 0)
 
-#define _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, _flags) \
+#define _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _off, _max, _flags) \
        {                                                               \
                .shift  = _shift,                                       \
                .width  = _width,                                       \
                .flags  = _flags,                                       \
                .max    = _max,                                         \
+               .offset = _off,                                         \
        }
 
+#define _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, _flags)         \
+       _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, 1, _max, _flags)
+
 #define _SUNXI_CCU_DIV_FLAGS(_shift, _width, _flags)                   \
        _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, 0, _flags)
 
 #define _SUNXI_CCU_DIV_MAX(_shift, _width, _max)                       \
        _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, 0)
 
+#define _SUNXI_CCU_DIV_OFFSET(_shift, _width, _offset)                 \
+       _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _offset, 0, 0)
+
 #define _SUNXI_CCU_DIV(_shift, _width)                                 \
        _SUNXI_CCU_DIV_FLAGS(_shift, _width, 0)
 
 
 
        m = reg >> cmp->m.shift;
        m &= (1 << cmp->m.width) - 1;
+       m += cmp->m.offset;
+       if (!m)
+               m++;
 
        p = reg >> cmp->p.shift;
        p &= (1 << cmp->p.width) - 1;
 
-       return (parent_rate >> p) / (m + 1);
+       return (parent_rate >> p) / m;
 }
 
 static int ccu_mp_determine_rate(struct clk_hw *hw,
        reg = readl(cmp->common.base + cmp->common.reg);
        reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);
        reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
+       reg |= (m - cmp->m.offset) << cmp->m.shift;
+       reg |= ilog2(p) << cmp->p.shift;
 
-       writel(reg | (ilog2(p) << cmp->p.shift) | ((m - 1) << cmp->m.shift),
-              cmp->common.base + cmp->common.reg);
+       writel(reg, cmp->common.base + cmp->common.reg);
 
        spin_unlock_irqrestore(cmp->common.lock, flags);
 
 
        ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1,
                                                &parent_rate);
 
-       return parent_rate * (val + 1);
+       return parent_rate * (val + cm->mult.offset);
 }
 
 static int ccu_mult_determine_rate(struct clk_hw *hw,
 
        reg = readl(cm->common.base + cm->common.reg);
        reg &= ~GENMASK(cm->mult.width + cm->mult.shift - 1, cm->mult.shift);
+       reg |= ((_cm.mult - cm->mult.offset) << cm->mult.shift);
 
-       writel(reg | ((_cm.mult - 1) << cm->mult.shift),
-              cm->common.base + cm->common.reg);
+       writel(reg, cm->common.base + cm->common.reg);
 
        spin_unlock_irqrestore(cm->common.lock, flags);
 
 
 #include "ccu_mux.h"
 
 struct ccu_mult_internal {
+       u8      offset;
        u8      shift;
        u8      width;
        u8      min;
 };
 
-#define _SUNXI_CCU_MULT_MIN(_shift, _width, _min)      \
-       {                                               \
-               .shift  = _shift,                       \
-               .width  = _width,                       \
-               .min    = _min,                         \
+#define _SUNXI_CCU_MULT_OFFSET_MIN(_shift, _width, _offset, _min)      \
+       {                                                               \
+               .min    = _min,                                         \
+               .offset = _offset,                                      \
+               .shift  = _shift,                                       \
+               .width  = _width,                                       \
        }
 
+#define _SUNXI_CCU_MULT_MIN(_shift, _width, _min)      \
+       _SUNXI_CCU_MULT_OFFSET_MIN(_shift, _width, 1, _min)
+
+#define _SUNXI_CCU_MULT_OFFSET(_shift, _width, _offset)        \
+       _SUNXI_CCU_MULT_OFFSET_MIN(_shift, _width, _offset, 1)
+
 #define _SUNXI_CCU_MULT(_shift, _width)                \
-       _SUNXI_CCU_MULT_MIN(_shift, _width, 1)
+       _SUNXI_CCU_MULT_OFFSET_MIN(_shift, _width, 1, 1)
 
 struct ccu_mult {
        u32                     enable;
 
 
        n = reg >> nk->n.shift;
        n &= (1 << nk->n.width) - 1;
+       n += nk->n.offset;
+       if (!n)
+               n++;
 
        k = reg >> nk->k.shift;
        k &= (1 << nk->k.width) - 1;
+       k += nk->k.offset;
+       if (!k)
+               k++;
 
-       rate = parent_rate * (n + 1) * (k + 1);
-
+       rate = parent_rate * n * k;
        if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
                rate /= nk->fixed_post_div;
 
        reg &= ~GENMASK(nk->n.width + nk->n.shift - 1, nk->n.shift);
        reg &= ~GENMASK(nk->k.width + nk->k.shift - 1, nk->k.shift);
 
-       writel(reg | ((_nk.k - 1) << nk->k.shift) | ((_nk.n - 1) << nk->n.shift),
-              nk->common.base + nk->common.reg);
+       reg |= (_nk.k - nk->k.offset) << nk->k.shift;
+       reg |= (_nk.n - nk->n.offset) << nk->n.shift;
+       writel(reg, nk->common.base + nk->common.reg);
 
        spin_unlock_irqrestore(nk->common.lock, flags);
 
 
 
        n = reg >> nkm->n.shift;
        n &= (1 << nkm->n.width) - 1;
+       n += nkm->n.offset;
+       if (!n)
+               n++;
 
        k = reg >> nkm->k.shift;
        k &= (1 << nkm->k.width) - 1;
+       k += nkm->k.offset;
+       if (!k)
+               k++;
 
        m = reg >> nkm->m.shift;
        m &= (1 << nkm->m.width) - 1;
+       m += nkm->m.offset;
+       if (!m)
+               m++;
 
-       return parent_rate * (n + 1) * (k + 1) / (m + 1);
+       return parent_rate * n  * k / m;
 }
 
 static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
        reg &= ~GENMASK(nkm->k.width + nkm->k.shift - 1, nkm->k.shift);
        reg &= ~GENMASK(nkm->m.width + nkm->m.shift - 1, nkm->m.shift);
 
-       reg |= (_nkm.n - 1) << nkm->n.shift;
-       reg |= (_nkm.k - 1) << nkm->k.shift;
-       reg |= (_nkm.m - 1) << nkm->m.shift;
-
+       reg |= (_nkm.n - nkm->n.offset) << nkm->n.shift;
+       reg |= (_nkm.k - nkm->k.offset) << nkm->k.shift;
+       reg |= (_nkm.m - nkm->m.offset) << nkm->m.shift;
        writel(reg, nkm->common.base + nkm->common.reg);
 
        spin_unlock_irqrestore(nkm->common.lock, flags);
 
 
        n = reg >> nkmp->n.shift;
        n &= (1 << nkmp->n.width) - 1;
+       n += nkmp->n.offset;
+       if (!n)
+               n++;
 
        k = reg >> nkmp->k.shift;
        k &= (1 << nkmp->k.width) - 1;
+       k += nkmp->k.offset;
+       if (!k)
+               k++;
 
        m = reg >> nkmp->m.shift;
        m &= (1 << nkmp->m.width) - 1;
+       m += nkmp->m.offset;
+       if (!m)
+               m++;
 
        p = reg >> nkmp->p.shift;
        p &= (1 << nkmp->p.width) - 1;
 
-       return (parent_rate * (n + 1) * (k + 1) >> p) / (m + 1);
+       return parent_rate * n * k >> p / m;
 }
 
 static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
        reg &= ~GENMASK(nkmp->m.width + nkmp->m.shift - 1, nkmp->m.shift);
        reg &= ~GENMASK(nkmp->p.width + nkmp->p.shift - 1, nkmp->p.shift);
 
-       reg |= (_nkmp.n - 1) << nkmp->n.shift;
-       reg |= (_nkmp.k - 1) << nkmp->k.shift;
-       reg |= (_nkmp.m - 1) << nkmp->m.shift;
+       reg |= (_nkmp.n - nkmp->n.offset) << nkmp->n.shift;
+       reg |= (_nkmp.k - nkmp->k.offset) << nkmp->k.shift;
+       reg |= (_nkmp.m - nkmp->m.offset) << nkmp->m.shift;
        reg |= ilog2(_nkmp.p) << nkmp->p.shift;
 
        writel(reg, nkmp->common.base + nkmp->common.reg);
 
 
        n = reg >> nm->n.shift;
        n &= (1 << nm->n.width) - 1;
+       n += nm->n.offset;
+       if (!n)
+               n++;
 
        m = reg >> nm->m.shift;
        m &= (1 << nm->m.width) - 1;
+       m += nm->m.offset;
+       if (!m)
+               m++;
 
-       return parent_rate * (n + 1) / (m + 1);
+       return parent_rate * n / m;
 }
 
 static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
        reg &= ~GENMASK(nm->n.width + nm->n.shift - 1, nm->n.shift);
        reg &= ~GENMASK(nm->m.width + nm->m.shift - 1, nm->m.shift);
 
-       writel(reg | ((_nm.m - 1) << nm->m.shift) | ((_nm.n - 1) << nm->n.shift),
-              nm->common.base + nm->common.reg);
+       reg |= (_nm.n - nm->n.offset) << nm->n.shift;
+       reg |= (_nm.m - nm->m.offset) << nm->m.shift;
+       writel(reg, nm->common.base + nm->common.reg);
 
        spin_unlock_irqrestore(nm->common.lock, flags);