1d37010a3SWen He // SPDX-License-Identifier: GPL-2.0 2d37010a3SWen He /* 3d37010a3SWen He * Copyright 2019 NXP 4d37010a3SWen He * 5d37010a3SWen He * Clock driver for LS1028A Display output interfaces(LCD, DPHY). 6d37010a3SWen He */ 7d37010a3SWen He 8d37010a3SWen He #include <linux/clk-provider.h> 9d37010a3SWen He #include <linux/device.h> 10d37010a3SWen He #include <linux/module.h> 11d37010a3SWen He #include <linux/err.h> 12d37010a3SWen He #include <linux/io.h> 13d37010a3SWen He #include <linux/iopoll.h> 14d37010a3SWen He #include <linux/of.h> 15d37010a3SWen He #include <linux/of_address.h> 16d37010a3SWen He #include <linux/of_device.h> 17d37010a3SWen He #include <linux/platform_device.h> 18d37010a3SWen He #include <linux/slab.h> 19d37010a3SWen He #include <linux/bitfield.h> 20d37010a3SWen He 21d37010a3SWen He /* PLLDIG register offsets and bit masks */ 22d37010a3SWen He #define PLLDIG_REG_PLLSR 0x24 23d37010a3SWen He #define PLLDIG_LOCK_MASK BIT(2) 24d37010a3SWen He #define PLLDIG_REG_PLLDV 0x28 25d37010a3SWen He #define PLLDIG_MFD_MASK GENMASK(7, 0) 26d37010a3SWen He #define PLLDIG_RFDPHI1_MASK GENMASK(30, 25) 27d37010a3SWen He #define PLLDIG_REG_PLLFM 0x2c 28d37010a3SWen He #define PLLDIG_SSCGBYP_ENABLE BIT(30) 29d37010a3SWen He #define PLLDIG_REG_PLLFD 0x30 30d37010a3SWen He #define PLLDIG_FDEN BIT(30) 31d37010a3SWen He #define PLLDIG_FRAC_MASK GENMASK(15, 0) 32d37010a3SWen He #define PLLDIG_REG_PLLCAL1 0x38 33d37010a3SWen He #define PLLDIG_REG_PLLCAL2 0x3c 34d37010a3SWen He 35d37010a3SWen He /* Range of the VCO frequencies, in Hz */ 36d37010a3SWen He #define PLLDIG_MIN_VCO_FREQ 650000000 37d37010a3SWen He #define PLLDIG_MAX_VCO_FREQ 1300000000 38d37010a3SWen He 39d37010a3SWen He /* Range of the output frequencies, in Hz */ 40*0d152f2dSStephen Boyd #define PHI1_MIN_FREQ 27000000UL 41*0d152f2dSStephen Boyd #define PHI1_MAX_FREQ 600000000UL 42d37010a3SWen He 43d37010a3SWen He /* Maximum value of the reduced frequency divider */ 44d37010a3SWen He #define MAX_RFDPHI1 63UL 45d37010a3SWen He 46d37010a3SWen He /* Best value of multiplication factor divider */ 47d37010a3SWen He #define PLLDIG_DEFAULT_MFD 44 48d37010a3SWen He 49d37010a3SWen He /* 50d37010a3SWen He * Denominator part of the fractional part of the 51d37010a3SWen He * loop multiplication factor. 52d37010a3SWen He */ 53d37010a3SWen He #define MFDEN 20480 54d37010a3SWen He 55d37010a3SWen He static const struct clk_parent_data parent_data[] = { 56d37010a3SWen He { .index = 0 }, 57d37010a3SWen He }; 58d37010a3SWen He 59d37010a3SWen He struct clk_plldig { 60d37010a3SWen He struct clk_hw hw; 61d37010a3SWen He void __iomem *regs; 62d37010a3SWen He unsigned int vco_freq; 63d37010a3SWen He }; 64d37010a3SWen He 65d37010a3SWen He #define to_clk_plldig(_hw) container_of(_hw, struct clk_plldig, hw) 66d37010a3SWen He 67d37010a3SWen He static int plldig_enable(struct clk_hw *hw) 68d37010a3SWen He { 69d37010a3SWen He struct clk_plldig *data = to_clk_plldig(hw); 70d37010a3SWen He u32 val; 71d37010a3SWen He 72d37010a3SWen He val = readl(data->regs + PLLDIG_REG_PLLFM); 73d37010a3SWen He /* 74d37010a3SWen He * Use Bypass mode with PLL off by default, the frequency overshoot 75d37010a3SWen He * detector output was disable. SSCG Bypass mode should be enable. 76d37010a3SWen He */ 77d37010a3SWen He val |= PLLDIG_SSCGBYP_ENABLE; 78d37010a3SWen He writel(val, data->regs + PLLDIG_REG_PLLFM); 79d37010a3SWen He 80d37010a3SWen He return 0; 81d37010a3SWen He } 82d37010a3SWen He 83d37010a3SWen He static void plldig_disable(struct clk_hw *hw) 84d37010a3SWen He { 85d37010a3SWen He struct clk_plldig *data = to_clk_plldig(hw); 86d37010a3SWen He u32 val; 87d37010a3SWen He 88d37010a3SWen He val = readl(data->regs + PLLDIG_REG_PLLFM); 89d37010a3SWen He 90d37010a3SWen He val &= ~PLLDIG_SSCGBYP_ENABLE; 91d37010a3SWen He val |= FIELD_PREP(PLLDIG_SSCGBYP_ENABLE, 0x0); 92d37010a3SWen He 93d37010a3SWen He writel(val, data->regs + PLLDIG_REG_PLLFM); 94d37010a3SWen He } 95d37010a3SWen He 96d37010a3SWen He static int plldig_is_enabled(struct clk_hw *hw) 97d37010a3SWen He { 98d37010a3SWen He struct clk_plldig *data = to_clk_plldig(hw); 99d37010a3SWen He 100d37010a3SWen He return readl(data->regs + PLLDIG_REG_PLLFM) & 101d37010a3SWen He PLLDIG_SSCGBYP_ENABLE; 102d37010a3SWen He } 103d37010a3SWen He 104d37010a3SWen He static unsigned long plldig_recalc_rate(struct clk_hw *hw, 105d37010a3SWen He unsigned long parent_rate) 106d37010a3SWen He { 107d37010a3SWen He struct clk_plldig *data = to_clk_plldig(hw); 108d37010a3SWen He u32 val, rfdphi1; 109d37010a3SWen He 110d37010a3SWen He val = readl(data->regs + PLLDIG_REG_PLLDV); 111d37010a3SWen He 112d37010a3SWen He /* Check if PLL is bypassed */ 113d37010a3SWen He if (val & PLLDIG_SSCGBYP_ENABLE) 114d37010a3SWen He return parent_rate; 115d37010a3SWen He 116d37010a3SWen He rfdphi1 = FIELD_GET(PLLDIG_RFDPHI1_MASK, val); 117d37010a3SWen He 118d37010a3SWen He /* 119d37010a3SWen He * If RFDPHI1 has a value of 1 the VCO frequency is also divided by 120d37010a3SWen He * one. 121d37010a3SWen He */ 122d37010a3SWen He if (!rfdphi1) 123d37010a3SWen He rfdphi1 = 1; 124d37010a3SWen He 125d37010a3SWen He return DIV_ROUND_UP(data->vco_freq, rfdphi1); 126d37010a3SWen He } 127d37010a3SWen He 128d37010a3SWen He static unsigned long plldig_calc_target_div(unsigned long vco_freq, 129d37010a3SWen He unsigned long target_rate) 130d37010a3SWen He { 131d37010a3SWen He unsigned long div; 132d37010a3SWen He 133d37010a3SWen He div = DIV_ROUND_CLOSEST(vco_freq, target_rate); 134d37010a3SWen He div = clamp(div, 1UL, MAX_RFDPHI1); 135d37010a3SWen He 136d37010a3SWen He return div; 137d37010a3SWen He } 138d37010a3SWen He 139d37010a3SWen He static int plldig_determine_rate(struct clk_hw *hw, 140d37010a3SWen He struct clk_rate_request *req) 141d37010a3SWen He { 142d37010a3SWen He struct clk_plldig *data = to_clk_plldig(hw); 143d37010a3SWen He unsigned int div; 144d37010a3SWen He 145d37010a3SWen He req->rate = clamp(req->rate, PHI1_MIN_FREQ, PHI1_MAX_FREQ); 146d37010a3SWen He div = plldig_calc_target_div(data->vco_freq, req->rate); 147d37010a3SWen He req->rate = DIV_ROUND_UP(data->vco_freq, div); 148d37010a3SWen He 149d37010a3SWen He return 0; 150d37010a3SWen He } 151d37010a3SWen He 152d37010a3SWen He static int plldig_set_rate(struct clk_hw *hw, unsigned long rate, 153d37010a3SWen He unsigned long parent_rate) 154d37010a3SWen He { 155d37010a3SWen He struct clk_plldig *data = to_clk_plldig(hw); 156d37010a3SWen He unsigned int val, cond; 157d37010a3SWen He unsigned int rfdphi1; 158d37010a3SWen He 159d37010a3SWen He rate = clamp(rate, PHI1_MIN_FREQ, PHI1_MAX_FREQ); 160d37010a3SWen He rfdphi1 = plldig_calc_target_div(data->vco_freq, rate); 161d37010a3SWen He 162d37010a3SWen He /* update the divider value */ 163d37010a3SWen He val = readl(data->regs + PLLDIG_REG_PLLDV); 164d37010a3SWen He val &= ~PLLDIG_RFDPHI1_MASK; 165d37010a3SWen He val |= FIELD_PREP(PLLDIG_RFDPHI1_MASK, rfdphi1); 166d37010a3SWen He writel(val, data->regs + PLLDIG_REG_PLLDV); 167d37010a3SWen He 168d37010a3SWen He /* waiting for old lock state to clear */ 169d37010a3SWen He udelay(200); 170d37010a3SWen He 171d37010a3SWen He /* Wait until PLL is locked or timeout */ 172d37010a3SWen He return readl_poll_timeout_atomic(data->regs + PLLDIG_REG_PLLSR, cond, 173d37010a3SWen He cond & PLLDIG_LOCK_MASK, 0, 174d37010a3SWen He USEC_PER_MSEC); 175d37010a3SWen He } 176d37010a3SWen He 177d37010a3SWen He static const struct clk_ops plldig_clk_ops = { 178d37010a3SWen He .enable = plldig_enable, 179d37010a3SWen He .disable = plldig_disable, 180d37010a3SWen He .is_enabled = plldig_is_enabled, 181d37010a3SWen He .recalc_rate = plldig_recalc_rate, 182d37010a3SWen He .determine_rate = plldig_determine_rate, 183d37010a3SWen He .set_rate = plldig_set_rate, 184d37010a3SWen He }; 185d37010a3SWen He 186d37010a3SWen He static int plldig_init(struct clk_hw *hw) 187d37010a3SWen He { 188d37010a3SWen He struct clk_plldig *data = to_clk_plldig(hw); 189d37010a3SWen He struct clk_hw *parent = clk_hw_get_parent(hw); 190d37010a3SWen He unsigned long parent_rate = clk_hw_get_rate(parent); 191d37010a3SWen He unsigned long val; 192d37010a3SWen He unsigned long long lltmp; 193d37010a3SWen He unsigned int mfd, fracdiv = 0; 194d37010a3SWen He 195d37010a3SWen He if (!parent) 196d37010a3SWen He return -EINVAL; 197d37010a3SWen He 198d37010a3SWen He if (data->vco_freq) { 199d37010a3SWen He mfd = data->vco_freq / parent_rate; 200d37010a3SWen He lltmp = data->vco_freq % parent_rate; 201d37010a3SWen He lltmp *= MFDEN; 202d37010a3SWen He do_div(lltmp, parent_rate); 203d37010a3SWen He fracdiv = lltmp; 204d37010a3SWen He } else { 205d37010a3SWen He mfd = PLLDIG_DEFAULT_MFD; 206d37010a3SWen He data->vco_freq = parent_rate * mfd; 207d37010a3SWen He } 208d37010a3SWen He 209d37010a3SWen He val = FIELD_PREP(PLLDIG_MFD_MASK, mfd); 210d37010a3SWen He writel(val, data->regs + PLLDIG_REG_PLLDV); 211d37010a3SWen He 212d37010a3SWen He /* Enable fractional divider */ 213d37010a3SWen He if (fracdiv) { 214d37010a3SWen He val = FIELD_PREP(PLLDIG_FRAC_MASK, fracdiv); 215d37010a3SWen He val |= PLLDIG_FDEN; 216d37010a3SWen He writel(val, data->regs + PLLDIG_REG_PLLFD); 217d37010a3SWen He } 218d37010a3SWen He 219d37010a3SWen He return 0; 220d37010a3SWen He } 221d37010a3SWen He 222d37010a3SWen He static int plldig_clk_probe(struct platform_device *pdev) 223d37010a3SWen He { 224d37010a3SWen He struct clk_plldig *data; 225d37010a3SWen He struct device *dev = &pdev->dev; 226d37010a3SWen He int ret; 227d37010a3SWen He 228d37010a3SWen He data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 229d37010a3SWen He if (!data) 230d37010a3SWen He return -ENOMEM; 231d37010a3SWen He 232d37010a3SWen He data->regs = devm_platform_ioremap_resource(pdev, 0); 233d37010a3SWen He if (IS_ERR(data->regs)) 234d37010a3SWen He return PTR_ERR(data->regs); 235d37010a3SWen He 236d37010a3SWen He data->hw.init = CLK_HW_INIT_PARENTS_DATA("dpclk", 237d37010a3SWen He parent_data, 238d37010a3SWen He &plldig_clk_ops, 239d37010a3SWen He 0); 240d37010a3SWen He 241d37010a3SWen He ret = devm_clk_hw_register(dev, &data->hw); 242d37010a3SWen He if (ret) { 243d37010a3SWen He dev_err(dev, "failed to register %s clock\n", 244d37010a3SWen He dev->of_node->name); 245d37010a3SWen He return ret; 246d37010a3SWen He } 247d37010a3SWen He 248d37010a3SWen He ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, 249d37010a3SWen He &data->hw); 250d37010a3SWen He if (ret) { 251d37010a3SWen He dev_err(dev, "unable to add clk provider\n"); 252d37010a3SWen He return ret; 253d37010a3SWen He } 254d37010a3SWen He 255d37010a3SWen He /* 256d37010a3SWen He * The frequency of the VCO cannot be changed during runtime. 257d37010a3SWen He * Therefore, let the user specify a desired frequency. 258d37010a3SWen He */ 259d37010a3SWen He if (!of_property_read_u32(dev->of_node, "fsl,vco-hz", 260d37010a3SWen He &data->vco_freq)) { 261d37010a3SWen He if (data->vco_freq < PLLDIG_MIN_VCO_FREQ || 262d37010a3SWen He data->vco_freq > PLLDIG_MAX_VCO_FREQ) 263d37010a3SWen He return -EINVAL; 264d37010a3SWen He } 265d37010a3SWen He 266d37010a3SWen He return plldig_init(&data->hw); 267d37010a3SWen He } 268d37010a3SWen He 269d37010a3SWen He static const struct of_device_id plldig_clk_id[] = { 270d37010a3SWen He { .compatible = "fsl,ls1028a-plldig" }, 271d37010a3SWen He { } 272d37010a3SWen He }; 273d37010a3SWen He MODULE_DEVICE_TABLE(of, plldig_clk_id); 274d37010a3SWen He 275d37010a3SWen He static struct platform_driver plldig_clk_driver = { 276d37010a3SWen He .driver = { 277d37010a3SWen He .name = "plldig-clock", 278d37010a3SWen He .of_match_table = plldig_clk_id, 279d37010a3SWen He }, 280d37010a3SWen He .probe = plldig_clk_probe, 281d37010a3SWen He }; 282d37010a3SWen He module_platform_driver(plldig_clk_driver); 283d37010a3SWen He 284d37010a3SWen He MODULE_LICENSE("GPL v2"); 285d37010a3SWen He MODULE_AUTHOR("Wen He <wen.he_1@nxp.com>"); 286d37010a3SWen He MODULE_DESCRIPTION("LS1028A Display output interface pixel clock driver"); 287