linux/drivers/clk/sunxi-ng/ccu_div.h
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2016 Maxime Ripard. All rights reserved.
   3 *
   4 * This software is licensed under the terms of the GNU General Public
   5 * License version 2, as published by the Free Software Foundation, and
   6 * may be copied, distributed, and modified under those terms.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 */
  13
  14#ifndef _CCU_DIV_H_
  15#define _CCU_DIV_H_
  16
  17#include <linux/clk-provider.h>
  18
  19#include "ccu_common.h"
  20#include "ccu_mux.h"
  21
  22/**
  23 * struct ccu_div_internal - Internal divider description
  24 * @shift: Bit offset of the divider in its register
  25 * @width: Width of the divider field in its register
  26 * @max: Maximum value allowed for that divider. This is the
  27 *       arithmetic value, not the maximum value to be set in the
  28 *       register.
  29 * @flags: clk_divider flags to apply on this divider
  30 * @table: Divider table pointer (if applicable)
  31 *
  32 * That structure represents a single divider, and is meant to be
  33 * embedded in other structures representing the various clock
  34 * classes.
  35 *
  36 * It is basically a wrapper around the clk_divider functions
  37 * arguments.
  38 */
  39struct ccu_div_internal {
  40        u8                      shift;
  41        u8                      width;
  42
  43        u32                     max;
  44        u32                     offset;
  45
  46        u32                     flags;
  47
  48        struct clk_div_table    *table;
  49};
  50
  51#define _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, _flags)      \
  52        {                                                               \
  53                .shift  = _shift,                                       \
  54                .width  = _width,                                       \
  55                .flags  = _flags,                                       \
  56                .table  = _table,                                       \
  57        }
  58
  59#define _SUNXI_CCU_DIV_TABLE(_shift, _width, _table)                    \
  60        _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, 0)
  61
  62#define _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _off, _max, _flags) \
  63        {                                                               \
  64                .shift  = _shift,                                       \
  65                .width  = _width,                                       \
  66                .flags  = _flags,                                       \
  67                .max    = _max,                                         \
  68                .offset = _off,                                         \
  69        }
  70
  71#define _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, _flags)          \
  72        _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, 1, _max, _flags)
  73
  74#define _SUNXI_CCU_DIV_FLAGS(_shift, _width, _flags)                    \
  75        _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, 0, _flags)
  76
  77#define _SUNXI_CCU_DIV_MAX(_shift, _width, _max)                        \
  78        _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, 0)
  79
  80#define _SUNXI_CCU_DIV_OFFSET(_shift, _width, _offset)                  \
  81        _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _offset, 0, 0)
  82
  83#define _SUNXI_CCU_DIV(_shift, _width)                                  \
  84        _SUNXI_CCU_DIV_FLAGS(_shift, _width, 0)
  85
  86struct ccu_div {
  87        u32                     enable;
  88
  89        struct ccu_div_internal div;
  90        struct ccu_mux_internal mux;
  91        struct ccu_common       common;
  92        unsigned int            fixed_post_div;
  93};
  94
  95#define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg,    \
  96                                      _shift, _width,                   \
  97                                      _table, _gate, _flags)            \
  98        struct ccu_div _struct = {                                      \
  99                .div            = _SUNXI_CCU_DIV_TABLE(_shift, _width,  \
 100                                                       _table),         \
 101                .enable         = _gate,                                \
 102                .common = {                                             \
 103                        .reg            = _reg,                         \
 104                        .hw.init        = CLK_HW_INIT(_name,            \
 105                                                      _parent,          \
 106                                                      &ccu_div_ops,     \
 107                                                      _flags),          \
 108                }                                                       \
 109        }
 110
 111
 112#define SUNXI_CCU_DIV_TABLE(_struct, _name, _parent, _reg,              \
 113                            _shift, _width,                             \
 114                            _table, _flags)                             \
 115        SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg,    \
 116                                      _shift, _width, _table, 0,        \
 117                                      _flags)
 118
 119#define SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,                 \
 120                                        _parents, _table,               \
 121                                        _reg,                           \
 122                                        _mshift, _mwidth,               \
 123                                        _muxshift, _muxwidth,           \
 124                                        _gate, _flags)                  \
 125        struct ccu_div _struct = {                                      \
 126                .enable = _gate,                                        \
 127                .div    = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
 128                .mux    = _SUNXI_CCU_MUX_TABLE(_muxshift, _muxwidth, _table), \
 129                .common = {                                             \
 130                        .reg            = _reg,                         \
 131                        .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
 132                                                              _parents, \
 133                                                              &ccu_div_ops, \
 134                                                              _flags),  \
 135                },                                                      \
 136        }
 137
 138#define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg,       \
 139                                  _mshift, _mwidth, _muxshift, _muxwidth, \
 140                                  _gate, _flags)                        \
 141        SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,                 \
 142                                        _parents, NULL,                 \
 143                                        _reg, _mshift, _mwidth,         \
 144                                        _muxshift, _muxwidth,           \
 145                                        _gate, _flags)
 146
 147#define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg,            \
 148                             _mshift, _mwidth, _muxshift, _muxwidth,    \
 149                             _flags)                                    \
 150        SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,                 \
 151                                        _parents, NULL,                 \
 152                                        _reg, _mshift, _mwidth,         \
 153                                        _muxshift, _muxwidth,           \
 154                                        0, _flags)
 155
 156
 157#define SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,            \
 158                              _mshift, _mwidth, _gate,                  \
 159                              _flags)                                   \
 160        struct ccu_div _struct = {                                      \
 161                .enable = _gate,                                        \
 162                .div    = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
 163                .common = {                                             \
 164                        .reg            = _reg,                         \
 165                        .hw.init        = CLK_HW_INIT(_name,            \
 166                                                      _parent,          \
 167                                                      &ccu_div_ops,     \
 168                                                      _flags),          \
 169                },                                                      \
 170        }
 171
 172#define SUNXI_CCU_M(_struct, _name, _parent, _reg, _mshift, _mwidth,    \
 173                    _flags)                                             \
 174        SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,            \
 175                              _mshift, _mwidth, 0, _flags)
 176
 177static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
 178{
 179        struct ccu_common *common = hw_to_ccu_common(hw);
 180
 181        return container_of(common, struct ccu_div, common);
 182}
 183
 184extern const struct clk_ops ccu_div_ops;
 185
 186#endif /* _CCU_DIV_H_ */
 187