root/drivers/clk/sprd/gate.h
/* SPDX-License-Identifier: GPL-2.0 */
//
// Spreadtrum gate clock driver
//
// Copyright (C) 2017 Spreadtrum, Inc.
// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>

#ifndef _SPRD_GATE_H_
#define _SPRD_GATE_H_

#include "common.h"

struct sprd_gate {
        u32                     enable_mask;
        u16                     flags;
        u16                     sc_offset;
        u16                     udelay;

        struct sprd_clk_common  common;
};

/*
 * sprd_gate->flags is used for:
 * CLK_GATE_SET_TO_DISABLE      BIT(0)
 * CLK_GATE_HIWORD_MASK         BIT(1)
 * CLK_GATE_BIG_ENDIAN          BIT(2)
 * so we define new flags from  BIT(3)
 */
#define SPRD_GATE_NON_AON BIT(3) /* not always powered on, check before read */

#define SPRD_SC_GATE_CLK_HW_INIT_FN(_struct, _name, _parent, _reg,      \
                                    _sc_offset, _enable_mask, _flags,   \
                                    _gate_flags, _udelay, _ops, _fn)    \
        struct sprd_gate _struct = {                                    \
                .enable_mask    = _enable_mask,                         \
                .sc_offset      = _sc_offset,                           \
                .flags          = _gate_flags,                          \
                .udelay         = _udelay,                              \
                .common = {                                             \
                        .regmap         = NULL,                         \
                        .reg            = _reg,                         \
                        .hw.init        = _fn(_name, _parent,           \
                                              _ops, _flags),            \
                }                                                       \
        }

#define SPRD_SC_GATE_CLK_OPS_UDELAY(_struct, _name, _parent, _reg,      \
                                    _sc_offset, _enable_mask, _flags,   \
                                    _gate_flags, _udelay, _ops)         \
        SPRD_SC_GATE_CLK_HW_INIT_FN(_struct, _name, _parent, _reg,      \
                                    _sc_offset, _enable_mask, _flags,   \
                                    _gate_flags, _udelay, _ops, CLK_HW_INIT)

#define SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, _sc_offset, \
                             _enable_mask, _flags, _gate_flags, _ops)   \
        SPRD_SC_GATE_CLK_OPS_UDELAY(_struct, _name, _parent, _reg,      \
                                    _sc_offset, _enable_mask, _flags,   \
                                    _gate_flags, 0, _ops)

#define SPRD_SC_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset,     \
                         _enable_mask, _flags, _gate_flags)             \
        SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, _sc_offset, \
                             _enable_mask, _flags, _gate_flags,         \
                             &sprd_sc_gate_ops)

#define SPRD_GATE_CLK(_struct, _name, _parent, _reg,                    \
                      _enable_mask, _flags, _gate_flags)                \
        SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, 0,          \
                             _enable_mask, _flags, _gate_flags,         \
                             &sprd_gate_ops)

#define SPRD_PLL_SC_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset, \
                             _enable_mask, _flags, _gate_flags,         \
                             _udelay)                                   \
        SPRD_SC_GATE_CLK_OPS_UDELAY(_struct, _name, _parent, _reg,      \
                                    _sc_offset, _enable_mask, _flags,   \
                                    _gate_flags, _udelay,               \
                                    &sprd_pll_sc_gate_ops)


#define SPRD_SC_GATE_CLK_HW_OPS_UDELAY(_struct, _name, _parent, _reg,   \
                                       _sc_offset, _enable_mask,        \
                                       _flags, _gate_flags,             \
                                       _udelay, _ops)                   \
        SPRD_SC_GATE_CLK_HW_INIT_FN(_struct, _name, _parent, _reg,      \
                                    _sc_offset, _enable_mask, _flags,   \
                                    _gate_flags, _udelay, _ops,         \
                                    CLK_HW_INIT_HW)

#define SPRD_SC_GATE_CLK_HW_OPS(_struct, _name, _parent, _reg,          \
                                _sc_offset, _enable_mask, _flags,       \
                                _gate_flags, _ops)                      \
        SPRD_SC_GATE_CLK_HW_OPS_UDELAY(_struct, _name, _parent, _reg,   \
                                       _sc_offset, _enable_mask,        \
                                       _flags, _gate_flags, 0, _ops)

