.name           = "usysclk",
        .id             = -1,
        .parent         = &clk_xtal,
-       .set_parent     = s3c2412_setparent_usysclk,
+       .ops            = &(struct clk_ops) {
+               .set_parent     = s3c2412_setparent_usysclk,
+       },
 };
 
 static struct clk clk_mrefclk = {
 static struct clk clk_usbsrc = {
        .name           = "usbsrc",
        .id             = -1,
-       .get_rate       = s3c2412_getrate_usbsrc,
-       .set_rate       = s3c2412_setrate_usbsrc,
-       .round_rate     = s3c2412_roundrate_usbsrc,
-       .set_parent     = s3c2412_setparent_usbsrc,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s3c2412_getrate_usbsrc,
+               .set_rate       = s3c2412_setrate_usbsrc,
+               .round_rate     = s3c2412_roundrate_usbsrc,
+               .set_parent     = s3c2412_setparent_usbsrc,
+       },
 };
 
 static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent)
 static struct clk clk_msysclk = {
        .name           = "msysclk",
        .id             = -1,
-       .set_parent     = s3c2412_setparent_msysclk,
+       .ops            = &(struct clk_ops) {
+               .set_parent     = s3c2412_setparent_msysclk,
+       },
 };
 
 static int s3c2412_setparent_armclk(struct clk *clk, struct clk *parent)
        .name           = "armclk",
        .id             = -1,
        .parent         = &clk_msysclk,
-       .set_parent     = s3c2412_setparent_armclk,
+       .ops            = &(struct clk_ops) {
+               .set_parent     = s3c2412_setparent_armclk,
+       },
 };
 
 /* these next clocks have an divider immediately after them,
 static struct clk clk_uart = {
        .name           = "uartclk",
        .id             = -1,
-       .get_rate       = s3c2412_getrate_uart,
-       .set_rate       = s3c2412_setrate_uart,
-       .set_parent     = s3c2412_setparent_uart,
-       .round_rate     = s3c2412_roundrate_clksrc,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s3c2412_getrate_uart,
+               .set_rate       = s3c2412_setrate_uart,
+               .set_parent     = s3c2412_setparent_uart,
+               .round_rate     = s3c2412_roundrate_clksrc,
+       },
 };
 
 static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent)
 static struct clk clk_i2s = {
        .name           = "i2sclk",
        .id             = -1,
-       .get_rate       = s3c2412_getrate_i2s,
-       .set_rate       = s3c2412_setrate_i2s,
-       .set_parent     = s3c2412_setparent_i2s,
-       .round_rate     = s3c2412_roundrate_clksrc,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s3c2412_getrate_i2s,
+               .set_rate       = s3c2412_setrate_i2s,
+               .set_parent     = s3c2412_setparent_i2s,
+               .round_rate     = s3c2412_roundrate_clksrc,
+       },
 };
 
 static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent)
 static struct clk clk_cam = {
        .name           = "camif-upll", /* same as 2440 name */
        .id             = -1,
-       .get_rate       = s3c2412_getrate_cam,
-       .set_rate       = s3c2412_setrate_cam,
-       .set_parent     = s3c2412_setparent_cam,
-       .round_rate     = s3c2412_roundrate_clksrc,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s3c2412_getrate_cam,
+               .set_rate       = s3c2412_setrate_cam,
+               .set_parent     = s3c2412_setparent_cam,
+               .round_rate     = s3c2412_roundrate_clksrc,
+       },
 };
 
 /* standard clock definitions */
 
 static struct clk s3c2440_clk_cam_upll = {
        .name           = "camif-upll",
        .id             = -1,
-       .set_rate       = s3c2440_camif_upll_setrate,
-       .round_rate     = s3c2440_camif_upll_round,
+       .ops            = &(struct clk_ops) {
+               .set_rate       = s3c2440_camif_upll_setrate,
+               .round_rate     = s3c2440_camif_upll_round,
+       },
 };
 
 static struct clk s3c2440_clk_ac97 = {
 
 static struct clk s3c2442_clk_cam_upll = {
        .name           = "camif-upll",
        .id             = -1,
-       .set_rate       = s3c2442_camif_upll_setrate,
-       .round_rate     = s3c2442_camif_upll_round,
+       .ops            = &(struct clk_ops) {
+               .set_rate       = s3c2442_camif_upll_setrate,
+               .round_rate     = s3c2442_camif_upll_round,
+       },
 };
 
 static int s3c2442_clk_add(struct sys_device *sysdev)
 
 static struct clk clk_epllref = {
        .name           = "epllref",
        .id             = -1,
-       .set_parent     = s3c2443_setparent_epllref,
+       .ops            = &(struct clk_ops) {
+               .set_parent     = s3c2443_setparent_epllref,
+       },
 };
 
 static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
        .name           = "mdivclk",
        .parent         = &clk_mpllref,
        .id             = -1,
-       .get_rate       = s3c2443_getrate_mdivclk,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s3c2443_getrate_mdivclk,
+       },
 };
 
 static int s3c2443_setparent_msysclk(struct clk *clk, struct clk *parent)
        .name           = "msysclk",
        .parent         = &clk_xtal,
        .id             = -1,
