19e5935c0SWenyou Yang /* 29e5935c0SWenyou Yang * Copyright (C) 2016 Atmel Corporation 39e5935c0SWenyou Yang * Wenyou.Yang <wenyou.yang@atmel.com> 49e5935c0SWenyou Yang * 59e5935c0SWenyou Yang * SPDX-License-Identifier: GPL-2.0+ 69e5935c0SWenyou Yang */ 79e5935c0SWenyou Yang 89e5935c0SWenyou Yang #include <common.h> 99e5935c0SWenyou Yang #include <clk-uclass.h> 109e5935c0SWenyou Yang #include <dm/device.h> 119e5935c0SWenyou Yang #include <linux/io.h> 129e5935c0SWenyou Yang #include <mach/at91_pmc.h> 139e5935c0SWenyou Yang #include "pmc.h" 149e5935c0SWenyou Yang 159e5935c0SWenyou Yang #define SYSTEM_MAX_ID 31 169e5935c0SWenyou Yang 17*6cadaa04SWenyou Yang /** 18*6cadaa04SWenyou Yang * at91_system_clk_bind() - for the system clock driver 19*6cadaa04SWenyou Yang * Recursively bind its children as clk devices. 20*6cadaa04SWenyou Yang * 21*6cadaa04SWenyou Yang * @return: 0 on success, or negative error code on failure 22*6cadaa04SWenyou Yang */ 23*6cadaa04SWenyou Yang static int at91_system_clk_bind(struct udevice *dev) 24*6cadaa04SWenyou Yang { 25*6cadaa04SWenyou Yang return at91_clk_sub_device_bind(dev, "system-clk"); 26*6cadaa04SWenyou Yang } 27*6cadaa04SWenyou Yang 28*6cadaa04SWenyou Yang static const struct udevice_id at91_system_clk_match[] = { 29*6cadaa04SWenyou Yang { .compatible = "atmel,at91rm9200-clk-system" }, 30*6cadaa04SWenyou Yang {} 31*6cadaa04SWenyou Yang }; 32*6cadaa04SWenyou Yang 33*6cadaa04SWenyou Yang U_BOOT_DRIVER(at91_system_clk) = { 34*6cadaa04SWenyou Yang .name = "at91-system-clk", 35*6cadaa04SWenyou Yang .id = UCLASS_MISC, 36*6cadaa04SWenyou Yang .of_match = at91_system_clk_match, 37*6cadaa04SWenyou Yang .bind = at91_system_clk_bind, 38*6cadaa04SWenyou Yang }; 39*6cadaa04SWenyou Yang 40*6cadaa04SWenyou Yang /*----------------------------------------------------------*/ 41*6cadaa04SWenyou Yang 429e5935c0SWenyou Yang static inline int is_pck(int id) 439e5935c0SWenyou Yang { 449e5935c0SWenyou Yang return (id >= 8) && (id <= 15); 459e5935c0SWenyou Yang } 469e5935c0SWenyou Yang 47*6cadaa04SWenyou Yang static int system_clk_enable(struct clk *clk) 489e5935c0SWenyou Yang { 499e5935c0SWenyou Yang struct pmc_platdata *plat = dev_get_platdata(clk->dev); 509e5935c0SWenyou Yang struct at91_pmc *pmc = plat->reg_base; 519e5935c0SWenyou Yang u32 mask; 529e5935c0SWenyou Yang 539e5935c0SWenyou Yang if (clk->id > SYSTEM_MAX_ID) 549e5935c0SWenyou Yang return -EINVAL; 559e5935c0SWenyou Yang 569e5935c0SWenyou Yang mask = BIT(clk->id); 579e5935c0SWenyou Yang 589e5935c0SWenyou Yang writel(mask, &pmc->scer); 599e5935c0SWenyou Yang 609e5935c0SWenyou Yang /** 619e5935c0SWenyou Yang * For the programmable clocks the Ready status in the PMC 629e5935c0SWenyou Yang * status register should be checked after enabling. 639e5935c0SWenyou Yang * For other clocks this is unnecessary. 649e5935c0SWenyou Yang */ 659e5935c0SWenyou Yang if (!is_pck(clk->id)) 669e5935c0SWenyou Yang return 0; 679e5935c0SWenyou Yang 689e5935c0SWenyou Yang while (!(readl(&pmc->sr) & mask)) 699e5935c0SWenyou Yang ; 709e5935c0SWenyou Yang 719e5935c0SWenyou Yang return 0; 729e5935c0SWenyou Yang } 739e5935c0SWenyou Yang 74*6cadaa04SWenyou Yang static struct clk_ops system_clk_ops = { 75*6cadaa04SWenyou Yang .of_xlate = at91_clk_of_xlate, 76*6cadaa04SWenyou Yang .enable = system_clk_enable, 779e5935c0SWenyou Yang }; 789e5935c0SWenyou Yang 79*6cadaa04SWenyou Yang U_BOOT_DRIVER(system_clk) = { 80*6cadaa04SWenyou Yang .name = "system-clk", 819e5935c0SWenyou Yang .id = UCLASS_CLK, 82*6cadaa04SWenyou Yang .probe = at91_clk_probe, 839e5935c0SWenyou Yang .platdata_auto_alloc_size = sizeof(struct pmc_platdata), 84*6cadaa04SWenyou Yang .ops = &system_clk_ops, 859e5935c0SWenyou Yang }; 86