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-en7523.c (8124B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2
      3#include <linux/delay.h>
      4#include <linux/clk-provider.h>
      5#include <linux/of.h>
      6#include <linux/of_address.h>
      7#include <linux/of_device.h>
      8#include <linux/platform_device.h>
      9#include <dt-bindings/clock/en7523-clk.h>
     10
     11#define REG_PCI_CONTROL			0x88
     12#define   REG_PCI_CONTROL_PERSTOUT	BIT(29)
     13#define   REG_PCI_CONTROL_PERSTOUT1	BIT(26)
     14#define   REG_PCI_CONTROL_REFCLK_EN1	BIT(22)
     15#define REG_GSW_CLK_DIV_SEL		0x1b4
     16#define REG_EMI_CLK_DIV_SEL		0x1b8
     17#define REG_BUS_CLK_DIV_SEL		0x1bc
     18#define REG_SPI_CLK_DIV_SEL		0x1c4
     19#define REG_SPI_CLK_FREQ_SEL		0x1c8
     20#define REG_NPU_CLK_DIV_SEL		0x1fc
     21#define REG_CRYPTO_CLKSRC		0x200
     22#define REG_RESET_CONTROL		0x834
     23#define   REG_RESET_CONTROL_PCIEHB	BIT(29)
     24#define   REG_RESET_CONTROL_PCIE1	BIT(27)
     25#define   REG_RESET_CONTROL_PCIE2	BIT(26)
     26
     27struct en_clk_desc {
     28	int id;
     29	const char *name;
     30	u32 base_reg;
     31	u8 base_bits;
     32	u8 base_shift;
     33	union {
     34		const unsigned int *base_values;
     35		unsigned int base_value;
     36	};
     37	size_t n_base_values;
     38
     39	u16 div_reg;
     40	u8 div_bits;
     41	u8 div_shift;
     42	u16 div_val0;
     43	u8 div_step;
     44};
     45
     46struct en_clk_gate {
     47	void __iomem *base;
     48	struct clk_hw hw;
     49};
     50
     51static const u32 gsw_base[] = { 400000000, 500000000 };
     52static const u32 emi_base[] = { 333000000, 400000000 };
     53static const u32 bus_base[] = { 500000000, 540000000 };
     54static const u32 slic_base[] = { 100000000, 3125000 };
     55static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
     56
     57static const struct en_clk_desc en7523_base_clks[] = {
     58	{
     59		.id = EN7523_CLK_GSW,
     60		.name = "gsw",
     61
     62		.base_reg = REG_GSW_CLK_DIV_SEL,
     63		.base_bits = 1,
     64		.base_shift = 8,
     65		.base_values = gsw_base,
     66		.n_base_values = ARRAY_SIZE(gsw_base),
     67
     68		.div_bits = 3,
     69		.div_shift = 0,
     70		.div_step = 1,
     71	}, {
     72		.id = EN7523_CLK_EMI,
     73		.name = "emi",
     74
     75		.base_reg = REG_EMI_CLK_DIV_SEL,
     76		.base_bits = 1,
     77		.base_shift = 8,
     78		.base_values = emi_base,
     79		.n_base_values = ARRAY_SIZE(emi_base),
     80
     81		.div_bits = 3,
     82		.div_shift = 0,
     83		.div_step = 1,
     84	}, {
     85		.id = EN7523_CLK_BUS,
     86		.name = "bus",
     87
     88		.base_reg = REG_BUS_CLK_DIV_SEL,
     89		.base_bits = 1,
     90		.base_shift = 8,
     91		.base_values = bus_base,
     92		.n_base_values = ARRAY_SIZE(bus_base),
     93
     94		.div_bits = 3,
     95		.div_shift = 0,
     96		.div_step = 1,
     97	}, {
     98		.id = EN7523_CLK_SLIC,
     99		.name = "slic",
    100
    101		.base_reg = REG_SPI_CLK_FREQ_SEL,
    102		.base_bits = 1,
    103		.base_shift = 0,
    104		.base_values = slic_base,
    105		.n_base_values = ARRAY_SIZE(slic_base),
    106
    107		.div_reg = REG_SPI_CLK_DIV_SEL,
    108		.div_bits = 5,
    109		.div_shift = 24,
    110		.div_val0 = 20,
    111		.div_step = 2,
    112	}, {
    113		.id = EN7523_CLK_SPI,
    114		.name = "spi",
    115
    116		.base_reg = REG_SPI_CLK_DIV_SEL,
    117
    118		.base_value = 400000000,
    119
    120		.div_bits = 5,
    121		.div_shift = 8,
    122		.div_val0 = 40,
    123		.div_step = 2,
    124	}, {
    125		.id = EN7523_CLK_NPU,
    126		.name = "npu",
    127
    128		.base_reg = REG_NPU_CLK_DIV_SEL,
    129		.base_bits = 2,
    130		.base_shift = 8,
    131		.base_values = npu_base,
    132		.n_base_values = ARRAY_SIZE(npu_base),
    133
    134		.div_bits = 3,
    135		.div_shift = 0,
    136		.div_step = 1,
    137	}, {
    138		.id = EN7523_CLK_CRYPTO,
    139		.name = "crypto",
    140
    141		.base_reg = REG_CRYPTO_CLKSRC,
    142		.base_bits = 1,
    143		.base_shift = 8,
    144		.base_values = emi_base,
    145		.n_base_values = ARRAY_SIZE(emi_base),
    146	}
    147};
    148
    149static const struct of_device_id of_match_clk_en7523[] = {
    150	{ .compatible = "airoha,en7523-scu", },
    151	{ /* sentinel */ }
    152};
    153
    154static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
    155{
    156	const struct en_clk_desc *desc = &en7523_base_clks[i];
    157	u32 val;
    158
    159	if (!desc->base_bits)
    160		return desc->base_value;
    161
    162	val = readl(base + desc->base_reg);
    163	val >>= desc->base_shift;
    164	val &= (1 << desc->base_bits) - 1;
    165
    166	if (val >= desc->n_base_values)
    167		return 0;
    168
    169	return desc->base_values[val];
    170}
    171
    172static u32 en7523_get_div(void __iomem *base, int i)
    173{
    174	const struct en_clk_desc *desc = &en7523_base_clks[i];
    175	u32 reg, val;
    176
    177	if (!desc->div_bits)
    178		return 1;
    179
    180	reg = desc->div_reg ? desc->div_reg : desc->base_reg;
    181	val = readl(base + reg);
    182	val >>= desc->div_shift;
    183	val &= (1 << desc->div_bits) - 1;
    184
    185	if (!val && desc->div_val0)
    186		return desc->div_val0;
    187
    188	return (val + 1) * desc->div_step;
    189}
    190
    191static int en7523_pci_is_enabled(struct clk_hw *hw)
    192{
    193	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
    194
    195	return !!(readl(cg->base + REG_PCI_CONTROL) & REG_PCI_CONTROL_REFCLK_EN1);
    196}
    197
    198static int en7523_pci_prepare(struct clk_hw *hw)
    199{
    200	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
    201	void __iomem *np_base = cg->base;
    202	u32 val, mask;
    203
    204	/* Need to pull device low before reset */
    205	val = readl(np_base + REG_PCI_CONTROL);
    206	val &= ~(REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT);
    207	writel(val, np_base + REG_PCI_CONTROL);
    208	usleep_range(1000, 2000);
    209
    210	/* Enable PCIe port 1 */
    211	val |= REG_PCI_CONTROL_REFCLK_EN1;
    212	writel(val, np_base + REG_PCI_CONTROL);
    213	usleep_range(1000, 2000);
    214
    215	/* Reset to default */
    216	val = readl(np_base + REG_RESET_CONTROL);
    217	mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
    218	       REG_RESET_CONTROL_PCIEHB;
    219	writel(val & ~mask, np_base + REG_RESET_CONTROL);
    220	usleep_range(1000, 2000);
    221	writel(val | mask, np_base + REG_RESET_CONTROL);
    222	msleep(100);
    223	writel(val & ~mask, np_base + REG_RESET_CONTROL);
    224	usleep_range(5000, 10000);
    225
    226	/* Release device */
    227	mask = REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT;
    228	val = readl(np_base + REG_PCI_CONTROL);
    229	writel(val & ~mask, np_base + REG_PCI_CONTROL);
    230	usleep_range(1000, 2000);
    231	writel(val | mask, np_base + REG_PCI_CONTROL);
    232	msleep(250);
    233
    234	return 0;
    235}
    236
    237static void en7523_pci_unprepare(struct clk_hw *hw)
    238{
    239	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
    240	void __iomem *np_base = cg->base;
    241	u32 val;
    242
    243	val = readl(np_base + REG_PCI_CONTROL);
    244	val &= ~REG_PCI_CONTROL_REFCLK_EN1;
    245	writel(val, np_base + REG_PCI_CONTROL);
    246}
    247
    248static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
    249					       void __iomem *np_base)
    250{
    251	static const struct clk_ops pcie_gate_ops = {
    252		.is_enabled = en7523_pci_is_enabled,
    253		.prepare = en7523_pci_prepare,
    254		.unprepare = en7523_pci_unprepare,
    255	};
    256	struct clk_init_data init = {
    257		.name = "pcie",
    258		.ops = &pcie_gate_ops,
    259	};
    260	struct en_clk_gate *cg;
    261
    262	cg = devm_kzalloc(dev, sizeof(*cg), GFP_KERNEL);
    263	if (!cg)
    264		return NULL;
    265
    266	cg->base = np_base;
    267	cg->hw.init = &init;
    268	en7523_pci_unprepare(&cg->hw);
    269
    270	if (clk_hw_register(dev, &cg->hw))
    271		return NULL;
    272
    273	return &cg->hw;
    274}
    275
    276static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
    277				   void __iomem *base, void __iomem *np_base)
    278{
    279	struct clk_hw *hw;
    280	u32 rate;
    281	int i;
    282
    283	for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
    284		const struct en_clk_desc *desc = &en7523_base_clks[i];
    285
    286		rate = en7523_get_base_rate(base, i);
    287		rate /= en7523_get_div(base, i);
    288
    289		hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
    290		if (IS_ERR(hw)) {
    291			pr_err("Failed to register clk %s: %ld\n",
    292			       desc->name, PTR_ERR(hw));
    293			continue;
    294		}
    295
    296		clk_data->hws[desc->id] = hw;
    297	}
    298
    299	hw = en7523_register_pcie_clk(dev, np_base);
    300	clk_data->hws[EN7523_CLK_PCIE] = hw;
    301
    302	clk_data->num = EN7523_NUM_CLOCKS;
    303}
    304
    305static int en7523_clk_probe(struct platform_device *pdev)
    306{
    307	struct device_node *node = pdev->dev.of_node;
    308	struct clk_hw_onecell_data *clk_data;
    309	void __iomem *base, *np_base;
    310	int r;
    311
    312	base = devm_platform_ioremap_resource(pdev, 0);
    313	if (IS_ERR(base))
    314		return PTR_ERR(base);
    315
    316	np_base = devm_platform_ioremap_resource(pdev, 1);
    317	if (IS_ERR(np_base))
    318		return PTR_ERR(np_base);
    319
    320	clk_data = devm_kzalloc(&pdev->dev,
    321				struct_size(clk_data, hws, EN7523_NUM_CLOCKS),
    322				GFP_KERNEL);
    323	if (!clk_data)
    324		return -ENOMEM;
    325
    326	en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
    327
    328	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
    329	if (r)
    330		dev_err(&pdev->dev,
    331			"could not register clock provider: %s: %d\n",
    332			pdev->name, r);
    333
    334	return r;
    335}
    336
    337static struct platform_driver clk_en7523_drv = {
    338	.probe = en7523_clk_probe,
    339	.driver = {
    340		.name = "clk-en7523",
    341		.of_match_table = of_match_clk_en7523,
    342		.suppress_bind_attrs = true,
    343	},
    344};
    345
    346static int __init clk_en7523_init(void)
    347{
    348	return platform_driver_register(&clk_en7523_drv);
    349}
    350
    351arch_initcall(clk_en7523_init);