#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/module.h>
-#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <dt-bindings/clock/bcm2835.h>
 #define LOCK_TIMEOUT_NS                100000000
 #define BCM2835_MAX_FB_RATE    1750000000u
 
+#define SOC_BCM2835            BIT(0)
+#define SOC_ALL                        (SOC_BCM2835)
+
 /*
  * Names of clocks used within the driver that need to be replaced
  * with an external parent's name.  This array is in the order that
        struct clk_hw_onecell_data onecell;
 };
 
+struct cprman_plat_data {
+       unsigned int soc;
+};
+
 static inline void cprman_write(struct bcm2835_cprman *cprman, u32 reg, u32 val)
 {
        writel(CM_PASSWORD | val, cprman->regs + reg);
                                               const void *data);
 struct bcm2835_clk_desc {
        bcm2835_clk_register clk_register;
+       unsigned int supported;
        const void *data;
 };
 
 /* assignment helper macros for different clock types */
-#define _REGISTER(f, ...) { .clk_register = (bcm2835_clk_register)f, \
-                           .data = __VA_ARGS__ }
-#define REGISTER_PLL(...)      _REGISTER(&bcm2835_register_pll,        \
+#define _REGISTER(f, s, ...) { .clk_register = (bcm2835_clk_register)f, \
+                              .supported = s,                          \
+                              .data = __VA_ARGS__ }
+#define REGISTER_PLL(s, ...)   _REGISTER(&bcm2835_register_pll,        \
+                                         s,                            \
                                          &(struct bcm2835_pll_data)    \
                                          {__VA_ARGS__})
-#define REGISTER_PLL_DIV(...)  _REGISTER(&bcm2835_register_pll_divider, \
-                                         &(struct bcm2835_pll_divider_data) \
-                                         {__VA_ARGS__})
-#define REGISTER_CLK(...)      _REGISTER(&bcm2835_register_clock,      \
+#define REGISTER_PLL_DIV(s, ...) _REGISTER(&bcm2835_register_pll_divider, \
+                                          s,                             \
+                                          &(struct bcm2835_pll_divider_data) \
+                                          {__VA_ARGS__})
+#define REGISTER_CLK(s, ...)   _REGISTER(&bcm2835_register_clock,      \
+                                         s,                            \
                                          &(struct bcm2835_clock_data)  \
                                          {__VA_ARGS__})
-#define REGISTER_GATE(...)     _REGISTER(&bcm2835_register_gate,       \
+#define REGISTER_GATE(s, ...)  _REGISTER(&bcm2835_register_gate,       \
+                                         s,                            \
                                          &(struct bcm2835_gate_data)   \
                                          {__VA_ARGS__})
 
        "testdebug1"
 };
 
-#define REGISTER_OSC_CLK(...)  REGISTER_CLK(                           \
+#define REGISTER_OSC_CLK(s, ...)       REGISTER_CLK(                   \
+       s,                                                              \
        .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents),       \
        .parents = bcm2835_clock_osc_parents,                           \
        __VA_ARGS__)
        "pllh_aux",
 };
 
-#define REGISTER_PER_CLK(...)  REGISTER_CLK(                           \
+#define REGISTER_PER_CLK(s, ...)       REGISTER_CLK(                   \
+       s,                                                              \
        .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),       \
        .parents = bcm2835_clock_per_parents,                           \
        __VA_ARGS__)
        "-",
 };
 
-#define REGISTER_PCM_CLK(...)  REGISTER_CLK(                           \
+#define REGISTER_PCM_CLK(s, ...)       REGISTER_CLK(                   \
+       s,                                                              \
        .num_mux_parents = ARRAY_SIZE(bcm2835_pcm_per_parents),         \
        .parents = bcm2835_pcm_per_parents,                             \
        __VA_ARGS__)
        "pllc_core2",
 };
 