-       .set_parent     = s3c2443_setparent_msysclk,
+       .ops            = &(struct clk_ops) {
+               .set_parent     = s3c2443_setparent_msysclk,
+       },
 };
 
 /* armdiv
 static struct clk clk_arm = {
        .name           = "armclk",
        .id             = -1,
-       .set_parent     = s3c2443_setparent_armclk,
+       .ops            = &(struct clk_ops) {
+               .set_parent     = s3c2443_setparent_armclk,
+       },
 };
 
 /* esysclk
        .name           = "esysclk",
        .parent         = &clk_epll,
        .id             = -1,
-       .set_parent     = s3c2443_setparent_esysclk,
+       .ops            = &(struct clk_ops) {
+               .set_parent     = s3c2443_setparent_esysclk,
+       },
 };
 
 /* uartclk
        .name           = "uartclk",
        .id             = -1,
        .parent         = &clk_esysclk,
-       .get_rate       = s3c2443_getrate_uart,
-       .set_rate       = s3c2443_setrate_uart,
-       .round_rate     = s3c2443_roundrate_clksrc16,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s3c2443_getrate_uart,
+               .set_rate       = s3c2443_setrate_uart,
+               .round_rate     = s3c2443_roundrate_clksrc16,
+       },
 };
 
 /* hsspi
        .parent         = &clk_esysclk,
        .ctrlbit        = S3C2443_SCLKCON_HSSPICLK,
        .enable         = s3c2443_clkcon_enable_s,
-       .get_rate       = s3c2443_getrate_hsspi,
-       .set_rate       = s3c2443_setrate_hsspi,
-       .round_rate     = s3c2443_roundrate_clksrc4,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s3c2443_getrate_hsspi,
+               .set_rate       = s3c2443_setrate_hsspi,
+               .round_rate     = s3c2443_roundrate_clksrc4,
+       },
 };
 
 /* usbhost
        .parent         = &clk_esysclk,
        .ctrlbit        = S3C2443_SCLKCON_USBHOST,
        .enable         = s3c2443_clkcon_enable_s,
-       .get_rate       = s3c2443_getrate_usbhost,
-       .set_rate       = s3c2443_setrate_usbhost,
-       .round_rate     = s3c2443_roundrate_clksrc4,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s3c2443_getrate_usbhost,
+               .set_rate       = s3c2443_setrate_usbhost,
+               .round_rate     = s3c2443_roundrate_clksrc4,
+       },
 };
 
 /* clk_hsmcc_div
        .name           = "hsmmc-div",
        .id             = -1,
        .parent         = &clk_esysclk,
-       .get_rate       = s3c2443_getrate_hsmmc_div,
-       .set_rate       = s3c2443_setrate_hsmmc_div,
-       .round_rate     = s3c2443_roundrate_clksrc4,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s3c2443_getrate_hsmmc_div,
+               .set_rate       = s3c2443_setrate_hsmmc_div,
+               .round_rate     = s3c2443_roundrate_clksrc4,
+       },
 };
 
 static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent)
        .id             = -1,
        .parent         = &clk_hsmmc_div,
        .enable         = s3c2443_enable_hsmmc,
-       .set_parent     = s3c2443_setparent_hsmmc,
+       .ops            = &(struct clk_ops) {
+               .set_parent     = s3c2443_setparent_hsmmc,
+       },
 };
 
 /* i2s_eplldiv
        .name           = "i2s-eplldiv",
        .id             = -1,
        .parent         = &clk_esysclk,
-       .get_rate       = s3c2443_getrate_i2s_eplldiv,
-       .set_rate       = s3c2443_setrate_i2s_eplldiv,
-       .round_rate     = s3c2443_roundrate_clksrc16,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s3c2443_getrate_i2s_eplldiv,
+               .set_rate       = s3c2443_setrate_i2s_eplldiv,
+               .round_rate     = s3c2443_roundrate_clksrc16,
+       },
 };
 
 /* i2s-ref
        .parent         = &clk_i2s_eplldiv,
        .ctrlbit        = S3C2443_SCLKCON_I2SCLK,
        .enable         = s3c2443_clkcon_enable_s,
-       .set_parent     = s3c2443_setparent_i2s,
+       .ops            = &(struct clk_ops) {
+               .set_parent     = s3c2443_setparent_i2s,
+       },
 };
 
 /* cam-if
        .parent         = &clk_esysclk,
        .ctrlbit        = S3C2443_SCLKCON_CAMCLK,
        .enable         = s3c2443_clkcon_enable_s,
-       .get_rate       = s3c2443_getrate_cam,
-       .set_rate       = s3c2443_setrate_cam,
-       .round_rate     = s3c2443_roundrate_clksrc16,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s3c2443_getrate_cam,
+               .set_rate       = s3c2443_setrate_cam,
+               .round_rate     = s3c2443_roundrate_clksrc16,
+       },
 };
 
 /* display-if
        .parent         = &clk_esysclk,
        .ctrlbit        = S3C2443_SCLKCON_DISPCLK,
        .enable         = s3c2443_clkcon_enable_s,
-       .get_rate       = s3c2443_getrate_display,
-       .set_rate       = s3c2443_setrate_display,
-       .round_rate     = s3c2443_roundrate_clksrc256,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s3c2443_getrate_display,
+               .set_rate       = s3c2443_setrate_display,
+               .round_rate     = s3c2443_roundrate_clksrc256,
+       },
 };
 
 /* prediv
        .name           = "prediv",
        .id             = -1,
        .parent         = &clk_msysclk,
-       .get_rate       = s3c2443_prediv_getrate,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s3c2443_prediv_getrate,
+       },
 };
 
 /* standard clock definitions */
 
        if (clk->rate != 0)
                return clk->rate;
 
