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-hix5hd2.c (10091B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2014 Linaro Ltd.
      4 * Copyright (c) 2014 Hisilicon Limited.
      5 */
      6
      7#include <linux/of_address.h>
      8#include <dt-bindings/clock/hix5hd2-clock.h>
      9#include <linux/slab.h>
     10#include <linux/delay.h>
     11#include "clk.h"
     12
     13static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] __initdata = {
     14	{ HIX5HD2_FIXED_1200M, "1200m", NULL, 0, 1200000000, },
     15	{ HIX5HD2_FIXED_400M, "400m", NULL, 0, 400000000, },
     16	{ HIX5HD2_FIXED_48M, "48m", NULL, 0, 48000000, },
     17	{ HIX5HD2_FIXED_24M, "24m", NULL, 0, 24000000, },
     18	{ HIX5HD2_FIXED_600M, "600m", NULL, 0, 600000000, },
     19	{ HIX5HD2_FIXED_300M, "300m", NULL, 0, 300000000, },
     20	{ HIX5HD2_FIXED_75M, "75m", NULL, 0, 75000000, },
     21	{ HIX5HD2_FIXED_200M, "200m", NULL, 0, 200000000, },
     22	{ HIX5HD2_FIXED_100M, "100m", NULL, 0, 100000000, },
     23	{ HIX5HD2_FIXED_40M, "40m", NULL, 0, 40000000, },
     24	{ HIX5HD2_FIXED_150M, "150m", NULL, 0, 150000000, },
     25	{ HIX5HD2_FIXED_1728M, "1728m", NULL, 0, 1728000000, },
     26	{ HIX5HD2_FIXED_28P8M, "28p8m", NULL, 0, 28000000, },
     27	{ HIX5HD2_FIXED_432M, "432m", NULL, 0, 432000000, },
     28	{ HIX5HD2_FIXED_345P6M, "345p6m", NULL, 0, 345000000, },
     29	{ HIX5HD2_FIXED_288M, "288m", NULL, 0, 288000000, },
     30	{ HIX5HD2_FIXED_60M,	"60m", NULL, 0, 60000000, },
     31	{ HIX5HD2_FIXED_750M, "750m", NULL, 0, 750000000, },
     32	{ HIX5HD2_FIXED_500M, "500m", NULL, 0, 500000000, },
     33	{ HIX5HD2_FIXED_54M,	"54m", NULL, 0, 54000000, },
     34	{ HIX5HD2_FIXED_27M, "27m", NULL, 0, 27000000, },
     35	{ HIX5HD2_FIXED_1500M, "1500m", NULL, 0, 1500000000, },
     36	{ HIX5HD2_FIXED_375M, "375m", NULL, 0, 375000000, },
     37	{ HIX5HD2_FIXED_187M, "187m", NULL, 0, 187000000, },
     38	{ HIX5HD2_FIXED_250M, "250m", NULL, 0, 250000000, },
     39	{ HIX5HD2_FIXED_125M, "125m", NULL, 0, 125000000, },
     40	{ HIX5HD2_FIXED_2P02M, "2m", NULL, 0, 2000000, },
     41	{ HIX5HD2_FIXED_50M, "50m", NULL, 0, 50000000, },
     42	{ HIX5HD2_FIXED_25M, "25m", NULL, 0, 25000000, },
     43	{ HIX5HD2_FIXED_83M, "83m", NULL, 0, 83333333, },
     44};
     45
     46static const char *const sfc_mux_p[] __initconst = {
     47		"24m", "150m", "200m", "100m", "75m", };
     48static u32 sfc_mux_table[] = {0, 4, 5, 6, 7};
     49
     50static const char *const sdio_mux_p[] __initconst = {
     51		"75m", "100m", "50m", "15m", };
     52static u32 sdio_mux_table[] = {0, 1, 2, 3};
     53
     54static const char *const fephy_mux_p[] __initconst = { "25m", "125m"};
     55static u32 fephy_mux_table[] = {0, 1};
     56
     57
     58static struct hisi_mux_clock hix5hd2_mux_clks[] __initdata = {
     59	{ HIX5HD2_SFC_MUX, "sfc_mux", sfc_mux_p, ARRAY_SIZE(sfc_mux_p),
     60		CLK_SET_RATE_PARENT, 0x5c, 8, 3, 0, sfc_mux_table, },
     61	{ HIX5HD2_MMC_MUX, "mmc_mux", sdio_mux_p, ARRAY_SIZE(sdio_mux_p),
     62		CLK_SET_RATE_PARENT, 0xa0, 8, 2, 0, sdio_mux_table, },
     63	{ HIX5HD2_SD_MUX, "sd_mux", sdio_mux_p, ARRAY_SIZE(sdio_mux_p),
     64		CLK_SET_RATE_PARENT, 0x9c, 8, 2, 0, sdio_mux_table, },
     65	{ HIX5HD2_FEPHY_MUX, "fephy_mux",
     66		fephy_mux_p, ARRAY_SIZE(fephy_mux_p),
     67		CLK_SET_RATE_PARENT, 0x120, 8, 2, 0, fephy_mux_table, },
     68};
     69
     70static struct hisi_gate_clock hix5hd2_gate_clks[] __initdata = {
     71	/* sfc */
     72	{ HIX5HD2_SFC_CLK, "clk_sfc", "sfc_mux",
     73		CLK_SET_RATE_PARENT, 0x5c, 0, 0, },
     74	{ HIX5HD2_SFC_RST, "rst_sfc", "clk_sfc",
     75		CLK_SET_RATE_PARENT, 0x5c, 4, CLK_GATE_SET_TO_DISABLE, },
     76	/* sdio0 */
     77	{ HIX5HD2_SD_BIU_CLK, "clk_sd_biu", "200m",
     78		CLK_SET_RATE_PARENT, 0x9c, 0, 0, },
     79	{ HIX5HD2_SD_CIU_CLK, "clk_sd_ciu", "sd_mux",
     80		CLK_SET_RATE_PARENT, 0x9c, 1, 0, },
     81	{ HIX5HD2_SD_CIU_RST, "rst_sd_ciu", "clk_sd_ciu",
     82		CLK_SET_RATE_PARENT, 0x9c, 4, CLK_GATE_SET_TO_DISABLE, },
     83	/* sdio1 */
     84	{ HIX5HD2_MMC_BIU_CLK, "clk_mmc_biu", "200m",
     85		CLK_SET_RATE_PARENT, 0xa0, 0, 0, },
     86	{ HIX5HD2_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux",
     87		CLK_SET_RATE_PARENT, 0xa0, 1, 0, },
     88	{ HIX5HD2_MMC_CIU_RST, "rst_mmc_ciu", "clk_mmc_ciu",
     89		CLK_SET_RATE_PARENT, 0xa0, 4, CLK_GATE_SET_TO_DISABLE, },
     90	/* gsf */
     91	{ HIX5HD2_FWD_BUS_CLK, "clk_fwd_bus", NULL, 0, 0xcc, 0, 0, },
     92	{ HIX5HD2_FWD_SYS_CLK, "clk_fwd_sys", "clk_fwd_bus", 0, 0xcc, 5, 0, },
     93	{ HIX5HD2_MAC0_PHY_CLK, "clk_fephy", "clk_fwd_sys",
     94		 CLK_SET_RATE_PARENT, 0x120, 0, 0, },
     95	/* wdg0 */
     96	{ HIX5HD2_WDG0_CLK, "clk_wdg0", "24m",
     97		CLK_SET_RATE_PARENT, 0x178, 0, 0, },
     98	{ HIX5HD2_WDG0_RST, "rst_wdg0", "clk_wdg0",
     99		CLK_SET_RATE_PARENT, 0x178, 4, CLK_GATE_SET_TO_DISABLE, },
    100	/* I2C */
    101	{HIX5HD2_I2C0_CLK, "clk_i2c0", "100m",
    102		 CLK_SET_RATE_PARENT, 0x06c, 4, 0, },
    103	{HIX5HD2_I2C0_RST, "rst_i2c0", "clk_i2c0",
    104		 CLK_SET_RATE_PARENT, 0x06c, 5, CLK_GATE_SET_TO_DISABLE, },
    105	{HIX5HD2_I2C1_CLK, "clk_i2c1", "100m",
    106		 CLK_SET_RATE_PARENT, 0x06c, 8, 0, },
    107	{HIX5HD2_I2C1_RST, "rst_i2c1", "clk_i2c1",
    108		 CLK_SET_RATE_PARENT, 0x06c, 9, CLK_GATE_SET_TO_DISABLE, },
    109	{HIX5HD2_I2C2_CLK, "clk_i2c2", "100m",
    110		 CLK_SET_RATE_PARENT, 0x06c, 12, 0, },
    111	{HIX5HD2_I2C2_RST, "rst_i2c2", "clk_i2c2",
    112		 CLK_SET_RATE_PARENT, 0x06c, 13, CLK_GATE_SET_TO_DISABLE, },
    113	{HIX5HD2_I2C3_CLK, "clk_i2c3", "100m",
    114		 CLK_SET_RATE_PARENT, 0x06c, 16, 0, },
    115	{HIX5HD2_I2C3_RST, "rst_i2c3", "clk_i2c3",
    116		 CLK_SET_RATE_PARENT, 0x06c, 17, CLK_GATE_SET_TO_DISABLE, },
    117	{HIX5HD2_I2C4_CLK, "clk_i2c4", "100m",
    118		 CLK_SET_RATE_PARENT, 0x06c, 20, 0, },
    119	{HIX5HD2_I2C4_RST, "rst_i2c4", "clk_i2c4",
    120		 CLK_SET_RATE_PARENT, 0x06c, 21, CLK_GATE_SET_TO_DISABLE, },
    121	{HIX5HD2_I2C5_CLK, "clk_i2c5", "100m",
    122		 CLK_SET_RATE_PARENT, 0x06c, 0, 0, },
    123	{HIX5HD2_I2C5_RST, "rst_i2c5", "clk_i2c5",
    124		 CLK_SET_RATE_PARENT, 0x06c, 1, CLK_GATE_SET_TO_DISABLE, },
    125};
    126
    127enum hix5hd2_clk_type {
    128	TYPE_COMPLEX,
    129	TYPE_ETHER,
    130};
    131
    132struct hix5hd2_complex_clock {
    133	const char	*name;
    134	const char	*parent_name;
    135	u32		id;
    136	u32		ctrl_reg;
    137	u32		ctrl_clk_mask;
    138	u32		ctrl_rst_mask;
    139	u32		phy_reg;
    140	u32		phy_clk_mask;
    141	u32		phy_rst_mask;
    142	enum hix5hd2_clk_type type;
    143};
    144
    145struct hix5hd2_clk_complex {
    146	struct clk_hw	hw;
    147	u32		id;
    148	void __iomem	*ctrl_reg;
    149	u32		ctrl_clk_mask;
    150	u32		ctrl_rst_mask;
    151	void __iomem	*phy_reg;
    152	u32		phy_clk_mask;
    153	u32		phy_rst_mask;
    154};
    155
    156static struct hix5hd2_complex_clock hix5hd2_complex_clks[] __initdata = {
    157	{"clk_mac0", "clk_fephy", HIX5HD2_MAC0_CLK,
    158		0xcc, 0xa, 0x500, 0x120, 0, 0x10, TYPE_ETHER},
    159	{"clk_mac1", "clk_fwd_sys", HIX5HD2_MAC1_CLK,
    160		0xcc, 0x14, 0xa00, 0x168, 0x2, 0, TYPE_ETHER},
    161	{"clk_sata", NULL, HIX5HD2_SATA_CLK,
    162		0xa8, 0x1f, 0x300, 0xac, 0x1, 0x0, TYPE_COMPLEX},
    163	{"clk_usb", NULL, HIX5HD2_USB_CLK,
    164		0xb8, 0xff, 0x3f000, 0xbc, 0x7, 0x3f00, TYPE_COMPLEX},
    165};
    166
    167#define to_complex_clk(_hw) container_of(_hw, struct hix5hd2_clk_complex, hw)
    168
    169static int clk_ether_prepare(struct clk_hw *hw)
    170{
    171	struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
    172	u32 val;
    173
    174	val = readl_relaxed(clk->ctrl_reg);
    175	val |= clk->ctrl_clk_mask | clk->ctrl_rst_mask;
    176	writel_relaxed(val, clk->ctrl_reg);
    177	val &= ~(clk->ctrl_rst_mask);
    178	writel_relaxed(val, clk->ctrl_reg);
    179
    180	val = readl_relaxed(clk->phy_reg);
    181	val |= clk->phy_clk_mask;
    182	val &= ~(clk->phy_rst_mask);
    183	writel_relaxed(val, clk->phy_reg);
    184	mdelay(10);
    185
    186	val &= ~(clk->phy_clk_mask);
    187	val |= clk->phy_rst_mask;
    188	writel_relaxed(val, clk->phy_reg);
    189	mdelay(10);
    190
    191	val |= clk->phy_clk_mask;
    192	val &= ~(clk->phy_rst_mask);
    193	writel_relaxed(val, clk->phy_reg);
    194	mdelay(30);
    195	return 0;
    196}
    197
    198static void clk_ether_unprepare(struct clk_hw *hw)
    199{
    200	struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
    201	u32 val;
    202
    203	val = readl_relaxed(clk->ctrl_reg);
    204	val &= ~(clk->ctrl_clk_mask);
    205	writel_relaxed(val, clk->ctrl_reg);
    206}
    207
    208static const struct clk_ops clk_ether_ops = {
    209	.prepare = clk_ether_prepare,
    210	.unprepare = clk_ether_unprepare,
    211};
    212
    213static int clk_complex_enable(struct clk_hw *hw)
    214{
    215	struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
    216	u32 val;
    217
    218	val = readl_relaxed(clk->ctrl_reg);
    219	val |= clk->ctrl_clk_mask;
    220	val &= ~(clk->ctrl_rst_mask);
    221	writel_relaxed(val, clk->ctrl_reg);
    222
    223	val = readl_relaxed(clk->phy_reg);
    224	val |= clk->phy_clk_mask;
    225	val &= ~(clk->phy_rst_mask);
    226	writel_relaxed(val, clk->phy_reg);
    227
    228	return 0;
    229}
    230
    231static void clk_complex_disable(struct clk_hw *hw)
    232{
    233	struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
    234	u32 val;
    235
    236	val = readl_relaxed(clk->ctrl_reg);
    237	val |= clk->ctrl_rst_mask;
    238	val &= ~(clk->ctrl_clk_mask);
    239	writel_relaxed(val, clk->ctrl_reg);
    240
    241	val = readl_relaxed(clk->phy_reg);
    242	val |= clk->phy_rst_mask;
    243	val &= ~(clk->phy_clk_mask);
    244	writel_relaxed(val, clk->phy_reg);
    245}
    246
    247static const struct clk_ops clk_complex_ops = {
    248	.enable = clk_complex_enable,
    249	.disable = clk_complex_disable,
    250};
    251
    252static void __init
    253hix5hd2_clk_register_complex(struct hix5hd2_complex_clock *clks, int nums,
    254			     struct hisi_clock_data *data)
    255{
    256	void __iomem *base = data->base;
    257	int i;
    258
    259	for (i = 0; i < nums; i++) {
    260		struct hix5hd2_clk_complex *p_clk;
    261		struct clk *clk;
    262		struct clk_init_data init;
    263
    264		p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL);
    265		if (!p_clk)
    266			return;
    267
    268		init.name = clks[i].name;
    269		if (clks[i].type == TYPE_ETHER)
    270			init.ops = &clk_ether_ops;
    271		else
    272			init.ops = &clk_complex_ops;
    273
    274		init.flags = 0;
    275		init.parent_names =
    276			(clks[i].parent_name ? &clks[i].parent_name : NULL);
    277		init.num_parents = (clks[i].parent_name ? 1 : 0);
    278
    279		p_clk->ctrl_reg = base + clks[i].ctrl_reg;
    280		p_clk->ctrl_clk_mask = clks[i].ctrl_clk_mask;
    281		p_clk->ctrl_rst_mask = clks[i].ctrl_rst_mask;
    282		p_clk->phy_reg = base + clks[i].phy_reg;
    283		p_clk->phy_clk_mask = clks[i].phy_clk_mask;
    284		p_clk->phy_rst_mask = clks[i].phy_rst_mask;
    285		p_clk->hw.init = &init;
    286
    287		clk = clk_register(NULL, &p_clk->hw);
    288		if (IS_ERR(clk)) {
    289			kfree(p_clk);
    290			pr_err("%s: failed to register clock %s\n",
    291			       __func__, clks[i].name);
    292			continue;
    293		}
    294
    295		data->clk_data.clks[clks[i].id] = clk;
    296	}
    297}
    298
    299static void __init hix5hd2_clk_init(struct device_node *np)
    300{
    301	struct hisi_clock_data *clk_data;
    302
    303	clk_data = hisi_clk_init(np, HIX5HD2_NR_CLKS);
    304	if (!clk_data)
    305		return;
    306
    307	hisi_clk_register_fixed_rate(hix5hd2_fixed_rate_clks,
    308				     ARRAY_SIZE(hix5hd2_fixed_rate_clks),
    309				     clk_data);
    310	hisi_clk_register_mux(hix5hd2_mux_clks, ARRAY_SIZE(hix5hd2_mux_clks),
    311					clk_data);
    312	hisi_clk_register_gate(hix5hd2_gate_clks,
    313			ARRAY_SIZE(hix5hd2_gate_clks), clk_data);
    314	hix5hd2_clk_register_complex(hix5hd2_complex_clks,
    315				     ARRAY_SIZE(hix5hd2_complex_clks),
    316				     clk_data);
    317}
    318
    319CLK_OF_DECLARE(hix5hd2_clk, "hisilicon,hix5hd2-clock", hix5hd2_clk_init);