^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for the ICST307 VCO clock found in the ARM Reference designs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * We wrap the custom interface from <asm/hardware/icst.h> into the generic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * clock framework.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2012-2015 Linus Walleij
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * TODO: when all ARM reference designs are migrated to generic clocks, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * ICST clock code from the ARM tree should probably be merged into this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "icst.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "clk-icst.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* Magic unlocking token used on all Versatile boards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define VERSATILE_LOCK_VAL 0xA05F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define VERSATILE_AUX_OSC_BITS 0x7FFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define INTEGRATOR_AP_CM_BITS 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define INTEGRATOR_AP_SYS_BITS 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define INTEGRATOR_CP_CM_CORE_BITS 0x7FF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define INTEGRATOR_CP_CM_MEM_BITS 0x7FF000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define INTEGRATOR_AP_PCI_25_33_MHZ BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * struct clk_icst - ICST VCO clock wrapper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * @hw: corresponding clock hardware entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * @vcoreg: VCO register address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * @lockreg: VCO lock register address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * @params: parameters for this ICST instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * @rate: current rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * @ctype: the type of control register for the ICST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct clk_icst {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct regmap *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) u32 vcoreg_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) u32 lockreg_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct icst_params *params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned long rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) enum icst_control_type ctype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define to_icst(_hw) container_of(_hw, struct clk_icst, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * vco_get() - get ICST VCO settings from a certain ICST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * @icst: the ICST clock to get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * @vco: the VCO struct to return the value in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static int vco_get(struct clk_icst *icst, struct icst_vco *vco)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ret = regmap_read(icst->map, icst->vcoreg_off, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * The Integrator/AP core clock can only access the low eight
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * bits of the v PLL divider. Bit 8 is tied low and always zero,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * r is hardwired to 22 and output divider s is hardwired to 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * (divide by 2) according to the document
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * "Integrator CM926EJ-S, CM946E-S, CM966E-S, CM1026EJ-S and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * CM1136JF-S User Guide" ARM DUI 0138E, page 3-13 thru 3-14.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (icst->ctype == ICST_INTEGRATOR_AP_CM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) vco->v = val & INTEGRATOR_AP_CM_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) vco->r = 22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) vco->s = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * The Integrator/AP system clock on the base board can only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * access the low eight bits of the v PLL divider. Bit 8 is tied low
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * and always zero, r is hardwired to 46, and the output divider is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * hardwired to 3 (divide by 4) according to the document
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * "Integrator AP ASIC Development Motherboard" ARM DUI 0098B,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * page 3-16.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (icst->ctype == ICST_INTEGRATOR_AP_SYS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) vco->v = val & INTEGRATOR_AP_SYS_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) vco->r = 46;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) vco->s = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * The Integrator/AP PCI clock is using an odd pattern to create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * the child clock, basically a single bit called DIVX/Y is used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * to select between two different hardwired values: setting the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * bit to 0 yields v = 17, r = 22 and OD = 1, whereas setting the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * bit to 1 yields v = 14, r = 14 and OD = 1 giving the frequencies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * 33 or 25 MHz respectively.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (icst->ctype == ICST_INTEGRATOR_AP_PCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) bool divxy = !!(val & INTEGRATOR_AP_PCI_25_33_MHZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) vco->v = divxy ? 17 : 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) vco->r = divxy ? 22 : 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) vco->s = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * The Integrator/CP core clock can access the low eight bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * of the v PLL divider. Bit 8 is tied low and always zero,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * r is hardwired to 22 and the output divider s is accessible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * in bits 8 thru 10 according to the document
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * "Integrator/CM940T, CM920T, CM740T, and CM720T User Guide"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * ARM DUI 0157A, page 3-20 thru 3-23 and 4-10.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (icst->ctype == ICST_INTEGRATOR_CP_CM_CORE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) vco->v = val & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) vco->r = 22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) vco->s = (val >> 8) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (icst->ctype == ICST_INTEGRATOR_CP_CM_MEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) vco->v = (val >> 12) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) vco->r = 22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) vco->s = (val >> 20) & 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) vco->v = val & 0x1ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) vco->r = (val >> 9) & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) vco->s = (val >> 16) & 03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * vco_set() - commit changes to an ICST VCO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * @icst: the ICST clock to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * @vco: the VCO struct to set the changes from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int vco_set(struct clk_icst *icst, struct icst_vco vco)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* Mask the bits used by the VCO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) switch (icst->ctype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) case ICST_INTEGRATOR_AP_CM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) mask = INTEGRATOR_AP_CM_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) val = vco.v & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (vco.v & 0x100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) pr_err("ICST error: tried to set bit 8 of VDW\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (vco.s != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) pr_err("ICST error: tried to use VOD != 1\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (vco.r != 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) pr_err("ICST error: tried to use RDW != 22\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) case ICST_INTEGRATOR_AP_SYS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) mask = INTEGRATOR_AP_SYS_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) val = vco.v & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (vco.v & 0x100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) pr_err("ICST error: tried to set bit 8 of VDW\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (vco.s != 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) pr_err("ICST error: tried to use VOD != 1\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (vco.r != 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) pr_err("ICST error: tried to use RDW != 22\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) case ICST_INTEGRATOR_CP_CM_CORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) mask = INTEGRATOR_CP_CM_CORE_BITS; /* Uses 12 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) val = (vco.v & 0xFF) | vco.s << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (vco.v & 0x100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) pr_err("ICST error: tried to set bit 8 of VDW\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (vco.r != 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) pr_err("ICST error: tried to use RDW != 22\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) case ICST_INTEGRATOR_CP_CM_MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) mask = INTEGRATOR_CP_CM_MEM_BITS; /* Uses 12 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) val = ((vco.v & 0xFF) << 12) | (vco.s << 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (vco.v & 0x100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) pr_err("ICST error: tried to set bit 8 of VDW\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (vco.r != 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) pr_err("ICST error: tried to use RDW != 22\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* Regular auxilary oscillator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) mask = VERSATILE_AUX_OSC_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) val = vco.v | (vco.r << 9) | (vco.s << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) pr_debug("ICST: new val = 0x%08x\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* This magic unlocks the VCO so it can be controlled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ret = regmap_write(icst->map, icst->lockreg_off, VERSATILE_LOCK_VAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) ret = regmap_update_bits(icst->map, icst->vcoreg_off, mask, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /* This locks the VCO again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ret = regmap_write(icst->map, icst->lockreg_off, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static unsigned long icst_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct clk_icst *icst = to_icst(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct icst_vco vco;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) icst->params->ref = parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) ret = vco_get(icst, &vco);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) pr_err("ICST: could not get VCO setting\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) icst->rate = icst_hz(icst->params, vco);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return icst->rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static long icst_round_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) unsigned long *prate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct clk_icst *icst = to_icst(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct icst_vco vco;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (icst->ctype == ICST_INTEGRATOR_AP_CM ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) icst->ctype == ICST_INTEGRATOR_CP_CM_CORE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (rate <= 12000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return 12000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (rate >= 160000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return 160000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /* Slam to closest megahertz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return DIV_ROUND_CLOSEST(rate, 1000000) * 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (icst->ctype == ICST_INTEGRATOR_CP_CM_MEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (rate <= 6000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return 6000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (rate >= 66000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return 66000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* Slam to closest 0.5 megahertz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return DIV_ROUND_CLOSEST(rate, 500000) * 500000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (icst->ctype == ICST_INTEGRATOR_AP_SYS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /* Divides between 3 and 50 MHz in steps of 0.25 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (rate <= 3000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return 3000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (rate >= 50000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return 5000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /* Slam to closest 0.25 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return DIV_ROUND_CLOSEST(rate, 250000) * 250000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (icst->ctype == ICST_INTEGRATOR_AP_PCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * If we're below or less than halfway from 25 to 33 MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * select 25 MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (rate <= 25000000 || rate < 29000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return 25000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* Else just return the default frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return 33000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) vco = icst_hz_to_vco(icst->params, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return icst_hz(icst->params, vco);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static int icst_set_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct clk_icst *icst = to_icst(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct icst_vco vco;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (icst->ctype == ICST_INTEGRATOR_AP_PCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* This clock is especially primitive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (rate == 25000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) } else if (rate == 33000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) val = INTEGRATOR_AP_PCI_25_33_MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) pr_err("ICST: cannot set PCI frequency %lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ret = regmap_write(icst->map, icst->lockreg_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) VERSATILE_LOCK_VAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ret = regmap_update_bits(icst->map, icst->vcoreg_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) INTEGRATOR_AP_PCI_25_33_MHZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* This locks the VCO again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ret = regmap_write(icst->map, icst->lockreg_off, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) icst->params->ref = parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) vco = icst_hz_to_vco(icst->params, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) icst->rate = icst_hz(icst->params, vco);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return vco_set(icst, vco);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static const struct clk_ops icst_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) .recalc_rate = icst_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) .round_rate = icst_round_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) .set_rate = icst_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct clk *icst_clk_setup(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) const struct clk_icst_desc *desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) const char *parent_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct regmap *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) enum icst_control_type ctype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct clk_icst *icst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct icst_params *pclone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) icst = kzalloc(sizeof(*icst), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (!icst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) pclone = kmemdup(desc->params, sizeof(*pclone), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (!pclone) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) kfree(icst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) init.ops = &icst_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) init.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) init.parent_names = (parent_name ? &parent_name : NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) init.num_parents = (parent_name ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) icst->map = map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) icst->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) icst->params = pclone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) icst->vcoreg_off = desc->vco_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) icst->lockreg_off = desc->lock_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) icst->ctype = ctype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) clk = clk_register(dev, &icst->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) kfree(pclone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) kfree(icst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) EXPORT_SYMBOL_GPL(icst_clk_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) struct clk *icst_clk_register(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) const struct clk_icst_desc *desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) const char *parent_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct regmap_config icst_regmap_conf = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) .reg_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) .val_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) .reg_stride = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct regmap *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) map = regmap_init_mmio(dev, base, &icst_regmap_conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (IS_ERR(map)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) pr_err("could not initialize ICST regmap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return ERR_CAST(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return icst_clk_setup(dev, desc, name, parent_name, map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ICST_VERSATILE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) EXPORT_SYMBOL_GPL(icst_clk_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * In a device tree, an memory-mapped ICST clock appear as a child
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * of a syscon node. Assume this and probe it only as a child of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * syscon.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static const struct icst_params icst525_params = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) .vco_max = ICST525_VCO_MAX_5V,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) .vco_min = ICST525_VCO_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .vd_min = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) .vd_max = 263,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) .rd_min = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) .rd_max = 65,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) .s2div = icst525_s2div,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) .idx2s = icst525_idx2s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static const struct icst_params icst307_params = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) .vco_max = ICST307_VCO_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) .vco_min = ICST307_VCO_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) .vd_min = 4 + 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) .vd_max = 511 + 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) .rd_min = 1 + 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) .rd_max = 127 + 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) .s2div = icst307_s2div,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) .idx2s = icst307_idx2s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * The core modules on the Integrator/AP and Integrator/CP have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * especially crippled ICST525 control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static const struct icst_params icst525_apcp_cm_params = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) .vco_max = ICST525_VCO_MAX_5V,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) .vco_min = ICST525_VCO_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* Minimum 12 MHz, VDW = 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) .vd_min = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * Maximum 160 MHz, VDW = 152 for all core modules, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * CM926EJ-S, CM1026EJ-S and CM1136JF-S can actually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * go to 200 MHz (max VDW = 192).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) .vd_max = 192,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /* r is hardcoded to 22 and this is the actual divisor, +2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) .rd_min = 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) .rd_max = 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) .s2div = icst525_s2div,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) .idx2s = icst525_idx2s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static const struct icst_params icst525_ap_sys_params = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) .vco_max = ICST525_VCO_MAX_5V,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) .vco_min = ICST525_VCO_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /* Minimum 3 MHz, VDW = 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) .vd_min = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) /* Maximum 50 MHz, VDW = 192 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) .vd_max = 50,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /* r is hardcoded to 46 and this is the actual divisor, +2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) .rd_min = 48,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) .rd_max = 48,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) .s2div = icst525_s2div,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) .idx2s = icst525_idx2s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) static const struct icst_params icst525_ap_pci_params = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) .vco_max = ICST525_VCO_MAX_5V,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) .vco_min = ICST525_VCO_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /* Minimum 25 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) .vd_min = 25,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /* Maximum 33 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) .vd_max = 33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* r is hardcoded to 14 or 22 and this is the actual divisors +2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) .rd_min = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) .rd_max = 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) .s2div = icst525_s2div,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) .idx2s = icst525_idx2s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static void __init of_syscon_icst_setup(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct device_node *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct regmap *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) struct clk_icst_desc icst_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) const char *name = np->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) const char *parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct clk *regclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) enum icst_control_type ctype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* We do not release this reference, we are using it perpetually */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) parent = of_get_parent(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (!parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) pr_err("no parent node for syscon ICST clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) map = syscon_node_to_regmap(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (IS_ERR(map)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) pr_err("no regmap for syscon ICST clock parent\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (of_property_read_u32(np, "vco-offset", &icst_desc.vco_offset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) pr_err("no VCO register offset for ICST clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (of_property_read_u32(np, "lock-offset", &icst_desc.lock_offset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) pr_err("no lock register offset for ICST clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (of_device_is_compatible(np, "arm,syscon-icst525")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) icst_desc.params = &icst525_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) ctype = ICST_VERSATILE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) } else if (of_device_is_compatible(np, "arm,syscon-icst307")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) icst_desc.params = &icst307_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) ctype = ICST_VERSATILE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) } else if (of_device_is_compatible(np, "arm,syscon-icst525-integratorap-cm")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) icst_desc.params = &icst525_apcp_cm_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) ctype = ICST_INTEGRATOR_AP_CM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) } else if (of_device_is_compatible(np, "arm,syscon-icst525-integratorap-sys")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) icst_desc.params = &icst525_ap_sys_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) ctype = ICST_INTEGRATOR_AP_SYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) } else if (of_device_is_compatible(np, "arm,syscon-icst525-integratorap-pci")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) icst_desc.params = &icst525_ap_pci_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) ctype = ICST_INTEGRATOR_AP_PCI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) } else if (of_device_is_compatible(np, "arm,syscon-icst525-integratorcp-cm-core")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) icst_desc.params = &icst525_apcp_cm_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) ctype = ICST_INTEGRATOR_CP_CM_CORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) } else if (of_device_is_compatible(np, "arm,syscon-icst525-integratorcp-cm-mem")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) icst_desc.params = &icst525_apcp_cm_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) ctype = ICST_INTEGRATOR_CP_CM_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) pr_err("unknown ICST clock %s\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /* Parent clock name is not the same as node parent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) parent_name = of_clk_get_parent_name(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) regclk = icst_clk_setup(NULL, &icst_desc, name, parent_name, map, ctype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (IS_ERR(regclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) pr_err("error setting up syscon ICST clock %s\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) of_clk_add_provider(np, of_clk_src_simple_get, regclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) pr_debug("registered syscon ICST clock %s\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) CLK_OF_DECLARE(arm_syscon_icst525_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) "arm,syscon-icst525", of_syscon_icst_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) CLK_OF_DECLARE(arm_syscon_icst307_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) "arm,syscon-icst307", of_syscon_icst_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) CLK_OF_DECLARE(arm_syscon_integratorap_cm_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) "arm,syscon-icst525-integratorap-cm", of_syscon_icst_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) CLK_OF_DECLARE(arm_syscon_integratorap_sys_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) "arm,syscon-icst525-integratorap-sys", of_syscon_icst_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) CLK_OF_DECLARE(arm_syscon_integratorap_pci_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) "arm,syscon-icst525-integratorap-pci", of_syscon_icst_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) CLK_OF_DECLARE(arm_syscon_integratorcp_cm_core_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) "arm,syscon-icst525-integratorcp-cm-core", of_syscon_icst_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) CLK_OF_DECLARE(arm_syscon_integratorcp_cm_mem_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) "arm,syscon-icst525-integratorcp-cm-mem", of_syscon_icst_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) #endif