cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

clk-hi3559a.c (24077B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Hisilicon Hi3559A clock driver
      4 *
      5 * Copyright (c) 2019-2020, Huawei Tech. Co., Ltd.
      6 *
      7 * Author: Dongjiu Geng <gengdongjiu@huawei.com>
      8 */
      9
     10#include <linux/clk-provider.h>
     11#include <linux/module.h>
     12#include <linux/of_device.h>
     13#include <linux/platform_device.h>
     14#include <linux/slab.h>
     15
     16#include <dt-bindings/clock/hi3559av100-clock.h>
     17
     18#include "clk.h"
     19#include "crg.h"
     20#include "reset.h"
     21
     22#define CRG_BASE_ADDR  0x18020000
     23#define PLL_MASK_WIDTH 24
     24
     25struct hi3559av100_pll_clock {
     26	u32	id;
     27	const char	*name;
     28	const char	*parent_name;
     29	const u32	ctrl_reg1;
     30	const u8	frac_shift;
     31	const u8	frac_width;
     32	const u8	postdiv1_shift;
     33	const u8	postdiv1_width;
     34	const u8	postdiv2_shift;
     35	const u8	postdiv2_width;
     36	const u32	ctrl_reg2;
     37	const u8	fbdiv_shift;
     38	const u8	fbdiv_width;
     39	const u8	refdiv_shift;
     40	const u8	refdiv_width;
     41};
     42
     43struct hi3559av100_clk_pll {
     44	struct clk_hw	hw;
     45	u32	id;
     46	void __iomem	*ctrl_reg1;
     47	u8	frac_shift;
     48	u8	frac_width;
     49	u8	postdiv1_shift;
     50	u8	postdiv1_width;
     51	u8	postdiv2_shift;
     52	u8	postdiv2_width;
     53	void __iomem	*ctrl_reg2;
     54	u8	fbdiv_shift;
     55	u8	fbdiv_width;
     56	u8	refdiv_shift;
     57	u8	refdiv_width;
     58};
     59
     60/* soc clk config */
     61static const struct hisi_fixed_rate_clock hi3559av100_fixed_rate_clks_crg[] = {
     62	{ HI3559AV100_FIXED_1188M, "1188m", NULL, 0, 1188000000, },
     63	{ HI3559AV100_FIXED_1000M, "1000m", NULL, 0, 1000000000, },
     64	{ HI3559AV100_FIXED_842M, "842m", NULL, 0, 842000000, },
     65	{ HI3559AV100_FIXED_792M, "792m", NULL, 0, 792000000, },
     66	{ HI3559AV100_FIXED_750M, "750m", NULL, 0, 750000000, },
     67	{ HI3559AV100_FIXED_710M, "710m", NULL, 0, 710000000, },
     68	{ HI3559AV100_FIXED_680M, "680m", NULL, 0, 680000000, },
     69	{ HI3559AV100_FIXED_667M, "667m", NULL, 0, 667000000, },
     70	{ HI3559AV100_FIXED_631M, "631m", NULL, 0, 631000000, },
     71	{ HI3559AV100_FIXED_600M, "600m", NULL, 0, 600000000, },
     72	{ HI3559AV100_FIXED_568M, "568m", NULL, 0, 568000000, },
     73	{ HI3559AV100_FIXED_500M, "500m", NULL, 0, 500000000, },
     74	{ HI3559AV100_FIXED_475M, "475m", NULL, 0, 475000000, },
     75	{ HI3559AV100_FIXED_428M, "428m", NULL, 0, 428000000, },
     76	{ HI3559AV100_FIXED_400M, "400m", NULL, 0, 400000000, },
     77	{ HI3559AV100_FIXED_396M, "396m", NULL, 0, 396000000, },
     78	{ HI3559AV100_FIXED_300M, "300m", NULL, 0, 300000000, },
     79	{ HI3559AV100_FIXED_250M, "250m", NULL, 0, 250000000, },
     80	{ HI3559AV100_FIXED_200M, "200m", NULL, 0, 200000000, },
     81	{ HI3559AV100_FIXED_198M, "198m", NULL, 0, 198000000, },
     82	{ HI3559AV100_FIXED_187p5M, "187p5m", NULL, 0, 187500000, },
     83	{ HI3559AV100_FIXED_150M, "150m", NULL, 0, 150000000, },
     84	{ HI3559AV100_FIXED_148p5M, "148p5m", NULL, 0, 1485000000, },
     85	{ HI3559AV100_FIXED_125M, "125m", NULL, 0, 125000000, },
     86	{ HI3559AV100_FIXED_107M, "107m", NULL, 0, 107000000, },
     87	{ HI3559AV100_FIXED_100M, "100m", NULL, 0, 100000000, },
     88	{ HI3559AV100_FIXED_99M, "99m",	NULL, 0, 99000000, },
     89	{ HI3559AV100_FIXED_75M, "75m", NULL, 0, 75000000, },
     90	{ HI3559AV100_FIXED_74p25M, "74p25m", NULL, 0, 74250000, },
     91	{ HI3559AV100_FIXED_72M, "72m",	NULL, 0, 72000000, },
     92	{ HI3559AV100_FIXED_60M, "60m",	NULL, 0, 60000000, },
     93	{ HI3559AV100_FIXED_54M, "54m",	NULL, 0, 54000000, },
     94	{ HI3559AV100_FIXED_50M, "50m",	NULL, 0, 50000000, },
     95	{ HI3559AV100_FIXED_49p5M, "49p5m", NULL, 0, 49500000, },
     96	{ HI3559AV100_FIXED_37p125M, "37p125m", NULL, 0, 37125000, },
     97	{ HI3559AV100_FIXED_36M, "36m",	NULL, 0, 36000000, },
     98	{ HI3559AV100_FIXED_32p4M, "32p4m", NULL, 0, 32400000, },
     99	{ HI3559AV100_FIXED_27M, "27m",	NULL, 0, 27000000, },
    100	{ HI3559AV100_FIXED_25M, "25m",	NULL, 0, 25000000, },
    101	{ HI3559AV100_FIXED_24M, "24m",	NULL, 0, 24000000, },
    102	{ HI3559AV100_FIXED_12M, "12m",	NULL, 0, 12000000, },
    103	{ HI3559AV100_FIXED_3M,	 "3m", NULL, 0, 3000000, },
    104	{ HI3559AV100_FIXED_1p6M, "1p6m", NULL, 0, 1600000, },
    105	{ HI3559AV100_FIXED_400K, "400k", NULL, 0, 400000, },
    106	{ HI3559AV100_FIXED_100K, "100k", NULL, 0, 100000, },
    107};
    108
    109
    110static const char *fmc_mux_p[] = {
    111	"24m", "75m", "125m", "150m", "200m", "250m", "300m", "400m"
    112};
    113
    114static const char *mmc_mux_p[] = {
    115	"100k", "25m", "49p5m", "99m", "187p5m", "150m", "198m", "400k"
    116};
    117
    118static const char *sysapb_mux_p[] = {
    119	"24m", "50m",
    120};
    121
    122static const char *sysbus_mux_p[] = {
    123	"24m", "300m"
    124};
    125
    126static const char *uart_mux_p[] = { "50m", "24m", "3m" };
    127
    128static const char *a73_clksel_mux_p[] = {
    129	"24m", "apll", "1000m"
    130};
    131
    132static const u32 fmc_mux_table[]	= { 0, 1, 2, 3, 4, 5, 6, 7 };
    133static const u32 mmc_mux_table[]	= { 0, 1, 2, 3, 4, 5, 6, 7 };
    134static const u32 sysapb_mux_table[]	= { 0, 1 };
    135static const u32 sysbus_mux_table[]	= { 0, 1 };
    136static const u32 uart_mux_table[]	= { 0, 1, 2 };
    137static const u32 a73_clksel_mux_table[] = { 0, 1, 2 };
    138
    139static struct hisi_mux_clock hi3559av100_mux_clks_crg[] = {
    140	{
    141		HI3559AV100_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p),
    142		CLK_SET_RATE_PARENT, 0x170, 2, 3, 0, fmc_mux_table,
    143	},
    144	{
    145		HI3559AV100_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
    146		CLK_SET_RATE_PARENT, 0x1a8, 24, 3, 0, mmc_mux_table,
    147	},
    148	{
    149		HI3559AV100_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
    150		CLK_SET_RATE_PARENT, 0x1ec, 24, 3, 0, mmc_mux_table,
    151	},
    152
    153	{
    154		HI3559AV100_MMC2_MUX, "mmc2_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
    155		CLK_SET_RATE_PARENT, 0x214, 24, 3, 0, mmc_mux_table,
    156	},
    157
    158	{
    159		HI3559AV100_MMC3_MUX, "mmc3_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
    160		CLK_SET_RATE_PARENT, 0x23c, 24, 3, 0, mmc_mux_table,
    161	},
    162
    163	{
    164		HI3559AV100_SYSAPB_MUX, "sysapb_mux", sysapb_mux_p, ARRAY_SIZE(sysapb_mux_p),
    165		CLK_SET_RATE_PARENT, 0xe8, 3, 1, 0, sysapb_mux_table
    166	},
    167
    168	{
    169		HI3559AV100_SYSBUS_MUX, "sysbus_mux", sysbus_mux_p, ARRAY_SIZE(sysbus_mux_p),
    170		CLK_SET_RATE_PARENT, 0xe8, 0, 1, 0, sysbus_mux_table
    171	},
    172
    173	{
    174		HI3559AV100_UART_MUX, "uart_mux", uart_mux_p, ARRAY_SIZE(uart_mux_p),
    175		CLK_SET_RATE_PARENT, 0x198, 28, 2, 0, uart_mux_table
    176	},
    177
    178	{
    179		HI3559AV100_A73_MUX, "a73_mux", a73_clksel_mux_p, ARRAY_SIZE(a73_clksel_mux_p),
    180		CLK_SET_RATE_PARENT, 0xe4, 0, 2, 0, a73_clksel_mux_table
    181	},
    182};
    183
    184static struct hisi_gate_clock hi3559av100_gate_clks[] = {
    185	{
    186		HI3559AV100_FMC_CLK, "clk_fmc", "fmc_mux",
    187		CLK_SET_RATE_PARENT, 0x170, 1, 0,
    188	},
    189	{
    190		HI3559AV100_MMC0_CLK, "clk_mmc0", "mmc0_mux",
    191		CLK_SET_RATE_PARENT, 0x1a8, 28, 0,
    192	},
    193	{
    194		HI3559AV100_MMC1_CLK, "clk_mmc1", "mmc1_mux",
    195		CLK_SET_RATE_PARENT, 0x1ec, 28, 0,
    196	},
    197	{
    198		HI3559AV100_MMC2_CLK, "clk_mmc2", "mmc2_mux",
    199		CLK_SET_RATE_PARENT, 0x214, 28, 0,
    200	},
    201	{
    202		HI3559AV100_MMC3_CLK, "clk_mmc3", "mmc3_mux",
    203		CLK_SET_RATE_PARENT, 0x23c, 28, 0,
    204	},
    205	{
    206		HI3559AV100_UART0_CLK, "clk_uart0", "uart_mux",
    207		CLK_SET_RATE_PARENT, 0x198, 23, 0,
    208	},
    209	{
    210		HI3559AV100_UART1_CLK, "clk_uart1", "uart_mux",
    211		CLK_SET_RATE_PARENT, 0x198, 24, 0,
    212	},
    213	{
    214		HI3559AV100_UART2_CLK, "clk_uart2", "uart_mux",
    215		CLK_SET_RATE_PARENT, 0x198, 25, 0,
    216	},
    217	{
    218		HI3559AV100_UART3_CLK, "clk_uart3", "uart_mux",
    219		CLK_SET_RATE_PARENT, 0x198, 26, 0,
    220	},
    221	{
    222		HI3559AV100_UART4_CLK, "clk_uart4", "uart_mux",
    223		CLK_SET_RATE_PARENT, 0x198, 27, 0,
    224	},
    225	{
    226		HI3559AV100_ETH_CLK, "clk_eth", NULL,
    227		CLK_SET_RATE_PARENT, 0x0174, 1, 0,
    228	},
    229	{
    230		HI3559AV100_ETH_MACIF_CLK, "clk_eth_macif", NULL,
    231		CLK_SET_RATE_PARENT, 0x0174, 5, 0,
    232	},
    233	{
    234		HI3559AV100_ETH1_CLK, "clk_eth1", NULL,
    235		CLK_SET_RATE_PARENT, 0x0174, 3, 0,
    236	},
    237	{
    238		HI3559AV100_ETH1_MACIF_CLK, "clk_eth1_macif", NULL,
    239		CLK_SET_RATE_PARENT, 0x0174, 7, 0,
    240	},
    241	{
    242		HI3559AV100_I2C0_CLK, "clk_i2c0", "50m",
    243		CLK_SET_RATE_PARENT, 0x01a0, 16, 0,
    244	},
    245	{
    246		HI3559AV100_I2C1_CLK, "clk_i2c1", "50m",
    247		CLK_SET_RATE_PARENT, 0x01a0, 17, 0,
    248	},
    249	{
    250		HI3559AV100_I2C2_CLK, "clk_i2c2", "50m",
    251		CLK_SET_RATE_PARENT, 0x01a0, 18, 0,
    252	},
    253	{
    254		HI3559AV100_I2C3_CLK, "clk_i2c3", "50m",
    255		CLK_SET_RATE_PARENT, 0x01a0, 19, 0,
    256	},
    257	{
    258		HI3559AV100_I2C4_CLK, "clk_i2c4", "50m",
    259		CLK_SET_RATE_PARENT, 0x01a0, 20, 0,
    260	},
    261	{
    262		HI3559AV100_I2C5_CLK, "clk_i2c5", "50m",
    263		CLK_SET_RATE_PARENT, 0x01a0, 21, 0,
    264	},
    265	{
    266		HI3559AV100_I2C6_CLK, "clk_i2c6", "50m",
    267		CLK_SET_RATE_PARENT, 0x01a0, 22, 0,
    268	},
    269	{
    270		HI3559AV100_I2C7_CLK, "clk_i2c7", "50m",
    271		CLK_SET_RATE_PARENT, 0x01a0, 23, 0,
    272	},
    273	{
    274		HI3559AV100_I2C8_CLK, "clk_i2c8", "50m",
    275		CLK_SET_RATE_PARENT, 0x01a0, 24, 0,
    276	},
    277	{
    278		HI3559AV100_I2C9_CLK, "clk_i2c9", "50m",
    279		CLK_SET_RATE_PARENT, 0x01a0, 25, 0,
    280	},
    281	{
    282		HI3559AV100_I2C10_CLK, "clk_i2c10", "50m",
    283		CLK_SET_RATE_PARENT, 0x01a0, 26, 0,
    284	},
    285	{
    286		HI3559AV100_I2C11_CLK, "clk_i2c11", "50m",
    287		CLK_SET_RATE_PARENT, 0x01a0, 27, 0,
    288	},
    289	{
    290		HI3559AV100_SPI0_CLK, "clk_spi0", "100m",
    291		CLK_SET_RATE_PARENT, 0x0198, 16, 0,
    292	},
    293	{
    294		HI3559AV100_SPI1_CLK, "clk_spi1", "100m",
    295		CLK_SET_RATE_PARENT, 0x0198, 17, 0,
    296	},
    297	{
    298		HI3559AV100_SPI2_CLK, "clk_spi2", "100m",
    299		CLK_SET_RATE_PARENT, 0x0198, 18, 0,
    300	},
    301	{
    302		HI3559AV100_SPI3_CLK, "clk_spi3", "100m",
    303		CLK_SET_RATE_PARENT, 0x0198, 19, 0,
    304	},
    305	{
    306		HI3559AV100_SPI4_CLK, "clk_spi4", "100m",
    307		CLK_SET_RATE_PARENT, 0x0198, 20, 0,
    308	},
    309	{
    310		HI3559AV100_SPI5_CLK, "clk_spi5", "100m",
    311		CLK_SET_RATE_PARENT, 0x0198, 21, 0,
    312	},
    313	{
    314		HI3559AV100_SPI6_CLK, "clk_spi6", "100m",
    315		CLK_SET_RATE_PARENT, 0x0198, 22, 0,
    316	},
    317	{
    318		HI3559AV100_EDMAC_AXICLK, "axi_clk_edmac", NULL,
    319		CLK_SET_RATE_PARENT, 0x16c, 6, 0,
    320	},
    321	{
    322		HI3559AV100_EDMAC_CLK, "clk_edmac", NULL,
    323		CLK_SET_RATE_PARENT, 0x16c, 5, 0,
    324	},
    325	{
    326		HI3559AV100_EDMAC1_AXICLK, "axi_clk_edmac1", NULL,
    327		CLK_SET_RATE_PARENT, 0x16c, 9, 0,
    328	},
    329	{
    330		HI3559AV100_EDMAC1_CLK, "clk_edmac1", NULL,
    331		CLK_SET_RATE_PARENT, 0x16c, 8, 0,
    332	},
    333	{
    334		HI3559AV100_VDMAC_CLK, "clk_vdmac", NULL,
    335		CLK_SET_RATE_PARENT, 0x14c, 5, 0,
    336	},
    337};
    338
    339static struct hi3559av100_pll_clock hi3559av100_pll_clks[] = {
    340	{
    341		HI3559AV100_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3,
    342		0x4, 0, 12, 12, 6
    343	},
    344	{
    345		HI3559AV100_GPLL_CLK, "gpll", NULL, 0x20, 0, 24, 24, 3, 28, 3,
    346		0x24, 0, 12, 12, 6
    347	},
    348};
    349
    350#define to_pll_clk(_hw) container_of(_hw, struct hi3559av100_clk_pll, hw)
    351static void hi3559av100_calc_pll(u32 *frac_val, u32 *postdiv1_val,
    352				 u32 *postdiv2_val,
    353				 u32 *fbdiv_val, u32 *refdiv_val, u64 rate)
    354{
    355	u64 rem;
    356
    357	*postdiv1_val = 2;
    358	*postdiv2_val = 1;
    359
    360	rate = rate * ((*postdiv1_val) * (*postdiv2_val));
    361
    362	*frac_val = 0;
    363	rem = do_div(rate, 1000000);
    364	rem = do_div(rate, PLL_MASK_WIDTH);
    365	*fbdiv_val = rate;
    366	*refdiv_val = 1;
    367	rem = rem * (1 << PLL_MASK_WIDTH);
    368	do_div(rem, PLL_MASK_WIDTH);
    369	*frac_val = rem;
    370}
    371
    372static int clk_pll_set_rate(struct clk_hw *hw,
    373			    unsigned long rate,
    374			    unsigned long parent_rate)
    375{
    376	struct hi3559av100_clk_pll *clk = to_pll_clk(hw);
    377	u32 frac_val, postdiv1_val, postdiv2_val, fbdiv_val, refdiv_val;
    378	u32 val;
    379
    380	postdiv1_val = postdiv2_val = 0;
    381
    382	hi3559av100_calc_pll(&frac_val, &postdiv1_val, &postdiv2_val,
    383			     &fbdiv_val, &refdiv_val, (u64)rate);
    384
    385	val = readl_relaxed(clk->ctrl_reg1);
    386	val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift);
    387	val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift);
    388	val &= ~(((1 << clk->postdiv2_width) - 1) << clk->postdiv2_shift);
    389
    390	val |= frac_val << clk->frac_shift;
    391	val |= postdiv1_val << clk->postdiv1_shift;
    392	val |= postdiv2_val << clk->postdiv2_shift;
    393	writel_relaxed(val, clk->ctrl_reg1);
    394
    395	val = readl_relaxed(clk->ctrl_reg2);
    396	val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift);
    397	val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift);
    398
    399	val |= fbdiv_val << clk->fbdiv_shift;
    400	val |= refdiv_val << clk->refdiv_shift;
    401	writel_relaxed(val, clk->ctrl_reg2);
    402
    403	return 0;
    404}
    405
    406static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
    407		unsigned long parent_rate)
    408{
    409	struct hi3559av100_clk_pll *clk = to_pll_clk(hw);
    410	u64 frac_val, fbdiv_val, refdiv_val;
    411	u32 postdiv1_val, postdiv2_val;
    412	u32 val;
    413	u64 tmp, rate;
    414
    415	val = readl_relaxed(clk->ctrl_reg1);
    416	val = val >> clk->frac_shift;
    417	val &= ((1 << clk->frac_width) - 1);
    418	frac_val = val;
    419
    420	val = readl_relaxed(clk->ctrl_reg1);
    421	val = val >> clk->postdiv1_shift;
    422	val &= ((1 << clk->postdiv1_width) - 1);
    423	postdiv1_val = val;
    424
    425	val = readl_relaxed(clk->ctrl_reg1);
    426	val = val >> clk->postdiv2_shift;
    427	val &= ((1 << clk->postdiv2_width) - 1);
    428	postdiv2_val = val;
    429
    430	val = readl_relaxed(clk->ctrl_reg2);
    431	val = val >> clk->fbdiv_shift;
    432	val &= ((1 << clk->fbdiv_width) - 1);
    433	fbdiv_val = val;
    434
    435	val = readl_relaxed(clk->ctrl_reg2);
    436	val = val >> clk->refdiv_shift;
    437	val &= ((1 << clk->refdiv_width) - 1);
    438	refdiv_val = val;
    439
    440	/* rate = 24000000 * (fbdiv + frac / (1<<24) ) / refdiv  */
    441	rate = 0;
    442	tmp = 24000000 * fbdiv_val + (24000000 * frac_val) / (1 << 24);
    443	rate += tmp;
    444	do_div(rate, refdiv_val);
    445	do_div(rate, postdiv1_val * postdiv2_val);
    446
    447	return rate;
    448}
    449
    450static const struct clk_ops hisi_clk_pll_ops = {
    451	.set_rate = clk_pll_set_rate,
    452	.recalc_rate = clk_pll_recalc_rate,
    453};
    454
    455static void hisi_clk_register_pll(struct hi3559av100_pll_clock *clks,
    456			   int nums, struct hisi_clock_data *data, struct device *dev)
    457{
    458	void __iomem *base = data->base;
    459	struct hi3559av100_clk_pll *p_clk = NULL;
    460	struct clk *clk = NULL;
    461	struct clk_init_data init;
    462	int i;
    463
    464	p_clk = devm_kzalloc(dev, sizeof(*p_clk) * nums, GFP_KERNEL);
    465
    466	if (!p_clk)
    467		return;
    468
    469	for (i = 0; i < nums; i++) {
    470		init.name = clks[i].name;
    471		init.flags = 0;
    472		init.parent_names =
    473			(clks[i].parent_name ? &clks[i].parent_name : NULL);
    474		init.num_parents = (clks[i].parent_name ? 1 : 0);
    475		init.ops = &hisi_clk_pll_ops;
    476
    477		p_clk->ctrl_reg1 = base + clks[i].ctrl_reg1;
    478		p_clk->frac_shift = clks[i].frac_shift;
    479		p_clk->frac_width = clks[i].frac_width;
    480		p_clk->postdiv1_shift = clks[i].postdiv1_shift;
    481		p_clk->postdiv1_width = clks[i].postdiv1_width;
    482		p_clk->postdiv2_shift = clks[i].postdiv2_shift;
    483		p_clk->postdiv2_width = clks[i].postdiv2_width;
    484
    485		p_clk->ctrl_reg2 = base + clks[i].ctrl_reg2;
    486		p_clk->fbdiv_shift = clks[i].fbdiv_shift;
    487		p_clk->fbdiv_width = clks[i].fbdiv_width;
    488		p_clk->refdiv_shift = clks[i].refdiv_shift;
    489		p_clk->refdiv_width = clks[i].refdiv_width;
    490		p_clk->hw.init = &init;
    491
    492		clk = clk_register(NULL, &p_clk->hw);
    493		if (IS_ERR(clk)) {
    494			devm_kfree(dev, p_clk);
    495			dev_err(dev, "%s: failed to register clock %s\n",
    496			       __func__, clks[i].name);
    497			continue;
    498		}
    499
    500		data->clk_data.clks[clks[i].id] = clk;
    501		p_clk++;
    502	}
    503}
    504
    505static struct hisi_clock_data *hi3559av100_clk_register(
    506	struct platform_device *pdev)
    507{
    508	struct hisi_clock_data *clk_data;
    509	int ret;
    510
    511	clk_data = hisi_clk_alloc(pdev, HI3559AV100_CRG_NR_CLKS);
    512	if (!clk_data)
    513		return ERR_PTR(-ENOMEM);
    514
    515	ret = hisi_clk_register_fixed_rate(hi3559av100_fixed_rate_clks_crg,
    516					   ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data);
    517	if (ret)
    518		return ERR_PTR(ret);
    519
    520	hisi_clk_register_pll(hi3559av100_pll_clks,
    521			      ARRAY_SIZE(hi3559av100_pll_clks), clk_data, &pdev->dev);
    522
    523	ret = hisi_clk_register_mux(hi3559av100_mux_clks_crg,
    524				    ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data);
    525	if (ret)
    526		goto unregister_fixed_rate;
    527
    528	ret = hisi_clk_register_gate(hi3559av100_gate_clks,
    529				     ARRAY_SIZE(hi3559av100_gate_clks), clk_data);
    530	if (ret)
    531		goto unregister_mux;
    532
    533	ret = of_clk_add_provider(pdev->dev.of_node,
    534				  of_clk_src_onecell_get, &clk_data->clk_data);
    535	if (ret)
    536		goto unregister_gate;
    537
    538	return clk_data;
    539
    540unregister_gate:
    541	hisi_clk_unregister_gate(hi3559av100_gate_clks,
    542				 ARRAY_SIZE(hi3559av100_gate_clks), clk_data);
    543unregister_mux:
    544	hisi_clk_unregister_mux(hi3559av100_mux_clks_crg,
    545				ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data);
    546unregister_fixed_rate:
    547	hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg,
    548				       ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data);
    549	return ERR_PTR(ret);
    550}
    551
    552static void hi3559av100_clk_unregister(struct platform_device *pdev)
    553{
    554	struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
    555
    556	of_clk_del_provider(pdev->dev.of_node);
    557
    558	hisi_clk_unregister_gate(hi3559av100_gate_clks,
    559				 ARRAY_SIZE(hi3559av100_gate_clks), crg->clk_data);
    560	hisi_clk_unregister_mux(hi3559av100_mux_clks_crg,
    561				ARRAY_SIZE(hi3559av100_mux_clks_crg), crg->clk_data);
    562	hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg,
    563				       ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), crg->clk_data);
    564}
    565
    566static const struct hisi_crg_funcs hi3559av100_crg_funcs = {
    567	.register_clks = hi3559av100_clk_register,
    568	.unregister_clks = hi3559av100_clk_unregister,
    569};
    570
    571static struct hisi_fixed_rate_clock hi3559av100_shub_fixed_rate_clks[] = {
    572	{ HI3559AV100_SHUB_SOURCE_SOC_24M, "clk_source_24M", NULL, 0, 24000000UL, },
    573	{ HI3559AV100_SHUB_SOURCE_SOC_200M, "clk_source_200M", NULL, 0, 200000000UL, },
    574	{ HI3559AV100_SHUB_SOURCE_SOC_300M, "clk_source_300M", NULL, 0, 300000000UL, },
    575	{ HI3559AV100_SHUB_SOURCE_PLL, "clk_source_PLL", NULL, 0, 192000000UL, },
    576	{ HI3559AV100_SHUB_I2C0_CLK, "clk_shub_i2c0", NULL, 0, 48000000UL, },
    577	{ HI3559AV100_SHUB_I2C1_CLK, "clk_shub_i2c1", NULL, 0, 48000000UL, },
    578	{ HI3559AV100_SHUB_I2C2_CLK, "clk_shub_i2c2", NULL, 0, 48000000UL, },
    579	{ HI3559AV100_SHUB_I2C3_CLK, "clk_shub_i2c3", NULL, 0, 48000000UL, },
    580	{ HI3559AV100_SHUB_I2C4_CLK, "clk_shub_i2c4", NULL, 0, 48000000UL, },
    581	{ HI3559AV100_SHUB_I2C5_CLK, "clk_shub_i2c5", NULL, 0, 48000000UL, },
    582	{ HI3559AV100_SHUB_I2C6_CLK, "clk_shub_i2c6", NULL, 0, 48000000UL, },
    583	{ HI3559AV100_SHUB_I2C7_CLK, "clk_shub_i2c7", NULL, 0, 48000000UL, },
    584	{ HI3559AV100_SHUB_UART_CLK_32K, "clk_uart_32K", NULL, 0, 32000UL, },
    585};
    586
    587/* shub mux clk */
    588static u32 shub_source_clk_mux_table[] = {0, 1, 2, 3};
    589static const char *shub_source_clk_mux_p[] = {
    590	"clk_source_24M", "clk_source_200M", "clk_source_300M", "clk_source_PLL"
    591};
    592
    593static u32 shub_uart_source_clk_mux_table[] = {0, 1, 2, 3};
    594static const char *shub_uart_source_clk_mux_p[] = {
    595	"clk_uart_32K", "clk_uart_div_clk", "clk_uart_div_clk", "clk_source_24M"
    596};
    597
    598static struct hisi_mux_clock hi3559av100_shub_mux_clks[] = {
    599	{
    600		HI3559AV100_SHUB_SOURCE_CLK, "shub_clk", shub_source_clk_mux_p,
    601		ARRAY_SIZE(shub_source_clk_mux_p),
    602		0, 0x0, 0, 2, 0, shub_source_clk_mux_table,
    603	},
    604
    605	{
    606		HI3559AV100_SHUB_UART_SOURCE_CLK, "shub_uart_source_clk",
    607		shub_uart_source_clk_mux_p, ARRAY_SIZE(shub_uart_source_clk_mux_p),
    608		0, 0x1c, 28, 2, 0, shub_uart_source_clk_mux_table,
    609	},
    610};
    611
    612
    613/* shub div clk */
    614static struct clk_div_table shub_spi_clk_table[] = {{0, 8}, {1, 4}, {2, 2}, {/*sentinel*/}};
    615static struct clk_div_table shub_uart_div_clk_table[] = {{1, 8}, {2, 4}, {/*sentinel*/}};
    616
    617static struct hisi_divider_clock hi3559av100_shub_div_clks[] = {
    618	{ HI3559AV100_SHUB_SPI_SOURCE_CLK, "clk_spi_clk", "shub_clk", 0, 0x20, 24, 2,
    619	  CLK_DIVIDER_ALLOW_ZERO, shub_spi_clk_table,
    620	},
    621	{ HI3559AV100_SHUB_UART_DIV_CLK, "clk_uart_div_clk", "shub_clk", 0, 0x1c, 28, 2,
    622	  CLK_DIVIDER_ALLOW_ZERO, shub_uart_div_clk_table,
    623	},
    624};
    625
    626/* shub gate clk */
    627static struct hisi_gate_clock hi3559av100_shub_gate_clks[] = {
    628	{
    629		HI3559AV100_SHUB_SPI0_CLK, "clk_shub_spi0", "clk_spi_clk",
    630		0, 0x20, 1, 0,
    631	},
    632	{
    633		HI3559AV100_SHUB_SPI1_CLK, "clk_shub_spi1", "clk_spi_clk",
    634		0, 0x20, 5, 0,
    635	},
    636	{
    637		HI3559AV100_SHUB_SPI2_CLK, "clk_shub_spi2", "clk_spi_clk",
    638		0, 0x20, 9, 0,
    639	},
    640
    641	{
    642		HI3559AV100_SHUB_UART0_CLK, "clk_shub_uart0", "shub_uart_source_clk",
    643		0, 0x1c, 1, 0,
    644	},
    645	{
    646		HI3559AV100_SHUB_UART1_CLK, "clk_shub_uart1", "shub_uart_source_clk",
    647		0, 0x1c, 5, 0,
    648	},
    649	{
    650		HI3559AV100_SHUB_UART2_CLK, "clk_shub_uart2", "shub_uart_source_clk",
    651		0, 0x1c, 9, 0,
    652	},
    653	{
    654		HI3559AV100_SHUB_UART3_CLK, "clk_shub_uart3", "shub_uart_source_clk",
    655		0, 0x1c, 13, 0,
    656	},
    657	{
    658		HI3559AV100_SHUB_UART4_CLK, "clk_shub_uart4", "shub_uart_source_clk",
    659		0, 0x1c, 17, 0,
    660	},
    661	{
    662		HI3559AV100_SHUB_UART5_CLK, "clk_shub_uart5", "shub_uart_source_clk",
    663		0, 0x1c, 21, 0,
    664	},
    665	{
    666		HI3559AV100_SHUB_UART6_CLK, "clk_shub_uart6", "shub_uart_source_clk",
    667		0, 0x1c, 25, 0,
    668	},
    669
    670	{
    671		HI3559AV100_SHUB_EDMAC_CLK, "clk_shub_dmac", "shub_clk",
    672		0, 0x24, 4, 0,
    673	},
    674};
    675
    676static int hi3559av100_shub_default_clk_set(void)
    677{
    678	void __iomem *crg_base;
    679	unsigned int val;
    680
    681	crg_base = ioremap(CRG_BASE_ADDR, SZ_4K);
    682
    683	/* SSP: 192M/2 */
    684	val = readl_relaxed(crg_base + 0x20);
    685	val |= (0x2 << 24);
    686	writel_relaxed(val, crg_base + 0x20);
    687
    688	/* UART: 192M/8 */
    689	val = readl_relaxed(crg_base + 0x1C);
    690	val |= (0x1 << 28);
    691	writel_relaxed(val, crg_base + 0x1C);
    692
    693	iounmap(crg_base);
    694	crg_base = NULL;
    695
    696	return 0;
    697}
    698
    699static struct hisi_clock_data *hi3559av100_shub_clk_register(
    700	struct platform_device *pdev)
    701{
    702	struct hisi_clock_data *clk_data = NULL;
    703	int ret;
    704
    705	hi3559av100_shub_default_clk_set();
    706
    707	clk_data = hisi_clk_alloc(pdev, HI3559AV100_SHUB_NR_CLKS);
    708	if (!clk_data)
    709		return ERR_PTR(-ENOMEM);
    710
    711	ret = hisi_clk_register_fixed_rate(hi3559av100_shub_fixed_rate_clks,
    712					   ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), clk_data);
    713	if (ret)
    714		return ERR_PTR(ret);
    715
    716	ret = hisi_clk_register_mux(hi3559av100_shub_mux_clks,
    717				    ARRAY_SIZE(hi3559av100_shub_mux_clks), clk_data);
    718	if (ret)
    719		goto unregister_fixed_rate;
    720
    721	ret = hisi_clk_register_divider(hi3559av100_shub_div_clks,
    722					ARRAY_SIZE(hi3559av100_shub_div_clks), clk_data);
    723	if (ret)
    724		goto unregister_mux;
    725
    726	ret = hisi_clk_register_gate(hi3559av100_shub_gate_clks,
    727				     ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data);
    728	if (ret)
    729		goto unregister_factor;
    730
    731	ret = of_clk_add_provider(pdev->dev.of_node,
    732				  of_clk_src_onecell_get, &clk_data->clk_data);
    733	if (ret)
    734		goto unregister_gate;
    735
    736	return clk_data;
    737
    738unregister_gate:
    739	hisi_clk_unregister_gate(hi3559av100_shub_gate_clks,
    740				 ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data);
    741unregister_factor:
    742	hisi_clk_unregister_divider(hi3559av100_shub_div_clks,
    743				    ARRAY_SIZE(hi3559av100_shub_div_clks), clk_data);
    744unregister_mux:
    745	hisi_clk_unregister_mux(hi3559av100_shub_mux_clks,
    746				ARRAY_SIZE(hi3559av100_shub_mux_clks), clk_data);
    747unregister_fixed_rate:
    748	hisi_clk_unregister_fixed_rate(hi3559av100_shub_fixed_rate_clks,
    749				       ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), clk_data);
    750	return ERR_PTR(ret);
    751}
    752
    753static void hi3559av100_shub_clk_unregister(struct platform_device *pdev)
    754{
    755	struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
    756
    757	of_clk_del_provider(pdev->dev.of_node);
    758
    759	hisi_clk_unregister_gate(hi3559av100_shub_gate_clks,
    760				 ARRAY_SIZE(hi3559av100_shub_gate_clks), crg->clk_data);
    761	hisi_clk_unregister_divider(hi3559av100_shub_div_clks,
    762				    ARRAY_SIZE(hi3559av100_shub_div_clks), crg->clk_data);
    763	hisi_clk_unregister_mux(hi3559av100_shub_mux_clks,
    764				ARRAY_SIZE(hi3559av100_shub_mux_clks), crg->clk_data);
    765	hisi_clk_unregister_fixed_rate(hi3559av100_shub_fixed_rate_clks,
    766				       ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), crg->clk_data);
    767}
    768
    769static const struct hisi_crg_funcs hi3559av100_shub_crg_funcs = {
    770	.register_clks = hi3559av100_shub_clk_register,
    771	.unregister_clks = hi3559av100_shub_clk_unregister,
    772};
    773
    774static const struct of_device_id hi3559av100_crg_match_table[] = {
    775	{
    776		.compatible = "hisilicon,hi3559av100-clock",
    777		.data = &hi3559av100_crg_funcs
    778	},
    779	{
    780		.compatible = "hisilicon,hi3559av100-shub-clock",
    781		.data = &hi3559av100_shub_crg_funcs
    782	},
    783	{ }
    784};
    785MODULE_DEVICE_TABLE(of, hi3559av100_crg_match_table);
    786
    787static int hi3559av100_crg_probe(struct platform_device *pdev)
    788{
    789	struct hisi_crg_dev *crg;
    790
    791	crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
    792	if (!crg)
    793		return -ENOMEM;
    794
    795	crg->funcs = of_device_get_match_data(&pdev->dev);
    796	if (!crg->funcs)
    797		return -ENOENT;
    798
    799	crg->rstc = hisi_reset_init(pdev);
    800	if (!crg->rstc)
    801		return -ENOMEM;
    802
    803	crg->clk_data = crg->funcs->register_clks(pdev);
    804	if (IS_ERR(crg->clk_data)) {
    805		hisi_reset_exit(crg->rstc);
    806		return PTR_ERR(crg->clk_data);
    807	}
    808
    809	platform_set_drvdata(pdev, crg);
    810	return 0;
    811}
    812
    813static int hi3559av100_crg_remove(struct platform_device *pdev)
    814{
    815	struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
    816
    817	hisi_reset_exit(crg->rstc);
    818	crg->funcs->unregister_clks(pdev);
    819	return 0;
    820}
    821
    822static struct platform_driver hi3559av100_crg_driver = {
    823	.probe		= hi3559av100_crg_probe,
    824	.remove		= hi3559av100_crg_remove,
    825	.driver		= {
    826		.name	= "hi3559av100-clock",
    827		.of_match_table = hi3559av100_crg_match_table,
    828	},
    829};
    830
    831static int __init hi3559av100_crg_init(void)
    832{
    833	return platform_driver_register(&hi3559av100_crg_driver);
    834}
    835core_initcall(hi3559av100_crg_init);
    836
    837static void __exit hi3559av100_crg_exit(void)
    838{
    839	platform_driver_unregister(&hi3559av100_crg_driver);
    840}
    841module_exit(hi3559av100_crg_exit);
    842
    843
    844MODULE_LICENSE("GPL v2");
    845MODULE_DESCRIPTION("HiSilicon Hi3559AV100 CRG Driver");