1bda00303SRobert Jarzmik /* 2bda00303SRobert Jarzmik * Marvell PXA family clocks 3bda00303SRobert Jarzmik * 4bda00303SRobert Jarzmik * Copyright (C) 2014 Robert Jarzmik 5bda00303SRobert Jarzmik * 6bda00303SRobert Jarzmik * Common clock code for PXA clocks ("CKEN" type clocks + DT) 7bda00303SRobert Jarzmik * 8bda00303SRobert Jarzmik * This program is free software; you can redistribute it and/or modify 9bda00303SRobert Jarzmik * it under the terms of the GNU General Public License as published by 10bda00303SRobert Jarzmik * the Free Software Foundation; version 2 of the License. 11bda00303SRobert Jarzmik * 12bda00303SRobert Jarzmik */ 13bda00303SRobert Jarzmik #include <linux/clk.h> 14bda00303SRobert Jarzmik #include <linux/clk-provider.h> 15bda00303SRobert Jarzmik #include <linux/clkdev.h> 16bda00303SRobert Jarzmik #include <linux/of.h> 17bda00303SRobert Jarzmik 18bda00303SRobert Jarzmik #include <dt-bindings/clock/pxa-clock.h> 19bda00303SRobert Jarzmik #include "clk-pxa.h" 20bda00303SRobert Jarzmik 21bda00303SRobert Jarzmik DEFINE_SPINLOCK(lock); 22bda00303SRobert Jarzmik 23bda00303SRobert Jarzmik static struct clk *pxa_clocks[CLK_MAX]; 24bda00303SRobert Jarzmik static struct clk_onecell_data onecell_data = { 25bda00303SRobert Jarzmik .clks = pxa_clocks, 26bda00303SRobert Jarzmik .clk_num = CLK_MAX, 27bda00303SRobert Jarzmik }; 28bda00303SRobert Jarzmik 2914dd5b01SRobert Jarzmik struct pxa_clk { 3014dd5b01SRobert Jarzmik struct clk_hw hw; 3114dd5b01SRobert Jarzmik struct clk_fixed_factor lp; 3214dd5b01SRobert Jarzmik struct clk_fixed_factor hp; 3314dd5b01SRobert Jarzmik struct clk_gate gate; 3414dd5b01SRobert Jarzmik bool (*is_in_low_power)(void); 3514dd5b01SRobert Jarzmik }; 3614dd5b01SRobert Jarzmik 3714dd5b01SRobert Jarzmik #define to_pxa_clk(_hw) container_of(_hw, struct pxa_clk, hw) 38bda00303SRobert Jarzmik 39bda00303SRobert Jarzmik static unsigned long cken_recalc_rate(struct clk_hw *hw, 40bda00303SRobert Jarzmik unsigned long parent_rate) 41bda00303SRobert Jarzmik { 4214dd5b01SRobert Jarzmik struct pxa_clk *pclk = to_pxa_clk(hw); 43bda00303SRobert Jarzmik struct clk_fixed_factor *fix; 44bda00303SRobert Jarzmik 45bda00303SRobert Jarzmik if (!pclk->is_in_low_power || pclk->is_in_low_power()) 46bda00303SRobert Jarzmik fix = &pclk->lp; 47bda00303SRobert Jarzmik else 48bda00303SRobert Jarzmik fix = &pclk->hp; 49bda00303SRobert Jarzmik fix->hw.clk = hw->clk; 50bda00303SRobert Jarzmik return clk_fixed_factor_ops.recalc_rate(&fix->hw, parent_rate); 51bda00303SRobert Jarzmik } 52bda00303SRobert Jarzmik 53bda00303SRobert Jarzmik static struct clk_ops cken_rate_ops = { 54bda00303SRobert Jarzmik .recalc_rate = cken_recalc_rate, 55bda00303SRobert Jarzmik }; 56bda00303SRobert Jarzmik 57bda00303SRobert Jarzmik static u8 cken_get_parent(struct clk_hw *hw) 58bda00303SRobert Jarzmik { 5914dd5b01SRobert Jarzmik struct pxa_clk *pclk = to_pxa_clk(hw); 60bda00303SRobert Jarzmik 61bda00303SRobert Jarzmik if (!pclk->is_in_low_power) 62bda00303SRobert Jarzmik return 0; 63bda00303SRobert Jarzmik return pclk->is_in_low_power() ? 0 : 1; 64bda00303SRobert Jarzmik } 65bda00303SRobert Jarzmik 66bda00303SRobert Jarzmik static struct clk_ops cken_mux_ops = { 67bda00303SRobert Jarzmik .get_parent = cken_get_parent, 68bda00303SRobert Jarzmik .set_parent = dummy_clk_set_parent, 69bda00303SRobert Jarzmik }; 70bda00303SRobert Jarzmik 71bda00303SRobert Jarzmik void __init clkdev_pxa_register(int ckid, const char *con_id, 72bda00303SRobert Jarzmik const char *dev_id, struct clk *clk) 73bda00303SRobert Jarzmik { 74bda00303SRobert Jarzmik if (!IS_ERR(clk) && (ckid != CLK_NONE)) 75bda00303SRobert Jarzmik pxa_clocks[ckid] = clk; 76bda00303SRobert Jarzmik if (!IS_ERR(clk)) 77bda00303SRobert Jarzmik clk_register_clkdev(clk, con_id, dev_id); 78bda00303SRobert Jarzmik } 79bda00303SRobert Jarzmik 8014dd5b01SRobert Jarzmik int __init clk_pxa_cken_init(const struct desc_clk_cken *clks, int nb_clks) 81bda00303SRobert Jarzmik { 82bda00303SRobert Jarzmik int i; 8314dd5b01SRobert Jarzmik struct pxa_clk *pxa_clk; 84bda00303SRobert Jarzmik struct clk *clk; 85bda00303SRobert Jarzmik 86bda00303SRobert Jarzmik for (i = 0; i < nb_clks; i++) { 8714dd5b01SRobert Jarzmik pxa_clk = kzalloc(sizeof(*pxa_clk), GFP_KERNEL); 8814dd5b01SRobert Jarzmik pxa_clk->is_in_low_power = clks[i].is_in_low_power; 8914dd5b01SRobert Jarzmik pxa_clk->lp = clks[i].lp; 9014dd5b01SRobert Jarzmik pxa_clk->hp = clks[i].hp; 9114dd5b01SRobert Jarzmik pxa_clk->gate = clks[i].gate; 9214dd5b01SRobert Jarzmik pxa_clk->gate.lock = &lock; 9314dd5b01SRobert Jarzmik clk = clk_register_composite(NULL, clks[i].name, 9414dd5b01SRobert Jarzmik clks[i].parent_names, 2, 9514dd5b01SRobert Jarzmik &pxa_clk->hw, &cken_mux_ops, 9614dd5b01SRobert Jarzmik &pxa_clk->hw, &cken_rate_ops, 9714dd5b01SRobert Jarzmik &pxa_clk->gate.hw, &clk_gate_ops, 9814dd5b01SRobert Jarzmik clks[i].flags); 9914dd5b01SRobert Jarzmik clkdev_pxa_register(clks[i].ckid, clks[i].con_id, 10014dd5b01SRobert Jarzmik clks[i].dev_id, clk); 101bda00303SRobert Jarzmik } 102bda00303SRobert Jarzmik return 0; 103bda00303SRobert Jarzmik } 104bda00303SRobert Jarzmik 105*6f8a444aSRobert Jarzmik void __init clk_pxa_dt_common_init(struct device_node *np) 106bda00303SRobert Jarzmik { 107bda00303SRobert Jarzmik of_clk_add_provider(np, of_clk_src_onecell_get, &onecell_data); 108bda00303SRobert Jarzmik } 109