^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) * linux/arch/arm/mach-sa1100/clock.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/clkdev.h>
^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/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <mach/hardware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <mach/generic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static const char * const clk_tucr_parents[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) "clk32768", "clk3686400",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static DEFINE_SPINLOCK(tucr_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static int clk_gpio27_enable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) unsigned long flags;
^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) * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * (SA-1110 Developer's Manual, section 9.1.2.1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) GAFR |= GPIO_32_768kHz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) GPDR |= GPIO_32_768kHz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void clk_gpio27_disable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) GPDR &= ~GPIO_32_768kHz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) GAFR &= ~GPIO_32_768kHz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static const struct clk_ops clk_gpio27_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .enable = clk_gpio27_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .disable = clk_gpio27_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static const char * const clk_gpio27_parents[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) "tucr-mux",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static const struct clk_init_data clk_gpio27_init_data __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .name = "gpio27",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .ops = &clk_gpio27_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .parent_names = clk_gpio27_parents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .num_parents = ARRAY_SIZE(clk_gpio27_parents),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) };
^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) * Derived from the table 8-1 in the SA1110 manual, the MPLL appears to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * multiply its input rate by 4 x (4 + PPCR). This calculation gives
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * the exact rate. The figures given in the table are the rates rounded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * to 100kHz. Stick with sa11x0_getspeed() for the time being.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static unsigned long clk_mpll_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned long prate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return sa11x0_getspeed(0) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static const struct clk_ops clk_mpll_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .recalc_rate = clk_mpll_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static const char * const clk_mpll_parents[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) "clk3686400",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static const struct clk_init_data clk_mpll_init_data __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .name = "mpll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .ops = &clk_mpll_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .parent_names = clk_mpll_parents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .num_parents = ARRAY_SIZE(clk_mpll_parents),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .flags = CLK_GET_RATE_NOCACHE | CLK_IS_CRITICAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int __init sa11xx_clk_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) hw = clk_hw_register_fixed_rate(NULL, "clk32768", NULL, 0, 32768);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (IS_ERR(hw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return PTR_ERR(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) clk_hw_register_clkdev(hw, NULL, "sa1100-rtc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) hw = clk_hw_register_fixed_rate(NULL, "clk3686400", NULL, 0, 3686400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (IS_ERR(hw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return PTR_ERR(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) clk_hw_register_clkdev(hw, "OSTIMER0", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) hw = kzalloc(sizeof(*hw), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (!hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) hw->init = &clk_mpll_init_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ret = clk_hw_register(NULL, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) kfree(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) clk_hw_register_clkdev(hw, NULL, "sa11x0-fb");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia.0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia.1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) clk_hw_register_clkdev(hw, NULL, "1800");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) hw = clk_hw_register_mux(NULL, "tucr-mux", clk_tucr_parents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ARRAY_SIZE(clk_tucr_parents), 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) (void __iomem *)&TUCR, FShft(TUCR_TSEL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) FAlnMsk(TUCR_TSEL), 0, &tucr_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) clk_set_rate(hw->clk, 3686400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) hw = kzalloc(sizeof(*hw), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (!hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) hw->init = &clk_gpio27_init_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ret = clk_hw_register(NULL, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) kfree(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) clk_hw_register_clkdev(hw, NULL, "sa1111.0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }