11f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON/* 21f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> 31f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON * 41f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON * This program is free software; you can redistribute it and/or modify 51f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON * it under the terms of the GNU General Public License as published by 61f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON * the Free Software Foundation; either version 2 of the License, or 71f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON * (at your option) any later version. 81f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON * 91f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON */ 101f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 111f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#include <linux/clk-provider.h> 121f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#include <linux/clkdev.h> 131f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#include <linux/clk/at91_pmc.h> 141f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#include <linux/of.h> 151f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#include <linux/of_address.h> 161f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#include <linux/io.h> 171f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#include <linux/wait.h> 181f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#include <linux/sched.h> 191f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 201f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#include "pmc.h" 211f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 221f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#define PROG_SOURCE_MAX 5 231f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#define PROG_ID_MAX 7 241f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 251f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#define PROG_STATUS_MASK(id) (1 << ((id) + 8)) 261f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#define PROG_PRES_MASK 0x7 271f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#define PROG_MAX_RM9200_CSS 3 281f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 291f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONstruct clk_programmable_layout { 301f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON u8 pres_shift; 311f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON u8 css_mask; 321f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON u8 have_slck_mck; 331f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON}; 341f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 351f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONstruct clk_programmable { 361f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct clk_hw hw; 371f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct at91_pmc *pmc; 381f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON u8 id; 391f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON const struct clk_programmable_layout *layout; 401f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON}; 411f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 421f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON#define to_clk_programmable(hw) container_of(hw, struct clk_programmable, hw) 431f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 441f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONstatic unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, 451f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON unsigned long parent_rate) 461f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON{ 47cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot u32 pres; 481f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct clk_programmable *prog = to_clk_programmable(hw); 491f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct at91_pmc *pmc = prog->pmc; 501f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON const struct clk_programmable_layout *layout = prog->layout; 511f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 52cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot pres = (pmc_read(pmc, AT91_PMC_PCKR(prog->id)) >> layout->pres_shift) & 53cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot PROG_PRES_MASK; 54cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot return parent_rate >> pres; 551f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON} 561f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 57419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLONstatic long clk_programmable_determine_rate(struct clk_hw *hw, 58419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON unsigned long rate, 59419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON unsigned long *best_parent_rate, 60419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON struct clk **best_parent_clk) 611f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON{ 62419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON struct clk *parent = NULL; 63419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON long best_rate = -EINVAL; 64419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON unsigned long parent_rate; 65419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON unsigned long tmp_rate; 66419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON int shift; 67419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON int i; 68419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON 69419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON for (i = 0; i < __clk_get_num_parents(hw->clk); i++) { 70419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON parent = clk_get_parent_by_index(hw->clk, i); 71419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON if (!parent) 72419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON continue; 73419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON 74419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON parent_rate = __clk_get_rate(parent); 75419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON for (shift = 0; shift < PROG_PRES_MASK; shift++) { 76419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON tmp_rate = parent_rate >> shift; 77419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON if (tmp_rate <= rate) 78419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON break; 79419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON } 801f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 81419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON if (tmp_rate > rate) 82419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON continue; 831f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 84419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON if (best_rate < 0 || (rate - tmp_rate) < (rate - best_rate)) { 85419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON best_rate = tmp_rate; 86419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON *best_parent_rate = parent_rate; 87419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON *best_parent_clk = parent; 881f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON } 891f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 90419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON if (!best_rate) 911f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON break; 921f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON } 931f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 941f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON return best_rate; 951f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON} 961f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 971f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONstatic int clk_programmable_set_parent(struct clk_hw *hw, u8 index) 981f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON{ 991f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct clk_programmable *prog = to_clk_programmable(hw); 1001f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON const struct clk_programmable_layout *layout = prog->layout; 101cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot struct at91_pmc *pmc = prog->pmc; 102cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot u32 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)) & ~layout->css_mask; 103cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot 104cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot if (layout->have_slck_mck) 105cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot tmp &= AT91_PMC_CSSMCK_MCK; 106cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot 1071f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON if (index > layout->css_mask) { 1081f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON if (index > PROG_MAX_RM9200_CSS && layout->have_slck_mck) { 109cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot tmp |= AT91_PMC_CSSMCK_MCK; 1101f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON return 0; 1111f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON } else { 1121f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON return -EINVAL; 1131f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON } 1141f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON } 1151f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 116cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot pmc_write(pmc, AT91_PMC_PCKR(prog->id), tmp | index); 1171f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON return 0; 1181f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON} 1191f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 1201f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONstatic u8 clk_programmable_get_parent(struct clk_hw *hw) 1211f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON{ 1221f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON u32 tmp; 1231f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON u8 ret; 1241f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct clk_programmable *prog = to_clk_programmable(hw); 1251f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct at91_pmc *pmc = prog->pmc; 1261f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON const struct clk_programmable_layout *layout = prog->layout; 1271f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 1281f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)); 129cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot ret = tmp & layout->css_mask; 130cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot if (layout->have_slck_mck && (tmp & AT91_PMC_CSSMCK_MCK) && !ret) 131cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot ret = PROG_MAX_RM9200_CSS + 1; 1321f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 1331f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON return ret; 1341f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON} 1351f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 1361f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONstatic int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate, 1371f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON unsigned long parent_rate) 1381f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON{ 1391f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct clk_programmable *prog = to_clk_programmable(hw); 140cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot struct at91_pmc *pmc = prog->pmc; 141cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot const struct clk_programmable_layout *layout = prog->layout; 142141c71dd2c00ca7d807138ece55a17c61085c793Jean-Jacques Hiblot unsigned long div = parent_rate / rate; 1431f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON int shift = 0; 144cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot u32 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)) & 145cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot ~(PROG_PRES_MASK << layout->pres_shift); 1461f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 147141c71dd2c00ca7d807138ece55a17c61085c793Jean-Jacques Hiblot if (!div) 148141c71dd2c00ca7d807138ece55a17c61085c793Jean-Jacques Hiblot return -EINVAL; 1491f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 150141c71dd2c00ca7d807138ece55a17c61085c793Jean-Jacques Hiblot shift = fls(div) - 1; 1511f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 152141c71dd2c00ca7d807138ece55a17c61085c793Jean-Jacques Hiblot if (div != (1<<shift)) 153141c71dd2c00ca7d807138ece55a17c61085c793Jean-Jacques Hiblot return -EINVAL; 1541f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 155141c71dd2c00ca7d807138ece55a17c61085c793Jean-Jacques Hiblot if (shift >= PROG_PRES_MASK) 156141c71dd2c00ca7d807138ece55a17c61085c793Jean-Jacques Hiblot return -EINVAL; 1571f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 158cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot pmc_write(pmc, AT91_PMC_PCKR(prog->id), 159cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot tmp | (shift << layout->pres_shift)); 160cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot 1611f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON return 0; 1621f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON} 1631f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 1641f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONstatic const struct clk_ops programmable_ops = { 1651f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON .recalc_rate = clk_programmable_recalc_rate, 166419f612932674d5f72b1995eda52ca15d87361efBoris BREZILLON .determine_rate = clk_programmable_determine_rate, 1671f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON .get_parent = clk_programmable_get_parent, 1681f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON .set_parent = clk_programmable_set_parent, 1691f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON .set_rate = clk_programmable_set_rate, 1701f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON}; 1711f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 1721f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONstatic struct clk * __init 173cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblotat91_clk_register_programmable(struct at91_pmc *pmc, 1741f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON const char *name, const char **parent_names, 1751f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON u8 num_parents, u8 id, 1761f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON const struct clk_programmable_layout *layout) 1771f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON{ 1781f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct clk_programmable *prog; 1791f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct clk *clk = NULL; 1801f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct clk_init_data init; 1811f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 1821f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON if (id > PROG_ID_MAX) 1831f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON return ERR_PTR(-EINVAL); 1841f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 1851f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON prog = kzalloc(sizeof(*prog), GFP_KERNEL); 1861f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON if (!prog) 1871f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON return ERR_PTR(-ENOMEM); 1881f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 1891f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON init.name = name; 1901f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON init.ops = &programmable_ops; 1911f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON init.parent_names = parent_names; 1921f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON init.num_parents = num_parents; 1931f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; 1941f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 1951f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON prog->id = id; 1961f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON prog->layout = layout; 1971f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON prog->hw.init = &init; 1981f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON prog->pmc = pmc; 1991f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2001f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON clk = clk_register(NULL, &prog->hw); 2011f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON if (IS_ERR(clk)) 2021f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON kfree(prog); 2031f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2041f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON return clk; 2051f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON} 2061f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2071f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONstatic const struct clk_programmable_layout at91rm9200_programmable_layout = { 2081f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON .pres_shift = 2, 2091f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON .css_mask = 0x3, 2101f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON .have_slck_mck = 0, 2111f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON}; 2121f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2131f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONstatic const struct clk_programmable_layout at91sam9g45_programmable_layout = { 2141f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON .pres_shift = 2, 2151f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON .css_mask = 0x3, 2161f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON .have_slck_mck = 1, 2171f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON}; 2181f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2191f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONstatic const struct clk_programmable_layout at91sam9x5_programmable_layout = { 2201f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON .pres_shift = 4, 2211f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON .css_mask = 0x7, 2221f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON .have_slck_mck = 0, 2231f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON}; 2241f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2251f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONstatic void __init 2261f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONof_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, 2271f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON const struct clk_programmable_layout *layout) 2281f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON{ 2291f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON int num; 2301f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON u32 id; 2311f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON int i; 2321f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct clk *clk; 2331f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON int num_parents; 2341f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON const char *parent_names[PROG_SOURCE_MAX]; 2351f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON const char *name; 2361f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct device_node *progclknp; 2371f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2381f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); 2391f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON if (num_parents <= 0 || num_parents > PROG_SOURCE_MAX) 2401f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON return; 2411f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2421f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON for (i = 0; i < num_parents; ++i) { 2431f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON parent_names[i] = of_clk_get_parent_name(np, i); 2441f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON if (!parent_names[i]) 2451f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON return; 2461f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON } 2471f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2481f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON num = of_get_child_count(np); 2491f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON if (!num || num > (PROG_ID_MAX + 1)) 2501f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON return; 2511f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2521f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON for_each_child_of_node(np, progclknp) { 2531f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON if (of_property_read_u32(progclknp, "reg", &id)) 2541f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON continue; 2551f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2561f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON if (of_property_read_string(np, "clock-output-names", &name)) 2571f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON name = progclknp->name; 2581f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 259cce6db80a049b23f867f4afded70ca8027876a08Jean-Jacques Hiblot clk = at91_clk_register_programmable(pmc, name, 2601f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON parent_names, num_parents, 2611f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON id, layout); 2621f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON if (IS_ERR(clk)) 2631f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON continue; 2641f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2651f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON of_clk_add_provider(progclknp, of_clk_src_simple_get, clk); 2661f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON } 2671f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON} 2681f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2691f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2701f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONvoid __init of_at91rm9200_clk_prog_setup(struct device_node *np, 2711f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct at91_pmc *pmc) 2721f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON{ 2731f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON of_at91_clk_prog_setup(np, pmc, &at91rm9200_programmable_layout); 2741f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON} 2751f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2761f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONvoid __init of_at91sam9g45_clk_prog_setup(struct device_node *np, 2771f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct at91_pmc *pmc) 2781f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON{ 2791f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON of_at91_clk_prog_setup(np, pmc, &at91sam9g45_programmable_layout); 2801f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON} 2811f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON 2821f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLONvoid __init of_at91sam9x5_clk_prog_setup(struct device_node *np, 2831f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON struct at91_pmc *pmc) 2841f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON{ 2851f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON of_at91_clk_prog_setup(np, pmc, &at91sam9x5_programmable_layout); 2861f22f8bb64b3619324020b48b03181914b1f5544Boris BREZILLON} 287