-       if (clk->get_rate != NULL)
-               return (clk->get_rate)(clk);
+       if (clk->ops != NULL && clk->ops->get_rate != NULL)
+               return (clk->ops->get_rate)(clk);
 
        if (clk->parent != NULL)
                return clk_get_rate(clk->parent);
 
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
-       if (!IS_ERR(clk) && clk->round_rate)
-               return (clk->round_rate)(clk, rate);
+       if (!IS_ERR(clk) && clk->ops && clk->ops->round_rate)
+               return (clk->ops->round_rate)(clk, rate);
 
        return rate;
 }
         * the clock may have been made this way by choice.
         */
 
-       WARN_ON(clk->set_rate == NULL);
+       WARN_ON(clk->ops == NULL);
+       WARN_ON(clk->ops && clk->ops->set_rate == NULL);
 
-       if (clk->set_rate == NULL)
+       if (clk->ops == NULL || clk->ops->set_rate == NULL)
                return -EINVAL;
 
        spin_lock(&clocks_lock);
-       ret = (clk->set_rate)(clk, rate);
+       ret = (clk->ops->set_rate)(clk, rate);
        spin_unlock(&clocks_lock);
 
        return ret;
 
        spin_lock(&clocks_lock);
 
-       if (clk->set_parent)
-               ret = (clk->set_parent)(clk, parent);
+       if (clk->ops && clk->ops->set_parent)
+               ret = (clk->ops->set_parent)(clk, parent);
 
        spin_unlock(&clocks_lock);
 
        return 0;
 }
 
