1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2021 Semihalf. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/bus.h> 30 #include <sys/kernel.h> 31 #include <sys/module.h> 32 #include <sys/mutex.h> 33 #include <sys/rman.h> 34 #include <machine/bus.h> 35 36 #include <dev/fdt/simplebus.h> 37 38 #include <dev/extres/clk/clk.h> 39 #include <dev/extres/clk/clk_fixed.h> 40 41 #include <dev/ofw/ofw_bus.h> 42 #include <dev/ofw/ofw_bus_subr.h> 43 44 #include "clkdev_if.h" 45 #include "periph.h" 46 47 #define NB_DEV_COUNT 17 48 49 static struct clk_div_table a37x0_periph_clk_table_6 [] = { 50 { .value = 1, .divider = 1 }, 51 { .value = 2, .divider = 2 }, 52 { .value = 3, .divider = 3 }, 53 { .value = 4, .divider = 4 }, 54 { .value = 5, .divider = 5 }, 55 { .value = 6, .divider = 6 }, 56 { .value = 0, .divider = 0 } 57 }; 58 59 static struct clk_div_table a37x0_periph_clk_table_2 [] = { 60 { .value = 0, .divider = 1 }, 61 { .value = 1, .divider = 2 }, 62 { .value = 2, .divider = 4 }, 63 { .value = 3, .divider = 1 } 64 }; 65 66 static struct a37x0_periph_clknode_def a37x0_nb_devices [] = { 67 CLK_FULL_DD("mmc", 0, 2, 0, 0, DIV_SEL2, DIV_SEL2, 16, 13, 68 "tbg_mux_mmc_50", "div1_mmc_51", "div2_mmc_52", "clk_mux_mmc_53"), 69 CLK_FULL_DD("sata_host", 1, 3, 2, 1, DIV_SEL2, DIV_SEL2, 10, 7, 70 "tbg_sata_host_mmc_55", "div1_sata_host_56", "div2_sata_host_57", 71 "clk_sata_host_mmc_58"), 72 CLK_FULL_DD("sec_at", 2, 6, 4, 2, DIV_SEL1, DIV_SEL1, 3, 0, 73 "tbg_mux_sec_at_60", "div1_sec_at_61", "div2_sec_at_62", 74 "clk_mux_sec_at_63"), 75 CLK_FULL_DD("sec_dap", 3, 7, 6, 3, DIV_SEL1, DIV_SEL1, 9, 6, 76 "tbg_mux_sec_dap_65", "div1_sec_dap_67", "div2_sec_dap_68", 77 "clk_mux_sec_dap_69"), 78 CLK_FULL_DD("tsecm", 4, 8, 8, 4, DIV_SEL1, DIV_SEL1, 15, 12, 79 "tbg_mux_tsecm_71", "div1_tsecm_72", "div2_tsecm_73", 80 "clk_mux_tsecm_74"), 81 CLK_FULL("setm_tmx", 5, 10, 10, 5, DIV_SEL1, 18, 82 a37x0_periph_clk_table_6, "tbg_mux_setm_tmx_76", 83 "div1_setm_tmx_77", "clk_mux_setm_tmx_78"), 84 CLK_FIXED("avs", 6, 11, 6, "mux_avs_80", "fixed1_avs_82"), 85 CLK_FULL_DD("pwm", 7, 13, 14, 8, DIV_SEL0, DIV_SEL0, 3, 0, 86 "tbg_mux_pwm_83", "div1_pwm_84", "div2_pwm_85", "clk_mux_pwm_86"), 87 CLK_FULL_DD("sqf", 8, 12, 12, 7, DIV_SEL1, DIV_SEL1, 27, 14, 88 "tbg_mux_sqf_88", "div1_sqf_89", "div2_sqf_90", "clk_mux_sqf_91"), 89 CLK_GATE("i2c_2", 9, 16, NULL), 90 CLK_GATE("i2c_1", 10, 17, NULL), 91 CLK_MUX_GATE_FIXED("ddr_phy", 11, 19, 10, "mux_ddr_phy_95", 92 "gate_ddr_phy_96", "fixed1_ddr_phy_97"), 93 CLK_FULL_DD("ddr_fclk", 12, 21, 16, 11, DIV_SEL0, DIV_SEL0, 15, 12, 94 "tbg_mux_ddr_fclk_99", "div1_ddr_fclk_100", "div2_ddr_fclk_101", 95 "clk_mux_ddr_fclk_102"), 96 CLK_FULL("trace", 13, 22, 18, 12, DIV_SEL0, 20, 97 a37x0_periph_clk_table_6, "tbg_mux_trace_104", "div1_trace_105", 98 "clk_mux_trace_106"), 99 CLK_FULL("counter", 14, 23, 20, 13, DIV_SEL0, 23, 100 a37x0_periph_clk_table_6, "tbg_mux_counter_108", 101 "div1_counter_109", "clk_mux_counter_110"), 102 CLK_FULL_DD("eip97", 15, 26, 24, 9, DIV_SEL2, DIV_SEL2, 22, 19, 103 "tbg_mux_eip97_112", "div1_eip97_113", "div2_eip97_114", 104 "clk_mux_eip97_115"), 105 CLK_CPU("cpu", 16, 22, 15, DIV_SEL0, 28, a37x0_periph_clk_table_2, 106 "tbg_mux_cpu_117", "div1_cpu_118"), 107 }; 108 109 static struct ofw_compat_data a37x0_periph_compat_data [] = { 110 { "marvell,armada-3700-periph-clock-nb", 1 }, 111 { NULL, 0 } 112 }; 113 114 static int a37x0_nb_periph_clk_attach(device_t); 115 static int a37x0_nb_periph_clk_probe(device_t); 116 117 static device_method_t a37x0_nb_periph_clk_methods[] = { 118 DEVMETHOD(clkdev_device_unlock, a37x0_periph_clk_device_unlock), 119 DEVMETHOD(clkdev_device_lock, a37x0_periph_clk_device_lock), 120 DEVMETHOD(clkdev_read_4, a37x0_periph_clk_read_4), 121 122 DEVMETHOD(device_attach, a37x0_nb_periph_clk_attach), 123 DEVMETHOD(device_detach, a37x0_periph_clk_detach), 124 DEVMETHOD(device_probe, a37x0_nb_periph_clk_probe), 125 126 DEVMETHOD_END 127 }; 128 129 static driver_t a37x0_nb_periph_driver = { 130 "a37x0_nb_periph_driver", 131 a37x0_nb_periph_clk_methods, 132 sizeof(struct a37x0_periph_clk_softc) 133 }; 134 135 EARLY_DRIVER_MODULE(a37x0_nb_periph, simplebus, a37x0_nb_periph_driver, 0, 0, 136 BUS_PASS_TIMER + BUS_PASS_ORDER_LATE); 137 138 static int 139 a37x0_nb_periph_clk_attach(device_t dev) 140 { 141 struct a37x0_periph_clk_softc *sc; 142 143 sc = device_get_softc(dev); 144 sc->devices = a37x0_nb_devices; 145 sc->device_count = NB_DEV_COUNT; 146 147 return (a37x0_periph_clk_attach(dev)); 148 } 149 150 static int 151 a37x0_nb_periph_clk_probe(device_t dev) 152 { 153 154 if (!ofw_bus_status_okay(dev)) 155 return (ENXIO); 156 157 if (!ofw_bus_search_compatible(dev, 158 a37x0_periph_compat_data)->ocd_data) 159 return (ENXIO); 160 161 device_set_desc(dev, "marvell,armada-3700-nb-periph-clock"); 162 163 return (BUS_PROBE_DEFAULT); 164 } 165