clk-xlnx-clock-wizard.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Xilinx 'Clocking Wizard' driver
  4. *
  5. * Copyright (C) 2013 - 2021 Xilinx
  6. *
  7. * Sören Brinkmann <[email protected]>
  8. *
  9. */
  10. #include <linux/platform_device.h>
  11. #include <linux/clk.h>
  12. #include <linux/clk-provider.h>
  13. #include <linux/slab.h>
  14. #include <linux/io.h>
  15. #include <linux/of.h>
  16. #include <linux/module.h>
  17. #include <linux/err.h>
  18. #include <linux/iopoll.h>
  19. #define WZRD_NUM_OUTPUTS 7
  20. #define WZRD_ACLK_MAX_FREQ 250000000UL
  21. #define WZRD_CLK_CFG_REG(n) (0x200 + 4 * (n))
  22. #define WZRD_CLKOUT0_FRAC_EN BIT(18)
  23. #define WZRD_CLKFBOUT_FRAC_EN BIT(26)
  24. #define WZRD_CLKFBOUT_MULT_SHIFT 8
  25. #define WZRD_CLKFBOUT_MULT_MASK (0xff << WZRD_CLKFBOUT_MULT_SHIFT)
  26. #define WZRD_CLKFBOUT_FRAC_SHIFT 16
  27. #define WZRD_CLKFBOUT_FRAC_MASK (0x3ff << WZRD_CLKFBOUT_FRAC_SHIFT)
  28. #define WZRD_DIVCLK_DIVIDE_SHIFT 0
  29. #define WZRD_DIVCLK_DIVIDE_MASK (0xff << WZRD_DIVCLK_DIVIDE_SHIFT)
  30. #define WZRD_CLKOUT_DIVIDE_SHIFT 0
  31. #define WZRD_CLKOUT_DIVIDE_WIDTH 8
  32. #define WZRD_CLKOUT_DIVIDE_MASK (0xff << WZRD_DIVCLK_DIVIDE_SHIFT)
  33. #define WZRD_CLKOUT_FRAC_SHIFT 8
  34. #define WZRD_CLKOUT_FRAC_MASK 0x3ff
  35. #define WZRD_DR_MAX_INT_DIV_VALUE 255
  36. #define WZRD_DR_STATUS_REG_OFFSET 0x04
  37. #define WZRD_DR_LOCK_BIT_MASK 0x00000001
  38. #define WZRD_DR_INIT_REG_OFFSET 0x25C
  39. #define WZRD_DR_DIV_TO_PHASE_OFFSET 4
  40. #define WZRD_DR_BEGIN_DYNA_RECONF 0x03
  41. #define WZRD_DR_BEGIN_DYNA_RECONF_5_2 0x07
  42. #define WZRD_DR_BEGIN_DYNA_RECONF1_5_2 0x02
  43. #define WZRD_USEC_POLL 10
  44. #define WZRD_TIMEOUT_POLL 1000
  45. /* Get the mask from width */
  46. #define div_mask(width) ((1 << (width)) - 1)
  47. /* Extract divider instance from clock hardware instance */
  48. #define to_clk_wzrd_divider(_hw) container_of(_hw, struct clk_wzrd_divider, hw)
  49. enum clk_wzrd_int_clks {
  50. wzrd_clk_mul,
  51. wzrd_clk_mul_div,
  52. wzrd_clk_mul_frac,
  53. wzrd_clk_int_max
  54. };
  55. /**
  56. * struct clk_wzrd - Clock wizard private data structure
  57. *
  58. * @clk_data: Clock data
  59. * @nb: Notifier block
  60. * @base: Memory base
  61. * @clk_in1: Handle to input clock 'clk_in1'
  62. * @axi_clk: Handle to input clock 's_axi_aclk'
  63. * @clks_internal: Internal clocks
  64. * @clkout: Output clocks
  65. * @speed_grade: Speed grade of the device
  66. * @suspended: Flag indicating power state of the device
  67. */
  68. struct clk_wzrd {
  69. struct clk_onecell_data clk_data;
  70. struct notifier_block nb;
  71. void __iomem *base;
  72. struct clk *clk_in1;
  73. struct clk *axi_clk;
  74. struct clk *clks_internal[wzrd_clk_int_max];
  75. struct clk *clkout[WZRD_NUM_OUTPUTS];
  76. unsigned int speed_grade;
  77. bool suspended;
  78. };
  79. /**
  80. * struct clk_wzrd_divider - clock divider specific to clk_wzrd
  81. *
  82. * @hw: handle between common and hardware-specific interfaces
  83. * @base: base address of register containing the divider
  84. * @offset: offset address of register containing the divider
  85. * @shift: shift to the divider bit field
  86. * @width: width of the divider bit field
  87. * @flags: clk_wzrd divider flags
  88. * @table: array of value/divider pairs, last entry should have div = 0
  89. * @lock: register lock
  90. */
  91. struct clk_wzrd_divider {
  92. struct clk_hw hw;
  93. void __iomem *base;
  94. u16 offset;
  95. u8 shift;
  96. u8 width;
  97. u8 flags;
  98. const struct clk_div_table *table;
  99. spinlock_t *lock; /* divider lock */
  100. };
  101. #define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb)
  102. /* maximum frequencies for input/output clocks per speed grade */
  103. static const unsigned long clk_wzrd_max_freq[] = {
  104. 800000000UL,
  105. 933000000UL,
  106. 1066000000UL
  107. };
  108. /* spin lock variable for clk_wzrd */
  109. static DEFINE_SPINLOCK(clkwzrd_lock);
  110. static unsigned long clk_wzrd_recalc_rate(struct clk_hw *hw,
  111. unsigned long parent_rate)
  112. {
  113. struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
  114. void __iomem *div_addr = divider->base + divider->offset;
  115. unsigned int val;
  116. val = readl(div_addr) >> divider->shift;
  117. val &= div_mask(divider->width);
  118. return divider_recalc_rate(hw, parent_rate, val, divider->table,
  119. divider->flags, divider->width);
  120. }
  121. static int clk_wzrd_dynamic_reconfig(struct clk_hw *hw, unsigned long rate,
  122. unsigned long parent_rate)
  123. {
  124. int err;
  125. u32 value;
  126. unsigned long flags = 0;
  127. struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
  128. void __iomem *div_addr = divider->base + divider->offset;
  129. if (divider->lock)
  130. spin_lock_irqsave(divider->lock, flags);
  131. else
  132. __acquire(divider->lock);
  133. value = DIV_ROUND_CLOSEST(parent_rate, rate);
  134. /* Cap the value to max */
  135. min_t(u32, value, WZRD_DR_MAX_INT_DIV_VALUE);
  136. /* Set divisor and clear phase offset */
  137. writel(value, div_addr);
  138. writel(0x00, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET);
  139. /* Check status register */
  140. err = readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET,
  141. value, value & WZRD_DR_LOCK_BIT_MASK,
  142. WZRD_USEC_POLL, WZRD_TIMEOUT_POLL);
  143. if (err)
  144. goto err_reconfig;
  145. /* Initiate reconfiguration */
  146. writel(WZRD_DR_BEGIN_DYNA_RECONF_5_2,
  147. divider->base + WZRD_DR_INIT_REG_OFFSET);
  148. writel(WZRD_DR_BEGIN_DYNA_RECONF1_5_2,
  149. divider->base + WZRD_DR_INIT_REG_OFFSET);
  150. /* Check status register */
  151. err = readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET,
  152. value, value & WZRD_DR_LOCK_BIT_MASK,
  153. WZRD_USEC_POLL, WZRD_TIMEOUT_POLL);
  154. err_reconfig:
  155. if (divider->lock)
  156. spin_unlock_irqrestore(divider->lock, flags);
  157. else
  158. __release(divider->lock);
  159. return err;
  160. }
  161. static long clk_wzrd_round_rate(struct clk_hw *hw, unsigned long rate,
  162. unsigned long *prate)
  163. {
  164. u8 div;
  165. /*
  166. * since we don't change parent rate we just round rate to closest
  167. * achievable
  168. */
  169. div = DIV_ROUND_CLOSEST(*prate, rate);
  170. return *prate / div;
  171. }
  172. static const struct clk_ops clk_wzrd_clk_divider_ops = {
  173. .round_rate = clk_wzrd_round_rate,
  174. .set_rate = clk_wzrd_dynamic_reconfig,
  175. .recalc_rate = clk_wzrd_recalc_rate,
  176. };
  177. static unsigned long clk_wzrd_recalc_ratef(struct clk_hw *hw,
  178. unsigned long parent_rate)
  179. {
  180. unsigned int val;
  181. u32 div, frac;
  182. struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
  183. void __iomem *div_addr = divider->base + divider->offset;
  184. val = readl(div_addr);
  185. div = val & div_mask(divider->width);
  186. frac = (val >> WZRD_CLKOUT_FRAC_SHIFT) & WZRD_CLKOUT_FRAC_MASK;
  187. return mult_frac(parent_rate, 1000, (div * 1000) + frac);
  188. }
  189. static int clk_wzrd_dynamic_reconfig_f(struct clk_hw *hw, unsigned long rate,
  190. unsigned long parent_rate)
  191. {
  192. int err;
  193. u32 value, pre;
  194. unsigned long rate_div, f, clockout0_div;
  195. struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
  196. void __iomem *div_addr = divider->base + divider->offset;
  197. rate_div = DIV_ROUND_DOWN_ULL(parent_rate * 1000, rate);
  198. clockout0_div = rate_div / 1000;
  199. pre = DIV_ROUND_CLOSEST((parent_rate * 1000), rate);
  200. f = (u32)(pre - (clockout0_div * 1000));
  201. f = f & WZRD_CLKOUT_FRAC_MASK;
  202. f = f << WZRD_CLKOUT_DIVIDE_WIDTH;
  203. value = (f | (clockout0_div & WZRD_CLKOUT_DIVIDE_MASK));
  204. /* Set divisor and clear phase offset */
  205. writel(value, div_addr);
  206. writel(0x0, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET);
  207. /* Check status register */
  208. err = readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, value,
  209. value & WZRD_DR_LOCK_BIT_MASK,
  210. WZRD_USEC_POLL, WZRD_TIMEOUT_POLL);
  211. if (err)
  212. return err;
  213. /* Initiate reconfiguration */
  214. writel(WZRD_DR_BEGIN_DYNA_RECONF_5_2,
  215. divider->base + WZRD_DR_INIT_REG_OFFSET);
  216. writel(WZRD_DR_BEGIN_DYNA_RECONF1_5_2,
  217. divider->base + WZRD_DR_INIT_REG_OFFSET);
  218. /* Check status register */
  219. return readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, value,
  220. value & WZRD_DR_LOCK_BIT_MASK,
  221. WZRD_USEC_POLL, WZRD_TIMEOUT_POLL);
  222. }
  223. static long clk_wzrd_round_rate_f(struct clk_hw *hw, unsigned long rate,
  224. unsigned long *prate)
  225. {
  226. return rate;
  227. }
  228. static const struct clk_ops clk_wzrd_clk_divider_ops_f = {
  229. .round_rate = clk_wzrd_round_rate_f,
  230. .set_rate = clk_wzrd_dynamic_reconfig_f,
  231. .recalc_rate = clk_wzrd_recalc_ratef,
  232. };
  233. static struct clk *clk_wzrd_register_divf(struct device *dev,
  234. const char *name,
  235. const char *parent_name,
  236. unsigned long flags,
  237. void __iomem *base, u16 offset,
  238. u8 shift, u8 width,
  239. u8 clk_divider_flags,
  240. const struct clk_div_table *table,
  241. spinlock_t *lock)
  242. {
  243. struct clk_wzrd_divider *div;
  244. struct clk_hw *hw;
  245. struct clk_init_data init;
  246. int ret;
  247. div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
  248. if (!div)
  249. return ERR_PTR(-ENOMEM);
  250. init.name = name;
  251. init.ops = &clk_wzrd_clk_divider_ops_f;
  252. init.flags = flags;
  253. init.parent_names = &parent_name;
  254. init.num_parents = 1;
  255. div->base = base;
  256. div->offset = offset;
  257. div->shift = shift;
  258. div->width = width;
  259. div->flags = clk_divider_flags;
  260. div->lock = lock;
  261. div->hw.init = &init;
  262. div->table = table;
  263. hw = &div->hw;
  264. ret = devm_clk_hw_register(dev, hw);
  265. if (ret)
  266. return ERR_PTR(ret);
  267. return hw->clk;
  268. }
  269. static struct clk *clk_wzrd_register_divider(struct device *dev,
  270. const char *name,
  271. const char *parent_name,
  272. unsigned long flags,
  273. void __iomem *base, u16 offset,
  274. u8 shift, u8 width,
  275. u8 clk_divider_flags,
  276. const struct clk_div_table *table,
  277. spinlock_t *lock)
  278. {
  279. struct clk_wzrd_divider *div;
  280. struct clk_hw *hw;
  281. struct clk_init_data init;
  282. int ret;
  283. div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
  284. if (!div)
  285. return ERR_PTR(-ENOMEM);
  286. init.name = name;
  287. init.ops = &clk_wzrd_clk_divider_ops;
  288. init.flags = flags;
  289. init.parent_names = &parent_name;
  290. init.num_parents = 1;
  291. div->base = base;
  292. div->offset = offset;
  293. div->shift = shift;
  294. div->width = width;
  295. div->flags = clk_divider_flags;
  296. div->lock = lock;
  297. div->hw.init = &init;
  298. div->table = table;
  299. hw = &div->hw;
  300. ret = devm_clk_hw_register(dev, hw);
  301. if (ret)
  302. return ERR_PTR(ret);
  303. return hw->clk;
  304. }
  305. static int clk_wzrd_clk_notifier(struct notifier_block *nb, unsigned long event,
  306. void *data)
  307. {
  308. unsigned long max;
  309. struct clk_notifier_data *ndata = data;
  310. struct clk_wzrd *clk_wzrd = to_clk_wzrd(nb);
  311. if (clk_wzrd->suspended)
  312. return NOTIFY_OK;
  313. if (ndata->clk == clk_wzrd->clk_in1)
  314. max = clk_wzrd_max_freq[clk_wzrd->speed_grade - 1];
  315. else if (ndata->clk == clk_wzrd->axi_clk)
  316. max = WZRD_ACLK_MAX_FREQ;
  317. else
  318. return NOTIFY_DONE; /* should never happen */
  319. switch (event) {
  320. case PRE_RATE_CHANGE:
  321. if (ndata->new_rate > max)
  322. return NOTIFY_BAD;
  323. return NOTIFY_OK;
  324. case POST_RATE_CHANGE:
  325. case ABORT_RATE_CHANGE:
  326. default:
  327. return NOTIFY_DONE;
  328. }
  329. }
  330. static int __maybe_unused clk_wzrd_suspend(struct device *dev)
  331. {
  332. struct clk_wzrd *clk_wzrd = dev_get_drvdata(dev);
  333. clk_disable_unprepare(clk_wzrd->axi_clk);
  334. clk_wzrd->suspended = true;
  335. return 0;
  336. }
  337. static int __maybe_unused clk_wzrd_resume(struct device *dev)
  338. {
  339. int ret;
  340. struct clk_wzrd *clk_wzrd = dev_get_drvdata(dev);
  341. ret = clk_prepare_enable(clk_wzrd->axi_clk);
  342. if (ret) {
  343. dev_err(dev, "unable to enable s_axi_aclk\n");
  344. return ret;
  345. }
  346. clk_wzrd->suspended = false;
  347. return 0;
  348. }
  349. static SIMPLE_DEV_PM_OPS(clk_wzrd_dev_pm_ops, clk_wzrd_suspend,
  350. clk_wzrd_resume);
  351. static int clk_wzrd_probe(struct platform_device *pdev)
  352. {
  353. int i, ret;
  354. u32 reg, reg_f, mult;
  355. unsigned long rate;
  356. const char *clk_name;
  357. void __iomem *ctrl_reg;
  358. struct clk_wzrd *clk_wzrd;
  359. struct device_node *np = pdev->dev.of_node;
  360. int nr_outputs;
  361. unsigned long flags = 0;
  362. clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL);
  363. if (!clk_wzrd)
  364. return -ENOMEM;
  365. platform_set_drvdata(pdev, clk_wzrd);
  366. clk_wzrd->base = devm_platform_ioremap_resource(pdev, 0);
  367. if (IS_ERR(clk_wzrd->base))
  368. return PTR_ERR(clk_wzrd->base);
  369. ret = of_property_read_u32(np, "xlnx,speed-grade", &clk_wzrd->speed_grade);
  370. if (!ret) {
  371. if (clk_wzrd->speed_grade < 1 || clk_wzrd->speed_grade > 3) {
  372. dev_warn(&pdev->dev, "invalid speed grade '%d'\n",
  373. clk_wzrd->speed_grade);
  374. clk_wzrd->speed_grade = 0;
  375. }
  376. }
  377. clk_wzrd->clk_in1 = devm_clk_get(&pdev->dev, "clk_in1");
  378. if (IS_ERR(clk_wzrd->clk_in1))
  379. return dev_err_probe(&pdev->dev, PTR_ERR(clk_wzrd->clk_in1),
  380. "clk_in1 not found\n");
  381. clk_wzrd->axi_clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
  382. if (IS_ERR(clk_wzrd->axi_clk))
  383. return dev_err_probe(&pdev->dev, PTR_ERR(clk_wzrd->axi_clk),
  384. "s_axi_aclk not found\n");
  385. ret = clk_prepare_enable(clk_wzrd->axi_clk);
  386. if (ret) {
  387. dev_err(&pdev->dev, "enabling s_axi_aclk failed\n");
  388. return ret;
  389. }
  390. rate = clk_get_rate(clk_wzrd->axi_clk);
  391. if (rate > WZRD_ACLK_MAX_FREQ) {
  392. dev_err(&pdev->dev, "s_axi_aclk frequency (%lu) too high\n",
  393. rate);
  394. ret = -EINVAL;
  395. goto err_disable_clk;
  396. }
  397. reg = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0));
  398. reg_f = reg & WZRD_CLKFBOUT_FRAC_MASK;
  399. reg_f = reg_f >> WZRD_CLKFBOUT_FRAC_SHIFT;
  400. reg = reg & WZRD_CLKFBOUT_MULT_MASK;
  401. reg = reg >> WZRD_CLKFBOUT_MULT_SHIFT;
  402. mult = (reg * 1000) + reg_f;
  403. clk_name = kasprintf(GFP_KERNEL, "%s_mul", dev_name(&pdev->dev));
  404. if (!clk_name) {
  405. ret = -ENOMEM;
  406. goto err_disable_clk;
  407. }
  408. ret = of_property_read_u32(np, "xlnx,nr-outputs", &nr_outputs);
  409. if (ret || nr_outputs > WZRD_NUM_OUTPUTS) {
  410. ret = -EINVAL;
  411. goto err_disable_clk;
  412. }
  413. if (nr_outputs == 1)
  414. flags = CLK_SET_RATE_PARENT;
  415. clk_wzrd->clks_internal[wzrd_clk_mul] = clk_register_fixed_factor
  416. (&pdev->dev, clk_name,
  417. __clk_get_name(clk_wzrd->clk_in1),
  418. 0, mult, 1000);
  419. if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul])) {
  420. dev_err(&pdev->dev, "unable to register fixed-factor clock\n");
  421. ret = PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul]);
  422. goto err_disable_clk;
  423. }
  424. clk_name = kasprintf(GFP_KERNEL, "%s_mul_div", dev_name(&pdev->dev));
  425. if (!clk_name) {
  426. ret = -ENOMEM;
  427. goto err_rm_int_clk;
  428. }
  429. ctrl_reg = clk_wzrd->base + WZRD_CLK_CFG_REG(0);
  430. /* register div */
  431. clk_wzrd->clks_internal[wzrd_clk_mul_div] = clk_register_divider
  432. (&pdev->dev, clk_name,
  433. __clk_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]),
  434. flags, ctrl_reg, 0, 8, CLK_DIVIDER_ONE_BASED |
  435. CLK_DIVIDER_ALLOW_ZERO, &clkwzrd_lock);
  436. if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div])) {
  437. dev_err(&pdev->dev, "unable to register divider clock\n");
  438. ret = PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div]);
  439. goto err_rm_int_clk;
  440. }
  441. /* register div per output */
  442. for (i = nr_outputs - 1; i >= 0 ; i--) {
  443. const char *clkout_name;
  444. clkout_name = kasprintf(GFP_KERNEL, "%s_out%d", dev_name(&pdev->dev), i);
  445. if (!clkout_name) {
  446. ret = -ENOMEM;
  447. goto err_rm_int_clk;
  448. }
  449. if (!i)
  450. clk_wzrd->clkout[i] = clk_wzrd_register_divf
  451. (&pdev->dev, clkout_name,
  452. clk_name, flags,
  453. clk_wzrd->base, (WZRD_CLK_CFG_REG(2) + i * 12),
  454. WZRD_CLKOUT_DIVIDE_SHIFT,
  455. WZRD_CLKOUT_DIVIDE_WIDTH,
  456. CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
  457. NULL, &clkwzrd_lock);
  458. else
  459. clk_wzrd->clkout[i] = clk_wzrd_register_divider
  460. (&pdev->dev, clkout_name,
  461. clk_name, 0,
  462. clk_wzrd->base, (WZRD_CLK_CFG_REG(2) + i * 12),
  463. WZRD_CLKOUT_DIVIDE_SHIFT,
  464. WZRD_CLKOUT_DIVIDE_WIDTH,
  465. CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
  466. NULL, &clkwzrd_lock);
  467. if (IS_ERR(clk_wzrd->clkout[i])) {
  468. int j;
  469. for (j = i + 1; j < nr_outputs; j++)
  470. clk_unregister(clk_wzrd->clkout[j]);
  471. dev_err(&pdev->dev,
  472. "unable to register divider clock\n");
  473. ret = PTR_ERR(clk_wzrd->clkout[i]);
  474. goto err_rm_int_clks;
  475. }
  476. }
  477. kfree(clk_name);
  478. clk_wzrd->clk_data.clks = clk_wzrd->clkout;
  479. clk_wzrd->clk_data.clk_num = ARRAY_SIZE(clk_wzrd->clkout);
  480. of_clk_add_provider(np, of_clk_src_onecell_get, &clk_wzrd->clk_data);
  481. if (clk_wzrd->speed_grade) {
  482. clk_wzrd->nb.notifier_call = clk_wzrd_clk_notifier;
  483. ret = clk_notifier_register(clk_wzrd->clk_in1,
  484. &clk_wzrd->nb);
  485. if (ret)
  486. dev_warn(&pdev->dev,
  487. "unable to register clock notifier\n");
  488. ret = clk_notifier_register(clk_wzrd->axi_clk, &clk_wzrd->nb);
  489. if (ret)
  490. dev_warn(&pdev->dev,
  491. "unable to register clock notifier\n");
  492. }
  493. return 0;
  494. err_rm_int_clks:
  495. clk_unregister(clk_wzrd->clks_internal[1]);
  496. err_rm_int_clk:
  497. kfree(clk_name);
  498. clk_unregister(clk_wzrd->clks_internal[0]);
  499. err_disable_clk:
  500. clk_disable_unprepare(clk_wzrd->axi_clk);
  501. return ret;
  502. }
  503. static int clk_wzrd_remove(struct platform_device *pdev)
  504. {
  505. int i;
  506. struct clk_wzrd *clk_wzrd = platform_get_drvdata(pdev);
  507. of_clk_del_provider(pdev->dev.of_node);
  508. for (i = 0; i < WZRD_NUM_OUTPUTS; i++)
  509. clk_unregister(clk_wzrd->clkout[i]);
  510. for (i = 0; i < wzrd_clk_int_max; i++)
  511. clk_unregister(clk_wzrd->clks_internal[i]);
  512. if (clk_wzrd->speed_grade) {
  513. clk_notifier_unregister(clk_wzrd->axi_clk, &clk_wzrd->nb);
  514. clk_notifier_unregister(clk_wzrd->clk_in1, &clk_wzrd->nb);
  515. }
  516. clk_disable_unprepare(clk_wzrd->axi_clk);
  517. return 0;
  518. }
  519. static const struct of_device_id clk_wzrd_ids[] = {
  520. { .compatible = "xlnx,clocking-wizard" },
  521. { .compatible = "xlnx,clocking-wizard-v5.2" },
  522. { .compatible = "xlnx,clocking-wizard-v6.0" },
  523. { },
  524. };
  525. MODULE_DEVICE_TABLE(of, clk_wzrd_ids);
  526. static struct platform_driver clk_wzrd_driver = {
  527. .driver = {
  528. .name = "clk-wizard",
  529. .of_match_table = clk_wzrd_ids,
  530. .pm = &clk_wzrd_dev_pm_ops,
  531. },
  532. .probe = clk_wzrd_probe,
  533. .remove = clk_wzrd_remove,
  534. };
  535. module_platform_driver(clk_wzrd_driver);
  536. MODULE_LICENSE("GPL");
  537. MODULE_AUTHOR("Soeren Brinkmann <[email protected]");
  538. MODULE_DESCRIPTION("Driver for the Xilinx Clocking Wizard IP core");