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