+static struct clk_ops clk_ops_def_setrate = {
+       .set_rate       = clk_default_setrate,
+};
+
 struct clk clk_xtal = {
        .name           = "xtal",
        .id             = -1,
 struct clk clk_mpll = {
        .name           = "mpll",
        .id             = -1,
-       .set_rate       = clk_default_setrate,
+       .ops            = &clk_ops_def_setrate,
 };
 
 struct clk clk_upll = {
        .rate           = 0,
        .parent         = &clk_mpll,
        .ctrlbit        = 0,
-       .set_rate       = clk_default_setrate,
 };
 
 struct clk clk_h = {
        .rate           = 0,
        .parent         = NULL,
        .ctrlbit        = 0,
-       .set_rate       = clk_default_setrate,
+       .ops            = &clk_ops_def_setrate,
 };
 
 struct clk clk_p = {
        .rate           = 0,
        .parent         = NULL,
        .ctrlbit        = 0,
-       .set_rate       = clk_default_setrate,
+       .ops            = &clk_ops_def_setrate,
 };
 
 struct clk clk_usb_bus = {
 };
 
 
-
 struct clk s3c24xx_uclk = {
        .name           = "uclk",
        .id             = -1,
 
        return 0;
 }
 
+static struct clk_ops clk_pwm_scaler_ops = {
+       .get_rate       = clk_pwm_scaler_get_rate,
+       .set_rate       = clk_pwm_scaler_set_rate,
+       .round_rate     = clk_pwm_scaler_round_rate,
+};
+
 static struct clk clk_timer_scaler[] = {
        [0]     = {
                .name           = "pwm-scaler0",
                .id             = -1,
-               .get_rate       = clk_pwm_scaler_get_rate,
-               .set_rate       = clk_pwm_scaler_set_rate,
-               .round_rate     = clk_pwm_scaler_round_rate,
+               .ops            = &clk_pwm_scaler_ops,
        },
        [1]     = {
                .name           = "pwm-scaler1",
                .id             = -1,
-               .get_rate       = clk_pwm_scaler_get_rate,
-               .set_rate       = clk_pwm_scaler_set_rate,
-               .round_rate     = clk_pwm_scaler_round_rate,
+               .ops            = &clk_pwm_scaler_ops,
        },
 };
 
        return 0;
 }
 
+static struct clk_ops clk_tdiv_ops = {
+       .get_rate       = clk_pwm_tdiv_get_rate,
+       .set_rate       = clk_pwm_tdiv_set_rate,
+       .round_rate     = clk_pwm_tdiv_round_rate,
+};
+
 static struct pwm_tdiv_clk clk_timer_tdiv[] = {
        [0]     = {
                .clk    = {
-                       .name           = "pwm-tdiv",
-                       .parent         = &clk_timer_scaler[0],
-                       .get_rate       = clk_pwm_tdiv_get_rate,
-                       .set_rate       = clk_pwm_tdiv_set_rate,
-                       .round_rate     = clk_pwm_tdiv_round_rate,
+                       .name   = "pwm-tdiv",
+                       .ops    = &clk_tdiv_ops,
+                       .parent = &clk_timer_scaler[0],
                },
        },
        [1]     = {
                .clk    = {
-                       .name           = "pwm-tdiv",
-                       .parent         = &clk_timer_scaler[0],
-                       .get_rate       = clk_pwm_tdiv_get_rate,
-                       .set_rate       = clk_pwm_tdiv_set_rate,
-                       .round_rate     = clk_pwm_tdiv_round_rate,
+                       .name   = "pwm-tdiv",
+                       .ops    = &clk_tdiv_ops,
+                       .parent = &clk_timer_scaler[0],
                }
        },
        [2]     = {
                .clk    = {
-                       .name           = "pwm-tdiv",
-                       .parent         = &clk_timer_scaler[1],
-                       .get_rate       = clk_pwm_tdiv_get_rate,
-                       .set_rate       = clk_pwm_tdiv_set_rate,
-                       .round_rate     = clk_pwm_tdiv_round_rate,
+                       .name   = "pwm-tdiv",
+                       .ops    = &clk_tdiv_ops,
+                       .parent = &clk_timer_scaler[1],
                },
        },
        [3]     = {
                .clk    = {
-                       .name           = "pwm-tdiv",
-                       .parent         = &clk_timer_scaler[1],
-                       .get_rate       = clk_pwm_tdiv_get_rate,
-                       .set_rate       = clk_pwm_tdiv_set_rate,
-                       .round_rate     = clk_pwm_tdiv_round_rate,
+                       .name   = "pwm-tdiv",
+                       .ops    = &clk_tdiv_ops,
+                       .parent = &clk_timer_scaler[1],
                },
        },
        [4]     = {
                .clk    = {
-                       .name           = "pwm-tdiv",
-                       .parent         = &clk_timer_scaler[1],
-                       .get_rate       = clk_pwm_tdiv_get_rate,
-                       .set_rate       = clk_pwm_tdiv_set_rate,
-                       .round_rate     = clk_pwm_tdiv_round_rate,
+                       .name   = "pwm-tdiv",
+                       .ops    = &clk_tdiv_ops,
+                       .parent = &clk_timer_scaler[1],
                },
        },
 };
        return 0;
 }
 
