diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index b3ab7f8a9688..71504a81cb0c 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -301,7 +301,7 @@ struct bcm2835_cprman { const char *osc_name; struct clk_onecell_data onecell; - struct clk *clks[BCM2835_CLOCK_COUNT]; + struct clk *clks[]; }; static inline void cprman_write(struct bcm2835_cprman *cprman, u32 reg, u32 val) @@ -850,6 +850,25 @@ static const struct bcm2835_clock_data bcm2835_clock_pwm_data = { .is_mash_clock = true, }; +struct bcm2835_gate_data { + const char *name; + const char *parent; + + u32 ctl_reg; +}; + +/* + * CM_PERIICTL (and CM_PERIACTL, CM_SYSCTL and CM_VPUCTL if + * you have the debug bit set in the power manager, which we + * don't bother exposing) are individual gates off of the + * non-stop vpu clock. + */ +static const struct bcm2835_gate_data bcm2835_clock_peri_image_data = { + .name = "peri_image", + .parent = "vpu", + .ctl_reg = CM_PERIICTL, +}; + struct bcm2835_pll { struct clk_hw hw; struct bcm2835_cprman *cprman; @@ -1642,14 +1661,81 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman, return devm_clk_register(cprman->dev, &clock->hw); } +static struct clk *bcm2835_register_gate(struct bcm2835_cprman *cprman, + const struct bcm2835_gate_data *data) +{ + return clk_register_gate(cprman->dev, data->name, data->parent, + CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, + cprman->regs + data->ctl_reg, + CM_GATE_BIT, 0, &cprman->regs_lock); +} + +typedef struct clk *(*bcm2835_clk_register)(struct bcm2835_cprman *cprman, + const void *data); +struct bcm2835_clk_desc { + bcm2835_clk_register clk_register; + const void *data; +}; + +#define _REGISTER(f, d) { .clk_register = (bcm2835_clk_register)f, \ + .data = d } +#define REGISTER_PLL(d) _REGISTER(&bcm2835_register_pll, d) +#define REGISTER_PLL_DIV(d) _REGISTER(&bcm2835_register_pll_divider, d) +#define REGISTER_CLK(d) _REGISTER(&bcm2835_register_clock, d) +#define REGISTER_GATE(d) _REGISTER(&bcm2835_register_gate, d) + +static const struct bcm2835_clk_desc clk_desc_array[] = { + /* register PLL */ + [BCM2835_PLLA] = REGISTER_PLL(&bcm2835_plla_data), + [BCM2835_PLLB] = REGISTER_PLL(&bcm2835_pllb_data), + [BCM2835_PLLC] = REGISTER_PLL(&bcm2835_pllc_data), + [BCM2835_PLLD] = REGISTER_PLL(&bcm2835_plld_data), + [BCM2835_PLLH] = REGISTER_PLL(&bcm2835_pllh_data), + /* the PLL dividers */ + [BCM2835_PLLA_CORE] = REGISTER_PLL_DIV(&bcm2835_plla_core_data), + [BCM2835_PLLA_PER] = REGISTER_PLL_DIV(&bcm2835_plla_per_data), + [BCM2835_PLLC_CORE0] = REGISTER_PLL_DIV(&bcm2835_pllc_core0_data), + [BCM2835_PLLC_CORE1] = REGISTER_PLL_DIV(&bcm2835_pllc_core1_data), + [BCM2835_PLLC_CORE2] = REGISTER_PLL_DIV(&bcm2835_pllc_core2_data), + [BCM2835_PLLC_PER] = REGISTER_PLL_DIV(&bcm2835_pllc_per_data), + [BCM2835_PLLD_CORE] = REGISTER_PLL_DIV(&bcm2835_plld_core_data), + [BCM2835_PLLD_PER] = REGISTER_PLL_DIV(&bcm2835_plld_per_data), + [BCM2835_PLLH_RCAL] = REGISTER_PLL_DIV(&bcm2835_pllh_rcal_data), + [BCM2835_PLLH_AUX] = REGISTER_PLL_DIV(&bcm2835_pllh_aux_data), + [BCM2835_PLLH_PIX] = REGISTER_PLL_DIV(&bcm2835_pllh_pix_data), + /* the clocks */ + [BCM2835_CLOCK_TIMER] = REGISTER_CLK(&bcm2835_clock_timer_data), + [BCM2835_CLOCK_OTP] = REGISTER_CLK(&bcm2835_clock_otp_data), + [BCM2835_CLOCK_TSENS] = REGISTER_CLK(&bcm2835_clock_tsens_data), + [BCM2835_CLOCK_VPU] = REGISTER_CLK(&bcm2835_clock_vpu_data), + [BCM2835_CLOCK_V3D] = REGISTER_CLK(&bcm2835_clock_v3d_data), + [BCM2835_CLOCK_ISP] = REGISTER_CLK(&bcm2835_clock_isp_data), + [BCM2835_CLOCK_H264] = REGISTER_CLK(&bcm2835_clock_h264_data), + [BCM2835_CLOCK_V3D] = REGISTER_CLK(&bcm2835_clock_v3d_data), + [BCM2835_CLOCK_SDRAM] = REGISTER_CLK(&bcm2835_clock_sdram_data), + [BCM2835_CLOCK_UART] = REGISTER_CLK(&bcm2835_clock_uart_data), + [BCM2835_CLOCK_VEC] = REGISTER_CLK(&bcm2835_clock_vec_data), + [BCM2835_CLOCK_HSM] = REGISTER_CLK(&bcm2835_clock_hsm_data), + [BCM2835_CLOCK_EMMC] = REGISTER_CLK(&bcm2835_clock_emmc_data), + [BCM2835_CLOCK_PWM] = REGISTER_CLK(&bcm2835_clock_pwm_data), + /* the gates */ + [BCM2835_CLOCK_PERI_IMAGE] = REGISTER_GATE( + &bcm2835_clock_peri_image_data), +}; + static int bcm2835_clk_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct clk **clks; struct bcm2835_cprman *cprman; struct resource *res; + const struct bcm2835_clk_desc *desc; + const size_t asize = ARRAY_SIZE(clk_desc_array); + size_t i; - cprman = devm_kzalloc(dev, sizeof(*cprman), GFP_KERNEL); + cprman = devm_kzalloc(dev, + sizeof(*cprman) + asize * sizeof(*clks), + GFP_KERNEL); if (!cprman) return -ENOMEM; @@ -1666,80 +1752,15 @@ static int bcm2835_clk_probe(struct platform_device *pdev) platform_set_drvdata(pdev, cprman); - cprman->onecell.clk_num = BCM2835_CLOCK_COUNT; + cprman->onecell.clk_num = asize; cprman->onecell.clks = cprman->clks; clks = cprman->clks; - clks[BCM2835_PLLA] = bcm2835_register_pll(cprman, &bcm2835_plla_data); - clks[BCM2835_PLLB] = bcm2835_register_pll(cprman, &bcm2835_pllb_data); - clks[BCM2835_PLLC] = bcm2835_register_pll(cprman, &bcm2835_pllc_data); - clks[BCM2835_PLLD] = bcm2835_register_pll(cprman, &bcm2835_plld_data); - clks[BCM2835_PLLH] = bcm2835_register_pll(cprman, &bcm2835_pllh_data); - - clks[BCM2835_PLLA_CORE] = - bcm2835_register_pll_divider(cprman, &bcm2835_plla_core_data); - clks[BCM2835_PLLA_PER] = - bcm2835_register_pll_divider(cprman, &bcm2835_plla_per_data); - clks[BCM2835_PLLC_CORE0] = - bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core0_data); - clks[BCM2835_PLLC_CORE1] = - bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core1_data); - clks[BCM2835_PLLC_CORE2] = - bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core2_data); - clks[BCM2835_PLLC_PER] = - bcm2835_register_pll_divider(cprman, &bcm2835_pllc_per_data); - clks[BCM2835_PLLD_CORE] = - bcm2835_register_pll_divider(cprman, &bcm2835_plld_core_data); - clks[BCM2835_PLLD_PER] = - bcm2835_register_pll_divider(cprman, &bcm2835_plld_per_data); - clks[BCM2835_PLLH_RCAL] = - bcm2835_register_pll_divider(cprman, &bcm2835_pllh_rcal_data); - clks[BCM2835_PLLH_AUX] = - bcm2835_register_pll_divider(cprman, &bcm2835_pllh_aux_data); - clks[BCM2835_PLLH_PIX] = - bcm2835_register_pll_divider(cprman, &bcm2835_pllh_pix_data); - - clks[BCM2835_CLOCK_TIMER] = - bcm2835_register_clock(cprman, &bcm2835_clock_timer_data); - clks[BCM2835_CLOCK_OTP] = - bcm2835_register_clock(cprman, &bcm2835_clock_otp_data); - clks[BCM2835_CLOCK_TSENS] = - bcm2835_register_clock(cprman, &bcm2835_clock_tsens_data); - clks[BCM2835_CLOCK_VPU] = - bcm2835_register_clock(cprman, &bcm2835_clock_vpu_data); - clks[BCM2835_CLOCK_V3D] = - bcm2835_register_clock(cprman, &bcm2835_clock_v3d_data); - clks[BCM2835_CLOCK_ISP] = - bcm2835_register_clock(cprman, &bcm2835_clock_isp_data); - clks[BCM2835_CLOCK_H264] = - bcm2835_register_clock(cprman, &bcm2835_clock_h264_data); - clks[BCM2835_CLOCK_V3D] = - bcm2835_register_clock(cprman, &bcm2835_clock_v3d_data); - clks[BCM2835_CLOCK_SDRAM] = - bcm2835_register_clock(cprman, &bcm2835_clock_sdram_data); - clks[BCM2835_CLOCK_UART] = - bcm2835_register_clock(cprman, &bcm2835_clock_uart_data); - clks[BCM2835_CLOCK_VEC] = - bcm2835_register_clock(cprman, &bcm2835_clock_vec_data); - clks[BCM2835_CLOCK_HSM] = - bcm2835_register_clock(cprman, &bcm2835_clock_hsm_data); - clks[BCM2835_CLOCK_EMMC] = - bcm2835_register_clock(cprman, &bcm2835_clock_emmc_data); - - /* - * CM_PERIICTL (and CM_PERIACTL, CM_SYSCTL and CM_VPUCTL if - * you have the debug bit set in the power manager, which we - * don't bother exposing) are individual gates off of the - * non-stop vpu clock. - */ - clks[BCM2835_CLOCK_PERI_IMAGE] = - clk_register_gate(dev, "peri_image", "vpu", - CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, - cprman->regs + CM_PERIICTL, CM_GATE_BIT, - 0, &cprman->regs_lock); - - clks[BCM2835_CLOCK_PWM] = - bcm2835_register_clock(cprman, &bcm2835_clock_pwm_data); + for (i = 0; i < asize; i++) { + desc = &clk_desc_array[i]; + if (desc->clk_register && desc->data) + clks[i] = desc->clk_register(cprman, desc->data); + } return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, &cprman->onecell); diff --git a/include/dt-bindings/clock/bcm2835.h b/include/dt-bindings/clock/bcm2835.h index 61f1d20c2a67..87235ac76ef1 100644 --- a/include/dt-bindings/clock/bcm2835.h +++ b/include/dt-bindings/clock/bcm2835.h @@ -44,5 +44,3 @@ #define BCM2835_CLOCK_EMMC 28 #define BCM2835_CLOCK_PERI_IMAGE 29 #define BCM2835_CLOCK_PWM 30 - -#define BCM2835_CLOCK_COUNT 31