xref: /openbmc/linux/drivers/clk/at91/pmc.c (revision 80eded6c)
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>
220ad6125bSBoris BREZILLON 
230ad6125bSBoris BREZILLON #include <asm/proc-fns.h>
240ad6125bSBoris BREZILLON 
250ad6125bSBoris BREZILLON #include "pmc.h"
260ad6125bSBoris BREZILLON 
270ad6125bSBoris BREZILLON void __iomem *at91_pmc_base;
280ad6125bSBoris BREZILLON EXPORT_SYMBOL_GPL(at91_pmc_base);
290ad6125bSBoris BREZILLON 
300ad6125bSBoris BREZILLON void at91sam9_idle(void)
310ad6125bSBoris BREZILLON {
320ad6125bSBoris BREZILLON 	at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK);
330ad6125bSBoris BREZILLON 	cpu_do_idle();
340ad6125bSBoris BREZILLON }
350ad6125bSBoris BREZILLON 
360ad6125bSBoris BREZILLON int of_at91_get_clk_range(struct device_node *np, const char *propname,
370ad6125bSBoris BREZILLON 			  struct clk_range *range)
380ad6125bSBoris BREZILLON {
390ad6125bSBoris BREZILLON 	u32 min, max;
400ad6125bSBoris BREZILLON 	int ret;
410ad6125bSBoris BREZILLON 
420ad6125bSBoris BREZILLON 	ret = of_property_read_u32_index(np, propname, 0, &min);
430ad6125bSBoris BREZILLON 	if (ret)
440ad6125bSBoris BREZILLON 		return ret;
450ad6125bSBoris BREZILLON 
460ad6125bSBoris BREZILLON 	ret = of_property_read_u32_index(np, propname, 1, &max);
470ad6125bSBoris BREZILLON 	if (ret)
480ad6125bSBoris BREZILLON 		return ret;
490ad6125bSBoris BREZILLON 
500ad6125bSBoris BREZILLON 	if (range) {
510ad6125bSBoris BREZILLON 		range->min = min;
520ad6125bSBoris BREZILLON 		range->max = max;
530ad6125bSBoris BREZILLON 	}
540ad6125bSBoris BREZILLON 
550ad6125bSBoris BREZILLON 	return 0;
560ad6125bSBoris BREZILLON }
570ad6125bSBoris BREZILLON EXPORT_SYMBOL_GPL(of_at91_get_clk_range);
580ad6125bSBoris BREZILLON 
590ad6125bSBoris BREZILLON static void pmc_irq_mask(struct irq_data *d)
600ad6125bSBoris BREZILLON {
610ad6125bSBoris BREZILLON 	struct at91_pmc *pmc = irq_data_get_irq_chip_data(d);
620ad6125bSBoris BREZILLON 
630ad6125bSBoris BREZILLON 	pmc_write(pmc, AT91_PMC_IDR, 1 << d->hwirq);
640ad6125bSBoris BREZILLON }
650ad6125bSBoris BREZILLON 
660ad6125bSBoris BREZILLON static void pmc_irq_unmask(struct irq_data *d)
670ad6125bSBoris BREZILLON {
680ad6125bSBoris BREZILLON 	struct at91_pmc *pmc = irq_data_get_irq_chip_data(d);
690ad6125bSBoris BREZILLON 
700ad6125bSBoris BREZILLON 	pmc_write(pmc, AT91_PMC_IER, 1 << d->hwirq);
710ad6125bSBoris BREZILLON }
720ad6125bSBoris BREZILLON 
730ad6125bSBoris BREZILLON static int pmc_irq_set_type(struct irq_data *d, unsigned type)
740ad6125bSBoris BREZILLON {
750ad6125bSBoris BREZILLON 	if (type != IRQ_TYPE_LEVEL_HIGH) {
760ad6125bSBoris BREZILLON 		pr_warn("PMC: type not supported (support only IRQ_TYPE_LEVEL_HIGH type)\n");
770ad6125bSBoris BREZILLON 		return -EINVAL;
780ad6125bSBoris BREZILLON 	}
790ad6125bSBoris BREZILLON 
800ad6125bSBoris BREZILLON 	return 0;
810ad6125bSBoris BREZILLON }
820ad6125bSBoris BREZILLON 
830ad6125bSBoris BREZILLON static struct irq_chip pmc_irq = {
840ad6125bSBoris BREZILLON 	.name = "PMC",
850ad6125bSBoris BREZILLON 	.irq_disable = pmc_irq_mask,
860ad6125bSBoris BREZILLON 	.irq_mask = pmc_irq_mask,
870ad6125bSBoris BREZILLON 	.irq_unmask = pmc_irq_unmask,
880ad6125bSBoris BREZILLON 	.irq_set_type = pmc_irq_set_type,
890ad6125bSBoris BREZILLON };
900ad6125bSBoris BREZILLON 
910ad6125bSBoris BREZILLON static struct lock_class_key pmc_lock_class;
920ad6125bSBoris BREZILLON 
930ad6125bSBoris BREZILLON static int pmc_irq_map(struct irq_domain *h, unsigned int virq,
940ad6125bSBoris BREZILLON 		       irq_hw_number_t hw)
950ad6125bSBoris BREZILLON {
960ad6125bSBoris BREZILLON 	struct at91_pmc	*pmc = h->host_data;
970ad6125bSBoris BREZILLON 
980ad6125bSBoris BREZILLON 	irq_set_lockdep_class(virq, &pmc_lock_class);
990ad6125bSBoris BREZILLON 
1000ad6125bSBoris BREZILLON 	irq_set_chip_and_handler(virq, &pmc_irq,
1010ad6125bSBoris BREZILLON 				 handle_level_irq);
1020ad6125bSBoris BREZILLON 	set_irq_flags(virq, IRQF_VALID);
1030ad6125bSBoris BREZILLON 	irq_set_chip_data(virq, pmc);
1040ad6125bSBoris BREZILLON 
1050ad6125bSBoris BREZILLON 	return 0;
1060ad6125bSBoris BREZILLON }
1070ad6125bSBoris BREZILLON 
1080ad6125bSBoris BREZILLON static int pmc_irq_domain_xlate(struct irq_domain *d,
1090ad6125bSBoris BREZILLON 				struct device_node *ctrlr,
1100ad6125bSBoris BREZILLON 				const u32 *intspec, unsigned int intsize,
1110ad6125bSBoris BREZILLON 				irq_hw_number_t *out_hwirq,
1120ad6125bSBoris BREZILLON 				unsigned int *out_type)
1130ad6125bSBoris BREZILLON {
1140ad6125bSBoris BREZILLON 	struct at91_pmc *pmc = d->host_data;
1150ad6125bSBoris BREZILLON 	const struct at91_pmc_caps *caps = pmc->caps;
1160ad6125bSBoris BREZILLON 
1170ad6125bSBoris BREZILLON 	if (WARN_ON(intsize < 1))
1180ad6125bSBoris BREZILLON 		return -EINVAL;
1190ad6125bSBoris BREZILLON 
1200ad6125bSBoris BREZILLON 	*out_hwirq = intspec[0];
1210ad6125bSBoris BREZILLON 
1220ad6125bSBoris BREZILLON 	if (!(caps->available_irqs & (1 << *out_hwirq)))
1230ad6125bSBoris BREZILLON 		return -EINVAL;
1240ad6125bSBoris BREZILLON 
1250ad6125bSBoris BREZILLON 	*out_type = IRQ_TYPE_LEVEL_HIGH;
1260ad6125bSBoris BREZILLON 
1270ad6125bSBoris BREZILLON 	return 0;
1280ad6125bSBoris BREZILLON }
1290ad6125bSBoris BREZILLON 
1300ad6125bSBoris BREZILLON static struct irq_domain_ops pmc_irq_ops = {
1310ad6125bSBoris BREZILLON 	.map	= pmc_irq_map,
1320ad6125bSBoris BREZILLON 	.xlate	= pmc_irq_domain_xlate,
1330ad6125bSBoris BREZILLON };
1340ad6125bSBoris BREZILLON 
1350ad6125bSBoris BREZILLON static irqreturn_t pmc_irq_handler(int irq, void *data)
1360ad6125bSBoris BREZILLON {
1370ad6125bSBoris BREZILLON 	struct at91_pmc *pmc = (struct at91_pmc *)data;
1380ad6125bSBoris BREZILLON 	unsigned long sr;
1390ad6125bSBoris BREZILLON 	int n;
1400ad6125bSBoris BREZILLON 
1410ad6125bSBoris BREZILLON 	sr = pmc_read(pmc, AT91_PMC_SR) & pmc_read(pmc, AT91_PMC_IMR);
1420ad6125bSBoris BREZILLON 	if (!sr)
1430ad6125bSBoris BREZILLON 		return IRQ_NONE;
1440ad6125bSBoris BREZILLON 
1450ad6125bSBoris BREZILLON 	for_each_set_bit(n, &sr, BITS_PER_LONG)
1460ad6125bSBoris BREZILLON 		generic_handle_irq(irq_find_mapping(pmc->irqdomain, n));
1470ad6125bSBoris BREZILLON 
1480ad6125bSBoris BREZILLON 	return IRQ_HANDLED;
1490ad6125bSBoris BREZILLON }
1500ad6125bSBoris BREZILLON 
1510ad6125bSBoris BREZILLON static const struct at91_pmc_caps at91rm9200_caps = {
1520ad6125bSBoris BREZILLON 	.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB |
1530ad6125bSBoris BREZILLON 			  AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY |
1540ad6125bSBoris BREZILLON 			  AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY |
1550ad6125bSBoris BREZILLON 			  AT91_PMC_PCK3RDY,
1560ad6125bSBoris BREZILLON };
1570ad6125bSBoris BREZILLON 
1580ad6125bSBoris BREZILLON static const struct at91_pmc_caps at91sam9260_caps = {
1590ad6125bSBoris BREZILLON 	.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB |
1600ad6125bSBoris BREZILLON 			  AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY |
1610ad6125bSBoris BREZILLON 			  AT91_PMC_PCK1RDY,
1620ad6125bSBoris BREZILLON };
1630ad6125bSBoris BREZILLON 
1640ad6125bSBoris BREZILLON static const struct at91_pmc_caps at91sam9g45_caps = {
1650ad6125bSBoris BREZILLON 	.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
1660ad6125bSBoris BREZILLON 			  AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
1670ad6125bSBoris BREZILLON 			  AT91_PMC_PCK1RDY,
1680ad6125bSBoris BREZILLON };
1690ad6125bSBoris BREZILLON 
1700ad6125bSBoris BREZILLON static const struct at91_pmc_caps at91sam9n12_caps = {
1710ad6125bSBoris BREZILLON 	.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB |
1720ad6125bSBoris BREZILLON 			  AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY |
1730ad6125bSBoris BREZILLON 			  AT91_PMC_PCK1RDY | AT91_PMC_MOSCSELS |
1740ad6125bSBoris BREZILLON 			  AT91_PMC_MOSCRCS | AT91_PMC_CFDEV,
1750ad6125bSBoris BREZILLON };
1760ad6125bSBoris BREZILLON 
1770ad6125bSBoris BREZILLON static const struct at91_pmc_caps at91sam9x5_caps = {
1780ad6125bSBoris BREZILLON 	.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
1790ad6125bSBoris BREZILLON 			  AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
1800ad6125bSBoris BREZILLON 			  AT91_PMC_PCK1RDY | AT91_PMC_MOSCSELS |
1810ad6125bSBoris BREZILLON 			  AT91_PMC_MOSCRCS | AT91_PMC_CFDEV,
1820ad6125bSBoris BREZILLON };
1830ad6125bSBoris BREZILLON 
1840ad6125bSBoris BREZILLON static const struct at91_pmc_caps sama5d3_caps = {
1850ad6125bSBoris BREZILLON 	.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
1860ad6125bSBoris BREZILLON 			  AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
1870ad6125bSBoris BREZILLON 			  AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY |
1880ad6125bSBoris BREZILLON 			  AT91_PMC_MOSCSELS | AT91_PMC_MOSCRCS |
1890ad6125bSBoris BREZILLON 			  AT91_PMC_CFDEV,
1900ad6125bSBoris BREZILLON };
1910ad6125bSBoris BREZILLON 
1920ad6125bSBoris BREZILLON static struct at91_pmc *__init at91_pmc_init(struct device_node *np,
1930ad6125bSBoris BREZILLON 					     void __iomem *regbase, int virq,
1940ad6125bSBoris BREZILLON 					     const struct at91_pmc_caps *caps)
1950ad6125bSBoris BREZILLON {
1960ad6125bSBoris BREZILLON 	struct at91_pmc *pmc;
1970ad6125bSBoris BREZILLON 
1980ad6125bSBoris BREZILLON 	if (!regbase || !virq ||  !caps)
1990ad6125bSBoris BREZILLON 		return NULL;
2000ad6125bSBoris BREZILLON 
2010ad6125bSBoris BREZILLON 	at91_pmc_base = regbase;
2020ad6125bSBoris BREZILLON 
2030ad6125bSBoris BREZILLON 	pmc = kzalloc(sizeof(*pmc), GFP_KERNEL);
2040ad6125bSBoris BREZILLON 	if (!pmc)
2050ad6125bSBoris BREZILLON 		return NULL;
2060ad6125bSBoris BREZILLON 
2070ad6125bSBoris BREZILLON 	spin_lock_init(&pmc->lock);
2080ad6125bSBoris BREZILLON 	pmc->regbase = regbase;
2090ad6125bSBoris BREZILLON 	pmc->virq = virq;
2100ad6125bSBoris BREZILLON 	pmc->caps = caps;
2110ad6125bSBoris BREZILLON 
2120ad6125bSBoris BREZILLON 	pmc->irqdomain = irq_domain_add_linear(np, 32, &pmc_irq_ops, pmc);
2130ad6125bSBoris BREZILLON 
2140ad6125bSBoris BREZILLON 	if (!pmc->irqdomain)
2150ad6125bSBoris BREZILLON 		goto out_free_pmc;
2160ad6125bSBoris BREZILLON 
2170ad6125bSBoris BREZILLON 	pmc_write(pmc, AT91_PMC_IDR, 0xffffffff);
2180ad6125bSBoris BREZILLON 	if (request_irq(pmc->virq, pmc_irq_handler, IRQF_SHARED, "pmc", pmc))
2190ad6125bSBoris BREZILLON 		goto out_remove_irqdomain;
2200ad6125bSBoris BREZILLON 
2210ad6125bSBoris BREZILLON 	return pmc;
2220ad6125bSBoris BREZILLON 
2230ad6125bSBoris BREZILLON out_remove_irqdomain:
2240ad6125bSBoris BREZILLON 	irq_domain_remove(pmc->irqdomain);
2250ad6125bSBoris BREZILLON out_free_pmc:
2260ad6125bSBoris BREZILLON 	kfree(pmc);
2270ad6125bSBoris BREZILLON 
2280ad6125bSBoris BREZILLON 	return NULL;
2290ad6125bSBoris BREZILLON }
2300ad6125bSBoris BREZILLON 
2317736c715SBoris BREZILLON static const struct of_device_id pmc_clk_ids[] __initconst = {
23280eded6cSBoris BREZILLON 	/* Slow oscillator */
23380eded6cSBoris BREZILLON 	{
23480eded6cSBoris BREZILLON 		.compatible = "atmel,at91sam9260-clk-slow",
23580eded6cSBoris BREZILLON 		.data = of_at91sam9260_clk_slow_setup,
23680eded6cSBoris BREZILLON 	},
23738d34c31SBoris BREZILLON 	/* Main clock */
23838d34c31SBoris BREZILLON 	{
23927cb1c20SBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-main-osc",
24027cb1c20SBoris BREZILLON 		.data = of_at91rm9200_clk_main_osc_setup,
24127cb1c20SBoris BREZILLON 	},
24227cb1c20SBoris BREZILLON 	{
24327cb1c20SBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-main-rc-osc",
24427cb1c20SBoris BREZILLON 		.data = of_at91sam9x5_clk_main_rc_osc_setup,
24527cb1c20SBoris BREZILLON 	},
24627cb1c20SBoris BREZILLON 	{
24738d34c31SBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-main",
24838d34c31SBoris BREZILLON 		.data = of_at91rm9200_clk_main_setup,
24938d34c31SBoris BREZILLON 	},
25027cb1c20SBoris BREZILLON 	{
25127cb1c20SBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-main",
25227cb1c20SBoris BREZILLON 		.data = of_at91sam9x5_clk_main_setup,
25327cb1c20SBoris BREZILLON 	},
2541a748d2bSBoris BREZILLON 	/* PLL clocks */
2551a748d2bSBoris BREZILLON 	{
2561a748d2bSBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-pll",
2571a748d2bSBoris BREZILLON 		.data = of_at91rm9200_clk_pll_setup,
2581a748d2bSBoris BREZILLON 	},
2591a748d2bSBoris BREZILLON 	{
2601a748d2bSBoris BREZILLON 		.compatible = "atmel,at91sam9g45-clk-pll",
2611a748d2bSBoris BREZILLON 		.data = of_at91sam9g45_clk_pll_setup,
2621a748d2bSBoris BREZILLON 	},
2631a748d2bSBoris BREZILLON 	{
2641a748d2bSBoris BREZILLON 		.compatible = "atmel,at91sam9g20-clk-pllb",
2651a748d2bSBoris BREZILLON 		.data = of_at91sam9g20_clk_pllb_setup,
2661a748d2bSBoris BREZILLON 	},
2671a748d2bSBoris BREZILLON 	{
2681a748d2bSBoris BREZILLON 		.compatible = "atmel,sama5d3-clk-pll",
2691a748d2bSBoris BREZILLON 		.data = of_sama5d3_clk_pll_setup,
2701a748d2bSBoris BREZILLON 	},
2711a748d2bSBoris BREZILLON 	{
2721a748d2bSBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-plldiv",
2731a748d2bSBoris BREZILLON 		.data = of_at91sam9x5_clk_plldiv_setup,
2741a748d2bSBoris BREZILLON 	},
275e442d234SBoris BREZILLON 	/* Master clock */
276e442d234SBoris BREZILLON 	{
277e442d234SBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-master",
278e442d234SBoris BREZILLON 		.data = of_at91rm9200_clk_master_setup,
279e442d234SBoris BREZILLON 	},
280e442d234SBoris BREZILLON 	{
281e442d234SBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-master",
282e442d234SBoris BREZILLON 		.data = of_at91sam9x5_clk_master_setup,
283e442d234SBoris BREZILLON 	},
2845fba62eaSBoris BREZILLON 	/* System clocks */
2855fba62eaSBoris BREZILLON 	{
2865fba62eaSBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-system",
2875fba62eaSBoris BREZILLON 		.data = of_at91rm9200_clk_sys_setup,
2885fba62eaSBoris BREZILLON 	},
2896114067eSBoris BREZILLON 	/* Peripheral clocks */
2906114067eSBoris BREZILLON 	{
2916114067eSBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-peripheral",
2926114067eSBoris BREZILLON 		.data = of_at91rm9200_clk_periph_setup,
2936114067eSBoris BREZILLON 	},
2946114067eSBoris BREZILLON 	{
2956114067eSBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-peripheral",
2966114067eSBoris BREZILLON 		.data = of_at91sam9x5_clk_periph_setup,
2976114067eSBoris BREZILLON 	},
2981f22f8bbSBoris BREZILLON 	/* Programmable clocks */
2991f22f8bbSBoris BREZILLON 	{
3001f22f8bbSBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-programmable",
3011f22f8bbSBoris BREZILLON 		.data = of_at91rm9200_clk_prog_setup,
3021f22f8bbSBoris BREZILLON 	},
3031f22f8bbSBoris BREZILLON 	{
3041f22f8bbSBoris BREZILLON 		.compatible = "atmel,at91sam9g45-clk-programmable",
3051f22f8bbSBoris BREZILLON 		.data = of_at91sam9g45_clk_prog_setup,
3061f22f8bbSBoris BREZILLON 	},
3071f22f8bbSBoris BREZILLON 	{
3081f22f8bbSBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-programmable",
3091f22f8bbSBoris BREZILLON 		.data = of_at91sam9x5_clk_prog_setup,
3101f22f8bbSBoris BREZILLON 	},
311f090fb37SBoris BREZILLON 	/* UTMI clock */
312f090fb37SBoris BREZILLON #if defined(CONFIG_HAVE_AT91_UTMI)
313f090fb37SBoris BREZILLON 	{
314f090fb37SBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-utmi",
315f090fb37SBoris BREZILLON 		.data = of_at91sam9x5_clk_utmi_setup,
316f090fb37SBoris BREZILLON 	},
317f090fb37SBoris BREZILLON #endif
318c84a61d8SBoris BREZILLON 	/* USB clock */
319c84a61d8SBoris BREZILLON #if defined(CONFIG_HAVE_AT91_USB_CLK)
320c84a61d8SBoris BREZILLON 	{
321c84a61d8SBoris BREZILLON 		.compatible = "atmel,at91rm9200-clk-usb",
322c84a61d8SBoris BREZILLON 		.data = of_at91rm9200_clk_usb_setup,
323c84a61d8SBoris BREZILLON 	},
324c84a61d8SBoris BREZILLON 	{
325c84a61d8SBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-usb",
326c84a61d8SBoris BREZILLON 		.data = of_at91sam9x5_clk_usb_setup,
327c84a61d8SBoris BREZILLON 	},
328c84a61d8SBoris BREZILLON 	{
329c84a61d8SBoris BREZILLON 		.compatible = "atmel,at91sam9n12-clk-usb",
330c84a61d8SBoris BREZILLON 		.data = of_at91sam9n12_clk_usb_setup,
331c84a61d8SBoris BREZILLON 	},
332c84a61d8SBoris BREZILLON #endif
333a9c0688fSBoris BREZILLON 	/* SMD clock */
334a9c0688fSBoris BREZILLON #if defined(CONFIG_HAVE_AT91_SMD)
335a9c0688fSBoris BREZILLON 	{
336a9c0688fSBoris BREZILLON 		.compatible = "atmel,at91sam9x5-clk-smd",
337a9c0688fSBoris BREZILLON 		.data = of_at91sam9x5_clk_smd_setup,
338a9c0688fSBoris BREZILLON 	},
339a9c0688fSBoris BREZILLON #endif
3400ad6125bSBoris BREZILLON 	{ /*sentinel*/ }
3410ad6125bSBoris BREZILLON };
3420ad6125bSBoris BREZILLON 
3430ad6125bSBoris BREZILLON static void __init of_at91_pmc_setup(struct device_node *np,
3440ad6125bSBoris BREZILLON 				     const struct at91_pmc_caps *caps)
3450ad6125bSBoris BREZILLON {
3460ad6125bSBoris BREZILLON 	struct at91_pmc *pmc;
3470ad6125bSBoris BREZILLON 	struct device_node *childnp;
3480ad6125bSBoris BREZILLON 	void (*clk_setup)(struct device_node *, struct at91_pmc *);
3490ad6125bSBoris BREZILLON 	const struct of_device_id *clk_id;
3500ad6125bSBoris BREZILLON 	void __iomem *regbase = of_iomap(np, 0);
3510ad6125bSBoris BREZILLON 	int virq;
3520ad6125bSBoris BREZILLON 
3530ad6125bSBoris BREZILLON 	if (!regbase)
3540ad6125bSBoris BREZILLON 		return;
3550ad6125bSBoris BREZILLON 
3560ad6125bSBoris BREZILLON 	virq = irq_of_parse_and_map(np, 0);
3570ad6125bSBoris BREZILLON 	if (!virq)
3580ad6125bSBoris BREZILLON 		return;
3590ad6125bSBoris BREZILLON 
3600ad6125bSBoris BREZILLON 	pmc = at91_pmc_init(np, regbase, virq, caps);
3610ad6125bSBoris BREZILLON 	if (!pmc)
3620ad6125bSBoris BREZILLON 		return;
3630ad6125bSBoris BREZILLON 	for_each_child_of_node(np, childnp) {
3640ad6125bSBoris BREZILLON 		clk_id = of_match_node(pmc_clk_ids, childnp);
3650ad6125bSBoris BREZILLON 		if (!clk_id)
3660ad6125bSBoris BREZILLON 			continue;
3670ad6125bSBoris BREZILLON 		clk_setup = clk_id->data;
3680ad6125bSBoris BREZILLON 		clk_setup(childnp, pmc);
3690ad6125bSBoris BREZILLON 	}
3700ad6125bSBoris BREZILLON }
3710ad6125bSBoris BREZILLON 
3720ad6125bSBoris BREZILLON static void __init of_at91rm9200_pmc_setup(struct device_node *np)
3730ad6125bSBoris BREZILLON {
3740ad6125bSBoris BREZILLON 	of_at91_pmc_setup(np, &at91rm9200_caps);
3750ad6125bSBoris BREZILLON }
3760ad6125bSBoris BREZILLON CLK_OF_DECLARE(at91rm9200_clk_pmc, "atmel,at91rm9200-pmc",
3770ad6125bSBoris BREZILLON 	       of_at91rm9200_pmc_setup);
3780ad6125bSBoris BREZILLON 
3790ad6125bSBoris BREZILLON static void __init of_at91sam9260_pmc_setup(struct device_node *np)
3800ad6125bSBoris BREZILLON {
3810ad6125bSBoris BREZILLON 	of_at91_pmc_setup(np, &at91sam9260_caps);
3820ad6125bSBoris BREZILLON }
3830ad6125bSBoris BREZILLON CLK_OF_DECLARE(at91sam9260_clk_pmc, "atmel,at91sam9260-pmc",
3840ad6125bSBoris BREZILLON 	       of_at91sam9260_pmc_setup);
3850ad6125bSBoris BREZILLON 
3860ad6125bSBoris BREZILLON static void __init of_at91sam9g45_pmc_setup(struct device_node *np)
3870ad6125bSBoris BREZILLON {
3880ad6125bSBoris BREZILLON 	of_at91_pmc_setup(np, &at91sam9g45_caps);
3890ad6125bSBoris BREZILLON }
3900ad6125bSBoris BREZILLON CLK_OF_DECLARE(at91sam9g45_clk_pmc, "atmel,at91sam9g45-pmc",
3910ad6125bSBoris BREZILLON 	       of_at91sam9g45_pmc_setup);
3920ad6125bSBoris BREZILLON 
3930ad6125bSBoris BREZILLON static void __init of_at91sam9n12_pmc_setup(struct device_node *np)
3940ad6125bSBoris BREZILLON {
3950ad6125bSBoris BREZILLON 	of_at91_pmc_setup(np, &at91sam9n12_caps);
3960ad6125bSBoris BREZILLON }
3970ad6125bSBoris BREZILLON CLK_OF_DECLARE(at91sam9n12_clk_pmc, "atmel,at91sam9n12-pmc",
3980ad6125bSBoris BREZILLON 	       of_at91sam9n12_pmc_setup);
3990ad6125bSBoris BREZILLON 
4000ad6125bSBoris BREZILLON static void __init of_at91sam9x5_pmc_setup(struct device_node *np)
4010ad6125bSBoris BREZILLON {
4020ad6125bSBoris BREZILLON 	of_at91_pmc_setup(np, &at91sam9x5_caps);
4030ad6125bSBoris BREZILLON }
4040ad6125bSBoris BREZILLON CLK_OF_DECLARE(at91sam9x5_clk_pmc, "atmel,at91sam9x5-pmc",
4050ad6125bSBoris BREZILLON 	       of_at91sam9x5_pmc_setup);
4060ad6125bSBoris BREZILLON 
4070ad6125bSBoris BREZILLON static void __init of_sama5d3_pmc_setup(struct device_node *np)
4080ad6125bSBoris BREZILLON {
4090ad6125bSBoris BREZILLON 	of_at91_pmc_setup(np, &sama5d3_caps);
4100ad6125bSBoris BREZILLON }
4110ad6125bSBoris BREZILLON CLK_OF_DECLARE(sama5d3_clk_pmc, "atmel,sama5d3-pmc",
4120ad6125bSBoris BREZILLON 	       of_sama5d3_pmc_setup);
413