2016-06-29 22:05:28 +03:00
/*
* Copyright ( c ) 2016 Maxime Ripard . All rights reserved .
*
* This software is licensed under the terms of the GNU General Public
* License version 2 , as published by the Free Software Foundation , and
* may be copied , distributed , and modified under those terms .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*/
# ifndef _CCU_DIV_H_
# define _CCU_DIV_H_
# include <linux/clk-provider.h>
# include "ccu_common.h"
# include "ccu_mux.h"
2016-09-08 12:29:13 +03:00
/**
2016-09-30 11:05:32 +03:00
* struct ccu_div_internal - Internal divider description
2016-09-08 12:29:13 +03:00
* @ shift : Bit offset of the divider in its register
* @ width : Width of the divider field in its register
2016-09-06 13:29:04 +03:00
* @ max : Maximum value allowed for that divider . This is the
* arithmetic value , not the maximum value to be set in the
* register .
2016-09-08 12:29:13 +03:00
* @ flags : clk_divider flags to apply on this divider
* @ table : Divider table pointer ( if applicable )
*
* That structure represents a single divider , and is meant to be
* embedded in other structures representing the various clock
* classes .
*
* It is basically a wrapper around the clk_divider functions
* arguments .
*/
2016-09-30 11:05:32 +03:00
struct ccu_div_internal {
2016-06-29 22:05:28 +03:00
u8 shift ;
u8 width ;
2016-09-06 13:29:04 +03:00
u32 max ;
2016-11-08 20:12:34 +03:00
u32 offset ;
2016-09-06 13:29:04 +03:00
2016-06-29 22:05:28 +03:00
u32 flags ;
struct clk_div_table * table ;
} ;
# define _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, _flags) \
{ \
. shift = _shift , \
. width = _width , \
. flags = _flags , \
. table = _table , \
}
# define _SUNXI_CCU_DIV_TABLE(_shift, _width, _table) \
_SUNXI_CCU_DIV_TABLE_FLAGS ( _shift , _width , _table , 0 )
2016-11-08 20:12:34 +03:00
# define _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _off, _max, _flags) \
2016-09-06 13:29:04 +03:00
{ \
. shift = _shift , \
. width = _width , \
. flags = _flags , \
. max = _max , \
2016-11-08 20:12:34 +03:00
. offset = _off , \
2016-09-06 13:29:04 +03:00
}
2016-11-08 20:12:34 +03:00
# define _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, _flags) \
_SUNXI_CCU_DIV_OFFSET_MAX_FLAGS ( _shift , _width , 1 , _max , _flags )
2016-09-06 13:29:04 +03:00
# define _SUNXI_CCU_DIV_FLAGS(_shift, _width, _flags) \
_SUNXI_CCU_DIV_MAX_FLAGS ( _shift , _width , 0 , _flags )
# define _SUNXI_CCU_DIV_MAX(_shift, _width, _max) \
_SUNXI_CCU_DIV_MAX_FLAGS ( _shift , _width , _max , 0 )
2016-11-08 20:12:34 +03:00
# define _SUNXI_CCU_DIV_OFFSET(_shift, _width, _offset) \
_SUNXI_CCU_DIV_OFFSET_MAX_FLAGS ( _shift , _width , _offset , 0 , 0 )
2016-06-29 22:05:28 +03:00
# define _SUNXI_CCU_DIV(_shift, _width) \
2016-09-06 13:29:04 +03:00
_SUNXI_CCU_DIV_FLAGS ( _shift , _width , 0 )
2016-06-29 22:05:28 +03:00
struct ccu_div {
u32 enable ;
2016-09-30 11:05:32 +03:00
struct ccu_div_internal div ;
2016-06-29 22:05:28 +03:00
struct ccu_mux_internal mux ;
struct ccu_common common ;
} ;
# define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg, \
_shift , _width , \
_table , _gate , _flags ) \
struct ccu_div _struct = { \
. div = _SUNXI_CCU_DIV_TABLE ( _shift , _width , \
_table ) , \
. enable = _gate , \
. common = { \
. reg = _reg , \
. hw . init = CLK_HW_INIT ( _name , \
_parent , \
& ccu_div_ops , \
_flags ) , \
} \
}
# define SUNXI_CCU_DIV_TABLE(_struct, _name, _parent, _reg, \
_shift , _width , \
_table , _flags ) \
SUNXI_CCU_DIV_TABLE_WITH_GATE ( _struct , _name , _parent , _reg , \
_shift , _width , _table , 0 , \
_flags )
2016-08-30 11:38:41 +03:00
# define SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name, \
_parents , _table , \
_reg , \
_mshift , _mwidth , \
_muxshift , _muxwidth , \
_gate , _flags ) \
2016-06-29 22:05:28 +03:00
struct ccu_div _struct = { \
. enable = _gate , \
. div = _SUNXI_CCU_DIV ( _mshift , _mwidth ) , \
2016-08-30 11:38:41 +03:00
. mux = _SUNXI_CCU_MUX_TABLE ( _muxshift , _muxwidth , _table ) , \
2016-06-29 22:05:28 +03:00
. common = { \
. reg = _reg , \
. hw . init = CLK_HW_INIT_PARENTS ( _name , \
_parents , \
& ccu_div_ops , \
_flags ) , \
} , \
}
2016-08-30 11:38:41 +03:00
# define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
_mshift , _mwidth , _muxshift , _muxwidth , \
_gate , _flags ) \
SUNXI_CCU_M_WITH_MUX_TABLE_GATE ( _struct , _name , \
_parents , NULL , \
_reg , _mshift , _mwidth , \
_muxshift , _muxwidth , \
_gate , _flags )
2016-06-29 22:05:28 +03:00
# define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg, \
_mshift , _mwidth , _muxshift , _muxwidth , \
_flags ) \
2016-08-30 11:38:41 +03:00
SUNXI_CCU_M_WITH_MUX_TABLE_GATE ( _struct , _name , \
_parents , NULL , \
_reg , _mshift , _mwidth , \
_muxshift , _muxwidth , \
0 , _flags )
2016-06-29 22:05:28 +03:00
# define SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg, \
_mshift , _mwidth , _gate , \
_flags ) \
struct ccu_div _struct = { \
. enable = _gate , \
. div = _SUNXI_CCU_DIV ( _mshift , _mwidth ) , \
. common = { \
. reg = _reg , \
. hw . init = CLK_HW_INIT ( _name , \
_parent , \
& ccu_div_ops , \
_flags ) , \
} , \
}
# define SUNXI_CCU_M(_struct, _name, _parent, _reg, _mshift, _mwidth, \
_flags ) \
SUNXI_CCU_M_WITH_GATE ( _struct , _name , _parent , _reg , \
_mshift , _mwidth , 0 , _flags )
static inline struct ccu_div * hw_to_ccu_div ( struct clk_hw * hw )
{
struct ccu_common * common = hw_to_ccu_common ( hw ) ;
return container_of ( common , struct ccu_div , common ) ;
}
extern const struct clk_ops ccu_div_ops ;
# endif /* _CCU_DIV_H_ */