+static struct clk_ops clk_tin_ops = {
+       .set_parent     = clk_pwm_tin_set_parent,
+};
+
 static struct clk clk_tin[] = {
        [0]     = {
-               .name           = "pwm-tin",
-               .id             = 0,
-               .set_parent     = clk_pwm_tin_set_parent,
+               .name   = "pwm-tin",
+               .id     = 0,
+               .ops    = &clk_tin_ops,
        },
        [1]     = {
-               .name           = "pwm-tin",
-               .id             = 1,
-               .set_parent     = clk_pwm_tin_set_parent,
+               .name   = "pwm-tin",
+               .id     = 1,
+               .ops    = &clk_tin_ops,
        },
        [2]     = {
-               .name           = "pwm-tin",
-               .id             = 2,
-               .set_parent     = clk_pwm_tin_set_parent,
+               .name   = "pwm-tin",
+               .id     = 2,
+               .ops    = &clk_tin_ops,
        },
        [3]     = {
-               .name           = "pwm-tin",
-               .id             = 3,
-               .set_parent     = clk_pwm_tin_set_parent,
+               .name   = "pwm-tin",
+               .id     = 3,
+               .ops    = &clk_tin_ops,
        },
        [4]     = {
-               .name           = "pwm-tin",
-               .id             = 4,
-               .set_parent     = clk_pwm_tin_set_parent,
+               .name   = "pwm-tin",
+               .id     = 4,
+               .ops    = &clk_tin_ops,
        },
 };
 
 
 
 /* external clock definitions */
 
+static struct clk_ops dclk_ops = {
+       .set_parent     = s3c24xx_dclk_setparent,
+       .set_rate       = s3c24xx_set_dclk_rate,
+       .round_rate     = s3c24xx_round_dclk_rate,
+};
+
 struct clk s3c24xx_dclk0 = {
        .name           = "dclk0",
        .id             = -1,
        .ctrlbit        = S3C2410_DCLKCON_DCLK0EN,
        .enable         = s3c24xx_dclk_enable,
-       .set_parent     = s3c24xx_dclk_setparent,
-       .set_rate       = s3c24xx_set_dclk_rate,
-       .round_rate     = s3c24xx_round_dclk_rate,
+       .ops            = &dclk_ops,
 };
 
 struct clk s3c24xx_dclk1 = {
        .id             = -1,
        .ctrlbit        = S3C2410_DCLKCON_DCLK1EN,
        .enable         = s3c24xx_dclk_enable,
-       .set_parent     = s3c24xx_dclk_setparent,
-       .set_rate       = s3c24xx_set_dclk_rate,
-       .round_rate     = s3c24xx_round_dclk_rate,
+       .ops            = &dclk_ops,
+};
+
+static struct clk_ops clkout_ops = {
+       .set_parent     = s3c24xx_clkout_setparent,
 };
 
 struct clk s3c24xx_clkout0 = {
        .name           = "clkout0",
        .id             = -1,
-       .set_parent     = s3c24xx_clkout_setparent,
+       .ops            = &clkout_ops,
 };
 
 struct clk s3c24xx_clkout1 = {
        .name           = "clkout1",
        .id             = -1,
-       .set_parent     = s3c24xx_clkout_setparent,
+       .ops            = &clkout_ops,
 };
 
 static struct clk clk_arm = {
        .name           = "armclk",
        .id             = -1,
-       .set_parent     = s3c2440_setparent_armclk,
+       .ops            = &(struct clk_ops) {
+               .set_parent     = s3c2440_setparent_armclk,
+       },
 };
 
 static int s3c244x_clk_add(struct sys_device *sysdev)
 
        .name           = "armclk",
        .id             = -1,
        .parent         = &clk_mout_apll.clk,
-       .get_rate       = s3c64xx_clk_arm_get_rate,
-       .set_rate       = s3c64xx_clk_arm_set_rate,
-       .round_rate     = s3c64xx_clk_arm_round_rate,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s3c64xx_clk_arm_get_rate,
+               .set_rate       = s3c64xx_clk_arm_set_rate,
+               .round_rate     = s3c64xx_clk_arm_round_rate,
+       },
 };
 
 static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
        return rate;
 }
 
+static struct clk_ops clk_dout_ops = {
+       .get_rate       = s3c64xx_clk_doutmpll_get_rate,
+};
+
 static struct clk clk_dout_mpll = {
        .name           = "dout_mpll",
        .id             = -1,
        .parent         = &clk_mout_mpll.clk,
-       .get_rate       = s3c64xx_clk_doutmpll_get_rate,
+       .ops            = &clk_dout_ops,
 };
 
 static struct clk *clkset_spi_mmc_list[] = {
 
        return 0;
 }
 
+static struct clk_ops clk_ops_default_setrate = {
+       .set_rate       = clk_default_setrate,
+};
+
 static int clk_dummy_enable(struct clk *clk, int enable)
 {
        return 0;
        .rate           = 0,
        .parent         = NULL,
        .ctrlbit        = 0,
-       .set_rate       = clk_default_setrate,
        .enable         = clk_dummy_enable,
+       .ops            = &clk_ops_default_setrate,
 };
 
 struct clk clk_pd0 = {
        .rate           = 0,
        .parent         = NULL,
        .ctrlbit        = 0,
-       .set_rate       = clk_default_setrate,
+       .ops            = &clk_ops_default_setrate,
        .enable         = clk_dummy_enable,
 };
 
 
        .name           = "dout_apll",
        .id             = -1,
        .parent         = &clk_mout_apll.clk,
-       .get_rate       = s5pc100_clk_dout_apll_get_rate,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s5pc100_clk_dout_apll_get_rate,
+       },
 };
 
 static unsigned long s5pc100_clk_arm_get_rate(struct clk *clk)
        .name           = "armclk",
        .id             = -1,
        .parent         = &clk_dout_apll,
-       .get_rate       = s5pc100_clk_arm_get_rate,
-       .set_rate       = s5pc100_clk_arm_set_rate,
-       .round_rate     = s5pc100_clk_arm_round_rate,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s5pc100_clk_arm_get_rate,
+               .set_rate       = s5pc100_clk_arm_set_rate,
+               .round_rate     = s5pc100_clk_arm_round_rate,
+       },
 };
 
 static unsigned long s5pc100_clk_dout_d0_bus_get_rate(struct clk *clk)
        .name           = "dout_d0_bus",
        .id             = -1,
        .parent         = &clk_arm,
-       .get_rate       = s5pc100_clk_dout_d0_bus_get_rate,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s5pc100_clk_dout_d0_bus_get_rate,
+       },
 };
 
 static unsigned long s5pc100_clk_dout_pclkd0_get_rate(struct clk *clk)
        .name           = "dout_pclkd0",
        .id             = -1,
        .parent         = &clk_dout_d0_bus,
-       .get_rate       = s5pc100_clk_dout_pclkd0_get_rate,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s5pc100_clk_dout_pclkd0_get_rate,
+       },
 };
 
 static unsigned long s5pc100_clk_dout_apll2_get_rate(struct clk *clk)
        .name           = "dout_apll2",
        .id             = -1,
        .parent         = &clk_mout_apll.clk,
-       .get_rate       = s5pc100_clk_dout_apll2_get_rate,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s5pc100_clk_dout_apll2_get_rate,
+       },
 };
 
 /* MPLL */
        .name           = "dout_d1_bus",
        .id             = -1,
        .parent         = &clk_mout_am.clk,
-       .get_rate       = s5pc100_clk_dout_d1_bus_get_rate,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s5pc100_clk_dout_d1_bus_get_rate,
+       },
 };
 
 static struct clk *clkset_onenand_list[] = {
        .name           = "dout_pclkd1",
        .id             = -1,
        .parent         = &clk_dout_d1_bus,
-       .get_rate       = s5pc100_clk_dout_pclkd1_get_rate,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s5pc100_clk_dout_pclkd1_get_rate,
+       },
 };
 
 static unsigned long s5pc100_clk_dout_mpll2_get_rate(struct clk *clk)
        .name           = "dout_mpll2",
        .id             = -1,
        .parent         = &clk_mout_am.clk,
-       .get_rate       = s5pc100_clk_dout_mpll2_get_rate,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s5pc100_clk_dout_mpll2_get_rate,
+       },
 };
 
 static unsigned long s5pc100_clk_dout_cam_get_rate(struct clk *clk)
        .name           = "dout_cam",
        .id             = -1,
        .parent         = &clk_dout_mpll2,
-       .get_rate       = s5pc100_clk_dout_cam_get_rate,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s5pc100_clk_dout_cam_get_rate,
+       },
 };
 
 static unsigned long s5pc100_clk_dout_mpll_get_rate(struct clk *clk)
        .name           = "dout_mpll",
        .id             = -1,
        .parent         = &clk_mout_am.clk,
