191b87a47SLinus Walleij /* 291b87a47SLinus Walleij * Driver for the ICST307 VCO clock found in the ARM Reference designs. 391b87a47SLinus Walleij * We wrap the custom interface from <asm/hardware/icst.h> into the generic 491b87a47SLinus Walleij * clock framework. 591b87a47SLinus Walleij * 6d430819dSLinus Walleij * Copyright (C) 2012-2015 Linus Walleij 7401301ccSLinus Walleij * 8401301ccSLinus Walleij * This program is free software; you can redistribute it and/or modify 9401301ccSLinus Walleij * it under the terms of the GNU General Public License version 2 as 10401301ccSLinus Walleij * published by the Free Software Foundation. 11401301ccSLinus Walleij * 1291b87a47SLinus Walleij * TODO: when all ARM reference designs are migrated to generic clocks, the 1391b87a47SLinus Walleij * ICST clock code from the ARM tree should probably be merged into this 1491b87a47SLinus Walleij * file. 1591b87a47SLinus Walleij */ 166d31e3b2SStephen Boyd #include <linux/kernel.h> 176d31e3b2SStephen Boyd #include <linux/slab.h> 186d31e3b2SStephen Boyd #include <linux/export.h> 1991b87a47SLinus Walleij #include <linux/err.h> 2091b87a47SLinus Walleij #include <linux/clk-provider.h> 217a9ad671SLinus Walleij #include <linux/io.h> 22179c8fb3SLinus Walleij #include <linux/regmap.h> 23384d977dSLinus Walleij #include <linux/mfd/syscon.h> 2491b87a47SLinus Walleij 25ba3fae06SLinus Walleij #include "icst.h" 2691b87a47SLinus Walleij #include "clk-icst.h" 2791b87a47SLinus Walleij 28179c8fb3SLinus Walleij /* Magic unlocking token used on all Versatile boards */ 29179c8fb3SLinus Walleij #define VERSATILE_LOCK_VAL 0xA05F 30179c8fb3SLinus Walleij 315e23c593SLinus Walleij #define VERSATILE_AUX_OSC_BITS 0x7FFFF 325e23c593SLinus Walleij #define INTEGRATOR_AP_CM_BITS 0xFF 33fa62e10dSLinus Walleij #define INTEGRATOR_AP_SYS_BITS 0xFF 345e23c593SLinus Walleij #define INTEGRATOR_CP_CM_CORE_BITS 0x7FF 355e23c593SLinus Walleij #define INTEGRATOR_CP_CM_MEM_BITS 0x7FF000 365e23c593SLinus Walleij 37fa62e10dSLinus Walleij #define INTEGRATOR_AP_PCI_25_33_MHZ BIT(8) 38fa62e10dSLinus Walleij 395e23c593SLinus Walleij /** 405e23c593SLinus Walleij * enum icst_control_type - the type of ICST control register 415e23c593SLinus Walleij */ 425e23c593SLinus Walleij enum icst_control_type { 435e23c593SLinus Walleij ICST_VERSATILE, /* The standard type, all control bits available */ 445e23c593SLinus Walleij ICST_INTEGRATOR_AP_CM, /* Only 8 bits of VDW available */ 45fa62e10dSLinus Walleij ICST_INTEGRATOR_AP_SYS, /* Only 8 bits of VDW available */ 46fa62e10dSLinus Walleij ICST_INTEGRATOR_AP_PCI, /* Odd bit pattern storage */ 475e23c593SLinus Walleij ICST_INTEGRATOR_CP_CM_CORE, /* Only 8 bits of VDW and 3 bits of OD */ 485e23c593SLinus Walleij ICST_INTEGRATOR_CP_CM_MEM, /* Only 8 bits of VDW and 3 bits of OD */ 495e23c593SLinus Walleij }; 505e23c593SLinus Walleij 5191b87a47SLinus Walleij /** 5291b87a47SLinus Walleij * struct clk_icst - ICST VCO clock wrapper 5391b87a47SLinus Walleij * @hw: corresponding clock hardware entry 547a9ad671SLinus Walleij * @vcoreg: VCO register address 557a9ad671SLinus Walleij * @lockreg: VCO lock register address 5691b87a47SLinus Walleij * @params: parameters for this ICST instance 5791b87a47SLinus Walleij * @rate: current rate 585e23c593SLinus Walleij * @ctype: the type of control register for the ICST 5991b87a47SLinus Walleij */ 6091b87a47SLinus Walleij struct clk_icst { 6191b87a47SLinus Walleij struct clk_hw hw; 62179c8fb3SLinus Walleij struct regmap *map; 63179c8fb3SLinus Walleij u32 vcoreg_off; 64179c8fb3SLinus Walleij u32 lockreg_off; 65a183da63SLinus Walleij struct icst_params *params; 6691b87a47SLinus Walleij unsigned long rate; 675e23c593SLinus Walleij enum icst_control_type ctype; 6891b87a47SLinus Walleij }; 6991b87a47SLinus Walleij 7091b87a47SLinus Walleij #define to_icst(_hw) container_of(_hw, struct clk_icst, hw) 7191b87a47SLinus Walleij 727a9ad671SLinus Walleij /** 73179c8fb3SLinus Walleij * vco_get() - get ICST VCO settings from a certain ICST 74179c8fb3SLinus Walleij * @icst: the ICST clock to get 75179c8fb3SLinus Walleij * @vco: the VCO struct to return the value in 767a9ad671SLinus Walleij */ 77179c8fb3SLinus Walleij static int vco_get(struct clk_icst *icst, struct icst_vco *vco) 787a9ad671SLinus Walleij { 797a9ad671SLinus Walleij u32 val; 80179c8fb3SLinus Walleij int ret; 817a9ad671SLinus Walleij 82179c8fb3SLinus Walleij ret = regmap_read(icst->map, icst->vcoreg_off, &val); 83179c8fb3SLinus Walleij if (ret) 84179c8fb3SLinus Walleij return ret; 855e23c593SLinus Walleij 865e23c593SLinus Walleij /* 875e23c593SLinus Walleij * The Integrator/AP core clock can only access the low eight 885e23c593SLinus Walleij * bits of the v PLL divider. Bit 8 is tied low and always zero, 895e23c593SLinus Walleij * r is hardwired to 22 and output divider s is hardwired to 1 905e23c593SLinus Walleij * (divide by 2) according to the document 915e23c593SLinus Walleij * "Integrator CM926EJ-S, CM946E-S, CM966E-S, CM1026EJ-S and 925e23c593SLinus Walleij * CM1136JF-S User Guide" ARM DUI 0138E, page 3-13 thru 3-14. 935e23c593SLinus Walleij */ 945e23c593SLinus Walleij if (icst->ctype == ICST_INTEGRATOR_AP_CM) { 955e23c593SLinus Walleij vco->v = val & INTEGRATOR_AP_CM_BITS; 965e23c593SLinus Walleij vco->r = 22; 975e23c593SLinus Walleij vco->s = 1; 985e23c593SLinus Walleij return 0; 995e23c593SLinus Walleij } 1005e23c593SLinus Walleij 1015e23c593SLinus Walleij /* 102fa62e10dSLinus Walleij * The Integrator/AP system clock on the base board can only 103fa62e10dSLinus Walleij * access the low eight bits of the v PLL divider. Bit 8 is tied low 104fa62e10dSLinus Walleij * and always zero, r is hardwired to 46, and the output divider is 105fa62e10dSLinus Walleij * hardwired to 3 (divide by 4) according to the document 106fa62e10dSLinus Walleij * "Integrator AP ASIC Development Motherboard" ARM DUI 0098B, 107fa62e10dSLinus Walleij * page 3-16. 108fa62e10dSLinus Walleij */ 109fa62e10dSLinus Walleij if (icst->ctype == ICST_INTEGRATOR_AP_SYS) { 110fa62e10dSLinus Walleij vco->v = val & INTEGRATOR_AP_SYS_BITS; 111fa62e10dSLinus Walleij vco->r = 46; 112fa62e10dSLinus Walleij vco->s = 3; 113fa62e10dSLinus Walleij return 0; 114fa62e10dSLinus Walleij } 115fa62e10dSLinus Walleij 116fa62e10dSLinus Walleij /* 117fa62e10dSLinus Walleij * The Integrator/AP PCI clock is using an odd pattern to create 118fa62e10dSLinus Walleij * the child clock, basically a single bit called DIVX/Y is used 119fa62e10dSLinus Walleij * to select between two different hardwired values: setting the 120fa62e10dSLinus Walleij * bit to 0 yields v = 17, r = 22 and OD = 1, whereas setting the 121fa62e10dSLinus Walleij * bit to 1 yields v = 14, r = 14 and OD = 1 giving the frequencies 122fa62e10dSLinus Walleij * 33 or 25 MHz respectively. 123fa62e10dSLinus Walleij */ 124fa62e10dSLinus Walleij if (icst->ctype == ICST_INTEGRATOR_AP_PCI) { 125fa62e10dSLinus Walleij bool divxy = !!(val & INTEGRATOR_AP_PCI_25_33_MHZ); 126fa62e10dSLinus Walleij 127fa62e10dSLinus Walleij vco->v = divxy ? 17 : 14; 128fa62e10dSLinus Walleij vco->r = divxy ? 22 : 14; 129fa62e10dSLinus Walleij vco->s = 1; 130fa62e10dSLinus Walleij return 0; 131fa62e10dSLinus Walleij } 132fa62e10dSLinus Walleij 133fa62e10dSLinus Walleij /* 1345e23c593SLinus Walleij * The Integrator/CP core clock can access the low eight bits 1355e23c593SLinus Walleij * of the v PLL divider. Bit 8 is tied low and always zero, 1365e23c593SLinus Walleij * r is hardwired to 22 and the output divider s is accessible 1375e23c593SLinus Walleij * in bits 8 thru 10 according to the document 1385e23c593SLinus Walleij * "Integrator/CM940T, CM920T, CM740T, and CM720T User Guide" 1395e23c593SLinus Walleij * ARM DUI 0157A, page 3-20 thru 3-23 and 4-10. 1405e23c593SLinus Walleij */ 1415e23c593SLinus Walleij if (icst->ctype == ICST_INTEGRATOR_CP_CM_CORE) { 1425e23c593SLinus Walleij vco->v = val & 0xFF; 1435e23c593SLinus Walleij vco->r = 22; 1445e23c593SLinus Walleij vco->s = (val >> 8) & 7; 1455e23c593SLinus Walleij return 0; 1465e23c593SLinus Walleij } 1475e23c593SLinus Walleij 1485e23c593SLinus Walleij if (icst->ctype == ICST_INTEGRATOR_CP_CM_MEM) { 1495e23c593SLinus Walleij vco->v = (val >> 12) & 0xFF; 1505e23c593SLinus Walleij vco->r = 22; 1515e23c593SLinus Walleij vco->s = (val >> 20) & 7; 1525e23c593SLinus Walleij return 0; 1535e23c593SLinus Walleij } 1545e23c593SLinus Walleij 155179c8fb3SLinus Walleij vco->v = val & 0x1ff; 156179c8fb3SLinus Walleij vco->r = (val >> 9) & 0x7f; 157179c8fb3SLinus Walleij vco->s = (val >> 16) & 03; 158179c8fb3SLinus Walleij return 0; 1597a9ad671SLinus Walleij } 1607a9ad671SLinus Walleij 1617a9ad671SLinus Walleij /** 1627a9ad671SLinus Walleij * vco_set() - commit changes to an ICST VCO 163179c8fb3SLinus Walleij * @icst: the ICST clock to set 164179c8fb3SLinus Walleij * @vco: the VCO struct to set the changes from 1657a9ad671SLinus Walleij */ 166179c8fb3SLinus Walleij static int vco_set(struct clk_icst *icst, struct icst_vco vco) 1677a9ad671SLinus Walleij { 1685e23c593SLinus Walleij u32 mask; 1697a9ad671SLinus Walleij u32 val; 170179c8fb3SLinus Walleij int ret; 1717a9ad671SLinus Walleij 1725e23c593SLinus Walleij /* Mask the bits used by the VCO */ 1735e23c593SLinus Walleij switch (icst->ctype) { 1745e23c593SLinus Walleij case ICST_INTEGRATOR_AP_CM: 1755e23c593SLinus Walleij mask = INTEGRATOR_AP_CM_BITS; 1765e23c593SLinus Walleij val = vco.v & 0xFF; 1775e23c593SLinus Walleij if (vco.v & 0x100) 1785e23c593SLinus Walleij pr_err("ICST error: tried to set bit 8 of VDW\n"); 1795e23c593SLinus Walleij if (vco.s != 1) 1805e23c593SLinus Walleij pr_err("ICST error: tried to use VOD != 1\n"); 1815e23c593SLinus Walleij if (vco.r != 22) 1825e23c593SLinus Walleij pr_err("ICST error: tried to use RDW != 22\n"); 1835e23c593SLinus Walleij break; 184fa62e10dSLinus Walleij case ICST_INTEGRATOR_AP_SYS: 185fa62e10dSLinus Walleij mask = INTEGRATOR_AP_SYS_BITS; 186fa62e10dSLinus Walleij val = vco.v & 0xFF; 187fa62e10dSLinus Walleij if (vco.v & 0x100) 188fa62e10dSLinus Walleij pr_err("ICST error: tried to set bit 8 of VDW\n"); 189fa62e10dSLinus Walleij if (vco.s != 3) 190fa62e10dSLinus Walleij pr_err("ICST error: tried to use VOD != 1\n"); 191fa62e10dSLinus Walleij if (vco.r != 46) 192fa62e10dSLinus Walleij pr_err("ICST error: tried to use RDW != 22\n"); 193fa62e10dSLinus Walleij break; 1945e23c593SLinus Walleij case ICST_INTEGRATOR_CP_CM_CORE: 1955e23c593SLinus Walleij mask = INTEGRATOR_CP_CM_CORE_BITS; /* Uses 12 bits */ 1965e23c593SLinus Walleij val = (vco.v & 0xFF) | vco.s << 8; 1975e23c593SLinus Walleij if (vco.v & 0x100) 1985e23c593SLinus Walleij pr_err("ICST error: tried to set bit 8 of VDW\n"); 1995e23c593SLinus Walleij if (vco.r != 22) 2005e23c593SLinus Walleij pr_err("ICST error: tried to use RDW != 22\n"); 2015e23c593SLinus Walleij break; 2025e23c593SLinus Walleij case ICST_INTEGRATOR_CP_CM_MEM: 2035e23c593SLinus Walleij mask = INTEGRATOR_CP_CM_MEM_BITS; /* Uses 12 bits */ 2045e23c593SLinus Walleij val = ((vco.v & 0xFF) << 12) | (vco.s << 20); 2055e23c593SLinus Walleij if (vco.v & 0x100) 2065e23c593SLinus Walleij pr_err("ICST error: tried to set bit 8 of VDW\n"); 2075e23c593SLinus Walleij if (vco.r != 22) 2085e23c593SLinus Walleij pr_err("ICST error: tried to use RDW != 22\n"); 2095e23c593SLinus Walleij break; 2105e23c593SLinus Walleij default: 2115e23c593SLinus Walleij /* Regular auxilary oscillator */ 2125e23c593SLinus Walleij mask = VERSATILE_AUX_OSC_BITS; 2135e23c593SLinus Walleij val = vco.v | (vco.r << 9) | (vco.s << 16); 2145e23c593SLinus Walleij break; 2155e23c593SLinus Walleij } 216df9cd564SLinus Walleij 2175e23c593SLinus Walleij pr_debug("ICST: new val = 0x%08x\n", val); 2187a9ad671SLinus Walleij 2197a9ad671SLinus Walleij /* This magic unlocks the VCO so it can be controlled */ 220179c8fb3SLinus Walleij ret = regmap_write(icst->map, icst->lockreg_off, VERSATILE_LOCK_VAL); 221179c8fb3SLinus Walleij if (ret) 222179c8fb3SLinus Walleij return ret; 2235e23c593SLinus Walleij ret = regmap_update_bits(icst->map, icst->vcoreg_off, mask, val); 224179c8fb3SLinus Walleij if (ret) 225179c8fb3SLinus Walleij return ret; 2267a9ad671SLinus Walleij /* This locks the VCO again */ 227179c8fb3SLinus Walleij ret = regmap_write(icst->map, icst->lockreg_off, 0); 228179c8fb3SLinus Walleij if (ret) 229179c8fb3SLinus Walleij return ret; 230179c8fb3SLinus Walleij return 0; 2317a9ad671SLinus Walleij } 2327a9ad671SLinus Walleij 23391b87a47SLinus Walleij static unsigned long icst_recalc_rate(struct clk_hw *hw, 23491b87a47SLinus Walleij unsigned long parent_rate) 23591b87a47SLinus Walleij { 23691b87a47SLinus Walleij struct clk_icst *icst = to_icst(hw); 23791b87a47SLinus Walleij struct icst_vco vco; 238179c8fb3SLinus Walleij int ret; 23991b87a47SLinus Walleij 240a183da63SLinus Walleij if (parent_rate) 241a183da63SLinus Walleij icst->params->ref = parent_rate; 242179c8fb3SLinus Walleij ret = vco_get(icst, &vco); 243179c8fb3SLinus Walleij if (ret) { 244179c8fb3SLinus Walleij pr_err("ICST: could not get VCO setting\n"); 245179c8fb3SLinus Walleij return 0; 246179c8fb3SLinus Walleij } 24791b87a47SLinus Walleij icst->rate = icst_hz(icst->params, vco); 24891b87a47SLinus Walleij return icst->rate; 24991b87a47SLinus Walleij } 25091b87a47SLinus Walleij 25191b87a47SLinus Walleij static long icst_round_rate(struct clk_hw *hw, unsigned long rate, 25291b87a47SLinus Walleij unsigned long *prate) 25391b87a47SLinus Walleij { 25491b87a47SLinus Walleij struct clk_icst *icst = to_icst(hw); 25591b87a47SLinus Walleij struct icst_vco vco; 25691b87a47SLinus Walleij 2575e23c593SLinus Walleij if (icst->ctype == ICST_INTEGRATOR_AP_CM || 2585e23c593SLinus Walleij icst->ctype == ICST_INTEGRATOR_CP_CM_CORE) { 2595e23c593SLinus Walleij if (rate <= 12000000) 2605e23c593SLinus Walleij return 12000000; 2615e23c593SLinus Walleij if (rate >= 160000000) 2625e23c593SLinus Walleij return 160000000; 2635e23c593SLinus Walleij /* Slam to closest megahertz */ 2645e23c593SLinus Walleij return DIV_ROUND_CLOSEST(rate, 1000000) * 1000000; 2655e23c593SLinus Walleij } 2665e23c593SLinus Walleij 2675e23c593SLinus Walleij if (icst->ctype == ICST_INTEGRATOR_CP_CM_MEM) { 2685e23c593SLinus Walleij if (rate <= 6000000) 2695e23c593SLinus Walleij return 6000000; 2705e23c593SLinus Walleij if (rate >= 66000000) 2715e23c593SLinus Walleij return 66000000; 2725e23c593SLinus Walleij /* Slam to closest 0.5 megahertz */ 2735e23c593SLinus Walleij return DIV_ROUND_CLOSEST(rate, 500000) * 500000; 2745e23c593SLinus Walleij } 2755e23c593SLinus Walleij 276fa62e10dSLinus Walleij if (icst->ctype == ICST_INTEGRATOR_AP_SYS) { 277fa62e10dSLinus Walleij /* Divides between 3 and 50 MHz in steps of 0.25 MHz */ 278fa62e10dSLinus Walleij if (rate <= 3000000) 279fa62e10dSLinus Walleij return 3000000; 280fa62e10dSLinus Walleij if (rate >= 50000000) 281fa62e10dSLinus Walleij return 5000000; 282fa62e10dSLinus Walleij /* Slam to closest 0.25 MHz */ 283fa62e10dSLinus Walleij return DIV_ROUND_CLOSEST(rate, 250000) * 250000; 284fa62e10dSLinus Walleij } 285fa62e10dSLinus Walleij 286fa62e10dSLinus Walleij if (icst->ctype == ICST_INTEGRATOR_AP_PCI) { 287fa62e10dSLinus Walleij /* 288fa62e10dSLinus Walleij * If we're below or less than halfway from 25 to 33 MHz 289fa62e10dSLinus Walleij * select 25 MHz 290fa62e10dSLinus Walleij */ 291fa62e10dSLinus Walleij if (rate <= 25000000 || rate < 29000000) 292fa62e10dSLinus Walleij return 25000000; 293fa62e10dSLinus Walleij /* Else just return the default frequency */ 294fa62e10dSLinus Walleij return 33000000; 295fa62e10dSLinus Walleij } 296fa62e10dSLinus Walleij 29791b87a47SLinus Walleij vco = icst_hz_to_vco(icst->params, rate); 29891b87a47SLinus Walleij return icst_hz(icst->params, vco); 29991b87a47SLinus Walleij } 30091b87a47SLinus Walleij 30191b87a47SLinus Walleij static int icst_set_rate(struct clk_hw *hw, unsigned long rate, 30291b87a47SLinus Walleij unsigned long parent_rate) 30391b87a47SLinus Walleij { 30491b87a47SLinus Walleij struct clk_icst *icst = to_icst(hw); 30591b87a47SLinus Walleij struct icst_vco vco; 30691b87a47SLinus Walleij 307fa62e10dSLinus Walleij if (icst->ctype == ICST_INTEGRATOR_AP_PCI) { 308fa62e10dSLinus Walleij /* This clock is especially primitive */ 309fa62e10dSLinus Walleij unsigned int val; 310fa62e10dSLinus Walleij int ret; 311fa62e10dSLinus Walleij 312fa62e10dSLinus Walleij if (rate == 25000000) { 313fa62e10dSLinus Walleij val = 0; 314fa62e10dSLinus Walleij } else if (rate == 33000000) { 315fa62e10dSLinus Walleij val = INTEGRATOR_AP_PCI_25_33_MHZ; 316fa62e10dSLinus Walleij } else { 317fa62e10dSLinus Walleij pr_err("ICST: cannot set PCI frequency %lu\n", 318fa62e10dSLinus Walleij rate); 319fa62e10dSLinus Walleij return -EINVAL; 320fa62e10dSLinus Walleij } 321fa62e10dSLinus Walleij ret = regmap_write(icst->map, icst->lockreg_off, 322fa62e10dSLinus Walleij VERSATILE_LOCK_VAL); 323fa62e10dSLinus Walleij if (ret) 324fa62e10dSLinus Walleij return ret; 325fa62e10dSLinus Walleij ret = regmap_update_bits(icst->map, icst->vcoreg_off, 326fa62e10dSLinus Walleij INTEGRATOR_AP_PCI_25_33_MHZ, 327fa62e10dSLinus Walleij val); 328fa62e10dSLinus Walleij if (ret) 329fa62e10dSLinus Walleij return ret; 330fa62e10dSLinus Walleij /* This locks the VCO again */ 331fa62e10dSLinus Walleij ret = regmap_write(icst->map, icst->lockreg_off, 0); 332fa62e10dSLinus Walleij if (ret) 333fa62e10dSLinus Walleij return ret; 334fa62e10dSLinus Walleij return 0; 335fa62e10dSLinus Walleij } 336fa62e10dSLinus Walleij 337a183da63SLinus Walleij if (parent_rate) 338a183da63SLinus Walleij icst->params->ref = parent_rate; 33991b87a47SLinus Walleij vco = icst_hz_to_vco(icst->params, rate); 34091b87a47SLinus Walleij icst->rate = icst_hz(icst->params, vco); 341179c8fb3SLinus Walleij return vco_set(icst, vco); 34291b87a47SLinus Walleij } 34391b87a47SLinus Walleij 34491b87a47SLinus Walleij static const struct clk_ops icst_ops = { 34591b87a47SLinus Walleij .recalc_rate = icst_recalc_rate, 34691b87a47SLinus Walleij .round_rate = icst_round_rate, 34791b87a47SLinus Walleij .set_rate = icst_set_rate, 34891b87a47SLinus Walleij }; 34991b87a47SLinus Walleij 350384d977dSLinus Walleij static struct clk *icst_clk_setup(struct device *dev, 3517a9ad671SLinus Walleij const struct clk_icst_desc *desc, 352ae6e694eSLinus Walleij const char *name, 353bf6edb4bSLinus Walleij const char *parent_name, 3545e23c593SLinus Walleij struct regmap *map, 3555e23c593SLinus Walleij enum icst_control_type ctype) 35691b87a47SLinus Walleij { 35791b87a47SLinus Walleij struct clk *clk; 35891b87a47SLinus Walleij struct clk_icst *icst; 35991b87a47SLinus Walleij struct clk_init_data init; 360a183da63SLinus Walleij struct icst_params *pclone; 36191b87a47SLinus Walleij 36291b87a47SLinus Walleij icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL); 363*e343b81eSMarkus Elfring if (!icst) 36491b87a47SLinus Walleij return ERR_PTR(-ENOMEM); 365a183da63SLinus Walleij 366a183da63SLinus Walleij pclone = kmemdup(desc->params, sizeof(*pclone), GFP_KERNEL); 367a183da63SLinus Walleij if (!pclone) { 368ab7ad353SColin Ian King kfree(icst); 369a183da63SLinus Walleij return ERR_PTR(-ENOMEM); 370a183da63SLinus Walleij } 371a183da63SLinus Walleij 372ae6e694eSLinus Walleij init.name = name; 37391b87a47SLinus Walleij init.ops = &icst_ops; 374ac82a8b5SStephen Boyd init.flags = 0; 375a183da63SLinus Walleij init.parent_names = (parent_name ? &parent_name : NULL); 376a183da63SLinus Walleij init.num_parents = (parent_name ? 1 : 0); 377384d977dSLinus Walleij icst->map = map; 37891b87a47SLinus Walleij icst->hw.init = &init; 379a183da63SLinus Walleij icst->params = pclone; 380179c8fb3SLinus Walleij icst->vcoreg_off = desc->vco_offset; 381179c8fb3SLinus Walleij icst->lockreg_off = desc->lock_offset; 3825e23c593SLinus Walleij icst->ctype = ctype; 38391b87a47SLinus Walleij 38491b87a47SLinus Walleij clk = clk_register(dev, &icst->hw); 3857bdccef3SLinus Walleij if (IS_ERR(clk)) { 3867bdccef3SLinus Walleij kfree(pclone); 38791b87a47SLinus Walleij kfree(icst); 3887bdccef3SLinus Walleij } 38991b87a47SLinus Walleij 39091b87a47SLinus Walleij return clk; 39191b87a47SLinus Walleij } 392384d977dSLinus Walleij 393384d977dSLinus Walleij struct clk *icst_clk_register(struct device *dev, 394384d977dSLinus Walleij const struct clk_icst_desc *desc, 395384d977dSLinus Walleij const char *name, 396384d977dSLinus Walleij const char *parent_name, 397384d977dSLinus Walleij void __iomem *base) 398384d977dSLinus Walleij { 399384d977dSLinus Walleij struct regmap_config icst_regmap_conf = { 400384d977dSLinus Walleij .reg_bits = 32, 401384d977dSLinus Walleij .val_bits = 32, 402384d977dSLinus Walleij .reg_stride = 4, 403384d977dSLinus Walleij }; 404384d977dSLinus Walleij struct regmap *map; 405384d977dSLinus Walleij 406384d977dSLinus Walleij map = regmap_init_mmio(dev, base, &icst_regmap_conf); 407384d977dSLinus Walleij if (IS_ERR(map)) { 408384d977dSLinus Walleij pr_err("could not initialize ICST regmap\n"); 409384d977dSLinus Walleij return ERR_CAST(map); 410384d977dSLinus Walleij } 4115e23c593SLinus Walleij return icst_clk_setup(dev, desc, name, parent_name, map, 4125e23c593SLinus Walleij ICST_VERSATILE); 413384d977dSLinus Walleij } 414a218d7faSArnd Bergmann EXPORT_SYMBOL_GPL(icst_clk_register); 415d430819dSLinus Walleij 416d430819dSLinus Walleij #ifdef CONFIG_OF 417d430819dSLinus Walleij /* 418d430819dSLinus Walleij * In a device tree, an memory-mapped ICST clock appear as a child 419d430819dSLinus Walleij * of a syscon node. Assume this and probe it only as a child of a 420d430819dSLinus Walleij * syscon. 421d430819dSLinus Walleij */ 422d430819dSLinus Walleij 423d430819dSLinus Walleij static const struct icst_params icst525_params = { 424d430819dSLinus Walleij .vco_max = ICST525_VCO_MAX_5V, 425d430819dSLinus Walleij .vco_min = ICST525_VCO_MIN, 426d430819dSLinus Walleij .vd_min = 8, 427d430819dSLinus Walleij .vd_max = 263, 428d430819dSLinus Walleij .rd_min = 3, 429d430819dSLinus Walleij .rd_max = 65, 430d430819dSLinus Walleij .s2div = icst525_s2div, 431d430819dSLinus Walleij .idx2s = icst525_idx2s, 432d430819dSLinus Walleij }; 433d430819dSLinus Walleij 434d430819dSLinus Walleij static const struct icst_params icst307_params = { 435d430819dSLinus Walleij .vco_max = ICST307_VCO_MAX, 436d430819dSLinus Walleij .vco_min = ICST307_VCO_MIN, 437d430819dSLinus Walleij .vd_min = 4 + 8, 438d430819dSLinus Walleij .vd_max = 511 + 8, 439d430819dSLinus Walleij .rd_min = 1 + 2, 440d430819dSLinus Walleij .rd_max = 127 + 2, 441d430819dSLinus Walleij .s2div = icst307_s2div, 442d430819dSLinus Walleij .idx2s = icst307_idx2s, 443d430819dSLinus Walleij }; 444d430819dSLinus Walleij 4455e23c593SLinus Walleij /** 4465e23c593SLinus Walleij * The core modules on the Integrator/AP and Integrator/CP have 4475e23c593SLinus Walleij * especially crippled ICST525 control. 4485e23c593SLinus Walleij */ 4495e23c593SLinus Walleij static const struct icst_params icst525_apcp_cm_params = { 4505e23c593SLinus Walleij .vco_max = ICST525_VCO_MAX_5V, 4515e23c593SLinus Walleij .vco_min = ICST525_VCO_MIN, 4525e23c593SLinus Walleij /* Minimum 12 MHz, VDW = 4 */ 4535e23c593SLinus Walleij .vd_min = 12, 4545e23c593SLinus Walleij /* 4555e23c593SLinus Walleij * Maximum 160 MHz, VDW = 152 for all core modules, but 4565e23c593SLinus Walleij * CM926EJ-S, CM1026EJ-S and CM1136JF-S can actually 4575e23c593SLinus Walleij * go to 200 MHz (max VDW = 192). 4585e23c593SLinus Walleij */ 4595e23c593SLinus Walleij .vd_max = 192, 4605e23c593SLinus Walleij /* r is hardcoded to 22 and this is the actual divisor, +2 */ 4615e23c593SLinus Walleij .rd_min = 24, 4625e23c593SLinus Walleij .rd_max = 24, 4635e23c593SLinus Walleij .s2div = icst525_s2div, 4645e23c593SLinus Walleij .idx2s = icst525_idx2s, 4655e23c593SLinus Walleij }; 4665e23c593SLinus Walleij 467fa62e10dSLinus Walleij static const struct icst_params icst525_ap_sys_params = { 468fa62e10dSLinus Walleij .vco_max = ICST525_VCO_MAX_5V, 469fa62e10dSLinus Walleij .vco_min = ICST525_VCO_MIN, 470fa62e10dSLinus Walleij /* Minimum 3 MHz, VDW = 4 */ 471fa62e10dSLinus Walleij .vd_min = 3, 472fa62e10dSLinus Walleij /* Maximum 50 MHz, VDW = 192 */ 473fa62e10dSLinus Walleij .vd_max = 50, 474fa62e10dSLinus Walleij /* r is hardcoded to 46 and this is the actual divisor, +2 */ 475fa62e10dSLinus Walleij .rd_min = 48, 476fa62e10dSLinus Walleij .rd_max = 48, 477fa62e10dSLinus Walleij .s2div = icst525_s2div, 478fa62e10dSLinus Walleij .idx2s = icst525_idx2s, 479fa62e10dSLinus Walleij }; 480fa62e10dSLinus Walleij 481fa62e10dSLinus Walleij static const struct icst_params icst525_ap_pci_params = { 482fa62e10dSLinus Walleij .vco_max = ICST525_VCO_MAX_5V, 483fa62e10dSLinus Walleij .vco_min = ICST525_VCO_MIN, 484fa62e10dSLinus Walleij /* Minimum 25 MHz */ 485fa62e10dSLinus Walleij .vd_min = 25, 486fa62e10dSLinus Walleij /* Maximum 33 MHz */ 487fa62e10dSLinus Walleij .vd_max = 33, 488fa62e10dSLinus Walleij /* r is hardcoded to 14 or 22 and this is the actual divisors +2 */ 489fa62e10dSLinus Walleij .rd_min = 16, 490fa62e10dSLinus Walleij .rd_max = 24, 491fa62e10dSLinus Walleij .s2div = icst525_s2div, 492fa62e10dSLinus Walleij .idx2s = icst525_idx2s, 493fa62e10dSLinus Walleij }; 494fa62e10dSLinus Walleij 495d430819dSLinus Walleij static void __init of_syscon_icst_setup(struct device_node *np) 496d430819dSLinus Walleij { 497d430819dSLinus Walleij struct device_node *parent; 498d430819dSLinus Walleij struct regmap *map; 499d430819dSLinus Walleij struct clk_icst_desc icst_desc; 500d430819dSLinus Walleij const char *name = np->name; 501d430819dSLinus Walleij const char *parent_name; 502d430819dSLinus Walleij struct clk *regclk; 5035e23c593SLinus Walleij enum icst_control_type ctype; 504d430819dSLinus Walleij 505d430819dSLinus Walleij /* We do not release this reference, we are using it perpetually */ 506d430819dSLinus Walleij parent = of_get_parent(np); 507d430819dSLinus Walleij if (!parent) { 508d430819dSLinus Walleij pr_err("no parent node for syscon ICST clock\n"); 509d430819dSLinus Walleij return; 510d430819dSLinus Walleij } 511d430819dSLinus Walleij map = syscon_node_to_regmap(parent); 512d430819dSLinus Walleij if (IS_ERR(map)) { 513d430819dSLinus Walleij pr_err("no regmap for syscon ICST clock parent\n"); 514d430819dSLinus Walleij return; 515d430819dSLinus Walleij } 516d430819dSLinus Walleij 517d430819dSLinus Walleij if (of_property_read_u32(np, "vco-offset", &icst_desc.vco_offset)) { 518d430819dSLinus Walleij pr_err("no VCO register offset for ICST clock\n"); 519d430819dSLinus Walleij return; 520d430819dSLinus Walleij } 521d430819dSLinus Walleij if (of_property_read_u32(np, "lock-offset", &icst_desc.lock_offset)) { 522d430819dSLinus Walleij pr_err("no lock register offset for ICST clock\n"); 523d430819dSLinus Walleij return; 524d430819dSLinus Walleij } 525d430819dSLinus Walleij 5265e23c593SLinus Walleij if (of_device_is_compatible(np, "arm,syscon-icst525")) { 527d430819dSLinus Walleij icst_desc.params = &icst525_params; 5285e23c593SLinus Walleij ctype = ICST_VERSATILE; 5295e23c593SLinus Walleij } else if (of_device_is_compatible(np, "arm,syscon-icst307")) { 530d430819dSLinus Walleij icst_desc.params = &icst307_params; 5315e23c593SLinus Walleij ctype = ICST_VERSATILE; 5325e23c593SLinus Walleij } else if (of_device_is_compatible(np, "arm,syscon-icst525-integratorap-cm")) { 5335e23c593SLinus Walleij icst_desc.params = &icst525_apcp_cm_params; 5345e23c593SLinus Walleij ctype = ICST_INTEGRATOR_AP_CM; 535fa62e10dSLinus Walleij } else if (of_device_is_compatible(np, "arm,syscon-icst525-integratorap-sys")) { 536fa62e10dSLinus Walleij icst_desc.params = &icst525_ap_sys_params; 537fa62e10dSLinus Walleij ctype = ICST_INTEGRATOR_AP_SYS; 538fa62e10dSLinus Walleij } else if (of_device_is_compatible(np, "arm,syscon-icst525-integratorap-pci")) { 539fa62e10dSLinus Walleij icst_desc.params = &icst525_ap_pci_params; 540fa62e10dSLinus Walleij ctype = ICST_INTEGRATOR_AP_PCI; 5415e23c593SLinus Walleij } else if (of_device_is_compatible(np, "arm,syscon-icst525-integratorcp-cm-core")) { 5425e23c593SLinus Walleij icst_desc.params = &icst525_apcp_cm_params; 5435e23c593SLinus Walleij ctype = ICST_INTEGRATOR_CP_CM_CORE; 5445e23c593SLinus Walleij } else if (of_device_is_compatible(np, "arm,syscon-icst525-integratorcp-cm-mem")) { 5455e23c593SLinus Walleij icst_desc.params = &icst525_apcp_cm_params; 5465e23c593SLinus Walleij ctype = ICST_INTEGRATOR_CP_CM_MEM; 5475e23c593SLinus Walleij } else { 548d430819dSLinus Walleij pr_err("unknown ICST clock %s\n", name); 549d430819dSLinus Walleij return; 550d430819dSLinus Walleij } 551d430819dSLinus Walleij 552d430819dSLinus Walleij /* Parent clock name is not the same as node parent */ 553d430819dSLinus Walleij parent_name = of_clk_get_parent_name(np, 0); 554d430819dSLinus Walleij 5555e23c593SLinus Walleij regclk = icst_clk_setup(NULL, &icst_desc, name, parent_name, map, ctype); 556d430819dSLinus Walleij if (IS_ERR(regclk)) { 557d430819dSLinus Walleij pr_err("error setting up syscon ICST clock %s\n", name); 558d430819dSLinus Walleij return; 559d430819dSLinus Walleij } 560d430819dSLinus Walleij of_clk_add_provider(np, of_clk_src_simple_get, regclk); 561d430819dSLinus Walleij pr_debug("registered syscon ICST clock %s\n", name); 562d430819dSLinus Walleij } 563d430819dSLinus Walleij 564d430819dSLinus Walleij CLK_OF_DECLARE(arm_syscon_icst525_clk, 565d430819dSLinus Walleij "arm,syscon-icst525", of_syscon_icst_setup); 566d430819dSLinus Walleij CLK_OF_DECLARE(arm_syscon_icst307_clk, 567d430819dSLinus Walleij "arm,syscon-icst307", of_syscon_icst_setup); 5685e23c593SLinus Walleij CLK_OF_DECLARE(arm_syscon_integratorap_cm_clk, 5695e23c593SLinus Walleij "arm,syscon-icst525-integratorap-cm", of_syscon_icst_setup); 570fa62e10dSLinus Walleij CLK_OF_DECLARE(arm_syscon_integratorap_sys_clk, 571fa62e10dSLinus Walleij "arm,syscon-icst525-integratorap-sys", of_syscon_icst_setup); 572fa62e10dSLinus Walleij CLK_OF_DECLARE(arm_syscon_integratorap_pci_clk, 573fa62e10dSLinus Walleij "arm,syscon-icst525-integratorap-pci", of_syscon_icst_setup); 5745e23c593SLinus Walleij CLK_OF_DECLARE(arm_syscon_integratorcp_cm_core_clk, 5755e23c593SLinus Walleij "arm,syscon-icst525-integratorcp-cm-core", of_syscon_icst_setup); 5765e23c593SLinus Walleij CLK_OF_DECLARE(arm_syscon_integratorcp_cm_mem_clk, 5775e23c593SLinus Walleij "arm,syscon-icst525-integratorcp-cm-mem", of_syscon_icst_setup); 578d430819dSLinus Walleij #endif 579