#define SPRD_SC_GATE_CLK_HW(_struct, _name, _parent, _reg,              \
                            _sc_offset, _enable_mask, _flags,           \
                            _gate_flags)                                \
        SPRD_SC_GATE_CLK_HW_OPS(_struct, _name, _parent, _reg,          \
                                _sc_offset, _enable_mask, _flags,       \
                                _gate_flags, &sprd_sc_gate_ops)

#define SPRD_GATE_CLK_HW(_struct, _name, _parent, _reg,                 \
                         _enable_mask, _flags, _gate_flags)             \
        SPRD_SC_GATE_CLK_HW_OPS(_struct, _name, _parent, _reg, 0,       \
                                _enable_mask, _flags, _gate_flags,      \
                                &sprd_gate_ops)

#define SPRD_PLL_SC_GATE_CLK_HW(_struct, _name, _parent, _reg,          \
                                _sc_offset, _enable_mask, _flags,       \
                                _gate_flags, _udelay)                   \
        SPRD_SC_GATE_CLK_HW_OPS_UDELAY(_struct, _name, _parent, _reg,   \
                                       _sc_offset, _enable_mask,        \
                                       _flags, _gate_flags, _udelay,    \
                                       &sprd_pll_sc_gate_ops)

#define SPRD_SC_GATE_CLK_FW_NAME_OPS_UDELAY(_struct, _name, _parent,    \
                                            _reg, _sc_offset,           \
                                            _enable_mask, _flags,       \
                                            _gate_flags, _udelay, _ops) \
        SPRD_SC_GATE_CLK_HW_INIT_FN(_struct, _name, _parent, _reg,      \
                                    _sc_offset, _enable_mask, _flags,   \
                                    _gate_flags, _udelay, _ops,         \
                                    CLK_HW_INIT_FW_NAME)

#define SPRD_SC_GATE_CLK_FW_NAME_OPS(_struct, _name, _parent, _reg,     \
                                     _sc_offset, _enable_mask, _flags,  \
                                     _gate_flags, _ops)                 \
        SPRD_SC_GATE_CLK_FW_NAME_OPS_UDELAY(_struct, _name, _parent,    \
                                            _reg, _sc_offset,           \
                                            _enable_mask, _flags,       \
                                            _gate_flags, 0, _ops)

#define SPRD_SC_GATE_CLK_FW_NAME(_struct, _name, _parent, _reg,         \
                                 _sc_offset, _enable_mask, _flags,      \
                                 _gate_flags)                           \
        SPRD_SC_GATE_CLK_FW_NAME_OPS(_struct, _name, _parent, _reg,     \
                                     _sc_offset, _enable_mask, _flags,  \
                                     _gate_flags, &sprd_sc_gate_ops)

#define SPRD_GATE_CLK_FW_NAME(_struct, _name, _parent, _reg,            \
                              _enable_mask, _flags, _gate_flags)        \
        SPRD_SC_GATE_CLK_FW_NAME_OPS(_struct, _name, _parent, _reg, 0,  \
                                     _enable_mask, _flags, _gate_flags, \
                                     &sprd_gate_ops)

#define SPRD_PLL_SC_GATE_CLK_FW_NAME(_struct, _name, _parent, _reg,     \
                                     _sc_offset, _enable_mask, _flags,  \
                                     _gate_flags, _udelay)              \
        SPRD_SC_GATE_CLK_FW_NAME_OPS_UDELAY(_struct, _name, _parent,    \
                                            _reg, _sc_offset,           \
                                            _enable_mask, _flags,       \
                                            _gate_flags, _udelay,       \
                                            &sprd_pll_sc_gate_ops)

static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw)
{
        struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);

        return container_of(common, struct sprd_gate, common);
}

extern const struct clk_ops sprd_gate_ops;
extern const struct clk_ops sprd_sc_gate_ops;
extern const struct clk_ops sprd_pll_sc_gate_ops;

#endif /* _SPRD_GATE_H_ */