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