Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  linux/arch/arm/mach-sa1100/clock.c
0004  */
0005 #include <linux/kernel.h>
0006 #include <linux/errno.h>
0007 #include <linux/err.h>
0008 #include <linux/clk.h>
0009 #include <linux/clkdev.h>
0010 #include <linux/clk-provider.h>
0011 #include <linux/io.h>
0012 #include <linux/spinlock.h>
0013 
0014 #include <mach/hardware.h>
0015 #include <mach/generic.h>
0016 
0017 static const char * const clk_tucr_parents[] = {
0018     "clk32768", "clk3686400",
0019 };
0020 
0021 static DEFINE_SPINLOCK(tucr_lock);
0022 
0023 static int clk_gpio27_enable(struct clk_hw *hw)
0024 {
0025     unsigned long flags;
0026 
0027     /*
0028      * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
0029      * (SA-1110 Developer's Manual, section 9.1.2.1)
0030      */
0031     local_irq_save(flags);
0032     GAFR |= GPIO_32_768kHz;
0033     GPDR |= GPIO_32_768kHz;
0034     local_irq_restore(flags);
0035 
0036     return 0;
0037 }
0038 
0039 static void clk_gpio27_disable(struct clk_hw *hw)
0040 {
0041     unsigned long flags;
0042 
0043     local_irq_save(flags);
0044     GPDR &= ~GPIO_32_768kHz;
0045     GAFR &= ~GPIO_32_768kHz;
0046     local_irq_restore(flags);
0047 }
0048 
0049 static const struct clk_ops clk_gpio27_ops = {
0050     .enable = clk_gpio27_enable,
0051     .disable = clk_gpio27_disable,
0052 };
0053 
0054 static const char * const clk_gpio27_parents[] = {
0055     "tucr-mux",
0056 };
0057 
0058 static const struct clk_init_data clk_gpio27_init_data __initconst = {
0059     .name = "gpio27",
0060     .ops = &clk_gpio27_ops,
0061     .parent_names = clk_gpio27_parents,
0062     .num_parents = ARRAY_SIZE(clk_gpio27_parents),
0063 };
0064 
0065 /*
0066  * Derived from the table 8-1 in the SA1110 manual, the MPLL appears to
0067  * multiply its input rate by 4 x (4 + PPCR).  This calculation gives
0068  * the exact rate.  The figures given in the table are the rates rounded
0069  * to 100kHz.  Stick with sa11x0_getspeed() for the time being.
0070  */
0071 static unsigned long clk_mpll_recalc_rate(struct clk_hw *hw,
0072     unsigned long prate)
0073 {
0074     return sa11x0_getspeed(0) * 1000;
0075 }
0076 
0077 static const struct clk_ops clk_mpll_ops = {
0078     .recalc_rate = clk_mpll_recalc_rate,
0079 };
0080 
0081 static const char * const clk_mpll_parents[] = {
0082     "clk3686400",
0083 };
0084 
0085 static const struct clk_init_data clk_mpll_init_data __initconst = {
0086     .name = "mpll",
0087     .ops = &clk_mpll_ops,
0088     .parent_names = clk_mpll_parents,
0089     .num_parents = ARRAY_SIZE(clk_mpll_parents),
0090     .flags = CLK_GET_RATE_NOCACHE | CLK_IS_CRITICAL,
0091 };
0092 
0093 int __init sa11xx_clk_init(void)
0094 {
0095     struct clk_hw *hw;
0096     int ret;
0097 
0098     hw = clk_hw_register_fixed_rate(NULL, "clk32768", NULL, 0, 32768);
0099     if (IS_ERR(hw))
0100         return PTR_ERR(hw);
0101 
0102     clk_hw_register_clkdev(hw, NULL, "sa1100-rtc");
0103 
0104     hw = clk_hw_register_fixed_rate(NULL, "clk3686400", NULL, 0, 3686400);
0105     if (IS_ERR(hw))
0106         return PTR_ERR(hw);
0107 
0108     clk_hw_register_clkdev(hw, "OSTIMER0", NULL);
0109 
0110     hw = kzalloc(sizeof(*hw), GFP_KERNEL);
0111     if (!hw)
0112         return -ENOMEM;
0113     hw->init = &clk_mpll_init_data;
0114     ret = clk_hw_register(NULL, hw);
0115     if (ret) {
0116         kfree(hw);
0117         return ret;
0118     }
0119 
0120     clk_hw_register_clkdev(hw, NULL, "sa11x0-fb");
0121     clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia");
0122     clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia.0");
0123     clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia.1");
0124     clk_hw_register_clkdev(hw, NULL, "1800");
0125 
0126     hw = clk_hw_register_mux(NULL, "tucr-mux", clk_tucr_parents,
0127                  ARRAY_SIZE(clk_tucr_parents), 0,
0128                  (void __iomem *)&TUCR, FShft(TUCR_TSEL),
0129                  FAlnMsk(TUCR_TSEL), 0, &tucr_lock);
0130     clk_set_rate(hw->clk, 3686400);
0131 
0132     hw = kzalloc(sizeof(*hw), GFP_KERNEL);
0133     if (!hw)
0134         return -ENOMEM;
0135     hw->init = &clk_gpio27_init_data;
0136     ret = clk_hw_register(NULL, hw);
0137     if (ret) {
0138         kfree(hw);
0139         return ret;
0140     }
0141 
0142     clk_hw_register_clkdev(hw, NULL, "sa1111.0");
0143 
0144     return 0;
0145 }