linux-stable/drivers/clk/mediatek/clk-apmixed.c
Chen-Yu Tsai 6f691a5862 clk: mediatek: Switch to clk_hw provider APIs
As part of the effort to improve the MediaTek clk drivers, the next step
is to switch from the old 'struct clk' clk prodivder APIs to the new
'struct clk_hw' ones.

In a previous patch, 'struct clk_onecell_data' was replaced with
'struct clk_hw_onecell_data', with (struct clk_hw *)->clk and
__clk_get_hw() bridging the new data structures and old code.

Now switch from the old 'clk_(un)?register*()' APIs to the new
'clk_hw_(un)?register*()' ones. This is done with the coccinelle script
below.

Unfortunately this also leaves clk-mt8173.c with a compile error that
would need a coccinelle script longer than the actual diff to fix. This
last part is fixed up by hand.

    // Fix prototypes
    @@
    identifier F =~ "^mtk_clk_register_";
    @@
    - struct clk *
    + struct clk_hw *
      F(...);

    // Fix calls to mtk_clk_register_<singular>
    @ reg @
    identifier F =~ "^mtk_clk_register_";
    identifier FS =~ "^mtk_clk_register_[a-z_]*s";
    identifier I;
    expression clk_data;
    expression E;
    @@
      FS(...) {
	    ...
    -	struct clk *I;
    +	struct clk_hw *hw;
	    ...
	    for (...;...;...) {
		    ...
    (
    -		I
    +		hw
		    =
    -		clk_register_fixed_rate(
    +		clk_hw_register_fixed_rate(
					    ...
		    );
    |
    -		I
    +		hw
		    =
    -		clk_register_fixed_factor(
    +		clk_hw_register_fixed_factor(
					    ...
		    );
    |
    -		I
    +		hw
		    =
    -		clk_register_divider(
    +		clk_hw_register_divider(
					    ...
		    );
    |
    -		I
    +		hw
		    =
		    F(...);
    )
		    ...
		    if (
    -		    IS_ERR(I)
    +		    IS_ERR(hw)
		       ) {
			    pr_err(...,
    -			       I
    +			       hw
			    ,...);
			    ...
		    }

    -		clk_data->hws[E] = __clk_get_hw(I);
    +		clk_data->hws[E] = hw;
	    }
	    ...
      }

    @ depends on reg @
    identifier reg.I;
    @@
      return PTR_ERR(
    - I
    + hw
      );

    // Fix mtk_clk_register_composite to return clk_hw instead of clk
    @@
    identifier I, R;
    expression E;
    @@
    - struct clk *
    + struct clk_hw *
      mtk_clk_register_composite(...) {
	    ...
    -	struct clk *I;
    +	struct clk_hw *hw;
	    ...
    -	I = clk_register_composite(
    +	hw = clk_hw_register_composite(
		    ...);
	    if (IS_ERR(
    -		   I
    +		   hw
		       )) {
		    ...
		    R = PTR_ERR(
    -			      I
    +			      hw
				  );
		    ...
	    }

	    return
    -		I
    +		hw
	    ;
	    ...
      }

    // Fix other mtk_clk_register_<singular> to return clk_hw instead of clk
    @@
    identifier F =~ "^mtk_clk_register_";
    identifier I, D, C;
    expression E;
    @@
    - struct clk *
    + struct clk_hw *
      F(...) {
	    ...
    -	struct clk *I;
    +	int ret;
	    ...
    -	I = clk_register(D, E);
    +	ret = clk_hw_register(D, E);
	    ...
    (
    -	if (IS_ERR(I))
    +	if (ret) {
		    kfree(C);
    +		return ERR_PTR(ret);
    +	}
    |
    -	if (IS_ERR(I))
    +	if (ret)
	    {
		    kfree(C);
    -		return I;
    +		return ERR_PTR(ret);
	    }
    )

    -	return I;
    +	return E;
      }

    // Fix mtk_clk_unregister_<singular> to take clk_hw instead of clk
    @@
    identifier F =~ "^mtk_clk_unregister_";
    identifier I, I2;
    @@
      static void F(
    - 	struct clk *I
    +	struct clk_hw *I2
      )
      {
	    ...
    -	struct clk_hw *I2;
	    ...
    -	I2 = __clk_get_hw(I);
	    ...
    (
    -	clk_unregister(I);
    +	clk_hw_unregister(I2);
    |
    -	clk_unregister_composite(I);
    +	clk_hw_unregister_composite(I2);
    )
	    ...
      }

    // Fix calls to mtk_clk_unregister_*()
    @@
    identifier F =~ "^mtk_clk_unregister_";
    expression I;
    expression E;
    @@
    - F(I->hws[E]->clk);
    + F(I->hws[E]);

Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
Reviewed-by: Miles Chen <miles.chen@mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Tested-by: Miles Chen <miles.chen@mediatek.com>
Link: https://lore.kernel.org/r/20220519071610.423372-5-wenst@chromium.org
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
2022-05-19 16:57:57 -07:00

102 lines
2.1 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015 MediaTek Inc.
* Author: James Liao <jamesjj.liao@mediatek.com>
*/
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include "clk-mtk.h"
#define REF2USB_TX_EN BIT(0)
#define REF2USB_TX_LPF_EN BIT(1)
#define REF2USB_TX_OUT_EN BIT(2)
#define REF2USB_EN_MASK (REF2USB_TX_EN | REF2USB_TX_LPF_EN | \
REF2USB_TX_OUT_EN)
struct mtk_ref2usb_tx {
struct clk_hw hw;
void __iomem *base_addr;
};
static inline struct mtk_ref2usb_tx *to_mtk_ref2usb_tx(struct clk_hw *hw)
{
return container_of(hw, struct mtk_ref2usb_tx, hw);
}
static int mtk_ref2usb_tx_is_prepared(struct clk_hw *hw)
{
struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
return (readl(tx->base_addr) & REF2USB_EN_MASK) == REF2USB_EN_MASK;
}
static int mtk_ref2usb_tx_prepare(struct clk_hw *hw)
{
struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
u32 val;
val = readl(tx->base_addr);
val |= REF2USB_TX_EN;
writel(val, tx->base_addr);
udelay(100);
val |= REF2USB_TX_LPF_EN;
writel(val, tx->base_addr);
val |= REF2USB_TX_OUT_EN;
writel(val, tx->base_addr);
return 0;
}
static void mtk_ref2usb_tx_unprepare(struct clk_hw *hw)
{
struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
u32 val;
val = readl(tx->base_addr);
val &= ~REF2USB_EN_MASK;
writel(val, tx->base_addr);
}
static const struct clk_ops mtk_ref2usb_tx_ops = {
.is_prepared = mtk_ref2usb_tx_is_prepared,
.prepare = mtk_ref2usb_tx_prepare,
.unprepare = mtk_ref2usb_tx_unprepare,
};
struct clk_hw * __init mtk_clk_register_ref2usb_tx(const char *name,
const char *parent_name, void __iomem *reg)
{
struct mtk_ref2usb_tx *tx;
struct clk_init_data init = {};
int ret;
tx = kzalloc(sizeof(*tx), GFP_KERNEL);
if (!tx)
return ERR_PTR(-ENOMEM);
tx->base_addr = reg;
tx->hw.init = &init;
init.name = name;
init.ops = &mtk_ref2usb_tx_ops;
init.parent_names = &parent_name;
init.num_parents = 1;
ret = clk_hw_register(NULL, &tx->hw);
if (ret) {
kfree(tx);
return ERR_PTR(ret);
}
return &tx->hw;
}
MODULE_LICENSE("GPL");