0001
0002
0003
0004
0005
0006 #include <linux/clk.h>
0007 #include <linux/clk-provider.h>
0008 #include <linux/clkdev.h>
0009 #include <linux/clk/at91_pmc.h>
0010 #include <linux/of.h>
0011 #include <linux/of_address.h>
0012 #include <linux/mfd/syscon.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/regmap.h>
0015 #include <linux/syscore_ops.h>
0016
0017 #include <asm/proc-fns.h>
0018
0019 #include "pmc.h"
0020
0021 #define PMC_MAX_IDS 128
0022 #define PMC_MAX_PCKS 8
0023
0024 int of_at91_get_clk_range(struct device_node *np, const char *propname,
0025 struct clk_range *range)
0026 {
0027 u32 min, max;
0028 int ret;
0029
0030 ret = of_property_read_u32_index(np, propname, 0, &min);
0031 if (ret)
0032 return ret;
0033
0034 ret = of_property_read_u32_index(np, propname, 1, &max);
0035 if (ret)
0036 return ret;
0037
0038 if (range) {
0039 range->min = min;
0040 range->max = max;
0041 }
0042
0043 return 0;
0044 }
0045 EXPORT_SYMBOL_GPL(of_at91_get_clk_range);
0046
0047 struct clk_hw *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data)
0048 {
0049 unsigned int type = clkspec->args[0];
0050 unsigned int idx = clkspec->args[1];
0051 struct pmc_data *pmc_data = data;
0052
0053 switch (type) {
0054 case PMC_TYPE_CORE:
0055 if (idx < pmc_data->ncore)
0056 return pmc_data->chws[idx];
0057 break;
0058 case PMC_TYPE_SYSTEM:
0059 if (idx < pmc_data->nsystem)
0060 return pmc_data->shws[idx];
0061 break;
0062 case PMC_TYPE_PERIPHERAL:
0063 if (idx < pmc_data->nperiph)
0064 return pmc_data->phws[idx];
0065 break;
0066 case PMC_TYPE_GCK:
0067 if (idx < pmc_data->ngck)
0068 return pmc_data->ghws[idx];
0069 break;
0070 case PMC_TYPE_PROGRAMMABLE:
0071 if (idx < pmc_data->npck)
0072 return pmc_data->pchws[idx];
0073 break;
0074 default:
0075 break;
0076 }
0077
0078 pr_err("%s: invalid type (%u) or index (%u)\n", __func__, type, idx);
0079
0080 return ERR_PTR(-EINVAL);
0081 }
0082
0083 struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
0084 unsigned int nperiph, unsigned int ngck,
0085 unsigned int npck)
0086 {
0087 unsigned int num_clks = ncore + nsystem + nperiph + ngck + npck;
0088 struct pmc_data *pmc_data;
0089
0090 pmc_data = kzalloc(struct_size(pmc_data, hwtable, num_clks),
0091 GFP_KERNEL);
0092 if (!pmc_data)
0093 return NULL;
0094
0095 pmc_data->ncore = ncore;
0096 pmc_data->chws = pmc_data->hwtable;
0097
0098 pmc_data->nsystem = nsystem;
0099 pmc_data->shws = pmc_data->chws + ncore;
0100
0101 pmc_data->nperiph = nperiph;
0102 pmc_data->phws = pmc_data->shws + nsystem;
0103
0104 pmc_data->ngck = ngck;
0105 pmc_data->ghws = pmc_data->phws + nperiph;
0106
0107 pmc_data->npck = npck;
0108 pmc_data->pchws = pmc_data->ghws + ngck;
0109
0110 return pmc_data;
0111 }
0112
0113 #ifdef CONFIG_PM
0114
0115
0116 static void __iomem *at91_pmc_backup_suspend;
0117
0118 static int at91_pmc_suspend(void)
0119 {
0120 unsigned int backup;
0121
0122 if (!at91_pmc_backup_suspend)
0123 return 0;
0124
0125 backup = readl_relaxed(at91_pmc_backup_suspend);
0126 if (!backup)
0127 return 0;
0128
0129 return clk_save_context();
0130 }
0131
0132 static void at91_pmc_resume(void)
0133 {
0134 unsigned int backup;
0135
0136 if (!at91_pmc_backup_suspend)
0137 return;
0138
0139 backup = readl_relaxed(at91_pmc_backup_suspend);
0140 if (!backup)
0141 return;
0142
0143 clk_restore_context();
0144 }
0145
0146 static struct syscore_ops pmc_syscore_ops = {
0147 .suspend = at91_pmc_suspend,
0148 .resume = at91_pmc_resume,
0149 };
0150
0151 static const struct of_device_id pmc_dt_ids[] = {
0152 { .compatible = "atmel,sama5d2-pmc" },
0153 { .compatible = "microchip,sama7g5-pmc", },
0154 { }
0155 };
0156
0157 static int __init pmc_register_ops(void)
0158 {
0159 struct device_node *np;
0160
0161 np = of_find_matching_node(NULL, pmc_dt_ids);
0162 if (!np)
0163 return -ENODEV;
0164
0165 if (!of_device_is_available(np)) {
0166 of_node_put(np);
0167 return -ENODEV;
0168 }
0169 of_node_put(np);
0170
0171 np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam");
0172 if (!np)
0173 return -ENODEV;
0174
0175 if (!of_device_is_available(np)) {
0176 of_node_put(np);
0177 return -ENODEV;
0178 }
0179 of_node_put(np);
0180
0181 at91_pmc_backup_suspend = of_iomap(np, 0);
0182 if (!at91_pmc_backup_suspend) {
0183 pr_warn("%s(): unable to map securam\n", __func__);
0184 return -ENOMEM;
0185 }
0186
0187 register_syscore_ops(&pmc_syscore_ops);
0188
0189 return 0;
0190 }
0191
0192 postcore_initcall(pmc_register_ops);
0193 #endif