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-a20-gmac.c (3197B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright 2013 Emilio López
      4 * Emilio López <emilio@elopez.com.ar>
      5 *
      6 * Copyright 2013 Chen-Yu Tsai
      7 * Chen-Yu Tsai <wens@csie.org>
      8 */
      9
     10#include <linux/clk-provider.h>
     11#include <linux/io.h>
     12#include <linux/of.h>
     13#include <linux/of_address.h>
     14#include <linux/slab.h>
     15
     16static DEFINE_SPINLOCK(gmac_lock);
     17
     18/**
     19 * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
     20 *
     21 * This clock looks something like this
     22 *                               ________________________
     23 *  MII TX clock from PHY >-----|___________    _________|----> to GMAC core
     24 *  GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
     25 *  Ext. 125MHz RGMII TX clk >--|__divider__/            |
     26 *                              |________________________|
     27 *
     28 * The external 125 MHz reference is optional, i.e. GMAC can use its
     29 * internal TX clock just fine. The A31 GMAC clock module does not have
     30 * the divider controls for the external reference.
     31 *
     32 * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
     33 * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
     34 * select the appropriate source and gate/ungate the output to the PHY.
     35 *
     36 * Only the GMAC should use this clock. Altering the clock so that it doesn't
     37 * match the GMAC's operation parameters will result in the GMAC not being
     38 * able to send traffic out. The GMAC driver should set the clock rate and
     39 * enable/disable this clock to configure the required state. The clock
     40 * driver then responds by auto-reparenting the clock.
     41 */
     42
     43#define SUN7I_A20_GMAC_GPIT	2
     44#define SUN7I_A20_GMAC_MASK	0x3
     45#define SUN7I_A20_GMAC_PARENTS	2
     46
     47static u32 sun7i_a20_gmac_mux_table[SUN7I_A20_GMAC_PARENTS] = {
     48	0x00, /* Select mii_phy_tx_clk */
     49	0x02, /* Select gmac_int_tx_clk */
     50};
     51
     52static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
     53{
     54	struct clk *clk;
     55	struct clk_mux *mux;
     56	struct clk_gate *gate;
     57	const char *clk_name = node->name;
     58	const char *parents[SUN7I_A20_GMAC_PARENTS];
     59	void __iomem *reg;
     60
     61	if (of_property_read_string(node, "clock-output-names", &clk_name))
     62		return;
     63
     64	/* allocate mux and gate clock structs */
     65	mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
     66	if (!mux)
     67		return;
     68
     69	gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
     70	if (!gate)
     71		goto free_mux;
     72
     73	/* gmac clock requires exactly 2 parents */
     74	if (of_clk_parent_fill(node, parents, 2) != 2)
     75		goto free_gate;
     76
     77	reg = of_iomap(node, 0);
     78	if (!reg)
     79		goto free_gate;
     80
     81	/* set up gate and fixed rate properties */
     82	gate->reg = reg;
     83	gate->bit_idx = SUN7I_A20_GMAC_GPIT;
     84	gate->lock = &gmac_lock;
     85	mux->reg = reg;
     86	mux->mask = SUN7I_A20_GMAC_MASK;
     87	mux->table = sun7i_a20_gmac_mux_table;
     88	mux->lock = &gmac_lock;
     89
     90	clk = clk_register_composite(NULL, clk_name,
     91			parents, SUN7I_A20_GMAC_PARENTS,
     92			&mux->hw, &clk_mux_ops,
     93			NULL, NULL,
     94			&gate->hw, &clk_gate_ops,
     95			0);
     96
     97	if (IS_ERR(clk))
     98		goto iounmap_reg;
     99
    100	of_clk_add_provider(node, of_clk_src_simple_get, clk);
    101
    102	return;
    103
    104iounmap_reg:
    105	iounmap(reg);
    106free_gate:
    107	kfree(gate);
    108free_mux:
    109	kfree(mux);
    110}
    111CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
    112		sun7i_a20_gmac_clk_setup);