-#define REGISTER_VPU_CLK(...)  REGISTER_CLK(                           \
+#define REGISTER_VPU_CLK(s, ...)       REGISTER_CLK(                   \
+       s,                                                              \
        .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),       \
        .parents = bcm2835_clock_vpu_parents,                           \
        __VA_ARGS__)
        "dsi1_byte_inv",
 };
 
-#define REGISTER_DSI0_CLK(...) REGISTER_CLK(                           \
+#define REGISTER_DSI0_CLK(s, ...)      REGISTER_CLK(                   \
+       s,                                                              \
        .num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi0_parents),      \
        .parents = bcm2835_clock_dsi0_parents,                          \
        __VA_ARGS__)
 
-#define REGISTER_DSI1_CLK(...) REGISTER_CLK(                           \
+#define REGISTER_DSI1_CLK(s, ...)      REGISTER_CLK(                   \
+       s,                                                              \
        .num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi1_parents),      \
        .parents = bcm2835_clock_dsi1_parents,                          \
        __VA_ARGS__)
         * AUDIO domain is on.
         */
        [BCM2835_PLLA]          = REGISTER_PLL(
+               SOC_ALL,
                .name = "plla",
                .cm_ctrl_reg = CM_PLLA,
                .a2w_ctrl_reg = A2W_PLLA_CTRL,
                .max_rate = 2400000000u,
                .max_fb_rate = BCM2835_MAX_FB_RATE),
        [BCM2835_PLLA_CORE]     = REGISTER_PLL_DIV(
+               SOC_ALL,
                .name = "plla_core",
                .source_pll = "plla",
                .cm_reg = CM_PLLA,
                .fixed_divider = 1,
                .flags = CLK_SET_RATE_PARENT),
        [BCM2835_PLLA_PER]      = REGISTER_PLL_DIV(
+               SOC_ALL,
                .name = "plla_per",
                .source_pll = "plla",
                .cm_reg = CM_PLLA,
                .fixed_divider = 1,
                .flags = CLK_SET_RATE_PARENT),
        [BCM2835_PLLA_DSI0]     = REGISTER_PLL_DIV(
+               SOC_ALL,
                .name = "plla_dsi0",
                .source_pll = "plla",
                .cm_reg = CM_PLLA,
                .hold_mask = CM_PLLA_HOLDDSI0,
                .fixed_divider = 1),
        [BCM2835_PLLA_CCP2]     = REGISTER_PLL_DIV(
+               SOC_ALL,
                .name = "plla_ccp2",
                .source_pll = "plla",
                .cm_reg = CM_PLLA,
         * AUDIO domain is on.
         */
        [BCM2835_PLLC]          = REGISTER_PLL(
+               SOC_ALL,
                .name = "pllc",
                .cm_ctrl_reg = CM_PLLC,
                .a2w_ctrl_reg = A2W_PLLC_CTRL,
                .max_rate = 3000000000u,
                .max_fb_rate = BCM2835_MAX_FB_RATE),
        [BCM2835_PLLC_CORE0]    = REGISTER_PLL_DIV(
+               SOC_ALL,
                .name = "pllc_core0",
                .source_pll = "pllc",
                .cm_reg = CM_PLLC,
                .fixed_divider = 1,
                .flags = CLK_SET_RATE_PARENT),
        [BCM2835_PLLC_CORE1]    = REGISTER_PLL_DIV(
+               SOC_ALL,
                .name = "pllc_core1",
                .source_pll = "pllc",
                .cm_reg = CM_PLLC,
                .fixed_divider = 1,
                .flags = CLK_SET_RATE_PARENT),
        [BCM2835_PLLC_CORE2]    = REGISTER_PLL_DIV(
+               SOC_ALL,
                .name = "pllc_core2",
                .source_pll = "pllc",
                .cm_reg = CM_PLLC,
                .fixed_divider = 1,
                .flags = CLK_SET_RATE_PARENT),
        [BCM2835_PLLC_PER]      = REGISTER_PLL_DIV(
+               SOC_ALL,
                .name = "pllc_per",
                .source_pll = "pllc",
                .cm_reg = CM_PLLC,
         * AUDIO domain is on.
         */
        [BCM2835_PLLD]          = REGISTER_PLL(
+               SOC_ALL,
                .name = "plld",
                .cm_ctrl_reg = CM_PLLD,
                .a2w_ctrl_reg = A2W_PLLD_CTRL,
                .max_rate = 2400000000u,
                .max_fb_rate = BCM2835_MAX_FB_RATE),
        [BCM2835_PLLD_CORE]     = REGISTER_PLL_DIV(
+               SOC_ALL,
                .name = "plld_core",
                .source_pll = "plld",
                .cm_reg = CM_PLLD,
                .fixed_divider = 1,
                .flags = CLK_SET_RATE_PARENT),
        [BCM2835_PLLD_PER]      = REGISTER_PLL_DIV(
+               SOC_ALL,
                .name = "plld_per",
                .source_pll = "plld",
                .cm_reg = CM_PLLD,
                .fixed_divider = 1,
                .flags = CLK_SET_RATE_PARENT),
        [BCM2835_PLLD_DSI0]     = REGISTER_PLL_DIV(
+               SOC_ALL,
                .name = "plld_dsi0",
                .source_pll = "plld",
                .cm_reg = CM_PLLD,
                .hold_mask = CM_PLLD_HOLDDSI0,
                .fixed_divider = 1),
        [BCM2835_PLLD_DSI1]     = REGISTER_PLL_DIV(
+               SOC_ALL,
                .name = "plld_dsi1",
                .source_pll = "plld",
                .cm_reg = CM_PLLD,
         * It is in the HDMI power domain.
         */
        [BCM2835_PLLH]          = REGISTER_PLL(
+               SOC_BCM2835,
                "pllh",
                .cm_ctrl_reg = CM_PLLH,
                .a2w_ctrl_reg = A2W_PLLH_CTRL,
                .max_rate = 3000000000u,
                .max_fb_rate = BCM2835_MAX_FB_RATE),
        [BCM2835_PLLH_RCAL]     = REGISTER_PLL_DIV(
+               SOC_BCM2835,
                .name = "pllh_rcal",
                .source_pll = "pllh",
                .cm_reg = CM_PLLH,
                .fixed_divider = 10,
                .flags = CLK_SET_RATE_PARENT),
        [BCM2835_PLLH_AUX]      = REGISTER_PLL_DIV(
+               SOC_BCM2835,
                .name = "pllh_aux",
                .source_pll = "pllh",
                .cm_reg = CM_PLLH,
                .fixed_divider = 1,
                .flags = CLK_SET_RATE_PARENT),
        [BCM2835_PLLH_PIX]      = REGISTER_PLL_DIV(
+               SOC_BCM2835,
                .name = "pllh_pix",
                .source_pll = "pllh",
                .cm_reg = CM_PLLH,
 
        /* One Time Programmable Memory clock.  Maximum 10Mhz. */
        [BCM2835_CLOCK_OTP]     = REGISTER_OSC_CLK(
+               SOC_ALL,
                .name = "otp",
                .ctl_reg = CM_OTPCTL,
                .div_reg = CM_OTPDIV,
         * bythe watchdog timer and the camera pulse generator.
         */
        [BCM2835_CLOCK_TIMER]   = REGISTER_OSC_CLK(
+               SOC_ALL,
                .name = "timer",
                .ctl_reg = CM_TIMERCTL,
                .div_reg = CM_TIMERDIV,
         * Generally run at 2Mhz, max 5Mhz.
         */
        [BCM2835_CLOCK_TSENS]   = REGISTER_OSC_CLK(
+               SOC_ALL,
                .name = "tsens",
                .ctl_reg = CM_TSENSCTL,
                .div_reg = CM_TSENSDIV,
                .int_bits = 5,
                .frac_bits = 0),
        [BCM2835_CLOCK_TEC]     = REGISTER_OSC_CLK(
+               SOC_ALL,
                .name = "tec",
                .ctl_reg = CM_TECCTL,
                .div_reg = CM_TECDIV,
 
        /* clocks with vpu parent mux */
        [BCM2835_CLOCK_H264]    = REGISTER_VPU_CLK(
+               SOC_ALL,
                .name = "h264",
                .ctl_reg = CM_H264CTL,
                .div_reg = CM_H264DIV,
                .frac_bits = 8,
                .tcnt_mux = 1),
        [BCM2835_CLOCK_ISP]     = REGISTER_VPU_CLK(
+               SOC_ALL,
                .name = "isp",
                .ctl_reg = CM_ISPCTL,
                .div_reg = CM_ISPDIV,
         * in the SDRAM controller can't be used.
         */
        [BCM2835_CLOCK_SDRAM]   = REGISTER_VPU_CLK(
+               SOC_ALL,
                .name = "sdram",
                .ctl_reg = CM_SDCCTL,
                .div_reg = CM_SDCDIV,
                .frac_bits = 0,
                .tcnt_mux = 3),
        [BCM2835_CLOCK_V3D]     = REGISTER_VPU_CLK(
+               SOC_ALL,
                .name = "v3d",
                .ctl_reg = CM_V3DCTL,
                .div_reg = CM_V3DDIV,
         * in various hardware documentation.
         */
        [BCM2835_CLOCK_VPU]     = REGISTER_VPU_CLK(
+               SOC_ALL,
                .name = "vpu",
                .ctl_reg = CM_VPUCTL,
                .div_reg = CM_VPUDIV,
 
        /* clocks with per parent mux */
        [BCM2835_CLOCK_AVEO]    = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "aveo",
                .ctl_reg = CM_AVEOCTL,
                .div_reg = CM_AVEODIV,
                .frac_bits = 0,
                .tcnt_mux = 38),
        [BCM2835_CLOCK_CAM0]    = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "cam0",
                .ctl_reg = CM_CAM0CTL,
                .div_reg = CM_CAM0DIV,
                .frac_bits = 8,
                .tcnt_mux = 14),
        [BCM2835_CLOCK_CAM1]    = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "cam1",
                .ctl_reg = CM_CAM1CTL,
                .div_reg = CM_CAM1DIV,
                .frac_bits = 8,
                .tcnt_mux = 15),
        [BCM2835_CLOCK_DFT]     = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "dft",
                .ctl_reg = CM_DFTCTL,
                .div_reg = CM_DFTDIV,
                .int_bits = 5,
                .frac_bits = 0),
        [BCM2835_CLOCK_DPI]     = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "dpi",
                .ctl_reg = CM_DPICTL,
                .div_reg = CM_DPIDIV,
 
        /* Arasan EMMC clock */
        [BCM2835_CLOCK_EMMC]    = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "emmc",
                .ctl_reg = CM_EMMCCTL,
                .div_reg = CM_EMMCDIV,
 
        /* General purpose (GPIO) clocks */
        [BCM2835_CLOCK_GP0]     = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "gp0",
                .ctl_reg = CM_GP0CTL,
                .div_reg = CM_GP0DIV,
                .is_mash_clock = true,
                .tcnt_mux = 20),
        [BCM2835_CLOCK_GP1]     = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "gp1",
                .ctl_reg = CM_GP1CTL,
                .div_reg = CM_GP1DIV,
                .is_mash_clock = true,
                .tcnt_mux = 21),
        [BCM2835_CLOCK_GP2]     = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "gp2",
                .ctl_reg = CM_GP2CTL,
                .div_reg = CM_GP2DIV,
 
        /* HDMI state machine */
        [BCM2835_CLOCK_HSM]     = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "hsm",
                .ctl_reg = CM_HSMCTL,
                .div_reg = CM_HSMDIV,
                .frac_bits = 8,
                .tcnt_mux = 22),
        [BCM2835_CLOCK_PCM]     = REGISTER_PCM_CLK(
+               SOC_ALL,
                .name = "pcm",
                .ctl_reg = CM_PCMCTL,
                .div_reg = CM_PCMDIV,
                .low_jitter = true,
                .tcnt_mux = 23),
        [BCM2835_CLOCK_PWM]     = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "pwm",
                .ctl_reg = CM_PWMCTL,
                .div_reg = CM_PWMDIV,
                .is_mash_clock = true,
                .tcnt_mux = 24),
        [BCM2835_CLOCK_SLIM]    = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "slim",
                .ctl_reg = CM_SLIMCTL,
                .div_reg = CM_SLIMDIV,
                .is_mash_clock = true,
                .tcnt_mux = 25),
        [BCM2835_CLOCK_SMI]     = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "smi",
                .ctl_reg = CM_SMICTL,
                .div_reg = CM_SMIDIV,
                .frac_bits = 8,
                .tcnt_mux = 27),
        [BCM2835_CLOCK_UART]    = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "uart",
                .ctl_reg = CM_UARTCTL,
                .div_reg = CM_UARTDIV,
 
        /* TV encoder clock.  Only operating frequency is 108Mhz.  */
        [BCM2835_CLOCK_VEC]     = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "vec",
                .ctl_reg = CM_VECCTL,
                .div_reg = CM_VECDIV,
 
        /* dsi clocks */
        [BCM2835_CLOCK_DSI0E]   = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "dsi0e",
                .ctl_reg = CM_DSI0ECTL,
                .div_reg = CM_DSI0EDIV,
                .frac_bits = 8,
                .tcnt_mux = 18),
        [BCM2835_CLOCK_DSI1E]   = REGISTER_PER_CLK(
+               SOC_ALL,
                .name = "dsi1e",
                .ctl_reg = CM_DSI1ECTL,
                .div_reg = CM_DSI1EDIV,
                .frac_bits = 8,
                .tcnt_mux = 19),
        [BCM2835_CLOCK_DSI0P]   = REGISTER_DSI0_CLK(
+               SOC_ALL,
                .name = "dsi0p",
                .ctl_reg = CM_DSI0PCTL,
                .div_reg = CM_DSI0PDIV,
                .frac_bits = 0,
                .tcnt_mux = 12),
        [BCM2835_CLOCK_DSI1P]   = REGISTER_DSI1_CLK(
+               SOC_ALL,
                .name = "dsi1p",
                .ctl_reg = CM_DSI1PCTL,
                .div_reg = CM_DSI1PDIV,
         * non-stop vpu clock.
         */
        [BCM2835_CLOCK_PERI_IMAGE] = REGISTER_GATE(
+               SOC_ALL,
                .name = "peri_image",
                .parent = "vpu",
                .ctl_reg = CM_PERIICTL),
        struct resource *res;
        const struct bcm2835_clk_desc *desc;
        const size_t asize = ARRAY_SIZE(clk_desc_array);
+       const struct cprman_plat_data *pdata;
        size_t i;
        int ret;
 
+       pdata = of_device_get_match_data(&pdev->dev);
+       if (!pdata)
+               return -ENODEV;
+
        cprman = devm_kzalloc(dev,
                              struct_size(cprman, onecell.hws, asize),
                              GFP_KERNEL);
 
        for (i = 0; i < asize; i++) {
                desc = &clk_desc_array[i];
-               if (desc->clk_register && desc->data)
+               if (desc->clk_register && desc->data &&
+                   (desc->supported & pdata->soc)) {
                        hws[i] = desc->clk_register(cprman, desc->data);
+               }
        }
 
        ret = bcm2835_mark_sdc_parent_critical(hws[BCM2835_CLOCK_SDRAM]->clk);
                                      &cprman->onecell);
 }
 
+static const struct cprman_plat_data cprman_bcm2835_plat_data = {
+       .soc = SOC_BCM2835,
+};
+
 static const struct of_device_id bcm2835_clk_of_match[] = {
-       { .compatible = "brcm,bcm2835-cprman", },
+       { .compatible = "brcm,bcm2835-cprman", .data = &cprman_bcm2835_plat_data },
        {}
 };
 MODULE_DEVICE_TABLE(of, bcm2835_clk_of_match);