^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Alchemy clocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Exposes all configurable internal clock sources to the clk framework.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * We have:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * - Root source, usually 12MHz supplied by an external crystal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * - 3 PLLs which generate multiples of root rate [AUX, CPU, AUX2]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Dividers:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * - 6 clock dividers with:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * * selectable source [one of the PLLs],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * * output divided between [2 .. 512 in steps of 2] (!Au1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * or [1 .. 256 in steps of 1] (Au1300),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * * can be enabled individually.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * - up to 6 "internal" (fixed) consumers which:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * * take either AUXPLL or one of the above 6 dividers as input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * * divide this input by 1, 2, or 4 (and 3 on Au1300).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * * can be disabled separately.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Misc clocks:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * - sysbus clock: CPU core clock (CPUPLL) divided by 2, 3 or 4.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * depends on board design and should be set by bootloader, read-only.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * - peripheral clock: half the rate of sysbus clock, source for a lot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * of peripheral blocks, read-only.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * - memory clock: clk rate to main memory chips, depends on board
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * design and is read-only,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * - lrclk: the static bus clock signal for synchronous operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * depends on board design, must be set by bootloader,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * but may be required to correctly configure devices attached to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * the static bus. The Au1000/1500/1100 manuals call it LCLK, on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * later models it's called RCLK.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/clkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <asm/mach-au1x00/au1000.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* Base clock: 12MHz is the default in all databooks, and I haven't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * found any board yet which uses a different rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define ALCHEMY_ROOTCLK_RATE 12000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * the internal sources which can be driven by the PLLs and dividers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * Names taken from the databooks, refer to them for more information,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * especially which ones are share a clock line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static const char * const alchemy_au1300_intclknames[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) "lcd_intclk", "gpemgp_clk", "maempe_clk", "maebsa_clk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) "EXTCLK0", "EXTCLK1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static const char * const alchemy_au1200_intclknames[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) "lcd_intclk", NULL, NULL, NULL, "EXTCLK0", "EXTCLK1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static const char * const alchemy_au1550_intclknames[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) "usb_clk", "psc0_intclk", "psc1_intclk", "pci_clko",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) "EXTCLK0", "EXTCLK1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static const char * const alchemy_au1100_intclknames[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) "usb_clk", "lcd_intclk", NULL, "i2s_clk", "EXTCLK0", "EXTCLK1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static const char * const alchemy_au1500_intclknames[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) NULL, "usbd_clk", "usbh_clk", "pci_clko", "EXTCLK0", "EXTCLK1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static const char * const alchemy_au1000_intclknames[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) "irda_clk", "usbd_clk", "usbh_clk", "i2s_clk", "EXTCLK0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) "EXTCLK1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* aliases for a few on-chip sources which are either shared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * or have gone through name changes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static struct clk_aliastable {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) char *alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) char *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int cputype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) } alchemy_clk_aliases[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) { "usbh_clk", "usb_clk", ALCHEMY_CPU_AU1100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) { "usbd_clk", "usb_clk", ALCHEMY_CPU_AU1100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) { "irda_clk", "usb_clk", ALCHEMY_CPU_AU1100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) { "usbh_clk", "usb_clk", ALCHEMY_CPU_AU1550 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) { "usbd_clk", "usb_clk", ALCHEMY_CPU_AU1550 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) { "psc2_intclk", "usb_clk", ALCHEMY_CPU_AU1550 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) { "psc3_intclk", "EXTCLK0", ALCHEMY_CPU_AU1550 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) { "psc0_intclk", "EXTCLK0", ALCHEMY_CPU_AU1200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) { "psc1_intclk", "EXTCLK1", ALCHEMY_CPU_AU1200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) { "psc0_intclk", "EXTCLK0", ALCHEMY_CPU_AU1300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) { "psc2_intclk", "EXTCLK0", ALCHEMY_CPU_AU1300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) { "psc1_intclk", "EXTCLK1", ALCHEMY_CPU_AU1300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) { "psc3_intclk", "EXTCLK1", ALCHEMY_CPU_AU1300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) { NULL, NULL, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define IOMEM(x) ((void __iomem *)(KSEG1ADDR(CPHYSADDR(x))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* access locks to SYS_FREQCTRL0/1 and SYS_CLKSRC registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static spinlock_t alchemy_clk_fg0_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static spinlock_t alchemy_clk_fg1_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static spinlock_t alchemy_clk_csrc_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* CPU Core clock *****************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static unsigned long alchemy_clk_cpu_recalc(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) unsigned long t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * On early Au1000, sys_cpupll was write-only. Since these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * silicon versions of Au1000 are not sold, we don't bend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * over backwards trying to determine the frequency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (unlikely(au1xxx_cpu_has_pll_wo()))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) t = 396000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) t = alchemy_rdsys(AU1000_SYS_CPUPLL) & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (alchemy_get_cputype() < ALCHEMY_CPU_AU1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) t &= 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) t *= parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) void __init alchemy_set_lpj(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) preset_lpj = alchemy_clk_cpu_recalc(NULL, ALCHEMY_ROOTCLK_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) preset_lpj /= 2 * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static const struct clk_ops alchemy_clkops_cpu = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .recalc_rate = alchemy_clk_cpu_recalc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int ctype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct clk_init_data id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct clk_hw *h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) h = kzalloc(sizeof(*h), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (!h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) id.name = ALCHEMY_CPU_CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) id.parent_names = &parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) id.num_parents = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) id.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) id.ops = &alchemy_clkops_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) h->init = &id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) clk = clk_register(NULL, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) pr_err("failed to register clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) kfree(h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* AUXPLLs ************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct alchemy_auxpll_clk {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) unsigned long reg; /* au1300 has also AUXPLL2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int maxmult; /* max multiplier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define to_auxpll_clk(x) container_of(x, struct alchemy_auxpll_clk, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static unsigned long alchemy_clk_aux_recalc(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return (alchemy_rdsys(a->reg) & 0xff) * parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static int alchemy_clk_aux_setr(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) unsigned long d = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) d /= parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) d = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /* minimum is 84MHz, max is 756-1032 depending on variant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (((d < 7) && (d != 0)) || (d > a->maxmult))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) alchemy_wrsys(d, a->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static long alchemy_clk_aux_roundr(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) unsigned long *parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) unsigned long mult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (!rate || !*parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) mult = rate / (*parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (mult && (mult < 7))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) mult = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (mult > a->maxmult)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) mult = a->maxmult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return (*parent_rate) * mult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static const struct clk_ops alchemy_clkops_aux = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) .recalc_rate = alchemy_clk_aux_recalc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .set_rate = alchemy_clk_aux_setr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .round_rate = alchemy_clk_aux_roundr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static struct clk __init *alchemy_clk_setup_aux(const char *parent_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) char *name, int maxmult,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) unsigned long reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct clk_init_data id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct clk *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct alchemy_auxpll_clk *a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) a = kzalloc(sizeof(*a), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (!a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) id.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) id.parent_names = &parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) id.num_parents = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) id.flags = CLK_GET_RATE_NOCACHE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) id.ops = &alchemy_clkops_aux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) a->reg = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) a->maxmult = maxmult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) a->hw.init = &id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) c = clk_register(NULL, &a->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (!IS_ERR(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) clk_register_clkdev(c, name, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) kfree(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* sysbus_clk *********************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static struct clk __init *alchemy_clk_setup_sysbus(const char *pn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) unsigned long v = (alchemy_rdsys(AU1000_SYS_POWERCTRL) & 3) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) struct clk *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) c = clk_register_fixed_factor(NULL, ALCHEMY_SYSBUS_CLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) pn, 0, 1, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (!IS_ERR(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) clk_register_clkdev(c, ALCHEMY_SYSBUS_CLK, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* Peripheral Clock ***************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static struct clk __init *alchemy_clk_setup_periph(const char *pn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* Peripheral clock runs at half the rate of sysbus clk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct clk *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) c = clk_register_fixed_factor(NULL, ALCHEMY_PERIPH_CLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) pn, 0, 1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (!IS_ERR(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) clk_register_clkdev(c, ALCHEMY_PERIPH_CLK, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /* mem clock **********************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static struct clk __init *alchemy_clk_setup_mem(const char *pn, int ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) void __iomem *addr = IOMEM(AU1000_MEM_PHYS_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) struct clk *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) int div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) switch (ct) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) case ALCHEMY_CPU_AU1550:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) case ALCHEMY_CPU_AU1200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) v = __raw_readl(addr + AU1550_MEM_SDCONFIGB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) div = (v & (1 << 15)) ? 1 : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) case ALCHEMY_CPU_AU1300:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) v = __raw_readl(addr + AU1550_MEM_SDCONFIGB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) div = (v & (1 << 31)) ? 1 : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) case ALCHEMY_CPU_AU1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) case ALCHEMY_CPU_AU1500:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) case ALCHEMY_CPU_AU1100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) div = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) c = clk_register_fixed_factor(NULL, ALCHEMY_MEM_CLK, pn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 0, 1, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (!IS_ERR(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) clk_register_clkdev(c, ALCHEMY_MEM_CLK, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /* lrclk: external synchronous static bus clock ***********************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static struct clk __init *alchemy_clk_setup_lrclk(const char *pn, int t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* Au1000, Au1500: MEM_STCFG0[11]: If bit is set, lrclk=pclk/5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * otherwise lrclk=pclk/4.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * All other variants: MEM_STCFG0[15:13] = divisor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * L/RCLK = periph_clk / (divisor + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * On Au1000, Au1500, Au1100 it's called LCLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * on later models it's called RCLK, but it's the same thing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct clk *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) unsigned long v = alchemy_rdsmem(AU1000_MEM_STCFG0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) switch (t) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) case ALCHEMY_CPU_AU1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) case ALCHEMY_CPU_AU1500:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) v = 4 + ((v >> 11) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) default: /* all other models */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) v = ((v >> 13) & 7) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) c = clk_register_fixed_factor(NULL, ALCHEMY_LR_CLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) pn, 0, 1, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (!IS_ERR(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) clk_register_clkdev(c, ALCHEMY_LR_CLK, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /* Clock dividers and muxes *******************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /* data for fgen and csrc mux-dividers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) struct alchemy_fgcs_clk {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) spinlock_t *reglock; /* register lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) unsigned long reg; /* SYS_FREQCTRL0/1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) int shift; /* offset in register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) int parent; /* parent before disable [Au1300] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) int isen; /* is it enabled? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) int *dt; /* dividertable for csrc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) #define to_fgcs_clk(x) container_of(x, struct alchemy_fgcs_clk, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static long alchemy_calc_div(unsigned long rate, unsigned long prate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) int scale, int maxdiv, unsigned long *rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) long div1, div2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) div1 = prate / rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if ((prate / div1) > rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) div1++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (scale == 2) { /* only div-by-multiple-of-2 possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (div1 & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) div1++; /* stay <=prate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) div2 = (div1 / scale) - 1; /* value to write to register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (div2 > maxdiv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) div2 = maxdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) *rv = div2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) div1 = ((div2 + 1) * scale);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return div1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static int alchemy_clk_fgcs_detr(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct clk_rate_request *req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int scale, int maxdiv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct clk_hw *pc, *bpc, *free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) long tdv, tpr, pr, nr, br, bpr, diff, lastdiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) lastdiff = INT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) bpr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) bpc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) br = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) free = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /* look at the rates each enabled parent supplies and select
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * the one that gets closest to but not over the requested rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) for (j = 0; j < 7; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) pc = clk_hw_get_parent_by_index(hw, j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (!pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* if this parent is currently unused, remember it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * XXX: we would actually want clk_has_active_children()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * but this is a good-enough approximation for now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (!clk_hw_is_prepared(pc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (!free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) free = pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) pr = clk_hw_get_rate(pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (pr < req->rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /* what can hardware actually provide */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) nr = pr / tdv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) diff = req->rate - nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (nr > req->rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (diff < lastdiff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) lastdiff = diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) bpr = pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) bpc = pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) br = nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (diff == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /* if we couldn't get the exact rate we wanted from the enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * parents, maybe we can tell an available disabled/inactive one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * to give us a rate we can divide down to the requested rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (lastdiff && free) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) for (j = (maxdiv == 4) ? 1 : scale; j <= maxdiv; j += scale) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) tpr = req->rate * j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (tpr < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) pr = clk_hw_round_rate(free, tpr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) nr = pr / tdv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) diff = req->rate - nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (nr > req->rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (diff < lastdiff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) lastdiff = diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) bpr = pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) bpc = free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) br = nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (diff == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (br < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return br;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) req->best_parent_rate = bpr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) req->best_parent_hw = bpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) req->rate = br;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) static int alchemy_clk_fgv1_en(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) unsigned long v, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) spin_lock_irqsave(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) v = alchemy_rdsys(c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) v |= (1 << 1) << c->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) alchemy_wrsys(v, c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) spin_unlock_irqrestore(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) static int alchemy_clk_fgv1_isen(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) unsigned long v = alchemy_rdsys(c->reg) >> (c->shift + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return v & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) static void alchemy_clk_fgv1_dis(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) unsigned long v, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) spin_lock_irqsave(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) v = alchemy_rdsys(c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) v &= ~((1 << 1) << c->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) alchemy_wrsys(v, c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) spin_unlock_irqrestore(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int alchemy_clk_fgv1_setp(struct clk_hw *hw, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) unsigned long v, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) spin_lock_irqsave(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) v = alchemy_rdsys(c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) v |= (1 << c->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) v &= ~(1 << c->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) alchemy_wrsys(v, c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) spin_unlock_irqrestore(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) static u8 alchemy_clk_fgv1_getp(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return (alchemy_rdsys(c->reg) >> c->shift) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) static int alchemy_clk_fgv1_setr(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) unsigned long div, v, flags, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) int sh = c->shift + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (!rate || !parent_rate || rate > (parent_rate / 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) ret = alchemy_calc_div(rate, parent_rate, 2, 512, &div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) spin_lock_irqsave(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) v = alchemy_rdsys(c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) v &= ~(0xff << sh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) v |= div << sh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) alchemy_wrsys(v, c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) spin_unlock_irqrestore(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) unsigned long v = alchemy_rdsys(c->reg) >> (c->shift + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) v = ((v & 0xff) + 1) * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return parent_rate / v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) static int alchemy_clk_fgv1_detr(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct clk_rate_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return alchemy_clk_fgcs_detr(hw, req, 2, 512);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) /* Au1000, Au1100, Au15x0, Au12x0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) static const struct clk_ops alchemy_clkops_fgenv1 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) .recalc_rate = alchemy_clk_fgv1_recalc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) .determine_rate = alchemy_clk_fgv1_detr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) .set_rate = alchemy_clk_fgv1_setr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) .set_parent = alchemy_clk_fgv1_setp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) .get_parent = alchemy_clk_fgv1_getp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) .enable = alchemy_clk_fgv1_en,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) .disable = alchemy_clk_fgv1_dis,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) .is_enabled = alchemy_clk_fgv1_isen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static void __alchemy_clk_fgv2_en(struct alchemy_fgcs_clk *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) unsigned long v = alchemy_rdsys(c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) v &= ~(3 << c->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) v |= (c->parent & 3) << c->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) alchemy_wrsys(v, c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) c->isen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) static int alchemy_clk_fgv2_en(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* enable by setting the previous parent clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) spin_lock_irqsave(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) __alchemy_clk_fgv2_en(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) spin_unlock_irqrestore(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) static int alchemy_clk_fgv2_isen(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return ((alchemy_rdsys(c->reg) >> c->shift) & 3) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) static void alchemy_clk_fgv2_dis(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) unsigned long v, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) spin_lock_irqsave(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) v = alchemy_rdsys(c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) v &= ~(3 << c->shift); /* set input mux to "disabled" state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) alchemy_wrsys(v, c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) c->isen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) spin_unlock_irqrestore(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static int alchemy_clk_fgv2_setp(struct clk_hw *hw, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) spin_lock_irqsave(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) c->parent = index + 1; /* value to write to register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (c->isen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) __alchemy_clk_fgv2_en(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) spin_unlock_irqrestore(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) static u8 alchemy_clk_fgv2_getp(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) unsigned long flags, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) spin_lock_irqsave(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) v = c->parent - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) spin_unlock_irqrestore(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /* fg0-2 and fg4-6 share a "scale"-bit. With this bit cleared, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * dividers behave exactly as on previous models (dividers are multiples
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * of 2); with the bit set, dividers are multiples of 1, halving their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * range, but making them also much more flexible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) static int alchemy_clk_fgv2_setr(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) int sh = c->shift + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) unsigned long div, v, flags, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (!rate || !parent_rate || rate > parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) v = alchemy_rdsys(c->reg) & (1 << 30); /* test "scale" bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) ret = alchemy_calc_div(rate, parent_rate, v ? 1 : 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) v ? 256 : 512, &div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) spin_lock_irqsave(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) v = alchemy_rdsys(c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) v &= ~(0xff << sh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) v |= (div & 0xff) << sh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) alchemy_wrsys(v, c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) spin_unlock_irqrestore(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) int sh = c->shift + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) unsigned long v, t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) v = alchemy_rdsys(c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) t = parent_rate / (((v >> sh) & 0xff) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if ((v & (1 << 30)) == 0) /* test scale bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) t /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) static int alchemy_clk_fgv2_detr(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct clk_rate_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) int scale, maxdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (alchemy_rdsys(c->reg) & (1 << 30)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) scale = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) maxdiv = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) scale = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) maxdiv = 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return alchemy_clk_fgcs_detr(hw, req, scale, maxdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) /* Au1300 larger input mux, no separate disable bit, flexible divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static const struct clk_ops alchemy_clkops_fgenv2 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) .recalc_rate = alchemy_clk_fgv2_recalc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) .determine_rate = alchemy_clk_fgv2_detr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) .set_rate = alchemy_clk_fgv2_setr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) .set_parent = alchemy_clk_fgv2_setp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) .get_parent = alchemy_clk_fgv2_getp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) .enable = alchemy_clk_fgv2_en,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) .disable = alchemy_clk_fgv2_dis,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) .is_enabled = alchemy_clk_fgv2_isen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) static const char * const alchemy_clk_fgv1_parents[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) ALCHEMY_CPU_CLK, ALCHEMY_AUXPLL_CLK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static const char * const alchemy_clk_fgv2_parents[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) ALCHEMY_AUXPLL2_CLK, ALCHEMY_CPU_CLK, ALCHEMY_AUXPLL_CLK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) static const char * const alchemy_clk_fgen_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) ALCHEMY_FG0_CLK, ALCHEMY_FG1_CLK, ALCHEMY_FG2_CLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) ALCHEMY_FG3_CLK, ALCHEMY_FG4_CLK, ALCHEMY_FG5_CLK };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) static int __init alchemy_clk_init_fgens(int ctype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) struct clk *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) struct clk_init_data id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) struct alchemy_fgcs_clk *a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) switch (ctype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) id.ops = &alchemy_clkops_fgenv1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) id.parent_names = alchemy_clk_fgv1_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) id.num_parents = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) case ALCHEMY_CPU_AU1300:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) id.ops = &alchemy_clkops_fgenv2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) id.parent_names = alchemy_clk_fgv2_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) id.num_parents = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) a = kzalloc((sizeof(*a)) * 6, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (!a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) spin_lock_init(&alchemy_clk_fg0_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) spin_lock_init(&alchemy_clk_fg1_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) id.name = alchemy_clk_fgen_names[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) a->shift = 10 * (i < 3 ? i : i - 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (i > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) a->reg = AU1000_SYS_FREQCTRL1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) a->reglock = &alchemy_clk_fg1_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) a->reg = AU1000_SYS_FREQCTRL0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) a->reglock = &alchemy_clk_fg0_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) /* default to first parent if bootloader has set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * the mux to disabled state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (ctype == ALCHEMY_CPU_AU1300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) v = alchemy_rdsys(a->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) a->parent = (v >> a->shift) & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (!a->parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) a->parent = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) a->isen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) a->isen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) a->hw.init = &id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) c = clk_register(NULL, &a->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (IS_ERR(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) ret++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) clk_register_clkdev(c, id.name, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) a++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) /* internal sources muxes *********************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static int alchemy_clk_csrc_isen(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) unsigned long v = alchemy_rdsys(c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return (((v >> c->shift) >> 2) & 7) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) static void __alchemy_clk_csrc_en(struct alchemy_fgcs_clk *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) unsigned long v = alchemy_rdsys(c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) v &= ~((7 << 2) << c->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) v |= ((c->parent & 7) << 2) << c->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) alchemy_wrsys(v, c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) c->isen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static int alchemy_clk_csrc_en(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) /* enable by setting the previous parent clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) spin_lock_irqsave(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) __alchemy_clk_csrc_en(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) spin_unlock_irqrestore(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) static void alchemy_clk_csrc_dis(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) unsigned long v, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) spin_lock_irqsave(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) v = alchemy_rdsys(c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) v &= ~((3 << 2) << c->shift); /* mux to "disabled" state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) alchemy_wrsys(v, c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) c->isen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) spin_unlock_irqrestore(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) static int alchemy_clk_csrc_setp(struct clk_hw *hw, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) spin_lock_irqsave(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) c->parent = index + 1; /* value to write to register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (c->isen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) __alchemy_clk_csrc_en(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) spin_unlock_irqrestore(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) static u8 alchemy_clk_csrc_getp(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return c->parent - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) static unsigned long alchemy_clk_csrc_recalc(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) unsigned long v = (alchemy_rdsys(c->reg) >> c->shift) & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return parent_rate / c->dt[v];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) unsigned long d, v, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (!rate || !parent_rate || rate > parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) d = (parent_rate + (rate / 2)) / rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) if (d > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if ((d == 3) && (c->dt[2] != 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) d = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (c->dt[i] == d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (i >= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return -EINVAL; /* oops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) spin_lock_irqsave(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) v = alchemy_rdsys(c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) v &= ~(3 << c->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) v |= (i & 3) << c->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) alchemy_wrsys(v, c->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) spin_unlock_irqrestore(c->reglock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) static int alchemy_clk_csrc_detr(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) struct clk_rate_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return alchemy_clk_fgcs_detr(hw, req, scale, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) static const struct clk_ops alchemy_clkops_csrc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) .recalc_rate = alchemy_clk_csrc_recalc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) .determine_rate = alchemy_clk_csrc_detr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) .set_rate = alchemy_clk_csrc_setr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) .set_parent = alchemy_clk_csrc_setp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) .get_parent = alchemy_clk_csrc_getp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) .enable = alchemy_clk_csrc_en,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) .disable = alchemy_clk_csrc_dis,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) .is_enabled = alchemy_clk_csrc_isen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) static const char * const alchemy_clk_csrc_parents[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) /* disabled at index 0 */ ALCHEMY_AUXPLL_CLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) ALCHEMY_FG0_CLK, ALCHEMY_FG1_CLK, ALCHEMY_FG2_CLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) ALCHEMY_FG3_CLK, ALCHEMY_FG4_CLK, ALCHEMY_FG5_CLK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) /* divider tables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) static int alchemy_csrc_dt1[] = { 1, 4, 1, 2 }; /* rest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) static int alchemy_csrc_dt2[] = { 1, 4, 3, 2 }; /* Au1300 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) static int __init alchemy_clk_setup_imux(int ctype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) struct alchemy_fgcs_clk *a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) const char * const *names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) struct clk_init_data id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) int i, ret, *dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) struct clk *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) id.ops = &alchemy_clkops_csrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) id.parent_names = alchemy_clk_csrc_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) id.num_parents = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) dt = alchemy_csrc_dt1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) switch (ctype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) case ALCHEMY_CPU_AU1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) names = alchemy_au1000_intclknames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) case ALCHEMY_CPU_AU1500:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) names = alchemy_au1500_intclknames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) case ALCHEMY_CPU_AU1100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) names = alchemy_au1100_intclknames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) case ALCHEMY_CPU_AU1550:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) names = alchemy_au1550_intclknames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) case ALCHEMY_CPU_AU1200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) names = alchemy_au1200_intclknames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) case ALCHEMY_CPU_AU1300:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) dt = alchemy_csrc_dt2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) names = alchemy_au1300_intclknames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) a = kcalloc(6, sizeof(*a), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (!a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) spin_lock_init(&alchemy_clk_csrc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) id.name = names[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (!id.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) a->shift = i * 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) a->reg = AU1000_SYS_CLKSRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) a->reglock = &alchemy_clk_csrc_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) a->dt = dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) /* default to first parent clock if mux is initially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) * set to disabled state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) v = alchemy_rdsys(a->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) a->parent = ((v >> a->shift) >> 2) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (!a->parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) a->parent = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) a->isen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) a->isen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) a->hw.init = &id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) c = clk_register(NULL, &a->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (IS_ERR(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) ret++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) clk_register_clkdev(c, id.name, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) a++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) /**********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) #define ERRCK(x) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (IS_ERR(x)) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) ret = PTR_ERR(x); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) goto out; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) static int __init alchemy_clk_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) int ctype = alchemy_get_cputype(), ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) struct clk_aliastable *t = alchemy_clk_aliases;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) struct clk *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) /* Root of the Alchemy clock tree: external 12MHz crystal osc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) c = clk_register_fixed_rate(NULL, ALCHEMY_ROOT_CLK, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 0, ALCHEMY_ROOTCLK_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) ERRCK(c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) /* CPU core clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) c = alchemy_clk_setup_cpu(ALCHEMY_ROOT_CLK, ctype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) ERRCK(c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) /* AUXPLLs: max 1GHz on Au1300, 748MHz on older models */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) i = (ctype == ALCHEMY_CPU_AU1300) ? 84 : 63;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) c = alchemy_clk_setup_aux(ALCHEMY_ROOT_CLK, ALCHEMY_AUXPLL_CLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) i, AU1000_SYS_AUXPLL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) ERRCK(c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (ctype == ALCHEMY_CPU_AU1300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) c = alchemy_clk_setup_aux(ALCHEMY_ROOT_CLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) ALCHEMY_AUXPLL2_CLK, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) AU1300_SYS_AUXPLL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) ERRCK(c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) /* sysbus clock: cpu core clock divided by 2, 3 or 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) c = alchemy_clk_setup_sysbus(ALCHEMY_CPU_CLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) ERRCK(c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) /* peripheral clock: runs at half rate of sysbus clk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) c = alchemy_clk_setup_periph(ALCHEMY_SYSBUS_CLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) ERRCK(c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) /* SDR/DDR memory clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) c = alchemy_clk_setup_mem(ALCHEMY_SYSBUS_CLK, ctype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) ERRCK(c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) /* L/RCLK: external static bus clock for synchronous mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) c = alchemy_clk_setup_lrclk(ALCHEMY_PERIPH_CLK, ctype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) ERRCK(c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) /* Frequency dividers 0-5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) ret = alchemy_clk_init_fgens(ctype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) /* diving muxes for internal sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) ret = alchemy_clk_setup_imux(ctype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) /* set up aliases drivers might look for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) while (t->base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) if (t->cputype == ctype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) clk_add_alias(t->alias, NULL, t->base, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) t++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) pr_info("Alchemy clocktree installed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) postcore_initcall(alchemy_clk_init);