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