400 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * WM831x clock control4 *5 * Copyright 2011-2 Wolfson Microelectronics PLC.6 *7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>8 */9 10#include <linux/clk-provider.h>11#include <linux/delay.h>12#include <linux/module.h>13#include <linux/slab.h>14#include <linux/platform_device.h>15#include <linux/mfd/wm831x/core.h>16 17struct wm831x_clk {18 struct wm831x *wm831x;19 struct clk_hw xtal_hw;20 struct clk_hw fll_hw;21 struct clk_hw clkout_hw;22 bool xtal_ena;23};24 25static int wm831x_xtal_is_prepared(struct clk_hw *hw)26{27 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,28 xtal_hw);29 30 return clkdata->xtal_ena;31}32 33static unsigned long wm831x_xtal_recalc_rate(struct clk_hw *hw,34 unsigned long parent_rate)35{36 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,37 xtal_hw);38 39 if (clkdata->xtal_ena)40 return 32768;41 else42 return 0;43}44 45static const struct clk_ops wm831x_xtal_ops = {46 .is_prepared = wm831x_xtal_is_prepared,47 .recalc_rate = wm831x_xtal_recalc_rate,48};49 50static const struct clk_init_data wm831x_xtal_init = {51 .name = "xtal",52 .ops = &wm831x_xtal_ops,53};54 55static const unsigned long wm831x_fll_auto_rates[] = {56 2048000,57 11289600,58 12000000,59 12288000,60 19200000,61 22579600,62 24000000,63 24576000,64};65 66static int wm831x_fll_is_prepared(struct clk_hw *hw)67{68 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,69 fll_hw);70 struct wm831x *wm831x = clkdata->wm831x;71 int ret;72 73 ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_1);74 if (ret < 0) {75 dev_err(wm831x->dev, "Unable to read FLL_CONTROL_1: %d\n",76 ret);77 return true;78 }79 80 return (ret & WM831X_FLL_ENA) != 0;81}82 83static int wm831x_fll_prepare(struct clk_hw *hw)84{85 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,86 fll_hw);87 struct wm831x *wm831x = clkdata->wm831x;88 int ret;89 90 ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_1,91 WM831X_FLL_ENA, WM831X_FLL_ENA);92 if (ret != 0)93 dev_crit(wm831x->dev, "Failed to enable FLL: %d\n", ret);94 95 /* wait 2-3 ms for new frequency taking effect */96 usleep_range(2000, 3000);97 98 return ret;99}100 101static void wm831x_fll_unprepare(struct clk_hw *hw)102{103 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,104 fll_hw);105 struct wm831x *wm831x = clkdata->wm831x;106 int ret;107 108 ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_1, WM831X_FLL_ENA, 0);109 if (ret != 0)110 dev_crit(wm831x->dev, "Failed to disable FLL: %d\n", ret);111}112 113static unsigned long wm831x_fll_recalc_rate(struct clk_hw *hw,114 unsigned long parent_rate)115{116 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,117 fll_hw);118 struct wm831x *wm831x = clkdata->wm831x;119 int ret;120 121 ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);122 if (ret < 0) {123 dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",124 ret);125 return 0;126 }127 128 if (ret & WM831X_FLL_AUTO)129 return wm831x_fll_auto_rates[ret & WM831X_FLL_AUTO_FREQ_MASK];130 131 dev_err(wm831x->dev, "FLL only supported in AUTO mode\n");132 133 return 0;134}135 136static long wm831x_fll_round_rate(struct clk_hw *hw, unsigned long rate,137 unsigned long *unused)138{139 int best = 0;140 int i;141 142 for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)143 if (abs(wm831x_fll_auto_rates[i] - rate) <144 abs(wm831x_fll_auto_rates[best] - rate))145 best = i;146 147 return wm831x_fll_auto_rates[best];148}149 150static int wm831x_fll_set_rate(struct clk_hw *hw, unsigned long rate,151 unsigned long parent_rate)152{153 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,154 fll_hw);155 struct wm831x *wm831x = clkdata->wm831x;156 int i;157 158 for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)159 if (wm831x_fll_auto_rates[i] == rate)160 break;161 if (i == ARRAY_SIZE(wm831x_fll_auto_rates))162 return -EINVAL;163 164 if (wm831x_fll_is_prepared(hw))165 return -EPERM;166 167 return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_2,168 WM831X_FLL_AUTO_FREQ_MASK, i);169}170 171static const char *wm831x_fll_parents[] = {172 "xtal",173 "clkin",174};175 176static u8 wm831x_fll_get_parent(struct clk_hw *hw)177{178 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,179 fll_hw);180 struct wm831x *wm831x = clkdata->wm831x;181 int ret;182 183 /* AUTO mode is always clocked from the crystal */184 ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);185 if (ret < 0) {186 dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",187 ret);188 return 0;189 }190 191 if (ret & WM831X_FLL_AUTO)192 return 0;193 194 ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_5);195 if (ret < 0) {196 dev_err(wm831x->dev, "Unable to read FLL_CONTROL_5: %d\n",197 ret);198 return 0;199 }200 201 switch (ret & WM831X_FLL_CLK_SRC_MASK) {202 case 0:203 return 0;204 case 1:205 return 1;206 default:207 dev_err(wm831x->dev, "Unsupported FLL clock source %d\n",208 ret & WM831X_FLL_CLK_SRC_MASK);209 return 0;210 }211}212 213static const struct clk_ops wm831x_fll_ops = {214 .is_prepared = wm831x_fll_is_prepared,215 .prepare = wm831x_fll_prepare,216 .unprepare = wm831x_fll_unprepare,217 .round_rate = wm831x_fll_round_rate,218 .recalc_rate = wm831x_fll_recalc_rate,219 .set_rate = wm831x_fll_set_rate,220 .get_parent = wm831x_fll_get_parent,221};222 223static const struct clk_init_data wm831x_fll_init = {224 .name = "fll",225 .ops = &wm831x_fll_ops,226 .parent_names = wm831x_fll_parents,227 .num_parents = ARRAY_SIZE(wm831x_fll_parents),228 .flags = CLK_SET_RATE_GATE,229};230 231static int wm831x_clkout_is_prepared(struct clk_hw *hw)232{233 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,234 clkout_hw);235 struct wm831x *wm831x = clkdata->wm831x;236 int ret;237 238 ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);239 if (ret < 0) {240 dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",241 ret);242 return false;243 }244 245 return (ret & WM831X_CLKOUT_ENA) != 0;246}247 248static int wm831x_clkout_prepare(struct clk_hw *hw)249{250 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,251 clkout_hw);252 struct wm831x *wm831x = clkdata->wm831x;253 int ret;254 255 ret = wm831x_reg_unlock(wm831x);256 if (ret != 0) {257 dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);258 return ret;259 }260 261 ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,262 WM831X_CLKOUT_ENA, WM831X_CLKOUT_ENA);263 if (ret != 0)264 dev_crit(wm831x->dev, "Failed to enable CLKOUT: %d\n", ret);265 266 wm831x_reg_lock(wm831x);267 268 return ret;269}270 271static void wm831x_clkout_unprepare(struct clk_hw *hw)272{273 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,274 clkout_hw);275 struct wm831x *wm831x = clkdata->wm831x;276 int ret;277 278 ret = wm831x_reg_unlock(wm831x);279 if (ret != 0) {280 dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);281 return;282 }283 284 ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,285 WM831X_CLKOUT_ENA, 0);286 if (ret != 0)287 dev_crit(wm831x->dev, "Failed to disable CLKOUT: %d\n", ret);288 289 wm831x_reg_lock(wm831x);290}291 292static const char *wm831x_clkout_parents[] = {293 "fll",294 "xtal",295};296 297static u8 wm831x_clkout_get_parent(struct clk_hw *hw)298{299 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,300 clkout_hw);301 struct wm831x *wm831x = clkdata->wm831x;302 int ret;303 304 ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);305 if (ret < 0) {306 dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",307 ret);308 return 0;309 }310 311 if (ret & WM831X_CLKOUT_SRC)312 return 1;313 else314 return 0;315}316 317static int wm831x_clkout_set_parent(struct clk_hw *hw, u8 parent)318{319 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,320 clkout_hw);321 struct wm831x *wm831x = clkdata->wm831x;322 323 return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,324 WM831X_CLKOUT_SRC,325 parent << WM831X_CLKOUT_SRC_SHIFT);326}327 328static const struct clk_ops wm831x_clkout_ops = {329 .is_prepared = wm831x_clkout_is_prepared,330 .prepare = wm831x_clkout_prepare,331 .unprepare = wm831x_clkout_unprepare,332 .determine_rate = clk_hw_determine_rate_no_reparent,333 .get_parent = wm831x_clkout_get_parent,334 .set_parent = wm831x_clkout_set_parent,335};336 337static const struct clk_init_data wm831x_clkout_init = {338 .name = "clkout",339 .ops = &wm831x_clkout_ops,340 .parent_names = wm831x_clkout_parents,341 .num_parents = ARRAY_SIZE(wm831x_clkout_parents),342 .flags = CLK_SET_RATE_PARENT,343};344 345static int wm831x_clk_probe(struct platform_device *pdev)346{347 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);348 struct wm831x_clk *clkdata;349 int ret;350 351 clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL);352 if (!clkdata)353 return -ENOMEM;354 355 clkdata->wm831x = wm831x;356 357 /* XTAL_ENA can only be set via OTP/InstantConfig so just read once */358 ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);359 if (ret < 0) {360 dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",361 ret);362 return ret;363 }364 clkdata->xtal_ena = ret & WM831X_XTAL_ENA;365 366 clkdata->xtal_hw.init = &wm831x_xtal_init;367 ret = devm_clk_hw_register(&pdev->dev, &clkdata->xtal_hw);368 if (ret)369 return ret;370 371 clkdata->fll_hw.init = &wm831x_fll_init;372 ret = devm_clk_hw_register(&pdev->dev, &clkdata->fll_hw);373 if (ret)374 return ret;375 376 clkdata->clkout_hw.init = &wm831x_clkout_init;377 ret = devm_clk_hw_register(&pdev->dev, &clkdata->clkout_hw);378 if (ret)379 return ret;380 381 platform_set_drvdata(pdev, clkdata);382 383 return 0;384}385 386static struct platform_driver wm831x_clk_driver = {387 .probe = wm831x_clk_probe,388 .driver = {389 .name = "wm831x-clk",390 },391};392 393module_platform_driver(wm831x_clk_driver);394 395/* Module information */396MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");397MODULE_DESCRIPTION("WM831x clock driver");398MODULE_LICENSE("GPL");399MODULE_ALIAS("platform:wm831x-clk");400