3 * Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2, as
7 * published by the Free Software Foundation.
11 #include <linux/clk-provider.h>
12 #include <linux/err.h>
15 #include <linux/of_address.h>
17 #define MHZ (1000 * 1000)
19 #define BASE_CPU_SHIFT 1
20 #define BASE_CPU_MASK 0x7F
22 #define CPU_AHB_SHIFT 12
23 #define CPU_AHB_MASK 0x07
25 #define FIXED_BASE_SHIFT 8
26 #define FIXED_BASE_MASK 0x01
28 #define CLASSIC_BASE_SHIFT 16
29 #define CLASSIC_BASE_MASK 0x1F
31 #define CX_BASE_SHIFT 15
32 #define CX_BASE_MASK 0x3F
34 #define CX_UNKNOWN_SHIFT 21
35 #define CX_UNKNOWN_MASK 0x03
37 struct nspire_clk_info
{
44 #define EXTRACT(var, prop) (((var)>>prop##_SHIFT) & prop##_MASK)
45 static void nspire_clkinfo_cx(u32 val
, struct nspire_clk_info
*clk
)
47 if (EXTRACT(val
, FIXED_BASE
))
48 clk
->base_clock
= 48 * MHZ
;
50 clk
->base_clock
= 6 * EXTRACT(val
, CX_BASE
) * MHZ
;
52 clk
->base_cpu_ratio
= EXTRACT(val
, BASE_CPU
) * EXTRACT(val
, CX_UNKNOWN
);
53 clk
->base_ahb_ratio
= clk
->base_cpu_ratio
* (EXTRACT(val
, CPU_AHB
) + 1);
56 static void nspire_clkinfo_classic(u32 val
, struct nspire_clk_info
*clk
)
58 if (EXTRACT(val
, FIXED_BASE
))
59 clk
->base_clock
= 27 * MHZ
;
61 clk
->base_clock
= (300 - 6 * EXTRACT(val
, CLASSIC_BASE
)) * MHZ
;
63 clk
->base_cpu_ratio
= EXTRACT(val
, BASE_CPU
) * 2;
64 clk
->base_ahb_ratio
= clk
->base_cpu_ratio
* (EXTRACT(val
, CPU_AHB
) + 1);
67 static void __init
nspire_ahbdiv_setup(struct device_node
*node
,
68 void (*get_clkinfo
)(u32
, struct nspire_clk_info
*))
73 const char *clk_name
= node
->name
;
74 const char *parent_name
;
75 struct nspire_clk_info info
;
77 io
= of_iomap(node
, 0);
83 get_clkinfo(val
, &info
);
85 of_property_read_string(node
, "clock-output-names", &clk_name
);
86 parent_name
= of_clk_get_parent_name(node
, 0);
88 clk
= clk_register_fixed_factor(NULL
, clk_name
, parent_name
, 0,
89 1, info
.base_ahb_ratio
);
91 of_clk_add_provider(node
, of_clk_src_simple_get
, clk
);
94 static void __init
nspire_ahbdiv_setup_cx(struct device_node
*node
)
96 nspire_ahbdiv_setup(node
, nspire_clkinfo_cx
);
99 static void __init
nspire_ahbdiv_setup_classic(struct device_node
*node
)
101 nspire_ahbdiv_setup(node
, nspire_clkinfo_classic
);
104 CLK_OF_DECLARE(nspire_ahbdiv_cx
, "lsi,nspire-cx-ahb-divider",
105 nspire_ahbdiv_setup_cx
);
106 CLK_OF_DECLARE(nspire_ahbdiv_classic
, "lsi,nspire-classic-ahb-divider",
107 nspire_ahbdiv_setup_classic
);
109 static void __init
nspire_clk_setup(struct device_node
*node
,
110 void (*get_clkinfo
)(u32
, struct nspire_clk_info
*))
115 const char *clk_name
= node
->name
;
116 struct nspire_clk_info info
;
118 io
= of_iomap(node
, 0);
124 get_clkinfo(val
, &info
);
126 of_property_read_string(node
, "clock-output-names", &clk_name
);
128 clk
= clk_register_fixed_rate(NULL
, clk_name
, NULL
, CLK_IS_ROOT
,
131 of_clk_add_provider(node
, of_clk_src_simple_get
, clk
);
135 pr_info("TI-NSPIRE Base: %uMHz CPU: %uMHz AHB: %uMHz\n",
136 info
.base_clock
/ MHZ
,
137 info
.base_clock
/ info
.base_cpu_ratio
/ MHZ
,
138 info
.base_clock
/ info
.base_ahb_ratio
/ MHZ
);
141 static void __init
nspire_clk_setup_cx(struct device_node
*node
)
143 nspire_clk_setup(node
, nspire_clkinfo_cx
);
146 static void __init
nspire_clk_setup_classic(struct device_node
*node
)
148 nspire_clk_setup(node
, nspire_clkinfo_classic
);
151 CLK_OF_DECLARE(nspire_clk_cx
, "lsi,nspire-cx-clock", nspire_clk_setup_cx
);
152 CLK_OF_DECLARE(nspire_clk_classic
, "lsi,nspire-classic-clock",
153 nspire_clk_setup_classic
);