121330497STony Lindgren /* 221330497STony Lindgren * This program is free software; you can redistribute it and/or 321330497STony Lindgren * modify it under the terms of the GNU General Public License as 421330497STony Lindgren * published by the Free Software Foundation version 2. 521330497STony Lindgren * 621330497STony Lindgren * This program is distributed "as is" WITHOUT ANY WARRANTY of any 721330497STony Lindgren * kind, whether express or implied; without even the implied warranty 821330497STony Lindgren * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 921330497STony Lindgren * GNU General Public License for more details. 1021330497STony Lindgren */ 1121330497STony Lindgren 1221330497STony Lindgren #include <linux/clk.h> 1321330497STony Lindgren #include <linux/clkdev.h> 1421330497STony Lindgren #include <linux/clk-provider.h> 1521330497STony Lindgren #include <linux/delay.h> 1621330497STony Lindgren #include <linux/err.h> 17*62e59c4eSStephen Boyd #include <linux/io.h> 1821330497STony Lindgren #include <linux/math64.h> 1921330497STony Lindgren #include <linux/module.h> 2021330497STony Lindgren #include <linux/of_device.h> 2121330497STony Lindgren #include <linux/string.h> 2221330497STony Lindgren 2321330497STony Lindgren #define ADPLL_PLLSS_MMR_LOCK_OFFSET 0x00 /* Managed by MPPULL */ 2421330497STony Lindgren #define ADPLL_PLLSS_MMR_LOCK_ENABLED 0x1f125B64 2521330497STony Lindgren #define ADPLL_PLLSS_MMR_UNLOCK_MAGIC 0x1eda4c3d 2621330497STony Lindgren 2721330497STony Lindgren #define ADPLL_PWRCTRL_OFFSET 0x00 2821330497STony Lindgren #define ADPLL_PWRCTRL_PONIN 5 2921330497STony Lindgren #define ADPLL_PWRCTRL_PGOODIN 4 3021330497STony Lindgren #define ADPLL_PWRCTRL_RET 3 3121330497STony Lindgren #define ADPLL_PWRCTRL_ISORET 2 3221330497STony Lindgren #define ADPLL_PWRCTRL_ISOSCAN 1 3321330497STony Lindgren #define ADPLL_PWRCTRL_OFFMODE 0 3421330497STony Lindgren 3521330497STony Lindgren #define ADPLL_CLKCTRL_OFFSET 0x04 3621330497STony Lindgren #define ADPLL_CLKCTRL_CLKDCOLDOEN 29 3721330497STony Lindgren #define ADPLL_CLKCTRL_IDLE 23 3821330497STony Lindgren #define ADPLL_CLKCTRL_CLKOUTEN 20 3921330497STony Lindgren #define ADPLL_CLKINPHIFSEL_ADPLL_S 19 /* REVISIT: which bit? */ 4021330497STony Lindgren #define ADPLL_CLKCTRL_CLKOUTLDOEN_ADPLL_LJ 19 4121330497STony Lindgren #define ADPLL_CLKCTRL_ULOWCLKEN 18 4221330497STony Lindgren #define ADPLL_CLKCTRL_CLKDCOLDOPWDNZ 17 4321330497STony Lindgren #define ADPLL_CLKCTRL_M2PWDNZ 16 4421330497STony Lindgren #define ADPLL_CLKCTRL_M3PWDNZ_ADPLL_S 15 4521330497STony Lindgren #define ADPLL_CLKCTRL_LOWCURRSTDBY_ADPLL_S 13 4621330497STony Lindgren #define ADPLL_CLKCTRL_LPMODE_ADPLL_S 12 4721330497STony Lindgren #define ADPLL_CLKCTRL_REGM4XEN_ADPLL_S 10 4821330497STony Lindgren #define ADPLL_CLKCTRL_SELFREQDCO_ADPLL_LJ 10 4921330497STony Lindgren #define ADPLL_CLKCTRL_TINITZ 0 5021330497STony Lindgren 5121330497STony Lindgren #define ADPLL_TENABLE_OFFSET 0x08 5221330497STony Lindgren #define ADPLL_TENABLEDIV_OFFSET 0x8c 5321330497STony Lindgren 5421330497STony Lindgren #define ADPLL_M2NDIV_OFFSET 0x10 5521330497STony Lindgren #define ADPLL_M2NDIV_M2 16 5621330497STony Lindgren #define ADPLL_M2NDIV_M2_ADPLL_S_WIDTH 5 5721330497STony Lindgren #define ADPLL_M2NDIV_M2_ADPLL_LJ_WIDTH 7 5821330497STony Lindgren 5921330497STony Lindgren #define ADPLL_MN2DIV_OFFSET 0x14 6021330497STony Lindgren #define ADPLL_MN2DIV_N2 16 6121330497STony Lindgren 6221330497STony Lindgren #define ADPLL_FRACDIV_OFFSET 0x18 6321330497STony Lindgren #define ADPLL_FRACDIV_REGSD 24 6421330497STony Lindgren #define ADPLL_FRACDIV_FRACTIONALM 0 6521330497STony Lindgren #define ADPLL_FRACDIV_FRACTIONALM_MASK 0x3ffff 6621330497STony Lindgren 6721330497STony Lindgren #define ADPLL_BWCTRL_OFFSET 0x1c 6821330497STony Lindgren #define ADPLL_BWCTRL_BWCONTROL 1 6921330497STony Lindgren #define ADPLL_BWCTRL_BW_INCR_DECRZ 0 7021330497STony Lindgren 7121330497STony Lindgren #define ADPLL_RESERVED_OFFSET 0x20 7221330497STony Lindgren 7321330497STony Lindgren #define ADPLL_STATUS_OFFSET 0x24 7421330497STony Lindgren #define ADPLL_STATUS_PONOUT 31 7521330497STony Lindgren #define ADPLL_STATUS_PGOODOUT 30 7621330497STony Lindgren #define ADPLL_STATUS_LDOPWDN 29 7721330497STony Lindgren #define ADPLL_STATUS_RECAL_BSTATUS3 28 7821330497STony Lindgren #define ADPLL_STATUS_RECAL_OPPIN 27 7921330497STony Lindgren #define ADPLL_STATUS_PHASELOCK 10 8021330497STony Lindgren #define ADPLL_STATUS_FREQLOCK 9 8121330497STony Lindgren #define ADPLL_STATUS_BYPASSACK 8 8221330497STony Lindgren #define ADPLL_STATUS_LOSSREF 6 8321330497STony Lindgren #define ADPLL_STATUS_CLKOUTENACK 5 8421330497STony Lindgren #define ADPLL_STATUS_LOCK2 4 8521330497STony Lindgren #define ADPLL_STATUS_M2CHANGEACK 3 8621330497STony Lindgren #define ADPLL_STATUS_HIGHJITTER 1 8721330497STony Lindgren #define ADPLL_STATUS_BYPASS 0 8821330497STony Lindgren #define ADPLL_STATUS_PREPARED_MASK (BIT(ADPLL_STATUS_PHASELOCK) | \ 8921330497STony Lindgren BIT(ADPLL_STATUS_FREQLOCK)) 9021330497STony Lindgren 9121330497STony Lindgren #define ADPLL_M3DIV_OFFSET 0x28 /* Only on MPUPLL */ 9221330497STony Lindgren #define ADPLL_M3DIV_M3 0 9321330497STony Lindgren #define ADPLL_M3DIV_M3_WIDTH 5 9421330497STony Lindgren #define ADPLL_M3DIV_M3_MASK 0x1f 9521330497STony Lindgren 9621330497STony Lindgren #define ADPLL_RAMPCTRL_OFFSET 0x2c /* Only on MPUPLL */ 9721330497STony Lindgren #define ADPLL_RAMPCTRL_CLKRAMPLEVEL 19 9821330497STony Lindgren #define ADPLL_RAMPCTRL_CLKRAMPRATE 16 9921330497STony Lindgren #define ADPLL_RAMPCTRL_RELOCK_RAMP_EN 0 10021330497STony Lindgren 10121330497STony Lindgren #define MAX_ADPLL_INPUTS 3 10221330497STony Lindgren #define MAX_ADPLL_OUTPUTS 4 10321330497STony Lindgren #define ADPLL_MAX_RETRIES 5 10421330497STony Lindgren 10521330497STony Lindgren #define to_dco(_hw) container_of(_hw, struct ti_adpll_dco_data, hw) 10621330497STony Lindgren #define to_adpll(_hw) container_of(_hw, struct ti_adpll_data, dco) 10721330497STony Lindgren #define to_clkout(_hw) container_of(_hw, struct ti_adpll_clkout_data, hw) 10821330497STony Lindgren 10921330497STony Lindgren enum ti_adpll_clocks { 11021330497STony Lindgren TI_ADPLL_DCO, 11121330497STony Lindgren TI_ADPLL_DCO_GATE, 11221330497STony Lindgren TI_ADPLL_N2, 11321330497STony Lindgren TI_ADPLL_M2, 11421330497STony Lindgren TI_ADPLL_M2_GATE, 11521330497STony Lindgren TI_ADPLL_BYPASS, 11621330497STony Lindgren TI_ADPLL_HIF, 11721330497STony Lindgren TI_ADPLL_DIV2, 11821330497STony Lindgren TI_ADPLL_CLKOUT, 11921330497STony Lindgren TI_ADPLL_CLKOUT2, 12021330497STony Lindgren TI_ADPLL_M3, 12121330497STony Lindgren }; 12221330497STony Lindgren 12321330497STony Lindgren #define TI_ADPLL_NR_CLOCKS (TI_ADPLL_M3 + 1) 12421330497STony Lindgren 12521330497STony Lindgren enum ti_adpll_inputs { 12621330497STony Lindgren TI_ADPLL_CLKINP, 12721330497STony Lindgren TI_ADPLL_CLKINPULOW, 12821330497STony Lindgren TI_ADPLL_CLKINPHIF, 12921330497STony Lindgren }; 13021330497STony Lindgren 13121330497STony Lindgren enum ti_adpll_s_outputs { 13221330497STony Lindgren TI_ADPLL_S_DCOCLKLDO, 13321330497STony Lindgren TI_ADPLL_S_CLKOUT, 13421330497STony Lindgren TI_ADPLL_S_CLKOUTX2, 13521330497STony Lindgren TI_ADPLL_S_CLKOUTHIF, 13621330497STony Lindgren }; 13721330497STony Lindgren 13821330497STony Lindgren enum ti_adpll_lj_outputs { 13921330497STony Lindgren TI_ADPLL_LJ_CLKDCOLDO, 14021330497STony Lindgren TI_ADPLL_LJ_CLKOUT, 14121330497STony Lindgren TI_ADPLL_LJ_CLKOUTLDO, 14221330497STony Lindgren }; 14321330497STony Lindgren 14421330497STony Lindgren struct ti_adpll_platform_data { 14521330497STony Lindgren const bool is_type_s; 14621330497STony Lindgren const int nr_max_inputs; 14721330497STony Lindgren const int nr_max_outputs; 14821330497STony Lindgren const int output_index; 14921330497STony Lindgren }; 15021330497STony Lindgren 15121330497STony Lindgren struct ti_adpll_clock { 15221330497STony Lindgren struct clk *clk; 15321330497STony Lindgren struct clk_lookup *cl; 15421330497STony Lindgren void (*unregister)(struct clk *clk); 15521330497STony Lindgren }; 15621330497STony Lindgren 15721330497STony Lindgren struct ti_adpll_dco_data { 15821330497STony Lindgren struct clk_hw hw; 15921330497STony Lindgren }; 16021330497STony Lindgren 16121330497STony Lindgren struct ti_adpll_clkout_data { 16221330497STony Lindgren struct ti_adpll_data *adpll; 16321330497STony Lindgren struct clk_gate gate; 16421330497STony Lindgren struct clk_hw hw; 16521330497STony Lindgren }; 16621330497STony Lindgren 16721330497STony Lindgren struct ti_adpll_data { 16821330497STony Lindgren struct device *dev; 16921330497STony Lindgren const struct ti_adpll_platform_data *c; 17021330497STony Lindgren struct device_node *np; 17121330497STony Lindgren unsigned long pa; 17221330497STony Lindgren void __iomem *iobase; 17321330497STony Lindgren void __iomem *regs; 17421330497STony Lindgren spinlock_t lock; /* For ADPLL shared register access */ 17521330497STony Lindgren const char *parent_names[MAX_ADPLL_INPUTS]; 17621330497STony Lindgren struct clk *parent_clocks[MAX_ADPLL_INPUTS]; 17721330497STony Lindgren struct ti_adpll_clock *clocks; 17821330497STony Lindgren struct clk_onecell_data outputs; 17921330497STony Lindgren struct ti_adpll_dco_data dco; 18021330497STony Lindgren }; 18121330497STony Lindgren 18221330497STony Lindgren static const char *ti_adpll_clk_get_name(struct ti_adpll_data *d, 18321330497STony Lindgren int output_index, 18421330497STony Lindgren const char *postfix) 18521330497STony Lindgren { 18621330497STony Lindgren const char *name; 18721330497STony Lindgren int err; 18821330497STony Lindgren 18921330497STony Lindgren if (output_index >= 0) { 19021330497STony Lindgren err = of_property_read_string_index(d->np, 19121330497STony Lindgren "clock-output-names", 19221330497STony Lindgren output_index, 19321330497STony Lindgren &name); 19421330497STony Lindgren if (err) 19521330497STony Lindgren return NULL; 19621330497STony Lindgren } else { 19721330497STony Lindgren const char *base_name = "adpll"; 19821330497STony Lindgren char *buf; 19921330497STony Lindgren 20021330497STony Lindgren buf = devm_kzalloc(d->dev, 8 + 1 + strlen(base_name) + 1 + 20121330497STony Lindgren strlen(postfix), GFP_KERNEL); 20221330497STony Lindgren if (!buf) 20321330497STony Lindgren return NULL; 20421330497STony Lindgren sprintf(buf, "%08lx.%s.%s", d->pa, base_name, postfix); 20521330497STony Lindgren name = buf; 20621330497STony Lindgren } 20721330497STony Lindgren 20821330497STony Lindgren return name; 20921330497STony Lindgren } 21021330497STony Lindgren 21121330497STony Lindgren #define ADPLL_MAX_CON_ID 16 /* See MAX_CON_ID */ 21221330497STony Lindgren 21321330497STony Lindgren static int ti_adpll_setup_clock(struct ti_adpll_data *d, struct clk *clock, 21421330497STony Lindgren int index, int output_index, const char *name, 21521330497STony Lindgren void (*unregister)(struct clk *clk)) 21621330497STony Lindgren { 21721330497STony Lindgren struct clk_lookup *cl; 21821330497STony Lindgren const char *postfix = NULL; 21921330497STony Lindgren char con_id[ADPLL_MAX_CON_ID]; 22021330497STony Lindgren 22121330497STony Lindgren d->clocks[index].clk = clock; 22221330497STony Lindgren d->clocks[index].unregister = unregister; 22321330497STony Lindgren 22421330497STony Lindgren /* Separate con_id in format "pll040dcoclkldo" to fit MAX_CON_ID */ 22521330497STony Lindgren postfix = strrchr(name, '.'); 226df2f8451SColin Ian King if (postfix && strlen(postfix) > 1) { 22721330497STony Lindgren if (strlen(postfix) > ADPLL_MAX_CON_ID) 22821330497STony Lindgren dev_warn(d->dev, "clock %s con_id lookup may fail\n", 22921330497STony Lindgren name); 23021330497STony Lindgren snprintf(con_id, 16, "pll%03lx%s", d->pa & 0xfff, postfix + 1); 23121330497STony Lindgren cl = clkdev_create(clock, con_id, NULL); 23221330497STony Lindgren if (!cl) 23321330497STony Lindgren return -ENOMEM; 23421330497STony Lindgren d->clocks[index].cl = cl; 23521330497STony Lindgren } else { 23621330497STony Lindgren dev_warn(d->dev, "no con_id for clock %s\n", name); 23721330497STony Lindgren } 23821330497STony Lindgren 23921330497STony Lindgren if (output_index < 0) 24021330497STony Lindgren return 0; 24121330497STony Lindgren 24221330497STony Lindgren d->outputs.clks[output_index] = clock; 24321330497STony Lindgren d->outputs.clk_num++; 24421330497STony Lindgren 24521330497STony Lindgren return 0; 24621330497STony Lindgren } 24721330497STony Lindgren 24821330497STony Lindgren static int ti_adpll_init_divider(struct ti_adpll_data *d, 24921330497STony Lindgren enum ti_adpll_clocks index, 25021330497STony Lindgren int output_index, char *name, 25121330497STony Lindgren struct clk *parent_clock, 25221330497STony Lindgren void __iomem *reg, 25321330497STony Lindgren u8 shift, u8 width, 25421330497STony Lindgren u8 clk_divider_flags) 25521330497STony Lindgren { 25621330497STony Lindgren const char *child_name; 25721330497STony Lindgren const char *parent_name; 25821330497STony Lindgren struct clk *clock; 25921330497STony Lindgren 26021330497STony Lindgren child_name = ti_adpll_clk_get_name(d, output_index, name); 26121330497STony Lindgren if (!child_name) 26221330497STony Lindgren return -EINVAL; 26321330497STony Lindgren 26421330497STony Lindgren parent_name = __clk_get_name(parent_clock); 26521330497STony Lindgren clock = clk_register_divider(d->dev, child_name, parent_name, 0, 26621330497STony Lindgren reg, shift, width, clk_divider_flags, 26721330497STony Lindgren &d->lock); 26821330497STony Lindgren if (IS_ERR(clock)) { 26921330497STony Lindgren dev_err(d->dev, "failed to register divider %s: %li\n", 27021330497STony Lindgren name, PTR_ERR(clock)); 27121330497STony Lindgren return PTR_ERR(clock); 27221330497STony Lindgren } 27321330497STony Lindgren 27421330497STony Lindgren return ti_adpll_setup_clock(d, clock, index, output_index, child_name, 27521330497STony Lindgren clk_unregister_divider); 27621330497STony Lindgren } 27721330497STony Lindgren 27821330497STony Lindgren static int ti_adpll_init_mux(struct ti_adpll_data *d, 27921330497STony Lindgren enum ti_adpll_clocks index, 28021330497STony Lindgren char *name, struct clk *clk0, 28121330497STony Lindgren struct clk *clk1, 28221330497STony Lindgren void __iomem *reg, 28321330497STony Lindgren u8 shift) 28421330497STony Lindgren { 28521330497STony Lindgren const char *child_name; 28621330497STony Lindgren const char *parents[2]; 28721330497STony Lindgren struct clk *clock; 28821330497STony Lindgren 28921330497STony Lindgren child_name = ti_adpll_clk_get_name(d, -ENODEV, name); 29021330497STony Lindgren if (!child_name) 29121330497STony Lindgren return -ENOMEM; 29221330497STony Lindgren parents[0] = __clk_get_name(clk0); 29321330497STony Lindgren parents[1] = __clk_get_name(clk1); 29421330497STony Lindgren clock = clk_register_mux(d->dev, child_name, parents, 2, 0, 29521330497STony Lindgren reg, shift, 1, 0, &d->lock); 29621330497STony Lindgren if (IS_ERR(clock)) { 29721330497STony Lindgren dev_err(d->dev, "failed to register mux %s: %li\n", 29821330497STony Lindgren name, PTR_ERR(clock)); 29921330497STony Lindgren return PTR_ERR(clock); 30021330497STony Lindgren } 30121330497STony Lindgren 30221330497STony Lindgren return ti_adpll_setup_clock(d, clock, index, -ENODEV, child_name, 30321330497STony Lindgren clk_unregister_mux); 30421330497STony Lindgren } 30521330497STony Lindgren 30621330497STony Lindgren static int ti_adpll_init_gate(struct ti_adpll_data *d, 30721330497STony Lindgren enum ti_adpll_clocks index, 30821330497STony Lindgren int output_index, char *name, 30921330497STony Lindgren struct clk *parent_clock, 31021330497STony Lindgren void __iomem *reg, 31121330497STony Lindgren u8 bit_idx, 31221330497STony Lindgren u8 clk_gate_flags) 31321330497STony Lindgren { 31421330497STony Lindgren const char *child_name; 31521330497STony Lindgren const char *parent_name; 31621330497STony Lindgren struct clk *clock; 31721330497STony Lindgren 31821330497STony Lindgren child_name = ti_adpll_clk_get_name(d, output_index, name); 31921330497STony Lindgren if (!child_name) 32021330497STony Lindgren return -EINVAL; 32121330497STony Lindgren 32221330497STony Lindgren parent_name = __clk_get_name(parent_clock); 32321330497STony Lindgren clock = clk_register_gate(d->dev, child_name, parent_name, 0, 32421330497STony Lindgren reg, bit_idx, clk_gate_flags, 32521330497STony Lindgren &d->lock); 32621330497STony Lindgren if (IS_ERR(clock)) { 32721330497STony Lindgren dev_err(d->dev, "failed to register gate %s: %li\n", 32821330497STony Lindgren name, PTR_ERR(clock)); 32921330497STony Lindgren return PTR_ERR(clock); 33021330497STony Lindgren } 33121330497STony Lindgren 33221330497STony Lindgren return ti_adpll_setup_clock(d, clock, index, output_index, child_name, 33321330497STony Lindgren clk_unregister_gate); 33421330497STony Lindgren } 33521330497STony Lindgren 33621330497STony Lindgren static int ti_adpll_init_fixed_factor(struct ti_adpll_data *d, 33721330497STony Lindgren enum ti_adpll_clocks index, 33821330497STony Lindgren char *name, 33921330497STony Lindgren struct clk *parent_clock, 34021330497STony Lindgren unsigned int mult, 34121330497STony Lindgren unsigned int div) 34221330497STony Lindgren { 34321330497STony Lindgren const char *child_name; 34421330497STony Lindgren const char *parent_name; 34521330497STony Lindgren struct clk *clock; 34621330497STony Lindgren 34721330497STony Lindgren child_name = ti_adpll_clk_get_name(d, -ENODEV, name); 34821330497STony Lindgren if (!child_name) 34921330497STony Lindgren return -ENOMEM; 35021330497STony Lindgren 35121330497STony Lindgren parent_name = __clk_get_name(parent_clock); 35221330497STony Lindgren clock = clk_register_fixed_factor(d->dev, child_name, parent_name, 35321330497STony Lindgren 0, mult, div); 35421330497STony Lindgren if (IS_ERR(clock)) 35521330497STony Lindgren return PTR_ERR(clock); 35621330497STony Lindgren 35721330497STony Lindgren return ti_adpll_setup_clock(d, clock, index, -ENODEV, child_name, 35821330497STony Lindgren clk_unregister); 35921330497STony Lindgren } 36021330497STony Lindgren 36121330497STony Lindgren static void ti_adpll_set_idle_bypass(struct ti_adpll_data *d) 36221330497STony Lindgren { 36321330497STony Lindgren unsigned long flags; 36421330497STony Lindgren u32 v; 36521330497STony Lindgren 36621330497STony Lindgren spin_lock_irqsave(&d->lock, flags); 36721330497STony Lindgren v = readl_relaxed(d->regs + ADPLL_CLKCTRL_OFFSET); 36821330497STony Lindgren v |= BIT(ADPLL_CLKCTRL_IDLE); 36921330497STony Lindgren writel_relaxed(v, d->regs + ADPLL_CLKCTRL_OFFSET); 37021330497STony Lindgren spin_unlock_irqrestore(&d->lock, flags); 37121330497STony Lindgren } 37221330497STony Lindgren 37321330497STony Lindgren static void ti_adpll_clear_idle_bypass(struct ti_adpll_data *d) 37421330497STony Lindgren { 37521330497STony Lindgren unsigned long flags; 37621330497STony Lindgren u32 v; 37721330497STony Lindgren 37821330497STony Lindgren spin_lock_irqsave(&d->lock, flags); 37921330497STony Lindgren v = readl_relaxed(d->regs + ADPLL_CLKCTRL_OFFSET); 38021330497STony Lindgren v &= ~BIT(ADPLL_CLKCTRL_IDLE); 38121330497STony Lindgren writel_relaxed(v, d->regs + ADPLL_CLKCTRL_OFFSET); 38221330497STony Lindgren spin_unlock_irqrestore(&d->lock, flags); 38321330497STony Lindgren } 38421330497STony Lindgren 38521330497STony Lindgren static bool ti_adpll_clock_is_bypass(struct ti_adpll_data *d) 38621330497STony Lindgren { 38721330497STony Lindgren u32 v; 38821330497STony Lindgren 38921330497STony Lindgren v = readl_relaxed(d->regs + ADPLL_STATUS_OFFSET); 39021330497STony Lindgren 39121330497STony Lindgren return v & BIT(ADPLL_STATUS_BYPASS); 39221330497STony Lindgren } 39321330497STony Lindgren 39421330497STony Lindgren /* 39521330497STony Lindgren * Locked and bypass are not actually mutually exclusive: if you only care 39621330497STony Lindgren * about the DCO clock and not CLKOUT you can clear M2PWDNZ before enabling 39721330497STony Lindgren * the PLL, resulting in status (FREQLOCK | PHASELOCK | BYPASS) after lock. 39821330497STony Lindgren */ 39921330497STony Lindgren static bool ti_adpll_is_locked(struct ti_adpll_data *d) 40021330497STony Lindgren { 40121330497STony Lindgren u32 v = readl_relaxed(d->regs + ADPLL_STATUS_OFFSET); 40221330497STony Lindgren 40321330497STony Lindgren return (v & ADPLL_STATUS_PREPARED_MASK) == ADPLL_STATUS_PREPARED_MASK; 40421330497STony Lindgren } 40521330497STony Lindgren 40621330497STony Lindgren static int ti_adpll_wait_lock(struct ti_adpll_data *d) 40721330497STony Lindgren { 40821330497STony Lindgren int retries = ADPLL_MAX_RETRIES; 40921330497STony Lindgren 41021330497STony Lindgren do { 41121330497STony Lindgren if (ti_adpll_is_locked(d)) 41221330497STony Lindgren return 0; 41321330497STony Lindgren usleep_range(200, 300); 41421330497STony Lindgren } while (retries--); 41521330497STony Lindgren 41621330497STony Lindgren dev_err(d->dev, "pll failed to lock\n"); 41721330497STony Lindgren return -ETIMEDOUT; 41821330497STony Lindgren } 41921330497STony Lindgren 42021330497STony Lindgren static int ti_adpll_prepare(struct clk_hw *hw) 42121330497STony Lindgren { 42221330497STony Lindgren struct ti_adpll_dco_data *dco = to_dco(hw); 42321330497STony Lindgren struct ti_adpll_data *d = to_adpll(dco); 42421330497STony Lindgren 42521330497STony Lindgren ti_adpll_clear_idle_bypass(d); 42621330497STony Lindgren ti_adpll_wait_lock(d); 42721330497STony Lindgren 42821330497STony Lindgren return 0; 42921330497STony Lindgren } 43021330497STony Lindgren 43121330497STony Lindgren static void ti_adpll_unprepare(struct clk_hw *hw) 43221330497STony Lindgren { 43321330497STony Lindgren struct ti_adpll_dco_data *dco = to_dco(hw); 43421330497STony Lindgren struct ti_adpll_data *d = to_adpll(dco); 43521330497STony Lindgren 43621330497STony Lindgren ti_adpll_set_idle_bypass(d); 43721330497STony Lindgren } 43821330497STony Lindgren 43921330497STony Lindgren static int ti_adpll_is_prepared(struct clk_hw *hw) 44021330497STony Lindgren { 44121330497STony Lindgren struct ti_adpll_dco_data *dco = to_dco(hw); 44221330497STony Lindgren struct ti_adpll_data *d = to_adpll(dco); 44321330497STony Lindgren 44421330497STony Lindgren return ti_adpll_is_locked(d); 44521330497STony Lindgren } 44621330497STony Lindgren 44721330497STony Lindgren /* 44821330497STony Lindgren * Note that the DCO clock is never subject to bypass: if the PLL is off, 44921330497STony Lindgren * dcoclk is low. 45021330497STony Lindgren */ 45121330497STony Lindgren static unsigned long ti_adpll_recalc_rate(struct clk_hw *hw, 45221330497STony Lindgren unsigned long parent_rate) 45321330497STony Lindgren { 45421330497STony Lindgren struct ti_adpll_dco_data *dco = to_dco(hw); 45521330497STony Lindgren struct ti_adpll_data *d = to_adpll(dco); 45621330497STony Lindgren u32 frac_m, divider, v; 45721330497STony Lindgren u64 rate; 45821330497STony Lindgren unsigned long flags; 45921330497STony Lindgren 46021330497STony Lindgren if (ti_adpll_clock_is_bypass(d)) 46121330497STony Lindgren return 0; 46221330497STony Lindgren 46321330497STony Lindgren spin_lock_irqsave(&d->lock, flags); 46421330497STony Lindgren frac_m = readl_relaxed(d->regs + ADPLL_FRACDIV_OFFSET); 46521330497STony Lindgren frac_m &= ADPLL_FRACDIV_FRACTIONALM_MASK; 4668a8b6eb7SStephen Boyd rate = (u64)readw_relaxed(d->regs + ADPLL_MN2DIV_OFFSET) << 18; 46721330497STony Lindgren rate += frac_m; 46821330497STony Lindgren rate *= parent_rate; 46921330497STony Lindgren divider = (readw_relaxed(d->regs + ADPLL_M2NDIV_OFFSET) + 1) << 18; 47021330497STony Lindgren spin_unlock_irqrestore(&d->lock, flags); 47121330497STony Lindgren 47221330497STony Lindgren do_div(rate, divider); 47321330497STony Lindgren 47421330497STony Lindgren if (d->c->is_type_s) { 47521330497STony Lindgren v = readl_relaxed(d->regs + ADPLL_CLKCTRL_OFFSET); 47621330497STony Lindgren if (v & BIT(ADPLL_CLKCTRL_REGM4XEN_ADPLL_S)) 47721330497STony Lindgren rate *= 4; 47821330497STony Lindgren rate *= 2; 47921330497STony Lindgren } 48021330497STony Lindgren 48121330497STony Lindgren return rate; 48221330497STony Lindgren } 48321330497STony Lindgren 48421330497STony Lindgren /* PLL parent is always clkinp, bypass only affects the children */ 48521330497STony Lindgren static u8 ti_adpll_get_parent(struct clk_hw *hw) 48621330497STony Lindgren { 48721330497STony Lindgren return 0; 48821330497STony Lindgren } 48921330497STony Lindgren 4907cc566a8SBhumika Goyal static const struct clk_ops ti_adpll_ops = { 49121330497STony Lindgren .prepare = ti_adpll_prepare, 49221330497STony Lindgren .unprepare = ti_adpll_unprepare, 49321330497STony Lindgren .is_prepared = ti_adpll_is_prepared, 49421330497STony Lindgren .recalc_rate = ti_adpll_recalc_rate, 49521330497STony Lindgren .get_parent = ti_adpll_get_parent, 49621330497STony Lindgren }; 49721330497STony Lindgren 49821330497STony Lindgren static int ti_adpll_init_dco(struct ti_adpll_data *d) 49921330497STony Lindgren { 50021330497STony Lindgren struct clk_init_data init; 50121330497STony Lindgren struct clk *clock; 50221330497STony Lindgren const char *postfix; 50321330497STony Lindgren int width, err; 50421330497STony Lindgren 505a86854d0SKees Cook d->outputs.clks = devm_kcalloc(d->dev, 50621330497STony Lindgren MAX_ADPLL_OUTPUTS, 507a86854d0SKees Cook sizeof(struct clk *), 50821330497STony Lindgren GFP_KERNEL); 50921330497STony Lindgren if (!d->outputs.clks) 51021330497STony Lindgren return -ENOMEM; 51121330497STony Lindgren 51221330497STony Lindgren if (d->c->output_index < 0) 51321330497STony Lindgren postfix = "dco"; 51421330497STony Lindgren else 51521330497STony Lindgren postfix = NULL; 51621330497STony Lindgren 51721330497STony Lindgren init.name = ti_adpll_clk_get_name(d, d->c->output_index, postfix); 51821330497STony Lindgren if (!init.name) 51921330497STony Lindgren return -EINVAL; 52021330497STony Lindgren 52121330497STony Lindgren init.parent_names = d->parent_names; 52221330497STony Lindgren init.num_parents = d->c->nr_max_inputs; 52321330497STony Lindgren init.ops = &ti_adpll_ops; 52421330497STony Lindgren init.flags = CLK_GET_RATE_NOCACHE; 52521330497STony Lindgren d->dco.hw.init = &init; 52621330497STony Lindgren 52721330497STony Lindgren if (d->c->is_type_s) 52821330497STony Lindgren width = 5; 52921330497STony Lindgren else 53021330497STony Lindgren width = 4; 53121330497STony Lindgren 53221330497STony Lindgren /* Internal input clock divider N2 */ 53321330497STony Lindgren err = ti_adpll_init_divider(d, TI_ADPLL_N2, -ENODEV, "n2", 53421330497STony Lindgren d->parent_clocks[TI_ADPLL_CLKINP], 53521330497STony Lindgren d->regs + ADPLL_MN2DIV_OFFSET, 53621330497STony Lindgren ADPLL_MN2DIV_N2, width, 0); 53721330497STony Lindgren if (err) 53821330497STony Lindgren return err; 53921330497STony Lindgren 54021330497STony Lindgren clock = devm_clk_register(d->dev, &d->dco.hw); 54121330497STony Lindgren if (IS_ERR(clock)) 54221330497STony Lindgren return PTR_ERR(clock); 54321330497STony Lindgren 54421330497STony Lindgren return ti_adpll_setup_clock(d, clock, TI_ADPLL_DCO, d->c->output_index, 54521330497STony Lindgren init.name, NULL); 54621330497STony Lindgren } 54721330497STony Lindgren 54821330497STony Lindgren static int ti_adpll_clkout_enable(struct clk_hw *hw) 54921330497STony Lindgren { 55021330497STony Lindgren struct ti_adpll_clkout_data *co = to_clkout(hw); 55121330497STony Lindgren struct clk_hw *gate_hw = &co->gate.hw; 55221330497STony Lindgren 55321330497STony Lindgren __clk_hw_set_clk(gate_hw, hw); 55421330497STony Lindgren 55521330497STony Lindgren return clk_gate_ops.enable(gate_hw); 55621330497STony Lindgren } 55721330497STony Lindgren 55821330497STony Lindgren static void ti_adpll_clkout_disable(struct clk_hw *hw) 55921330497STony Lindgren { 56021330497STony Lindgren struct ti_adpll_clkout_data *co = to_clkout(hw); 56121330497STony Lindgren struct clk_hw *gate_hw = &co->gate.hw; 56221330497STony Lindgren 56321330497STony Lindgren __clk_hw_set_clk(gate_hw, hw); 56421330497STony Lindgren clk_gate_ops.disable(gate_hw); 56521330497STony Lindgren } 56621330497STony Lindgren 56721330497STony Lindgren static int ti_adpll_clkout_is_enabled(struct clk_hw *hw) 56821330497STony Lindgren { 56921330497STony Lindgren struct ti_adpll_clkout_data *co = to_clkout(hw); 57021330497STony Lindgren struct clk_hw *gate_hw = &co->gate.hw; 57121330497STony Lindgren 57221330497STony Lindgren __clk_hw_set_clk(gate_hw, hw); 57321330497STony Lindgren 57421330497STony Lindgren return clk_gate_ops.is_enabled(gate_hw); 57521330497STony Lindgren } 57621330497STony Lindgren 57721330497STony Lindgren /* Setting PLL bypass puts clkout and clkoutx2 into bypass */ 57821330497STony Lindgren static u8 ti_adpll_clkout_get_parent(struct clk_hw *hw) 57921330497STony Lindgren { 58021330497STony Lindgren struct ti_adpll_clkout_data *co = to_clkout(hw); 58121330497STony Lindgren struct ti_adpll_data *d = co->adpll; 58221330497STony Lindgren 58321330497STony Lindgren return ti_adpll_clock_is_bypass(d); 58421330497STony Lindgren } 58521330497STony Lindgren 58621330497STony Lindgren static int ti_adpll_init_clkout(struct ti_adpll_data *d, 58721330497STony Lindgren enum ti_adpll_clocks index, 58821330497STony Lindgren int output_index, int gate_bit, 58921330497STony Lindgren char *name, struct clk *clk0, 59021330497STony Lindgren struct clk *clk1) 59121330497STony Lindgren { 59221330497STony Lindgren struct ti_adpll_clkout_data *co; 59321330497STony Lindgren struct clk_init_data init; 59421330497STony Lindgren struct clk_ops *ops; 59521330497STony Lindgren const char *parent_names[2]; 59621330497STony Lindgren const char *child_name; 59721330497STony Lindgren struct clk *clock; 59821330497STony Lindgren int err; 59921330497STony Lindgren 60021330497STony Lindgren co = devm_kzalloc(d->dev, sizeof(*co), GFP_KERNEL); 60121330497STony Lindgren if (!co) 60221330497STony Lindgren return -ENOMEM; 60321330497STony Lindgren co->adpll = d; 60421330497STony Lindgren 60521330497STony Lindgren err = of_property_read_string_index(d->np, 60621330497STony Lindgren "clock-output-names", 60721330497STony Lindgren output_index, 60821330497STony Lindgren &child_name); 60921330497STony Lindgren if (err) 61021330497STony Lindgren return err; 61121330497STony Lindgren 61221330497STony Lindgren ops = devm_kzalloc(d->dev, sizeof(*ops), GFP_KERNEL); 61321330497STony Lindgren if (!ops) 61421330497STony Lindgren return -ENOMEM; 61521330497STony Lindgren 61621330497STony Lindgren init.name = child_name; 61721330497STony Lindgren init.ops = ops; 6188aa09cf3STero Kristo init.flags = 0; 61921330497STony Lindgren co->hw.init = &init; 62021330497STony Lindgren parent_names[0] = __clk_get_name(clk0); 62121330497STony Lindgren parent_names[1] = __clk_get_name(clk1); 62221330497STony Lindgren init.parent_names = parent_names; 62321330497STony Lindgren init.num_parents = 2; 62421330497STony Lindgren 62521330497STony Lindgren ops->get_parent = ti_adpll_clkout_get_parent; 62621330497STony Lindgren ops->determine_rate = __clk_mux_determine_rate; 62721330497STony Lindgren if (gate_bit) { 62821330497STony Lindgren co->gate.lock = &d->lock; 62921330497STony Lindgren co->gate.reg = d->regs + ADPLL_CLKCTRL_OFFSET; 63021330497STony Lindgren co->gate.bit_idx = gate_bit; 63121330497STony Lindgren ops->enable = ti_adpll_clkout_enable; 63221330497STony Lindgren ops->disable = ti_adpll_clkout_disable; 63321330497STony Lindgren ops->is_enabled = ti_adpll_clkout_is_enabled; 63421330497STony Lindgren } 63521330497STony Lindgren 63621330497STony Lindgren clock = devm_clk_register(d->dev, &co->hw); 63721330497STony Lindgren if (IS_ERR(clock)) { 63821330497STony Lindgren dev_err(d->dev, "failed to register output %s: %li\n", 63921330497STony Lindgren name, PTR_ERR(clock)); 64021330497STony Lindgren return PTR_ERR(clock); 64121330497STony Lindgren } 64221330497STony Lindgren 64321330497STony Lindgren return ti_adpll_setup_clock(d, clock, index, output_index, child_name, 64421330497STony Lindgren NULL); 64521330497STony Lindgren } 64621330497STony Lindgren 64721330497STony Lindgren static int ti_adpll_init_children_adpll_s(struct ti_adpll_data *d) 64821330497STony Lindgren { 64921330497STony Lindgren int err; 65021330497STony Lindgren 65121330497STony Lindgren if (!d->c->is_type_s) 65221330497STony Lindgren return 0; 65321330497STony Lindgren 65421330497STony Lindgren /* Internal mux, sources from divider N2 or clkinpulow */ 65521330497STony Lindgren err = ti_adpll_init_mux(d, TI_ADPLL_BYPASS, "bypass", 65621330497STony Lindgren d->clocks[TI_ADPLL_N2].clk, 65721330497STony Lindgren d->parent_clocks[TI_ADPLL_CLKINPULOW], 65821330497STony Lindgren d->regs + ADPLL_CLKCTRL_OFFSET, 65921330497STony Lindgren ADPLL_CLKCTRL_ULOWCLKEN); 66021330497STony Lindgren if (err) 66121330497STony Lindgren return err; 66221330497STony Lindgren 66321330497STony Lindgren /* Internal divider M2, sources DCO */ 66421330497STony Lindgren err = ti_adpll_init_divider(d, TI_ADPLL_M2, -ENODEV, "m2", 66521330497STony Lindgren d->clocks[TI_ADPLL_DCO].clk, 66621330497STony Lindgren d->regs + ADPLL_M2NDIV_OFFSET, 66721330497STony Lindgren ADPLL_M2NDIV_M2, 66821330497STony Lindgren ADPLL_M2NDIV_M2_ADPLL_S_WIDTH, 66921330497STony Lindgren CLK_DIVIDER_ONE_BASED); 67021330497STony Lindgren if (err) 67121330497STony Lindgren return err; 67221330497STony Lindgren 67321330497STony Lindgren /* Internal fixed divider, after M2 before clkout */ 67421330497STony Lindgren err = ti_adpll_init_fixed_factor(d, TI_ADPLL_DIV2, "div2", 67521330497STony Lindgren d->clocks[TI_ADPLL_M2].clk, 67621330497STony Lindgren 1, 2); 67721330497STony Lindgren if (err) 67821330497STony Lindgren return err; 67921330497STony Lindgren 68021330497STony Lindgren /* Output clkout with a mux and gate, sources from div2 or bypass */ 68121330497STony Lindgren err = ti_adpll_init_clkout(d, TI_ADPLL_CLKOUT, TI_ADPLL_S_CLKOUT, 68221330497STony Lindgren ADPLL_CLKCTRL_CLKOUTEN, "clkout", 68321330497STony Lindgren d->clocks[TI_ADPLL_DIV2].clk, 68421330497STony Lindgren d->clocks[TI_ADPLL_BYPASS].clk); 68521330497STony Lindgren if (err) 68621330497STony Lindgren return err; 68721330497STony Lindgren 68821330497STony Lindgren /* Output clkoutx2 with a mux and gate, sources from M2 or bypass */ 68921330497STony Lindgren err = ti_adpll_init_clkout(d, TI_ADPLL_CLKOUT2, TI_ADPLL_S_CLKOUTX2, 0, 69021330497STony Lindgren "clkout2", d->clocks[TI_ADPLL_M2].clk, 69121330497STony Lindgren d->clocks[TI_ADPLL_BYPASS].clk); 69221330497STony Lindgren if (err) 69321330497STony Lindgren return err; 69421330497STony Lindgren 69521330497STony Lindgren /* Internal mux, sources from DCO and clkinphif */ 69621330497STony Lindgren if (d->parent_clocks[TI_ADPLL_CLKINPHIF]) { 69721330497STony Lindgren err = ti_adpll_init_mux(d, TI_ADPLL_HIF, "hif", 69821330497STony Lindgren d->clocks[TI_ADPLL_DCO].clk, 69921330497STony Lindgren d->parent_clocks[TI_ADPLL_CLKINPHIF], 70021330497STony Lindgren d->regs + ADPLL_CLKCTRL_OFFSET, 70121330497STony Lindgren ADPLL_CLKINPHIFSEL_ADPLL_S); 70221330497STony Lindgren if (err) 70321330497STony Lindgren return err; 70421330497STony Lindgren } 70521330497STony Lindgren 70621330497STony Lindgren /* Output clkouthif with a divider M3, sources from hif */ 70721330497STony Lindgren err = ti_adpll_init_divider(d, TI_ADPLL_M3, TI_ADPLL_S_CLKOUTHIF, "m3", 70821330497STony Lindgren d->clocks[TI_ADPLL_HIF].clk, 70921330497STony Lindgren d->regs + ADPLL_M3DIV_OFFSET, 71021330497STony Lindgren ADPLL_M3DIV_M3, 71121330497STony Lindgren ADPLL_M3DIV_M3_WIDTH, 71221330497STony Lindgren CLK_DIVIDER_ONE_BASED); 71321330497STony Lindgren if (err) 71421330497STony Lindgren return err; 71521330497STony Lindgren 71621330497STony Lindgren /* Output clock dcoclkldo is the DCO */ 71721330497STony Lindgren 71821330497STony Lindgren return 0; 71921330497STony Lindgren } 72021330497STony Lindgren 72121330497STony Lindgren static int ti_adpll_init_children_adpll_lj(struct ti_adpll_data *d) 72221330497STony Lindgren { 72321330497STony Lindgren int err; 72421330497STony Lindgren 72521330497STony Lindgren if (d->c->is_type_s) 72621330497STony Lindgren return 0; 72721330497STony Lindgren 72821330497STony Lindgren /* Output clkdcoldo, gated output of DCO */ 72921330497STony Lindgren err = ti_adpll_init_gate(d, TI_ADPLL_DCO_GATE, TI_ADPLL_LJ_CLKDCOLDO, 73021330497STony Lindgren "clkdcoldo", d->clocks[TI_ADPLL_DCO].clk, 73121330497STony Lindgren d->regs + ADPLL_CLKCTRL_OFFSET, 73221330497STony Lindgren ADPLL_CLKCTRL_CLKDCOLDOEN, 0); 73321330497STony Lindgren if (err) 73421330497STony Lindgren return err; 73521330497STony Lindgren 73621330497STony Lindgren /* Internal divider M2, sources from DCO */ 73721330497STony Lindgren err = ti_adpll_init_divider(d, TI_ADPLL_M2, -ENODEV, 73821330497STony Lindgren "m2", d->clocks[TI_ADPLL_DCO].clk, 73921330497STony Lindgren d->regs + ADPLL_M2NDIV_OFFSET, 74021330497STony Lindgren ADPLL_M2NDIV_M2, 74121330497STony Lindgren ADPLL_M2NDIV_M2_ADPLL_LJ_WIDTH, 74221330497STony Lindgren CLK_DIVIDER_ONE_BASED); 74321330497STony Lindgren if (err) 74421330497STony Lindgren return err; 74521330497STony Lindgren 74621330497STony Lindgren /* Output clkoutldo, gated output of M2 */ 74721330497STony Lindgren err = ti_adpll_init_gate(d, TI_ADPLL_M2_GATE, TI_ADPLL_LJ_CLKOUTLDO, 74821330497STony Lindgren "clkoutldo", d->clocks[TI_ADPLL_M2].clk, 74921330497STony Lindgren d->regs + ADPLL_CLKCTRL_OFFSET, 75021330497STony Lindgren ADPLL_CLKCTRL_CLKOUTLDOEN_ADPLL_LJ, 75121330497STony Lindgren 0); 75221330497STony Lindgren if (err) 75321330497STony Lindgren return err; 75421330497STony Lindgren 75521330497STony Lindgren /* Internal mux, sources from divider N2 or clkinpulow */ 75621330497STony Lindgren err = ti_adpll_init_mux(d, TI_ADPLL_BYPASS, "bypass", 75721330497STony Lindgren d->clocks[TI_ADPLL_N2].clk, 75821330497STony Lindgren d->parent_clocks[TI_ADPLL_CLKINPULOW], 75921330497STony Lindgren d->regs + ADPLL_CLKCTRL_OFFSET, 76021330497STony Lindgren ADPLL_CLKCTRL_ULOWCLKEN); 76121330497STony Lindgren if (err) 76221330497STony Lindgren return err; 76321330497STony Lindgren 76421330497STony Lindgren /* Output clkout, sources M2 or bypass */ 76521330497STony Lindgren err = ti_adpll_init_clkout(d, TI_ADPLL_CLKOUT, TI_ADPLL_S_CLKOUT, 76621330497STony Lindgren ADPLL_CLKCTRL_CLKOUTEN, "clkout", 76721330497STony Lindgren d->clocks[TI_ADPLL_M2].clk, 76821330497STony Lindgren d->clocks[TI_ADPLL_BYPASS].clk); 76921330497STony Lindgren if (err) 77021330497STony Lindgren return err; 77121330497STony Lindgren 77221330497STony Lindgren return 0; 77321330497STony Lindgren } 77421330497STony Lindgren 77521330497STony Lindgren static void ti_adpll_free_resources(struct ti_adpll_data *d) 77621330497STony Lindgren { 77721330497STony Lindgren int i; 77821330497STony Lindgren 77921330497STony Lindgren for (i = TI_ADPLL_M3; i >= 0; i--) { 78021330497STony Lindgren struct ti_adpll_clock *ac = &d->clocks[i]; 78121330497STony Lindgren 78221330497STony Lindgren if (!ac || IS_ERR_OR_NULL(ac->clk)) 78321330497STony Lindgren continue; 78421330497STony Lindgren if (ac->cl) 78521330497STony Lindgren clkdev_drop(ac->cl); 78621330497STony Lindgren if (ac->unregister) 78721330497STony Lindgren ac->unregister(ac->clk); 78821330497STony Lindgren } 78921330497STony Lindgren } 79021330497STony Lindgren 79121330497STony Lindgren /* MPU PLL manages the lock register for all PLLs */ 79221330497STony Lindgren static void ti_adpll_unlock_all(void __iomem *reg) 79321330497STony Lindgren { 79421330497STony Lindgren u32 v; 79521330497STony Lindgren 79621330497STony Lindgren v = readl_relaxed(reg); 79721330497STony Lindgren if (v == ADPLL_PLLSS_MMR_LOCK_ENABLED) 79821330497STony Lindgren writel_relaxed(ADPLL_PLLSS_MMR_UNLOCK_MAGIC, reg); 79921330497STony Lindgren } 80021330497STony Lindgren 80121330497STony Lindgren static int ti_adpll_init_registers(struct ti_adpll_data *d) 80221330497STony Lindgren { 80321330497STony Lindgren int register_offset = 0; 80421330497STony Lindgren 80521330497STony Lindgren if (d->c->is_type_s) { 80621330497STony Lindgren register_offset = 8; 80721330497STony Lindgren ti_adpll_unlock_all(d->iobase + ADPLL_PLLSS_MMR_LOCK_OFFSET); 80821330497STony Lindgren } 80921330497STony Lindgren 81021330497STony Lindgren d->regs = d->iobase + register_offset + ADPLL_PWRCTRL_OFFSET; 81121330497STony Lindgren 81221330497STony Lindgren return 0; 81321330497STony Lindgren } 81421330497STony Lindgren 81521330497STony Lindgren static int ti_adpll_init_inputs(struct ti_adpll_data *d) 81621330497STony Lindgren { 81721330497STony Lindgren const char *error = "need at least %i inputs"; 81821330497STony Lindgren struct clk *clock; 81921330497STony Lindgren int nr_inputs; 82021330497STony Lindgren 82121330497STony Lindgren nr_inputs = of_clk_get_parent_count(d->np); 82221330497STony Lindgren if (nr_inputs < d->c->nr_max_inputs) { 82321330497STony Lindgren dev_err(d->dev, error, nr_inputs); 82421330497STony Lindgren return -EINVAL; 82521330497STony Lindgren } 82621330497STony Lindgren of_clk_parent_fill(d->np, d->parent_names, nr_inputs); 82721330497STony Lindgren 82821330497STony Lindgren clock = devm_clk_get(d->dev, d->parent_names[0]); 82921330497STony Lindgren if (IS_ERR(clock)) { 83021330497STony Lindgren dev_err(d->dev, "could not get clkinp\n"); 83121330497STony Lindgren return PTR_ERR(clock); 83221330497STony Lindgren } 83321330497STony Lindgren d->parent_clocks[TI_ADPLL_CLKINP] = clock; 83421330497STony Lindgren 83521330497STony Lindgren clock = devm_clk_get(d->dev, d->parent_names[1]); 83621330497STony Lindgren if (IS_ERR(clock)) { 83721330497STony Lindgren dev_err(d->dev, "could not get clkinpulow clock\n"); 83821330497STony Lindgren return PTR_ERR(clock); 83921330497STony Lindgren } 84021330497STony Lindgren d->parent_clocks[TI_ADPLL_CLKINPULOW] = clock; 84121330497STony Lindgren 84221330497STony Lindgren if (d->c->is_type_s) { 84321330497STony Lindgren clock = devm_clk_get(d->dev, d->parent_names[2]); 84421330497STony Lindgren if (IS_ERR(clock)) { 84521330497STony Lindgren dev_err(d->dev, "could not get clkinphif clock\n"); 84621330497STony Lindgren return PTR_ERR(clock); 84721330497STony Lindgren } 84821330497STony Lindgren d->parent_clocks[TI_ADPLL_CLKINPHIF] = clock; 84921330497STony Lindgren } 85021330497STony Lindgren 85121330497STony Lindgren return 0; 85221330497STony Lindgren } 85321330497STony Lindgren 85421330497STony Lindgren static const struct ti_adpll_platform_data ti_adpll_type_s = { 85521330497STony Lindgren .is_type_s = true, 85621330497STony Lindgren .nr_max_inputs = MAX_ADPLL_INPUTS, 85721330497STony Lindgren .nr_max_outputs = MAX_ADPLL_OUTPUTS, 85821330497STony Lindgren .output_index = TI_ADPLL_S_DCOCLKLDO, 85921330497STony Lindgren }; 86021330497STony Lindgren 86121330497STony Lindgren static const struct ti_adpll_platform_data ti_adpll_type_lj = { 86221330497STony Lindgren .is_type_s = false, 86321330497STony Lindgren .nr_max_inputs = MAX_ADPLL_INPUTS - 1, 86421330497STony Lindgren .nr_max_outputs = MAX_ADPLL_OUTPUTS - 1, 86521330497STony Lindgren .output_index = -EINVAL, 86621330497STony Lindgren }; 86721330497STony Lindgren 86821330497STony Lindgren static const struct of_device_id ti_adpll_match[] = { 86921330497STony Lindgren { .compatible = "ti,dm814-adpll-s-clock", &ti_adpll_type_s }, 87021330497STony Lindgren { .compatible = "ti,dm814-adpll-lj-clock", &ti_adpll_type_lj }, 87121330497STony Lindgren {}, 87221330497STony Lindgren }; 87321330497STony Lindgren MODULE_DEVICE_TABLE(of, ti_adpll_match); 87421330497STony Lindgren 87521330497STony Lindgren static int ti_adpll_probe(struct platform_device *pdev) 87621330497STony Lindgren { 87721330497STony Lindgren struct device_node *node = pdev->dev.of_node; 87821330497STony Lindgren struct device *dev = &pdev->dev; 87921330497STony Lindgren const struct of_device_id *match; 88021330497STony Lindgren const struct ti_adpll_platform_data *pdata; 88121330497STony Lindgren struct ti_adpll_data *d; 88221330497STony Lindgren struct resource *res; 88321330497STony Lindgren int err; 88421330497STony Lindgren 88521330497STony Lindgren match = of_match_device(ti_adpll_match, dev); 88621330497STony Lindgren if (match) 88721330497STony Lindgren pdata = match->data; 88821330497STony Lindgren else 88921330497STony Lindgren return -ENODEV; 89021330497STony Lindgren 89121330497STony Lindgren d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL); 89221330497STony Lindgren if (!d) 89321330497STony Lindgren return -ENOMEM; 89421330497STony Lindgren d->dev = dev; 89521330497STony Lindgren d->np = node; 89621330497STony Lindgren d->c = pdata; 89721330497STony Lindgren dev_set_drvdata(d->dev, d); 89821330497STony Lindgren spin_lock_init(&d->lock); 89921330497STony Lindgren 90021330497STony Lindgren res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 90121330497STony Lindgren if (!res) 90221330497STony Lindgren return -ENODEV; 90321330497STony Lindgren d->pa = res->start; 90421330497STony Lindgren 90521330497STony Lindgren d->iobase = devm_ioremap_resource(dev, res); 90621330497STony Lindgren if (IS_ERR(d->iobase)) { 90721330497STony Lindgren dev_err(dev, "could not get IO base: %li\n", 90821330497STony Lindgren PTR_ERR(d->iobase)); 90921330497STony Lindgren return PTR_ERR(d->iobase); 91021330497STony Lindgren } 91121330497STony Lindgren 91221330497STony Lindgren err = ti_adpll_init_registers(d); 91321330497STony Lindgren if (err) 91421330497STony Lindgren return err; 91521330497STony Lindgren 91621330497STony Lindgren err = ti_adpll_init_inputs(d); 91721330497STony Lindgren if (err) 91821330497STony Lindgren return err; 91921330497STony Lindgren 920a86854d0SKees Cook d->clocks = devm_kcalloc(d->dev, 92121330497STony Lindgren TI_ADPLL_NR_CLOCKS, 922a86854d0SKees Cook sizeof(struct ti_adpll_clock), 92321330497STony Lindgren GFP_KERNEL); 92421330497STony Lindgren if (!d->clocks) 9258a8b6eb7SStephen Boyd return -ENOMEM; 92621330497STony Lindgren 92721330497STony Lindgren err = ti_adpll_init_dco(d); 92821330497STony Lindgren if (err) { 92921330497STony Lindgren dev_err(dev, "could not register dco: %i\n", err); 93021330497STony Lindgren goto free; 93121330497STony Lindgren } 93221330497STony Lindgren 93321330497STony Lindgren err = ti_adpll_init_children_adpll_s(d); 93421330497STony Lindgren if (err) 93521330497STony Lindgren goto free; 93621330497STony Lindgren err = ti_adpll_init_children_adpll_lj(d); 93721330497STony Lindgren if (err) 93821330497STony Lindgren goto free; 93921330497STony Lindgren 94021330497STony Lindgren err = of_clk_add_provider(d->np, of_clk_src_onecell_get, &d->outputs); 94121330497STony Lindgren if (err) 94221330497STony Lindgren goto free; 94321330497STony Lindgren 94421330497STony Lindgren return 0; 94521330497STony Lindgren 94621330497STony Lindgren free: 94721330497STony Lindgren WARN_ON(1); 94821330497STony Lindgren ti_adpll_free_resources(d); 94921330497STony Lindgren 95021330497STony Lindgren return err; 95121330497STony Lindgren } 95221330497STony Lindgren 95321330497STony Lindgren static int ti_adpll_remove(struct platform_device *pdev) 95421330497STony Lindgren { 95521330497STony Lindgren struct ti_adpll_data *d = dev_get_drvdata(&pdev->dev); 95621330497STony Lindgren 95721330497STony Lindgren ti_adpll_free_resources(d); 95821330497STony Lindgren 95921330497STony Lindgren return 0; 96021330497STony Lindgren } 96121330497STony Lindgren 96221330497STony Lindgren static struct platform_driver ti_adpll_driver = { 96321330497STony Lindgren .driver = { 96421330497STony Lindgren .name = "ti-adpll", 96521330497STony Lindgren .of_match_table = ti_adpll_match, 96621330497STony Lindgren }, 96721330497STony Lindgren .probe = ti_adpll_probe, 96821330497STony Lindgren .remove = ti_adpll_remove, 96921330497STony Lindgren }; 97021330497STony Lindgren 97121330497STony Lindgren static int __init ti_adpll_init(void) 97221330497STony Lindgren { 97321330497STony Lindgren return platform_driver_register(&ti_adpll_driver); 97421330497STony Lindgren } 97521330497STony Lindgren core_initcall(ti_adpll_init); 97621330497STony Lindgren 97721330497STony Lindgren static void __exit ti_adpll_exit(void) 97821330497STony Lindgren { 97921330497STony Lindgren platform_driver_unregister(&ti_adpll_driver); 98021330497STony Lindgren } 98121330497STony Lindgren module_exit(ti_adpll_exit); 98221330497STony Lindgren 98321330497STony Lindgren MODULE_DESCRIPTION("Clock driver for dm814x ADPLL"); 98421330497STony Lindgren MODULE_ALIAS("platform:dm814-adpll-clock"); 98521330497STony Lindgren MODULE_AUTHOR("Tony LIndgren <tony@atomide.com>"); 98621330497STony Lindgren MODULE_LICENSE("GPL v2"); 987