15b82d03bSUlf Hansson /* 25b82d03bSUlf Hansson * Sysctrl clock implementation for ux500 platform. 35b82d03bSUlf Hansson * 45b82d03bSUlf Hansson * Copyright (C) 2013 ST-Ericsson SA 55b82d03bSUlf Hansson * Author: Ulf Hansson <ulf.hansson@linaro.org> 65b82d03bSUlf Hansson * 75b82d03bSUlf Hansson * License terms: GNU General Public License (GPL) version 2 85b82d03bSUlf Hansson */ 95b82d03bSUlf Hansson 105b82d03bSUlf Hansson #include <linux/clk-provider.h> 115b82d03bSUlf Hansson #include <linux/mfd/abx500/ab8500-sysctrl.h> 125b82d03bSUlf Hansson #include <linux/device.h> 135b82d03bSUlf Hansson #include <linux/slab.h> 145b82d03bSUlf Hansson #include <linux/delay.h> 155b82d03bSUlf Hansson #include <linux/io.h> 165b82d03bSUlf Hansson #include <linux/err.h> 175b82d03bSUlf Hansson #include "clk.h" 185b82d03bSUlf Hansson 195b82d03bSUlf Hansson #define SYSCTRL_MAX_NUM_PARENTS 4 205b82d03bSUlf Hansson 215b82d03bSUlf Hansson #define to_clk_sysctrl(_hw) container_of(_hw, struct clk_sysctrl, hw) 225b82d03bSUlf Hansson 235b82d03bSUlf Hansson struct clk_sysctrl { 245b82d03bSUlf Hansson struct clk_hw hw; 255b82d03bSUlf Hansson struct device *dev; 265b82d03bSUlf Hansson u8 parent_index; 275b82d03bSUlf Hansson u16 reg_sel[SYSCTRL_MAX_NUM_PARENTS]; 285b82d03bSUlf Hansson u8 reg_mask[SYSCTRL_MAX_NUM_PARENTS]; 295b82d03bSUlf Hansson u8 reg_bits[SYSCTRL_MAX_NUM_PARENTS]; 305b82d03bSUlf Hansson unsigned long rate; 315b82d03bSUlf Hansson unsigned long enable_delay_us; 325b82d03bSUlf Hansson }; 335b82d03bSUlf Hansson 345b82d03bSUlf Hansson /* Sysctrl clock operations. */ 355b82d03bSUlf Hansson 365b82d03bSUlf Hansson static int clk_sysctrl_prepare(struct clk_hw *hw) 375b82d03bSUlf Hansson { 385b82d03bSUlf Hansson int ret; 395b82d03bSUlf Hansson struct clk_sysctrl *clk = to_clk_sysctrl(hw); 405b82d03bSUlf Hansson 415b82d03bSUlf Hansson ret = ab8500_sysctrl_write(clk->reg_sel[0], clk->reg_mask[0], 425b82d03bSUlf Hansson clk->reg_bits[0]); 435b82d03bSUlf Hansson 445b82d03bSUlf Hansson if (!ret && clk->enable_delay_us) 455b82d03bSUlf Hansson usleep_range(clk->enable_delay_us, clk->enable_delay_us); 465b82d03bSUlf Hansson 475b82d03bSUlf Hansson return ret; 485b82d03bSUlf Hansson } 495b82d03bSUlf Hansson 505b82d03bSUlf Hansson static void clk_sysctrl_unprepare(struct clk_hw *hw) 515b82d03bSUlf Hansson { 525b82d03bSUlf Hansson struct clk_sysctrl *clk = to_clk_sysctrl(hw); 535b82d03bSUlf Hansson if (ab8500_sysctrl_clear(clk->reg_sel[0], clk->reg_mask[0])) 545b82d03bSUlf Hansson dev_err(clk->dev, "clk_sysctrl: %s fail to clear %s.\n", 55836ee0f7SStephen Boyd __func__, clk_hw_get_name(hw)); 565b82d03bSUlf Hansson } 575b82d03bSUlf Hansson 585b82d03bSUlf Hansson static unsigned long clk_sysctrl_recalc_rate(struct clk_hw *hw, 595b82d03bSUlf Hansson unsigned long parent_rate) 605b82d03bSUlf Hansson { 615b82d03bSUlf Hansson struct clk_sysctrl *clk = to_clk_sysctrl(hw); 625b82d03bSUlf Hansson return clk->rate; 635b82d03bSUlf Hansson } 645b82d03bSUlf Hansson 655b82d03bSUlf Hansson static int clk_sysctrl_set_parent(struct clk_hw *hw, u8 index) 665b82d03bSUlf Hansson { 675b82d03bSUlf Hansson struct clk_sysctrl *clk = to_clk_sysctrl(hw); 685b82d03bSUlf Hansson u8 old_index = clk->parent_index; 695b82d03bSUlf Hansson int ret = 0; 705b82d03bSUlf Hansson 715b82d03bSUlf Hansson if (clk->reg_sel[old_index]) { 725b82d03bSUlf Hansson ret = ab8500_sysctrl_clear(clk->reg_sel[old_index], 735b82d03bSUlf Hansson clk->reg_mask[old_index]); 745b82d03bSUlf Hansson if (ret) 755b82d03bSUlf Hansson return ret; 765b82d03bSUlf Hansson } 775b82d03bSUlf Hansson 785b82d03bSUlf Hansson if (clk->reg_sel[index]) { 795b82d03bSUlf Hansson ret = ab8500_sysctrl_write(clk->reg_sel[index], 805b82d03bSUlf Hansson clk->reg_mask[index], 815b82d03bSUlf Hansson clk->reg_bits[index]); 825b82d03bSUlf Hansson if (ret) { 835b82d03bSUlf Hansson if (clk->reg_sel[old_index]) 845b82d03bSUlf Hansson ab8500_sysctrl_write(clk->reg_sel[old_index], 855b82d03bSUlf Hansson clk->reg_mask[old_index], 865b82d03bSUlf Hansson clk->reg_bits[old_index]); 875b82d03bSUlf Hansson return ret; 885b82d03bSUlf Hansson } 895b82d03bSUlf Hansson } 905b82d03bSUlf Hansson clk->parent_index = index; 915b82d03bSUlf Hansson 925b82d03bSUlf Hansson return ret; 935b82d03bSUlf Hansson } 945b82d03bSUlf Hansson 955b82d03bSUlf Hansson static u8 clk_sysctrl_get_parent(struct clk_hw *hw) 965b82d03bSUlf Hansson { 975b82d03bSUlf Hansson struct clk_sysctrl *clk = to_clk_sysctrl(hw); 985b82d03bSUlf Hansson return clk->parent_index; 995b82d03bSUlf Hansson } 1005b82d03bSUlf Hansson 1015b82d03bSUlf Hansson static struct clk_ops clk_sysctrl_gate_ops = { 1025b82d03bSUlf Hansson .prepare = clk_sysctrl_prepare, 1035b82d03bSUlf Hansson .unprepare = clk_sysctrl_unprepare, 1045b82d03bSUlf Hansson }; 1055b82d03bSUlf Hansson 1065b82d03bSUlf Hansson static struct clk_ops clk_sysctrl_gate_fixed_rate_ops = { 1075b82d03bSUlf Hansson .prepare = clk_sysctrl_prepare, 1085b82d03bSUlf Hansson .unprepare = clk_sysctrl_unprepare, 1095b82d03bSUlf Hansson .recalc_rate = clk_sysctrl_recalc_rate, 1105b82d03bSUlf Hansson }; 1115b82d03bSUlf Hansson 1125b82d03bSUlf Hansson static struct clk_ops clk_sysctrl_set_parent_ops = { 1135b82d03bSUlf Hansson .set_parent = clk_sysctrl_set_parent, 1145b82d03bSUlf Hansson .get_parent = clk_sysctrl_get_parent, 1155b82d03bSUlf Hansson }; 1165b82d03bSUlf Hansson 1175b82d03bSUlf Hansson static struct clk *clk_reg_sysctrl(struct device *dev, 1185b82d03bSUlf Hansson const char *name, 1195b82d03bSUlf Hansson const char **parent_names, 1205b82d03bSUlf Hansson u8 num_parents, 1215b82d03bSUlf Hansson u16 *reg_sel, 1225b82d03bSUlf Hansson u8 *reg_mask, 1235b82d03bSUlf Hansson u8 *reg_bits, 1245b82d03bSUlf Hansson unsigned long rate, 1255b82d03bSUlf Hansson unsigned long enable_delay_us, 1265b82d03bSUlf Hansson unsigned long flags, 1275b82d03bSUlf Hansson struct clk_ops *clk_sysctrl_ops) 1285b82d03bSUlf Hansson { 1295b82d03bSUlf Hansson struct clk_sysctrl *clk; 1305b82d03bSUlf Hansson struct clk_init_data clk_sysctrl_init; 1315b82d03bSUlf Hansson struct clk *clk_reg; 1325b82d03bSUlf Hansson int i; 1335b82d03bSUlf Hansson 1345b82d03bSUlf Hansson if (!dev) 1355b82d03bSUlf Hansson return ERR_PTR(-EINVAL); 1365b82d03bSUlf Hansson 1375b82d03bSUlf Hansson if (!name || (num_parents > SYSCTRL_MAX_NUM_PARENTS)) { 1385b82d03bSUlf Hansson dev_err(dev, "clk_sysctrl: invalid arguments passed\n"); 1395b82d03bSUlf Hansson return ERR_PTR(-EINVAL); 1405b82d03bSUlf Hansson } 1415b82d03bSUlf Hansson 1425b82d03bSUlf Hansson clk = devm_kzalloc(dev, sizeof(struct clk_sysctrl), GFP_KERNEL); 1435b82d03bSUlf Hansson if (!clk) { 1445b82d03bSUlf Hansson dev_err(dev, "clk_sysctrl: could not allocate clk\n"); 1455b82d03bSUlf Hansson return ERR_PTR(-ENOMEM); 1465b82d03bSUlf Hansson } 1475b82d03bSUlf Hansson 148f586938bSFabio Baltieri /* set main clock registers */ 149f586938bSFabio Baltieri clk->reg_sel[0] = reg_sel[0]; 150f586938bSFabio Baltieri clk->reg_bits[0] = reg_bits[0]; 151f586938bSFabio Baltieri clk->reg_mask[0] = reg_mask[0]; 152f586938bSFabio Baltieri 153f586938bSFabio Baltieri /* handle clocks with more than one parent */ 154f586938bSFabio Baltieri for (i = 1; i < num_parents; i++) { 1555b82d03bSUlf Hansson clk->reg_sel[i] = reg_sel[i]; 1565b82d03bSUlf Hansson clk->reg_bits[i] = reg_bits[i]; 1575b82d03bSUlf Hansson clk->reg_mask[i] = reg_mask[i]; 1585b82d03bSUlf Hansson } 1595b82d03bSUlf Hansson 1605b82d03bSUlf Hansson clk->parent_index = 0; 1615b82d03bSUlf Hansson clk->rate = rate; 1625b82d03bSUlf Hansson clk->enable_delay_us = enable_delay_us; 1635b82d03bSUlf Hansson clk->dev = dev; 1645b82d03bSUlf Hansson 1655b82d03bSUlf Hansson clk_sysctrl_init.name = name; 1665b82d03bSUlf Hansson clk_sysctrl_init.ops = clk_sysctrl_ops; 1675b82d03bSUlf Hansson clk_sysctrl_init.flags = flags; 1685b82d03bSUlf Hansson clk_sysctrl_init.parent_names = parent_names; 1695b82d03bSUlf Hansson clk_sysctrl_init.num_parents = num_parents; 1705b82d03bSUlf Hansson clk->hw.init = &clk_sysctrl_init; 1715b82d03bSUlf Hansson 1725b82d03bSUlf Hansson clk_reg = devm_clk_register(clk->dev, &clk->hw); 1735b82d03bSUlf Hansson if (IS_ERR(clk_reg)) 1745b82d03bSUlf Hansson dev_err(dev, "clk_sysctrl: clk_register failed\n"); 1755b82d03bSUlf Hansson 1765b82d03bSUlf Hansson return clk_reg; 1775b82d03bSUlf Hansson } 1785b82d03bSUlf Hansson 1795b82d03bSUlf Hansson struct clk *clk_reg_sysctrl_gate(struct device *dev, 1805b82d03bSUlf Hansson const char *name, 1815b82d03bSUlf Hansson const char *parent_name, 1825b82d03bSUlf Hansson u16 reg_sel, 1835b82d03bSUlf Hansson u8 reg_mask, 1845b82d03bSUlf Hansson u8 reg_bits, 1855b82d03bSUlf Hansson unsigned long enable_delay_us, 1865b82d03bSUlf Hansson unsigned long flags) 1875b82d03bSUlf Hansson { 1885b82d03bSUlf Hansson const char **parent_names = (parent_name ? &parent_name : NULL); 1895b82d03bSUlf Hansson u8 num_parents = (parent_name ? 1 : 0); 1905b82d03bSUlf Hansson 1915b82d03bSUlf Hansson return clk_reg_sysctrl(dev, name, parent_names, num_parents, 1925b82d03bSUlf Hansson ®_sel, ®_mask, ®_bits, 0, enable_delay_us, 1935b82d03bSUlf Hansson flags, &clk_sysctrl_gate_ops); 1945b82d03bSUlf Hansson } 1955b82d03bSUlf Hansson 1965b82d03bSUlf Hansson struct clk *clk_reg_sysctrl_gate_fixed_rate(struct device *dev, 1975b82d03bSUlf Hansson const char *name, 1985b82d03bSUlf Hansson const char *parent_name, 1995b82d03bSUlf Hansson u16 reg_sel, 2005b82d03bSUlf Hansson u8 reg_mask, 2015b82d03bSUlf Hansson u8 reg_bits, 2025b82d03bSUlf Hansson unsigned long rate, 2035b82d03bSUlf Hansson unsigned long enable_delay_us, 2045b82d03bSUlf Hansson unsigned long flags) 2055b82d03bSUlf Hansson { 2065b82d03bSUlf Hansson const char **parent_names = (parent_name ? &parent_name : NULL); 2075b82d03bSUlf Hansson u8 num_parents = (parent_name ? 1 : 0); 2085b82d03bSUlf Hansson 2095b82d03bSUlf Hansson return clk_reg_sysctrl(dev, name, parent_names, num_parents, 2105b82d03bSUlf Hansson ®_sel, ®_mask, ®_bits, 2115b82d03bSUlf Hansson rate, enable_delay_us, flags, 2125b82d03bSUlf Hansson &clk_sysctrl_gate_fixed_rate_ops); 2135b82d03bSUlf Hansson } 2145b82d03bSUlf Hansson 2155b82d03bSUlf Hansson struct clk *clk_reg_sysctrl_set_parent(struct device *dev, 2165b82d03bSUlf Hansson const char *name, 2175b82d03bSUlf Hansson const char **parent_names, 2185b82d03bSUlf Hansson u8 num_parents, 2195b82d03bSUlf Hansson u16 *reg_sel, 2205b82d03bSUlf Hansson u8 *reg_mask, 2215b82d03bSUlf Hansson u8 *reg_bits, 2225b82d03bSUlf Hansson unsigned long flags) 2235b82d03bSUlf Hansson { 2245b82d03bSUlf Hansson return clk_reg_sysctrl(dev, name, parent_names, num_parents, 2255b82d03bSUlf Hansson reg_sel, reg_mask, reg_bits, 0, 0, flags, 2265b82d03bSUlf Hansson &clk_sysctrl_set_parent_ops); 2275b82d03bSUlf Hansson } 228