-       .get_rate       = s5pc100_clk_dout_mpll_get_rate,
+       .ops            = &(struct clk_ops) {
+               .get_rate       = s5pc100_clk_dout_mpll_get_rate,
+       },
 };
 
 /* EPLL */
        return rate;
 }
 
+static struct clk_ops s5pc100_clksrc_ops = {
+       .set_parent     = s5pc100_setparent_clksrc,
+       .get_rate       = s5pc100_getrate_clksrc,
+       .set_rate       = s5pc100_setrate_clksrc,
+       .round_rate     = s5pc100_roundrate_clksrc,
+};
+
 static struct clk *clkset_spi_list[] = {
        &clk_mout_epll.clk,
        &clk_dout_mpll2,
                .id             = 0,
                .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI0,
                .enable         = s5pc100_sclk0_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+
        },
        .shift          = S5PC100_CLKSRC1_SPI0_SHIFT,
        .mask           = S5PC100_CLKSRC1_SPI0_MASK,
                .id             = 1,
                .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI1,
                .enable         = s5pc100_sclk0_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+               .ops            = &s5pc100_clksrc_ops,
        },
        .shift          = S5PC100_CLKSRC1_SPI1_SHIFT,
        .mask           = S5PC100_CLKSRC1_SPI1_MASK,
                .id             = 2,
                .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI2,
                .enable         = s5pc100_sclk0_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+               .ops            = &s5pc100_clksrc_ops,
        },
        .shift          = S5PC100_CLKSRC1_SPI2_SHIFT,
        .mask           = S5PC100_CLKSRC1_SPI2_MASK,
                .id             = -1,
                .ctrlbit        = S5PC100_CLKGATE_SCLK0_UART,
                .enable         = s5pc100_sclk0_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+               .ops            = &s5pc100_clksrc_ops,
        },
        .shift          = S5PC100_CLKSRC1_UART_SHIFT,
        .mask           = S5PC100_CLKSRC1_UART_MASK,
                .id             = 0,
                .ctrlbit        = S5PC100_CLKGATE_SCLK1_AUDIO0,
                .enable         = s5pc100_sclk1_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+               .ops            = &s5pc100_clksrc_ops,
        },
        .shift          = S5PC100_CLKSRC3_AUDIO0_SHIFT,
        .mask           = S5PC100_CLKSRC3_AUDIO0_MASK,
                .id             = 1,
                .ctrlbit        = S5PC100_CLKGATE_SCLK1_AUDIO1,
                .enable         = s5pc100_sclk1_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+               .ops            = &s5pc100_clksrc_ops,
        },
        .shift          = S5PC100_CLKSRC3_AUDIO1_SHIFT,
        .mask           = S5PC100_CLKSRC3_AUDIO1_MASK,
                .id             = 2,
                .ctrlbit        = S5PC100_CLKGATE_SCLK1_AUDIO2,
                .enable         = s5pc100_sclk1_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+               .ops            = &s5pc100_clksrc_ops,
        },
        .shift          = S5PC100_CLKSRC3_AUDIO2_SHIFT,
        .mask           = S5PC100_CLKSRC3_AUDIO2_MASK,
                .id             = -1,
                .ctrlbit        = S5PC100_CLKGATE_SCLK1_LCD,
                .enable         = s5pc100_sclk1_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+               .ops            = &s5pc100_clksrc_ops,
        },
        .shift          = S5PC100_CLKSRC2_LCD_SHIFT,
        .mask           = S5PC100_CLKSRC2_LCD_MASK,
                .id             = 0,
                .ctrlbit        = S5PC100_CLKGATE_SCLK1_FIMC0,
                .enable         = s5pc100_sclk1_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+               .ops            = &s5pc100_clksrc_ops,
        },
        .shift          = S5PC100_CLKSRC2_FIMC0_SHIFT,
        .mask           = S5PC100_CLKSRC2_FIMC0_MASK,
                .id             = 1,
                .ctrlbit        = S5PC100_CLKGATE_SCLK1_FIMC1,
                .enable         = s5pc100_sclk1_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+               .ops            = &s5pc100_clksrc_ops,
        },
        .shift          = S5PC100_CLKSRC2_FIMC1_SHIFT,
        .mask           = S5PC100_CLKSRC2_FIMC1_MASK,
                .id             = 2,
                .ctrlbit        = S5PC100_CLKGATE_SCLK1_FIMC2,
                .enable         = s5pc100_sclk1_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+               .ops            = &s5pc100_clksrc_ops,
        },
        .shift          = S5PC100_CLKSRC2_FIMC2_SHIFT,
        .mask           = S5PC100_CLKSRC2_FIMC2_MASK,
                .id             = 0,
                .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC0,
                .enable         = s5pc100_sclk0_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+               .ops            = &s5pc100_clksrc_ops,
        },
        .shift          = S5PC100_CLKSRC2_MMC0_SHIFT,
        .mask           = S5PC100_CLKSRC2_MMC0_MASK,
                .id             = 1,
                .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC1,
                .enable         = s5pc100_sclk0_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+               .ops            = &s5pc100_clksrc_ops,
        },
        .shift          = S5PC100_CLKSRC2_MMC1_SHIFT,
        .mask           = S5PC100_CLKSRC2_MMC1_MASK,
                .id             = 2,
                .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC2,
                .enable         = s5pc100_sclk0_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+               .ops            = &s5pc100_clksrc_ops,
        },
        .shift          = S5PC100_CLKSRC2_MMC2_SHIFT,
        .mask           = S5PC100_CLKSRC2_MMC2_MASK,
                .id             = -1,
                .ctrlbit        = S5PC100_CLKGATE_SCLK0_USBHOST,
                .enable         = s5pc100_sclk0_ctrl,
