linux/drivers/clk/mediatek/clk-apmixed.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2015 MediaTek Inc.
   4 * Author: James Liao <jamesjj.liao@mediatek.com>
   5 */
   6
   7#include <linux/delay.h>
   8#include <linux/of_address.h>
   9#include <linux/slab.h>
  10
  11#include "clk-mtk.h"
  12
  13#define REF2USB_TX_EN           BIT(0)
  14#define REF2USB_TX_LPF_EN       BIT(1)
  15#define REF2USB_TX_OUT_EN       BIT(2)
  16#define REF2USB_EN_MASK         (REF2USB_TX_EN | REF2USB_TX_LPF_EN | \
  17                                 REF2USB_TX_OUT_EN)
  18
  19struct mtk_ref2usb_tx {
  20        struct clk_hw   hw;
  21        void __iomem    *base_addr;
  22};
  23
  24static inline struct mtk_ref2usb_tx *to_mtk_ref2usb_tx(struct clk_hw *hw)
  25{
  26        return container_of(hw, struct mtk_ref2usb_tx, hw);
  27}
  28
  29static int mtk_ref2usb_tx_is_prepared(struct clk_hw *hw)
  30{
  31        struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
  32
  33        return (readl(tx->base_addr) & REF2USB_EN_MASK) == REF2USB_EN_MASK;
  34}
  35
  36static int mtk_ref2usb_tx_prepare(struct clk_hw *hw)
  37{
  38        struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
  39        u32 val;
  40
  41        val = readl(tx->base_addr);
  42
  43        val |= REF2USB_TX_EN;
  44        writel(val, tx->base_addr);
  45        udelay(100);
  46
  47        val |= REF2USB_TX_LPF_EN;
  48        writel(val, tx->base_addr);
  49
  50        val |= REF2USB_TX_OUT_EN;
  51        writel(val, tx->base_addr);
  52
  53        return 0;
  54}
  55
  56static void mtk_ref2usb_tx_unprepare(struct clk_hw *hw)
  57{
  58        struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
  59        u32 val;
  60
  61        val = readl(tx->base_addr);
  62        val &= ~REF2USB_EN_MASK;
  63        writel(val, tx->base_addr);
  64}
  65
  66static const struct clk_ops mtk_ref2usb_tx_ops = {
  67        .is_prepared    = mtk_ref2usb_tx_is_prepared,
  68        .prepare        = mtk_ref2usb_tx_prepare,
  69        .unprepare      = mtk_ref2usb_tx_unprepare,
  70};
  71
  72struct clk * __init mtk_clk_register_ref2usb_tx(const char *name,
  73                        const char *parent_name, void __iomem *reg)
  74{
  75        struct mtk_ref2usb_tx *tx;
  76        struct clk_init_data init = {};
  77        struct clk *clk;
  78
  79        tx = kzalloc(sizeof(*tx), GFP_KERNEL);
  80        if (!tx)
  81                return ERR_PTR(-ENOMEM);
  82
  83        tx->base_addr = reg;
  84        tx->hw.init = &init;
  85
  86        init.name = name;
  87        init.ops = &mtk_ref2usb_tx_ops;
  88        init.parent_names = &parent_name;
  89        init.num_parents = 1;
  90
  91        clk = clk_register(NULL, &tx->hw);
  92
  93        if (IS_ERR(clk)) {
  94                pr_err("Failed to register clk %s: %ld\n", name, PTR_ERR(clk));
  95                kfree(tx);
  96        }
  97
  98        return clk;
  99}
 100