2 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
11 #include <linux/clk-provider.h>
12 #include <linux/clkdev.h>
13 #include <linux/clk/at91_pmc.h>
15 #include <linux/mfd/syscon.h>
16 #include <linux/platform_device.h>
17 #include <linux/regmap.h>
18 #include <linux/syscore_ops.h>
20 #include <asm/proc-fns.h>
24 #define PMC_MAX_IDS 128
26 int of_at91_get_clk_range(struct device_node
*np
, const char *propname
,
27 struct clk_range
*range
)
32 ret
= of_property_read_u32_index(np
, propname
, 0, &min
);
36 ret
= of_property_read_u32_index(np
, propname
, 1, &max
);
47 EXPORT_SYMBOL_GPL(of_at91_get_clk_range
);
50 static struct regmap
*pmcreg
;
52 static u8 registered_ids
[PMC_MAX_IDS
];
71 void pmc_register_id(u8 id
)
75 for (i
= 0; i
< PMC_MAX_IDS
; i
++) {
76 if (registered_ids
[i
] == 0) {
77 registered_ids
[i
] = id
;
80 if (registered_ids
[i
] == id
)
85 static int pmc_suspend(void)
89 regmap_read(pmcreg
, AT91_PMC_IMR
, &pmc_cache
.scsr
);
90 regmap_read(pmcreg
, AT91_PMC_PCSR
, &pmc_cache
.pcsr0
);
91 regmap_read(pmcreg
, AT91_CKGR_UCKR
, &pmc_cache
.uckr
);
92 regmap_read(pmcreg
, AT91_CKGR_MOR
, &pmc_cache
.mor
);
93 regmap_read(pmcreg
, AT91_CKGR_MCFR
, &pmc_cache
.mcfr
);
94 regmap_read(pmcreg
, AT91_CKGR_PLLAR
, &pmc_cache
.pllar
);
95 regmap_read(pmcreg
, AT91_PMC_MCKR
, &pmc_cache
.mckr
);
96 regmap_read(pmcreg
, AT91_PMC_USB
, &pmc_cache
.usb
);
97 regmap_read(pmcreg
, AT91_PMC_IMR
, &pmc_cache
.imr
);
98 regmap_read(pmcreg
, AT91_PMC_PCSR1
, &pmc_cache
.pcsr1
);
100 for (i
= 0; registered_ids
[i
]; i
++) {
101 regmap_write(pmcreg
, AT91_PMC_PCR
,
102 (registered_ids
[i
] & AT91_PMC_PCR_PID_MASK
));
103 regmap_read(pmcreg
, AT91_PMC_PCR
,
104 &pmc_cache
.pcr
[registered_ids
[i
]]);
110 static bool pmc_ready(unsigned int mask
)
114 regmap_read(pmcreg
, AT91_PMC_SR
, &status
);
116 return ((status
& mask
) == mask
) ? 1 : 0;
119 static void pmc_resume(void)
123 u32 mask
= AT91_PMC_MCKRDY
| AT91_PMC_LOCKA
;
125 regmap_read(pmcreg
, AT91_PMC_MCKR
, &tmp
);
126 if (pmc_cache
.mckr
!= tmp
)
127 pr_warn("MCKR was not configured properly by the firmware\n");
128 regmap_read(pmcreg
, AT91_CKGR_PLLAR
, &tmp
);
129 if (pmc_cache
.pllar
!= tmp
)
130 pr_warn("PLLAR was not configured properly by the firmware\n");
132 regmap_write(pmcreg
, AT91_PMC_IMR
, pmc_cache
.scsr
);
133 regmap_write(pmcreg
, AT91_PMC_PCER
, pmc_cache
.pcsr0
);
134 regmap_write(pmcreg
, AT91_CKGR_UCKR
, pmc_cache
.uckr
);
135 regmap_write(pmcreg
, AT91_CKGR_MOR
, pmc_cache
.mor
);
136 regmap_write(pmcreg
, AT91_CKGR_MCFR
, pmc_cache
.mcfr
);
137 regmap_write(pmcreg
, AT91_PMC_USB
, pmc_cache
.usb
);
138 regmap_write(pmcreg
, AT91_PMC_IMR
, pmc_cache
.imr
);
139 regmap_write(pmcreg
, AT91_PMC_PCER1
, pmc_cache
.pcsr1
);
141 for (i
= 0; registered_ids
[i
]; i
++) {
142 regmap_write(pmcreg
, AT91_PMC_PCR
,
143 pmc_cache
.pcr
[registered_ids
[i
]] |
147 if (pmc_cache
.uckr
& AT91_PMC_UPLLEN
)
148 mask
|= AT91_PMC_LOCKU
;
150 while (!pmc_ready(mask
))
154 static struct syscore_ops pmc_syscore_ops
= {
155 .suspend
= pmc_suspend
,
156 .resume
= pmc_resume
,
159 static const struct of_device_id sama5d2_pmc_dt_ids
[] = {
160 { .compatible
= "atmel,sama5d2-pmc" },
164 static int __init
pmc_register_ops(void)
166 struct device_node
*np
;
168 np
= of_find_matching_node(NULL
, sama5d2_pmc_dt_ids
);
170 pmcreg
= syscon_node_to_regmap(np
);
172 return PTR_ERR(pmcreg
);
174 register_syscore_ops(&pmc_syscore_ops
);
178 /* This has to happen before arch_initcall because of the tcb_clksrc driver */
179 postcore_initcall(pmc_register_ops
);