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