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