10e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen/* 20e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen * AXI clkgen driver 30e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen * 40e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen * Copyright 2012-2013 Analog Devices Inc. 50e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen * Author: Lars-Peter Clausen <lars@metafoo.de> 60e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen * 70e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen * Licensed under the GPL-2. 80e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen * 90e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen */ 100e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 110e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen#include <linux/platform_device.h> 120e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen#include <linux/clk-provider.h> 130e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen#include <linux/clk.h> 140e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen#include <linux/slab.h> 150e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen#include <linux/io.h> 160e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen#include <linux/of.h> 170e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen#include <linux/module.h> 180e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen#include <linux/err.h> 190e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 201887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V1_REG_UPDATE_ENABLE 0x04 211887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V1_REG_CLK_OUT1 0x08 221887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V1_REG_CLK_OUT2 0x0c 231887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V1_REG_CLK_DIV 0x10 241887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V1_REG_CLK_FB1 0x14 251887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V1_REG_CLK_FB2 0x18 261887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V1_REG_LOCK1 0x1c 271887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V1_REG_LOCK2 0x20 281887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V1_REG_LOCK3 0x24 291887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V1_REG_FILTER1 0x28 301887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V1_REG_FILTER2 0x2c 311887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 321887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V2_REG_RESET 0x40 331887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V2_REG_DRP_CNTRL 0x70 341887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V2_REG_DRP_STATUS 0x74 351887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 361887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V2_RESET_MMCM_ENABLE BIT(1) 371887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V2_RESET_ENABLE BIT(0) 381887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 391887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V2_DRP_CNTRL_SEL BIT(29) 401887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V2_DRP_CNTRL_READ BIT(28) 411887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 421887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define AXI_CLKGEN_V2_DRP_STATUS_BUSY BIT(16) 431887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 441887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define MMCM_REG_CLKOUT0_1 0x08 451887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define MMCM_REG_CLKOUT0_2 0x09 461887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define MMCM_REG_CLK_FB1 0x14 471887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define MMCM_REG_CLK_FB2 0x15 481887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define MMCM_REG_CLK_DIV 0x16 491887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define MMCM_REG_LOCK1 0x18 501887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define MMCM_REG_LOCK2 0x19 511887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define MMCM_REG_LOCK3 0x1a 521887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define MMCM_REG_FILTER1 0x4e 531887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen#define MMCM_REG_FILTER2 0x4f 541887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 551887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstruct axi_clkgen; 561887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 571887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstruct axi_clkgen_mmcm_ops { 581887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen void (*enable)(struct axi_clkgen *axi_clkgen, bool enable); 591887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen int (*write)(struct axi_clkgen *axi_clkgen, unsigned int reg, 601887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen unsigned int val, unsigned int mask); 611887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen int (*read)(struct axi_clkgen *axi_clkgen, unsigned int reg, 621887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen unsigned int *val); 631887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen}; 640e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 650e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstruct axi_clkgen { 660e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen void __iomem *base; 671887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen const struct axi_clkgen_mmcm_ops *mmcm_ops; 680e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen struct clk_hw clk_hw; 690e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen}; 700e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 711887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic void axi_clkgen_mmcm_enable(struct axi_clkgen *axi_clkgen, 721887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen bool enable) 731887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen{ 741887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen->mmcm_ops->enable(axi_clkgen, enable); 751887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen} 761887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 771887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic int axi_clkgen_mmcm_write(struct axi_clkgen *axi_clkgen, 781887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen unsigned int reg, unsigned int val, unsigned int mask) 791887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen{ 801887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return axi_clkgen->mmcm_ops->write(axi_clkgen, reg, val, mask); 811887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen} 821887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 831887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic int axi_clkgen_mmcm_read(struct axi_clkgen *axi_clkgen, 841887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen unsigned int reg, unsigned int *val) 851887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen{ 861887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return axi_clkgen->mmcm_ops->read(axi_clkgen, reg, val); 871887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen} 881887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 890e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic uint32_t axi_clkgen_lookup_filter(unsigned int m) 900e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen{ 910e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen switch (m) { 920e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen case 0: 930e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0x01001990; 940e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen case 1: 950e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0x01001190; 960e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen case 2: 970e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0x01009890; 980e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen case 3: 990e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0x01001890; 1000e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen case 4: 1010e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0x01008890; 1020e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen case 5 ... 8: 1030e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0x01009090; 1040e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen case 9 ... 11: 1050e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0x01000890; 1060e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen case 12: 1070e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0x08009090; 1080e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen case 13 ... 22: 1090e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0x01001090; 1100e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen case 23 ... 36: 1110e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0x01008090; 1120e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen case 37 ... 46: 1130e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0x08001090; 1140e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen default: 1150e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0x08008090; 1160e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen } 1170e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen} 1180e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 1190e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic const uint32_t axi_clkgen_lock_table[] = { 1200e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 0x060603e8, 0x060603e8, 0x080803e8, 0x0b0b03e8, 1210e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 0x0e0e03e8, 0x111103e8, 0x131303e8, 0x161603e8, 1220e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 0x191903e8, 0x1c1c03e8, 0x1f1f0384, 0x1f1f0339, 1230e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 0x1f1f02ee, 0x1f1f02bc, 0x1f1f028a, 0x1f1f0271, 1240e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 0x1f1f023f, 0x1f1f0226, 0x1f1f020d, 0x1f1f01f4, 1250e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 0x1f1f01db, 0x1f1f01c2, 0x1f1f01a9, 0x1f1f0190, 1260e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 0x1f1f0190, 0x1f1f0177, 0x1f1f015e, 0x1f1f015e, 1270e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 0x1f1f0145, 0x1f1f0145, 0x1f1f012c, 0x1f1f012c, 1280e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 0x1f1f012c, 0x1f1f0113, 0x1f1f0113, 0x1f1f0113, 1290e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen}; 1300e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 1310e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic uint32_t axi_clkgen_lookup_lock(unsigned int m) 1320e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen{ 1330e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen if (m < ARRAY_SIZE(axi_clkgen_lock_table)) 1340e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return axi_clkgen_lock_table[m]; 1350e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0x1f1f00fa; 1360e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen} 1370e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 1380e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic const unsigned int fpfd_min = 10000; 1390e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic const unsigned int fpfd_max = 300000; 1400e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic const unsigned int fvco_min = 600000; 1410e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic const unsigned int fvco_max = 1200000; 1420e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 1430e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic void axi_clkgen_calc_params(unsigned long fin, unsigned long fout, 1440e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned int *best_d, unsigned int *best_m, unsigned int *best_dout) 1450e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen{ 1460e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned long d, d_min, d_max, _d_min, _d_max; 1470e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned long m, m_min, m_max; 1480e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned long f, dout, best_f, fvco; 1490e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 1500e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen fin /= 1000; 1510e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen fout /= 1000; 1520e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 1530e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen best_f = ULONG_MAX; 1540e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen *best_d = 0; 1550e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen *best_m = 0; 1560e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen *best_dout = 0; 1570e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 1580e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1); 1590e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen d_max = min_t(unsigned long, fin / fpfd_min, 80); 1600e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 1610e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min, fin) * d_min, 1); 1620e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen m_max = min_t(unsigned long, fvco_max * d_max / fin, 64); 1630e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 1640e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen for (m = m_min; m <= m_max; m++) { 1650e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen _d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max)); 1660e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen _d_max = min(d_max, fin * m / fvco_min); 1670e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 1680e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen for (d = _d_min; d <= _d_max; d++) { 1690e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen fvco = fin * m / d; 1700e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 1710e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen dout = DIV_ROUND_CLOSEST(fvco, fout); 1720e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen dout = clamp_t(unsigned long, dout, 1, 128); 1730e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen f = fvco / dout; 1740e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen if (abs(f - fout) < abs(best_f - fout)) { 1750e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen best_f = f; 1760e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen *best_d = d; 1770e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen *best_m = m; 1780e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen *best_dout = dout; 1790e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen if (best_f == fout) 1800e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return; 1810e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen } 1820e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen } 1830e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen } 1840e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen} 1850e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 1860e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic void axi_clkgen_calc_clk_params(unsigned int divider, unsigned int *low, 1870e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned int *high, unsigned int *edge, unsigned int *nocount) 1880e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen{ 1890e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen if (divider == 1) 1900e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen *nocount = 1; 1910e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen else 1920e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen *nocount = 0; 1930e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 1940e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen *high = divider / 2; 1950e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen *edge = divider % 2; 1960e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen *low = divider - *high; 1970e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen} 1980e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 1990e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic void axi_clkgen_write(struct axi_clkgen *axi_clkgen, 2000e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned int reg, unsigned int val) 2010e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen{ 2020e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen writel(val, axi_clkgen->base + reg); 2030e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen} 2040e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 2050e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic void axi_clkgen_read(struct axi_clkgen *axi_clkgen, 2060e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned int reg, unsigned int *val) 2070e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen{ 2080e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen *val = readl(axi_clkgen->base + reg); 2090e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen} 2100e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 2111887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic unsigned int axi_clkgen_v1_map_mmcm_reg(unsigned int reg) 2121887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen{ 2131887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen switch (reg) { 2141887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen case MMCM_REG_CLKOUT0_1: 2151887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return AXI_CLKGEN_V1_REG_CLK_OUT1; 2161887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen case MMCM_REG_CLKOUT0_2: 2171887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return AXI_CLKGEN_V1_REG_CLK_OUT2; 2181887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen case MMCM_REG_CLK_FB1: 2191887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return AXI_CLKGEN_V1_REG_CLK_FB1; 2201887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen case MMCM_REG_CLK_FB2: 2211887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return AXI_CLKGEN_V1_REG_CLK_FB2; 2221887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen case MMCM_REG_CLK_DIV: 2231887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return AXI_CLKGEN_V1_REG_CLK_DIV; 2241887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen case MMCM_REG_LOCK1: 2251887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return AXI_CLKGEN_V1_REG_LOCK1; 2261887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen case MMCM_REG_LOCK2: 2271887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return AXI_CLKGEN_V1_REG_LOCK2; 2281887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen case MMCM_REG_LOCK3: 2291887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return AXI_CLKGEN_V1_REG_LOCK3; 2301887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen case MMCM_REG_FILTER1: 2311887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return AXI_CLKGEN_V1_REG_FILTER1; 2321887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen case MMCM_REG_FILTER2: 2331887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return AXI_CLKGEN_V1_REG_FILTER2; 2341887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen default: 2351887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return 0; 2361887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen } 2371887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen} 2381887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 2391887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic int axi_clkgen_v1_mmcm_write(struct axi_clkgen *axi_clkgen, 2401887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen unsigned int reg, unsigned int val, unsigned int mask) 2411887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen{ 2421887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen reg = axi_clkgen_v1_map_mmcm_reg(reg); 2431887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen if (reg == 0) 2441887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return -EINVAL; 2451887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 2461887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_write(axi_clkgen, reg, val); 2471887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 2481887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return 0; 2491887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen} 2501887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 2511887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic int axi_clkgen_v1_mmcm_read(struct axi_clkgen *axi_clkgen, 2521887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen unsigned int reg, unsigned int *val) 2531887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen{ 2541887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen reg = axi_clkgen_v1_map_mmcm_reg(reg); 2551887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen if (reg == 0) 2561887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return -EINVAL; 2571887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 2581887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_read(axi_clkgen, reg, val); 2591887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 2601887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return 0; 2611887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen} 2621887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 2631887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic void axi_clkgen_v1_mmcm_enable(struct axi_clkgen *axi_clkgen, 2641887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen bool enable) 2651887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen{ 2661887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V1_REG_UPDATE_ENABLE, enable); 2671887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen} 2681887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 2691887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic const struct axi_clkgen_mmcm_ops axi_clkgen_v1_mmcm_ops = { 2701887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen .write = axi_clkgen_v1_mmcm_write, 2711887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen .read = axi_clkgen_v1_mmcm_read, 2721887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen .enable = axi_clkgen_v1_mmcm_enable, 2731887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen}; 2741887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 2751887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic int axi_clkgen_wait_non_busy(struct axi_clkgen *axi_clkgen) 2761887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen{ 2771887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen unsigned int timeout = 10000; 2781887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen unsigned int val; 2791887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 2801887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen do { 2811887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_read(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_STATUS, &val); 2821887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen } while ((val & AXI_CLKGEN_V2_DRP_STATUS_BUSY) && --timeout); 2831887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 2841887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen if (val & AXI_CLKGEN_V2_DRP_STATUS_BUSY) 2851887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return -EIO; 2861887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 2871887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return val & 0xffff; 2881887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen} 2891887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 2901887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic int axi_clkgen_v2_mmcm_read(struct axi_clkgen *axi_clkgen, 2911887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen unsigned int reg, unsigned int *val) 2921887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen{ 2931887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen unsigned int reg_val; 2941887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen int ret; 2951887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 2961887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen ret = axi_clkgen_wait_non_busy(axi_clkgen); 2971887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen if (ret < 0) 2981887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return ret; 2991887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3001887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen reg_val = AXI_CLKGEN_V2_DRP_CNTRL_SEL | AXI_CLKGEN_V2_DRP_CNTRL_READ; 3011887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen reg_val |= (reg << 16); 3021887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3031887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val); 3041887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3051887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen ret = axi_clkgen_wait_non_busy(axi_clkgen); 3061887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen if (ret < 0) 3071887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return ret; 3081887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3091887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen *val = ret; 3101887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3111887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return 0; 3121887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen} 3131887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3141887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic int axi_clkgen_v2_mmcm_write(struct axi_clkgen *axi_clkgen, 3151887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen unsigned int reg, unsigned int val, unsigned int mask) 3161887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen{ 3171887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen unsigned int reg_val = 0; 3181887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen int ret; 3191887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3201887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen ret = axi_clkgen_wait_non_busy(axi_clkgen); 3211887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen if (ret < 0) 3221887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return ret; 3231887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3241887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen if (mask != 0xffff) { 3251887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_v2_mmcm_read(axi_clkgen, reg, ®_val); 3261887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen reg_val &= ~mask; 3271887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen } 3281887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3291887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen reg_val |= AXI_CLKGEN_V2_DRP_CNTRL_SEL | (reg << 16) | (val & mask); 3301887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3311887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val); 3321887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3331887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return 0; 3341887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen} 3351887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3361887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic void axi_clkgen_v2_mmcm_enable(struct axi_clkgen *axi_clkgen, 3371887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen bool enable) 3381887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen{ 3391887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen unsigned int val = AXI_CLKGEN_V2_RESET_ENABLE; 3401887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3411887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen if (enable) 3421887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen val |= AXI_CLKGEN_V2_RESET_MMCM_ENABLE; 3431887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3441887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_RESET, val); 3451887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen} 3461887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3471887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic const struct axi_clkgen_mmcm_ops axi_clkgen_v2_mmcm_ops = { 3481887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen .write = axi_clkgen_v2_mmcm_write, 3491887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen .read = axi_clkgen_v2_mmcm_read, 3501887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen .enable = axi_clkgen_v2_mmcm_enable, 3511887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen}; 3521887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3530e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw) 3540e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen{ 3550e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return container_of(clk_hw, struct axi_clkgen, clk_hw); 3560e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen} 3570e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 3580e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic int axi_clkgen_set_rate(struct clk_hw *clk_hw, 3590e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned long rate, unsigned long parent_rate) 3600e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen{ 3610e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); 3620e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned int d, m, dout; 3630e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned int nocount; 3640e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned int high; 3650e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned int edge; 3660e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned int low; 3670e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen uint32_t filter; 3680e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen uint32_t lock; 3690e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 3700e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen if (parent_rate == 0 || rate == 0) 3710e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return -EINVAL; 3720e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 3730e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen axi_clkgen_calc_params(parent_rate, rate, &d, &m, &dout); 3740e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 3750e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen if (d == 0 || dout == 0 || m == 0) 3760e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return -EINVAL; 3770e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 3780e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen filter = axi_clkgen_lookup_filter(m - 1); 3790e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen lock = axi_clkgen_lookup_lock(m - 1); 3800e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 3810e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount); 3821887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_1, 3831887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen (high << 6) | low, 0xefff); 3841887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_2, 3851887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen (edge << 7) | (nocount << 6), 0x03ff); 3860e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 3870e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount); 3881887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_DIV, 3891887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen (edge << 13) | (nocount << 12) | (high << 6) | low, 0x3fff); 3900e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 3910e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount); 3921887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB1, 3931887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen (high << 6) | low, 0xefff); 3941887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB2, 3951887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen (edge << 7) | (nocount << 6), 0x03ff); 3961887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 3971887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK1, lock & 0x3ff, 0x3ff); 3981887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK2, 3991887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen (((lock >> 16) & 0x1f) << 10) | 0x1, 0x7fff); 4001887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK3, 4011887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen (((lock >> 24) & 0x1f) << 10) | 0x3e9, 0x7fff); 4021887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER1, filter >> 16, 0x9900); 4031887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER2, filter, 0x9900); 4040e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 4050e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0; 4060e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen} 4070e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 4080e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate, 4090e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned long *parent_rate) 4100e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen{ 4110e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned int d, m, dout; 4120e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 4130e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen axi_clkgen_calc_params(*parent_rate, rate, &d, &m, &dout); 4140e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 4150e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen if (d == 0 || dout == 0 || m == 0) 4160e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return -EINVAL; 4170e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 4180e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return *parent_rate / d * m / dout; 4190e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen} 4200e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 4210e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw, 4220e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned long parent_rate) 4230e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen{ 4240e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); 4250e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned int d, m, dout; 4260e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned int reg; 4270e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen unsigned long long tmp; 4280e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 4291887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, ®); 4300e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen dout = (reg & 0x3f) + ((reg >> 6) & 0x3f); 4311887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, ®); 4320e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen d = (reg & 0x3f) + ((reg >> 6) & 0x3f); 4331887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, ®); 4340e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen m = (reg & 0x3f) + ((reg >> 6) & 0x3f); 4350e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 4360e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen if (d == 0 || dout == 0) 4370e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0; 4380e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 4390e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen tmp = (unsigned long long)(parent_rate / d) * m; 4400e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen do_div(tmp, dout); 4410e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 4420e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen if (tmp > ULONG_MAX) 4430e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return ULONG_MAX; 4440e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 4450e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return tmp; 4460e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen} 4470e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 4481887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic int axi_clkgen_enable(struct clk_hw *clk_hw) 4491887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen{ 4501887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); 4511887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 4521887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_enable(axi_clkgen, true); 4531887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 4541887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return 0; 4551887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen} 4561887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 4571887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic void axi_clkgen_disable(struct clk_hw *clk_hw) 4581887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen{ 4591887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); 4601887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 4611887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_enable(axi_clkgen, false); 4621887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen} 4631887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 4640e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic const struct clk_ops axi_clkgen_ops = { 4650e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen .recalc_rate = axi_clkgen_recalc_rate, 4660e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen .round_rate = axi_clkgen_round_rate, 4670e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen .set_rate = axi_clkgen_set_rate, 4681887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen .enable = axi_clkgen_enable, 4691887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen .disable = axi_clkgen_disable, 4700e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen}; 4710e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 4721887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausenstatic const struct of_device_id axi_clkgen_ids[] = { 4731887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen { 4741887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen .compatible = "adi,axi-clkgen-1.00.a", 4751887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen .data = &axi_clkgen_v1_mmcm_ops 4761887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen }, { 4771887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen .compatible = "adi,axi-clkgen-2.00.a", 4781887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen .data = &axi_clkgen_v2_mmcm_ops, 4791887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen }, 4801887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen { }, 4811887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen}; 4821887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter ClausenMODULE_DEVICE_TABLE(of, axi_clkgen_ids); 4831887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 4840e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic int axi_clkgen_probe(struct platform_device *pdev) 4850e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen{ 4861887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen const struct of_device_id *id; 4870e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen struct axi_clkgen *axi_clkgen; 4880e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen struct clk_init_data init; 4890e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen const char *parent_name; 4900e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen const char *clk_name; 4910e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen struct resource *mem; 4920e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen struct clk *clk; 4930e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 4941887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen if (!pdev->dev.of_node) 4951887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return -ENODEV; 4961887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 4971887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen id = of_match_node(axi_clkgen_ids, pdev->dev.of_node); 4981887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen if (!id) 4991887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen return -ENODEV; 5001887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 5010e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL); 5020e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen if (!axi_clkgen) 5030e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return -ENOMEM; 5040e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 5051887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen->mmcm_ops = id->data; 5061887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 5070e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 5080e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem); 5090e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen if (IS_ERR(axi_clkgen->base)) 5100e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return PTR_ERR(axi_clkgen->base); 5110e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 5120e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0); 5130e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen if (!parent_name) 5140e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return -EINVAL; 5150e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 5160e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen clk_name = pdev->dev.of_node->name; 5170e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen of_property_read_string(pdev->dev.of_node, "clock-output-names", 5180e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen &clk_name); 5190e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 5200e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen init.name = clk_name; 5210e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen init.ops = &axi_clkgen_ops; 5221887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen init.flags = CLK_SET_RATE_GATE; 5230e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen init.parent_names = &parent_name; 5240e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen init.num_parents = 1; 5250e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 5261887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen axi_clkgen_mmcm_enable(axi_clkgen, false); 5271887c3a64fab8300a5be3fb5fd8d6474a63b50a0Lars-Peter Clausen 5280e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen axi_clkgen->clk_hw.init = &init; 5290e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen clk = devm_clk_register(&pdev->dev, &axi_clkgen->clk_hw); 5300e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen if (IS_ERR(clk)) 5310e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return PTR_ERR(clk); 5320e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 5330e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, 5340e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen clk); 5350e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen} 5360e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 5370e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic int axi_clkgen_remove(struct platform_device *pdev) 5380e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen{ 5390e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen of_clk_del_provider(pdev->dev.of_node); 5400e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 5410e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen return 0; 5420e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen} 5430e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 5440e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenstatic struct platform_driver axi_clkgen_driver = { 5450e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen .driver = { 5460e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen .name = "adi-axi-clkgen", 5470e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen .of_match_table = axi_clkgen_ids, 5480e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen }, 5490e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen .probe = axi_clkgen_probe, 5500e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen .remove = axi_clkgen_remove, 5510e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen}; 5520e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausenmodule_platform_driver(axi_clkgen_driver); 5530e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter Clausen 5540e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter ClausenMODULE_LICENSE("GPL v2"); 5550e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter ClausenMODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 5560e646c52cf0ee186ec50b41c4db8cf81500c8dd1Lars-Peter ClausenMODULE_DESCRIPTION("Driver for the Analog Devices' AXI clkgen pcore clock generator"); 557