xref: /openbmc/linux/drivers/clk/at91/pmc.c (revision 863a81c3)
10ad6125bSBoris BREZILLON /*
20ad6125bSBoris BREZILLON  *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
30ad6125bSBoris BREZILLON  *
40ad6125bSBoris BREZILLON  * This program is free software; you can redistribute it and/or modify
50ad6125bSBoris BREZILLON  * it under the terms of the GNU General Public License as published by
60ad6125bSBoris BREZILLON  * the Free Software Foundation; either version 2 of the License, or
70ad6125bSBoris BREZILLON  * (at your option) any later version.
80ad6125bSBoris BREZILLON  *
90ad6125bSBoris BREZILLON  */
100ad6125bSBoris BREZILLON 
110ad6125bSBoris BREZILLON #include <linux/clk-provider.h>
120ad6125bSBoris BREZILLON #include <linux/clkdev.h>
130ad6125bSBoris BREZILLON #include <linux/clk/at91_pmc.h>
140ad6125bSBoris BREZILLON #include <linux/of.h>
150ad6125bSBoris BREZILLON #include <linux/of_address.h>
160ad6125bSBoris BREZILLON #include <linux/io.h>
170ad6125bSBoris BREZILLON #include <linux/interrupt.h>
180ad6125bSBoris BREZILLON #include <linux/irq.h>
190ad6125bSBoris BREZILLON #include <linux/irqchip/chained_irq.h>
200ad6125bSBoris BREZILLON #include <linux/irqdomain.h>
210ad6125bSBoris BREZILLON #include <linux/of_irq.h>
22863a81c3SBoris Brezillon #include <linux/mfd/syscon.h>
230ad6125bSBoris BREZILLON 
240ad6125bSBoris BREZILLON #include <asm/proc-fns.h>
250ad6125bSBoris BREZILLON 
260ad6125bSBoris BREZILLON #include "pmc.h"
270ad6125bSBoris BREZILLON 
280ad6125bSBoris BREZILLON void __iomem *at91_pmc_base;
290ad6125bSBoris BREZILLON EXPORT_SYMBOL_GPL(at91_pmc_base);
300ad6125bSBoris BREZILLON 
3129ee506dSAlexandre Belloni void at91rm9200_idle(void)
3229ee506dSAlexandre Belloni {
3329ee506dSAlexandre Belloni 	/*
3429ee506dSAlexandre Belloni 	 * Disable the processor clock.  The processor will be automatically
3529ee506dSAlexandre Belloni 	 * re-enabled by an interrupt or by a reset.
3629ee506dSAlexandre Belloni 	 */
3729ee506dSAlexandre Belloni 	at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK);
3829ee506dSAlexandre Belloni }
3929ee506dSAlexandre Belloni 
400ad6125bSBoris BREZILLON void at91sam9_idle(void)
410ad6125bSBoris BREZILLON {
420ad6125bSBoris BREZILLON 	at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK);
430ad6125bSBoris BREZILLON 	cpu_do_idle();
440ad6125bSBoris BREZILLON }
450ad6125bSBoris BREZILLON 
460ad6125bSBoris BREZILLON int of_at91_get_clk_range(struct device_node *np, const char *propname,
470ad6125bSBoris BREZILLON 			  struct clk_range *range)
480ad6125bSBoris BREZILLON {
490ad6125bSBoris BREZILLON 	u32 min, max;
500ad6125bSBoris BREZILLON 	int ret;
510ad6125bSBoris BREZILLON 
520ad6125bSBoris BREZILLON 	ret = of_property_read_u32_index(np, propname, 0, &min);
530ad6125bSBoris BREZILLON 	if (ret)
540ad6125bSBoris BREZILLON 		return ret;
550ad6125bSBoris BREZILLON 
560ad6125bSBoris BREZILLON 	ret = of_property_read_u32_index(np, propname, 1, &max);
570ad6125bSBoris BREZILLON 	if (ret)
580ad6125bSBoris BREZILLON 		return ret;
590ad6125bSBoris BREZILLON 
600ad6125bSBoris BREZILLON 	if (range) {
610ad6125bSBoris BREZILLON 		range->min = min;
620ad6125bSBoris BREZILLON 		range->max = max;
630ad6125bSBoris BREZILLON 	}
640ad6125bSBoris BREZILLON 
650ad6125bSBoris BREZILLON 	return 0;
660ad6125bSBoris BREZILLON }
670ad6125bSBoris BREZILLON EXPORT_SYMBOL_GPL(of_at91_get_clk_range);
680ad6125bSBoris BREZILLON 
690ad6125bSBoris BREZILLON static void pmc_irq_mask(struct irq_data *d)
700ad6125bSBoris BREZILLON {
710ad6125bSBoris BREZILLON 	struct at91_pmc *pmc = irq_data_get_irq_chip_data(d);
720ad6125bSBoris BREZILLON 
730ad6125bSBoris BREZILLON 	pmc_write(pmc, AT91_PMC_IDR, 1 << d->hwirq);
740ad6125bSBoris BREZILLON }
750ad6125bSBoris BREZILLON 
760ad6125bSBoris BREZILLON static void pmc_irq_unmask(struct irq_data *d)
770ad6125bSBoris BREZILLON {
780ad6125bSBoris BREZILLON 	struct at91_pmc *pmc = irq_data_get_irq_chip_data(d);
790ad6125bSBoris BREZILLON 
800ad6125bSBoris BREZILLON 	pmc_write(pmc, AT91_PMC_IER, 1 << d->hwirq);
810ad6125bSBoris BREZILLON }
820ad6125bSBoris BREZILLON 
830ad6125bSBoris BREZILLON static int pmc_irq_set_type(struct irq_data *d, unsigned type)
840ad6125bSBoris BREZILLON {
850ad6125bSBoris BREZILLON 	if (type != IRQ_TYPE_LEVEL_HIGH) {
860ad6125bSBoris BREZILLON 		pr_warn("PMC: type not supported (support only IRQ_TYPE_LEVEL_HIGH type)\n");
870ad6125bSBoris BREZILLON 		return -EINVAL;
880ad6125bSBoris BREZILLON 	}
890ad6125bSBoris BREZILLON 
900ad6125bSBoris BREZILLON 	return 0;
910ad6125bSBoris BREZILLON }
920ad6125bSBoris BREZILLON 
93947f5b10SBoris BREZILLON static void pmc_irq_suspend(struct irq_data *d)
94947f5b10SBoris BREZILLON {
95947f5b10SBoris BREZILLON 	struct at91_pmc *pmc = irq_data_get_irq_chip_data(d);
96947f5b10SBoris BREZILLON 
97947f5b10SBoris BREZILLON 	pmc->imr = pmc_read(pmc, AT91_PMC_IMR);
98947f5b10SBoris BREZILLON 	pmc_write(pmc, AT91_PMC_IDR, pmc->imr);
99947f5b10SBoris BREZILLON }
100947f5b10SBoris BREZILLON 
101947f5b10SBoris BREZILLON static void pmc_irq_resume(struct irq_data *d)
102947f5b10SBoris BREZILLON {
103947f5b10SBoris BREZILLON 	struct at91_pmc *pmc = irq_data_get_irq_chip_data(d);
104947f5b10SBoris BREZILLON 
105947f5b10SBoris BREZILLON 	pmc_write(pmc, AT91_PMC_IER, pmc->imr);
106947f5b10SBoris BREZILLON }
107947f5b10SBoris BREZILLON 
1080ad6125bSBoris BREZILLON static struct irq_chip pmc_irq = {
1090ad6125bSBoris BREZILLON 	.name = "PMC",
1100ad6125bSBoris BREZILLON 	.irq_disable = pmc_irq_mask,
1110ad6125bSBoris BREZILLON 	.irq_mask = pmc_irq_mask,
1120ad6125bSBoris BREZILLON 	.irq_unmask = pmc_irq_unmask,
1130ad6125bSBoris BREZILLON 	.irq_set_type = pmc_irq_set_type,
114947f5b10SBoris BREZILLON 	.irq_suspend = pmc_irq_suspend,
115947f5b10SBoris BREZILLON 	.irq_resume = pmc_irq_resume,
1160ad6125bSBoris BREZILLON };
1170ad6125bSBoris BREZILLON 
1180ad6125bSBoris BREZILLON static struct lock_class_key pmc_lock_class;
1190ad6125bSBoris BREZILLON 
1200ad6125bSBoris BREZILLON static int pmc_irq_map(struct irq_domain *h, unsigned int virq,
1210ad6125bSBoris BREZILLON 		       irq_hw_number_t hw)
1220ad6125bSBoris BREZILLON {
1230ad6125bSBoris BREZILLON 	struct at91_pmc	*pmc = h->host_data;
1240ad6125bSBoris BREZILLON 
1250ad6125bSBoris BREZILLON 	irq_set_lockdep_class(virq, &pmc_lock_class);
1260ad6125bSBoris BREZILLON 
1270ad6125bSBoris BREZILLON 	irq_set_chip_and_handler(virq, &pmc_irq,
1280ad6125bSBoris BREZILLON 				 handle_level_irq);
1290ad6125bSBoris BREZILLON 	irq_set_chip_data(virq, pmc);
1300ad6125bSBoris BREZILLON 
1310ad6125bSBoris BREZILLON 	return 0;
1320ad6125bSBoris BREZILLON }
1330ad6125bSBoris BREZILLON 
1340ad6125bSBoris BREZILLON static int pmc_irq_domain_xlate(struct irq_domain *d,
1350ad6125bSBoris BREZILLON 				struct device_node *ctrlr,
1360ad6125bSBoris BREZILLON 				const u32 *intspec, unsigned int intsize,
1370ad6125bSBoris BREZILLON 				irq_hw_number_t *out_hwirq,
1380ad6125bSBoris BREZILLON 				unsigned int *out_type)
1390ad6125bSBoris BREZILLON {
1400ad6125bSBoris BREZILLON 	struct at91_pmc *pmc = d->host_data;
1410ad6125bSBoris BREZILLON 	const struct at91_pmc_caps *caps = pmc->caps;
1420ad6125bSBoris BREZILLON 
1430ad6125bSBoris BREZILLON 	if (WARN_ON(intsize < 1))
1440ad6125bSBoris BREZILLON 		return -EINVAL;
1450ad6125bSBoris BREZILLON 
1460ad6125bSBoris BREZILLON 	*out_hwirq = intspec[0];
1470ad6125bSBoris BREZILLON 
1480ad6125bSBoris BREZILLON 	if (!(caps->available_irqs & (1 << *out_hwirq)))
1490ad6125bSBoris BREZILLON 		return -EINVAL;
1500ad6125bSBoris BREZILLON 
1510ad6125bSBoris BREZILLON 	*out_type = IRQ_TYPE_LEVEL_HIGH;
1520ad6125bSBoris BREZILLON 
1530ad6125bSBoris BREZILLON 	return 0;
1540ad6125bSBoris BREZILLON }
1550ad6125bSBoris BREZILLON 
156d6c27678SKrzysztof Kozlowski static const struct irq_domain_ops pmc_irq_ops = {
1570ad6125bSBoris BREZILLON 	.map	= pmc_irq_map,
1580ad6125bSBoris BREZILLON 	.xlate	= pmc_irq_domain_xlate,
1590ad6125bSBoris BREZILLON };
1600ad6125bSBoris BREZILLON 
1610ad6125bSBoris BREZILLON static irqreturn_t pmc_irq_handler(int irq, void *data)
1620ad6125bSBoris BREZILLON {
1630ad6125bSBoris BREZILLON 	struct at91_pmc *pmc = (struct at91_pmc *)data;
1640ad6125bSBoris BREZILLON 	unsigned long sr;
1650ad6125bSBoris BREZILLON 	int n;
1660ad6125bSBoris BREZILLON 
1670ad6125bSBoris BREZILLON 	sr = pmc_read(pmc, AT91_PMC_SR) & pmc_read(pmc, AT91_PMC_IMR);
1680ad6125bSBoris BREZILLON 	if (!sr)
1690ad6125bSBoris BREZILLON 		return IRQ_NONE;
1700ad6125bSBoris BREZILLON 
1710ad6125bSBoris BREZILLON 	for_each_set_bit(n, &sr, BITS_PER_LONG)
1720ad6125bSBoris BREZILLON 		generic_handle_irq(irq_find_mapping(pmc->irqdomain, n));
1730ad6125bSBoris BREZILLON 
1740ad6125bSBoris BREZILLON 	return IRQ_HANDLED;
1750ad6125bSBoris BREZILLON }
1760ad6125bSBoris BREZILLON 
1770ad6125bSBoris BREZILLON static const struct at91_pmc_caps at91rm9200_caps = {
1780ad6125bSBoris BREZILLON 	.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB |
1790ad6125bSBoris BREZILLON 			  AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY |
1800ad6125bSBoris BREZILLON 			  AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY |
1810ad6125bSBoris BREZILLON 			  AT91_PMC_PCK3RDY,
1820ad6125bSBoris BREZILLON };
1830ad6125bSBoris BREZILLON 
1840ad6125bSBoris BREZILLON static const struct at91_pmc_caps at91sam9260_caps = {
1850ad6125bSBoris BREZILLON 	.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB |
1860ad6125bSBoris BREZILLON 			  AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY |
1870ad6125bSBoris BREZILLON 			  AT91_PMC_PCK1RDY,
1880ad6125bSBoris BREZILLON };
1890ad6125bSBoris BREZILLON 
1900ad6125bSBoris BREZILLON static const struct at91_pmc_caps at91sam9g45_caps = {
1910ad6125bSBoris BREZILLON 	.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
1920ad6125bSBoris BREZILLON 			  AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
1930ad6125bSBoris BREZILLON 			  AT91_PMC_PCK1RDY,
1940ad6125bSBoris BREZILLON };
1950ad6125bSBoris BREZILLON 
1960ad6125bSBoris BREZILLON static const struct at91_pmc_caps at91sam9n12_caps = {
1970ad6125bSBoris BREZILLON 	.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB |
1980ad6125bSBoris BREZILLON 			  AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY |
1990ad6125bSBoris BREZILLON 			  AT91_PMC_PCK1RDY | AT91_PMC_MOSCSELS |
2000ad6125bSBoris BREZILLON 			  AT91_PMC_MOSCRCS | AT91_PMC_CFDEV,
2010ad6125bSBoris BREZILLON };
2020ad6125bSBoris BREZILLON 
2030ad6125bSBoris BREZILLON static const struct at91_pmc_caps at91sam9x5_caps = {
2040ad6125bSBoris BREZILLON 	.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
2050ad6125bSBoris BREZILLON 			  AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
2060ad6125bSBoris BREZILLON 			  AT91_PMC_PCK1RDY | AT91_PMC_MOSCSELS |
2070ad6125bSBoris BREZILLON 			  AT91_PMC_MOSCRCS | AT91_PMC_CFDEV,
2080ad6125bSBoris BREZILLON };
2090ad6125bSBoris BREZILLON 
210a5752e57SNicolas Ferre static const struct at91_pmc_caps sama5d2_caps = {
211a5752e57SNicolas Ferre 	.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
212a5752e57SNicolas Ferre 			  AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
213a5752e57SNicolas Ferre 			  AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY |
214a5752e57SNicolas Ferre 			  AT91_PMC_MOSCSELS | AT91_PMC_MOSCRCS |
215a5752e57SNicolas Ferre 			  AT91_PMC_CFDEV | AT91_PMC_GCKRDY,
216a5752e57SNicolas Ferre };
217a5752e57SNicolas Ferre 
2180ad6125bSBoris BREZILLON static const struct at91_pmc_caps sama5d3_caps = {
2190ad6125bSBoris BREZILLON 	.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
2200ad6125bSBoris BREZILLON 			  AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
2210ad6125bSBoris BREZILLON 			  AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY |
2220ad6125bSBoris BREZILLON 			  AT91_PMC_MOSCSELS | AT91_PMC_MOSCRCS |
2230ad6125bSBoris BREZILLON 			  AT91_PMC_CFDEV,
2240ad6125bSBoris BREZILLON };
2250ad6125bSBoris BREZILLON 
2260ad6125bSBoris BREZILLON static struct at91_pmc *__init at91_pmc_init(struct device_node *np,
227863a81c3SBoris Brezillon 					     struct regmap *regmap,
2280ad6125bSBoris BREZILLON 					     void __iomem *regbase, int virq,
2290ad6125bSBoris BREZILLON 					     const struct at91_pmc_caps *caps)
2300ad6125bSBoris BREZILLON {
2310ad6125bSBoris BREZILLON 	struct at91_pmc *pmc;
2320ad6125bSBoris BREZILLON 
2330ad6125bSBoris BREZILLON 	if (!regbase || !virq ||  !caps)
2340ad6125bSBoris BREZILLON 		return NULL;
2350ad6125bSBoris BREZILLON 
2360ad6125bSBoris BREZILLON 	at91_pmc_base = regbase;
2370ad6125bSBoris BREZILLON 
2380ad6125bSBoris BREZILLON 	pmc = kzalloc(sizeof(*pmc), GFP_KERNEL);
2390ad6125bSBoris BREZILLON 	if (!pmc)
2400ad6125bSBoris BREZILLON 		return NULL;
2410ad6125bSBoris BREZILLON 
2420ad6125bSBoris BREZILLON 	spin_lock_init(&pmc->lock);
243863a81c3SBoris Brezillon 	pmc->regmap = regmap;
2440ad6125bSBoris BREZILLON 	pmc->virq = virq;
2450ad6125bSBoris BREZILLON 	pmc->caps = caps;
2460ad6125bSBoris BREZILLON 
2470ad6125bSBoris BREZILLON 	pmc->irqdomain = irq_domain_add_linear(np, 32, &pmc_irq_ops, pmc);
2480ad6125bSBoris BREZILLON 
2490ad6125bSBoris BREZILLON 	if (!pmc->irqdomain)
2500ad6125bSBoris BREZILLON 		goto out_free_pmc;
2510ad6125bSBoris BREZILLON 
2520ad6125bSBoris BREZILLON 	pmc_write(pmc, AT91_PMC_IDR, 0xffffffff);
253947f5b10SBoris BREZILLON 	if (request_irq(pmc->virq, pmc_irq_handler,
254947f5b10SBoris BREZILLON 			IRQF_SHARED | IRQF_COND_SUSPEND, "pmc", pmc))
2550ad6125bSBoris BREZILLON 		goto out_remove_irqdomain;
2560ad6125bSBoris BREZILLON 
2570ad6125bSBoris BREZILLON 	return pmc;
2580ad6125bSBoris BREZILLON 
2590ad6125bSBoris BREZILLON out_remove_irqdomain:
2600ad6125bSBoris BREZILLON 	irq_domain_remove(pmc->irqdomain);
2610ad6125bSBoris BREZILLON out_free_pmc:
2620ad6125bSBoris BREZILLON 	kfree(pmc);
2630ad6125bSBoris BREZILLON 
2640ad6125bSBoris BREZILLON 	return NULL;
2650ad6125bSBoris BREZILLON }
2660ad6125bSBoris BREZILLON 
2677736c715SBoris BREZILLON static const struct of_device_id pmc_clk_ids[] __initconst = {
26880eded6cSBoris BREZILLON 	/* Slow oscillator */
26980eded6cSBoris BREZILLON 	{
27080eded6cSBoris BREZILLON 		.compatible = "atmel,at91sam9260-clk-slow",
27180eded6cSBoris BREZILLON 		.data = of_at91sam9260_clk_slow_setup,
27280eded6cSBoris BREZILLON 	},
27338d34c31SBoris BREZILLON 	/* Main clock */
27438d34c31SBoris BREZILLON 	{
27527cb1c20SBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-main-osc",
27627cb1c20SBoris BREZILLON 		.data = of_at91rm9200_clk_main_osc_setup,
27727cb1c20SBoris BREZILLON 	},
27827cb1c20SBoris BREZILLON 	{
27927cb1c20SBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-main-rc-osc",
28027cb1c20SBoris BREZILLON 		.data = of_at91sam9x5_clk_main_rc_osc_setup,
28127cb1c20SBoris BREZILLON 	},
28227cb1c20SBoris BREZILLON 	{
28338d34c31SBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-main",
28438d34c31SBoris BREZILLON 		.data = of_at91rm9200_clk_main_setup,
28538d34c31SBoris BREZILLON 	},
28627cb1c20SBoris BREZILLON 	{
28727cb1c20SBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-main",
28827cb1c20SBoris BREZILLON 		.data = of_at91sam9x5_clk_main_setup,
28927cb1c20SBoris BREZILLON 	},
2901a748d2bSBoris BREZILLON 	/* PLL clocks */
2911a748d2bSBoris BREZILLON 	{
2921a748d2bSBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-pll",
2931a748d2bSBoris BREZILLON 		.data = of_at91rm9200_clk_pll_setup,
2941a748d2bSBoris BREZILLON 	},
2951a748d2bSBoris BREZILLON 	{
2961a748d2bSBoris BREZILLON 		.compatible = "atmel,at91sam9g45-clk-pll",
2971a748d2bSBoris BREZILLON 		.data = of_at91sam9g45_clk_pll_setup,
2981a748d2bSBoris BREZILLON 	},
2991a748d2bSBoris BREZILLON 	{
3001a748d2bSBoris BREZILLON 		.compatible = "atmel,at91sam9g20-clk-pllb",
3011a748d2bSBoris BREZILLON 		.data = of_at91sam9g20_clk_pllb_setup,
3021a748d2bSBoris BREZILLON 	},
3031a748d2bSBoris BREZILLON 	{
3041a748d2bSBoris BREZILLON 		.compatible = "atmel,sama5d3-clk-pll",
3051a748d2bSBoris BREZILLON 		.data = of_sama5d3_clk_pll_setup,
3061a748d2bSBoris BREZILLON 	},
3071a748d2bSBoris BREZILLON 	{
3081a748d2bSBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-plldiv",
3091a748d2bSBoris BREZILLON 		.data = of_at91sam9x5_clk_plldiv_setup,
3101a748d2bSBoris BREZILLON 	},
311e442d234SBoris BREZILLON 	/* Master clock */
312e442d234SBoris BREZILLON 	{
313e442d234SBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-master",
314e442d234SBoris BREZILLON 		.data = of_at91rm9200_clk_master_setup,
315e442d234SBoris BREZILLON 	},
316e442d234SBoris BREZILLON 	{
317e442d234SBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-master",
318e442d234SBoris BREZILLON 		.data = of_at91sam9x5_clk_master_setup,
319e442d234SBoris BREZILLON 	},
3205fba62eaSBoris BREZILLON 	/* System clocks */
3215fba62eaSBoris BREZILLON 	{
3225fba62eaSBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-system",
3235fba62eaSBoris BREZILLON 		.data = of_at91rm9200_clk_sys_setup,
3245fba62eaSBoris BREZILLON 	},
3256114067eSBoris BREZILLON 	/* Peripheral clocks */
3266114067eSBoris BREZILLON 	{
3276114067eSBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-peripheral",
3286114067eSBoris BREZILLON 		.data = of_at91rm9200_clk_periph_setup,
3296114067eSBoris BREZILLON 	},
3306114067eSBoris BREZILLON 	{
3316114067eSBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-peripheral",
3326114067eSBoris BREZILLON 		.data = of_at91sam9x5_clk_periph_setup,
3336114067eSBoris BREZILLON 	},
3341f22f8bbSBoris BREZILLON 	/* Programmable clocks */
3351f22f8bbSBoris BREZILLON 	{
3361f22f8bbSBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-programmable",
3371f22f8bbSBoris BREZILLON 		.data = of_at91rm9200_clk_prog_setup,
3381f22f8bbSBoris BREZILLON 	},
3391f22f8bbSBoris BREZILLON 	{
3401f22f8bbSBoris BREZILLON 		.compatible = "atmel,at91sam9g45-clk-programmable",
3411f22f8bbSBoris BREZILLON 		.data = of_at91sam9g45_clk_prog_setup,
3421f22f8bbSBoris BREZILLON 	},
3431f22f8bbSBoris BREZILLON 	{
3441f22f8bbSBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-programmable",
3451f22f8bbSBoris BREZILLON 		.data = of_at91sam9x5_clk_prog_setup,
3461f22f8bbSBoris BREZILLON 	},
347f090fb37SBoris BREZILLON 	/* UTMI clock */
348f090fb37SBoris BREZILLON #if defined(CONFIG_HAVE_AT91_UTMI)
349f090fb37SBoris BREZILLON 	{
350f090fb37SBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-utmi",
351f090fb37SBoris BREZILLON 		.data = of_at91sam9x5_clk_utmi_setup,
352f090fb37SBoris BREZILLON 	},
353f090fb37SBoris BREZILLON #endif
354c84a61d8SBoris BREZILLON 	/* USB clock */
355c84a61d8SBoris BREZILLON #if defined(CONFIG_HAVE_AT91_USB_CLK)
356c84a61d8SBoris BREZILLON 	{
357c84a61d8SBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-usb",
358c84a61d8SBoris BREZILLON 		.data = of_at91rm9200_clk_usb_setup,
359c84a61d8SBoris BREZILLON 	},
360c84a61d8SBoris BREZILLON 	{
361c84a61d8SBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-usb",
362c84a61d8SBoris BREZILLON 		.data = of_at91sam9x5_clk_usb_setup,
363c84a61d8SBoris BREZILLON 	},
364c84a61d8SBoris BREZILLON 	{
365c84a61d8SBoris BREZILLON 		.compatible = "atmel,at91sam9n12-clk-usb",
366c84a61d8SBoris BREZILLON 		.data = of_at91sam9n12_clk_usb_setup,
367c84a61d8SBoris BREZILLON 	},
368c84a61d8SBoris BREZILLON #endif
369a9c0688fSBoris BREZILLON 	/* SMD clock */
370a9c0688fSBoris BREZILLON #if defined(CONFIG_HAVE_AT91_SMD)
371a9c0688fSBoris BREZILLON 	{
372a9c0688fSBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-smd",
373a9c0688fSBoris BREZILLON 		.data = of_at91sam9x5_clk_smd_setup,
374a9c0688fSBoris BREZILLON 	},
375a9c0688fSBoris BREZILLON #endif
376bcc5fd49SAlexandre Belloni #if defined(CONFIG_HAVE_AT91_H32MX)
377bcc5fd49SAlexandre Belloni 	{
378bcc5fd49SAlexandre Belloni 		.compatible = "atmel,sama5d4-clk-h32mx",
379bcc5fd49SAlexandre Belloni 		.data = of_sama5d4_clk_h32mx_setup,
380bcc5fd49SAlexandre Belloni 	},
381bcc5fd49SAlexandre Belloni #endif
382df70aeefSNicolas Ferre #if defined(CONFIG_HAVE_AT91_GENERATED_CLK)
383df70aeefSNicolas Ferre 	{
384df70aeefSNicolas Ferre 		.compatible = "atmel,sama5d2-clk-generated",
385df70aeefSNicolas Ferre 		.data = of_sama5d2_clk_generated_setup,
386df70aeefSNicolas Ferre 	},
387df70aeefSNicolas Ferre #endif
3880ad6125bSBoris BREZILLON 	{ /*sentinel*/ }
3890ad6125bSBoris BREZILLON };
3900ad6125bSBoris BREZILLON 
3910ad6125bSBoris BREZILLON static void __init of_at91_pmc_setup(struct device_node *np,
3920ad6125bSBoris BREZILLON 				     const struct at91_pmc_caps *caps)
3930ad6125bSBoris BREZILLON {
3940ad6125bSBoris BREZILLON 	struct at91_pmc *pmc;
3950ad6125bSBoris BREZILLON 	struct device_node *childnp;
3960ad6125bSBoris BREZILLON 	void (*clk_setup)(struct device_node *, struct at91_pmc *);
3970ad6125bSBoris BREZILLON 	const struct of_device_id *clk_id;
3980ad6125bSBoris BREZILLON 	void __iomem *regbase = of_iomap(np, 0);
399863a81c3SBoris Brezillon 	struct regmap *regmap;
4000ad6125bSBoris BREZILLON 	int virq;
4010ad6125bSBoris BREZILLON 
402863a81c3SBoris Brezillon 	regmap = syscon_node_to_regmap(np);
403863a81c3SBoris Brezillon 	if (IS_ERR(regmap))
404863a81c3SBoris Brezillon 		panic("Could not retrieve syscon regmap");
4050ad6125bSBoris BREZILLON 
4060ad6125bSBoris BREZILLON 	virq = irq_of_parse_and_map(np, 0);
4070ad6125bSBoris BREZILLON 	if (!virq)
4080ad6125bSBoris BREZILLON 		return;
4090ad6125bSBoris BREZILLON 
410863a81c3SBoris Brezillon 	pmc = at91_pmc_init(np, regmap, regbase, virq, caps);
4110ad6125bSBoris BREZILLON 	if (!pmc)
4120ad6125bSBoris BREZILLON 		return;
4130ad6125bSBoris BREZILLON 	for_each_child_of_node(np, childnp) {
4140ad6125bSBoris BREZILLON 		clk_id = of_match_node(pmc_clk_ids, childnp);
4150ad6125bSBoris BREZILLON 		if (!clk_id)
4160ad6125bSBoris BREZILLON 			continue;
4170ad6125bSBoris BREZILLON 		clk_setup = clk_id->data;
4180ad6125bSBoris BREZILLON 		clk_setup(childnp, pmc);
4190ad6125bSBoris BREZILLON 	}
4200ad6125bSBoris BREZILLON }
4210ad6125bSBoris BREZILLON 
4220ad6125bSBoris BREZILLON static void __init of_at91rm9200_pmc_setup(struct device_node *np)
4230ad6125bSBoris BREZILLON {
4240ad6125bSBoris BREZILLON 	of_at91_pmc_setup(np, &at91rm9200_caps);
4250ad6125bSBoris BREZILLON }
4260ad6125bSBoris BREZILLON CLK_OF_DECLARE(at91rm9200_clk_pmc, "atmel,at91rm9200-pmc",
4270ad6125bSBoris BREZILLON 	       of_at91rm9200_pmc_setup);
4280ad6125bSBoris BREZILLON 
4290ad6125bSBoris BREZILLON static void __init of_at91sam9260_pmc_setup(struct device_node *np)
4300ad6125bSBoris BREZILLON {
4310ad6125bSBoris BREZILLON 	of_at91_pmc_setup(np, &at91sam9260_caps);
4320ad6125bSBoris BREZILLON }
4330ad6125bSBoris BREZILLON CLK_OF_DECLARE(at91sam9260_clk_pmc, "atmel,at91sam9260-pmc",
4340ad6125bSBoris BREZILLON 	       of_at91sam9260_pmc_setup);
4350ad6125bSBoris BREZILLON 
4360ad6125bSBoris BREZILLON static void __init of_at91sam9g45_pmc_setup(struct device_node *np)
4370ad6125bSBoris BREZILLON {
4380ad6125bSBoris BREZILLON 	of_at91_pmc_setup(np, &at91sam9g45_caps);
4390ad6125bSBoris BREZILLON }
4400ad6125bSBoris BREZILLON CLK_OF_DECLARE(at91sam9g45_clk_pmc, "atmel,at91sam9g45-pmc",
4410ad6125bSBoris BREZILLON 	       of_at91sam9g45_pmc_setup);
4420ad6125bSBoris BREZILLON 
4430ad6125bSBoris BREZILLON static void __init of_at91sam9n12_pmc_setup(struct device_node *np)
4440ad6125bSBoris BREZILLON {
4450ad6125bSBoris BREZILLON 	of_at91_pmc_setup(np, &at91sam9n12_caps);
4460ad6125bSBoris BREZILLON }
4470ad6125bSBoris BREZILLON CLK_OF_DECLARE(at91sam9n12_clk_pmc, "atmel,at91sam9n12-pmc",
4480ad6125bSBoris BREZILLON 	       of_at91sam9n12_pmc_setup);
4490ad6125bSBoris BREZILLON 
4500ad6125bSBoris BREZILLON static void __init of_at91sam9x5_pmc_setup(struct device_node *np)
4510ad6125bSBoris BREZILLON {
4520ad6125bSBoris BREZILLON 	of_at91_pmc_setup(np, &at91sam9x5_caps);
4530ad6125bSBoris BREZILLON }
4540ad6125bSBoris BREZILLON CLK_OF_DECLARE(at91sam9x5_clk_pmc, "atmel,at91sam9x5-pmc",
4550ad6125bSBoris BREZILLON 	       of_at91sam9x5_pmc_setup);
4560ad6125bSBoris BREZILLON 
457a5752e57SNicolas Ferre static void __init of_sama5d2_pmc_setup(struct device_node *np)
458a5752e57SNicolas Ferre {
459a5752e57SNicolas Ferre 	of_at91_pmc_setup(np, &sama5d2_caps);
460a5752e57SNicolas Ferre }
461a5752e57SNicolas Ferre CLK_OF_DECLARE(sama5d2_clk_pmc, "atmel,sama5d2-pmc",
462a5752e57SNicolas Ferre 	       of_sama5d2_pmc_setup);
463a5752e57SNicolas Ferre 
4640ad6125bSBoris BREZILLON static void __init of_sama5d3_pmc_setup(struct device_node *np)
4650ad6125bSBoris BREZILLON {
4660ad6125bSBoris BREZILLON 	of_at91_pmc_setup(np, &sama5d3_caps);
4670ad6125bSBoris BREZILLON }
4680ad6125bSBoris BREZILLON CLK_OF_DECLARE(sama5d3_clk_pmc, "atmel,sama5d3-pmc",
4690ad6125bSBoris BREZILLON 	       of_sama5d3_pmc_setup);
470