Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Copyright (c) 2016 Maxime Ripard. All rights reserved.
0004  */
0005 
0006 #ifndef _CCU_DIV_H_
0007 #define _CCU_DIV_H_
0008 
0009 #include <linux/clk-provider.h>
0010 
0011 #include "ccu_common.h"
0012 #include "ccu_mux.h"
0013 
0014 /**
0015  * struct ccu_div_internal - Internal divider description
0016  * @shift: Bit offset of the divider in its register
0017  * @width: Width of the divider field in its register
0018  * @max: Maximum value allowed for that divider. This is the
0019  *       arithmetic value, not the maximum value to be set in the
0020  *       register.
0021  * @flags: clk_divider flags to apply on this divider
0022  * @table: Divider table pointer (if applicable)
0023  *
0024  * That structure represents a single divider, and is meant to be
0025  * embedded in other structures representing the various clock
0026  * classes.
0027  *
0028  * It is basically a wrapper around the clk_divider functions
0029  * arguments.
0030  */
0031 struct ccu_div_internal {
0032     u8          shift;
0033     u8          width;
0034 
0035     u32         max;
0036     u32         offset;
0037 
0038     u32         flags;
0039 
0040     struct clk_div_table    *table;
0041 };
0042 
0043 #define _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, _flags)  \
0044     {                               \
0045         .shift  = _shift,                   \
0046         .width  = _width,                   \
0047         .flags  = _flags,                   \
0048         .table  = _table,                   \
0049     }
0050 
0051 #define _SUNXI_CCU_DIV_TABLE(_shift, _width, _table)            \
0052     _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, 0)
0053 
0054 #define _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _off, _max, _flags) \
0055     {                               \
0056         .shift  = _shift,                   \
0057         .width  = _width,                   \
0058         .flags  = _flags,                   \
0059         .max    = _max,                     \
0060         .offset = _off,                     \
0061     }
0062 
0063 #define _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, _flags)      \
0064     _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, 1, _max, _flags)
0065 
0066 #define _SUNXI_CCU_DIV_FLAGS(_shift, _width, _flags)            \
0067     _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, 0, _flags)
0068 
0069 #define _SUNXI_CCU_DIV_MAX(_shift, _width, _max)            \
0070     _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, 0)
0071 
0072 #define _SUNXI_CCU_DIV_OFFSET(_shift, _width, _offset)          \
0073     _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _offset, 0, 0)
0074 
0075 #define _SUNXI_CCU_DIV(_shift, _width)                  \
0076     _SUNXI_CCU_DIV_FLAGS(_shift, _width, 0)
0077 
0078 struct ccu_div {
0079     u32         enable;
0080 
0081     struct ccu_div_internal div;
0082     struct ccu_mux_internal mux;
0083     struct ccu_common   common;
0084     unsigned int        fixed_post_div;
0085 };
0086 
0087 #define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg,    \
0088                       _shift, _width,           \
0089                       _table, _gate, _flags)        \
0090     struct ccu_div _struct = {                  \
0091         .div        = _SUNXI_CCU_DIV_TABLE(_shift, _width,  \
0092                                _table),     \
0093         .enable     = _gate,                \
0094         .common = {                     \
0095             .reg        = _reg,             \
0096             .hw.init    = CLK_HW_INIT(_name,        \
0097                               _parent,      \
0098                               &ccu_div_ops, \
0099                               _flags),      \
0100         }                           \
0101     }
0102 
0103 
0104 #define SUNXI_CCU_DIV_TABLE(_struct, _name, _parent, _reg,      \
0105                 _shift, _width,             \
0106                 _table, _flags)             \
0107     SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg,    \
0108                       _shift, _width, _table, 0,    \
0109                       _flags)
0110 
0111 #define SUNXI_CCU_DIV_TABLE_HW(_struct, _name, _parent, _reg,       \
0112                    _shift, _width,              \
0113                    _table, _flags)              \
0114     struct ccu_div _struct = {                  \
0115         .div        = _SUNXI_CCU_DIV_TABLE(_shift, _width,  \
0116                                _table),     \
0117         .common = {                     \
0118             .reg        = _reg,             \
0119             .hw.init    = CLK_HW_INIT_HW(_name,     \
0120                              _parent,   \
0121                              &ccu_div_ops,  \
0122                              _flags),   \
0123         }                           \
0124     }
0125 
0126 
0127 #define SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,         \
0128                     _parents, _table,       \
0129                     _reg,               \
0130                     _mshift, _mwidth,       \
0131                     _muxshift, _muxwidth,       \
0132                     _gate, _flags)          \
0133     struct ccu_div _struct = {                  \
0134         .enable = _gate,                    \
0135         .div    = _SUNXI_CCU_DIV(_mshift, _mwidth),     \
0136         .mux    = _SUNXI_CCU_MUX_TABLE(_muxshift, _muxwidth, _table), \
0137         .common = {                     \
0138             .reg        = _reg,             \
0139             .hw.init    = CLK_HW_INIT_PARENTS(_name,    \
0140                                   _parents, \
0141                                   &ccu_div_ops, \
0142                                   _flags),  \
0143         },                          \
0144     }
0145 
0146 #define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg,   \
0147                   _mshift, _mwidth, _muxshift, _muxwidth, \
0148                   _gate, _flags)            \
0149     SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,         \
0150                     _parents, NULL,         \
0151                     _reg, _mshift, _mwidth,     \
0152                     _muxshift, _muxwidth,       \
0153                     _gate, _flags)
0154 
0155 #define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg,        \
0156                  _mshift, _mwidth, _muxshift, _muxwidth,    \
0157                  _flags)                    \
0158     SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,         \
0159                     _parents, NULL,         \
0160                     _reg, _mshift, _mwidth,     \
0161                     _muxshift, _muxwidth,       \
0162                     0, _flags)
0163 
0164 
0165 #define SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,        \
0166                   _mshift, _mwidth, _gate,          \
0167                   _flags)                   \
0168     struct ccu_div _struct = {                  \
0169         .enable = _gate,                    \
0170         .div    = _SUNXI_CCU_DIV(_mshift, _mwidth),     \
0171         .common = {                     \
0172             .reg        = _reg,             \
0173             .hw.init    = CLK_HW_INIT(_name,        \
0174                               _parent,      \
0175                               &ccu_div_ops, \
0176                               _flags),      \
0177         },                          \
0178     }
0179 
0180 #define SUNXI_CCU_M(_struct, _name, _parent, _reg, _mshift, _mwidth,    \
0181             _flags)                     \
0182     SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,        \
0183                   _mshift, _mwidth, 0, _flags)
0184 
0185 #define SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg,  \
0186                        _mshift, _mwidth,        \
0187                        _muxshift, _muxwidth,        \
0188                        _gate, _flags)           \
0189     struct ccu_div _struct = {                  \
0190         .enable = _gate,                    \
0191         .div    = _SUNXI_CCU_DIV(_mshift, _mwidth),     \
0192         .mux    = _SUNXI_CCU_MUX(_muxshift, _muxwidth),     \
0193         .common = {                     \
0194             .reg        = _reg,             \
0195             .hw.init    = CLK_HW_INIT_PARENTS_DATA(_name, \
0196                                    _parents, \
0197                                    &ccu_div_ops, \
0198                                    _flags), \
0199         },                          \
0200     }
0201 
0202 #define SUNXI_CCU_M_DATA_WITH_MUX(_struct, _name, _parents, _reg,   \
0203                   _mshift, _mwidth,         \
0204                   _muxshift, _muxwidth,         \
0205                   _flags)               \
0206     SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg,  \
0207                        _mshift, _mwidth,        \
0208                        _muxshift, _muxwidth,        \
0209                        0, _flags)
0210 
0211 #define SUNXI_CCU_M_HW_WITH_MUX_GATE(_struct, _name, _parents, _reg,    \
0212                      _mshift, _mwidth, _muxshift, _muxwidth, \
0213                      _gate, _flags)         \
0214     struct ccu_div _struct = {                  \
0215         .enable = _gate,                    \
0216         .div    = _SUNXI_CCU_DIV(_mshift, _mwidth),     \
0217         .mux    = _SUNXI_CCU_MUX(_muxshift, _muxwidth),     \
0218         .common = {                     \
0219             .reg        = _reg,             \
0220             .hw.init    = CLK_HW_INIT_PARENTS_HW(_name, \
0221                                  _parents, \
0222                                  &ccu_div_ops, \
0223                                  _flags), \
0224         },                          \
0225     }
0226 
0227 #define SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg,    \
0228                   _mshift, _mwidth, _gate,      \
0229                   _flags)               \
0230     struct ccu_div _struct = {                  \
0231         .enable = _gate,                    \
0232         .div    = _SUNXI_CCU_DIV(_mshift, _mwidth),     \
0233         .common = {                     \
0234             .reg        = _reg,             \
0235             .hw.init    = CLK_HW_INIT_HWS(_name,    \
0236                               _parent,  \
0237                               &ccu_div_ops, \
0238                               _flags),  \
0239         },                          \
0240     }
0241 
0242 #define SUNXI_CCU_M_HWS(_struct, _name, _parent, _reg, _mshift,     \
0243             _mwidth, _flags)                \
0244     SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg,    \
0245                   _mshift, _mwidth, 0, _flags)
0246 
0247 static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
0248 {
0249     struct ccu_common *common = hw_to_ccu_common(hw);
0250 
0251     return container_of(common, struct ccu_div, common);
0252 }
0253 
0254 extern const struct clk_ops ccu_div_ops;
0255 
0256 #endif /* _CCU_DIV_H_ */