-               .set_parent     = s5pc100_setparent_clksrc,
-               .get_rate       = s5pc100_getrate_clksrc,
-               .set_rate       = s5pc100_setrate_clksrc,
-               .round_rate     = s5pc100_roundrate_clksrc,
+               .ops            = &s5pc100_clksrc_ops,
        },
        .shift          = S5PC100_CLKSRC1_UHOST_SHIFT,
        .mask           = S5PC100_CLKSRC1_UHOST_MASK,
 
               clk_get_rate(&clk->clk));
 }
 
+static struct clk_ops clksrc_ops = {
+       .set_parent     = s3c_setparent_clksrc,
+       .get_rate       = s3c_getrate_clksrc,
+       .set_rate       = s3c_setrate_clksrc,
+       .round_rate     = s3c_roundrate_clksrc,
+};
+
 void __init s3c_register_clksrc(struct clksrc_clk *clksrc, int size)
 {
        int ret;
 
        for (; size > 0; size--, clksrc++) {
                /* fill in the default functions */
-               if (!clksrc->clk.set_parent)
-                       clksrc->clk.set_parent = s3c_setparent_clksrc;
-               if (!clksrc->clk.get_rate)
-                       clksrc->clk.get_rate = s3c_getrate_clksrc;
-               if (!clksrc->clk.set_rate)
-                       clksrc->clk.set_rate = s3c_setrate_clksrc;
-               if (!clksrc->clk.round_rate)
-                       clksrc->clk.round_rate = s3c_roundrate_clksrc;
+               if (!clksrc->clk.ops)
+                       clksrc->clk.ops = &clksrc_ops;
 
                s3c_set_clksrc(clksrc);
 
 
 
 #include <linux/spinlock.h>
 
+struct clk;
+
+/**
+ * struct clk_ops - standard clock operations
+ * @set_rate: set the clock rate, see clk_set_rate().
+ * @get_rate: get the clock rate, see clk_get_rate().
+ * @round_rate: round a given clock rate, see clk_round_rate().
+ * @set_parent: set the clock's parent, see clk_set_parent().
+ *
+ * Group the common clock implementations together so that we
+ * don't have to keep setting the same fiels again. We leave
+ * enable in struct clk.
+ *
+ * Adding an extra layer of indirection into the process should
+ * not be a problem as it is unlikely these operations are going
+ * to need to be called quickly.
+ */
+struct clk_ops {
+       int                 (*set_rate)(struct clk *c, unsigned long rate);
+       unsigned long       (*get_rate)(struct clk *c);
+       unsigned long       (*round_rate)(struct clk *c, unsigned long rate);
+       int                 (*set_parent)(struct clk *c, struct clk *parent);
+};
+
 struct clk {
        struct list_head      list;
        struct module        *owner;
        unsigned long         rate;
        unsigned long         ctrlbit;
 
+       struct clk_ops          *ops;
        int                 (*enable)(struct clk *, int enable);
-       int                 (*set_rate)(struct clk *c, unsigned long rate);
-       unsigned long       (*get_rate)(struct clk *c);
-       unsigned long       (*round_rate)(struct clk *c, unsigned long rate);
-       int                 (*set_parent)(struct clk *c, struct clk *parent);
 };
 
 /* other clocks which may be registered by board support */