949 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Bitmain BM1880 SoC clock driver4 *5 * Copyright (c) 2019 Linaro Ltd.6 * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>7 */8 9#include <linux/clk-provider.h>10#include <linux/io.h>11#include <linux/kernel.h>12#include <linux/mod_devicetable.h>13#include <linux/module.h>14#include <linux/platform_device.h>15#include <linux/slab.h>16 17#include <dt-bindings/clock/bm1880-clock.h>18 19#define BM1880_CLK_MPLL_CTL 0x0020#define BM1880_CLK_SPLL_CTL 0x0421#define BM1880_CLK_FPLL_CTL 0x0822#define BM1880_CLK_DDRPLL_CTL 0x0c23 24#define BM1880_CLK_ENABLE0 0x0025#define BM1880_CLK_ENABLE1 0x0426#define BM1880_CLK_SELECT 0x2027#define BM1880_CLK_DIV0 0x4028#define BM1880_CLK_DIV1 0x4429#define BM1880_CLK_DIV2 0x4830#define BM1880_CLK_DIV3 0x4c31#define BM1880_CLK_DIV4 0x5032#define BM1880_CLK_DIV5 0x5433#define BM1880_CLK_DIV6 0x5834#define BM1880_CLK_DIV7 0x5c35#define BM1880_CLK_DIV8 0x6036#define BM1880_CLK_DIV9 0x6437#define BM1880_CLK_DIV10 0x6838#define BM1880_CLK_DIV11 0x6c39#define BM1880_CLK_DIV12 0x7040#define BM1880_CLK_DIV13 0x7441#define BM1880_CLK_DIV14 0x7842#define BM1880_CLK_DIV15 0x7c43#define BM1880_CLK_DIV16 0x8044#define BM1880_CLK_DIV17 0x8445#define BM1880_CLK_DIV18 0x8846#define BM1880_CLK_DIV19 0x8c47#define BM1880_CLK_DIV20 0x9048#define BM1880_CLK_DIV21 0x9449#define BM1880_CLK_DIV22 0x9850#define BM1880_CLK_DIV23 0x9c51#define BM1880_CLK_DIV24 0xa052#define BM1880_CLK_DIV25 0xa453#define BM1880_CLK_DIV26 0xa854#define BM1880_CLK_DIV27 0xac55#define BM1880_CLK_DIV28 0xb056 57#define to_bm1880_pll_clk(_hw) container_of(_hw, struct bm1880_pll_hw_clock, hw)58#define to_bm1880_div_clk(_hw) container_of(_hw, struct bm1880_div_hw_clock, hw)59 60static DEFINE_SPINLOCK(bm1880_clk_lock);61 62struct bm1880_clock_data {63 void __iomem *pll_base;64 void __iomem *sys_base;65 struct clk_hw_onecell_data hw_data;66};67 68struct bm1880_gate_clock {69 unsigned int id;70 const char *name;71 const char *parent;72 u32 gate_reg;73 s8 gate_shift;74 unsigned long flags;75};76 77struct bm1880_mux_clock {78 unsigned int id;79 const char *name;80 const char * const *parents;81 s8 num_parents;82 u32 reg;83 s8 shift;84 unsigned long flags;85};86 87struct bm1880_div_clock {88 unsigned int id;89 const char *name;90 u32 reg;91 u8 shift;92 u8 width;93 u32 initval;94 const struct clk_div_table *table;95 unsigned long flags;96};97 98struct bm1880_div_hw_clock {99 struct bm1880_div_clock div;100 void __iomem *base;101 spinlock_t *lock;102 struct clk_hw hw;103 struct clk_init_data init;104};105 106struct bm1880_composite_clock {107 unsigned int id;108 const char *name;109 const char *parent;110 const char * const *parents;111 unsigned int num_parents;112 unsigned long flags;113 114 u32 gate_reg;115 u32 mux_reg;116 u32 div_reg;117 118 s8 gate_shift;119 s8 mux_shift;120 s8 div_shift;121 s8 div_width;122 s16 div_initval;123 const struct clk_div_table *table;124};125 126struct bm1880_pll_clock {127 unsigned int id;128 const char *name;129 u32 reg;130 unsigned long flags;131};132 133struct bm1880_pll_hw_clock {134 struct bm1880_pll_clock pll;135 void __iomem *base;136 struct clk_hw hw;137 struct clk_init_data init;138};139 140static const struct clk_ops bm1880_pll_ops;141static const struct clk_ops bm1880_clk_div_ops;142 143#define GATE_DIV(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, \144 _div_shift, _div_width, _div_initval, _table, \145 _flags) { \146 .id = _id, \147 .parent = _parent, \148 .name = _name, \149 .gate_reg = _gate_reg, \150 .gate_shift = _gate_shift, \151 .div_reg = _div_reg, \152 .div_shift = _div_shift, \153 .div_width = _div_width, \154 .div_initval = _div_initval, \155 .table = _table, \156 .mux_shift = -1, \157 .flags = _flags, \158 }159 160#define GATE_MUX(_id, _name, _parents, _gate_reg, _gate_shift, \161 _mux_reg, _mux_shift, _flags) { \162 .id = _id, \163 .parents = _parents, \164 .num_parents = ARRAY_SIZE(_parents), \165 .name = _name, \166 .gate_reg = _gate_reg, \167 .gate_shift = _gate_shift, \168 .div_shift = -1, \169 .mux_reg = _mux_reg, \170 .mux_shift = _mux_shift, \171 .flags = _flags, \172 }173 174#define CLK_PLL(_id, _name, _parent, _reg, _flags) { \175 .pll.id = _id, \176 .pll.name = _name, \177 .pll.reg = _reg, \178 .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parent, \179 &bm1880_pll_ops, \180 _flags), \181 }182 183#define CLK_DIV(_id, _name, _parent, _reg, _shift, _width, _initval, \184 _table, _flags) { \185 .div.id = _id, \186 .div.name = _name, \187 .div.reg = _reg, \188 .div.shift = _shift, \189 .div.width = _width, \190 .div.initval = _initval, \191 .div.table = _table, \192 .hw.init = CLK_HW_INIT_HW(_name, _parent, \193 &bm1880_clk_div_ops, \194 _flags), \195 }196 197static struct clk_parent_data bm1880_pll_parent[] = {198 { .fw_name = "osc", .name = "osc" },199};200 201/*202 * All PLL clocks are marked as CRITICAL, hence they are very crucial203 * for the functioning of the SoC204 */205static struct bm1880_pll_hw_clock bm1880_pll_clks[] = {206 CLK_PLL(BM1880_CLK_MPLL, "clk_mpll", bm1880_pll_parent,207 BM1880_CLK_MPLL_CTL, 0),208 CLK_PLL(BM1880_CLK_SPLL, "clk_spll", bm1880_pll_parent,209 BM1880_CLK_SPLL_CTL, 0),210 CLK_PLL(BM1880_CLK_FPLL, "clk_fpll", bm1880_pll_parent,211 BM1880_CLK_FPLL_CTL, 0),212 CLK_PLL(BM1880_CLK_DDRPLL, "clk_ddrpll", bm1880_pll_parent,213 BM1880_CLK_DDRPLL_CTL, 0),214};215 216/*217 * Clocks marked as CRITICAL are needed for the proper functioning218 * of the SoC.219 */220static const struct bm1880_gate_clock bm1880_gate_clks[] = {221 { BM1880_CLK_AHB_ROM, "clk_ahb_rom", "clk_mux_axi6",222 BM1880_CLK_ENABLE0, 2, 0 },223 { BM1880_CLK_AXI_SRAM, "clk_axi_sram", "clk_axi1",224 BM1880_CLK_ENABLE0, 3, 0 },225 /*226 * Since this clock is sourcing the DDR memory, let's mark it as227 * critical to avoid gating.228 */229 { BM1880_CLK_DDR_AXI, "clk_ddr_axi", "clk_mux_axi6",230 BM1880_CLK_ENABLE0, 4, CLK_IS_CRITICAL },231 { BM1880_CLK_APB_EFUSE, "clk_apb_efuse", "clk_mux_axi6",232 BM1880_CLK_ENABLE0, 6, 0 },233 { BM1880_CLK_AXI5_EMMC, "clk_axi5_emmc", "clk_axi5",234 BM1880_CLK_ENABLE0, 7, 0 },235 { BM1880_CLK_AXI5_SD, "clk_axi5_sd", "clk_axi5",236 BM1880_CLK_ENABLE0, 10, 0 },237 { BM1880_CLK_AXI4_ETH0, "clk_axi4_eth0", "clk_axi4",238 BM1880_CLK_ENABLE0, 14, 0 },239 { BM1880_CLK_AXI4_ETH1, "clk_axi4_eth1", "clk_axi4",240 BM1880_CLK_ENABLE0, 16, 0 },241 { BM1880_CLK_AXI1_GDMA, "clk_axi1_gdma", "clk_axi1",242 BM1880_CLK_ENABLE0, 17, 0 },243 /* Don't gate GPIO clocks as it is not owned by the GPIO driver */244 { BM1880_CLK_APB_GPIO, "clk_apb_gpio", "clk_mux_axi6",245 BM1880_CLK_ENABLE0, 18, CLK_IGNORE_UNUSED },246 { BM1880_CLK_APB_GPIO_INTR, "clk_apb_gpio_intr", "clk_mux_axi6",247 BM1880_CLK_ENABLE0, 19, CLK_IGNORE_UNUSED },248 { BM1880_CLK_AXI1_MINER, "clk_axi1_miner", "clk_axi1",249 BM1880_CLK_ENABLE0, 21, 0 },250 { BM1880_CLK_AHB_SF, "clk_ahb_sf", "clk_mux_axi6",251 BM1880_CLK_ENABLE0, 22, 0 },252 /*253 * Not sure which module this clock is sourcing but gating this clock254 * prevents the system from booting. So, let's mark it as critical.255 */256 { BM1880_CLK_SDMA_AXI, "clk_sdma_axi", "clk_axi5",257 BM1880_CLK_ENABLE0, 23, CLK_IS_CRITICAL },258 { BM1880_CLK_APB_I2C, "clk_apb_i2c", "clk_mux_axi6",259 BM1880_CLK_ENABLE0, 25, 0 },260 { BM1880_CLK_APB_WDT, "clk_apb_wdt", "clk_mux_axi6",261 BM1880_CLK_ENABLE0, 26, 0 },262 { BM1880_CLK_APB_JPEG, "clk_apb_jpeg", "clk_axi6",263 BM1880_CLK_ENABLE0, 27, 0 },264 { BM1880_CLK_AXI5_NF, "clk_axi5_nf", "clk_axi5",265 BM1880_CLK_ENABLE0, 29, 0 },266 { BM1880_CLK_APB_NF, "clk_apb_nf", "clk_axi6",267 BM1880_CLK_ENABLE0, 30, 0 },268 { BM1880_CLK_APB_PWM, "clk_apb_pwm", "clk_mux_axi6",269 BM1880_CLK_ENABLE1, 0, 0 },270 { BM1880_CLK_RV, "clk_rv", "clk_mux_rv",271 BM1880_CLK_ENABLE1, 1, 0 },272 { BM1880_CLK_APB_SPI, "clk_apb_spi", "clk_mux_axi6",273 BM1880_CLK_ENABLE1, 2, 0 },274 { BM1880_CLK_UART_500M, "clk_uart_500m", "clk_div_uart_500m",275 BM1880_CLK_ENABLE1, 4, 0 },276 { BM1880_CLK_APB_UART, "clk_apb_uart", "clk_axi6",277 BM1880_CLK_ENABLE1, 5, 0 },278 { BM1880_CLK_APB_I2S, "clk_apb_i2s", "clk_axi6",279 BM1880_CLK_ENABLE1, 6, 0 },280 { BM1880_CLK_AXI4_USB, "clk_axi4_usb", "clk_axi4",281 BM1880_CLK_ENABLE1, 7, 0 },282 { BM1880_CLK_APB_USB, "clk_apb_usb", "clk_axi6",283 BM1880_CLK_ENABLE1, 8, 0 },284 { BM1880_CLK_12M_USB, "clk_12m_usb", "clk_div_12m_usb",285 BM1880_CLK_ENABLE1, 11, 0 },286 { BM1880_CLK_APB_VIDEO, "clk_apb_video", "clk_axi6",287 BM1880_CLK_ENABLE1, 12, 0 },288 { BM1880_CLK_APB_VPP, "clk_apb_vpp", "clk_axi6",289 BM1880_CLK_ENABLE1, 15, 0 },290 { BM1880_CLK_AXI6, "clk_axi6", "clk_mux_axi6",291 BM1880_CLK_ENABLE1, 21, 0 },292};293 294static const char * const clk_a53_parents[] = { "clk_spll", "clk_mpll" };295static const char * const clk_rv_parents[] = { "clk_div_1_rv", "clk_div_0_rv" };296static const char * const clk_axi1_parents[] = { "clk_div_1_axi1", "clk_div_0_axi1" };297static const char * const clk_axi6_parents[] = { "clk_div_1_axi6", "clk_div_0_axi6" };298 299static const struct bm1880_mux_clock bm1880_mux_clks[] = {300 { BM1880_CLK_MUX_RV, "clk_mux_rv", clk_rv_parents, 2,301 BM1880_CLK_SELECT, 1, 0 },302 { BM1880_CLK_MUX_AXI6, "clk_mux_axi6", clk_axi6_parents, 2,303 BM1880_CLK_SELECT, 3, 0 },304};305 306static const struct clk_div_table bm1880_div_table_0[] = {307 { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },308 { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 },309 { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 },310 { 12, 13 }, { 13, 14 }, { 14, 15 }, { 15, 16 },311 { 16, 17 }, { 17, 18 }, { 18, 19 }, { 19, 20 },312 { 20, 21 }, { 21, 22 }, { 22, 23 }, { 23, 24 },313 { 24, 25 }, { 25, 26 }, { 26, 27 }, { 27, 28 },314 { 28, 29 }, { 29, 30 }, { 30, 31 }, { 31, 32 },315 { 0, 0 }316};317 318static const struct clk_div_table bm1880_div_table_1[] = {319 { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },320 { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 },321 { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 },322 { 12, 13 }, { 13, 14 }, { 14, 15 }, { 15, 16 },323 { 16, 17 }, { 17, 18 }, { 18, 19 }, { 19, 20 },324 { 20, 21 }, { 21, 22 }, { 22, 23 }, { 23, 24 },325 { 24, 25 }, { 25, 26 }, { 26, 27 }, { 27, 28 },326 { 28, 29 }, { 29, 30 }, { 30, 31 }, { 31, 32 },327 { 127, 128 }, { 0, 0 }328};329 330static const struct clk_div_table bm1880_div_table_2[] = {331 { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },332 { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 },333 { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 },334 { 12, 13 }, { 13, 14 }, { 14, 15 }, { 15, 16 },335 { 16, 17 }, { 17, 18 }, { 18, 19 }, { 19, 20 },336 { 20, 21 }, { 21, 22 }, { 22, 23 }, { 23, 24 },337 { 24, 25 }, { 25, 26 }, { 26, 27 }, { 27, 28 },338 { 28, 29 }, { 29, 30 }, { 30, 31 }, { 31, 32 },339 { 127, 128 }, { 255, 256 }, { 0, 0 }340};341 342static const struct clk_div_table bm1880_div_table_3[] = {343 { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },344 { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 },345 { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 },346 { 12, 13 }, { 13, 14 }, { 14, 15 }, { 15, 16 },347 { 16, 17 }, { 17, 18 }, { 18, 19 }, { 19, 20 },348 { 20, 21 }, { 21, 22 }, { 22, 23 }, { 23, 24 },349 { 24, 25 }, { 25, 26 }, { 26, 27 }, { 27, 28 },350 { 28, 29 }, { 29, 30 }, { 30, 31 }, { 31, 32 },351 { 127, 128 }, { 255, 256 }, { 511, 512 }, { 0, 0 }352};353 354static const struct clk_div_table bm1880_div_table_4[] = {355 { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },356 { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 },357 { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 },358 { 12, 13 }, { 13, 14 }, { 14, 15 }, { 15, 16 },359 { 16, 17 }, { 17, 18 }, { 18, 19 }, { 19, 20 },360 { 20, 21 }, { 21, 22 }, { 22, 23 }, { 23, 24 },361 { 24, 25 }, { 25, 26 }, { 26, 27 }, { 27, 28 },362 { 28, 29 }, { 29, 30 }, { 30, 31 }, { 31, 32 },363 { 127, 128 }, { 255, 256 }, { 511, 512 }, { 65535, 65536 },364 { 0, 0 }365};366 367/*368 * Clocks marked as CRITICAL are needed for the proper functioning369 * of the SoC.370 */371static struct bm1880_div_hw_clock bm1880_div_clks[] = {372 CLK_DIV(BM1880_CLK_DIV_0_RV, "clk_div_0_rv", &bm1880_pll_clks[1].hw,373 BM1880_CLK_DIV12, 16, 5, 1, bm1880_div_table_0, 0),374 CLK_DIV(BM1880_CLK_DIV_1_RV, "clk_div_1_rv", &bm1880_pll_clks[2].hw,375 BM1880_CLK_DIV13, 16, 5, 1, bm1880_div_table_0, 0),376 CLK_DIV(BM1880_CLK_DIV_UART_500M, "clk_div_uart_500m", &bm1880_pll_clks[2].hw,377 BM1880_CLK_DIV15, 16, 7, 3, bm1880_div_table_1, 0),378 CLK_DIV(BM1880_CLK_DIV_0_AXI1, "clk_div_0_axi1", &bm1880_pll_clks[0].hw,379 BM1880_CLK_DIV21, 16, 5, 2, bm1880_div_table_0,380 0),381 CLK_DIV(BM1880_CLK_DIV_1_AXI1, "clk_div_1_axi1", &bm1880_pll_clks[2].hw,382 BM1880_CLK_DIV22, 16, 5, 3, bm1880_div_table_0,383 0),384 CLK_DIV(BM1880_CLK_DIV_0_AXI6, "clk_div_0_axi6", &bm1880_pll_clks[2].hw,385 BM1880_CLK_DIV27, 16, 5, 15, bm1880_div_table_0,386 0),387 CLK_DIV(BM1880_CLK_DIV_1_AXI6, "clk_div_1_axi6", &bm1880_pll_clks[0].hw,388 BM1880_CLK_DIV28, 16, 5, 11, bm1880_div_table_0,389 0),390 CLK_DIV(BM1880_CLK_DIV_12M_USB, "clk_div_12m_usb", &bm1880_pll_clks[2].hw,391 BM1880_CLK_DIV18, 16, 7, 125, bm1880_div_table_1, 0),392};393 394/*395 * Clocks marked as CRITICAL are all needed for the proper functioning396 * of the SoC.397 */398static struct bm1880_composite_clock bm1880_composite_clks[] = {399 /*400 * Since clk_a53 and clk_50m_a53 clocks are sourcing the CPU core,401 * let's mark them as critical to avoid gating.402 */403 GATE_MUX(BM1880_CLK_A53, "clk_a53", clk_a53_parents,404 BM1880_CLK_ENABLE0, 0, BM1880_CLK_SELECT, 0,405 CLK_IS_CRITICAL),406 GATE_DIV(BM1880_CLK_50M_A53, "clk_50m_a53", "clk_fpll",407 BM1880_CLK_ENABLE0, 1, BM1880_CLK_DIV0, 16, 5, 30,408 bm1880_div_table_0, CLK_IS_CRITICAL),409 GATE_DIV(BM1880_CLK_EFUSE, "clk_efuse", "clk_fpll",410 BM1880_CLK_ENABLE0, 5, BM1880_CLK_DIV1, 16, 7, 60,411 bm1880_div_table_1, 0),412 GATE_DIV(BM1880_CLK_EMMC, "clk_emmc", "clk_fpll",413 BM1880_CLK_ENABLE0, 8, BM1880_CLK_DIV2, 16, 5, 15,414 bm1880_div_table_0, 0),415 GATE_DIV(BM1880_CLK_100K_EMMC, "clk_100k_emmc", "clk_div_12m_usb",416 BM1880_CLK_ENABLE0, 9, BM1880_CLK_DIV3, 16, 8, 120,417 bm1880_div_table_2, 0),418 GATE_DIV(BM1880_CLK_SD, "clk_sd", "clk_fpll",419 BM1880_CLK_ENABLE0, 11, BM1880_CLK_DIV4, 16, 5, 15,420 bm1880_div_table_0, 0),421 GATE_DIV(BM1880_CLK_100K_SD, "clk_100k_sd", "clk_div_12m_usb",422 BM1880_CLK_ENABLE0, 12, BM1880_CLK_DIV5, 16, 8, 120,423 bm1880_div_table_2, 0),424 GATE_DIV(BM1880_CLK_500M_ETH0, "clk_500m_eth0", "clk_fpll",425 BM1880_CLK_ENABLE0, 13, BM1880_CLK_DIV6, 16, 5, 3,426 bm1880_div_table_0, 0),427 GATE_DIV(BM1880_CLK_500M_ETH1, "clk_500m_eth1", "clk_fpll",428 BM1880_CLK_ENABLE0, 15, BM1880_CLK_DIV7, 16, 5, 3,429 bm1880_div_table_0, 0),430 /* Don't gate GPIO clocks as it is not owned by the GPIO driver */431 GATE_DIV(BM1880_CLK_GPIO_DB, "clk_gpio_db", "clk_div_12m_usb",432 BM1880_CLK_ENABLE0, 20, BM1880_CLK_DIV8, 16, 16, 120,433 bm1880_div_table_4, CLK_IGNORE_UNUSED),434 GATE_DIV(BM1880_CLK_SDMA_AUD, "clk_sdma_aud", "clk_fpll",435 BM1880_CLK_ENABLE0, 24, BM1880_CLK_DIV9, 16, 7, 61,436 bm1880_div_table_1, 0),437 GATE_DIV(BM1880_CLK_JPEG_AXI, "clk_jpeg_axi", "clk_fpll",438 BM1880_CLK_ENABLE0, 28, BM1880_CLK_DIV10, 16, 5, 4,439 bm1880_div_table_0, 0),440 GATE_DIV(BM1880_CLK_NF, "clk_nf", "clk_fpll",441 BM1880_CLK_ENABLE0, 31, BM1880_CLK_DIV11, 16, 5, 30,442 bm1880_div_table_0, 0),443 GATE_DIV(BM1880_CLK_TPU_AXI, "clk_tpu_axi", "clk_spll",444 BM1880_CLK_ENABLE1, 3, BM1880_CLK_DIV14, 16, 5, 1,445 bm1880_div_table_0, 0),446 GATE_DIV(BM1880_CLK_125M_USB, "clk_125m_usb", "clk_fpll",447 BM1880_CLK_ENABLE1, 9, BM1880_CLK_DIV16, 16, 5, 12,448 bm1880_div_table_0, 0),449 GATE_DIV(BM1880_CLK_33K_USB, "clk_33k_usb", "clk_div_12m_usb",450 BM1880_CLK_ENABLE1, 10, BM1880_CLK_DIV17, 16, 9, 363,451 bm1880_div_table_3, 0),452 GATE_DIV(BM1880_CLK_VIDEO_AXI, "clk_video_axi", "clk_fpll",453 BM1880_CLK_ENABLE1, 13, BM1880_CLK_DIV19, 16, 5, 4,454 bm1880_div_table_0, 0),455 GATE_DIV(BM1880_CLK_VPP_AXI, "clk_vpp_axi", "clk_fpll",456 BM1880_CLK_ENABLE1, 14, BM1880_CLK_DIV20, 16, 5, 4,457 bm1880_div_table_0, 0),458 GATE_MUX(BM1880_CLK_AXI1, "clk_axi1", clk_axi1_parents,459 BM1880_CLK_ENABLE1, 15, BM1880_CLK_SELECT, 2, 0),460 GATE_DIV(BM1880_CLK_AXI2, "clk_axi2", "clk_fpll",461 BM1880_CLK_ENABLE1, 17, BM1880_CLK_DIV23, 16, 5, 3,462 bm1880_div_table_0, 0),463 GATE_DIV(BM1880_CLK_AXI3, "clk_axi3", "clk_mux_rv",464 BM1880_CLK_ENABLE1, 18, BM1880_CLK_DIV24, 16, 5, 2,465 bm1880_div_table_0, 0),466 GATE_DIV(BM1880_CLK_AXI4, "clk_axi4", "clk_fpll",467 BM1880_CLK_ENABLE1, 19, BM1880_CLK_DIV25, 16, 5, 6,468 bm1880_div_table_0, 0),469 GATE_DIV(BM1880_CLK_AXI5, "clk_axi5", "clk_fpll",470 BM1880_CLK_ENABLE1, 20, BM1880_CLK_DIV26, 16, 5, 15,471 bm1880_div_table_0, 0),472};473 474static unsigned long bm1880_pll_rate_calc(u32 regval, unsigned long parent_rate)475{476 u64 numerator;477 u32 fbdiv, refdiv;478 u32 postdiv1, postdiv2, denominator;479 480 fbdiv = (regval >> 16) & 0xfff;481 refdiv = regval & 0x1f;482 postdiv1 = (regval >> 8) & 0x7;483 postdiv2 = (regval >> 12) & 0x7;484 485 numerator = parent_rate * fbdiv;486 denominator = refdiv * postdiv1 * postdiv2;487 do_div(numerator, denominator);488 489 return (unsigned long)numerator;490}491 492static unsigned long bm1880_pll_recalc_rate(struct clk_hw *hw,493 unsigned long parent_rate)494{495 struct bm1880_pll_hw_clock *pll_hw = to_bm1880_pll_clk(hw);496 unsigned long rate;497 u32 regval;498 499 regval = readl(pll_hw->base + pll_hw->pll.reg);500 rate = bm1880_pll_rate_calc(regval, parent_rate);501 502 return rate;503}504 505static const struct clk_ops bm1880_pll_ops = {506 .recalc_rate = bm1880_pll_recalc_rate,507};508 509static struct clk_hw *bm1880_clk_register_pll(struct bm1880_pll_hw_clock *pll_clk,510 void __iomem *sys_base)511{512 struct clk_hw *hw;513 int err;514 515 pll_clk->base = sys_base;516 hw = &pll_clk->hw;517 518 err = clk_hw_register(NULL, hw);519 if (err)520 return ERR_PTR(err);521 522 return hw;523}524 525static int bm1880_clk_register_plls(struct bm1880_pll_hw_clock *clks,526 int num_clks,527 struct bm1880_clock_data *data)528{529 struct clk_hw *hw;530 void __iomem *pll_base = data->pll_base;531 int i;532 533 for (i = 0; i < num_clks; i++) {534 struct bm1880_pll_hw_clock *bm1880_clk = &clks[i];535 536 hw = bm1880_clk_register_pll(bm1880_clk, pll_base);537 if (IS_ERR(hw)) {538 pr_err("%s: failed to register clock %s\n",539 __func__, bm1880_clk->pll.name);540 goto err_clk;541 }542 543 data->hw_data.hws[clks[i].pll.id] = hw;544 }545 546 return 0;547 548err_clk:549 while (i--)550 clk_hw_unregister(data->hw_data.hws[clks[i].pll.id]);551 552 return PTR_ERR(hw);553}554 555static int bm1880_clk_register_mux(const struct bm1880_mux_clock *clks,556 int num_clks,557 struct bm1880_clock_data *data)558{559 struct clk_hw *hw;560 void __iomem *sys_base = data->sys_base;561 int i;562 563 for (i = 0; i < num_clks; i++) {564 hw = clk_hw_register_mux(NULL, clks[i].name,565 clks[i].parents,566 clks[i].num_parents,567 clks[i].flags,568 sys_base + clks[i].reg,569 clks[i].shift, 1, 0,570 &bm1880_clk_lock);571 if (IS_ERR(hw)) {572 pr_err("%s: failed to register clock %s\n",573 __func__, clks[i].name);574 goto err_clk;575 }576 577 data->hw_data.hws[clks[i].id] = hw;578 }579 580 return 0;581 582err_clk:583 while (i--)584 clk_hw_unregister_mux(data->hw_data.hws[clks[i].id]);585 586 return PTR_ERR(hw);587}588 589static unsigned long bm1880_clk_div_recalc_rate(struct clk_hw *hw,590 unsigned long parent_rate)591{592 struct bm1880_div_hw_clock *div_hw = to_bm1880_div_clk(hw);593 struct bm1880_div_clock *div = &div_hw->div;594 void __iomem *reg_addr = div_hw->base + div->reg;595 unsigned int val;596 unsigned long rate;597 598 if (!(readl(reg_addr) & BIT(3))) {599 val = div->initval;600 } else {601 val = readl(reg_addr) >> div->shift;602 val &= clk_div_mask(div->width);603 }604 605 rate = divider_recalc_rate(hw, parent_rate, val, div->table,606 div->flags, div->width);607 608 return rate;609}610 611static long bm1880_clk_div_round_rate(struct clk_hw *hw, unsigned long rate,612 unsigned long *prate)613{614 struct bm1880_div_hw_clock *div_hw = to_bm1880_div_clk(hw);615 struct bm1880_div_clock *div = &div_hw->div;616 void __iomem *reg_addr = div_hw->base + div->reg;617 618 if (div->flags & CLK_DIVIDER_READ_ONLY) {619 u32 val;620 621 val = readl(reg_addr) >> div->shift;622 val &= clk_div_mask(div->width);623 624 return divider_ro_round_rate(hw, rate, prate, div->table,625 div->width, div->flags,626 val);627 }628 629 return divider_round_rate(hw, rate, prate, div->table,630 div->width, div->flags);631}632 633static int bm1880_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,634 unsigned long parent_rate)635{636 struct bm1880_div_hw_clock *div_hw = to_bm1880_div_clk(hw);637 struct bm1880_div_clock *div = &div_hw->div;638 void __iomem *reg_addr = div_hw->base + div->reg;639 unsigned long flags = 0;640 int value;641 u32 val;642 643 value = divider_get_val(rate, parent_rate, div->table,644 div->width, div_hw->div.flags);645 if (value < 0)646 return value;647 648 if (div_hw->lock)649 spin_lock_irqsave(div_hw->lock, flags);650 else651 __acquire(div_hw->lock);652 653 val = readl(reg_addr);654 val &= ~(clk_div_mask(div->width) << div_hw->div.shift);655 val |= (u32)value << div->shift;656 writel(val, reg_addr);657 658 if (div_hw->lock)659 spin_unlock_irqrestore(div_hw->lock, flags);660 else661 __release(div_hw->lock);662 663 return 0;664}665 666static const struct clk_ops bm1880_clk_div_ops = {667 .recalc_rate = bm1880_clk_div_recalc_rate,668 .round_rate = bm1880_clk_div_round_rate,669 .set_rate = bm1880_clk_div_set_rate,670};671 672static struct clk_hw *bm1880_clk_register_div(struct bm1880_div_hw_clock *div_clk,673 void __iomem *sys_base)674{675 struct clk_hw *hw;676 int err;677 678 div_clk->div.flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;679 div_clk->base = sys_base;680 div_clk->lock = &bm1880_clk_lock;681 682 hw = &div_clk->hw;683 err = clk_hw_register(NULL, hw);684 if (err)685 return ERR_PTR(err);686 687 return hw;688}689 690static int bm1880_clk_register_divs(struct bm1880_div_hw_clock *clks,691 int num_clks,692 struct bm1880_clock_data *data)693{694 struct clk_hw *hw;695 void __iomem *sys_base = data->sys_base;696 unsigned int i, id;697 698 for (i = 0; i < num_clks; i++) {699 struct bm1880_div_hw_clock *bm1880_clk = &clks[i];700 701 hw = bm1880_clk_register_div(bm1880_clk, sys_base);702 if (IS_ERR(hw)) {703 pr_err("%s: failed to register clock %s\n",704 __func__, bm1880_clk->div.name);705 goto err_clk;706 }707 708 id = clks[i].div.id;709 data->hw_data.hws[id] = hw;710 }711 712 return 0;713 714err_clk:715 while (i--)716 clk_hw_unregister(data->hw_data.hws[clks[i].div.id]);717 718 return PTR_ERR(hw);719}720 721static int bm1880_clk_register_gate(const struct bm1880_gate_clock *clks,722 int num_clks,723 struct bm1880_clock_data *data)724{725 struct clk_hw *hw;726 void __iomem *sys_base = data->sys_base;727 int i;728 729 for (i = 0; i < num_clks; i++) {730 hw = clk_hw_register_gate(NULL, clks[i].name,731 clks[i].parent,732 clks[i].flags,733 sys_base + clks[i].gate_reg,734 clks[i].gate_shift, 0,735 &bm1880_clk_lock);736 if (IS_ERR(hw)) {737 pr_err("%s: failed to register clock %s\n",738 __func__, clks[i].name);739 goto err_clk;740 }741 742 data->hw_data.hws[clks[i].id] = hw;743 }744 745 return 0;746 747err_clk:748 while (i--)749 clk_hw_unregister_gate(data->hw_data.hws[clks[i].id]);750 751 return PTR_ERR(hw);752}753 754static struct clk_hw *bm1880_clk_register_composite(struct bm1880_composite_clock *clks,755 void __iomem *sys_base)756{757 struct clk_hw *hw;758 struct clk_mux *mux = NULL;759 struct clk_gate *gate = NULL;760 struct bm1880_div_hw_clock *div_hws = NULL;761 struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;762 const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL;763 const char * const *parent_names;764 const char *parent;765 int num_parents;766 int ret;767 768 if (clks->mux_shift >= 0) {769 mux = kzalloc(sizeof(*mux), GFP_KERNEL);770 if (!mux)771 return ERR_PTR(-ENOMEM);772 773 mux->reg = sys_base + clks->mux_reg;774 mux->mask = 1;775 mux->shift = clks->mux_shift;776 mux_hw = &mux->hw;777 mux_ops = &clk_mux_ops;778 mux->lock = &bm1880_clk_lock;779 780 parent_names = clks->parents;781 num_parents = clks->num_parents;782 } else {783 parent = clks->parent;784 parent_names = &parent;785 num_parents = 1;786 }787 788 if (clks->gate_shift >= 0) {789 gate = kzalloc(sizeof(*gate), GFP_KERNEL);790 if (!gate) {791 ret = -ENOMEM;792 goto err_out;793 }794 795 gate->reg = sys_base + clks->gate_reg;796 gate->bit_idx = clks->gate_shift;797 gate->lock = &bm1880_clk_lock;798 799 gate_hw = &gate->hw;800 gate_ops = &clk_gate_ops;801 }802 803 if (clks->div_shift >= 0) {804 div_hws = kzalloc(sizeof(*div_hws), GFP_KERNEL);805 if (!div_hws) {806 ret = -ENOMEM;807 goto err_out;808 }809 810 div_hws->base = sys_base;811 div_hws->div.reg = clks->div_reg;812 div_hws->div.shift = clks->div_shift;813 div_hws->div.width = clks->div_width;814 div_hws->div.table = clks->table;815 div_hws->div.initval = clks->div_initval;816 div_hws->lock = &bm1880_clk_lock;817 div_hws->div.flags = CLK_DIVIDER_ONE_BASED |818 CLK_DIVIDER_ALLOW_ZERO;819 820 div_hw = &div_hws->hw;821 div_ops = &bm1880_clk_div_ops;822 }823 824 hw = clk_hw_register_composite(NULL, clks->name, parent_names,825 num_parents, mux_hw, mux_ops, div_hw,826 div_ops, gate_hw, gate_ops,827 clks->flags);828 829 if (IS_ERR(hw)) {830 ret = PTR_ERR(hw);831 goto err_out;832 }833 834 return hw;835 836err_out:837 kfree(div_hws);838 kfree(gate);839 kfree(mux);840 841 return ERR_PTR(ret);842}843 844static int bm1880_clk_register_composites(struct bm1880_composite_clock *clks,845 int num_clks,846 struct bm1880_clock_data *data)847{848 struct clk_hw *hw;849 void __iomem *sys_base = data->sys_base;850 int i;851 852 for (i = 0; i < num_clks; i++) {853 struct bm1880_composite_clock *bm1880_clk = &clks[i];854 855 hw = bm1880_clk_register_composite(bm1880_clk, sys_base);856 if (IS_ERR(hw)) {857 pr_err("%s: failed to register clock %s\n",858 __func__, bm1880_clk->name);859 goto err_clk;860 }861 862 data->hw_data.hws[clks[i].id] = hw;863 }864 865 return 0;866 867err_clk:868 while (i--)869 clk_hw_unregister_composite(data->hw_data.hws[clks[i].id]);870 871 return PTR_ERR(hw);872}873 874static int bm1880_clk_probe(struct platform_device *pdev)875{876 struct bm1880_clock_data *clk_data;877 void __iomem *pll_base, *sys_base;878 struct device *dev = &pdev->dev;879 int num_clks, i;880 881 pll_base = devm_platform_ioremap_resource(pdev, 0);882 if (IS_ERR(pll_base))883 return PTR_ERR(pll_base);884 885 sys_base = devm_platform_ioremap_resource(pdev, 1);886 if (IS_ERR(sys_base))887 return PTR_ERR(sys_base);888 889 num_clks = ARRAY_SIZE(bm1880_pll_clks) +890 ARRAY_SIZE(bm1880_div_clks) +891 ARRAY_SIZE(bm1880_mux_clks) +892 ARRAY_SIZE(bm1880_composite_clks) +893 ARRAY_SIZE(bm1880_gate_clks);894 895 clk_data = devm_kzalloc(dev, struct_size(clk_data, hw_data.hws,896 num_clks), GFP_KERNEL);897 if (!clk_data)898 return -ENOMEM;899 900 clk_data->pll_base = pll_base;901 clk_data->sys_base = sys_base;902 903 for (i = 0; i < num_clks; i++)904 clk_data->hw_data.hws[i] = ERR_PTR(-ENOENT);905 906 clk_data->hw_data.num = num_clks;907 908 bm1880_clk_register_plls(bm1880_pll_clks,909 ARRAY_SIZE(bm1880_pll_clks),910 clk_data);911 912 bm1880_clk_register_divs(bm1880_div_clks,913 ARRAY_SIZE(bm1880_div_clks),914 clk_data);915 916 bm1880_clk_register_mux(bm1880_mux_clks,917 ARRAY_SIZE(bm1880_mux_clks),918 clk_data);919 920 bm1880_clk_register_composites(bm1880_composite_clks,921 ARRAY_SIZE(bm1880_composite_clks),922 clk_data);923 924 bm1880_clk_register_gate(bm1880_gate_clks,925 ARRAY_SIZE(bm1880_gate_clks),926 clk_data);927 928 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,929 &clk_data->hw_data);930}931 932static const struct of_device_id bm1880_of_match[] = {933 { .compatible = "bitmain,bm1880-clk", },934 {}935};936MODULE_DEVICE_TABLE(of, bm1880_of_match);937 938static struct platform_driver bm1880_clk_driver = {939 .driver = {940 .name = "bm1880-clk",941 .of_match_table = bm1880_of_match,942 },943 .probe = bm1880_clk_probe,944};945module_platform_driver(bm1880_clk_driver);946 947MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");948MODULE_DESCRIPTION("Clock driver for Bitmain BM1880 SoC");949