Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *
0004  * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
0005  * Copyright (C) 2010 John Crispin <john@phrozen.org>
0006  */
0007 #include <linux/io.h>
0008 #include <linux/export.h>
0009 #include <linux/init.h>
0010 #include <linux/kernel.h>
0011 #include <linux/types.h>
0012 #include <linux/clk.h>
0013 #include <linux/clkdev.h>
0014 #include <linux/err.h>
0015 #include <linux/list.h>
0016 
0017 #include <asm/time.h>
0018 #include <asm/irq.h>
0019 #include <asm/div64.h>
0020 
0021 #include <lantiq_soc.h>
0022 
0023 #include "clk.h"
0024 #include "prom.h"
0025 
0026 /* lantiq socs have 3 static clocks */
0027 static struct clk cpu_clk_generic[4];
0028 
0029 void clkdev_add_static(unsigned long cpu, unsigned long fpi,
0030             unsigned long io, unsigned long ppe)
0031 {
0032     cpu_clk_generic[0].rate = cpu;
0033     cpu_clk_generic[1].rate = fpi;
0034     cpu_clk_generic[2].rate = io;
0035     cpu_clk_generic[3].rate = ppe;
0036 }
0037 
0038 struct clk *clk_get_cpu(void)
0039 {
0040     return &cpu_clk_generic[0];
0041 }
0042 
0043 struct clk *clk_get_fpi(void)
0044 {
0045     return &cpu_clk_generic[1];
0046 }
0047 EXPORT_SYMBOL_GPL(clk_get_fpi);
0048 
0049 struct clk *clk_get_io(void)
0050 {
0051     return &cpu_clk_generic[2];
0052 }
0053 EXPORT_SYMBOL_GPL(clk_get_io);
0054 
0055 struct clk *clk_get_ppe(void)
0056 {
0057     return &cpu_clk_generic[3];
0058 }
0059 EXPORT_SYMBOL_GPL(clk_get_ppe);
0060 
0061 static inline int clk_good(struct clk *clk)
0062 {
0063     return clk && !IS_ERR(clk);
0064 }
0065 
0066 unsigned long clk_get_rate(struct clk *clk)
0067 {
0068     if (unlikely(!clk_good(clk)))
0069         return 0;
0070 
0071     if (clk->rate != 0)
0072         return clk->rate;
0073 
0074     if (clk->get_rate != NULL)
0075         return clk->get_rate();
0076 
0077     return 0;
0078 }
0079 EXPORT_SYMBOL(clk_get_rate);
0080 
0081 int clk_set_rate(struct clk *clk, unsigned long rate)
0082 {
0083     if (unlikely(!clk_good(clk)))
0084         return 0;
0085     if (clk->rates && *clk->rates) {
0086         unsigned long *r = clk->rates;
0087 
0088         while (*r && (*r != rate))
0089             r++;
0090         if (!*r) {
0091             pr_err("clk %s.%s: trying to set invalid rate %ld\n",
0092                 clk->cl.dev_id, clk->cl.con_id, rate);
0093             return -1;
0094         }
0095     }
0096     clk->rate = rate;
0097     return 0;
0098 }
0099 EXPORT_SYMBOL(clk_set_rate);
0100 
0101 long clk_round_rate(struct clk *clk, unsigned long rate)
0102 {
0103     if (unlikely(!clk_good(clk)))
0104         return 0;
0105     if (clk->rates && *clk->rates) {
0106         unsigned long *r = clk->rates;
0107 
0108         while (*r && (*r != rate))
0109             r++;
0110         if (!*r) {
0111             return clk->rate;
0112         }
0113     }
0114     return rate;
0115 }
0116 EXPORT_SYMBOL(clk_round_rate);
0117 
0118 int clk_enable(struct clk *clk)
0119 {
0120     if (unlikely(!clk_good(clk)))
0121         return -1;
0122 
0123     if (clk->enable)
0124         return clk->enable(clk);
0125 
0126     return -1;
0127 }
0128 EXPORT_SYMBOL(clk_enable);
0129 
0130 void clk_disable(struct clk *clk)
0131 {
0132     if (unlikely(!clk_good(clk)))
0133         return;
0134 
0135     if (clk->disable)
0136         clk->disable(clk);
0137 }
0138 EXPORT_SYMBOL(clk_disable);
0139 
0140 int clk_activate(struct clk *clk)
0141 {
0142     if (unlikely(!clk_good(clk)))
0143         return -1;
0144 
0145     if (clk->activate)
0146         return clk->activate(clk);
0147 
0148     return -1;
0149 }
0150 EXPORT_SYMBOL(clk_activate);
0151 
0152 void clk_deactivate(struct clk *clk)
0153 {
0154     if (unlikely(!clk_good(clk)))
0155         return;
0156 
0157     if (clk->deactivate)
0158         clk->deactivate(clk);
0159 }
0160 EXPORT_SYMBOL(clk_deactivate);
0161 
0162 struct clk *clk_get_parent(struct clk *clk)
0163 {
0164     return NULL;
0165 }
0166 EXPORT_SYMBOL(clk_get_parent);
0167 
0168 int clk_set_parent(struct clk *clk, struct clk *parent)
0169 {
0170     return 0;
0171 }
0172 EXPORT_SYMBOL(clk_set_parent);
0173 
0174 static inline u32 get_counter_resolution(void)
0175 {
0176     u32 res;
0177 
0178     __asm__ __volatile__(
0179         ".set   push\n"
0180         ".set   mips32r2\n"
0181         "rdhwr  %0, $3\n"
0182         ".set pop\n"
0183         : "=&r" (res)
0184         : /* no input */
0185         : "memory");
0186 
0187     return res;
0188 }
0189 
0190 void __init plat_time_init(void)
0191 {
0192     struct clk *clk;
0193 
0194     ltq_soc_init();
0195 
0196     clk = clk_get_cpu();
0197     mips_hpt_frequency = clk_get_rate(clk) / get_counter_resolution();
0198     write_c0_compare(read_c0_count());
0199     pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
0200     clk_put(clk);
0201 }