0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/clk.h>
0014 #include <linux/clk-provider.h>
0015 #include <linux/device.h>
0016 #include <linux/err.h>
0017 #include <linux/init.h>
0018 #include <linux/io.h>
0019 #include <linux/pm.h>
0020 #include <linux/slab.h>
0021 #include <linux/sys_soc.h>
0022
0023 #include "rcar-cpg-lib.h"
0024
0025 spinlock_t cpg_lock;
0026
0027 void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set)
0028 {
0029 unsigned long flags;
0030 u32 val;
0031
0032 spin_lock_irqsave(&cpg_lock, flags);
0033 val = readl(reg);
0034 val &= ~clear;
0035 val |= set;
0036 writel(val, reg);
0037 spin_unlock_irqrestore(&cpg_lock, flags);
0038 };
0039
0040 static int cpg_simple_notifier_call(struct notifier_block *nb,
0041 unsigned long action, void *data)
0042 {
0043 struct cpg_simple_notifier *csn =
0044 container_of(nb, struct cpg_simple_notifier, nb);
0045
0046 switch (action) {
0047 case PM_EVENT_SUSPEND:
0048 csn->saved = readl(csn->reg);
0049 return NOTIFY_OK;
0050
0051 case PM_EVENT_RESUME:
0052 writel(csn->saved, csn->reg);
0053 return NOTIFY_OK;
0054 }
0055 return NOTIFY_DONE;
0056 }
0057
0058 void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
0059 struct cpg_simple_notifier *csn)
0060 {
0061 csn->nb.notifier_call = cpg_simple_notifier_call;
0062 raw_notifier_chain_register(notifiers, &csn->nb);
0063 }
0064
0065
0066
0067
0068
0069 #define SDnSRCFC_SHIFT 2
0070 #define STPnHCK BIT(9 - SDnSRCFC_SHIFT)
0071
0072 static const struct clk_div_table cpg_sdh_div_table[] = {
0073 { 0, 1 }, { 1, 2 }, { STPnHCK | 2, 4 }, { STPnHCK | 3, 8 },
0074 { STPnHCK | 4, 16 }, { 0, 0 },
0075 };
0076
0077 struct clk * __init cpg_sdh_clk_register(const char *name,
0078 void __iomem *sdnckcr, const char *parent_name,
0079 struct raw_notifier_head *notifiers)
0080 {
0081 struct cpg_simple_notifier *csn;
0082 struct clk *clk;
0083
0084 csn = kzalloc(sizeof(*csn), GFP_KERNEL);
0085 if (!csn)
0086 return ERR_PTR(-ENOMEM);
0087
0088 csn->reg = sdnckcr;
0089
0090 clk = clk_register_divider_table(NULL, name, parent_name, 0, sdnckcr,
0091 SDnSRCFC_SHIFT, 8, 0, cpg_sdh_div_table,
0092 &cpg_lock);
0093 if (IS_ERR(clk)) {
0094 kfree(csn);
0095 return clk;
0096 }
0097
0098 cpg_simple_notifier_register(notifiers, csn);
0099 return clk;
0100 }
0101
0102 static const struct clk_div_table cpg_sd_div_table[] = {
0103 { 0, 2 }, { 1, 4 }, { 0, 0 },
0104 };
0105
0106 struct clk * __init cpg_sd_clk_register(const char *name,
0107 void __iomem *sdnckcr, const char *parent_name)
0108 {
0109 return clk_register_divider_table(NULL, name, parent_name, 0, sdnckcr,
0110 0, 2, 0, cpg_sd_div_table, &cpg_lock);
0111 }
0112
0113 struct rpc_clock {
0114 struct clk_divider div;
0115 struct clk_gate gate;
0116
0117
0118
0119
0120 struct cpg_simple_notifier csn;
0121 };
0122
0123 static const struct clk_div_table cpg_rpc_div_table[] = {
0124 { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 0, 0 },
0125 };
0126
0127 struct clk * __init cpg_rpc_clk_register(const char *name,
0128 void __iomem *rpcckcr, const char *parent_name,
0129 struct raw_notifier_head *notifiers)
0130 {
0131 struct rpc_clock *rpc;
0132 struct clk *clk;
0133
0134 rpc = kzalloc(sizeof(*rpc), GFP_KERNEL);
0135 if (!rpc)
0136 return ERR_PTR(-ENOMEM);
0137
0138 rpc->div.reg = rpcckcr;
0139 rpc->div.width = 3;
0140 rpc->div.table = cpg_rpc_div_table;
0141 rpc->div.lock = &cpg_lock;
0142
0143 rpc->gate.reg = rpcckcr;
0144 rpc->gate.bit_idx = 8;
0145 rpc->gate.flags = CLK_GATE_SET_TO_DISABLE;
0146 rpc->gate.lock = &cpg_lock;
0147
0148 rpc->csn.reg = rpcckcr;
0149
0150 clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
0151 &rpc->div.hw, &clk_divider_ops,
0152 &rpc->gate.hw, &clk_gate_ops,
0153 CLK_SET_RATE_PARENT);
0154 if (IS_ERR(clk)) {
0155 kfree(rpc);
0156 return clk;
0157 }
0158
0159 cpg_simple_notifier_register(notifiers, &rpc->csn);
0160 return clk;
0161 }
0162
0163 struct rpcd2_clock {
0164 struct clk_fixed_factor fixed;
0165 struct clk_gate gate;
0166 };
0167
0168 struct clk * __init cpg_rpcd2_clk_register(const char *name,
0169 void __iomem *rpcckcr,
0170 const char *parent_name)
0171 {
0172 struct rpcd2_clock *rpcd2;
0173 struct clk *clk;
0174
0175 rpcd2 = kzalloc(sizeof(*rpcd2), GFP_KERNEL);
0176 if (!rpcd2)
0177 return ERR_PTR(-ENOMEM);
0178
0179 rpcd2->fixed.mult = 1;
0180 rpcd2->fixed.div = 2;
0181
0182 rpcd2->gate.reg = rpcckcr;
0183 rpcd2->gate.bit_idx = 9;
0184 rpcd2->gate.flags = CLK_GATE_SET_TO_DISABLE;
0185 rpcd2->gate.lock = &cpg_lock;
0186
0187 clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
0188 &rpcd2->fixed.hw, &clk_fixed_factor_ops,
0189 &rpcd2->gate.hw, &clk_gate_ops,
0190 CLK_SET_RATE_PARENT);
0191 if (IS_ERR(clk))
0192 kfree(rpcd2);
0193
0194 return clk;
0195 }
0196