Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
c818f97b
K
Kernel
项目概览
openeuler
/
Kernel
接近 2 年 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
c818f97b
编写于
5月 09, 2012
作者:
S
Sascha Hauer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ARM i.MX: remove now unused clock files
Signed-off-by:
N
Sascha Hauer
<
s.hauer@pengutronix.de
>
上级
2acd1b6f
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
0 addition
and
7958 deletion
+0
-7958
arch/arm/mach-imx/clock-imx1.c
arch/arm/mach-imx/clock-imx1.c
+0
-636
arch/arm/mach-imx/clock-imx21.c
arch/arm/mach-imx/clock-imx21.c
+0
-1239
arch/arm/mach-imx/clock-imx25.c
arch/arm/mach-imx/clock-imx25.c
+0
-346
arch/arm/mach-imx/clock-imx27.c
arch/arm/mach-imx/clock-imx27.c
+0
-785
arch/arm/mach-imx/clock-imx31.c
arch/arm/mach-imx/clock-imx31.c
+0
-630
arch/arm/mach-imx/clock-imx35.c
arch/arm/mach-imx/clock-imx35.c
+0
-536
arch/arm/mach-imx/clock-imx6q.c
arch/arm/mach-imx/clock-imx6q.c
+0
-2111
arch/arm/mach-imx/clock-mx51-mx53.c
arch/arm/mach-imx/clock-mx51-mx53.c
+0
-1675
未找到文件。
arch/arm/mach-imx/clock-imx1.c
已删除
100644 → 0
浏览文件 @
2acd1b6f
/*
* Copyright (C) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/math64.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/clkdev.h>
#include <mach/clock.h>
#include <mach/hardware.h>
#include <mach/common.h>
#define IO_ADDR_CCM(off) (MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR + (off)))
/* CCM register addresses */
#define CCM_CSCR IO_ADDR_CCM(0x0)
#define CCM_MPCTL0 IO_ADDR_CCM(0x4)
#define CCM_SPCTL0 IO_ADDR_CCM(0xc)
#define CCM_PCDR IO_ADDR_CCM(0x20)
#define CCM_CSCR_CLKO_OFFSET 29
#define CCM_CSCR_CLKO_MASK (0x7 << 29)
#define CCM_CSCR_USB_OFFSET 26
#define CCM_CSCR_USB_MASK (0x7 << 26)
#define CCM_CSCR_OSC_EN_SHIFT 17
#define CCM_CSCR_SYSTEM_SEL (1 << 16)
#define CCM_CSCR_BCLK_OFFSET 10
#define CCM_CSCR_BCLK_MASK (0xf << 10)
#define CCM_CSCR_PRESC (1 << 15)
#define CCM_PCDR_PCLK3_OFFSET 16
#define CCM_PCDR_PCLK3_MASK (0x7f << 16)
#define CCM_PCDR_PCLK2_OFFSET 4
#define CCM_PCDR_PCLK2_MASK (0xf << 4)
#define CCM_PCDR_PCLK1_OFFSET 0
#define CCM_PCDR_PCLK1_MASK 0xf
#define IO_ADDR_SCM(off) (MX1_IO_ADDRESS(MX1_SCM_BASE_ADDR + (off)))
/* SCM register addresses */
#define SCM_GCCR IO_ADDR_SCM(0xc)
#define SCM_GCCR_DMA_CLK_EN_OFFSET 3
#define SCM_GCCR_CSI_CLK_EN_OFFSET 2
#define SCM_GCCR_MMA_CLK_EN_OFFSET 1
#define SCM_GCCR_USBD_CLK_EN_OFFSET 0
static
int
_clk_enable
(
struct
clk
*
clk
)
{
unsigned
int
reg
;
reg
=
__raw_readl
(
clk
->
enable_reg
);
reg
|=
1
<<
clk
->
enable_shift
;
__raw_writel
(
reg
,
clk
->
enable_reg
);
return
0
;
}
static
void
_clk_disable
(
struct
clk
*
clk
)
{
unsigned
int
reg
;
reg
=
__raw_readl
(
clk
->
enable_reg
);
reg
&=
~
(
1
<<
clk
->
enable_shift
);
__raw_writel
(
reg
,
clk
->
enable_reg
);
}
static
int
_clk_can_use_parent
(
const
struct
clk
*
clk_arr
[],
unsigned
int
size
,
struct
clk
*
parent
)
{
int
i
;
for
(
i
=
0
;
i
<
size
;
i
++
)
if
(
parent
==
clk_arr
[
i
])
return
i
;
return
-
EINVAL
;
}
static
unsigned
long
_clk_simple_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
,
unsigned
int
limit
)
{
int
div
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
div
=
parent_rate
/
rate
;
if
(
parent_rate
%
rate
)
div
++
;
if
(
div
>
limit
)
div
=
limit
;
return
parent_rate
/
div
;
}
static
unsigned
long
_clk_parent_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
return
clk
->
parent
->
round_rate
(
clk
->
parent
,
rate
);
}
static
int
_clk_parent_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
return
clk
->
parent
->
set_rate
(
clk
->
parent
,
rate
);
}
static
unsigned
long
clk16m_get_rate
(
struct
clk
*
clk
)
{
return
16000000
;
}
static
struct
clk
clk16m
=
{
.
get_rate
=
clk16m_get_rate
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_CSCR
,
.
enable_shift
=
CCM_CSCR_OSC_EN_SHIFT
,
.
disable
=
_clk_disable
,
};
/* in Hz */
static
unsigned
long
clk32_rate
;
static
unsigned
long
clk32_get_rate
(
struct
clk
*
clk
)
{
return
clk32_rate
;
}
static
struct
clk
clk32
=
{
.
get_rate
=
clk32_get_rate
,
};
static
unsigned
long
clk32_premult_get_rate
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
)
*
512
;
}
static
struct
clk
clk32_premult
=
{
.
parent
=
&
clk32
,
.
get_rate
=
clk32_premult_get_rate
,
};
static
const
struct
clk
*
prem_clk_clocks
[]
=
{
&
clk32_premult
,
&
clk16m
,
};
static
int
prem_clk_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
int
i
;
unsigned
int
reg
=
__raw_readl
(
CCM_CSCR
);
i
=
_clk_can_use_parent
(
prem_clk_clocks
,
ARRAY_SIZE
(
prem_clk_clocks
),
parent
);
switch
(
i
)
{
case
0
:
reg
&=
~
CCM_CSCR_SYSTEM_SEL
;
break
;
case
1
:
reg
|=
CCM_CSCR_SYSTEM_SEL
;
break
;
default:
return
i
;
}
__raw_writel
(
reg
,
CCM_CSCR
);
return
0
;
}
static
struct
clk
prem_clk
=
{
.
set_parent
=
prem_clk_set_parent
,
};
static
unsigned
long
system_clk_get_rate
(
struct
clk
*
clk
)
{
return
mxc_decode_pll
(
__raw_readl
(
CCM_SPCTL0
),
clk_get_rate
(
clk
->
parent
));
}
static
struct
clk
system_clk
=
{
.
parent
=
&
prem_clk
,
.
get_rate
=
system_clk_get_rate
,
};
static
unsigned
long
mcu_clk_get_rate
(
struct
clk
*
clk
)
{
return
mxc_decode_pll
(
__raw_readl
(
CCM_MPCTL0
),
clk_get_rate
(
clk
->
parent
));
}
static
struct
clk
mcu_clk
=
{
.
parent
=
&
clk32_premult
,
.
get_rate
=
mcu_clk_get_rate
,
};
static
unsigned
long
fclk_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
fclk
=
clk_get_rate
(
clk
->
parent
);
if
(
__raw_readl
(
CCM_CSCR
)
&
CCM_CSCR_PRESC
)
fclk
/=
2
;
return
fclk
;
}
static
struct
clk
fclk
=
{
.
parent
=
&
mcu_clk
,
.
get_rate
=
fclk_get_rate
,
};
/*
* get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
*/
static
unsigned
long
hclk_get_rate
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
)
/
(((
__raw_readl
(
CCM_CSCR
)
&
CCM_CSCR_BCLK_MASK
)
>>
CCM_CSCR_BCLK_OFFSET
)
+
1
);
}
static
unsigned
long
hclk_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
return
_clk_simple_round_rate
(
clk
,
rate
,
16
);
}
static
int
hclk_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
unsigned
int
div
;
unsigned
int
reg
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
div
=
parent_rate
/
rate
;
if
(
div
>
16
||
div
<
1
||
((
parent_rate
/
div
)
!=
rate
))
return
-
EINVAL
;
div
--
;
reg
=
__raw_readl
(
CCM_CSCR
);
reg
&=
~
CCM_CSCR_BCLK_MASK
;
reg
|=
div
<<
CCM_CSCR_BCLK_OFFSET
;
__raw_writel
(
reg
,
CCM_CSCR
);
return
0
;
}
static
struct
clk
hclk
=
{
.
parent
=
&
system_clk
,
.
get_rate
=
hclk_get_rate
,
.
round_rate
=
hclk_round_rate
,
.
set_rate
=
hclk_set_rate
,
};
static
unsigned
long
clk48m_get_rate
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
)
/
(((
__raw_readl
(
CCM_CSCR
)
&
CCM_CSCR_USB_MASK
)
>>
CCM_CSCR_USB_OFFSET
)
+
1
);
}
static
unsigned
long
clk48m_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
return
_clk_simple_round_rate
(
clk
,
rate
,
8
);
}
static
int
clk48m_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
unsigned
int
div
;
unsigned
int
reg
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
div
=
parent_rate
/
rate
;
if
(
div
>
8
||
div
<
1
||
((
parent_rate
/
div
)
!=
rate
))
return
-
EINVAL
;
div
--
;
reg
=
__raw_readl
(
CCM_CSCR
);
reg
&=
~
CCM_CSCR_USB_MASK
;
reg
|=
div
<<
CCM_CSCR_USB_OFFSET
;
__raw_writel
(
reg
,
CCM_CSCR
);
return
0
;
}
static
struct
clk
clk48m
=
{
.
parent
=
&
system_clk
,
.
get_rate
=
clk48m_get_rate
,
.
round_rate
=
clk48m_round_rate
,
.
set_rate
=
clk48m_set_rate
,
};
/*
* get peripheral clock 1 ( UART[12], Timer[12], PWM )
*/
static
unsigned
long
perclk1_get_rate
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
)
/
(((
__raw_readl
(
CCM_PCDR
)
&
CCM_PCDR_PCLK1_MASK
)
>>
CCM_PCDR_PCLK1_OFFSET
)
+
1
);
}
static
unsigned
long
perclk1_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
return
_clk_simple_round_rate
(
clk
,
rate
,
16
);
}
static
int
perclk1_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
unsigned
int
div
;
unsigned
int
reg
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
div
=
parent_rate
/
rate
;
if
(
div
>
16
||
div
<
1
||
((
parent_rate
/
div
)
!=
rate
))
return
-
EINVAL
;
div
--
;
reg
=
__raw_readl
(
CCM_PCDR
);
reg
&=
~
CCM_PCDR_PCLK1_MASK
;
reg
|=
div
<<
CCM_PCDR_PCLK1_OFFSET
;
__raw_writel
(
reg
,
CCM_PCDR
);
return
0
;
}
/*
* get peripheral clock 2 ( LCD, SD, SPI[12] )
*/
static
unsigned
long
perclk2_get_rate
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
)
/
(((
__raw_readl
(
CCM_PCDR
)
&
CCM_PCDR_PCLK2_MASK
)
>>
CCM_PCDR_PCLK2_OFFSET
)
+
1
);
}
static
unsigned
long
perclk2_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
return
_clk_simple_round_rate
(
clk
,
rate
,
16
);
}
static
int
perclk2_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
unsigned
int
div
;
unsigned
int
reg
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
div
=
parent_rate
/
rate
;
if
(
div
>
16
||
div
<
1
||
((
parent_rate
/
div
)
!=
rate
))
return
-
EINVAL
;
div
--
;
reg
=
__raw_readl
(
CCM_PCDR
);
reg
&=
~
CCM_PCDR_PCLK2_MASK
;
reg
|=
div
<<
CCM_PCDR_PCLK2_OFFSET
;
__raw_writel
(
reg
,
CCM_PCDR
);
return
0
;
}
/*
* get peripheral clock 3 ( SSI )
*/
static
unsigned
long
perclk3_get_rate
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
)
/
(((
__raw_readl
(
CCM_PCDR
)
&
CCM_PCDR_PCLK3_MASK
)
>>
CCM_PCDR_PCLK3_OFFSET
)
+
1
);
}
static
unsigned
long
perclk3_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
return
_clk_simple_round_rate
(
clk
,
rate
,
128
);
}
static
int
perclk3_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
unsigned
int
div
;
unsigned
int
reg
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
div
=
parent_rate
/
rate
;
if
(
div
>
128
||
div
<
1
||
((
parent_rate
/
div
)
!=
rate
))
return
-
EINVAL
;
div
--
;
reg
=
__raw_readl
(
CCM_PCDR
);
reg
&=
~
CCM_PCDR_PCLK3_MASK
;
reg
|=
div
<<
CCM_PCDR_PCLK3_OFFSET
;
__raw_writel
(
reg
,
CCM_PCDR
);
return
0
;
}
static
struct
clk
perclk
[]
=
{
{
.
id
=
0
,
.
parent
=
&
system_clk
,
.
get_rate
=
perclk1_get_rate
,
.
round_rate
=
perclk1_round_rate
,
.
set_rate
=
perclk1_set_rate
,
},
{
.
id
=
1
,
.
parent
=
&
system_clk
,
.
get_rate
=
perclk2_get_rate
,
.
round_rate
=
perclk2_round_rate
,
.
set_rate
=
perclk2_set_rate
,
},
{
.
id
=
2
,
.
parent
=
&
system_clk
,
.
get_rate
=
perclk3_get_rate
,
.
round_rate
=
perclk3_round_rate
,
.
set_rate
=
perclk3_set_rate
,
}
};
static
const
struct
clk
*
clko_clocks
[]
=
{
&
perclk
[
0
],
&
hclk
,
&
clk48m
,
&
clk16m
,
&
prem_clk
,
&
fclk
,
};
static
int
clko_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
int
i
;
unsigned
int
reg
;
i
=
_clk_can_use_parent
(
clko_clocks
,
ARRAY_SIZE
(
clko_clocks
),
parent
);
if
(
i
<
0
)
return
i
;
reg
=
__raw_readl
(
CCM_CSCR
)
&
~
CCM_CSCR_CLKO_MASK
;
reg
|=
i
<<
CCM_CSCR_CLKO_OFFSET
;
__raw_writel
(
reg
,
CCM_CSCR
);
if
(
clko_clocks
[
i
]
->
set_rate
&&
clko_clocks
[
i
]
->
round_rate
)
{
clk
->
set_rate
=
_clk_parent_set_rate
;
clk
->
round_rate
=
_clk_parent_round_rate
;
}
else
{
clk
->
set_rate
=
NULL
;
clk
->
round_rate
=
NULL
;
}
return
0
;
}
static
struct
clk
clko_clk
=
{
.
set_parent
=
clko_set_parent
,
};
static
struct
clk
dma_clk
=
{
.
parent
=
&
hclk
,
.
round_rate
=
_clk_parent_round_rate
,
.
set_rate
=
_clk_parent_set_rate
,
.
enable
=
_clk_enable
,
.
enable_reg
=
SCM_GCCR
,
.
enable_shift
=
SCM_GCCR_DMA_CLK_EN_OFFSET
,
.
disable
=
_clk_disable
,
};
static
struct
clk
csi_clk
=
{
.
parent
=
&
hclk
,
.
round_rate
=
_clk_parent_round_rate
,
.
set_rate
=
_clk_parent_set_rate
,
.
enable
=
_clk_enable
,
.
enable_reg
=
SCM_GCCR
,
.
enable_shift
=
SCM_GCCR_CSI_CLK_EN_OFFSET
,
.
disable
=
_clk_disable
,
};
static
struct
clk
mma_clk
=
{
.
parent
=
&
hclk
,
.
round_rate
=
_clk_parent_round_rate
,
.
set_rate
=
_clk_parent_set_rate
,
.
enable
=
_clk_enable
,
.
enable_reg
=
SCM_GCCR
,
.
enable_shift
=
SCM_GCCR_MMA_CLK_EN_OFFSET
,
.
disable
=
_clk_disable
,
};
static
struct
clk
usbd_clk
=
{
.
parent
=
&
clk48m
,
.
round_rate
=
_clk_parent_round_rate
,
.
set_rate
=
_clk_parent_set_rate
,
.
enable
=
_clk_enable
,
.
enable_reg
=
SCM_GCCR
,
.
enable_shift
=
SCM_GCCR_USBD_CLK_EN_OFFSET
,
.
disable
=
_clk_disable
,
};
static
struct
clk
gpt_clk
=
{
.
parent
=
&
perclk
[
0
],
.
round_rate
=
_clk_parent_round_rate
,
.
set_rate
=
_clk_parent_set_rate
,
};
static
struct
clk
uart_clk
=
{
.
parent
=
&
perclk
[
0
],
.
round_rate
=
_clk_parent_round_rate
,
.
set_rate
=
_clk_parent_set_rate
,
};
static
struct
clk
i2c_clk
=
{
.
parent
=
&
hclk
,
.
round_rate
=
_clk_parent_round_rate
,
.
set_rate
=
_clk_parent_set_rate
,
};
static
struct
clk
spi_clk
=
{
.
parent
=
&
perclk
[
1
],
.
round_rate
=
_clk_parent_round_rate
,
.
set_rate
=
_clk_parent_set_rate
,
};
static
struct
clk
sdhc_clk
=
{
.
parent
=
&
perclk
[
1
],
.
round_rate
=
_clk_parent_round_rate
,
.
set_rate
=
_clk_parent_set_rate
,
};
static
struct
clk
lcdc_clk
=
{
.
parent
=
&
perclk
[
1
],
.
round_rate
=
_clk_parent_round_rate
,
.
set_rate
=
_clk_parent_set_rate
,
};
static
struct
clk
mshc_clk
=
{
.
parent
=
&
hclk
,
.
round_rate
=
_clk_parent_round_rate
,
.
set_rate
=
_clk_parent_set_rate
,
};
static
struct
clk
ssi_clk
=
{
.
parent
=
&
perclk
[
2
],
.
round_rate
=
_clk_parent_round_rate
,
.
set_rate
=
_clk_parent_set_rate
,
};
static
struct
clk
rtc_clk
=
{
.
parent
=
&
clk32
,
};
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
},
static
struct
clk_lookup
lookups
[]
__initdata
=
{
_REGISTER_CLOCK
(
NULL
,
"dma"
,
dma_clk
)
_REGISTER_CLOCK
(
"mx1-camera.0"
,
NULL
,
csi_clk
)
_REGISTER_CLOCK
(
NULL
,
"mma"
,
mma_clk
)
_REGISTER_CLOCK
(
"imx_udc.0"
,
NULL
,
usbd_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpt"
,
gpt_clk
)
_REGISTER_CLOCK
(
"imx1-uart.0"
,
NULL
,
uart_clk
)
_REGISTER_CLOCK
(
"imx1-uart.1"
,
NULL
,
uart_clk
)
_REGISTER_CLOCK
(
"imx1-uart.2"
,
NULL
,
uart_clk
)
_REGISTER_CLOCK
(
"imx-i2c.0"
,
NULL
,
i2c_clk
)
_REGISTER_CLOCK
(
"imx1-cspi.0"
,
NULL
,
spi_clk
)
_REGISTER_CLOCK
(
"imx1-cspi.1"
,
NULL
,
spi_clk
)
_REGISTER_CLOCK
(
"imx-mmc.0"
,
NULL
,
sdhc_clk
)
_REGISTER_CLOCK
(
"imx-fb.0"
,
NULL
,
lcdc_clk
)
_REGISTER_CLOCK
(
NULL
,
"mshc"
,
mshc_clk
)
_REGISTER_CLOCK
(
NULL
,
"ssi"
,
ssi_clk
)
_REGISTER_CLOCK
(
"mxc_rtc.0"
,
NULL
,
rtc_clk
)
};
int
__init
mx1_clocks_init
(
unsigned
long
fref
)
{
unsigned
int
reg
;
/* disable clocks we are able to */
__raw_writel
(
0
,
SCM_GCCR
);
clk32_rate
=
fref
;
reg
=
__raw_readl
(
CCM_CSCR
);
/* detect clock reference for system PLL */
if
(
reg
&
CCM_CSCR_SYSTEM_SEL
)
{
prem_clk
.
parent
=
&
clk16m
;
}
else
{
/* ensure that oscillator is disabled */
reg
&=
~
(
1
<<
CCM_CSCR_OSC_EN_SHIFT
);
__raw_writel
(
reg
,
CCM_CSCR
);
prem_clk
.
parent
=
&
clk32_premult
;
}
/* detect reference for CLKO */
reg
=
(
reg
&
CCM_CSCR_CLKO_MASK
)
>>
CCM_CSCR_CLKO_OFFSET
;
clko_clk
.
parent
=
(
struct
clk
*
)
clko_clocks
[
reg
];
clkdev_add_table
(
lookups
,
ARRAY_SIZE
(
lookups
));
clk_enable
(
&
hclk
);
clk_enable
(
&
fclk
);
mxc_timer_init
(
&
gpt_clk
,
MX1_IO_ADDRESS
(
MX1_TIM1_BASE_ADDR
),
MX1_TIM1_INT
);
return
0
;
}
arch/arm/mach-imx/clock-imx21.c
已删除
100644 → 0
浏览文件 @
2acd1b6f
/*
* Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
* Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/clkdev.h>
#include <mach/clock.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include <asm/div64.h>
#define IO_ADDR_CCM(off) (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off)))
/* Register offsets */
#define CCM_CSCR IO_ADDR_CCM(0x0)
#define CCM_MPCTL0 IO_ADDR_CCM(0x4)
#define CCM_MPCTL1 IO_ADDR_CCM(0x8)
#define CCM_SPCTL0 IO_ADDR_CCM(0xc)
#define CCM_SPCTL1 IO_ADDR_CCM(0x10)
#define CCM_OSC26MCTL IO_ADDR_CCM(0x14)
#define CCM_PCDR0 IO_ADDR_CCM(0x18)
#define CCM_PCDR1 IO_ADDR_CCM(0x1c)
#define CCM_PCCR0 IO_ADDR_CCM(0x20)
#define CCM_PCCR1 IO_ADDR_CCM(0x24)
#define CCM_CCSR IO_ADDR_CCM(0x28)
#define CCM_PMCTL IO_ADDR_CCM(0x2c)
#define CCM_PMCOUNT IO_ADDR_CCM(0x30)
#define CCM_WKGDCTL IO_ADDR_CCM(0x34)
#define CCM_CSCR_PRESC_OFFSET 29
#define CCM_CSCR_PRESC_MASK (0x7 << CCM_CSCR_PRESC_OFFSET)
#define CCM_CSCR_USB_OFFSET 26
#define CCM_CSCR_USB_MASK (0x7 << CCM_CSCR_USB_OFFSET)
#define CCM_CSCR_SD_OFFSET 24
#define CCM_CSCR_SD_MASK (0x3 << CCM_CSCR_SD_OFFSET)
#define CCM_CSCR_SPLLRES (1 << 22)
#define CCM_CSCR_MPLLRES (1 << 21)
#define CCM_CSCR_SSI2_OFFSET 20
#define CCM_CSCR_SSI2 (1 << CCM_CSCR_SSI2_OFFSET)
#define CCM_CSCR_SSI1_OFFSET 19
#define CCM_CSCR_SSI1 (1 << CCM_CSCR_SSI1_OFFSET)
#define CCM_CSCR_FIR_OFFSET 18
#define CCM_CSCR_FIR (1 << CCM_CSCR_FIR_OFFSET)
#define CCM_CSCR_SP (1 << 17)
#define CCM_CSCR_MCU (1 << 16)
#define CCM_CSCR_BCLK_OFFSET 10
#define CCM_CSCR_BCLK_MASK (0xf << CCM_CSCR_BCLK_OFFSET)
#define CCM_CSCR_IPDIV_OFFSET 9
#define CCM_CSCR_IPDIV (1 << CCM_CSCR_IPDIV_OFFSET)
#define CCM_CSCR_OSC26MDIV (1 << 4)
#define CCM_CSCR_OSC26M (1 << 3)
#define CCM_CSCR_FPM (1 << 2)
#define CCM_CSCR_SPEN (1 << 1)
#define CCM_CSCR_MPEN 1
#define CCM_MPCTL0_CPLM (1 << 31)
#define CCM_MPCTL0_PD_OFFSET 26
#define CCM_MPCTL0_PD_MASK (0xf << 26)
#define CCM_MPCTL0_MFD_OFFSET 16
#define CCM_MPCTL0_MFD_MASK (0x3ff << 16)
#define CCM_MPCTL0_MFI_OFFSET 10
#define CCM_MPCTL0_MFI_MASK (0xf << 10)
#define CCM_MPCTL0_MFN_OFFSET 0
#define CCM_MPCTL0_MFN_MASK 0x3ff
#define CCM_MPCTL1_LF (1 << 15)
#define CCM_MPCTL1_BRMO (1 << 6)
#define CCM_SPCTL0_CPLM (1 << 31)
#define CCM_SPCTL0_PD_OFFSET 26
#define CCM_SPCTL0_PD_MASK (0xf << 26)
#define CCM_SPCTL0_MFD_OFFSET 16
#define CCM_SPCTL0_MFD_MASK (0x3ff << 16)
#define CCM_SPCTL0_MFI_OFFSET 10
#define CCM_SPCTL0_MFI_MASK (0xf << 10)
#define CCM_SPCTL0_MFN_OFFSET 0
#define CCM_SPCTL0_MFN_MASK 0x3ff
#define CCM_SPCTL1_LF (1 << 15)
#define CCM_SPCTL1_BRMO (1 << 6)
#define CCM_OSC26MCTL_PEAK_OFFSET 16
#define CCM_OSC26MCTL_PEAK_MASK (0x3 << 16)
#define CCM_OSC26MCTL_AGC_OFFSET 8
#define CCM_OSC26MCTL_AGC_MASK (0x3f << 8)
#define CCM_OSC26MCTL_ANATEST_OFFSET 0
#define CCM_OSC26MCTL_ANATEST_MASK 0x3f
#define CCM_PCDR0_SSI2BAUDDIV_OFFSET 26
#define CCM_PCDR0_SSI2BAUDDIV_MASK (0x3f << 26)
#define CCM_PCDR0_SSI1BAUDDIV_OFFSET 16
#define CCM_PCDR0_SSI1BAUDDIV_MASK (0x3f << 16)
#define CCM_PCDR0_NFCDIV_OFFSET 12
#define CCM_PCDR0_NFCDIV_MASK (0xf << 12)
#define CCM_PCDR0_48MDIV_OFFSET 5
#define CCM_PCDR0_48MDIV_MASK (0x7 << CCM_PCDR0_48MDIV_OFFSET)
#define CCM_PCDR0_FIRIDIV_OFFSET 0
#define CCM_PCDR0_FIRIDIV_MASK 0x1f
#define CCM_PCDR1_PERDIV4_OFFSET 24
#define CCM_PCDR1_PERDIV4_MASK (0x3f << 24)
#define CCM_PCDR1_PERDIV3_OFFSET 16
#define CCM_PCDR1_PERDIV3_MASK (0x3f << 16)
#define CCM_PCDR1_PERDIV2_OFFSET 8
#define CCM_PCDR1_PERDIV2_MASK (0x3f << 8)
#define CCM_PCDR1_PERDIV1_OFFSET 0
#define CCM_PCDR1_PERDIV1_MASK 0x3f
#define CCM_PCCR_HCLK_CSI_OFFSET 31
#define CCM_PCCR_HCLK_CSI_REG CCM_PCCR0
#define CCM_PCCR_HCLK_DMA_OFFSET 30
#define CCM_PCCR_HCLK_DMA_REG CCM_PCCR0
#define CCM_PCCR_HCLK_BROM_OFFSET 28
#define CCM_PCCR_HCLK_BROM_REG CCM_PCCR0
#define CCM_PCCR_HCLK_EMMA_OFFSET 27
#define CCM_PCCR_HCLK_EMMA_REG CCM_PCCR0
#define CCM_PCCR_HCLK_LCDC_OFFSET 26
#define CCM_PCCR_HCLK_LCDC_REG CCM_PCCR0
#define CCM_PCCR_HCLK_SLCDC_OFFSET 25
#define CCM_PCCR_HCLK_SLCDC_REG CCM_PCCR0
#define CCM_PCCR_HCLK_USBOTG_OFFSET 24
#define CCM_PCCR_HCLK_USBOTG_REG CCM_PCCR0
#define CCM_PCCR_HCLK_BMI_OFFSET 23
#define CCM_PCCR_BMI_MASK (1 << CCM_PCCR_BMI_MASK)
#define CCM_PCCR_HCLK_BMI_REG CCM_PCCR0
#define CCM_PCCR_PERCLK4_OFFSET 22
#define CCM_PCCR_PERCLK4_REG CCM_PCCR0
#define CCM_PCCR_SLCDC_OFFSET 21
#define CCM_PCCR_SLCDC_REG CCM_PCCR0
#define CCM_PCCR_FIRI_BAUD_OFFSET 20
#define CCM_PCCR_FIRI_BAUD_MASK (1 << CCM_PCCR_FIRI_BAUD_MASK)
#define CCM_PCCR_FIRI_BAUD_REG CCM_PCCR0
#define CCM_PCCR_NFC_OFFSET 19
#define CCM_PCCR_NFC_REG CCM_PCCR0
#define CCM_PCCR_LCDC_OFFSET 18
#define CCM_PCCR_LCDC_REG CCM_PCCR0
#define CCM_PCCR_SSI1_BAUD_OFFSET 17
#define CCM_PCCR_SSI1_BAUD_REG CCM_PCCR0
#define CCM_PCCR_SSI2_BAUD_OFFSET 16
#define CCM_PCCR_SSI2_BAUD_REG CCM_PCCR0
#define CCM_PCCR_EMMA_OFFSET 15
#define CCM_PCCR_EMMA_REG CCM_PCCR0
#define CCM_PCCR_USBOTG_OFFSET 14
#define CCM_PCCR_USBOTG_REG CCM_PCCR0
#define CCM_PCCR_DMA_OFFSET 13
#define CCM_PCCR_DMA_REG CCM_PCCR0
#define CCM_PCCR_I2C1_OFFSET 12
#define CCM_PCCR_I2C1_REG CCM_PCCR0
#define CCM_PCCR_GPIO_OFFSET 11
#define CCM_PCCR_GPIO_REG CCM_PCCR0
#define CCM_PCCR_SDHC2_OFFSET 10
#define CCM_PCCR_SDHC2_REG CCM_PCCR0
#define CCM_PCCR_SDHC1_OFFSET 9
#define CCM_PCCR_SDHC1_REG CCM_PCCR0
#define CCM_PCCR_FIRI_OFFSET 8
#define CCM_PCCR_FIRI_MASK (1 << CCM_PCCR_BAUD_MASK)
#define CCM_PCCR_FIRI_REG CCM_PCCR0
#define CCM_PCCR_SSI2_IPG_OFFSET 7
#define CCM_PCCR_SSI2_REG CCM_PCCR0
#define CCM_PCCR_SSI1_IPG_OFFSET 6
#define CCM_PCCR_SSI1_REG CCM_PCCR0
#define CCM_PCCR_CSPI2_OFFSET 5
#define CCM_PCCR_CSPI2_REG CCM_PCCR0
#define CCM_PCCR_CSPI1_OFFSET 4
#define CCM_PCCR_CSPI1_REG CCM_PCCR0
#define CCM_PCCR_UART4_OFFSET 3
#define CCM_PCCR_UART4_REG CCM_PCCR0
#define CCM_PCCR_UART3_OFFSET 2
#define CCM_PCCR_UART3_REG CCM_PCCR0
#define CCM_PCCR_UART2_OFFSET 1
#define CCM_PCCR_UART2_REG CCM_PCCR0
#define CCM_PCCR_UART1_OFFSET 0
#define CCM_PCCR_UART1_REG CCM_PCCR0
#define CCM_PCCR_OWIRE_OFFSET 31
#define CCM_PCCR_OWIRE_REG CCM_PCCR1
#define CCM_PCCR_KPP_OFFSET 30
#define CCM_PCCR_KPP_REG CCM_PCCR1
#define CCM_PCCR_RTC_OFFSET 29
#define CCM_PCCR_RTC_REG CCM_PCCR1
#define CCM_PCCR_PWM_OFFSET 28
#define CCM_PCCR_PWM_REG CCM_PCCR1
#define CCM_PCCR_GPT3_OFFSET 27
#define CCM_PCCR_GPT3_REG CCM_PCCR1
#define CCM_PCCR_GPT2_OFFSET 26
#define CCM_PCCR_GPT2_REG CCM_PCCR1
#define CCM_PCCR_GPT1_OFFSET 25
#define CCM_PCCR_GPT1_REG CCM_PCCR1
#define CCM_PCCR_WDT_OFFSET 24
#define CCM_PCCR_WDT_REG CCM_PCCR1
#define CCM_PCCR_CSPI3_OFFSET 23
#define CCM_PCCR_CSPI3_REG CCM_PCCR1
#define CCM_PCCR_CSPI1_MASK (1 << CCM_PCCR_CSPI1_OFFSET)
#define CCM_PCCR_CSPI2_MASK (1 << CCM_PCCR_CSPI2_OFFSET)
#define CCM_PCCR_CSPI3_MASK (1 << CCM_PCCR_CSPI3_OFFSET)
#define CCM_PCCR_DMA_MASK (1 << CCM_PCCR_DMA_OFFSET)
#define CCM_PCCR_EMMA_MASK (1 << CCM_PCCR_EMMA_OFFSET)
#define CCM_PCCR_GPIO_MASK (1 << CCM_PCCR_GPIO_OFFSET)
#define CCM_PCCR_GPT1_MASK (1 << CCM_PCCR_GPT1_OFFSET)
#define CCM_PCCR_GPT2_MASK (1 << CCM_PCCR_GPT2_OFFSET)
#define CCM_PCCR_GPT3_MASK (1 << CCM_PCCR_GPT3_OFFSET)
#define CCM_PCCR_HCLK_BROM_MASK (1 << CCM_PCCR_HCLK_BROM_OFFSET)
#define CCM_PCCR_HCLK_CSI_MASK (1 << CCM_PCCR_HCLK_CSI_OFFSET)
#define CCM_PCCR_HCLK_DMA_MASK (1 << CCM_PCCR_HCLK_DMA_OFFSET)
#define CCM_PCCR_HCLK_EMMA_MASK (1 << CCM_PCCR_HCLK_EMMA_OFFSET)
#define CCM_PCCR_HCLK_LCDC_MASK (1 << CCM_PCCR_HCLK_LCDC_OFFSET)
#define CCM_PCCR_HCLK_SLCDC_MASK (1 << CCM_PCCR_HCLK_SLCDC_OFFSET)
#define CCM_PCCR_HCLK_USBOTG_MASK (1 << CCM_PCCR_HCLK_USBOTG_OFFSET)
#define CCM_PCCR_I2C1_MASK (1 << CCM_PCCR_I2C1_OFFSET)
#define CCM_PCCR_KPP_MASK (1 << CCM_PCCR_KPP_OFFSET)
#define CCM_PCCR_LCDC_MASK (1 << CCM_PCCR_LCDC_OFFSET)
#define CCM_PCCR_NFC_MASK (1 << CCM_PCCR_NFC_OFFSET)
#define CCM_PCCR_OWIRE_MASK (1 << CCM_PCCR_OWIRE_OFFSET)
#define CCM_PCCR_PERCLK4_MASK (1 << CCM_PCCR_PERCLK4_OFFSET)
#define CCM_PCCR_PWM_MASK (1 << CCM_PCCR_PWM_OFFSET)
#define CCM_PCCR_RTC_MASK (1 << CCM_PCCR_RTC_OFFSET)
#define CCM_PCCR_SDHC1_MASK (1 << CCM_PCCR_SDHC1_OFFSET)
#define CCM_PCCR_SDHC2_MASK (1 << CCM_PCCR_SDHC2_OFFSET)
#define CCM_PCCR_SLCDC_MASK (1 << CCM_PCCR_SLCDC_OFFSET)
#define CCM_PCCR_SSI1_BAUD_MASK (1 << CCM_PCCR_SSI1_BAUD_OFFSET)
#define CCM_PCCR_SSI1_IPG_MASK (1 << CCM_PCCR_SSI1_IPG_OFFSET)
#define CCM_PCCR_SSI2_BAUD_MASK (1 << CCM_PCCR_SSI2_BAUD_OFFSET)
#define CCM_PCCR_SSI2_IPG_MASK (1 << CCM_PCCR_SSI2_IPG_OFFSET)
#define CCM_PCCR_UART1_MASK (1 << CCM_PCCR_UART1_OFFSET)
#define CCM_PCCR_UART2_MASK (1 << CCM_PCCR_UART2_OFFSET)
#define CCM_PCCR_UART3_MASK (1 << CCM_PCCR_UART3_OFFSET)
#define CCM_PCCR_UART4_MASK (1 << CCM_PCCR_UART4_OFFSET)
#define CCM_PCCR_USBOTG_MASK (1 << CCM_PCCR_USBOTG_OFFSET)
#define CCM_PCCR_WDT_MASK (1 << CCM_PCCR_WDT_OFFSET)
#define CCM_CCSR_32KSR (1 << 15)
#define CCM_CCSR_CLKMODE1 (1 << 9)
#define CCM_CCSR_CLKMODE0 (1 << 8)
#define CCM_CCSR_CLKOSEL_OFFSET 0
#define CCM_CCSR_CLKOSEL_MASK 0x1f
#define SYS_FMCR 0x14
/* Functional Muxing Control Reg */
#define SYS_CHIP_ID 0x00
/* The offset of CHIP ID register */
static
int
_clk_enable
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
__raw_readl
(
clk
->
enable_reg
);
reg
|=
1
<<
clk
->
enable_shift
;
__raw_writel
(
reg
,
clk
->
enable_reg
);
return
0
;
}
static
void
_clk_disable
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
__raw_readl
(
clk
->
enable_reg
);
reg
&=
~
(
1
<<
clk
->
enable_shift
);
__raw_writel
(
reg
,
clk
->
enable_reg
);
}
static
unsigned
long
_clk_generic_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
,
u32
max_divisor
)
{
u32
div
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
div
=
parent_rate
/
rate
;
if
(
parent_rate
%
rate
)
div
++
;
if
(
div
>
max_divisor
)
div
=
max_divisor
;
return
parent_rate
/
div
;
}
static
int
_clk_spll_enable
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
__raw_readl
(
CCM_CSCR
);
reg
|=
CCM_CSCR_SPEN
;
__raw_writel
(
reg
,
CCM_CSCR
);
while
((
__raw_readl
(
CCM_SPCTL1
)
&
CCM_SPCTL1_LF
)
==
0
)
;
return
0
;
}
static
void
_clk_spll_disable
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
__raw_readl
(
CCM_CSCR
);
reg
&=
~
CCM_CSCR_SPEN
;
__raw_writel
(
reg
,
CCM_CSCR
);
}
#define CSCR() (__raw_readl(CCM_CSCR))
#define PCDR0() (__raw_readl(CCM_PCDR0))
#define PCDR1() (__raw_readl(CCM_PCDR1))
static
unsigned
long
_clk_perclkx_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
return
_clk_generic_round_rate
(
clk
,
rate
,
64
);
}
static
int
_clk_perclkx_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
reg
;
u32
div
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
if
(
clk
->
id
<
0
||
clk
->
id
>
3
)
return
-
EINVAL
;
div
=
parent_rate
/
rate
;
if
(
div
>
64
||
div
<
1
||
((
parent_rate
/
div
)
!=
rate
))
return
-
EINVAL
;
div
--
;
reg
=
__raw_readl
(
CCM_PCDR1
)
&
~
(
CCM_PCDR1_PERDIV1_MASK
<<
(
clk
->
id
<<
3
));
reg
|=
div
<<
(
clk
->
id
<<
3
);
__raw_writel
(
reg
,
CCM_PCDR1
);
return
0
;
}
static
unsigned
long
_clk_usb_recalc
(
struct
clk
*
clk
)
{
unsigned
long
usb_pdf
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
usb_pdf
=
(
CSCR
()
&
CCM_CSCR_USB_MASK
)
>>
CCM_CSCR_USB_OFFSET
;
return
parent_rate
/
(
usb_pdf
+
1U
);
}
static
unsigned
long
_clk_usb_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
return
_clk_generic_round_rate
(
clk
,
rate
,
8
);
}
static
int
_clk_usb_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
reg
;
u32
div
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
div
=
parent_rate
/
rate
;
if
(
div
>
8
||
div
<
1
||
((
parent_rate
/
div
)
!=
rate
))
return
-
EINVAL
;
div
--
;
reg
=
CSCR
()
&
~
CCM_CSCR_USB_MASK
;
reg
|=
div
<<
CCM_CSCR_USB_OFFSET
;
__raw_writel
(
reg
,
CCM_CSCR
);
return
0
;
}
static
unsigned
long
_clk_ssix_recalc
(
struct
clk
*
clk
,
unsigned
long
pdf
)
{
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
pdf
=
(
pdf
<
2
)
?
124UL
:
pdf
;
/* MX21 & MX27 TO1 */
return
2UL
*
parent_rate
/
pdf
;
}
static
unsigned
long
_clk_ssi1_recalc
(
struct
clk
*
clk
)
{
return
_clk_ssix_recalc
(
clk
,
(
PCDR0
()
&
CCM_PCDR0_SSI1BAUDDIV_MASK
)
>>
CCM_PCDR0_SSI1BAUDDIV_OFFSET
);
}
static
unsigned
long
_clk_ssi2_recalc
(
struct
clk
*
clk
)
{
return
_clk_ssix_recalc
(
clk
,
(
PCDR0
()
&
CCM_PCDR0_SSI2BAUDDIV_MASK
)
>>
CCM_PCDR0_SSI2BAUDDIV_OFFSET
);
}
static
unsigned
long
_clk_nfc_recalc
(
struct
clk
*
clk
)
{
unsigned
long
nfc_pdf
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
nfc_pdf
=
(
PCDR0
()
&
CCM_PCDR0_NFCDIV_MASK
)
>>
CCM_PCDR0_NFCDIV_OFFSET
;
return
parent_rate
/
(
nfc_pdf
+
1
);
}
static
unsigned
long
_clk_parent_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
return
clk
->
parent
->
round_rate
(
clk
->
parent
,
rate
);
}
static
int
_clk_parent_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
return
clk
->
parent
->
set_rate
(
clk
->
parent
,
rate
);
}
static
unsigned
long
external_high_reference
;
/* in Hz */
static
unsigned
long
get_high_reference_clock_rate
(
struct
clk
*
clk
)
{
return
external_high_reference
;
}
/*
* the high frequency external clock reference
* Default case is 26MHz.
*/
static
struct
clk
ckih_clk
=
{
.
get_rate
=
get_high_reference_clock_rate
,
};
static
unsigned
long
external_low_reference
;
/* in Hz */
static
unsigned
long
get_low_reference_clock_rate
(
struct
clk
*
clk
)
{
return
external_low_reference
;
}
/*
* the low frequency external clock reference
* Default case is 32.768kHz.
*/
static
struct
clk
ckil_clk
=
{
.
get_rate
=
get_low_reference_clock_rate
,
};
static
unsigned
long
_clk_fpm_recalc
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
)
*
512
;
}
/* Output of frequency pre multiplier */
static
struct
clk
fpm_clk
=
{
.
parent
=
&
ckil_clk
,
.
get_rate
=
_clk_fpm_recalc
,
};
static
unsigned
long
get_mpll_clk
(
struct
clk
*
clk
)
{
uint32_t
reg
;
unsigned
long
ref_clk
;
unsigned
long
mfi
=
0
,
mfn
=
0
,
mfd
=
0
,
pdf
=
0
;
unsigned
long
long
temp
;
ref_clk
=
clk_get_rate
(
clk
->
parent
);
reg
=
__raw_readl
(
CCM_MPCTL0
);
pdf
=
(
reg
&
CCM_MPCTL0_PD_MASK
)
>>
CCM_MPCTL0_PD_OFFSET
;
mfd
=
(
reg
&
CCM_MPCTL0_MFD_MASK
)
>>
CCM_MPCTL0_MFD_OFFSET
;
mfi
=
(
reg
&
CCM_MPCTL0_MFI_MASK
)
>>
CCM_MPCTL0_MFI_OFFSET
;
mfn
=
(
reg
&
CCM_MPCTL0_MFN_MASK
)
>>
CCM_MPCTL0_MFN_OFFSET
;
mfi
=
(
mfi
<=
5
)
?
5
:
mfi
;
temp
=
2LL
*
ref_clk
*
mfn
;
do_div
(
temp
,
mfd
+
1
);
temp
=
2LL
*
ref_clk
*
mfi
+
temp
;
do_div
(
temp
,
pdf
+
1
);
return
(
unsigned
long
)
temp
;
}
static
struct
clk
mpll_clk
=
{
.
parent
=
&
ckih_clk
,
.
get_rate
=
get_mpll_clk
,
};
static
unsigned
long
_clk_fclk_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
parent_rate
;
u32
div
;
div
=
(
CSCR
()
&
CCM_CSCR_PRESC_MASK
)
>>
CCM_CSCR_PRESC_OFFSET
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
return
parent_rate
/
(
div
+
1
);
}
static
struct
clk
fclk_clk
=
{
.
parent
=
&
mpll_clk
,
.
get_rate
=
_clk_fclk_get_rate
};
static
unsigned
long
get_spll_clk
(
struct
clk
*
clk
)
{
uint32_t
reg
;
unsigned
long
ref_clk
;
unsigned
long
mfi
=
0
,
mfn
=
0
,
mfd
=
0
,
pdf
=
0
;
unsigned
long
long
temp
;
ref_clk
=
clk_get_rate
(
clk
->
parent
);
reg
=
__raw_readl
(
CCM_SPCTL0
);
pdf
=
(
reg
&
CCM_SPCTL0_PD_MASK
)
>>
CCM_SPCTL0_PD_OFFSET
;
mfd
=
(
reg
&
CCM_SPCTL0_MFD_MASK
)
>>
CCM_SPCTL0_MFD_OFFSET
;
mfi
=
(
reg
&
CCM_SPCTL0_MFI_MASK
)
>>
CCM_SPCTL0_MFI_OFFSET
;
mfn
=
(
reg
&
CCM_SPCTL0_MFN_MASK
)
>>
CCM_SPCTL0_MFN_OFFSET
;
mfi
=
(
mfi
<=
5
)
?
5
:
mfi
;
temp
=
2LL
*
ref_clk
*
mfn
;
do_div
(
temp
,
mfd
+
1
);
temp
=
2LL
*
ref_clk
*
mfi
+
temp
;
do_div
(
temp
,
pdf
+
1
);
return
(
unsigned
long
)
temp
;
}
static
struct
clk
spll_clk
=
{
.
parent
=
&
ckih_clk
,
.
get_rate
=
get_spll_clk
,
.
enable
=
_clk_spll_enable
,
.
disable
=
_clk_spll_disable
,
};
static
unsigned
long
get_hclk_clk
(
struct
clk
*
clk
)
{
unsigned
long
rate
;
unsigned
long
bclk_pdf
;
bclk_pdf
=
(
CSCR
()
&
CCM_CSCR_BCLK_MASK
)
>>
CCM_CSCR_BCLK_OFFSET
;
rate
=
clk_get_rate
(
clk
->
parent
);
return
rate
/
(
bclk_pdf
+
1
);
}
static
struct
clk
hclk_clk
=
{
.
parent
=
&
fclk_clk
,
.
get_rate
=
get_hclk_clk
,
};
static
unsigned
long
get_ipg_clk
(
struct
clk
*
clk
)
{
unsigned
long
rate
;
unsigned
long
ipg_pdf
;
ipg_pdf
=
(
CSCR
()
&
CCM_CSCR_IPDIV
)
>>
CCM_CSCR_IPDIV_OFFSET
;
rate
=
clk_get_rate
(
clk
->
parent
);
return
rate
/
(
ipg_pdf
+
1
);
}
static
struct
clk
ipg_clk
=
{
.
parent
=
&
hclk_clk
,
.
get_rate
=
get_ipg_clk
,
};
static
unsigned
long
_clk_perclkx_recalc
(
struct
clk
*
clk
)
{
unsigned
long
perclk_pdf
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
if
(
clk
->
id
<
0
||
clk
->
id
>
3
)
return
0
;
perclk_pdf
=
(
PCDR1
()
>>
(
clk
->
id
<<
3
))
&
CCM_PCDR1_PERDIV1_MASK
;
return
parent_rate
/
(
perclk_pdf
+
1
);
}
static
struct
clk
per_clk
[]
=
{
{
.
id
=
0
,
.
parent
=
&
mpll_clk
,
.
get_rate
=
_clk_perclkx_recalc
,
},
{
.
id
=
1
,
.
parent
=
&
mpll_clk
,
.
get_rate
=
_clk_perclkx_recalc
,
},
{
.
id
=
2
,
.
parent
=
&
mpll_clk
,
.
round_rate
=
_clk_perclkx_round_rate
,
.
set_rate
=
_clk_perclkx_set_rate
,
.
get_rate
=
_clk_perclkx_recalc
,
/* Enable/Disable done via lcd_clkc[1] */
},
{
.
id
=
3
,
.
parent
=
&
mpll_clk
,
.
round_rate
=
_clk_perclkx_round_rate
,
.
set_rate
=
_clk_perclkx_set_rate
,
.
get_rate
=
_clk_perclkx_recalc
,
/* Enable/Disable done via csi_clk[1] */
},
};
static
struct
clk
uart_ipg_clk
[];
static
struct
clk
uart_clk
[]
=
{
{
.
id
=
0
,
.
parent
=
&
per_clk
[
0
],
.
secondary
=
&
uart_ipg_clk
[
0
],
},
{
.
id
=
1
,
.
parent
=
&
per_clk
[
0
],
.
secondary
=
&
uart_ipg_clk
[
1
],
},
{
.
id
=
2
,
.
parent
=
&
per_clk
[
0
],
.
secondary
=
&
uart_ipg_clk
[
2
],
},
{
.
id
=
3
,
.
parent
=
&
per_clk
[
0
],
.
secondary
=
&
uart_ipg_clk
[
3
],
},
};
static
struct
clk
uart_ipg_clk
[]
=
{
{
.
id
=
0
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_UART1_REG
,
.
enable_shift
=
CCM_PCCR_UART1_OFFSET
,
.
disable
=
_clk_disable
,
},
{
.
id
=
1
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_UART2_REG
,
.
enable_shift
=
CCM_PCCR_UART2_OFFSET
,
.
disable
=
_clk_disable
,
},
{
.
id
=
2
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_UART3_REG
,
.
enable_shift
=
CCM_PCCR_UART3_OFFSET
,
.
disable
=
_clk_disable
,
},
{
.
id
=
3
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_UART4_REG
,
.
enable_shift
=
CCM_PCCR_UART4_OFFSET
,
.
disable
=
_clk_disable
,
},
};
static
struct
clk
gpt_ipg_clk
[];
static
struct
clk
gpt_clk
[]
=
{
{
.
id
=
0
,
.
parent
=
&
per_clk
[
0
],
.
secondary
=
&
gpt_ipg_clk
[
0
],
},
{
.
id
=
1
,
.
parent
=
&
per_clk
[
0
],
.
secondary
=
&
gpt_ipg_clk
[
1
],
},
{
.
id
=
2
,
.
parent
=
&
per_clk
[
0
],
.
secondary
=
&
gpt_ipg_clk
[
2
],
},
};
static
struct
clk
gpt_ipg_clk
[]
=
{
{
.
id
=
0
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_GPT1_REG
,
.
enable_shift
=
CCM_PCCR_GPT1_OFFSET
,
.
disable
=
_clk_disable
,
},
{
.
id
=
1
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_GPT2_REG
,
.
enable_shift
=
CCM_PCCR_GPT2_OFFSET
,
.
disable
=
_clk_disable
,
},
{
.
id
=
2
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_GPT3_REG
,
.
enable_shift
=
CCM_PCCR_GPT3_OFFSET
,
.
disable
=
_clk_disable
,
},
};
static
struct
clk
pwm_clk
[]
=
{
{
.
parent
=
&
per_clk
[
0
],
.
secondary
=
&
pwm_clk
[
1
],
},
{
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_PWM_REG
,
.
enable_shift
=
CCM_PCCR_PWM_OFFSET
,
.
disable
=
_clk_disable
,
},
};
static
struct
clk
sdhc_ipg_clk
[];
static
struct
clk
sdhc_clk
[]
=
{
{
.
id
=
0
,
.
parent
=
&
per_clk
[
1
],
.
secondary
=
&
sdhc_ipg_clk
[
0
],
},
{
.
id
=
1
,
.
parent
=
&
per_clk
[
1
],
.
secondary
=
&
sdhc_ipg_clk
[
1
],
},
};
static
struct
clk
sdhc_ipg_clk
[]
=
{
{
.
id
=
0
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_SDHC1_REG
,
.
enable_shift
=
CCM_PCCR_SDHC1_OFFSET
,
.
disable
=
_clk_disable
,
},
{
.
id
=
1
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_SDHC2_REG
,
.
enable_shift
=
CCM_PCCR_SDHC2_OFFSET
,
.
disable
=
_clk_disable
,
},
};
static
struct
clk
cspi_ipg_clk
[];
static
struct
clk
cspi_clk
[]
=
{
{
.
id
=
0
,
.
parent
=
&
per_clk
[
1
],
.
secondary
=
&
cspi_ipg_clk
[
0
],
},
{
.
id
=
1
,
.
parent
=
&
per_clk
[
1
],
.
secondary
=
&
cspi_ipg_clk
[
1
],
},
{
.
id
=
2
,
.
parent
=
&
per_clk
[
1
],
.
secondary
=
&
cspi_ipg_clk
[
2
],
},
};
static
struct
clk
cspi_ipg_clk
[]
=
{
{
.
id
=
0
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_CSPI1_REG
,
.
enable_shift
=
CCM_PCCR_CSPI1_OFFSET
,
.
disable
=
_clk_disable
,
},
{
.
id
=
1
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_CSPI2_REG
,
.
enable_shift
=
CCM_PCCR_CSPI2_OFFSET
,
.
disable
=
_clk_disable
,
},
{
.
id
=
3
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_CSPI3_REG
,
.
enable_shift
=
CCM_PCCR_CSPI3_OFFSET
,
.
disable
=
_clk_disable
,
},
};
static
struct
clk
lcdc_clk
[]
=
{
{
.
parent
=
&
per_clk
[
2
],
.
secondary
=
&
lcdc_clk
[
1
],
.
round_rate
=
_clk_parent_round_rate
,
.
set_rate
=
_clk_parent_set_rate
,
},
{
.
parent
=
&
ipg_clk
,
.
secondary
=
&
lcdc_clk
[
2
],
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_LCDC_REG
,
.
enable_shift
=
CCM_PCCR_LCDC_OFFSET
,
.
disable
=
_clk_disable
,
},
{
.
parent
=
&
hclk_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_HCLK_LCDC_REG
,
.
enable_shift
=
CCM_PCCR_HCLK_LCDC_OFFSET
,
.
disable
=
_clk_disable
,
},
};
static
struct
clk
csi_clk
[]
=
{
{
.
parent
=
&
per_clk
[
3
],
.
secondary
=
&
csi_clk
[
1
],
.
round_rate
=
_clk_parent_round_rate
,
.
set_rate
=
_clk_parent_set_rate
,
},
{
.
parent
=
&
hclk_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_HCLK_CSI_REG
,
.
enable_shift
=
CCM_PCCR_HCLK_CSI_OFFSET
,
.
disable
=
_clk_disable
,
},
};
static
struct
clk
usb_clk
[]
=
{
{
.
parent
=
&
spll_clk
,
.
secondary
=
&
usb_clk
[
1
],
.
get_rate
=
_clk_usb_recalc
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_USBOTG_REG
,
.
enable_shift
=
CCM_PCCR_USBOTG_OFFSET
,
.
disable
=
_clk_disable
,
.
round_rate
=
_clk_usb_round_rate
,
.
set_rate
=
_clk_usb_set_rate
,
},
{
.
parent
=
&
hclk_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_HCLK_USBOTG_REG
,
.
enable_shift
=
CCM_PCCR_HCLK_USBOTG_OFFSET
,
.
disable
=
_clk_disable
,
}
};
static
struct
clk
ssi_ipg_clk
[];
static
struct
clk
ssi_clk
[]
=
{
{
.
id
=
0
,
.
parent
=
&
mpll_clk
,
.
secondary
=
&
ssi_ipg_clk
[
0
],
.
get_rate
=
_clk_ssi1_recalc
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_SSI1_BAUD_REG
,
.
enable_shift
=
CCM_PCCR_SSI1_BAUD_OFFSET
,
.
disable
=
_clk_disable
,
},
{
.
id
=
1
,
.
parent
=
&
mpll_clk
,
.
secondary
=
&
ssi_ipg_clk
[
1
],
.
get_rate
=
_clk_ssi2_recalc
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_SSI2_BAUD_REG
,
.
enable_shift
=
CCM_PCCR_SSI2_BAUD_OFFSET
,
.
disable
=
_clk_disable
,
},
};
static
struct
clk
ssi_ipg_clk
[]
=
{
{
.
id
=
0
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_SSI1_REG
,
.
enable_shift
=
CCM_PCCR_SSI1_IPG_OFFSET
,
.
disable
=
_clk_disable
,
},
{
.
id
=
1
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_SSI2_REG
,
.
enable_shift
=
CCM_PCCR_SSI2_IPG_OFFSET
,
.
disable
=
_clk_disable
,
},
};
static
struct
clk
nfc_clk
=
{
.
parent
=
&
fclk_clk
,
.
get_rate
=
_clk_nfc_recalc
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_NFC_REG
,
.
enable_shift
=
CCM_PCCR_NFC_OFFSET
,
.
disable
=
_clk_disable
,
};
static
struct
clk
dma_clk
[]
=
{
{
.
parent
=
&
hclk_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_DMA_REG
,
.
enable_shift
=
CCM_PCCR_DMA_OFFSET
,
.
disable
=
_clk_disable
,
.
secondary
=
&
dma_clk
[
1
],
},
{
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_HCLK_DMA_REG
,
.
enable_shift
=
CCM_PCCR_HCLK_DMA_OFFSET
,
.
disable
=
_clk_disable
,
},
};
static
struct
clk
brom_clk
=
{
.
parent
=
&
hclk_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_HCLK_BROM_REG
,
.
enable_shift
=
CCM_PCCR_HCLK_BROM_OFFSET
,
.
disable
=
_clk_disable
,
};
static
struct
clk
emma_clk
[]
=
{
{
.
parent
=
&
hclk_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_EMMA_REG
,
.
enable_shift
=
CCM_PCCR_EMMA_OFFSET
,
.
disable
=
_clk_disable
,
.
secondary
=
&
emma_clk
[
1
],
},
{
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_HCLK_EMMA_REG
,
.
enable_shift
=
CCM_PCCR_HCLK_EMMA_OFFSET
,
.
disable
=
_clk_disable
,
}
};
static
struct
clk
slcdc_clk
[]
=
{
{
.
parent
=
&
hclk_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_SLCDC_REG
,
.
enable_shift
=
CCM_PCCR_SLCDC_OFFSET
,
.
disable
=
_clk_disable
,
.
secondary
=
&
slcdc_clk
[
1
],
},
{
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_HCLK_SLCDC_REG
,
.
enable_shift
=
CCM_PCCR_HCLK_SLCDC_OFFSET
,
.
disable
=
_clk_disable
,
}
};
static
struct
clk
wdog_clk
=
{
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_WDT_REG
,
.
enable_shift
=
CCM_PCCR_WDT_OFFSET
,
.
disable
=
_clk_disable
,
};
static
struct
clk
gpio_clk
=
{
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_GPIO_REG
,
.
enable_shift
=
CCM_PCCR_GPIO_OFFSET
,
.
disable
=
_clk_disable
,
};
static
struct
clk
i2c_clk
=
{
.
id
=
0
,
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_I2C1_REG
,
.
enable_shift
=
CCM_PCCR_I2C1_OFFSET
,
.
disable
=
_clk_disable
,
};
static
struct
clk
kpp_clk
=
{
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_KPP_REG
,
.
enable_shift
=
CCM_PCCR_KPP_OFFSET
,
.
disable
=
_clk_disable
,
};
static
struct
clk
owire_clk
=
{
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_OWIRE_REG
,
.
enable_shift
=
CCM_PCCR_OWIRE_OFFSET
,
.
disable
=
_clk_disable
,
};
static
struct
clk
rtc_clk
=
{
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_enable
,
.
enable_reg
=
CCM_PCCR_RTC_REG
,
.
enable_shift
=
CCM_PCCR_RTC_OFFSET
,
.
disable
=
_clk_disable
,
};
static
unsigned
long
_clk_clko_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
return
_clk_generic_round_rate
(
clk
,
rate
,
8
);
}
static
int
_clk_clko_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
reg
;
u32
div
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
div
=
parent_rate
/
rate
;
if
(
div
>
8
||
div
<
1
||
((
parent_rate
/
div
)
!=
rate
))
return
-
EINVAL
;
div
--
;
reg
=
__raw_readl
(
CCM_PCDR0
);
if
(
clk
->
parent
==
&
usb_clk
[
0
])
{
reg
&=
~
CCM_PCDR0_48MDIV_MASK
;
reg
|=
div
<<
CCM_PCDR0_48MDIV_OFFSET
;
}
__raw_writel
(
reg
,
CCM_PCDR0
);
return
0
;
}
static
unsigned
long
_clk_clko_recalc
(
struct
clk
*
clk
)
{
u32
div
=
0
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
if
(
clk
->
parent
==
&
usb_clk
[
0
])
/* 48M */
div
=
__raw_readl
(
CCM_PCDR0
)
&
CCM_PCDR0_48MDIV_MASK
>>
CCM_PCDR0_48MDIV_OFFSET
;
div
++
;
return
parent_rate
/
div
;
}
static
struct
clk
clko_clk
;
static
int
_clk_clko_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
u32
reg
;
reg
=
__raw_readl
(
CCM_CCSR
)
&
~
CCM_CCSR_CLKOSEL_MASK
;
if
(
parent
==
&
ckil_clk
)
reg
|=
0
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
fpm_clk
)
reg
|=
1
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
ckih_clk
)
reg
|=
2
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
mpll_clk
.
parent
)
reg
|=
3
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
spll_clk
.
parent
)
reg
|=
4
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
mpll_clk
)
reg
|=
5
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
spll_clk
)
reg
|=
6
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
fclk_clk
)
reg
|=
7
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
hclk_clk
)
reg
|=
8
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
ipg_clk
)
reg
|=
9
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
per_clk
[
0
])
reg
|=
0xA
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
per_clk
[
1
])
reg
|=
0xB
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
per_clk
[
2
])
reg
|=
0xC
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
per_clk
[
3
])
reg
|=
0xD
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
ssi_clk
[
0
])
reg
|=
0xE
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
ssi_clk
[
1
])
reg
|=
0xF
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
nfc_clk
)
reg
|=
0x10
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
usb_clk
[
0
])
reg
|=
0x14
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
if
(
parent
==
&
clko_clk
)
reg
|=
0x15
<<
CCM_CCSR_CLKOSEL_OFFSET
;
else
return
-
EINVAL
;
__raw_writel
(
reg
,
CCM_CCSR
);
return
0
;
}
static
struct
clk
clko_clk
=
{
.
get_rate
=
_clk_clko_recalc
,
.
set_rate
=
_clk_clko_set_rate
,
.
round_rate
=
_clk_clko_round_rate
,
.
set_parent
=
_clk_clko_set_parent
,
};
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
},
static
struct
clk_lookup
lookups
[]
=
{
/* It's unlikely that any driver wants one of them directly:
_REGISTER_CLOCK(NULL, "ckih", ckih_clk)
_REGISTER_CLOCK(NULL, "ckil", ckil_clk)
_REGISTER_CLOCK(NULL, "fpm", fpm_clk)
_REGISTER_CLOCK(NULL, "mpll", mpll_clk)
_REGISTER_CLOCK(NULL, "spll", spll_clk)
_REGISTER_CLOCK(NULL, "fclk", fclk_clk)
_REGISTER_CLOCK(NULL, "hclk", hclk_clk)
_REGISTER_CLOCK(NULL, "ipg", ipg_clk)
*/
_REGISTER_CLOCK
(
NULL
,
"perclk1"
,
per_clk
[
0
])
_REGISTER_CLOCK
(
NULL
,
"perclk2"
,
per_clk
[
1
])
_REGISTER_CLOCK
(
NULL
,
"perclk3"
,
per_clk
[
2
])
_REGISTER_CLOCK
(
NULL
,
"perclk4"
,
per_clk
[
3
])
_REGISTER_CLOCK
(
NULL
,
"clko"
,
clko_clk
)
_REGISTER_CLOCK
(
"imx21-uart.0"
,
NULL
,
uart_clk
[
0
])
_REGISTER_CLOCK
(
"imx21-uart.1"
,
NULL
,
uart_clk
[
1
])
_REGISTER_CLOCK
(
"imx21-uart.2"
,
NULL
,
uart_clk
[
2
])
_REGISTER_CLOCK
(
"imx21-uart.3"
,
NULL
,
uart_clk
[
3
])
_REGISTER_CLOCK
(
NULL
,
"gpt1"
,
gpt_clk
[
0
])
_REGISTER_CLOCK
(
NULL
,
"gpt1"
,
gpt_clk
[
1
])
_REGISTER_CLOCK
(
NULL
,
"gpt1"
,
gpt_clk
[
2
])
_REGISTER_CLOCK
(
NULL
,
"pwm"
,
pwm_clk
[
0
])
_REGISTER_CLOCK
(
NULL
,
"sdhc1"
,
sdhc_clk
[
0
])
_REGISTER_CLOCK
(
NULL
,
"sdhc2"
,
sdhc_clk
[
1
])
_REGISTER_CLOCK
(
"imx21-cspi.0"
,
NULL
,
cspi_clk
[
0
])
_REGISTER_CLOCK
(
"imx21-cspi.1"
,
NULL
,
cspi_clk
[
1
])
_REGISTER_CLOCK
(
"imx21-cspi.2"
,
NULL
,
cspi_clk
[
2
])
_REGISTER_CLOCK
(
"imx-fb.0"
,
NULL
,
lcdc_clk
[
0
])
_REGISTER_CLOCK
(
NULL
,
"csi"
,
csi_clk
[
0
])
_REGISTER_CLOCK
(
"imx21-hcd.0"
,
NULL
,
usb_clk
[
0
])
_REGISTER_CLOCK
(
NULL
,
"ssi1"
,
ssi_clk
[
0
])
_REGISTER_CLOCK
(
NULL
,
"ssi2"
,
ssi_clk
[
1
])
_REGISTER_CLOCK
(
"mxc_nand.0"
,
NULL
,
nfc_clk
)
_REGISTER_CLOCK
(
NULL
,
"dma"
,
dma_clk
[
0
])
_REGISTER_CLOCK
(
NULL
,
"brom"
,
brom_clk
)
_REGISTER_CLOCK
(
NULL
,
"emma"
,
emma_clk
[
0
])
_REGISTER_CLOCK
(
NULL
,
"slcdc"
,
slcdc_clk
[
0
])
_REGISTER_CLOCK
(
"imx2-wdt.0"
,
NULL
,
wdog_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpio"
,
gpio_clk
)
_REGISTER_CLOCK
(
"imx-i2c.0"
,
NULL
,
i2c_clk
)
_REGISTER_CLOCK
(
"mxc-keypad"
,
NULL
,
kpp_clk
)
_REGISTER_CLOCK
(
NULL
,
"owire"
,
owire_clk
)
_REGISTER_CLOCK
(
NULL
,
"rtc"
,
rtc_clk
)
};
/*
* must be called very early to get information about the
* available clock rate when the timer framework starts
*/
int
__init
mx21_clocks_init
(
unsigned
long
lref
,
unsigned
long
href
)
{
u32
cscr
;
external_low_reference
=
lref
;
external_high_reference
=
href
;
/* detect clock reference for both system PLL */
cscr
=
CSCR
();
if
(
cscr
&
CCM_CSCR_MCU
)
mpll_clk
.
parent
=
&
ckih_clk
;
else
mpll_clk
.
parent
=
&
fpm_clk
;
if
(
cscr
&
CCM_CSCR_SP
)
spll_clk
.
parent
=
&
ckih_clk
;
else
spll_clk
.
parent
=
&
fpm_clk
;
clkdev_add_table
(
lookups
,
ARRAY_SIZE
(
lookups
));
/* Turn off all clock gates */
__raw_writel
(
0
,
CCM_PCCR0
);
__raw_writel
(
CCM_PCCR_GPT1_MASK
,
CCM_PCCR1
);
/* This turns of the serial PLL as well */
spll_clk
.
disable
(
&
spll_clk
);
/* This will propagate to all children and init all the clock rates. */
clk_enable
(
&
per_clk
[
0
]);
clk_enable
(
&
gpio_clk
);
#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
clk_enable
(
&
uart_clk
[
0
]);
#endif
mxc_timer_init
(
&
gpt_clk
[
0
],
MX21_IO_ADDRESS
(
MX21_GPT1_BASE_ADDR
),
MX21_INT_GPT1
);
return
0
;
}
arch/arm/mach-imx/clock-imx25.c
已删除
100644 → 0
浏览文件 @
2acd1b6f
/*
* Copyright (C) 2009 by Sascha Hauer, Pengutronix
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/clkdev.h>
#include <mach/clock.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/mx25.h>
#define CRM_BASE MX25_IO_ADDRESS(MX25_CRM_BASE_ADDR)
#define CCM_MPCTL 0x00
#define CCM_UPCTL 0x04
#define CCM_CCTL 0x08
#define CCM_CGCR0 0x0C
#define CCM_CGCR1 0x10
#define CCM_CGCR2 0x14
#define CCM_PCDR0 0x18
#define CCM_PCDR1 0x1C
#define CCM_PCDR2 0x20
#define CCM_PCDR3 0x24
#define CCM_RCSR 0x28
#define CCM_CRDR 0x2C
#define CCM_DCVR0 0x30
#define CCM_DCVR1 0x34
#define CCM_DCVR2 0x38
#define CCM_DCVR3 0x3c
#define CCM_LTR0 0x40
#define CCM_LTR1 0x44
#define CCM_LTR2 0x48
#define CCM_LTR3 0x4c
static
unsigned
long
get_rate_mpll
(
void
)
{
ulong
mpctl
=
__raw_readl
(
CRM_BASE
+
CCM_MPCTL
);
return
mxc_decode_pll
(
mpctl
,
24000000
);
}
static
unsigned
long
get_rate_upll
(
void
)
{
ulong
mpctl
=
__raw_readl
(
CRM_BASE
+
CCM_UPCTL
);
return
mxc_decode_pll
(
mpctl
,
24000000
);
}
unsigned
long
get_rate_arm
(
struct
clk
*
clk
)
{
unsigned
long
cctl
=
readl
(
CRM_BASE
+
CCM_CCTL
);
unsigned
long
rate
=
get_rate_mpll
();
if
(
cctl
&
(
1
<<
14
))
rate
=
(
rate
*
3
)
>>
2
;
return
rate
/
((
cctl
>>
30
)
+
1
);
}
static
unsigned
long
get_rate_ahb
(
struct
clk
*
clk
)
{
unsigned
long
cctl
=
readl
(
CRM_BASE
+
CCM_CCTL
);
return
get_rate_arm
(
NULL
)
/
(((
cctl
>>
28
)
&
0x3
)
+
1
);
}
static
unsigned
long
get_rate_ipg
(
struct
clk
*
clk
)
{
return
get_rate_ahb
(
NULL
)
>>
1
;
}
static
unsigned
long
get_rate_per
(
int
per
)
{
unsigned
long
ofs
=
(
per
&
0x3
)
*
8
;
unsigned
long
reg
=
per
&
~
0x3
;
unsigned
long
val
=
(
readl
(
CRM_BASE
+
CCM_PCDR0
+
reg
)
>>
ofs
)
&
0x3f
;
unsigned
long
fref
;
if
(
readl
(
CRM_BASE
+
0x64
)
&
(
1
<<
per
))
fref
=
get_rate_upll
();
else
fref
=
get_rate_ahb
(
NULL
);
return
fref
/
(
val
+
1
);
}
static
unsigned
long
get_rate_uart
(
struct
clk
*
clk
)
{
return
get_rate_per
(
15
);
}
static
unsigned
long
get_rate_ssi2
(
struct
clk
*
clk
)
{
return
get_rate_per
(
14
);
}
static
unsigned
long
get_rate_ssi1
(
struct
clk
*
clk
)
{
return
get_rate_per
(
13
);
}
static
unsigned
long
get_rate_i2c
(
struct
clk
*
clk
)
{
return
get_rate_per
(
6
);
}
static
unsigned
long
get_rate_nfc
(
struct
clk
*
clk
)
{
return
get_rate_per
(
8
);
}
static
unsigned
long
get_rate_gpt
(
struct
clk
*
clk
)
{
return
get_rate_per
(
5
);
}
static
unsigned
long
get_rate_lcdc
(
struct
clk
*
clk
)
{
return
get_rate_per
(
7
);
}
static
unsigned
long
get_rate_esdhc1
(
struct
clk
*
clk
)
{
return
get_rate_per
(
3
);
}
static
unsigned
long
get_rate_esdhc2
(
struct
clk
*
clk
)
{
return
get_rate_per
(
4
);
}
static
unsigned
long
get_rate_csi
(
struct
clk
*
clk
)
{
return
get_rate_per
(
0
);
}
static
unsigned
long
get_rate_otg
(
struct
clk
*
clk
)
{
unsigned
long
cctl
=
readl
(
CRM_BASE
+
CCM_CCTL
);
unsigned
long
rate
=
get_rate_upll
();
return
(
cctl
&
(
1
<<
23
))
?
0
:
rate
/
((
0x3F
&
(
cctl
>>
16
))
+
1
);
}
static
int
clk_cgcr_enable
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
__raw_readl
(
clk
->
enable_reg
);
reg
|=
1
<<
clk
->
enable_shift
;
__raw_writel
(
reg
,
clk
->
enable_reg
);
return
0
;
}
static
void
clk_cgcr_disable
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
__raw_readl
(
clk
->
enable_reg
);
reg
&=
~
(
1
<<
clk
->
enable_shift
);
__raw_writel
(
reg
,
clk
->
enable_reg
);
}
#define DEFINE_CLOCK(name, i, er, es, gr, sr, s) \
static struct clk name = { \
.id = i, \
.enable_reg = CRM_BASE + er, \
.enable_shift = es, \
.get_rate = gr, \
.set_rate = sr, \
.enable = clk_cgcr_enable, \
.disable = clk_cgcr_disable, \
.secondary = s, \
}
/*
* Note: the following IPG clock gating bits are wrongly marked "Reserved" in
* the i.MX25 Reference Manual Rev 1, table 15-13. The information below is
* taken from the Freescale released BSP.
*
* bit reg offset clock
*
* 0 CGCR1 0 AUDMUX
* 12 CGCR1 12 ESAI
* 16 CGCR1 16 GPIO1
* 17 CGCR1 17 GPIO2
* 18 CGCR1 18 GPIO3
* 23 CGCR1 23 I2C1
* 24 CGCR1 24 I2C2
* 25 CGCR1 25 I2C3
* 27 CGCR1 27 IOMUXC
* 28 CGCR1 28 KPP
* 30 CGCR1 30 OWIRE
* 36 CGCR2 4 RTIC
* 51 CGCR2 19 WDOG
*/
DEFINE_CLOCK
(
gpt_clk
,
0
,
CCM_CGCR0
,
5
,
get_rate_gpt
,
NULL
,
NULL
);
DEFINE_CLOCK
(
uart_per_clk
,
0
,
CCM_CGCR0
,
15
,
get_rate_uart
,
NULL
,
NULL
);
DEFINE_CLOCK
(
ssi1_per_clk
,
0
,
CCM_CGCR0
,
13
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
ssi2_per_clk
,
0
,
CCM_CGCR0
,
14
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
cspi1_clk
,
0
,
CCM_CGCR1
,
5
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
cspi2_clk
,
0
,
CCM_CGCR1
,
6
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
cspi3_clk
,
0
,
CCM_CGCR1
,
7
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
esdhc1_ahb_clk
,
0
,
CCM_CGCR0
,
21
,
get_rate_esdhc1
,
NULL
,
NULL
);
DEFINE_CLOCK
(
esdhc1_per_clk
,
0
,
CCM_CGCR0
,
3
,
get_rate_esdhc1
,
NULL
,
&
esdhc1_ahb_clk
);
DEFINE_CLOCK
(
esdhc2_ahb_clk
,
0
,
CCM_CGCR0
,
22
,
get_rate_esdhc2
,
NULL
,
NULL
);
DEFINE_CLOCK
(
esdhc2_per_clk
,
0
,
CCM_CGCR0
,
4
,
get_rate_esdhc2
,
NULL
,
&
esdhc2_ahb_clk
);
DEFINE_CLOCK
(
sdma_ahb_clk
,
0
,
CCM_CGCR0
,
26
,
NULL
,
NULL
,
NULL
);
DEFINE_CLOCK
(
fec_ahb_clk
,
0
,
CCM_CGCR0
,
23
,
NULL
,
NULL
,
NULL
);
DEFINE_CLOCK
(
lcdc_ahb_clk
,
0
,
CCM_CGCR0
,
24
,
NULL
,
NULL
,
NULL
);
DEFINE_CLOCK
(
lcdc_per_clk
,
0
,
CCM_CGCR0
,
7
,
NULL
,
NULL
,
&
lcdc_ahb_clk
);
DEFINE_CLOCK
(
csi_ahb_clk
,
0
,
CCM_CGCR0
,
18
,
get_rate_csi
,
NULL
,
NULL
);
DEFINE_CLOCK
(
csi_per_clk
,
0
,
CCM_CGCR0
,
0
,
get_rate_csi
,
NULL
,
&
csi_ahb_clk
);
DEFINE_CLOCK
(
uart1_clk
,
0
,
CCM_CGCR2
,
14
,
get_rate_uart
,
NULL
,
&
uart_per_clk
);
DEFINE_CLOCK
(
uart2_clk
,
0
,
CCM_CGCR2
,
15
,
get_rate_uart
,
NULL
,
&
uart_per_clk
);
DEFINE_CLOCK
(
uart3_clk
,
0
,
CCM_CGCR2
,
16
,
get_rate_uart
,
NULL
,
&
uart_per_clk
);
DEFINE_CLOCK
(
uart4_clk
,
0
,
CCM_CGCR2
,
17
,
get_rate_uart
,
NULL
,
&
uart_per_clk
);
DEFINE_CLOCK
(
uart5_clk
,
0
,
CCM_CGCR2
,
18
,
get_rate_uart
,
NULL
,
&
uart_per_clk
);
DEFINE_CLOCK
(
nfc_clk
,
0
,
CCM_CGCR0
,
8
,
get_rate_nfc
,
NULL
,
NULL
);
DEFINE_CLOCK
(
usbotg_clk
,
0
,
CCM_CGCR0
,
28
,
get_rate_otg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
pwm1_clk
,
0
,
CCM_CGCR1
,
31
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
pwm2_clk
,
0
,
CCM_CGCR2
,
0
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
pwm3_clk
,
0
,
CCM_CGCR2
,
1
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
pwm4_clk
,
0
,
CCM_CGCR2
,
2
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
kpp_clk
,
0
,
CCM_CGCR1
,
28
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
tsc_clk
,
0
,
CCM_CGCR2
,
13
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
i2c_clk
,
0
,
CCM_CGCR0
,
6
,
get_rate_i2c
,
NULL
,
NULL
);
DEFINE_CLOCK
(
fec_clk
,
0
,
CCM_CGCR1
,
15
,
get_rate_ipg
,
NULL
,
&
fec_ahb_clk
);
DEFINE_CLOCK
(
dryice_clk
,
0
,
CCM_CGCR1
,
8
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
lcdc_clk
,
0
,
CCM_CGCR1
,
29
,
get_rate_lcdc
,
NULL
,
&
lcdc_per_clk
);
DEFINE_CLOCK
(
wdt_clk
,
0
,
CCM_CGCR2
,
19
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
ssi1_clk
,
0
,
CCM_CGCR2
,
11
,
get_rate_ssi1
,
NULL
,
&
ssi1_per_clk
);
DEFINE_CLOCK
(
ssi2_clk
,
1
,
CCM_CGCR2
,
12
,
get_rate_ssi2
,
NULL
,
&
ssi2_per_clk
);
DEFINE_CLOCK
(
sdma_clk
,
0
,
CCM_CGCR2
,
6
,
get_rate_ipg
,
NULL
,
&
sdma_ahb_clk
);
DEFINE_CLOCK
(
esdhc1_clk
,
0
,
CCM_CGCR1
,
13
,
get_rate_esdhc1
,
NULL
,
&
esdhc1_per_clk
);
DEFINE_CLOCK
(
esdhc2_clk
,
1
,
CCM_CGCR1
,
14
,
get_rate_esdhc2
,
NULL
,
&
esdhc2_per_clk
);
DEFINE_CLOCK
(
audmux_clk
,
0
,
CCM_CGCR1
,
0
,
NULL
,
NULL
,
NULL
);
DEFINE_CLOCK
(
csi_clk
,
0
,
CCM_CGCR1
,
4
,
get_rate_csi
,
NULL
,
&
csi_per_clk
);
DEFINE_CLOCK
(
can1_clk
,
0
,
CCM_CGCR1
,
2
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
can2_clk
,
1
,
CCM_CGCR1
,
3
,
get_rate_ipg
,
NULL
,
NULL
);
DEFINE_CLOCK
(
iim_clk
,
0
,
CCM_CGCR1
,
26
,
NULL
,
NULL
,
NULL
);
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
},
static
struct
clk_lookup
lookups
[]
=
{
/* i.mx25 has the i.mx21 type uart */
_REGISTER_CLOCK
(
"imx21-uart.0"
,
NULL
,
uart1_clk
)
_REGISTER_CLOCK
(
"imx21-uart.1"
,
NULL
,
uart2_clk
)
_REGISTER_CLOCK
(
"imx21-uart.2"
,
NULL
,
uart3_clk
)
_REGISTER_CLOCK
(
"imx21-uart.3"
,
NULL
,
uart4_clk
)
_REGISTER_CLOCK
(
"imx21-uart.4"
,
NULL
,
uart5_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.0"
,
"usb"
,
usbotg_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.1"
,
"usb"
,
usbotg_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.2"
,
"usb"
,
usbotg_clk
)
_REGISTER_CLOCK
(
"fsl-usb2-udc"
,
"usb"
,
usbotg_clk
)
_REGISTER_CLOCK
(
"mxc_nand.0"
,
NULL
,
nfc_clk
)
/* i.mx25 has the i.mx35 type cspi */
_REGISTER_CLOCK
(
"imx35-cspi.0"
,
NULL
,
cspi1_clk
)
_REGISTER_CLOCK
(
"imx35-cspi.1"
,
NULL
,
cspi2_clk
)
_REGISTER_CLOCK
(
"imx35-cspi.2"
,
NULL
,
cspi3_clk
)
_REGISTER_CLOCK
(
"mxc_pwm.0"
,
NULL
,
pwm1_clk
)
_REGISTER_CLOCK
(
"mxc_pwm.1"
,
NULL
,
pwm2_clk
)
_REGISTER_CLOCK
(
"mxc_pwm.2"
,
NULL
,
pwm3_clk
)
_REGISTER_CLOCK
(
"mxc_pwm.3"
,
NULL
,
pwm4_clk
)
_REGISTER_CLOCK
(
"imx-keypad"
,
NULL
,
kpp_clk
)
_REGISTER_CLOCK
(
"mx25-adc"
,
NULL
,
tsc_clk
)
_REGISTER_CLOCK
(
"imx-i2c.0"
,
NULL
,
i2c_clk
)
_REGISTER_CLOCK
(
"imx-i2c.1"
,
NULL
,
i2c_clk
)
_REGISTER_CLOCK
(
"imx-i2c.2"
,
NULL
,
i2c_clk
)
_REGISTER_CLOCK
(
"imx25-fec.0"
,
NULL
,
fec_clk
)
_REGISTER_CLOCK
(
"imxdi_rtc.0"
,
NULL
,
dryice_clk
)
_REGISTER_CLOCK
(
"imx-fb.0"
,
NULL
,
lcdc_clk
)
_REGISTER_CLOCK
(
"imx2-wdt.0"
,
NULL
,
wdt_clk
)
_REGISTER_CLOCK
(
"imx-ssi.0"
,
NULL
,
ssi1_clk
)
_REGISTER_CLOCK
(
"imx-ssi.1"
,
NULL
,
ssi2_clk
)
_REGISTER_CLOCK
(
"sdhci-esdhc-imx25.0"
,
NULL
,
esdhc1_clk
)
_REGISTER_CLOCK
(
"sdhci-esdhc-imx25.1"
,
NULL
,
esdhc2_clk
)
_REGISTER_CLOCK
(
"mx2-camera.0"
,
NULL
,
csi_clk
)
_REGISTER_CLOCK
(
NULL
,
"audmux"
,
audmux_clk
)
_REGISTER_CLOCK
(
"flexcan.0"
,
NULL
,
can1_clk
)
_REGISTER_CLOCK
(
"flexcan.1"
,
NULL
,
can2_clk
)
/* i.mx25 has the i.mx35 type sdma */
_REGISTER_CLOCK
(
"imx35-sdma"
,
NULL
,
sdma_clk
)
_REGISTER_CLOCK
(
NULL
,
"iim"
,
iim_clk
)
};
int
__init
mx25_clocks_init
(
void
)
{
clkdev_add_table
(
lookups
,
ARRAY_SIZE
(
lookups
));
/* Turn off all clocks except the ones we need to survive, namely:
* EMI, GPIO1-3 (CCM_CGCR1[18:16]), GPT1, IOMUXC (CCM_CGCR1[27]), IIM,
* SCC
*/
__raw_writel
((
1
<<
19
),
CRM_BASE
+
CCM_CGCR0
);
__raw_writel
((
0xf
<<
16
)
|
(
3
<<
26
),
CRM_BASE
+
CCM_CGCR1
);
__raw_writel
((
1
<<
5
),
CRM_BASE
+
CCM_CGCR2
);
#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
clk_enable
(
&
uart1_clk
);
#endif
/* Clock source for lcdc and csi is upll */
__raw_writel
(
__raw_readl
(
CRM_BASE
+
0x64
)
|
(
1
<<
7
)
|
(
1
<<
0
),
CRM_BASE
+
0x64
);
/* Clock source for gpt is ahb_div */
__raw_writel
(
__raw_readl
(
CRM_BASE
+
0x64
)
&
~
(
1
<<
5
),
CRM_BASE
+
0x64
);
clk_enable
(
&
iim_clk
);
imx_print_silicon_rev
(
"i.MX25"
,
mx25_revision
());
clk_disable
(
&
iim_clk
);
mxc_timer_init
(
&
gpt_clk
,
MX25_IO_ADDRESS
(
MX25_GPT1_BASE_ADDR
),
54
);
return
0
;
}
arch/arm/mach-imx/clock-imx27.c
已删除
100644 → 0
浏览文件 @
2acd1b6f
/*
* Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
* Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/clkdev.h>
#include <linux/of.h>
#include <asm/div64.h>
#include <mach/clock.h>
#include <mach/common.h>
#include <mach/hardware.h>
#define IO_ADDR_CCM(off) (MX27_IO_ADDRESS(MX27_CCM_BASE_ADDR + (off)))
/* Register offsets */
#define CCM_CSCR IO_ADDR_CCM(0x0)
#define CCM_MPCTL0 IO_ADDR_CCM(0x4)
#define CCM_MPCTL1 IO_ADDR_CCM(0x8)
#define CCM_SPCTL0 IO_ADDR_CCM(0xc)
#define CCM_SPCTL1 IO_ADDR_CCM(0x10)
#define CCM_OSC26MCTL IO_ADDR_CCM(0x14)
#define CCM_PCDR0 IO_ADDR_CCM(0x18)
#define CCM_PCDR1 IO_ADDR_CCM(0x1c)
#define CCM_PCCR0 IO_ADDR_CCM(0x20)
#define CCM_PCCR1 IO_ADDR_CCM(0x24)
#define CCM_CCSR IO_ADDR_CCM(0x28)
#define CCM_PMCTL IO_ADDR_CCM(0x2c)
#define CCM_PMCOUNT IO_ADDR_CCM(0x30)
#define CCM_WKGDCTL IO_ADDR_CCM(0x34)
#define CCM_CSCR_UPDATE_DIS (1 << 31)
#define CCM_CSCR_SSI2 (1 << 23)
#define CCM_CSCR_SSI1 (1 << 22)
#define CCM_CSCR_VPU (1 << 21)
#define CCM_CSCR_MSHC (1 << 20)
#define CCM_CSCR_SPLLRES (1 << 19)
#define CCM_CSCR_MPLLRES (1 << 18)
#define CCM_CSCR_SP (1 << 17)
#define CCM_CSCR_MCU (1 << 16)
#define CCM_CSCR_OSC26MDIV (1 << 4)
#define CCM_CSCR_OSC26M (1 << 3)
#define CCM_CSCR_FPM (1 << 2)
#define CCM_CSCR_SPEN (1 << 1)
#define CCM_CSCR_MPEN (1 << 0)
/* i.MX27 TO 2+ */
#define CCM_CSCR_ARM_SRC (1 << 15)
#define CCM_SPCTL1_LF (1 << 15)
#define CCM_SPCTL1_BRMO (1 << 6)
static
struct
clk
mpll_main1_clk
,
mpll_main2_clk
;
static
int
clk_pccr_enable
(
struct
clk
*
clk
)
{
unsigned
long
reg
;
if
(
!
clk
->
enable_reg
)
return
0
;
reg
=
__raw_readl
(
clk
->
enable_reg
);
reg
|=
1
<<
clk
->
enable_shift
;
__raw_writel
(
reg
,
clk
->
enable_reg
);
return
0
;
}
static
void
clk_pccr_disable
(
struct
clk
*
clk
)
{
unsigned
long
reg
;
if
(
!
clk
->
enable_reg
)
return
;
reg
=
__raw_readl
(
clk
->
enable_reg
);
reg
&=
~
(
1
<<
clk
->
enable_shift
);
__raw_writel
(
reg
,
clk
->
enable_reg
);
}
static
int
clk_spll_enable
(
struct
clk
*
clk
)
{
unsigned
long
reg
;
reg
=
__raw_readl
(
CCM_CSCR
);
reg
|=
CCM_CSCR_SPEN
;
__raw_writel
(
reg
,
CCM_CSCR
);
while
(
!
(
__raw_readl
(
CCM_SPCTL1
)
&
CCM_SPCTL1_LF
));
return
0
;
}
static
void
clk_spll_disable
(
struct
clk
*
clk
)
{
unsigned
long
reg
;
reg
=
__raw_readl
(
CCM_CSCR
);
reg
&=
~
CCM_CSCR_SPEN
;
__raw_writel
(
reg
,
CCM_CSCR
);
}
static
int
clk_cpu_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
int
cscr
=
__raw_readl
(
CCM_CSCR
);
if
(
clk
->
parent
==
parent
)
return
0
;
if
(
mx27_revision
()
>=
IMX_CHIP_REVISION_2_0
)
{
if
(
parent
==
&
mpll_main1_clk
)
{
cscr
|=
CCM_CSCR_ARM_SRC
;
}
else
{
if
(
parent
==
&
mpll_main2_clk
)
cscr
&=
~
CCM_CSCR_ARM_SRC
;
else
return
-
EINVAL
;
}
__raw_writel
(
cscr
,
CCM_CSCR
);
clk
->
parent
=
parent
;
return
0
;
}
return
-
ENODEV
;
}
static
unsigned
long
round_rate_cpu
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
int
div
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
div
=
parent_rate
/
rate
;
if
(
parent_rate
%
rate
)
div
++
;
if
(
div
>
4
)
div
=
4
;
return
parent_rate
/
div
;
}
static
int
set_rate_cpu
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
unsigned
int
div
;
uint32_t
reg
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
div
=
parent_rate
/
rate
;
if
(
div
>
4
||
div
<
1
||
((
parent_rate
/
div
)
!=
rate
))
return
-
EINVAL
;
div
--
;
reg
=
__raw_readl
(
CCM_CSCR
);
if
(
mx27_revision
()
>=
IMX_CHIP_REVISION_2_0
)
{
reg
&=
~
(
3
<<
12
);
reg
|=
div
<<
12
;
reg
&=
~
(
CCM_CSCR_FPM
|
CCM_CSCR_SPEN
);
__raw_writel
(
reg
|
CCM_CSCR_UPDATE_DIS
,
CCM_CSCR
);
}
else
{
printk
(
KERN_ERR
"Can't set CPU frequency!
\n
"
);
}
return
0
;
}
static
unsigned
long
round_rate_per
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
div
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
div
=
parent_rate
/
rate
;
if
(
parent_rate
%
rate
)
div
++
;
if
(
div
>
64
)
div
=
64
;
return
parent_rate
/
div
;
}
static
int
set_rate_per
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
reg
;
u32
div
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
if
(
clk
->
id
<
0
||
clk
->
id
>
3
)
return
-
EINVAL
;
div
=
parent_rate
/
rate
;
if
(
div
>
64
||
div
<
1
||
((
parent_rate
/
div
)
!=
rate
))
return
-
EINVAL
;
div
--
;
reg
=
__raw_readl
(
CCM_PCDR1
)
&
~
(
0x3f
<<
(
clk
->
id
<<
3
));
reg
|=
div
<<
(
clk
->
id
<<
3
);
__raw_writel
(
reg
,
CCM_PCDR1
);
return
0
;
}
static
unsigned
long
get_rate_usb
(
struct
clk
*
clk
)
{
unsigned
long
usb_pdf
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
usb_pdf
=
(
__raw_readl
(
CCM_CSCR
)
>>
28
)
&
0x7
;
return
parent_rate
/
(
usb_pdf
+
1U
);
}
static
unsigned
long
get_rate_ssix
(
struct
clk
*
clk
,
unsigned
long
pdf
)
{
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
if
(
mx27_revision
()
>=
IMX_CHIP_REVISION_2_0
)
pdf
+=
4
;
/* MX27 TO2+ */
else
pdf
=
(
pdf
<
2
)
?
124UL
:
pdf
;
/* MX21 & MX27 TO1 */
return
2UL
*
parent_rate
/
pdf
;
}
static
unsigned
long
get_rate_ssi1
(
struct
clk
*
clk
)
{
return
get_rate_ssix
(
clk
,
(
__raw_readl
(
CCM_PCDR0
)
>>
16
)
&
0x3f
);
}
static
unsigned
long
get_rate_ssi2
(
struct
clk
*
clk
)
{
return
get_rate_ssix
(
clk
,
(
__raw_readl
(
CCM_PCDR0
)
>>
26
)
&
0x3f
);
}
static
unsigned
long
get_rate_nfc
(
struct
clk
*
clk
)
{
unsigned
long
nfc_pdf
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
if
(
mx27_revision
()
>=
IMX_CHIP_REVISION_2_0
)
nfc_pdf
=
(
__raw_readl
(
CCM_PCDR0
)
>>
6
)
&
0xf
;
else
nfc_pdf
=
(
__raw_readl
(
CCM_PCDR0
)
>>
12
)
&
0xf
;
return
parent_rate
/
(
nfc_pdf
+
1
);
}
static
unsigned
long
get_rate_vpu
(
struct
clk
*
clk
)
{
unsigned
long
vpu_pdf
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
if
(
mx27_revision
()
>=
IMX_CHIP_REVISION_2_0
)
{
vpu_pdf
=
(
__raw_readl
(
CCM_PCDR0
)
>>
10
)
&
0x3f
;
vpu_pdf
+=
4
;
}
else
{
vpu_pdf
=
(
__raw_readl
(
CCM_PCDR0
)
>>
8
)
&
0xf
;
vpu_pdf
=
(
vpu_pdf
<
2
)
?
124
:
vpu_pdf
;
}
return
2UL
*
parent_rate
/
vpu_pdf
;
}
static
unsigned
long
round_rate_parent
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
return
clk
->
parent
->
round_rate
(
clk
->
parent
,
rate
);
}
static
unsigned
long
get_rate_parent
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
);
}
static
int
set_rate_parent
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
return
clk
->
parent
->
set_rate
(
clk
->
parent
,
rate
);
}
/* in Hz */
static
unsigned
long
external_high_reference
=
26000000
;
static
unsigned
long
get_rate_high_reference
(
struct
clk
*
clk
)
{
return
external_high_reference
;
}
/* in Hz */
static
unsigned
long
external_low_reference
=
32768
;
static
unsigned
long
get_rate_low_reference
(
struct
clk
*
clk
)
{
return
external_low_reference
;
}
static
unsigned
long
get_rate_fpm
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
)
*
1024
;
}
static
unsigned
long
get_rate_mpll
(
struct
clk
*
clk
)
{
return
mxc_decode_pll
(
__raw_readl
(
CCM_MPCTL0
),
clk_get_rate
(
clk
->
parent
));
}
static
unsigned
long
get_rate_mpll_main
(
struct
clk
*
clk
)
{
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
/* i.MX27 TO2:
* clk->id == 0: arm clock source path 1 which is from 2 * MPLL / 2
* clk->id == 1: arm clock source path 2 which is from 2 * MPLL / 3
*/
if
(
mx27_revision
()
>=
IMX_CHIP_REVISION_2_0
&&
clk
->
id
==
1
)
return
2UL
*
parent_rate
/
3UL
;
return
parent_rate
;
}
static
unsigned
long
get_rate_spll
(
struct
clk
*
clk
)
{
uint32_t
reg
;
unsigned
long
rate
;
rate
=
clk_get_rate
(
clk
->
parent
);
reg
=
__raw_readl
(
CCM_SPCTL0
);
/* On TO2 we have to write the value back. Otherwise we
* read 0 from this register the next time.
*/
if
(
mx27_revision
()
>=
IMX_CHIP_REVISION_2_0
)
__raw_writel
(
reg
,
CCM_SPCTL0
);
return
mxc_decode_pll
(
reg
,
rate
);
}
static
unsigned
long
get_rate_cpu
(
struct
clk
*
clk
)
{
u32
div
;
unsigned
long
rate
;
if
(
mx27_revision
()
>=
IMX_CHIP_REVISION_2_0
)
div
=
(
__raw_readl
(
CCM_CSCR
)
>>
12
)
&
0x3
;
else
div
=
(
__raw_readl
(
CCM_CSCR
)
>>
13
)
&
0x7
;
rate
=
clk_get_rate
(
clk
->
parent
);
return
rate
/
(
div
+
1
);
}
static
unsigned
long
get_rate_ahb
(
struct
clk
*
clk
)
{
unsigned
long
rate
,
bclk_pdf
;
if
(
mx27_revision
()
>=
IMX_CHIP_REVISION_2_0
)
bclk_pdf
=
(
__raw_readl
(
CCM_CSCR
)
>>
8
)
&
0x3
;
else
bclk_pdf
=
(
__raw_readl
(
CCM_CSCR
)
>>
9
)
&
0xf
;
rate
=
clk_get_rate
(
clk
->
parent
);
return
rate
/
(
bclk_pdf
+
1
);
}
static
unsigned
long
get_rate_ipg
(
struct
clk
*
clk
)
{
unsigned
long
rate
,
ipg_pdf
;
if
(
mx27_revision
()
>=
IMX_CHIP_REVISION_2_0
)
return
clk_get_rate
(
clk
->
parent
);
else
ipg_pdf
=
(
__raw_readl
(
CCM_CSCR
)
>>
8
)
&
1
;
rate
=
clk_get_rate
(
clk
->
parent
);
return
rate
/
(
ipg_pdf
+
1
);
}
static
unsigned
long
get_rate_per
(
struct
clk
*
clk
)
{
unsigned
long
perclk_pdf
,
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
if
(
clk
->
id
<
0
||
clk
->
id
>
3
)
return
0
;
perclk_pdf
=
(
__raw_readl
(
CCM_PCDR1
)
>>
(
clk
->
id
<<
3
))
&
0x3f
;
return
parent_rate
/
(
perclk_pdf
+
1
);
}
/*
* the high frequency external clock reference
* Default case is 26MHz. Could be changed at runtime
* with a call to change_external_high_reference()
*/
static
struct
clk
ckih_clk
=
{
.
get_rate
=
get_rate_high_reference
,
};
static
struct
clk
mpll_clk
=
{
.
parent
=
&
ckih_clk
,
.
get_rate
=
get_rate_mpll
,
};
/* For i.MX27 TO2, it is the MPLL path 1 of ARM core
* It provides the clock source whose rate is same as MPLL
*/
static
struct
clk
mpll_main1_clk
=
{
.
id
=
0
,
.
parent
=
&
mpll_clk
,
.
get_rate
=
get_rate_mpll_main
,
};
/* For i.MX27 TO2, it is the MPLL path 2 of ARM core
* It provides the clock source whose rate is same MPLL * 2 / 3
*/
static
struct
clk
mpll_main2_clk
=
{
.
id
=
1
,
.
parent
=
&
mpll_clk
,
.
get_rate
=
get_rate_mpll_main
,
};
static
struct
clk
ahb_clk
=
{
.
parent
=
&
mpll_main2_clk
,
.
get_rate
=
get_rate_ahb
,
};
static
struct
clk
ipg_clk
=
{
.
parent
=
&
ahb_clk
,
.
get_rate
=
get_rate_ipg
,
};
static
struct
clk
cpu_clk
=
{
.
parent
=
&
mpll_main2_clk
,
.
set_parent
=
clk_cpu_set_parent
,
.
round_rate
=
round_rate_cpu
,
.
get_rate
=
get_rate_cpu
,
.
set_rate
=
set_rate_cpu
,
};
static
struct
clk
spll_clk
=
{
.
parent
=
&
ckih_clk
,
.
get_rate
=
get_rate_spll
,
.
enable
=
clk_spll_enable
,
.
disable
=
clk_spll_disable
,
};
/*
* the low frequency external clock reference
* Default case is 32.768kHz.
*/
static
struct
clk
ckil_clk
=
{
.
get_rate
=
get_rate_low_reference
,
};
/* Output of frequency pre multiplier */
static
struct
clk
fpm_clk
=
{
.
parent
=
&
ckil_clk
,
.
get_rate
=
get_rate_fpm
,
};
#define PCCR0 CCM_PCCR0
#define PCCR1 CCM_PCCR1
#define DEFINE_CLOCK(name, i, er, es, gr, s, p) \
static struct clk name = { \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
.get_rate = gr, \
.enable = clk_pccr_enable, \
.disable = clk_pccr_disable, \
.secondary = s, \
.parent = p, \
}
#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p) \
static struct clk name = { \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
.get_rate = get_rate_##getsetround, \
.set_rate = set_rate_##getsetround, \
.round_rate = round_rate_##getsetround, \
.enable = clk_pccr_enable, \
.disable = clk_pccr_disable, \
.secondary = s, \
.parent = p, \
}
/* Forward declaration to keep the following list in order */
static
struct
clk
slcdc_clk1
,
sahara2_clk1
,
rtic_clk1
,
fec_clk1
,
emma_clk1
,
dma_clk1
,
lcdc_clk2
,
vpu_clk1
;
/* All clocks we can gate through PCCRx in the order of PCCRx bits */
DEFINE_CLOCK
(
ssi2_clk1
,
1
,
PCCR0
,
0
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
ssi1_clk1
,
0
,
PCCR0
,
1
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
slcdc_clk
,
0
,
PCCR0
,
2
,
NULL
,
&
slcdc_clk1
,
&
ahb_clk
);
DEFINE_CLOCK
(
sdhc3_clk1
,
0
,
PCCR0
,
3
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
sdhc2_clk1
,
0
,
PCCR0
,
4
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
sdhc1_clk1
,
0
,
PCCR0
,
5
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
scc_clk
,
0
,
PCCR0
,
6
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
sahara2_clk
,
0
,
PCCR0
,
7
,
NULL
,
&
sahara2_clk1
,
&
ahb_clk
);
DEFINE_CLOCK
(
rtic_clk
,
0
,
PCCR0
,
8
,
NULL
,
&
rtic_clk1
,
&
ahb_clk
);
DEFINE_CLOCK
(
rtc_clk
,
0
,
PCCR0
,
9
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
pwm_clk1
,
0
,
PCCR0
,
11
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
owire_clk
,
0
,
PCCR0
,
12
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
mstick_clk1
,
0
,
PCCR0
,
13
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
lcdc_clk1
,
0
,
PCCR0
,
14
,
NULL
,
&
lcdc_clk2
,
&
ipg_clk
);
DEFINE_CLOCK
(
kpp_clk
,
0
,
PCCR0
,
15
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
iim_clk
,
0
,
PCCR0
,
16
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
i2c2_clk
,
1
,
PCCR0
,
17
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
i2c1_clk
,
0
,
PCCR0
,
18
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
gpt6_clk1
,
0
,
PCCR0
,
29
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
gpt5_clk1
,
0
,
PCCR0
,
20
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
gpt4_clk1
,
0
,
PCCR0
,
21
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
gpt3_clk1
,
0
,
PCCR0
,
22
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
gpt2_clk1
,
0
,
PCCR0
,
23
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
gpt1_clk1
,
0
,
PCCR0
,
24
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
gpio_clk
,
0
,
PCCR0
,
25
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
fec_clk
,
0
,
PCCR0
,
26
,
NULL
,
&
fec_clk1
,
&
ahb_clk
);
DEFINE_CLOCK
(
emma_clk
,
0
,
PCCR0
,
27
,
NULL
,
&
emma_clk1
,
&
ahb_clk
);
DEFINE_CLOCK
(
dma_clk
,
0
,
PCCR0
,
28
,
NULL
,
&
dma_clk1
,
&
ahb_clk
);
DEFINE_CLOCK
(
cspi13_clk1
,
0
,
PCCR0
,
29
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
cspi2_clk1
,
0
,
PCCR0
,
30
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
cspi1_clk1
,
0
,
PCCR0
,
31
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
mstick_clk
,
0
,
PCCR1
,
2
,
NULL
,
&
mstick_clk1
,
&
ipg_clk
);
DEFINE_CLOCK
(
nfc_clk
,
0
,
PCCR1
,
3
,
get_rate_nfc
,
NULL
,
&
cpu_clk
);
DEFINE_CLOCK
(
ssi2_clk
,
1
,
PCCR1
,
4
,
get_rate_ssi2
,
&
ssi2_clk1
,
&
mpll_main2_clk
);
DEFINE_CLOCK
(
ssi1_clk
,
0
,
PCCR1
,
5
,
get_rate_ssi1
,
&
ssi1_clk1
,
&
mpll_main2_clk
);
DEFINE_CLOCK
(
vpu_clk
,
0
,
PCCR1
,
6
,
get_rate_vpu
,
&
vpu_clk1
,
&
mpll_main2_clk
);
DEFINE_CLOCK1
(
per4_clk
,
3
,
PCCR1
,
7
,
per
,
NULL
,
&
mpll_main2_clk
);
DEFINE_CLOCK1
(
per3_clk
,
2
,
PCCR1
,
8
,
per
,
NULL
,
&
mpll_main2_clk
);
DEFINE_CLOCK1
(
per2_clk
,
1
,
PCCR1
,
9
,
per
,
NULL
,
&
mpll_main2_clk
);
DEFINE_CLOCK1
(
per1_clk
,
0
,
PCCR1
,
10
,
per
,
NULL
,
&
mpll_main2_clk
);
DEFINE_CLOCK
(
usb_clk1
,
0
,
PCCR1
,
11
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
slcdc_clk1
,
0
,
PCCR1
,
12
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
sahara2_clk1
,
0
,
PCCR1
,
13
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
rtic_clk1
,
0
,
PCCR1
,
14
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
lcdc_clk2
,
0
,
PCCR1
,
15
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
vpu_clk1
,
0
,
PCCR1
,
16
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
fec_clk1
,
0
,
PCCR1
,
17
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
emma_clk1
,
0
,
PCCR1
,
18
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
emi_clk
,
0
,
PCCR1
,
19
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
dma_clk1
,
0
,
PCCR1
,
20
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
csi_clk1
,
0
,
PCCR1
,
21
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
brom_clk
,
0
,
PCCR1
,
22
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
pata_clk
,
0
,
PCCR1
,
23
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
wdog_clk
,
0
,
PCCR1
,
24
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
usb_clk
,
0
,
PCCR1
,
25
,
get_rate_usb
,
&
usb_clk1
,
&
spll_clk
);
DEFINE_CLOCK
(
uart6_clk1
,
0
,
PCCR1
,
26
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
uart5_clk1
,
0
,
PCCR1
,
27
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
uart4_clk1
,
0
,
PCCR1
,
28
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
uart3_clk1
,
0
,
PCCR1
,
29
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
uart2_clk1
,
0
,
PCCR1
,
30
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
uart1_clk1
,
0
,
PCCR1
,
31
,
NULL
,
NULL
,
&
ipg_clk
);
/* Clocks we cannot directly gate, but drivers need their rates */
DEFINE_CLOCK
(
cspi1_clk
,
0
,
NULL
,
0
,
NULL
,
&
cspi1_clk1
,
&
per2_clk
);
DEFINE_CLOCK
(
cspi2_clk
,
1
,
NULL
,
0
,
NULL
,
&
cspi2_clk1
,
&
per2_clk
);
DEFINE_CLOCK
(
cspi3_clk
,
2
,
NULL
,
0
,
NULL
,
&
cspi13_clk1
,
&
per2_clk
);
DEFINE_CLOCK
(
sdhc1_clk
,
0
,
NULL
,
0
,
NULL
,
&
sdhc1_clk1
,
&
per2_clk
);
DEFINE_CLOCK
(
sdhc2_clk
,
1
,
NULL
,
0
,
NULL
,
&
sdhc2_clk1
,
&
per2_clk
);
DEFINE_CLOCK
(
sdhc3_clk
,
2
,
NULL
,
0
,
NULL
,
&
sdhc3_clk1
,
&
per2_clk
);
DEFINE_CLOCK
(
pwm_clk
,
0
,
NULL
,
0
,
NULL
,
&
pwm_clk1
,
&
per1_clk
);
DEFINE_CLOCK
(
gpt1_clk
,
0
,
NULL
,
0
,
NULL
,
&
gpt1_clk1
,
&
per1_clk
);
DEFINE_CLOCK
(
gpt2_clk
,
1
,
NULL
,
0
,
NULL
,
&
gpt2_clk1
,
&
per1_clk
);
DEFINE_CLOCK
(
gpt3_clk
,
2
,
NULL
,
0
,
NULL
,
&
gpt3_clk1
,
&
per1_clk
);
DEFINE_CLOCK
(
gpt4_clk
,
3
,
NULL
,
0
,
NULL
,
&
gpt4_clk1
,
&
per1_clk
);
DEFINE_CLOCK
(
gpt5_clk
,
4
,
NULL
,
0
,
NULL
,
&
gpt5_clk1
,
&
per1_clk
);
DEFINE_CLOCK
(
gpt6_clk
,
5
,
NULL
,
0
,
NULL
,
&
gpt6_clk1
,
&
per1_clk
);
DEFINE_CLOCK
(
uart1_clk
,
0
,
NULL
,
0
,
NULL
,
&
uart1_clk1
,
&
per1_clk
);
DEFINE_CLOCK
(
uart2_clk
,
1
,
NULL
,
0
,
NULL
,
&
uart2_clk1
,
&
per1_clk
);
DEFINE_CLOCK
(
uart3_clk
,
2
,
NULL
,
0
,
NULL
,
&
uart3_clk1
,
&
per1_clk
);
DEFINE_CLOCK
(
uart4_clk
,
3
,
NULL
,
0
,
NULL
,
&
uart4_clk1
,
&
per1_clk
);
DEFINE_CLOCK
(
uart5_clk
,
4
,
NULL
,
0
,
NULL
,
&
uart5_clk1
,
&
per1_clk
);
DEFINE_CLOCK
(
uart6_clk
,
5
,
NULL
,
0
,
NULL
,
&
uart6_clk1
,
&
per1_clk
);
DEFINE_CLOCK1
(
lcdc_clk
,
0
,
NULL
,
0
,
parent
,
&
lcdc_clk1
,
&
per3_clk
);
DEFINE_CLOCK1
(
csi_clk
,
0
,
NULL
,
0
,
parent
,
&
csi_clk1
,
&
per4_clk
);
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
},
static
struct
clk_lookup
lookups
[]
=
{
/* i.mx27 has the i.mx21 type uart */
_REGISTER_CLOCK
(
"imx21-uart.0"
,
NULL
,
uart1_clk
)
_REGISTER_CLOCK
(
"imx21-uart.1"
,
NULL
,
uart2_clk
)
_REGISTER_CLOCK
(
"imx21-uart.2"
,
NULL
,
uart3_clk
)
_REGISTER_CLOCK
(
"imx21-uart.3"
,
NULL
,
uart4_clk
)
_REGISTER_CLOCK
(
"imx21-uart.4"
,
NULL
,
uart5_clk
)
_REGISTER_CLOCK
(
"imx21-uart.5"
,
NULL
,
uart6_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpt1"
,
gpt1_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpt2"
,
gpt2_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpt3"
,
gpt3_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpt4"
,
gpt4_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpt5"
,
gpt5_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpt6"
,
gpt6_clk
)
_REGISTER_CLOCK
(
"mxc_pwm.0"
,
NULL
,
pwm_clk
)
_REGISTER_CLOCK
(
"mxc-mmc.0"
,
NULL
,
sdhc1_clk
)
_REGISTER_CLOCK
(
"mxc-mmc.1"
,
NULL
,
sdhc2_clk
)
_REGISTER_CLOCK
(
"mxc-mmc.2"
,
NULL
,
sdhc3_clk
)
_REGISTER_CLOCK
(
"imx27-cspi.0"
,
NULL
,
cspi1_clk
)
_REGISTER_CLOCK
(
"imx27-cspi.1"
,
NULL
,
cspi2_clk
)
_REGISTER_CLOCK
(
"imx27-cspi.2"
,
NULL
,
cspi3_clk
)
_REGISTER_CLOCK
(
"imx-fb.0"
,
NULL
,
lcdc_clk
)
_REGISTER_CLOCK
(
"mx2-camera.0"
,
NULL
,
csi_clk
)
_REGISTER_CLOCK
(
"fsl-usb2-udc"
,
"usb"
,
usb_clk
)
_REGISTER_CLOCK
(
"fsl-usb2-udc"
,
"usb_ahb"
,
usb_clk1
)
_REGISTER_CLOCK
(
"mxc-ehci.0"
,
"usb"
,
usb_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.0"
,
"usb_ahb"
,
usb_clk1
)
_REGISTER_CLOCK
(
"mxc-ehci.1"
,
"usb"
,
usb_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.1"
,
"usb_ahb"
,
usb_clk1
)
_REGISTER_CLOCK
(
"mxc-ehci.2"
,
"usb"
,
usb_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.2"
,
"usb_ahb"
,
usb_clk1
)
_REGISTER_CLOCK
(
"imx-ssi.0"
,
NULL
,
ssi1_clk
)
_REGISTER_CLOCK
(
"imx-ssi.1"
,
NULL
,
ssi2_clk
)
_REGISTER_CLOCK
(
"mxc_nand.0"
,
NULL
,
nfc_clk
)
_REGISTER_CLOCK
(
NULL
,
"vpu"
,
vpu_clk
)
_REGISTER_CLOCK
(
NULL
,
"dma"
,
dma_clk
)
_REGISTER_CLOCK
(
NULL
,
"rtic"
,
rtic_clk
)
_REGISTER_CLOCK
(
NULL
,
"brom"
,
brom_clk
)
_REGISTER_CLOCK
(
NULL
,
"emma"
,
emma_clk
)
_REGISTER_CLOCK
(
"m2m-emmaprp.0"
,
NULL
,
emma_clk
)
_REGISTER_CLOCK
(
NULL
,
"slcdc"
,
slcdc_clk
)
_REGISTER_CLOCK
(
"imx27-fec.0"
,
NULL
,
fec_clk
)
_REGISTER_CLOCK
(
NULL
,
"emi"
,
emi_clk
)
_REGISTER_CLOCK
(
NULL
,
"sahara2"
,
sahara2_clk
)
_REGISTER_CLOCK
(
"pata_imx"
,
NULL
,
pata_clk
)
_REGISTER_CLOCK
(
NULL
,
"mstick"
,
mstick_clk
)
_REGISTER_CLOCK
(
"imx2-wdt.0"
,
NULL
,
wdog_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpio"
,
gpio_clk
)
_REGISTER_CLOCK
(
"imx-i2c.0"
,
NULL
,
i2c1_clk
)
_REGISTER_CLOCK
(
"imx-i2c.1"
,
NULL
,
i2c2_clk
)
_REGISTER_CLOCK
(
NULL
,
"iim"
,
iim_clk
)
_REGISTER_CLOCK
(
NULL
,
"kpp"
,
kpp_clk
)
_REGISTER_CLOCK
(
"mxc_w1.0"
,
NULL
,
owire_clk
)
_REGISTER_CLOCK
(
NULL
,
"rtc"
,
rtc_clk
)
_REGISTER_CLOCK
(
NULL
,
"scc"
,
scc_clk
)
};
/* Adjust the clock path for TO2 and later */
static
void
__init
to2_adjust_clocks
(
void
)
{
unsigned
long
cscr
=
__raw_readl
(
CCM_CSCR
);
if
(
mx27_revision
()
>=
IMX_CHIP_REVISION_2_0
)
{
if
(
cscr
&
CCM_CSCR_ARM_SRC
)
cpu_clk
.
parent
=
&
mpll_main1_clk
;
if
(
!
(
cscr
&
CCM_CSCR_SSI2
))
ssi1_clk
.
parent
=
&
spll_clk
;
if
(
!
(
cscr
&
CCM_CSCR_SSI1
))
ssi1_clk
.
parent
=
&
spll_clk
;
if
(
!
(
cscr
&
CCM_CSCR_VPU
))
vpu_clk
.
parent
=
&
spll_clk
;
}
else
{
cpu_clk
.
parent
=
&
mpll_clk
;
cpu_clk
.
set_parent
=
NULL
;
cpu_clk
.
round_rate
=
NULL
;
cpu_clk
.
set_rate
=
NULL
;
ahb_clk
.
parent
=
&
mpll_clk
;
per1_clk
.
parent
=
&
mpll_clk
;
per2_clk
.
parent
=
&
mpll_clk
;
per3_clk
.
parent
=
&
mpll_clk
;
per4_clk
.
parent
=
&
mpll_clk
;
ssi1_clk
.
parent
=
&
mpll_clk
;
ssi2_clk
.
parent
=
&
mpll_clk
;
vpu_clk
.
parent
=
&
mpll_clk
;
}
}
/*
* must be called very early to get information about the
* available clock rate when the timer framework starts
*/
int
__init
mx27_clocks_init
(
unsigned
long
fref
)
{
u32
cscr
=
__raw_readl
(
CCM_CSCR
);
external_high_reference
=
fref
;
/* detect clock reference for both system PLLs */
if
(
cscr
&
CCM_CSCR_MCU
)
mpll_clk
.
parent
=
&
ckih_clk
;
else
mpll_clk
.
parent
=
&
fpm_clk
;
if
(
cscr
&
CCM_CSCR_SP
)
spll_clk
.
parent
=
&
ckih_clk
;
else
spll_clk
.
parent
=
&
fpm_clk
;
to2_adjust_clocks
();
clkdev_add_table
(
lookups
,
ARRAY_SIZE
(
lookups
));
/* Turn off all clocks we do not need */
__raw_writel
(
0
,
CCM_PCCR0
);
__raw_writel
((
1
<<
10
)
|
(
1
<<
19
),
CCM_PCCR1
);
spll_clk
.
disable
(
&
spll_clk
);
/* enable basic clocks */
clk_enable
(
&
per1_clk
);
clk_enable
(
&
gpio_clk
);
clk_enable
(
&
emi_clk
);
clk_enable
(
&
iim_clk
);
imx_print_silicon_rev
(
"i.MX27"
,
mx27_revision
());
clk_disable
(
&
iim_clk
);
#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
clk_enable
(
&
uart1_clk
);
#endif
mxc_timer_init
(
&
gpt1_clk
,
MX27_IO_ADDRESS
(
MX27_GPT1_BASE_ADDR
),
MX27_INT_GPT1
);
return
0
;
}
#ifdef CONFIG_OF
int
__init
mx27_clocks_init_dt
(
void
)
{
struct
device_node
*
np
;
u32
fref
=
26000000
;
/* default */
for_each_compatible_node
(
np
,
NULL
,
"fixed-clock"
)
{
if
(
!
of_device_is_compatible
(
np
,
"fsl,imx-osc26m"
))
continue
;
if
(
!
of_property_read_u32
(
np
,
"clock-frequency"
,
&
fref
))
break
;
}
return
mx27_clocks_init
(
fref
);
}
#endif
arch/arm/mach-imx/clock-imx31.c
已删除
100644 → 0
浏览文件 @
2acd1b6f
/*
* Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/clkdev.h>
#include <asm/div64.h>
#include <mach/clock.h>
#include <mach/hardware.h>
#include <mach/mx31.h>
#include <mach/common.h>
#include "crmregs-imx3.h"
#define PRE_DIV_MIN_FREQ 10000000
/* Minimum Frequency after Predivider */
static
void
__calc_pre_post_dividers
(
u32
div
,
u32
*
pre
,
u32
*
post
)
{
u32
min_pre
,
temp_pre
,
old_err
,
err
;
if
(
div
>=
512
)
{
*
pre
=
8
;
*
post
=
64
;
}
else
if
(
div
>=
64
)
{
min_pre
=
(
div
-
1
)
/
64
+
1
;
old_err
=
8
;
for
(
temp_pre
=
8
;
temp_pre
>=
min_pre
;
temp_pre
--
)
{
err
=
div
%
temp_pre
;
if
(
err
==
0
)
{
*
pre
=
temp_pre
;
break
;
}
err
=
temp_pre
-
err
;
if
(
err
<
old_err
)
{
old_err
=
err
;
*
pre
=
temp_pre
;
}
}
*
post
=
(
div
+
*
pre
-
1
)
/
*
pre
;
}
else
if
(
div
<=
8
)
{
*
pre
=
div
;
*
post
=
1
;
}
else
{
*
pre
=
1
;
*
post
=
div
;
}
}
static
struct
clk
mcu_pll_clk
;
static
struct
clk
serial_pll_clk
;
static
struct
clk
ipg_clk
;
static
struct
clk
ckih_clk
;
static
int
cgr_enable
(
struct
clk
*
clk
)
{
u32
reg
;
if
(
!
clk
->
enable_reg
)
return
0
;
reg
=
__raw_readl
(
clk
->
enable_reg
);
reg
|=
3
<<
clk
->
enable_shift
;
__raw_writel
(
reg
,
clk
->
enable_reg
);
return
0
;
}
static
void
cgr_disable
(
struct
clk
*
clk
)
{
u32
reg
;
if
(
!
clk
->
enable_reg
)
return
;
reg
=
__raw_readl
(
clk
->
enable_reg
);
reg
&=
~
(
3
<<
clk
->
enable_shift
);
/* special case for EMI clock */
if
(
clk
->
enable_reg
==
MXC_CCM_CGR2
&&
clk
->
enable_shift
==
8
)
reg
|=
(
1
<<
clk
->
enable_shift
);
__raw_writel
(
reg
,
clk
->
enable_reg
);
}
static
unsigned
long
pll_ref_get_rate
(
void
)
{
unsigned
long
ccmr
;
unsigned
int
prcs
;
ccmr
=
__raw_readl
(
MXC_CCM_CCMR
);
prcs
=
(
ccmr
&
MXC_CCM_CCMR_PRCS_MASK
)
>>
MXC_CCM_CCMR_PRCS_OFFSET
;
if
(
prcs
==
0x1
)
return
CKIL_CLK_FREQ
*
1024
;
else
return
clk_get_rate
(
&
ckih_clk
);
}
static
unsigned
long
usb_pll_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
reg
;
reg
=
__raw_readl
(
MXC_CCM_UPCTL
);
return
mxc_decode_pll
(
reg
,
pll_ref_get_rate
());
}
static
unsigned
long
serial_pll_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
reg
;
reg
=
__raw_readl
(
MXC_CCM_SRPCTL
);
return
mxc_decode_pll
(
reg
,
pll_ref_get_rate
());
}
static
unsigned
long
mcu_pll_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
reg
,
ccmr
;
ccmr
=
__raw_readl
(
MXC_CCM_CCMR
);
if
(
!
(
ccmr
&
MXC_CCM_CCMR_MPE
)
||
(
ccmr
&
MXC_CCM_CCMR_MDS
))
return
clk_get_rate
(
&
ckih_clk
);
reg
=
__raw_readl
(
MXC_CCM_MPCTL
);
return
mxc_decode_pll
(
reg
,
pll_ref_get_rate
());
}
static
int
usb_pll_enable
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
__raw_readl
(
MXC_CCM_CCMR
);
reg
|=
MXC_CCM_CCMR_UPE
;
__raw_writel
(
reg
,
MXC_CCM_CCMR
);
/* No lock bit on MX31, so using max time from spec */
udelay
(
80
);
return
0
;
}
static
void
usb_pll_disable
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
__raw_readl
(
MXC_CCM_CCMR
);
reg
&=
~
MXC_CCM_CCMR_UPE
;
__raw_writel
(
reg
,
MXC_CCM_CCMR
);
}
static
int
serial_pll_enable
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
__raw_readl
(
MXC_CCM_CCMR
);
reg
|=
MXC_CCM_CCMR_SPE
;
__raw_writel
(
reg
,
MXC_CCM_CCMR
);
/* No lock bit on MX31, so using max time from spec */
udelay
(
80
);
return
0
;
}
static
void
serial_pll_disable
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
__raw_readl
(
MXC_CCM_CCMR
);
reg
&=
~
MXC_CCM_CCMR_SPE
;
__raw_writel
(
reg
,
MXC_CCM_CCMR
);
}
#define PDR0(mask, off) ((__raw_readl(MXC_CCM_PDR0) & mask) >> off)
#define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off)
#define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off)
static
unsigned
long
mcu_main_get_rate
(
struct
clk
*
clk
)
{
u32
pmcr0
=
__raw_readl
(
MXC_CCM_PMCR0
);
if
((
pmcr0
&
MXC_CCM_PMCR0_DFSUP1
)
==
MXC_CCM_PMCR0_DFSUP1_SPLL
)
return
clk_get_rate
(
&
serial_pll_clk
);
else
return
clk_get_rate
(
&
mcu_pll_clk
);
}
static
unsigned
long
ahb_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
max_pdf
;
max_pdf
=
PDR0
(
MXC_CCM_PDR0_MAX_PODF_MASK
,
MXC_CCM_PDR0_MAX_PODF_OFFSET
);
return
clk_get_rate
(
clk
->
parent
)
/
(
max_pdf
+
1
);
}
static
unsigned
long
ipg_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
ipg_pdf
;
ipg_pdf
=
PDR0
(
MXC_CCM_PDR0_IPG_PODF_MASK
,
MXC_CCM_PDR0_IPG_PODF_OFFSET
);
return
clk_get_rate
(
clk
->
parent
)
/
(
ipg_pdf
+
1
);
}
static
unsigned
long
nfc_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
nfc_pdf
;
nfc_pdf
=
PDR0
(
MXC_CCM_PDR0_NFC_PODF_MASK
,
MXC_CCM_PDR0_NFC_PODF_OFFSET
);
return
clk_get_rate
(
clk
->
parent
)
/
(
nfc_pdf
+
1
);
}
static
unsigned
long
hsp_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
hsp_pdf
;
hsp_pdf
=
PDR0
(
MXC_CCM_PDR0_HSP_PODF_MASK
,
MXC_CCM_PDR0_HSP_PODF_OFFSET
);
return
clk_get_rate
(
clk
->
parent
)
/
(
hsp_pdf
+
1
);
}
static
unsigned
long
usb_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
usb_pdf
,
usb_prepdf
;
usb_pdf
=
PDR1
(
MXC_CCM_PDR1_USB_PODF_MASK
,
MXC_CCM_PDR1_USB_PODF_OFFSET
);
usb_prepdf
=
PDR1
(
MXC_CCM_PDR1_USB_PRDF_MASK
,
MXC_CCM_PDR1_USB_PRDF_OFFSET
);
return
clk_get_rate
(
clk
->
parent
)
/
(
usb_prepdf
+
1
)
/
(
usb_pdf
+
1
);
}
static
unsigned
long
csi_get_rate
(
struct
clk
*
clk
)
{
u32
reg
,
pre
,
post
;
reg
=
__raw_readl
(
MXC_CCM_PDR0
);
pre
=
(
reg
&
MXC_CCM_PDR0_CSI_PRDF_MASK
)
>>
MXC_CCM_PDR0_CSI_PRDF_OFFSET
;
pre
++
;
post
=
(
reg
&
MXC_CCM_PDR0_CSI_PODF_MASK
)
>>
MXC_CCM_PDR0_CSI_PODF_OFFSET
;
post
++
;
return
clk_get_rate
(
clk
->
parent
)
/
(
pre
*
post
);
}
static
unsigned
long
csi_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
pre
,
post
,
parent
=
clk_get_rate
(
clk
->
parent
);
u32
div
=
parent
/
rate
;
if
(
parent
%
rate
)
div
++
;
__calc_pre_post_dividers
(
div
,
&
pre
,
&
post
);
return
parent
/
(
pre
*
post
);
}
static
int
csi_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
reg
,
div
,
pre
,
post
,
parent
=
clk_get_rate
(
clk
->
parent
);
div
=
parent
/
rate
;
if
((
parent
/
div
)
!=
rate
)
return
-
EINVAL
;
__calc_pre_post_dividers
(
div
,
&
pre
,
&
post
);
/* Set CSI clock divider */
reg
=
__raw_readl
(
MXC_CCM_PDR0
)
&
~
(
MXC_CCM_PDR0_CSI_PODF_MASK
|
MXC_CCM_PDR0_CSI_PRDF_MASK
);
reg
|=
(
post
-
1
)
<<
MXC_CCM_PDR0_CSI_PODF_OFFSET
;
reg
|=
(
pre
-
1
)
<<
MXC_CCM_PDR0_CSI_PRDF_OFFSET
;
__raw_writel
(
reg
,
MXC_CCM_PDR0
);
return
0
;
}
static
unsigned
long
ssi1_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
ssi1_pdf
,
ssi1_prepdf
;
ssi1_pdf
=
PDR1
(
MXC_CCM_PDR1_SSI1_PODF_MASK
,
MXC_CCM_PDR1_SSI1_PODF_OFFSET
);
ssi1_prepdf
=
PDR1
(
MXC_CCM_PDR1_SSI1_PRE_PODF_MASK
,
MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET
);
return
clk_get_rate
(
clk
->
parent
)
/
(
ssi1_prepdf
+
1
)
/
(
ssi1_pdf
+
1
);
}
static
unsigned
long
ssi2_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
ssi2_pdf
,
ssi2_prepdf
;
ssi2_pdf
=
PDR1
(
MXC_CCM_PDR1_SSI2_PODF_MASK
,
MXC_CCM_PDR1_SSI2_PODF_OFFSET
);
ssi2_prepdf
=
PDR1
(
MXC_CCM_PDR1_SSI2_PRE_PODF_MASK
,
MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET
);
return
clk_get_rate
(
clk
->
parent
)
/
(
ssi2_prepdf
+
1
)
/
(
ssi2_pdf
+
1
);
}
static
unsigned
long
firi_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
firi_pdf
,
firi_prepdf
;
firi_pdf
=
PDR1
(
MXC_CCM_PDR1_FIRI_PODF_MASK
,
MXC_CCM_PDR1_FIRI_PODF_OFFSET
);
firi_prepdf
=
PDR1
(
MXC_CCM_PDR1_FIRI_PRE_PODF_MASK
,
MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET
);
return
clk_get_rate
(
clk
->
parent
)
/
(
firi_prepdf
+
1
)
/
(
firi_pdf
+
1
);
}
static
unsigned
long
firi_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
pre
,
post
;
u32
parent
=
clk_get_rate
(
clk
->
parent
);
u32
div
=
parent
/
rate
;
if
(
parent
%
rate
)
div
++
;
__calc_pre_post_dividers
(
div
,
&
pre
,
&
post
);
return
parent
/
(
pre
*
post
);
}
static
int
firi_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
reg
,
div
,
pre
,
post
,
parent
=
clk_get_rate
(
clk
->
parent
);
div
=
parent
/
rate
;
if
((
parent
/
div
)
!=
rate
)
return
-
EINVAL
;
__calc_pre_post_dividers
(
div
,
&
pre
,
&
post
);
/* Set FIRI clock divider */
reg
=
__raw_readl
(
MXC_CCM_PDR1
)
&
~
(
MXC_CCM_PDR1_FIRI_PODF_MASK
|
MXC_CCM_PDR1_FIRI_PRE_PODF_MASK
);
reg
|=
(
pre
-
1
)
<<
MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET
;
reg
|=
(
post
-
1
)
<<
MXC_CCM_PDR1_FIRI_PODF_OFFSET
;
__raw_writel
(
reg
,
MXC_CCM_PDR1
);
return
0
;
}
static
unsigned
long
mbx_get_rate
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
)
/
2
;
}
static
unsigned
long
mstick1_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
msti_pdf
;
msti_pdf
=
PDR2
(
MXC_CCM_PDR2_MST1_PDF_MASK
,
MXC_CCM_PDR2_MST1_PDF_OFFSET
);
return
clk_get_rate
(
clk
->
parent
)
/
(
msti_pdf
+
1
);
}
static
unsigned
long
mstick2_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
msti_pdf
;
msti_pdf
=
PDR2
(
MXC_CCM_PDR2_MST2_PDF_MASK
,
MXC_CCM_PDR2_MST2_PDF_OFFSET
);
return
clk_get_rate
(
clk
->
parent
)
/
(
msti_pdf
+
1
);
}
static
unsigned
long
ckih_rate
;
static
unsigned
long
clk_ckih_get_rate
(
struct
clk
*
clk
)
{
return
ckih_rate
;
}
static
unsigned
long
clk_ckil_get_rate
(
struct
clk
*
clk
)
{
return
CKIL_CLK_FREQ
;
}
static
struct
clk
ckih_clk
=
{
.
get_rate
=
clk_ckih_get_rate
,
};
static
struct
clk
mcu_pll_clk
=
{
.
parent
=
&
ckih_clk
,
.
get_rate
=
mcu_pll_get_rate
,
};
static
struct
clk
mcu_main_clk
=
{
.
parent
=
&
mcu_pll_clk
,
.
get_rate
=
mcu_main_get_rate
,
};
static
struct
clk
serial_pll_clk
=
{
.
parent
=
&
ckih_clk
,
.
get_rate
=
serial_pll_get_rate
,
.
enable
=
serial_pll_enable
,
.
disable
=
serial_pll_disable
,
};
static
struct
clk
usb_pll_clk
=
{
.
parent
=
&
ckih_clk
,
.
get_rate
=
usb_pll_get_rate
,
.
enable
=
usb_pll_enable
,
.
disable
=
usb_pll_disable
,
};
static
struct
clk
ahb_clk
=
{
.
parent
=
&
mcu_main_clk
,
.
get_rate
=
ahb_get_rate
,
};
#define DEFINE_CLOCK(name, i, er, es, gr, s, p) \
static struct clk name = { \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
.get_rate = gr, \
.enable = cgr_enable, \
.disable = cgr_disable, \
.secondary = s, \
.parent = p, \
}
#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p) \
static struct clk name = { \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
.get_rate = getsetround##_get_rate, \
.set_rate = getsetround##_set_rate, \
.round_rate = getsetround##_round_rate, \
.enable = cgr_enable, \
.disable = cgr_disable, \
.secondary = s, \
.parent = p, \
}
DEFINE_CLOCK
(
perclk_clk
,
0
,
NULL
,
0
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
ckil_clk
,
0
,
NULL
,
0
,
clk_ckil_get_rate
,
NULL
,
NULL
);
DEFINE_CLOCK
(
sdhc1_clk
,
0
,
MXC_CCM_CGR0
,
0
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
sdhc2_clk
,
1
,
MXC_CCM_CGR0
,
2
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
gpt_clk
,
0
,
MXC_CCM_CGR0
,
4
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
epit1_clk
,
0
,
MXC_CCM_CGR0
,
6
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
epit2_clk
,
1
,
MXC_CCM_CGR0
,
8
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
iim_clk
,
0
,
MXC_CCM_CGR0
,
10
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
pata_clk
,
0
,
MXC_CCM_CGR0
,
12
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
sdma_clk1
,
0
,
MXC_CCM_CGR0
,
14
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
cspi3_clk
,
2
,
MXC_CCM_CGR0
,
16
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
rng_clk
,
0
,
MXC_CCM_CGR0
,
18
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
uart1_clk
,
0
,
MXC_CCM_CGR0
,
20
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
uart2_clk
,
1
,
MXC_CCM_CGR0
,
22
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
ssi1_clk
,
0
,
MXC_CCM_CGR0
,
24
,
ssi1_get_rate
,
NULL
,
&
serial_pll_clk
);
DEFINE_CLOCK
(
i2c1_clk
,
0
,
MXC_CCM_CGR0
,
26
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
i2c2_clk
,
1
,
MXC_CCM_CGR0
,
28
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
i2c3_clk
,
2
,
MXC_CCM_CGR0
,
30
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
mpeg4_clk
,
0
,
MXC_CCM_CGR1
,
0
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
mstick1_clk
,
0
,
MXC_CCM_CGR1
,
2
,
mstick1_get_rate
,
NULL
,
&
usb_pll_clk
);
DEFINE_CLOCK
(
mstick2_clk
,
1
,
MXC_CCM_CGR1
,
4
,
mstick2_get_rate
,
NULL
,
&
usb_pll_clk
);
DEFINE_CLOCK1
(
csi_clk
,
0
,
MXC_CCM_CGR1
,
6
,
csi
,
NULL
,
&
serial_pll_clk
);
DEFINE_CLOCK
(
rtc_clk
,
0
,
MXC_CCM_CGR1
,
8
,
NULL
,
NULL
,
&
ckil_clk
);
DEFINE_CLOCK
(
wdog_clk
,
0
,
MXC_CCM_CGR1
,
10
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
pwm_clk
,
0
,
MXC_CCM_CGR1
,
12
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
usb_clk2
,
0
,
MXC_CCM_CGR1
,
18
,
usb_get_rate
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
kpp_clk
,
0
,
MXC_CCM_CGR1
,
20
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
ipu_clk
,
0
,
MXC_CCM_CGR1
,
22
,
hsp_get_rate
,
NULL
,
&
mcu_main_clk
);
DEFINE_CLOCK
(
uart3_clk
,
2
,
MXC_CCM_CGR1
,
24
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
uart4_clk
,
3
,
MXC_CCM_CGR1
,
26
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
uart5_clk
,
4
,
MXC_CCM_CGR1
,
28
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
owire_clk
,
0
,
MXC_CCM_CGR1
,
30
,
NULL
,
NULL
,
&
perclk_clk
);
DEFINE_CLOCK
(
ssi2_clk
,
1
,
MXC_CCM_CGR2
,
0
,
ssi2_get_rate
,
NULL
,
&
serial_pll_clk
);
DEFINE_CLOCK
(
cspi1_clk
,
0
,
MXC_CCM_CGR2
,
2
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
cspi2_clk
,
1
,
MXC_CCM_CGR2
,
4
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
mbx_clk
,
0
,
MXC_CCM_CGR2
,
6
,
mbx_get_rate
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
emi_clk
,
0
,
MXC_CCM_CGR2
,
8
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
rtic_clk
,
0
,
MXC_CCM_CGR2
,
10
,
NULL
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK1
(
firi_clk
,
0
,
MXC_CCM_CGR2
,
12
,
firi
,
NULL
,
&
usb_pll_clk
);
DEFINE_CLOCK
(
sdma_clk2
,
0
,
NULL
,
0
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
usb_clk1
,
0
,
NULL
,
0
,
usb_get_rate
,
NULL
,
&
usb_pll_clk
);
DEFINE_CLOCK
(
nfc_clk
,
0
,
NULL
,
0
,
nfc_get_rate
,
NULL
,
&
ahb_clk
);
DEFINE_CLOCK
(
scc_clk
,
0
,
NULL
,
0
,
NULL
,
NULL
,
&
ipg_clk
);
DEFINE_CLOCK
(
ipg_clk
,
0
,
NULL
,
0
,
ipg_get_rate
,
NULL
,
&
ahb_clk
);
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
},
static
struct
clk_lookup
lookups
[]
=
{
_REGISTER_CLOCK
(
NULL
,
"emi"
,
emi_clk
)
_REGISTER_CLOCK
(
"imx31-cspi.0"
,
NULL
,
cspi1_clk
)
_REGISTER_CLOCK
(
"imx31-cspi.1"
,
NULL
,
cspi2_clk
)
_REGISTER_CLOCK
(
"imx31-cspi.2"
,
NULL
,
cspi3_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpt"
,
gpt_clk
)
_REGISTER_CLOCK
(
NULL
,
"pwm"
,
pwm_clk
)
_REGISTER_CLOCK
(
"imx2-wdt.0"
,
NULL
,
wdog_clk
)
_REGISTER_CLOCK
(
NULL
,
"rtc"
,
rtc_clk
)
_REGISTER_CLOCK
(
NULL
,
"epit"
,
epit1_clk
)
_REGISTER_CLOCK
(
NULL
,
"epit"
,
epit2_clk
)
_REGISTER_CLOCK
(
"mxc_nand.0"
,
NULL
,
nfc_clk
)
_REGISTER_CLOCK
(
"ipu-core"
,
NULL
,
ipu_clk
)
_REGISTER_CLOCK
(
"mx3_sdc_fb"
,
NULL
,
ipu_clk
)
_REGISTER_CLOCK
(
NULL
,
"kpp"
,
kpp_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.0"
,
"usb"
,
usb_clk1
)
_REGISTER_CLOCK
(
"mxc-ehci.0"
,
"usb_ahb"
,
usb_clk2
)
_REGISTER_CLOCK
(
"mxc-ehci.1"
,
"usb"
,
usb_clk1
)
_REGISTER_CLOCK
(
"mxc-ehci.1"
,
"usb_ahb"
,
usb_clk2
)
_REGISTER_CLOCK
(
"mxc-ehci.2"
,
"usb"
,
usb_clk1
)
_REGISTER_CLOCK
(
"mxc-ehci.2"
,
"usb_ahb"
,
usb_clk2
)
_REGISTER_CLOCK
(
"fsl-usb2-udc"
,
"usb"
,
usb_clk1
)
_REGISTER_CLOCK
(
"fsl-usb2-udc"
,
"usb_ahb"
,
usb_clk2
)
_REGISTER_CLOCK
(
"mx3-camera.0"
,
NULL
,
csi_clk
)
/* i.mx31 has the i.mx21 type uart */
_REGISTER_CLOCK
(
"imx21-uart.0"
,
NULL
,
uart1_clk
)
_REGISTER_CLOCK
(
"imx21-uart.1"
,
NULL
,
uart2_clk
)
_REGISTER_CLOCK
(
"imx21-uart.2"
,
NULL
,
uart3_clk
)
_REGISTER_CLOCK
(
"imx21-uart.3"
,
NULL
,
uart4_clk
)
_REGISTER_CLOCK
(
"imx21-uart.4"
,
NULL
,
uart5_clk
)
_REGISTER_CLOCK
(
"imx-i2c.0"
,
NULL
,
i2c1_clk
)
_REGISTER_CLOCK
(
"imx-i2c.1"
,
NULL
,
i2c2_clk
)
_REGISTER_CLOCK
(
"imx-i2c.2"
,
NULL
,
i2c3_clk
)
_REGISTER_CLOCK
(
"mxc_w1.0"
,
NULL
,
owire_clk
)
_REGISTER_CLOCK
(
"mxc-mmc.0"
,
NULL
,
sdhc1_clk
)
_REGISTER_CLOCK
(
"mxc-mmc.1"
,
NULL
,
sdhc2_clk
)
_REGISTER_CLOCK
(
"imx-ssi.0"
,
NULL
,
ssi1_clk
)
_REGISTER_CLOCK
(
"imx-ssi.1"
,
NULL
,
ssi2_clk
)
_REGISTER_CLOCK
(
NULL
,
"firi"
,
firi_clk
)
_REGISTER_CLOCK
(
"pata_imx"
,
NULL
,
pata_clk
)
_REGISTER_CLOCK
(
NULL
,
"rtic"
,
rtic_clk
)
_REGISTER_CLOCK
(
NULL
,
"rng"
,
rng_clk
)
_REGISTER_CLOCK
(
"imx31-sdma"
,
NULL
,
sdma_clk1
)
_REGISTER_CLOCK
(
NULL
,
"sdma_ipg"
,
sdma_clk2
)
_REGISTER_CLOCK
(
NULL
,
"mstick"
,
mstick1_clk
)
_REGISTER_CLOCK
(
NULL
,
"mstick"
,
mstick2_clk
)
_REGISTER_CLOCK
(
NULL
,
"scc"
,
scc_clk
)
_REGISTER_CLOCK
(
NULL
,
"iim"
,
iim_clk
)
_REGISTER_CLOCK
(
NULL
,
"mpeg4"
,
mpeg4_clk
)
_REGISTER_CLOCK
(
NULL
,
"mbx"
,
mbx_clk
)
};
int
__init
mx31_clocks_init
(
unsigned
long
fref
)
{
u32
reg
;
ckih_rate
=
fref
;
clkdev_add_table
(
lookups
,
ARRAY_SIZE
(
lookups
));
/* change the csi_clk parent if necessary */
reg
=
__raw_readl
(
MXC_CCM_CCMR
);
if
(
!
(
reg
&
MXC_CCM_CCMR_CSCS
))
if
(
clk_set_parent
(
&
csi_clk
,
&
usb_pll_clk
))
pr_err
(
"%s: error changing csi_clk parent
\n
"
,
__func__
);
/* Turn off all possible clocks */
__raw_writel
((
3
<<
4
),
MXC_CCM_CGR0
);
__raw_writel
(
0
,
MXC_CCM_CGR1
);
__raw_writel
((
3
<<
8
)
|
(
3
<<
14
)
|
(
3
<<
16
)
|
1
<<
27
|
1
<<
28
,
/* Bit 27 and 28 are not defined for
MX32, but still required to be set */
MXC_CCM_CGR2
);
/*
* Before turning off usb_pll make sure ipg_per_clk is generated
* by ipg_clk and not usb_pll.
*/
__raw_writel
(
__raw_readl
(
MXC_CCM_CCMR
)
|
(
1
<<
24
),
MXC_CCM_CCMR
);
usb_pll_disable
(
&
usb_pll_clk
);
pr_info
(
"Clock input source is %ld
\n
"
,
clk_get_rate
(
&
ckih_clk
));
clk_enable
(
&
gpt_clk
);
clk_enable
(
&
emi_clk
);
clk_enable
(
&
iim_clk
);
mx31_revision
();
clk_disable
(
&
iim_clk
);
clk_enable
(
&
serial_pll_clk
);
if
(
mx31_revision
()
>=
IMX_CHIP_REVISION_2_0
)
{
reg
=
__raw_readl
(
MXC_CCM_PMCR1
);
/* No PLL restart on DVFS switch; enable auto EMI handshake */
reg
|=
MXC_CCM_PMCR1_PLLRDIS
|
MXC_CCM_PMCR1_EMIRQ_EN
;
__raw_writel
(
reg
,
MXC_CCM_PMCR1
);
}
mxc_timer_init
(
&
ipg_clk
,
MX31_IO_ADDRESS
(
MX31_GPT1_BASE_ADDR
),
MX31_INT_GPT
);
return
0
;
}
arch/arm/mach-imx/clock-imx35.c
已删除
100644 → 0
浏览文件 @
2acd1b6f
/*
* Copyright (C) 2009 by Sascha Hauer, Pengutronix
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/clkdev.h>
#include <mach/clock.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include "crmregs-imx3.h"
#ifdef HAVE_SET_RATE_SUPPORT
static
void
calc_dividers
(
u32
div
,
u32
*
pre
,
u32
*
post
,
u32
maxpost
)
{
u32
min_pre
,
temp_pre
,
old_err
,
err
;
min_pre
=
(
div
-
1
)
/
maxpost
+
1
;
old_err
=
8
;
for
(
temp_pre
=
8
;
temp_pre
>=
min_pre
;
temp_pre
--
)
{
if
(
div
>
(
temp_pre
*
maxpost
))
break
;
if
(
div
<
(
temp_pre
*
temp_pre
))
continue
;
err
=
div
%
temp_pre
;
if
(
err
==
0
)
{
*
pre
=
temp_pre
;
break
;
}
err
=
temp_pre
-
err
;
if
(
err
<
old_err
)
{
old_err
=
err
;
*
pre
=
temp_pre
;
}
}
*
post
=
(
div
+
*
pre
-
1
)
/
*
pre
;
}
/* get the best values for a 3-bit divider combined with a 6-bit divider */
static
void
calc_dividers_3_6
(
u32
div
,
u32
*
pre
,
u32
*
post
)
{
if
(
div
>=
512
)
{
*
pre
=
8
;
*
post
=
64
;
}
else
if
(
div
>=
64
)
{
calc_dividers
(
div
,
pre
,
post
,
64
);
}
else
if
(
div
<=
8
)
{
*
pre
=
div
;
*
post
=
1
;
}
else
{
*
pre
=
1
;
*
post
=
div
;
}
}
/* get the best values for two cascaded 3-bit dividers */
static
void
calc_dividers_3_3
(
u32
div
,
u32
*
pre
,
u32
*
post
)
{
if
(
div
>=
64
)
{
*
pre
=
*
post
=
8
;
}
else
if
(
div
>
8
)
{
calc_dividers
(
div
,
pre
,
post
,
8
);
}
else
{
*
pre
=
1
;
*
post
=
div
;
}
}
#endif
static
unsigned
long
get_rate_mpll
(
void
)
{
ulong
mpctl
=
__raw_readl
(
MX35_CCM_MPCTL
);
return
mxc_decode_pll
(
mpctl
,
24000000
);
}
static
unsigned
long
get_rate_ppll
(
void
)
{
ulong
ppctl
=
__raw_readl
(
MX35_CCM_PPCTL
);
return
mxc_decode_pll
(
ppctl
,
24000000
);
}
struct
arm_ahb_div
{
unsigned
char
arm
,
ahb
,
sel
;
};
static
struct
arm_ahb_div
clk_consumer
[]
=
{
{
.
arm
=
1
,
.
ahb
=
4
,
.
sel
=
0
},
{
.
arm
=
1
,
.
ahb
=
3
,
.
sel
=
1
},
{
.
arm
=
2
,
.
ahb
=
2
,
.
sel
=
0
},
{
.
arm
=
0
,
.
ahb
=
0
,
.
sel
=
0
},
{
.
arm
=
0
,
.
ahb
=
0
,
.
sel
=
0
},
{
.
arm
=
0
,
.
ahb
=
0
,
.
sel
=
0
},
{
.
arm
=
4
,
.
ahb
=
1
,
.
sel
=
0
},
{
.
arm
=
1
,
.
ahb
=
5
,
.
sel
=
0
},
{
.
arm
=
1
,
.
ahb
=
8
,
.
sel
=
0
},
{
.
arm
=
1
,
.
ahb
=
6
,
.
sel
=
1
},
{
.
arm
=
2
,
.
ahb
=
4
,
.
sel
=
0
},
{
.
arm
=
0
,
.
ahb
=
0
,
.
sel
=
0
},
{
.
arm
=
0
,
.
ahb
=
0
,
.
sel
=
0
},
{
.
arm
=
0
,
.
ahb
=
0
,
.
sel
=
0
},
{
.
arm
=
4
,
.
ahb
=
2
,
.
sel
=
0
},
{
.
arm
=
0
,
.
ahb
=
0
,
.
sel
=
0
},
};
static
unsigned
long
get_rate_arm
(
void
)
{
unsigned
long
pdr0
=
__raw_readl
(
MXC_CCM_PDR0
);
struct
arm_ahb_div
*
aad
;
unsigned
long
fref
=
get_rate_mpll
();
aad
=
&
clk_consumer
[(
pdr0
>>
16
)
&
0xf
];
if
(
aad
->
sel
)
fref
=
fref
*
3
/
4
;
return
fref
/
aad
->
arm
;
}
static
unsigned
long
get_rate_ahb
(
struct
clk
*
clk
)
{
unsigned
long
pdr0
=
__raw_readl
(
MXC_CCM_PDR0
);
struct
arm_ahb_div
*
aad
;
unsigned
long
fref
=
get_rate_arm
();
aad
=
&
clk_consumer
[(
pdr0
>>
16
)
&
0xf
];
return
fref
/
aad
->
ahb
;
}
static
unsigned
long
get_rate_ipg
(
struct
clk
*
clk
)
{
return
get_rate_ahb
(
NULL
)
>>
1
;
}
static
unsigned
long
get_rate_uart
(
struct
clk
*
clk
)
{
unsigned
long
pdr3
=
__raw_readl
(
MX35_CCM_PDR3
);
unsigned
long
pdr4
=
__raw_readl
(
MX35_CCM_PDR4
);
unsigned
long
div
=
((
pdr4
>>
10
)
&
0x3f
)
+
1
;
if
(
pdr3
&
(
1
<<
14
))
return
get_rate_arm
()
/
div
;
else
return
get_rate_ppll
()
/
div
;
}
static
unsigned
long
get_rate_sdhc
(
struct
clk
*
clk
)
{
unsigned
long
pdr3
=
__raw_readl
(
MX35_CCM_PDR3
);
unsigned
long
div
,
rate
;
if
(
pdr3
&
(
1
<<
6
))
rate
=
get_rate_arm
();
else
rate
=
get_rate_ppll
();
switch
(
clk
->
id
)
{
default:
case
0
:
div
=
pdr3
&
0x3f
;
break
;
case
1
:
div
=
(
pdr3
>>
8
)
&
0x3f
;
break
;
case
2
:
div
=
(
pdr3
>>
16
)
&
0x3f
;
break
;
}
return
rate
/
(
div
+
1
);
}
static
unsigned
long
get_rate_mshc
(
struct
clk
*
clk
)
{
unsigned
long
pdr1
=
__raw_readl
(
MXC_CCM_PDR1
);
unsigned
long
div1
,
div2
,
rate
;
if
(
pdr1
&
(
1
<<
7
))
rate
=
get_rate_arm
();
else
rate
=
get_rate_ppll
();
div1
=
(
pdr1
>>
29
)
&
0x7
;
div2
=
(
pdr1
>>
22
)
&
0x3f
;
return
rate
/
((
div1
+
1
)
*
(
div2
+
1
));
}
static
unsigned
long
get_rate_ssi
(
struct
clk
*
clk
)
{
unsigned
long
pdr2
=
__raw_readl
(
MX35_CCM_PDR2
);
unsigned
long
div1
,
div2
,
rate
;
if
(
pdr2
&
(
1
<<
6
))
rate
=
get_rate_arm
();
else
rate
=
get_rate_ppll
();
switch
(
clk
->
id
)
{
default:
case
0
:
div1
=
pdr2
&
0x3f
;
div2
=
(
pdr2
>>
24
)
&
0x7
;
break
;
case
1
:
div1
=
(
pdr2
>>
8
)
&
0x3f
;
div2
=
(
pdr2
>>
27
)
&
0x7
;
break
;
}
return
rate
/
((
div1
+
1
)
*
(
div2
+
1
));
}
static
unsigned
long
get_rate_csi
(
struct
clk
*
clk
)
{
unsigned
long
pdr2
=
__raw_readl
(
MX35_CCM_PDR2
);
unsigned
long
rate
;
if
(
pdr2
&
(
1
<<
7
))
rate
=
get_rate_arm
();
else
rate
=
get_rate_ppll
();
return
rate
/
(((
pdr2
>>
16
)
&
0x3f
)
+
1
);
}
static
unsigned
long
get_rate_otg
(
struct
clk
*
clk
)
{
unsigned
long
pdr4
=
__raw_readl
(
MX35_CCM_PDR4
);
unsigned
long
rate
;
if
(
pdr4
&
(
1
<<
9
))
rate
=
get_rate_arm
();
else
rate
=
get_rate_ppll
();
return
rate
/
(((
pdr4
>>
22
)
&
0x3f
)
+
1
);
}
static
unsigned
long
get_rate_ipg_per
(
struct
clk
*
clk
)
{
unsigned
long
pdr0
=
__raw_readl
(
MXC_CCM_PDR0
);
unsigned
long
pdr4
=
__raw_readl
(
MX35_CCM_PDR4
);
unsigned
long
div
;
if
(
pdr0
&
(
1
<<
26
))
{
div
=
(
pdr4
>>
16
)
&
0x3f
;
return
get_rate_arm
()
/
(
div
+
1
);
}
else
{
div
=
(
pdr0
>>
12
)
&
0x7
;
return
get_rate_ahb
(
NULL
)
/
(
div
+
1
);
}
}
static
unsigned
long
get_rate_hsp
(
struct
clk
*
clk
)
{
unsigned
long
hsp_podf
=
(
__raw_readl
(
MXC_CCM_PDR0
)
>>
20
)
&
0x03
;
unsigned
long
fref
=
get_rate_mpll
();
if
(
fref
>
400
*
1000
*
1000
)
{
switch
(
hsp_podf
)
{
case
0
:
return
fref
>>
2
;
case
1
:
return
fref
>>
3
;
case
2
:
return
fref
/
3
;
}
}
else
{
switch
(
hsp_podf
)
{
case
0
:
case
2
:
return
fref
/
3
;
case
1
:
return
fref
/
6
;
}
}
return
0
;
}
static
int
clk_cgr_enable
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
__raw_readl
(
clk
->
enable_reg
);
reg
|=
3
<<
clk
->
enable_shift
;
__raw_writel
(
reg
,
clk
->
enable_reg
);
return
0
;
}
static
void
clk_cgr_disable
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
__raw_readl
(
clk
->
enable_reg
);
reg
&=
~
(
3
<<
clk
->
enable_shift
);
__raw_writel
(
reg
,
clk
->
enable_reg
);
}
#define DEFINE_CLOCK(name, i, er, es, gr, sr) \
static struct clk name = { \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
.get_rate = gr, \
.set_rate = sr, \
.enable = clk_cgr_enable, \
.disable = clk_cgr_disable, \
}
DEFINE_CLOCK
(
asrc_clk
,
0
,
MX35_CCM_CGR0
,
0
,
NULL
,
NULL
);
DEFINE_CLOCK
(
pata_clk
,
0
,
MX35_CCM_CGR0
,
2
,
get_rate_ipg
,
NULL
);
/* DEFINE_CLOCK(audmux_clk, 0, MX35_CCM_CGR0, 4, NULL, NULL); */
DEFINE_CLOCK
(
can1_clk
,
0
,
MX35_CCM_CGR0
,
6
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
can2_clk
,
1
,
MX35_CCM_CGR0
,
8
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
cspi1_clk
,
0
,
MX35_CCM_CGR0
,
10
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
cspi2_clk
,
1
,
MX35_CCM_CGR0
,
12
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
ect_clk
,
0
,
MX35_CCM_CGR0
,
14
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
edio_clk
,
0
,
MX35_CCM_CGR0
,
16
,
NULL
,
NULL
);
DEFINE_CLOCK
(
emi_clk
,
0
,
MX35_CCM_CGR0
,
18
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
epit1_clk
,
0
,
MX35_CCM_CGR0
,
20
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
epit2_clk
,
1
,
MX35_CCM_CGR0
,
22
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
esai_clk
,
0
,
MX35_CCM_CGR0
,
24
,
NULL
,
NULL
);
DEFINE_CLOCK
(
esdhc1_clk
,
0
,
MX35_CCM_CGR0
,
26
,
get_rate_sdhc
,
NULL
);
DEFINE_CLOCK
(
esdhc2_clk
,
1
,
MX35_CCM_CGR0
,
28
,
get_rate_sdhc
,
NULL
);
DEFINE_CLOCK
(
esdhc3_clk
,
2
,
MX35_CCM_CGR0
,
30
,
get_rate_sdhc
,
NULL
);
DEFINE_CLOCK
(
fec_clk
,
0
,
MX35_CCM_CGR1
,
0
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
gpio1_clk
,
0
,
MX35_CCM_CGR1
,
2
,
NULL
,
NULL
);
DEFINE_CLOCK
(
gpio2_clk
,
1
,
MX35_CCM_CGR1
,
4
,
NULL
,
NULL
);
DEFINE_CLOCK
(
gpio3_clk
,
2
,
MX35_CCM_CGR1
,
6
,
NULL
,
NULL
);
DEFINE_CLOCK
(
gpt_clk
,
0
,
MX35_CCM_CGR1
,
8
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
i2c1_clk
,
0
,
MX35_CCM_CGR1
,
10
,
get_rate_ipg_per
,
NULL
);
DEFINE_CLOCK
(
i2c2_clk
,
1
,
MX35_CCM_CGR1
,
12
,
get_rate_ipg_per
,
NULL
);
DEFINE_CLOCK
(
i2c3_clk
,
2
,
MX35_CCM_CGR1
,
14
,
get_rate_ipg_per
,
NULL
);
DEFINE_CLOCK
(
iomuxc_clk
,
0
,
MX35_CCM_CGR1
,
16
,
NULL
,
NULL
);
DEFINE_CLOCK
(
ipu_clk
,
0
,
MX35_CCM_CGR1
,
18
,
get_rate_hsp
,
NULL
);
DEFINE_CLOCK
(
kpp_clk
,
0
,
MX35_CCM_CGR1
,
20
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
mlb_clk
,
0
,
MX35_CCM_CGR1
,
22
,
get_rate_ahb
,
NULL
);
DEFINE_CLOCK
(
mshc_clk
,
0
,
MX35_CCM_CGR1
,
24
,
get_rate_mshc
,
NULL
);
DEFINE_CLOCK
(
owire_clk
,
0
,
MX35_CCM_CGR1
,
26
,
get_rate_ipg_per
,
NULL
);
DEFINE_CLOCK
(
pwm_clk
,
0
,
MX35_CCM_CGR1
,
28
,
get_rate_ipg_per
,
NULL
);
DEFINE_CLOCK
(
rngc_clk
,
0
,
MX35_CCM_CGR1
,
30
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
rtc_clk
,
0
,
MX35_CCM_CGR2
,
0
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
rtic_clk
,
0
,
MX35_CCM_CGR2
,
2
,
get_rate_ahb
,
NULL
);
DEFINE_CLOCK
(
scc_clk
,
0
,
MX35_CCM_CGR2
,
4
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
sdma_clk
,
0
,
MX35_CCM_CGR2
,
6
,
NULL
,
NULL
);
DEFINE_CLOCK
(
spba_clk
,
0
,
MX35_CCM_CGR2
,
8
,
get_rate_ipg
,
NULL
);
DEFINE_CLOCK
(
spdif_clk
,
0
,
MX35_CCM_CGR2
,
10
,
NULL
,
NULL
);
DEFINE_CLOCK
(
ssi1_clk
,
0
,
MX35_CCM_CGR2
,
12
,
get_rate_ssi
,
NULL
);
DEFINE_CLOCK
(
ssi2_clk
,
1
,
MX35_CCM_CGR2
,
14
,
get_rate_ssi
,
NULL
);
DEFINE_CLOCK
(
uart1_clk
,
0
,
MX35_CCM_CGR2
,
16
,
get_rate_uart
,
NULL
);
DEFINE_CLOCK
(
uart2_clk
,
1
,
MX35_CCM_CGR2
,
18
,
get_rate_uart
,
NULL
);
DEFINE_CLOCK
(
uart3_clk
,
2
,
MX35_CCM_CGR2
,
20
,
get_rate_uart
,
NULL
);
DEFINE_CLOCK
(
usbotg_clk
,
0
,
MX35_CCM_CGR2
,
22
,
get_rate_otg
,
NULL
);
DEFINE_CLOCK
(
wdog_clk
,
0
,
MX35_CCM_CGR2
,
24
,
NULL
,
NULL
);
DEFINE_CLOCK
(
max_clk
,
0
,
MX35_CCM_CGR2
,
26
,
NULL
,
NULL
);
DEFINE_CLOCK
(
audmux_clk
,
0
,
MX35_CCM_CGR2
,
30
,
NULL
,
NULL
);
DEFINE_CLOCK
(
csi_clk
,
0
,
MX35_CCM_CGR3
,
0
,
get_rate_csi
,
NULL
);
DEFINE_CLOCK
(
iim_clk
,
0
,
MX35_CCM_CGR3
,
2
,
NULL
,
NULL
);
DEFINE_CLOCK
(
gpu2d_clk
,
0
,
MX35_CCM_CGR3
,
4
,
NULL
,
NULL
);
DEFINE_CLOCK
(
usbahb_clk
,
0
,
0
,
0
,
get_rate_ahb
,
NULL
);
static
int
clk_dummy_enable
(
struct
clk
*
clk
)
{
return
0
;
}
static
void
clk_dummy_disable
(
struct
clk
*
clk
)
{
}
static
unsigned
long
get_rate_nfc
(
struct
clk
*
clk
)
{
unsigned
long
div1
;
div1
=
(
__raw_readl
(
MX35_CCM_PDR4
)
>>
28
)
+
1
;
return
get_rate_ahb
(
NULL
)
/
div1
;
}
/* NAND Controller: It seems it can't be disabled */
static
struct
clk
nfc_clk
=
{
.
id
=
0
,
.
enable_reg
=
0
,
.
enable_shift
=
0
,
.
get_rate
=
get_rate_nfc
,
.
set_rate
=
NULL
,
/* set_rate_nfc, */
.
enable
=
clk_dummy_enable
,
.
disable
=
clk_dummy_disable
};
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
},
static
struct
clk_lookup
lookups
[]
=
{
_REGISTER_CLOCK
(
NULL
,
"asrc"
,
asrc_clk
)
_REGISTER_CLOCK
(
"pata_imx"
,
NULL
,
pata_clk
)
_REGISTER_CLOCK
(
"flexcan.0"
,
NULL
,
can1_clk
)
_REGISTER_CLOCK
(
"flexcan.1"
,
NULL
,
can2_clk
)
_REGISTER_CLOCK
(
"imx35-cspi.0"
,
NULL
,
cspi1_clk
)
_REGISTER_CLOCK
(
"imx35-cspi.1"
,
NULL
,
cspi2_clk
)
_REGISTER_CLOCK
(
NULL
,
"ect"
,
ect_clk
)
_REGISTER_CLOCK
(
NULL
,
"edio"
,
edio_clk
)
_REGISTER_CLOCK
(
NULL
,
"emi"
,
emi_clk
)
_REGISTER_CLOCK
(
"imx-epit.0"
,
NULL
,
epit1_clk
)
_REGISTER_CLOCK
(
"imx-epit.1"
,
NULL
,
epit2_clk
)
_REGISTER_CLOCK
(
NULL
,
"esai"
,
esai_clk
)
_REGISTER_CLOCK
(
"sdhci-esdhc-imx35.0"
,
NULL
,
esdhc1_clk
)
_REGISTER_CLOCK
(
"sdhci-esdhc-imx35.1"
,
NULL
,
esdhc2_clk
)
_REGISTER_CLOCK
(
"sdhci-esdhc-imx35.2"
,
NULL
,
esdhc3_clk
)
/* i.mx35 has the i.mx27 type fec */
_REGISTER_CLOCK
(
"imx27-fec.0"
,
NULL
,
fec_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpio"
,
gpio1_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpio"
,
gpio2_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpio"
,
gpio3_clk
)
_REGISTER_CLOCK
(
"gpt.0"
,
NULL
,
gpt_clk
)
_REGISTER_CLOCK
(
"imx-i2c.0"
,
NULL
,
i2c1_clk
)
_REGISTER_CLOCK
(
"imx-i2c.1"
,
NULL
,
i2c2_clk
)
_REGISTER_CLOCK
(
"imx-i2c.2"
,
NULL
,
i2c3_clk
)
_REGISTER_CLOCK
(
NULL
,
"iomuxc"
,
iomuxc_clk
)
_REGISTER_CLOCK
(
"ipu-core"
,
NULL
,
ipu_clk
)
_REGISTER_CLOCK
(
"mx3_sdc_fb"
,
NULL
,
ipu_clk
)
_REGISTER_CLOCK
(
NULL
,
"kpp"
,
kpp_clk
)
_REGISTER_CLOCK
(
NULL
,
"mlb"
,
mlb_clk
)
_REGISTER_CLOCK
(
NULL
,
"mshc"
,
mshc_clk
)
_REGISTER_CLOCK
(
"mxc_w1"
,
NULL
,
owire_clk
)
_REGISTER_CLOCK
(
NULL
,
"pwm"
,
pwm_clk
)
_REGISTER_CLOCK
(
NULL
,
"rngc"
,
rngc_clk
)
_REGISTER_CLOCK
(
NULL
,
"rtc"
,
rtc_clk
)
_REGISTER_CLOCK
(
NULL
,
"rtic"
,
rtic_clk
)
_REGISTER_CLOCK
(
NULL
,
"scc"
,
scc_clk
)
_REGISTER_CLOCK
(
"imx35-sdma"
,
NULL
,
sdma_clk
)
_REGISTER_CLOCK
(
NULL
,
"spba"
,
spba_clk
)
_REGISTER_CLOCK
(
NULL
,
"spdif"
,
spdif_clk
)
_REGISTER_CLOCK
(
"imx-ssi.0"
,
NULL
,
ssi1_clk
)
_REGISTER_CLOCK
(
"imx-ssi.1"
,
NULL
,
ssi2_clk
)
/* i.mx35 has the i.mx21 type uart */
_REGISTER_CLOCK
(
"imx21-uart.0"
,
NULL
,
uart1_clk
)
_REGISTER_CLOCK
(
"imx21-uart.1"
,
NULL
,
uart2_clk
)
_REGISTER_CLOCK
(
"imx21-uart.2"
,
NULL
,
uart3_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.0"
,
"usb"
,
usbotg_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.1"
,
"usb"
,
usbotg_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.2"
,
"usb"
,
usbotg_clk
)
_REGISTER_CLOCK
(
"fsl-usb2-udc"
,
"usb"
,
usbotg_clk
)
_REGISTER_CLOCK
(
"fsl-usb2-udc"
,
"usb_ahb"
,
usbahb_clk
)
_REGISTER_CLOCK
(
"imx2-wdt.0"
,
NULL
,
wdog_clk
)
_REGISTER_CLOCK
(
NULL
,
"max"
,
max_clk
)
_REGISTER_CLOCK
(
NULL
,
"audmux"
,
audmux_clk
)
_REGISTER_CLOCK
(
"mx3-camera.0"
,
NULL
,
csi_clk
)
_REGISTER_CLOCK
(
NULL
,
"iim"
,
iim_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpu2d"
,
gpu2d_clk
)
_REGISTER_CLOCK
(
"mxc_nand.0"
,
NULL
,
nfc_clk
)
};
int
__init
mx35_clocks_init
()
{
unsigned
int
cgr2
=
3
<<
26
;
#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
cgr2
|=
3
<<
16
;
#endif
clkdev_add_table
(
lookups
,
ARRAY_SIZE
(
lookups
));
/* Turn off all clocks except the ones we need to survive, namely:
* EMI, GPIO1/2/3, GPT, IOMUX, MAX and eventually uart
*/
__raw_writel
((
3
<<
18
),
MX35_CCM_CGR0
);
__raw_writel
((
3
<<
2
)
|
(
3
<<
4
)
|
(
3
<<
6
)
|
(
3
<<
8
)
|
(
3
<<
16
),
MX35_CCM_CGR1
);
__raw_writel
(
cgr2
,
MX35_CCM_CGR2
);
__raw_writel
(
0
,
MX35_CCM_CGR3
);
clk_enable
(
&
iim_clk
);
imx_print_silicon_rev
(
"i.MX35"
,
mx35_revision
());
clk_disable
(
&
iim_clk
);
/*
* Check if we came up in internal boot mode. If yes, we need some
* extra clocks turned on, otherwise the MX35 boot ROM code will
* hang after a watchdog reset.
*/
if
(
!
(
__raw_readl
(
MX35_CCM_RCSR
)
&
(
3
<<
10
)))
{
/* Additionally turn on UART1, SCC, and IIM clocks */
clk_enable
(
&
iim_clk
);
clk_enable
(
&
uart1_clk
);
clk_enable
(
&
scc_clk
);
}
#ifdef CONFIG_MXC_USE_EPIT
epit_timer_init
(
&
epit1_clk
,
MX35_IO_ADDRESS
(
MX35_EPIT1_BASE_ADDR
),
MX35_INT_EPIT1
);
#else
mxc_timer_init
(
&
gpt_clk
,
MX35_IO_ADDRESS
(
MX35_GPT1_BASE_ADDR
),
MX35_INT_GPT
);
#endif
return
0
;
}
arch/arm/mach-imx/clock-imx6q.c
已删除
100644 → 0
浏览文件 @
2acd1b6f
/*
* Copyright 2011 Freescale Semiconductor, Inc.
* Copyright 2011 Linaro Ltd.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/init.h>
#include <linux/types.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <asm/div64.h>
#include <asm/mach/map.h>
#include <mach/clock.h>
#include <mach/common.h>
#include <mach/hardware.h>
#define PLL_BASE IMX_IO_ADDRESS(MX6Q_ANATOP_BASE_ADDR)
#define PLL1_SYS (PLL_BASE + 0x000)
#define PLL2_BUS (PLL_BASE + 0x030)
#define PLL3_USB_OTG (PLL_BASE + 0x010)
#define PLL4_AUDIO (PLL_BASE + 0x070)
#define PLL5_VIDEO (PLL_BASE + 0x0a0)
#define PLL6_MLB (PLL_BASE + 0x0d0)
#define PLL7_USB_HOST (PLL_BASE + 0x020)
#define PLL8_ENET (PLL_BASE + 0x0e0)
#define PFD_480 (PLL_BASE + 0x0f0)
#define PFD_528 (PLL_BASE + 0x100)
#define PLL_NUM_OFFSET 0x010
#define PLL_DENOM_OFFSET 0x020
#define PFD0 7
#define PFD1 15
#define PFD2 23
#define PFD3 31
#define PFD_FRAC_MASK 0x3f
#define BM_PLL_BYPASS (0x1 << 16)
#define BM_PLL_ENABLE (0x1 << 13)
#define BM_PLL_POWER_DOWN (0x1 << 12)
#define BM_PLL_LOCK (0x1 << 31)
#define BP_PLL_SYS_DIV_SELECT 0
#define BM_PLL_SYS_DIV_SELECT (0x7f << 0)
#define BP_PLL_BUS_DIV_SELECT 0
#define BM_PLL_BUS_DIV_SELECT (0x1 << 0)
#define BP_PLL_USB_DIV_SELECT 0
#define BM_PLL_USB_DIV_SELECT (0x3 << 0)
#define BP_PLL_AV_DIV_SELECT 0
#define BM_PLL_AV_DIV_SELECT (0x7f << 0)
#define BP_PLL_ENET_DIV_SELECT 0
#define BM_PLL_ENET_DIV_SELECT (0x3 << 0)
#define BM_PLL_ENET_EN_PCIE (0x1 << 19)
#define BM_PLL_ENET_EN_SATA (0x1 << 20)
#define CCM_BASE IMX_IO_ADDRESS(MX6Q_CCM_BASE_ADDR)
#define CCR (CCM_BASE + 0x00)
#define CCDR (CCM_BASE + 0x04)
#define CSR (CCM_BASE + 0x08)
#define CCSR (CCM_BASE + 0x0c)
#define CACRR (CCM_BASE + 0x10)
#define CBCDR (CCM_BASE + 0x14)
#define CBCMR (CCM_BASE + 0x18)
#define CSCMR1 (CCM_BASE + 0x1c)
#define CSCMR2 (CCM_BASE + 0x20)
#define CSCDR1 (CCM_BASE + 0x24)
#define CS1CDR (CCM_BASE + 0x28)
#define CS2CDR (CCM_BASE + 0x2c)
#define CDCDR (CCM_BASE + 0x30)
#define CHSCCDR (CCM_BASE + 0x34)
#define CSCDR2 (CCM_BASE + 0x38)
#define CSCDR3 (CCM_BASE + 0x3c)
#define CSCDR4 (CCM_BASE + 0x40)
#define CWDR (CCM_BASE + 0x44)
#define CDHIPR (CCM_BASE + 0x48)
#define CDCR (CCM_BASE + 0x4c)
#define CTOR (CCM_BASE + 0x50)
#define CLPCR (CCM_BASE + 0x54)
#define CISR (CCM_BASE + 0x58)
#define CIMR (CCM_BASE + 0x5c)
#define CCOSR (CCM_BASE + 0x60)
#define CGPR (CCM_BASE + 0x64)
#define CCGR0 (CCM_BASE + 0x68)
#define CCGR1 (CCM_BASE + 0x6c)
#define CCGR2 (CCM_BASE + 0x70)
#define CCGR3 (CCM_BASE + 0x74)
#define CCGR4 (CCM_BASE + 0x78)
#define CCGR5 (CCM_BASE + 0x7c)
#define CCGR6 (CCM_BASE + 0x80)
#define CCGR7 (CCM_BASE + 0x84)
#define CMEOR (CCM_BASE + 0x88)
#define CG0 0
#define CG1 2
#define CG2 4
#define CG3 6
#define CG4 8
#define CG5 10
#define CG6 12
#define CG7 14
#define CG8 16
#define CG9 18
#define CG10 20
#define CG11 22
#define CG12 24
#define CG13 26
#define CG14 28
#define CG15 30
#define BM_CCSR_PLL1_SW_SEL (0x1 << 2)
#define BM_CCSR_STEP_SEL (0x1 << 8)
#define BP_CACRR_ARM_PODF 0
#define BM_CACRR_ARM_PODF (0x7 << 0)
#define BP_CBCDR_PERIPH2_CLK2_PODF 0
#define BM_CBCDR_PERIPH2_CLK2_PODF (0x7 << 0)
#define BP_CBCDR_MMDC_CH1_AXI_PODF 3
#define BM_CBCDR_MMDC_CH1_AXI_PODF (0x7 << 3)
#define BP_CBCDR_AXI_SEL 6
#define BM_CBCDR_AXI_SEL (0x3 << 6)
#define BP_CBCDR_IPG_PODF 8
#define BM_CBCDR_IPG_PODF (0x3 << 8)
#define BP_CBCDR_AHB_PODF 10
#define BM_CBCDR_AHB_PODF (0x7 << 10)
#define BP_CBCDR_AXI_PODF 16
#define BM_CBCDR_AXI_PODF (0x7 << 16)
#define BP_CBCDR_MMDC_CH0_AXI_PODF 19
#define BM_CBCDR_MMDC_CH0_AXI_PODF (0x7 << 19)
#define BP_CBCDR_PERIPH_CLK_SEL 25
#define BM_CBCDR_PERIPH_CLK_SEL (0x1 << 25)
#define BP_CBCDR_PERIPH2_CLK_SEL 26
#define BM_CBCDR_PERIPH2_CLK_SEL (0x1 << 26)
#define BP_CBCDR_PERIPH_CLK2_PODF 27
#define BM_CBCDR_PERIPH_CLK2_PODF (0x7 << 27)
#define BP_CBCMR_GPU2D_AXI_SEL 0
#define BM_CBCMR_GPU2D_AXI_SEL (0x1 << 0)
#define BP_CBCMR_GPU3D_AXI_SEL 1
#define BM_CBCMR_GPU3D_AXI_SEL (0x1 << 1)
#define BP_CBCMR_GPU3D_CORE_SEL 4
#define BM_CBCMR_GPU3D_CORE_SEL (0x3 << 4)
#define BP_CBCMR_GPU3D_SHADER_SEL 8
#define BM_CBCMR_GPU3D_SHADER_SEL (0x3 << 8)
#define BP_CBCMR_PCIE_AXI_SEL 10
#define BM_CBCMR_PCIE_AXI_SEL (0x1 << 10)
#define BP_CBCMR_VDO_AXI_SEL 11
#define BM_CBCMR_VDO_AXI_SEL (0x1 << 11)
#define BP_CBCMR_PERIPH_CLK2_SEL 12
#define BM_CBCMR_PERIPH_CLK2_SEL (0x3 << 12)
#define BP_CBCMR_VPU_AXI_SEL 14
#define BM_CBCMR_VPU_AXI_SEL (0x3 << 14)
#define BP_CBCMR_GPU2D_CORE_SEL 16
#define BM_CBCMR_GPU2D_CORE_SEL (0x3 << 16)
#define BP_CBCMR_PRE_PERIPH_CLK_SEL 18
#define BM_CBCMR_PRE_PERIPH_CLK_SEL (0x3 << 18)
#define BP_CBCMR_PERIPH2_CLK2_SEL 20
#define BM_CBCMR_PERIPH2_CLK2_SEL (0x1 << 20)
#define BP_CBCMR_PRE_PERIPH2_CLK_SEL 21
#define BM_CBCMR_PRE_PERIPH2_CLK_SEL (0x3 << 21)
#define BP_CBCMR_GPU2D_CORE_PODF 23
#define BM_CBCMR_GPU2D_CORE_PODF (0x7 << 23)
#define BP_CBCMR_GPU3D_CORE_PODF 26
#define BM_CBCMR_GPU3D_CORE_PODF (0x7 << 26)
#define BP_CBCMR_GPU3D_SHADER_PODF 29
#define BM_CBCMR_GPU3D_SHADER_PODF (0x7 << 29)
#define BP_CSCMR1_PERCLK_PODF 0
#define BM_CSCMR1_PERCLK_PODF (0x3f << 0)
#define BP_CSCMR1_SSI1_SEL 10
#define BM_CSCMR1_SSI1_SEL (0x3 << 10)
#define BP_CSCMR1_SSI2_SEL 12
#define BM_CSCMR1_SSI2_SEL (0x3 << 12)
#define BP_CSCMR1_SSI3_SEL 14
#define BM_CSCMR1_SSI3_SEL (0x3 << 14)
#define BP_CSCMR1_USDHC1_SEL 16
#define BM_CSCMR1_USDHC1_SEL (0x1 << 16)
#define BP_CSCMR1_USDHC2_SEL 17
#define BM_CSCMR1_USDHC2_SEL (0x1 << 17)
#define BP_CSCMR1_USDHC3_SEL 18
#define BM_CSCMR1_USDHC3_SEL (0x1 << 18)
#define BP_CSCMR1_USDHC4_SEL 19
#define BM_CSCMR1_USDHC4_SEL (0x1 << 19)
#define BP_CSCMR1_EMI_PODF 20
#define BM_CSCMR1_EMI_PODF (0x7 << 20)
#define BP_CSCMR1_EMI_SLOW_PODF 23
#define BM_CSCMR1_EMI_SLOW_PODF (0x7 << 23)
#define BP_CSCMR1_EMI_SEL 27
#define BM_CSCMR1_EMI_SEL (0x3 << 27)
#define BP_CSCMR1_EMI_SLOW_SEL 29
#define BM_CSCMR1_EMI_SLOW_SEL (0x3 << 29)
#define BP_CSCMR2_CAN_PODF 2
#define BM_CSCMR2_CAN_PODF (0x3f << 2)
#define BM_CSCMR2_LDB_DI0_IPU_DIV (0x1 << 10)
#define BM_CSCMR2_LDB_DI1_IPU_DIV (0x1 << 11)
#define BP_CSCMR2_ESAI_SEL 19
#define BM_CSCMR2_ESAI_SEL (0x3 << 19)
#define BP_CSCDR1_UART_PODF 0
#define BM_CSCDR1_UART_PODF (0x3f << 0)
#define BP_CSCDR1_USDHC1_PODF 11
#define BM_CSCDR1_USDHC1_PODF (0x7 << 11)
#define BP_CSCDR1_USDHC2_PODF 16
#define BM_CSCDR1_USDHC2_PODF (0x7 << 16)
#define BP_CSCDR1_USDHC3_PODF 19
#define BM_CSCDR1_USDHC3_PODF (0x7 << 19)
#define BP_CSCDR1_USDHC4_PODF 22
#define BM_CSCDR1_USDHC4_PODF (0x7 << 22)
#define BP_CSCDR1_VPU_AXI_PODF 25
#define BM_CSCDR1_VPU_AXI_PODF (0x7 << 25)
#define BP_CS1CDR_SSI1_PODF 0
#define BM_CS1CDR_SSI1_PODF (0x3f << 0)
#define BP_CS1CDR_SSI1_PRED 6
#define BM_CS1CDR_SSI1_PRED (0x7 << 6)
#define BP_CS1CDR_ESAI_PRED 9
#define BM_CS1CDR_ESAI_PRED (0x7 << 9)
#define BP_CS1CDR_SSI3_PODF 16
#define BM_CS1CDR_SSI3_PODF (0x3f << 16)
#define BP_CS1CDR_SSI3_PRED 22
#define BM_CS1CDR_SSI3_PRED (0x7 << 22)
#define BP_CS1CDR_ESAI_PODF 25
#define BM_CS1CDR_ESAI_PODF (0x7 << 25)
#define BP_CS2CDR_SSI2_PODF 0
#define BM_CS2CDR_SSI2_PODF (0x3f << 0)
#define BP_CS2CDR_SSI2_PRED 6
#define BM_CS2CDR_SSI2_PRED (0x7 << 6)
#define BP_CS2CDR_LDB_DI0_SEL 9
#define BM_CS2CDR_LDB_DI0_SEL (0x7 << 9)
#define BP_CS2CDR_LDB_DI1_SEL 12
#define BM_CS2CDR_LDB_DI1_SEL (0x7 << 12)
#define BP_CS2CDR_ENFC_SEL 16
#define BM_CS2CDR_ENFC_SEL (0x3 << 16)
#define BP_CS2CDR_ENFC_PRED 18
#define BM_CS2CDR_ENFC_PRED (0x7 << 18)
#define BP_CS2CDR_ENFC_PODF 21
#define BM_CS2CDR_ENFC_PODF (0x3f << 21)
#define BP_CDCDR_ASRC_SERIAL_SEL 7
#define BM_CDCDR_ASRC_SERIAL_SEL (0x3 << 7)
#define BP_CDCDR_ASRC_SERIAL_PODF 9
#define BM_CDCDR_ASRC_SERIAL_PODF (0x7 << 9)
#define BP_CDCDR_ASRC_SERIAL_PRED 12
#define BM_CDCDR_ASRC_SERIAL_PRED (0x7 << 12)
#define BP_CDCDR_SPDIF_SEL 20
#define BM_CDCDR_SPDIF_SEL (0x3 << 20)
#define BP_CDCDR_SPDIF_PODF 22
#define BM_CDCDR_SPDIF_PODF (0x7 << 22)
#define BP_CDCDR_SPDIF_PRED 25
#define BM_CDCDR_SPDIF_PRED (0x7 << 25)
#define BP_CDCDR_HSI_TX_PODF 29
#define BM_CDCDR_HSI_TX_PODF (0x7 << 29)
#define BP_CDCDR_HSI_TX_SEL 28
#define BM_CDCDR_HSI_TX_SEL (0x1 << 28)
#define BP_CHSCCDR_IPU1_DI0_SEL 0
#define BM_CHSCCDR_IPU1_DI0_SEL (0x7 << 0)
#define BP_CHSCCDR_IPU1_DI0_PRE_PODF 3
#define BM_CHSCCDR_IPU1_DI0_PRE_PODF (0x7 << 3)
#define BP_CHSCCDR_IPU1_DI0_PRE_SEL 6
#define BM_CHSCCDR_IPU1_DI0_PRE_SEL (0x7 << 6)
#define BP_CHSCCDR_IPU1_DI1_SEL 9
#define BM_CHSCCDR_IPU1_DI1_SEL (0x7 << 9)
#define BP_CHSCCDR_IPU1_DI1_PRE_PODF 12
#define BM_CHSCCDR_IPU1_DI1_PRE_PODF (0x7 << 12)
#define BP_CHSCCDR_IPU1_DI1_PRE_SEL 15
#define BM_CHSCCDR_IPU1_DI1_PRE_SEL (0x7 << 15)
#define BP_CSCDR2_IPU2_DI0_SEL 0
#define BM_CSCDR2_IPU2_DI0_SEL (0x7)
#define BP_CSCDR2_IPU2_DI0_PRE_PODF 3
#define BM_CSCDR2_IPU2_DI0_PRE_PODF (0x7 << 3)
#define BP_CSCDR2_IPU2_DI0_PRE_SEL 6
#define BM_CSCDR2_IPU2_DI0_PRE_SEL (0x7 << 6)
#define BP_CSCDR2_IPU2_DI1_SEL 9
#define BM_CSCDR2_IPU2_DI1_SEL (0x7 << 9)
#define BP_CSCDR2_IPU2_DI1_PRE_PODF 12
#define BM_CSCDR2_IPU2_DI1_PRE_PODF (0x7 << 12)
#define BP_CSCDR2_IPU2_DI1_PRE_SEL 15
#define BM_CSCDR2_IPU2_DI1_PRE_SEL (0x7 << 15)
#define BP_CSCDR2_ECSPI_CLK_PODF 19
#define BM_CSCDR2_ECSPI_CLK_PODF (0x3f << 19)
#define BP_CSCDR3_IPU1_HSP_SEL 9
#define BM_CSCDR3_IPU1_HSP_SEL (0x3 << 9)
#define BP_CSCDR3_IPU1_HSP_PODF 11
#define BM_CSCDR3_IPU1_HSP_PODF (0x7 << 11)
#define BP_CSCDR3_IPU2_HSP_SEL 14
#define BM_CSCDR3_IPU2_HSP_SEL (0x3 << 14)
#define BP_CSCDR3_IPU2_HSP_PODF 16
#define BM_CSCDR3_IPU2_HSP_PODF (0x7 << 16)
#define BM_CDHIPR_AXI_PODF_BUSY (0x1 << 0)
#define BM_CDHIPR_AHB_PODF_BUSY (0x1 << 1)
#define BM_CDHIPR_MMDC_CH1_PODF_BUSY (0x1 << 2)
#define BM_CDHIPR_PERIPH2_SEL_BUSY (0x1 << 3)
#define BM_CDHIPR_MMDC_CH0_PODF_BUSY (0x1 << 4)
#define BM_CDHIPR_PERIPH_SEL_BUSY (0x1 << 5)
#define BM_CDHIPR_ARM_PODF_BUSY (0x1 << 16)
#define BP_CLPCR_LPM 0
#define BM_CLPCR_LPM (0x3 << 0)
#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2)
#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
#define BM_CLPCR_SBYOS (0x1 << 6)
#define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
#define BM_CLPCR_VSTBY (0x1 << 8)
#define BP_CLPCR_STBY_COUNT 9
#define BM_CLPCR_STBY_COUNT (0x3 << 9)
#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11)
#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16)
#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17)
#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19)
#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21)
#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24)
#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25)
#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
#define BP_CCOSR_CKO1_EN 7
#define BP_CCOSR_CKO1_PODF 4
#define BM_CCOSR_CKO1_PODF (0x7 << 4)
#define BP_CCOSR_CKO1_SEL 0
#define BM_CCOSR_CKO1_SEL (0xf << 0)
#define FREQ_480M 480000000
#define FREQ_528M 528000000
#define FREQ_594M 594000000
#define FREQ_650M 650000000
#define FREQ_1300M 1300000000
static
struct
clk
pll1_sys
;
static
struct
clk
pll2_bus
;
static
struct
clk
pll3_usb_otg
;
static
struct
clk
pll4_audio
;
static
struct
clk
pll5_video
;
static
struct
clk
pll6_mlb
;
static
struct
clk
pll7_usb_host
;
static
struct
clk
pll8_enet
;
static
struct
clk
apbh_dma_clk
;
static
struct
clk
arm_clk
;
static
struct
clk
ipg_clk
;
static
struct
clk
ahb_clk
;
static
struct
clk
axi_clk
;
static
struct
clk
mmdc_ch0_axi_clk
;
static
struct
clk
mmdc_ch1_axi_clk
;
static
struct
clk
periph_clk
;
static
struct
clk
periph_pre_clk
;
static
struct
clk
periph_clk2_clk
;
static
struct
clk
periph2_clk
;
static
struct
clk
periph2_pre_clk
;
static
struct
clk
periph2_clk2_clk
;
static
struct
clk
gpu2d_core_clk
;
static
struct
clk
gpu3d_core_clk
;
static
struct
clk
gpu3d_shader_clk
;
static
struct
clk
ipg_perclk
;
static
struct
clk
emi_clk
;
static
struct
clk
emi_slow_clk
;
static
struct
clk
can1_clk
;
static
struct
clk
uart_clk
;
static
struct
clk
usdhc1_clk
;
static
struct
clk
usdhc2_clk
;
static
struct
clk
usdhc3_clk
;
static
struct
clk
usdhc4_clk
;
static
struct
clk
vpu_clk
;
static
struct
clk
hsi_tx_clk
;
static
struct
clk
ipu1_di0_pre_clk
;
static
struct
clk
ipu1_di1_pre_clk
;
static
struct
clk
ipu2_di0_pre_clk
;
static
struct
clk
ipu2_di1_pre_clk
;
static
struct
clk
ipu1_clk
;
static
struct
clk
ipu2_clk
;
static
struct
clk
ssi1_clk
;
static
struct
clk
ssi3_clk
;
static
struct
clk
esai_clk
;
static
struct
clk
ssi2_clk
;
static
struct
clk
spdif_clk
;
static
struct
clk
asrc_serial_clk
;
static
struct
clk
gpu2d_axi_clk
;
static
struct
clk
gpu3d_axi_clk
;
static
struct
clk
pcie_clk
;
static
struct
clk
vdo_axi_clk
;
static
struct
clk
ldb_di0_clk
;
static
struct
clk
ldb_di1_clk
;
static
struct
clk
ipu1_di0_clk
;
static
struct
clk
ipu1_di1_clk
;
static
struct
clk
ipu2_di0_clk
;
static
struct
clk
ipu2_di1_clk
;
static
struct
clk
enfc_clk
;
static
struct
clk
cko1_clk
;
static
struct
clk
dummy_clk
=
{};
static
unsigned
long
external_high_reference
;
static
unsigned
long
external_low_reference
;
static
unsigned
long
oscillator_reference
;
static
unsigned
long
get_oscillator_reference_clock_rate
(
struct
clk
*
clk
)
{
return
oscillator_reference
;
}
static
unsigned
long
get_high_reference_clock_rate
(
struct
clk
*
clk
)
{
return
external_high_reference
;
}
static
unsigned
long
get_low_reference_clock_rate
(
struct
clk
*
clk
)
{
return
external_low_reference
;
}
static
struct
clk
ckil_clk
=
{
.
get_rate
=
get_low_reference_clock_rate
,
};
static
struct
clk
ckih_clk
=
{
.
get_rate
=
get_high_reference_clock_rate
,
};
static
struct
clk
osc_clk
=
{
.
get_rate
=
get_oscillator_reference_clock_rate
,
};
static
inline
void
__iomem
*
pll_get_reg_addr
(
struct
clk
*
pll
)
{
if
(
pll
==
&
pll1_sys
)
return
PLL1_SYS
;
else
if
(
pll
==
&
pll2_bus
)
return
PLL2_BUS
;
else
if
(
pll
==
&
pll3_usb_otg
)
return
PLL3_USB_OTG
;
else
if
(
pll
==
&
pll4_audio
)
return
PLL4_AUDIO
;
else
if
(
pll
==
&
pll5_video
)
return
PLL5_VIDEO
;
else
if
(
pll
==
&
pll6_mlb
)
return
PLL6_MLB
;
else
if
(
pll
==
&
pll7_usb_host
)
return
PLL7_USB_HOST
;
else
if
(
pll
==
&
pll8_enet
)
return
PLL8_ENET
;
else
BUG
();
return
NULL
;
}
static
int
pll_enable
(
struct
clk
*
clk
)
{
int
timeout
=
0x100000
;
void
__iomem
*
reg
;
u32
val
;
reg
=
pll_get_reg_addr
(
clk
);
val
=
readl_relaxed
(
reg
);
val
&=
~
BM_PLL_BYPASS
;
val
&=
~
BM_PLL_POWER_DOWN
;
/* 480MHz PLLs have the opposite definition for power bit */
if
(
clk
==
&
pll3_usb_otg
||
clk
==
&
pll7_usb_host
)
val
|=
BM_PLL_POWER_DOWN
;
writel_relaxed
(
val
,
reg
);
/* Wait for PLL to lock */
while
(
!
(
readl_relaxed
(
reg
)
&
BM_PLL_LOCK
)
&&
--
timeout
)
cpu_relax
();
if
(
unlikely
(
!
timeout
))
return
-
EBUSY
;
/* Enable the PLL output now */
val
=
readl_relaxed
(
reg
);
val
|=
BM_PLL_ENABLE
;
writel_relaxed
(
val
,
reg
);
return
0
;
}
static
void
pll_disable
(
struct
clk
*
clk
)
{
void
__iomem
*
reg
;
u32
val
;
reg
=
pll_get_reg_addr
(
clk
);
val
=
readl_relaxed
(
reg
);
val
&=
~
BM_PLL_ENABLE
;
val
|=
BM_PLL_BYPASS
;
val
|=
BM_PLL_POWER_DOWN
;
if
(
clk
==
&
pll3_usb_otg
||
clk
==
&
pll7_usb_host
)
val
&=
~
BM_PLL_POWER_DOWN
;
writel_relaxed
(
val
,
reg
);
}
static
unsigned
long
pll1_sys_get_rate
(
struct
clk
*
clk
)
{
u32
div
=
(
readl_relaxed
(
PLL1_SYS
)
&
BM_PLL_SYS_DIV_SELECT
)
>>
BP_PLL_SYS_DIV_SELECT
;
return
clk_get_rate
(
clk
->
parent
)
*
div
/
2
;
}
static
int
pll1_sys_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
val
,
div
;
if
(
rate
<
FREQ_650M
||
rate
>
FREQ_1300M
)
return
-
EINVAL
;
div
=
rate
*
2
/
clk_get_rate
(
clk
->
parent
);
val
=
readl_relaxed
(
PLL1_SYS
);
val
&=
~
BM_PLL_SYS_DIV_SELECT
;
val
|=
div
<<
BP_PLL_SYS_DIV_SELECT
;
writel_relaxed
(
val
,
PLL1_SYS
);
return
0
;
}
static
unsigned
long
pll8_enet_get_rate
(
struct
clk
*
clk
)
{
u32
div
=
(
readl_relaxed
(
PLL8_ENET
)
&
BM_PLL_ENET_DIV_SELECT
)
>>
BP_PLL_ENET_DIV_SELECT
;
switch
(
div
)
{
case
0
:
return
25000000
;
case
1
:
return
50000000
;
case
2
:
return
100000000
;
case
3
:
return
125000000
;
}
return
0
;
}
static
int
pll8_enet_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
val
,
div
;
switch
(
rate
)
{
case
25000000
:
div
=
0
;
break
;
case
50000000
:
div
=
1
;
break
;
case
100000000
:
div
=
2
;
break
;
case
125000000
:
div
=
3
;
break
;
default:
return
-
EINVAL
;
}
val
=
readl_relaxed
(
PLL8_ENET
);
val
&=
~
BM_PLL_ENET_DIV_SELECT
;
val
|=
div
<<
BP_PLL_ENET_DIV_SELECT
;
writel_relaxed
(
val
,
PLL8_ENET
);
return
0
;
}
static
unsigned
long
pll_av_get_rate
(
struct
clk
*
clk
)
{
void
__iomem
*
reg
=
(
clk
==
&
pll4_audio
)
?
PLL4_AUDIO
:
PLL5_VIDEO
;
unsigned
long
parent_rate
=
clk_get_rate
(
clk
->
parent
);
u32
mfn
=
readl_relaxed
(
reg
+
PLL_NUM_OFFSET
);
u32
mfd
=
readl_relaxed
(
reg
+
PLL_DENOM_OFFSET
);
u32
div
=
(
readl_relaxed
(
reg
)
&
BM_PLL_AV_DIV_SELECT
)
>>
BP_PLL_AV_DIV_SELECT
;
return
(
parent_rate
*
div
)
+
((
parent_rate
/
mfd
)
*
mfn
);
}
static
int
pll_av_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
void
__iomem
*
reg
=
(
clk
==
&
pll4_audio
)
?
PLL4_AUDIO
:
PLL5_VIDEO
;
unsigned
int
parent_rate
=
clk_get_rate
(
clk
->
parent
);
u32
val
,
div
;
u32
mfn
,
mfd
=
1000000
;
s64
temp64
;
if
(
rate
<
FREQ_650M
||
rate
>
FREQ_1300M
)
return
-
EINVAL
;
div
=
rate
/
parent_rate
;
temp64
=
(
u64
)
(
rate
-
div
*
parent_rate
);
temp64
*=
mfd
;
do_div
(
temp64
,
parent_rate
);
mfn
=
temp64
;
val
=
readl_relaxed
(
reg
);
val
&=
~
BM_PLL_AV_DIV_SELECT
;
val
|=
div
<<
BP_PLL_AV_DIV_SELECT
;
writel_relaxed
(
val
,
reg
);
writel_relaxed
(
mfn
,
reg
+
PLL_NUM_OFFSET
);
writel_relaxed
(
mfd
,
reg
+
PLL_DENOM_OFFSET
);
return
0
;
}
static
void
__iomem
*
pll_get_div_reg_bit
(
struct
clk
*
clk
,
u32
*
bp
,
u32
*
bm
)
{
void
__iomem
*
reg
;
if
(
clk
==
&
pll2_bus
)
{
reg
=
PLL2_BUS
;
*
bp
=
BP_PLL_BUS_DIV_SELECT
;
*
bm
=
BM_PLL_BUS_DIV_SELECT
;
}
else
if
(
clk
==
&
pll3_usb_otg
)
{
reg
=
PLL3_USB_OTG
;
*
bp
=
BP_PLL_USB_DIV_SELECT
;
*
bm
=
BM_PLL_USB_DIV_SELECT
;
}
else
if
(
clk
==
&
pll7_usb_host
)
{
reg
=
PLL7_USB_HOST
;
*
bp
=
BP_PLL_USB_DIV_SELECT
;
*
bm
=
BM_PLL_USB_DIV_SELECT
;
}
else
{
BUG
();
}
return
reg
;
}
static
unsigned
long
pll_get_rate
(
struct
clk
*
clk
)
{
void
__iomem
*
reg
;
u32
div
,
bp
,
bm
;
reg
=
pll_get_div_reg_bit
(
clk
,
&
bp
,
&
bm
);
div
=
(
readl_relaxed
(
reg
)
&
bm
)
>>
bp
;
return
(
div
==
1
)
?
clk_get_rate
(
clk
->
parent
)
*
22
:
clk_get_rate
(
clk
->
parent
)
*
20
;
}
static
int
pll_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
void
__iomem
*
reg
;
u32
val
,
div
,
bp
,
bm
;
if
(
rate
==
FREQ_528M
)
div
=
1
;
else
if
(
rate
==
FREQ_480M
)
div
=
0
;
else
return
-
EINVAL
;
reg
=
pll_get_div_reg_bit
(
clk
,
&
bp
,
&
bm
);
val
=
readl_relaxed
(
reg
);
val
&=
~
bm
;
val
|=
div
<<
bp
;
writel_relaxed
(
val
,
reg
);
return
0
;
}
#define pll2_bus_get_rate pll_get_rate
#define pll2_bus_set_rate pll_set_rate
#define pll3_usb_otg_get_rate pll_get_rate
#define pll3_usb_otg_set_rate pll_set_rate
#define pll7_usb_host_get_rate pll_get_rate
#define pll7_usb_host_set_rate pll_set_rate
#define pll4_audio_get_rate pll_av_get_rate
#define pll4_audio_set_rate pll_av_set_rate
#define pll5_video_get_rate pll_av_get_rate
#define pll5_video_set_rate pll_av_set_rate
#define pll6_mlb_get_rate NULL
#define pll6_mlb_set_rate NULL
#define DEF_PLL(name) \
static struct clk name = { \
.enable = pll_enable, \
.disable = pll_disable, \
.get_rate = name##_get_rate, \
.set_rate = name##_set_rate, \
.parent = &osc_clk, \
}
DEF_PLL
(
pll1_sys
);
DEF_PLL
(
pll2_bus
);
DEF_PLL
(
pll3_usb_otg
);
DEF_PLL
(
pll4_audio
);
DEF_PLL
(
pll5_video
);
DEF_PLL
(
pll6_mlb
);
DEF_PLL
(
pll7_usb_host
);
DEF_PLL
(
pll8_enet
);
static
unsigned
long
pfd_get_rate
(
struct
clk
*
clk
)
{
u64
tmp
=
(
u64
)
clk_get_rate
(
clk
->
parent
)
*
18
;
u32
frac
,
bp_frac
;
if
(
apbh_dma_clk
.
usecount
==
0
)
apbh_dma_clk
.
enable
(
&
apbh_dma_clk
);
bp_frac
=
clk
->
enable_shift
-
7
;
frac
=
readl_relaxed
(
clk
->
enable_reg
)
>>
bp_frac
&
PFD_FRAC_MASK
;
do_div
(
tmp
,
frac
);
return
tmp
;
}
static
int
pfd_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
val
,
frac
,
bp_frac
;
u64
tmp
=
(
u64
)
clk_get_rate
(
clk
->
parent
)
*
18
;
if
(
apbh_dma_clk
.
usecount
==
0
)
apbh_dma_clk
.
enable
(
&
apbh_dma_clk
);
/*
* Round up the divider so that we don't set a rate
* higher than what is requested
*/
tmp
+=
rate
/
2
;
do_div
(
tmp
,
rate
);
frac
=
tmp
;
frac
=
(
frac
<
12
)
?
12
:
frac
;
frac
=
(
frac
>
35
)
?
35
:
frac
;
/*
* The frac field always starts from 7 bits lower
* position of enable bit
*/
bp_frac
=
clk
->
enable_shift
-
7
;
val
=
readl_relaxed
(
clk
->
enable_reg
);
val
&=
~
(
PFD_FRAC_MASK
<<
bp_frac
);
val
|=
frac
<<
bp_frac
;
writel_relaxed
(
val
,
clk
->
enable_reg
);
tmp
=
(
u64
)
clk_get_rate
(
clk
->
parent
)
*
18
;
do_div
(
tmp
,
frac
);
if
(
apbh_dma_clk
.
usecount
==
0
)
apbh_dma_clk
.
disable
(
&
apbh_dma_clk
);
return
0
;
}
static
unsigned
long
pfd_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
frac
;
u64
tmp
;
tmp
=
(
u64
)
clk_get_rate
(
clk
->
parent
)
*
18
;
tmp
+=
rate
/
2
;
do_div
(
tmp
,
rate
);
frac
=
tmp
;
frac
=
(
frac
<
12
)
?
12
:
frac
;
frac
=
(
frac
>
35
)
?
35
:
frac
;
tmp
=
(
u64
)
clk_get_rate
(
clk
->
parent
)
*
18
;
do_div
(
tmp
,
frac
);
return
tmp
;
}
static
int
pfd_enable
(
struct
clk
*
clk
)
{
u32
val
;
if
(
apbh_dma_clk
.
usecount
==
0
)
apbh_dma_clk
.
enable
(
&
apbh_dma_clk
);
val
=
readl_relaxed
(
clk
->
enable_reg
);
val
&=
~
(
1
<<
clk
->
enable_shift
);
writel_relaxed
(
val
,
clk
->
enable_reg
);
if
(
apbh_dma_clk
.
usecount
==
0
)
apbh_dma_clk
.
disable
(
&
apbh_dma_clk
);
return
0
;
}
static
void
pfd_disable
(
struct
clk
*
clk
)
{
u32
val
;
if
(
apbh_dma_clk
.
usecount
==
0
)
apbh_dma_clk
.
enable
(
&
apbh_dma_clk
);
val
=
readl_relaxed
(
clk
->
enable_reg
);
val
|=
1
<<
clk
->
enable_shift
;
writel_relaxed
(
val
,
clk
->
enable_reg
);
if
(
apbh_dma_clk
.
usecount
==
0
)
apbh_dma_clk
.
disable
(
&
apbh_dma_clk
);
}
#define DEF_PFD(name, er, es, p) \
static struct clk name = { \
.enable_reg = er, \
.enable_shift = es, \
.enable = pfd_enable, \
.disable = pfd_disable, \
.get_rate = pfd_get_rate, \
.set_rate = pfd_set_rate, \
.round_rate = pfd_round_rate, \
.parent = p, \
}
DEF_PFD
(
pll2_pfd_352m
,
PFD_528
,
PFD0
,
&
pll2_bus
);
DEF_PFD
(
pll2_pfd_594m
,
PFD_528
,
PFD1
,
&
pll2_bus
);
DEF_PFD
(
pll2_pfd_400m
,
PFD_528
,
PFD2
,
&
pll2_bus
);
DEF_PFD
(
pll3_pfd_720m
,
PFD_480
,
PFD0
,
&
pll3_usb_otg
);
DEF_PFD
(
pll3_pfd_540m
,
PFD_480
,
PFD1
,
&
pll3_usb_otg
);
DEF_PFD
(
pll3_pfd_508m
,
PFD_480
,
PFD2
,
&
pll3_usb_otg
);
DEF_PFD
(
pll3_pfd_454m
,
PFD_480
,
PFD3
,
&
pll3_usb_otg
);
static
unsigned
long
twd_clk_get_rate
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
)
/
2
;
}
static
struct
clk
twd_clk
=
{
.
parent
=
&
arm_clk
,
.
get_rate
=
twd_clk_get_rate
,
};
static
unsigned
long
pll2_200m_get_rate
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
)
/
2
;
}
static
struct
clk
pll2_200m
=
{
.
parent
=
&
pll2_pfd_400m
,
.
get_rate
=
pll2_200m_get_rate
,
};
static
unsigned
long
pll3_120m_get_rate
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
)
/
4
;
}
static
struct
clk
pll3_120m
=
{
.
parent
=
&
pll3_usb_otg
,
.
get_rate
=
pll3_120m_get_rate
,
};
static
unsigned
long
pll3_80m_get_rate
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
)
/
6
;
}
static
struct
clk
pll3_80m
=
{
.
parent
=
&
pll3_usb_otg
,
.
get_rate
=
pll3_80m_get_rate
,
};
static
unsigned
long
pll3_60m_get_rate
(
struct
clk
*
clk
)
{
return
clk_get_rate
(
clk
->
parent
)
/
8
;
}
static
struct
clk
pll3_60m
=
{
.
parent
=
&
pll3_usb_otg
,
.
get_rate
=
pll3_60m_get_rate
,
};
static
int
pll1_sw_clk_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
u32
val
=
readl_relaxed
(
CCSR
);
if
(
parent
==
&
pll1_sys
)
{
val
&=
~
BM_CCSR_PLL1_SW_SEL
;
val
&=
~
BM_CCSR_STEP_SEL
;
}
else
if
(
parent
==
&
osc_clk
)
{
val
|=
BM_CCSR_PLL1_SW_SEL
;
val
&=
~
BM_CCSR_STEP_SEL
;
}
else
if
(
parent
==
&
pll2_pfd_400m
)
{
val
|=
BM_CCSR_PLL1_SW_SEL
;
val
|=
BM_CCSR_STEP_SEL
;
}
else
{
return
-
EINVAL
;
}
writel_relaxed
(
val
,
CCSR
);
return
0
;
}
static
struct
clk
pll1_sw_clk
=
{
.
parent
=
&
pll1_sys
,
.
set_parent
=
pll1_sw_clk_set_parent
,
};
static
void
calc_pred_podf_dividers
(
u32
div
,
u32
*
pred
,
u32
*
podf
)
{
u32
min_pred
,
temp_pred
,
old_err
,
err
;
if
(
div
>=
512
)
{
*
pred
=
8
;
*
podf
=
64
;
}
else
if
(
div
>=
8
)
{
min_pred
=
(
div
-
1
)
/
64
+
1
;
old_err
=
8
;
for
(
temp_pred
=
8
;
temp_pred
>=
min_pred
;
temp_pred
--
)
{
err
=
div
%
temp_pred
;
if
(
err
==
0
)
{
*
pred
=
temp_pred
;
break
;
}
err
=
temp_pred
-
err
;
if
(
err
<
old_err
)
{
old_err
=
err
;
*
pred
=
temp_pred
;
}
}
*
podf
=
(
div
+
*
pred
-
1
)
/
*
pred
;
}
else
if
(
div
<
8
)
{
*
pred
=
div
;
*
podf
=
1
;
}
}
static
int
_clk_enable
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
readl_relaxed
(
clk
->
enable_reg
);
reg
|=
0x3
<<
clk
->
enable_shift
;
writel_relaxed
(
reg
,
clk
->
enable_reg
);
return
0
;
}
static
void
_clk_disable
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
readl_relaxed
(
clk
->
enable_reg
);
reg
&=
~
(
0x3
<<
clk
->
enable_shift
);
writel_relaxed
(
reg
,
clk
->
enable_reg
);
}
static
int
_clk_enable_1b
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
readl_relaxed
(
clk
->
enable_reg
);
reg
|=
0x1
<<
clk
->
enable_shift
;
writel_relaxed
(
reg
,
clk
->
enable_reg
);
return
0
;
}
static
void
_clk_disable_1b
(
struct
clk
*
clk
)
{
u32
reg
;
reg
=
readl_relaxed
(
clk
->
enable_reg
);
reg
&=
~
(
0x1
<<
clk
->
enable_shift
);
writel_relaxed
(
reg
,
clk
->
enable_reg
);
}
struct
divider
{
struct
clk
*
clk
;
void
__iomem
*
reg
;
u32
bp_pred
;
u32
bm_pred
;
u32
bp_podf
;
u32
bm_podf
;
};
#define DEF_CLK_DIV1(d, c, r, b) \
static struct divider d = { \
.clk = c, \
.reg = r, \
.bp_podf = BP_##r##_##b##_PODF, \
.bm_podf = BM_##r##_##b##_PODF, \
}
DEF_CLK_DIV1
(
arm_div
,
&
arm_clk
,
CACRR
,
ARM
);
DEF_CLK_DIV1
(
ipg_div
,
&
ipg_clk
,
CBCDR
,
IPG
);
DEF_CLK_DIV1
(
ahb_div
,
&
ahb_clk
,
CBCDR
,
AHB
);
DEF_CLK_DIV1
(
axi_div
,
&
axi_clk
,
CBCDR
,
AXI
);
DEF_CLK_DIV1
(
mmdc_ch0_axi_div
,
&
mmdc_ch0_axi_clk
,
CBCDR
,
MMDC_CH0_AXI
);
DEF_CLK_DIV1
(
mmdc_ch1_axi_div
,
&
mmdc_ch1_axi_clk
,
CBCDR
,
MMDC_CH1_AXI
);
DEF_CLK_DIV1
(
periph_clk2_div
,
&
periph_clk2_clk
,
CBCDR
,
PERIPH_CLK2
);
DEF_CLK_DIV1
(
periph2_clk2_div
,
&
periph2_clk2_clk
,
CBCDR
,
PERIPH2_CLK2
);
DEF_CLK_DIV1
(
gpu2d_core_div
,
&
gpu2d_core_clk
,
CBCMR
,
GPU2D_CORE
);
DEF_CLK_DIV1
(
gpu3d_core_div
,
&
gpu3d_core_clk
,
CBCMR
,
GPU3D_CORE
);
DEF_CLK_DIV1
(
gpu3d_shader_div
,
&
gpu3d_shader_clk
,
CBCMR
,
GPU3D_SHADER
);
DEF_CLK_DIV1
(
ipg_perclk_div
,
&
ipg_perclk
,
CSCMR1
,
PERCLK
);
DEF_CLK_DIV1
(
emi_div
,
&
emi_clk
,
CSCMR1
,
EMI
);
DEF_CLK_DIV1
(
emi_slow_div
,
&
emi_slow_clk
,
CSCMR1
,
EMI_SLOW
);
DEF_CLK_DIV1
(
can_div
,
&
can1_clk
,
CSCMR2
,
CAN
);
DEF_CLK_DIV1
(
uart_div
,
&
uart_clk
,
CSCDR1
,
UART
);
DEF_CLK_DIV1
(
usdhc1_div
,
&
usdhc1_clk
,
CSCDR1
,
USDHC1
);
DEF_CLK_DIV1
(
usdhc2_div
,
&
usdhc2_clk
,
CSCDR1
,
USDHC2
);
DEF_CLK_DIV1
(
usdhc3_div
,
&
usdhc3_clk
,
CSCDR1
,
USDHC3
);
DEF_CLK_DIV1
(
usdhc4_div
,
&
usdhc4_clk
,
CSCDR1
,
USDHC4
);
DEF_CLK_DIV1
(
vpu_div
,
&
vpu_clk
,
CSCDR1
,
VPU_AXI
);
DEF_CLK_DIV1
(
hsi_tx_div
,
&
hsi_tx_clk
,
CDCDR
,
HSI_TX
);
DEF_CLK_DIV1
(
ipu1_di0_pre_div
,
&
ipu1_di0_pre_clk
,
CHSCCDR
,
IPU1_DI0_PRE
);
DEF_CLK_DIV1
(
ipu1_di1_pre_div
,
&
ipu1_di1_pre_clk
,
CHSCCDR
,
IPU1_DI1_PRE
);
DEF_CLK_DIV1
(
ipu2_di0_pre_div
,
&
ipu2_di0_pre_clk
,
CSCDR2
,
IPU2_DI0_PRE
);
DEF_CLK_DIV1
(
ipu2_di1_pre_div
,
&
ipu2_di1_pre_clk
,
CSCDR2
,
IPU2_DI1_PRE
);
DEF_CLK_DIV1
(
ipu1_div
,
&
ipu1_clk
,
CSCDR3
,
IPU1_HSP
);
DEF_CLK_DIV1
(
ipu2_div
,
&
ipu2_clk
,
CSCDR3
,
IPU2_HSP
);
DEF_CLK_DIV1
(
cko1_div
,
&
cko1_clk
,
CCOSR
,
CKO1
);
#define DEF_CLK_DIV2(d, c, r, b) \
static struct divider d = { \
.clk = c, \
.reg = r, \
.bp_pred = BP_##r##_##b##_PRED, \
.bm_pred = BM_##r##_##b##_PRED, \
.bp_podf = BP_##r##_##b##_PODF, \
.bm_podf = BM_##r##_##b##_PODF, \
}
DEF_CLK_DIV2
(
ssi1_div
,
&
ssi1_clk
,
CS1CDR
,
SSI1
);
DEF_CLK_DIV2
(
ssi3_div
,
&
ssi3_clk
,
CS1CDR
,
SSI3
);
DEF_CLK_DIV2
(
esai_div
,
&
esai_clk
,
CS1CDR
,
ESAI
);
DEF_CLK_DIV2
(
ssi2_div
,
&
ssi2_clk
,
CS2CDR
,
SSI2
);
DEF_CLK_DIV2
(
enfc_div
,
&
enfc_clk
,
CS2CDR
,
ENFC
);
DEF_CLK_DIV2
(
spdif_div
,
&
spdif_clk
,
CDCDR
,
SPDIF
);
DEF_CLK_DIV2
(
asrc_serial_div
,
&
asrc_serial_clk
,
CDCDR
,
ASRC_SERIAL
);
static
struct
divider
*
dividers
[]
=
{
&
arm_div
,
&
ipg_div
,
&
ahb_div
,
&
axi_div
,
&
mmdc_ch0_axi_div
,
&
mmdc_ch1_axi_div
,
&
periph_clk2_div
,
&
periph2_clk2_div
,
&
gpu2d_core_div
,
&
gpu3d_core_div
,
&
gpu3d_shader_div
,
&
ipg_perclk_div
,
&
emi_div
,
&
emi_slow_div
,
&
can_div
,
&
uart_div
,
&
usdhc1_div
,
&
usdhc2_div
,
&
usdhc3_div
,
&
usdhc4_div
,
&
vpu_div
,
&
hsi_tx_div
,
&
ipu1_di0_pre_div
,
&
ipu1_di1_pre_div
,
&
ipu2_di0_pre_div
,
&
ipu2_di1_pre_div
,
&
ipu1_div
,
&
ipu2_div
,
&
ssi1_div
,
&
ssi3_div
,
&
esai_div
,
&
ssi2_div
,
&
enfc_div
,
&
spdif_div
,
&
asrc_serial_div
,
&
cko1_div
,
};
static
unsigned
long
ldb_di_clk_get_rate
(
struct
clk
*
clk
)
{
u32
val
=
readl_relaxed
(
CSCMR2
);
val
&=
(
clk
==
&
ldb_di0_clk
)
?
BM_CSCMR2_LDB_DI0_IPU_DIV
:
BM_CSCMR2_LDB_DI1_IPU_DIV
;
if
(
val
)
return
clk_get_rate
(
clk
->
parent
)
/
7
;
else
return
clk_get_rate
(
clk
->
parent
)
*
2
/
7
;
}
static
int
ldb_di_clk_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
unsigned
long
parent_rate
=
clk_get_rate
(
clk
->
parent
);
u32
val
=
readl_relaxed
(
CSCMR2
);
if
(
rate
*
7
<=
parent_rate
+
parent_rate
/
20
)
val
|=
BM_CSCMR2_LDB_DI0_IPU_DIV
;
else
val
&=
~
BM_CSCMR2_LDB_DI0_IPU_DIV
;
writel_relaxed
(
val
,
CSCMR2
);
return
0
;
}
static
unsigned
long
ldb_di_clk_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
unsigned
long
parent_rate
=
clk_get_rate
(
clk
->
parent
);
if
(
rate
*
7
<=
parent_rate
+
parent_rate
/
20
)
return
parent_rate
/
7
;
else
return
2
*
parent_rate
/
7
;
}
static
unsigned
long
_clk_get_rate
(
struct
clk
*
clk
)
{
struct
divider
*
d
;
u32
val
,
pred
,
podf
;
int
i
,
num
;
if
(
clk
==
&
ldb_di0_clk
||
clk
==
&
ldb_di1_clk
)
return
ldb_di_clk_get_rate
(
clk
);
num
=
ARRAY_SIZE
(
dividers
);
for
(
i
=
0
;
i
<
num
;
i
++
)
if
(
dividers
[
i
]
->
clk
==
clk
)
{
d
=
dividers
[
i
];
break
;
}
if
(
i
==
num
)
return
clk_get_rate
(
clk
->
parent
);
val
=
readl_relaxed
(
d
->
reg
);
pred
=
((
val
&
d
->
bm_pred
)
>>
d
->
bp_pred
)
+
1
;
podf
=
((
val
&
d
->
bm_podf
)
>>
d
->
bp_podf
)
+
1
;
return
clk_get_rate
(
clk
->
parent
)
/
(
pred
*
podf
);
}
static
int
clk_busy_wait
(
struct
clk
*
clk
)
{
int
timeout
=
0x100000
;
u32
bm
;
if
(
clk
==
&
axi_clk
)
bm
=
BM_CDHIPR_AXI_PODF_BUSY
;
else
if
(
clk
==
&
ahb_clk
)
bm
=
BM_CDHIPR_AHB_PODF_BUSY
;
else
if
(
clk
==
&
mmdc_ch0_axi_clk
)
bm
=
BM_CDHIPR_MMDC_CH0_PODF_BUSY
;
else
if
(
clk
==
&
periph_clk
)
bm
=
BM_CDHIPR_PERIPH_SEL_BUSY
;
else
if
(
clk
==
&
arm_clk
)
bm
=
BM_CDHIPR_ARM_PODF_BUSY
;
else
return
-
EINVAL
;
while
((
readl_relaxed
(
CDHIPR
)
&
bm
)
&&
--
timeout
)
cpu_relax
();
if
(
unlikely
(
!
timeout
))
return
-
EBUSY
;
return
0
;
}
static
int
_clk_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
unsigned
long
parent_rate
=
clk_get_rate
(
clk
->
parent
);
struct
divider
*
d
;
u32
val
,
div
,
max_div
,
pred
=
0
,
podf
;
int
i
,
num
;
if
(
clk
==
&
ldb_di0_clk
||
clk
==
&
ldb_di1_clk
)
return
ldb_di_clk_set_rate
(
clk
,
rate
);
num
=
ARRAY_SIZE
(
dividers
);
for
(
i
=
0
;
i
<
num
;
i
++
)
if
(
dividers
[
i
]
->
clk
==
clk
)
{
d
=
dividers
[
i
];
break
;
}
if
(
i
==
num
)
return
-
EINVAL
;
max_div
=
((
d
->
bm_pred
>>
d
->
bp_pred
)
+
1
)
*
((
d
->
bm_podf
>>
d
->
bp_podf
)
+
1
);
div
=
parent_rate
/
rate
;
if
(
div
==
0
)
div
++
;
if
((
parent_rate
/
div
!=
rate
)
||
div
>
max_div
)
return
-
EINVAL
;
if
(
d
->
bm_pred
)
{
calc_pred_podf_dividers
(
div
,
&
pred
,
&
podf
);
}
else
{
pred
=
1
;
podf
=
div
;
}
val
=
readl_relaxed
(
d
->
reg
);
val
&=
~
(
d
->
bm_pred
|
d
->
bm_podf
);
val
|=
(
pred
-
1
)
<<
d
->
bp_pred
|
(
podf
-
1
)
<<
d
->
bp_podf
;
writel_relaxed
(
val
,
d
->
reg
);
if
(
clk
==
&
axi_clk
||
clk
==
&
ahb_clk
||
clk
==
&
mmdc_ch0_axi_clk
||
clk
==
&
arm_clk
)
return
clk_busy_wait
(
clk
);
return
0
;
}
static
unsigned
long
_clk_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
unsigned
long
parent_rate
=
clk_get_rate
(
clk
->
parent
);
u32
div
=
parent_rate
/
rate
;
u32
div_max
,
pred
=
0
,
podf
;
struct
divider
*
d
;
int
i
,
num
;
if
(
clk
==
&
ldb_di0_clk
||
clk
==
&
ldb_di1_clk
)
return
ldb_di_clk_round_rate
(
clk
,
rate
);
num
=
ARRAY_SIZE
(
dividers
);
for
(
i
=
0
;
i
<
num
;
i
++
)
if
(
dividers
[
i
]
->
clk
==
clk
)
{
d
=
dividers
[
i
];
break
;
}
if
(
i
==
num
)
return
-
EINVAL
;
if
(
div
==
0
||
parent_rate
%
rate
)
div
++
;
if
(
d
->
bm_pred
)
{
calc_pred_podf_dividers
(
div
,
&
pred
,
&
podf
);
div
=
pred
*
podf
;
}
else
{
div_max
=
(
d
->
bm_podf
>>
d
->
bp_podf
)
+
1
;
if
(
div
>
div_max
)
div
=
div_max
;
}
return
parent_rate
/
div
;
}
struct
multiplexer
{
struct
clk
*
clk
;
void
__iomem
*
reg
;
u32
bp
;
u32
bm
;
int
pnum
;
struct
clk
*
parents
[];
};
static
struct
multiplexer
axi_mux
=
{
.
clk
=
&
axi_clk
,
.
reg
=
CBCDR
,
.
bp
=
BP_CBCDR_AXI_SEL
,
.
bm
=
BM_CBCDR_AXI_SEL
,
.
parents
=
{
&
periph_clk
,
&
pll2_pfd_400m
,
&
pll3_pfd_540m
,
NULL
},
};
static
struct
multiplexer
periph_mux
=
{
.
clk
=
&
periph_clk
,
.
reg
=
CBCDR
,
.
bp
=
BP_CBCDR_PERIPH_CLK_SEL
,
.
bm
=
BM_CBCDR_PERIPH_CLK_SEL
,
.
parents
=
{
&
periph_pre_clk
,
&
periph_clk2_clk
,
NULL
},
};
static
struct
multiplexer
periph_pre_mux
=
{
.
clk
=
&
periph_pre_clk
,
.
reg
=
CBCMR
,
.
bp
=
BP_CBCMR_PRE_PERIPH_CLK_SEL
,
.
bm
=
BM_CBCMR_PRE_PERIPH_CLK_SEL
,
.
parents
=
{
&
pll2_bus
,
&
pll2_pfd_400m
,
&
pll2_pfd_352m
,
&
pll2_200m
,
NULL
},
};
static
struct
multiplexer
periph_clk2_mux
=
{
.
clk
=
&
periph_clk2_clk
,
.
reg
=
CBCMR
,
.
bp
=
BP_CBCMR_PERIPH_CLK2_SEL
,
.
bm
=
BM_CBCMR_PERIPH_CLK2_SEL
,
.
parents
=
{
&
pll3_usb_otg
,
&
osc_clk
,
NULL
},
};
static
struct
multiplexer
periph2_mux
=
{
.
clk
=
&
periph2_clk
,
.
reg
=
CBCDR
,
.
bp
=
BP_CBCDR_PERIPH2_CLK_SEL
,
.
bm
=
BM_CBCDR_PERIPH2_CLK_SEL
,
.
parents
=
{
&
periph2_pre_clk
,
&
periph2_clk2_clk
,
NULL
},
};
static
struct
multiplexer
periph2_pre_mux
=
{
.
clk
=
&
periph2_pre_clk
,
.
reg
=
CBCMR
,
.
bp
=
BP_CBCMR_PRE_PERIPH2_CLK_SEL
,
.
bm
=
BM_CBCMR_PRE_PERIPH2_CLK_SEL
,
.
parents
=
{
&
pll2_bus
,
&
pll2_pfd_400m
,
&
pll2_pfd_352m
,
&
pll2_200m
,
NULL
},
};
static
struct
multiplexer
periph2_clk2_mux
=
{
.
clk
=
&
periph2_clk2_clk
,
.
reg
=
CBCMR
,
.
bp
=
BP_CBCMR_PERIPH2_CLK2_SEL
,
.
bm
=
BM_CBCMR_PERIPH2_CLK2_SEL
,
.
parents
=
{
&
pll3_usb_otg
,
&
osc_clk
,
NULL
},
};
static
struct
multiplexer
gpu2d_axi_mux
=
{
.
clk
=
&
gpu2d_axi_clk
,
.
reg
=
CBCMR
,
.
bp
=
BP_CBCMR_GPU2D_AXI_SEL
,
.
bm
=
BM_CBCMR_GPU2D_AXI_SEL
,
.
parents
=
{
&
axi_clk
,
&
ahb_clk
,
NULL
},
};
static
struct
multiplexer
gpu3d_axi_mux
=
{
.
clk
=
&
gpu3d_axi_clk
,
.
reg
=
CBCMR
,
.
bp
=
BP_CBCMR_GPU3D_AXI_SEL
,
.
bm
=
BM_CBCMR_GPU3D_AXI_SEL
,
.
parents
=
{
&
axi_clk
,
&
ahb_clk
,
NULL
},
};
static
struct
multiplexer
gpu3d_core_mux
=
{
.
clk
=
&
gpu3d_core_clk
,
.
reg
=
CBCMR
,
.
bp
=
BP_CBCMR_GPU3D_CORE_SEL
,
.
bm
=
BM_CBCMR_GPU3D_CORE_SEL
,
.
parents
=
{
&
mmdc_ch0_axi_clk
,
&
pll3_usb_otg
,
&
pll2_pfd_594m
,
&
pll2_pfd_400m
,
NULL
},
};
static
struct
multiplexer
gpu3d_shader_mux
=
{
.
clk
=
&
gpu3d_shader_clk
,
.
reg
=
CBCMR
,
.
bp
=
BP_CBCMR_GPU3D_SHADER_SEL
,
.
bm
=
BM_CBCMR_GPU3D_SHADER_SEL
,
.
parents
=
{
&
mmdc_ch0_axi_clk
,
&
pll3_usb_otg
,
&
pll2_pfd_594m
,
&
pll3_pfd_720m
,
NULL
},
};
static
struct
multiplexer
pcie_axi_mux
=
{
.
clk
=
&
pcie_clk
,
.
reg
=
CBCMR
,
.
bp
=
BP_CBCMR_PCIE_AXI_SEL
,
.
bm
=
BM_CBCMR_PCIE_AXI_SEL
,
.
parents
=
{
&
axi_clk
,
&
ahb_clk
,
NULL
},
};
static
struct
multiplexer
vdo_axi_mux
=
{
.
clk
=
&
vdo_axi_clk
,
.
reg
=
CBCMR
,
.
bp
=
BP_CBCMR_VDO_AXI_SEL
,
.
bm
=
BM_CBCMR_VDO_AXI_SEL
,
.
parents
=
{
&
axi_clk
,
&
ahb_clk
,
NULL
},
};
static
struct
multiplexer
vpu_axi_mux
=
{
.
clk
=
&
vpu_clk
,
.
reg
=
CBCMR
,
.
bp
=
BP_CBCMR_VPU_AXI_SEL
,
.
bm
=
BM_CBCMR_VPU_AXI_SEL
,
.
parents
=
{
&
axi_clk
,
&
pll2_pfd_400m
,
&
pll2_pfd_352m
,
NULL
},
};
static
struct
multiplexer
gpu2d_core_mux
=
{
.
clk
=
&
gpu2d_core_clk
,
.
reg
=
CBCMR
,
.
bp
=
BP_CBCMR_GPU2D_CORE_SEL
,
.
bm
=
BM_CBCMR_GPU2D_CORE_SEL
,
.
parents
=
{
&
axi_clk
,
&
pll3_usb_otg
,
&
pll2_pfd_352m
,
&
pll2_pfd_400m
,
NULL
},
};
#define DEF_SSI_MUX(id) \
static struct multiplexer ssi##id##_mux = { \
.clk = &ssi##id##_clk, \
.reg = CSCMR1, \
.bp = BP_CSCMR1_SSI##id##_SEL, \
.bm = BM_CSCMR1_SSI##id##_SEL, \
.parents = { \
&pll3_pfd_508m, \
&pll3_pfd_454m, \
&pll4_audio, \
NULL \
}, \
}
DEF_SSI_MUX
(
1
);
DEF_SSI_MUX
(
2
);
DEF_SSI_MUX
(
3
);
#define DEF_USDHC_MUX(id) \
static struct multiplexer usdhc##id##_mux = { \
.clk = &usdhc##id##_clk, \
.reg = CSCMR1, \
.bp = BP_CSCMR1_USDHC##id##_SEL, \
.bm = BM_CSCMR1_USDHC##id##_SEL, \
.parents = { \
&pll2_pfd_400m, \
&pll2_pfd_352m, \
NULL \
}, \
}
DEF_USDHC_MUX
(
1
);
DEF_USDHC_MUX
(
2
);
DEF_USDHC_MUX
(
3
);
DEF_USDHC_MUX
(
4
);
static
struct
multiplexer
emi_mux
=
{
.
clk
=
&
emi_clk
,
.
reg
=
CSCMR1
,
.
bp
=
BP_CSCMR1_EMI_SEL
,
.
bm
=
BM_CSCMR1_EMI_SEL
,
.
parents
=
{
&
axi_clk
,
&
pll3_usb_otg
,
&
pll2_pfd_400m
,
&
pll2_pfd_352m
,
NULL
},
};
static
struct
multiplexer
emi_slow_mux
=
{
.
clk
=
&
emi_slow_clk
,
.
reg
=
CSCMR1
,
.
bp
=
BP_CSCMR1_EMI_SLOW_SEL
,
.
bm
=
BM_CSCMR1_EMI_SLOW_SEL
,
.
parents
=
{
&
axi_clk
,
&
pll3_usb_otg
,
&
pll2_pfd_400m
,
&
pll2_pfd_352m
,
NULL
},
};
static
struct
multiplexer
esai_mux
=
{
.
clk
=
&
esai_clk
,
.
reg
=
CSCMR2
,
.
bp
=
BP_CSCMR2_ESAI_SEL
,
.
bm
=
BM_CSCMR2_ESAI_SEL
,
.
parents
=
{
&
pll4_audio
,
&
pll3_pfd_508m
,
&
pll3_pfd_454m
,
&
pll3_usb_otg
,
NULL
},
};
#define DEF_LDB_DI_MUX(id) \
static struct multiplexer ldb_di##id##_mux = { \
.clk = &ldb_di##id##_clk, \
.reg = CS2CDR, \
.bp = BP_CS2CDR_LDB_DI##id##_SEL, \
.bm = BM_CS2CDR_LDB_DI##id##_SEL, \
.parents = { \
&pll5_video, \
&pll2_pfd_352m, \
&pll2_pfd_400m, \
&pll3_pfd_540m, \
&pll3_usb_otg, \
NULL \
}, \
}
DEF_LDB_DI_MUX
(
0
);
DEF_LDB_DI_MUX
(
1
);
static
struct
multiplexer
enfc_mux
=
{
.
clk
=
&
enfc_clk
,
.
reg
=
CS2CDR
,
.
bp
=
BP_CS2CDR_ENFC_SEL
,
.
bm
=
BM_CS2CDR_ENFC_SEL
,
.
parents
=
{
&
pll2_pfd_352m
,
&
pll2_bus
,
&
pll3_usb_otg
,
&
pll2_pfd_400m
,
NULL
},
};
static
struct
multiplexer
spdif_mux
=
{
.
clk
=
&
spdif_clk
,
.
reg
=
CDCDR
,
.
bp
=
BP_CDCDR_SPDIF_SEL
,
.
bm
=
BM_CDCDR_SPDIF_SEL
,
.
parents
=
{
&
pll4_audio
,
&
pll3_pfd_508m
,
&
pll3_pfd_454m
,
&
pll3_usb_otg
,
NULL
},
};
static
struct
multiplexer
asrc_serial_mux
=
{
.
clk
=
&
asrc_serial_clk
,
.
reg
=
CDCDR
,
.
bp
=
BP_CDCDR_ASRC_SERIAL_SEL
,
.
bm
=
BM_CDCDR_ASRC_SERIAL_SEL
,
.
parents
=
{
&
pll4_audio
,
&
pll3_pfd_508m
,
&
pll3_pfd_454m
,
&
pll3_usb_otg
,
NULL
},
};
static
struct
multiplexer
hsi_tx_mux
=
{
.
clk
=
&
hsi_tx_clk
,
.
reg
=
CDCDR
,
.
bp
=
BP_CDCDR_HSI_TX_SEL
,
.
bm
=
BM_CDCDR_HSI_TX_SEL
,
.
parents
=
{
&
pll3_120m
,
&
pll2_pfd_400m
,
NULL
},
};
#define DEF_IPU_DI_PRE_MUX(r, i, d) \
static struct multiplexer ipu##i##_di##d##_pre_mux = { \
.clk = &ipu##i##_di##d##_pre_clk, \
.reg = r, \
.bp = BP_##r##_IPU##i##_DI##d##_PRE_SEL, \
.bm = BM_##r##_IPU##i##_DI##d##_PRE_SEL, \
.parents = { \
&mmdc_ch0_axi_clk, \
&pll3_usb_otg, \
&pll5_video, \
&pll2_pfd_352m, \
&pll2_pfd_400m, \
&pll3_pfd_540m, \
NULL \
}, \
}
DEF_IPU_DI_PRE_MUX
(
CHSCCDR
,
1
,
0
);
DEF_IPU_DI_PRE_MUX
(
CHSCCDR
,
1
,
1
);
DEF_IPU_DI_PRE_MUX
(
CSCDR2
,
2
,
0
);
DEF_IPU_DI_PRE_MUX
(
CSCDR2
,
2
,
1
);
#define DEF_IPU_DI_MUX(r, i, d) \
static struct multiplexer ipu##i##_di##d##_mux = { \
.clk = &ipu##i##_di##d##_clk, \
.reg = r, \
.bp = BP_##r##_IPU##i##_DI##d##_SEL, \
.bm = BM_##r##_IPU##i##_DI##d##_SEL, \
.parents = { \
&ipu##i##_di##d##_pre_clk, \
&dummy_clk, \
&dummy_clk, \
&ldb_di0_clk, \
&ldb_di1_clk, \
NULL \
}, \
}
DEF_IPU_DI_MUX
(
CHSCCDR
,
1
,
0
);
DEF_IPU_DI_MUX
(
CHSCCDR
,
1
,
1
);
DEF_IPU_DI_MUX
(
CSCDR2
,
2
,
0
);
DEF_IPU_DI_MUX
(
CSCDR2
,
2
,
1
);
#define DEF_IPU_MUX(id) \
static struct multiplexer ipu##id##_mux = { \
.clk = &ipu##id##_clk, \
.reg = CSCDR3, \
.bp = BP_CSCDR3_IPU##id##_HSP_SEL, \
.bm = BM_CSCDR3_IPU##id##_HSP_SEL, \
.parents = { \
&mmdc_ch0_axi_clk, \
&pll2_pfd_400m, \
&pll3_120m, \
&pll3_pfd_540m, \
NULL \
}, \
}
DEF_IPU_MUX
(
1
);
DEF_IPU_MUX
(
2
);
static
struct
multiplexer
cko1_mux
=
{
.
clk
=
&
cko1_clk
,
.
reg
=
CCOSR
,
.
bp
=
BP_CCOSR_CKO1_SEL
,
.
bm
=
BM_CCOSR_CKO1_SEL
,
.
parents
=
{
&
pll3_usb_otg
,
&
pll2_bus
,
&
pll1_sys
,
&
pll5_video
,
&
dummy_clk
,
&
axi_clk
,
&
enfc_clk
,
&
ipu1_di0_clk
,
&
ipu1_di1_clk
,
&
ipu2_di0_clk
,
&
ipu2_di1_clk
,
&
ahb_clk
,
&
ipg_clk
,
&
ipg_perclk
,
&
ckil_clk
,
&
pll4_audio
,
NULL
},
};
static
struct
multiplexer
*
multiplexers
[]
=
{
&
axi_mux
,
&
periph_mux
,
&
periph_pre_mux
,
&
periph_clk2_mux
,
&
periph2_mux
,
&
periph2_pre_mux
,
&
periph2_clk2_mux
,
&
gpu2d_axi_mux
,
&
gpu3d_axi_mux
,
&
gpu3d_core_mux
,
&
gpu3d_shader_mux
,
&
pcie_axi_mux
,
&
vdo_axi_mux
,
&
vpu_axi_mux
,
&
gpu2d_core_mux
,
&
ssi1_mux
,
&
ssi2_mux
,
&
ssi3_mux
,
&
usdhc1_mux
,
&
usdhc2_mux
,
&
usdhc3_mux
,
&
usdhc4_mux
,
&
emi_mux
,
&
emi_slow_mux
,
&
esai_mux
,
&
ldb_di0_mux
,
&
ldb_di1_mux
,
&
enfc_mux
,
&
spdif_mux
,
&
asrc_serial_mux
,
&
hsi_tx_mux
,
&
ipu1_di0_pre_mux
,
&
ipu1_di0_mux
,
&
ipu1_di1_pre_mux
,
&
ipu1_di1_mux
,
&
ipu2_di0_pre_mux
,
&
ipu2_di0_mux
,
&
ipu2_di1_pre_mux
,
&
ipu2_di1_mux
,
&
ipu1_mux
,
&
ipu2_mux
,
&
cko1_mux
,
};
static
int
_clk_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
struct
multiplexer
*
m
;
int
i
,
num
;
u32
val
;
num
=
ARRAY_SIZE
(
multiplexers
);
for
(
i
=
0
;
i
<
num
;
i
++
)
if
(
multiplexers
[
i
]
->
clk
==
clk
)
{
m
=
multiplexers
[
i
];
break
;
}
if
(
i
==
num
)
return
-
EINVAL
;
i
=
0
;
while
(
m
->
parents
[
i
])
{
if
(
parent
==
m
->
parents
[
i
])
break
;
i
++
;
}
if
(
!
m
->
parents
[
i
]
||
m
->
parents
[
i
]
==
&
dummy_clk
)
return
-
EINVAL
;
val
=
readl_relaxed
(
m
->
reg
);
val
&=
~
m
->
bm
;
val
|=
i
<<
m
->
bp
;
writel_relaxed
(
val
,
m
->
reg
);
if
(
clk
==
&
periph_clk
)
return
clk_busy_wait
(
clk
);
return
0
;
}
#define DEF_NG_CLK(name, p) \
static struct clk name = { \
.get_rate = _clk_get_rate, \
.set_rate = _clk_set_rate, \
.round_rate = _clk_round_rate, \
.set_parent = _clk_set_parent, \
.parent = p, \
}
DEF_NG_CLK
(
periph_clk2_clk
,
&
osc_clk
);
DEF_NG_CLK
(
periph_pre_clk
,
&
pll2_bus
);
DEF_NG_CLK
(
periph_clk
,
&
periph_pre_clk
);
DEF_NG_CLK
(
periph2_clk2_clk
,
&
osc_clk
);
DEF_NG_CLK
(
periph2_pre_clk
,
&
pll2_bus
);
DEF_NG_CLK
(
periph2_clk
,
&
periph2_pre_clk
);
DEF_NG_CLK
(
axi_clk
,
&
periph_clk
);
DEF_NG_CLK
(
emi_clk
,
&
axi_clk
);
DEF_NG_CLK
(
arm_clk
,
&
pll1_sw_clk
);
DEF_NG_CLK
(
ahb_clk
,
&
periph_clk
);
DEF_NG_CLK
(
ipg_clk
,
&
ahb_clk
);
DEF_NG_CLK
(
ipg_perclk
,
&
ipg_clk
);
DEF_NG_CLK
(
ipu1_di0_pre_clk
,
&
pll3_pfd_540m
);
DEF_NG_CLK
(
ipu1_di1_pre_clk
,
&
pll3_pfd_540m
);
DEF_NG_CLK
(
ipu2_di0_pre_clk
,
&
pll3_pfd_540m
);
DEF_NG_CLK
(
ipu2_di1_pre_clk
,
&
pll3_pfd_540m
);
DEF_NG_CLK
(
asrc_serial_clk
,
&
pll3_usb_otg
);
#define DEF_CLK(name, er, es, p, s) \
static struct clk name = { \
.enable_reg = er, \
.enable_shift = es, \
.enable = _clk_enable, \
.disable = _clk_disable, \
.get_rate = _clk_get_rate, \
.set_rate = _clk_set_rate, \
.round_rate = _clk_round_rate, \
.set_parent = _clk_set_parent, \
.parent = p, \
.secondary = s, \
}
#define DEF_CLK_1B(name, er, es, p, s) \
static struct clk name = { \
.enable_reg = er, \
.enable_shift = es, \
.enable = _clk_enable_1b, \
.disable = _clk_disable_1b, \
.get_rate = _clk_get_rate, \
.set_rate = _clk_set_rate, \
.round_rate = _clk_round_rate, \
.set_parent = _clk_set_parent, \
.parent = p, \
.secondary = s, \
}
DEF_CLK
(
aips_tz1_clk
,
CCGR0
,
CG0
,
&
ahb_clk
,
NULL
);
DEF_CLK
(
aips_tz2_clk
,
CCGR0
,
CG1
,
&
ahb_clk
,
NULL
);
DEF_CLK
(
apbh_dma_clk
,
CCGR0
,
CG2
,
&
ahb_clk
,
NULL
);
DEF_CLK
(
asrc_clk
,
CCGR0
,
CG3
,
&
pll4_audio
,
NULL
);
DEF_CLK
(
can1_serial_clk
,
CCGR0
,
CG8
,
&
pll3_usb_otg
,
NULL
);
DEF_CLK
(
can1_clk
,
CCGR0
,
CG7
,
&
pll3_usb_otg
,
&
can1_serial_clk
);
DEF_CLK
(
can2_serial_clk
,
CCGR0
,
CG10
,
&
pll3_usb_otg
,
NULL
);
DEF_CLK
(
can2_clk
,
CCGR0
,
CG9
,
&
pll3_usb_otg
,
&
can2_serial_clk
);
DEF_CLK
(
ecspi1_clk
,
CCGR1
,
CG0
,
&
pll3_60m
,
NULL
);
DEF_CLK
(
ecspi2_clk
,
CCGR1
,
CG1
,
&
pll3_60m
,
NULL
);
DEF_CLK
(
ecspi3_clk
,
CCGR1
,
CG2
,
&
pll3_60m
,
NULL
);
DEF_CLK
(
ecspi4_clk
,
CCGR1
,
CG3
,
&
pll3_60m
,
NULL
);
DEF_CLK
(
ecspi5_clk
,
CCGR1
,
CG4
,
&
pll3_60m
,
NULL
);
DEF_CLK
(
enet_clk
,
CCGR1
,
CG5
,
&
ipg_clk
,
NULL
);
DEF_CLK
(
esai_clk
,
CCGR1
,
CG8
,
&
pll3_usb_otg
,
NULL
);
DEF_CLK
(
gpt_serial_clk
,
CCGR1
,
CG11
,
&
ipg_perclk
,
NULL
);
DEF_CLK
(
gpt_clk
,
CCGR1
,
CG10
,
&
ipg_perclk
,
&
gpt_serial_clk
);
DEF_CLK
(
gpu2d_core_clk
,
CCGR1
,
CG12
,
&
pll2_pfd_352m
,
&
gpu2d_axi_clk
);
DEF_CLK
(
gpu3d_core_clk
,
CCGR1
,
CG13
,
&
pll2_pfd_594m
,
&
gpu3d_axi_clk
);
DEF_CLK
(
gpu3d_shader_clk
,
CCGR1
,
CG13
,
&
pll3_pfd_720m
,
&
gpu3d_axi_clk
);
DEF_CLK
(
hdmi_iahb_clk
,
CCGR2
,
CG0
,
&
ahb_clk
,
NULL
);
DEF_CLK
(
hdmi_isfr_clk
,
CCGR2
,
CG2
,
&
pll3_pfd_540m
,
&
hdmi_iahb_clk
);
DEF_CLK
(
i2c1_clk
,
CCGR2
,
CG3
,
&
ipg_perclk
,
NULL
);
DEF_CLK
(
i2c2_clk
,
CCGR2
,
CG4
,
&
ipg_perclk
,
NULL
);
DEF_CLK
(
i2c3_clk
,
CCGR2
,
CG5
,
&
ipg_perclk
,
NULL
);
DEF_CLK
(
iim_clk
,
CCGR2
,
CG6
,
&
ipg_clk
,
NULL
);
DEF_CLK
(
enfc_clk
,
CCGR2
,
CG7
,
&
pll2_pfd_352m
,
NULL
);
DEF_CLK
(
ipu1_clk
,
CCGR3
,
CG0
,
&
mmdc_ch0_axi_clk
,
NULL
);
DEF_CLK
(
ipu1_di0_clk
,
CCGR3
,
CG1
,
&
ipu1_di0_pre_clk
,
NULL
);
DEF_CLK
(
ipu1_di1_clk
,
CCGR3
,
CG2
,
&
ipu1_di1_pre_clk
,
NULL
);
DEF_CLK
(
ipu2_clk
,
CCGR3
,
CG3
,
&
mmdc_ch0_axi_clk
,
NULL
);
DEF_CLK
(
ipu2_di0_clk
,
CCGR3
,
CG4
,
&
ipu2_di0_pre_clk
,
NULL
);
DEF_CLK
(
ipu2_di1_clk
,
CCGR3
,
CG5
,
&
ipu2_di1_pre_clk
,
NULL
);
DEF_CLK
(
ldb_di0_clk
,
CCGR3
,
CG6
,
&
pll3_pfd_540m
,
NULL
);
DEF_CLK
(
ldb_di1_clk
,
CCGR3
,
CG7
,
&
pll3_pfd_540m
,
NULL
);
DEF_CLK
(
hsi_tx_clk
,
CCGR3
,
CG8
,
&
pll2_pfd_400m
,
NULL
);
DEF_CLK
(
mlb_clk
,
CCGR3
,
CG9
,
&
pll6_mlb
,
NULL
);
DEF_CLK
(
mmdc_ch0_ipg_clk
,
CCGR3
,
CG12
,
&
ipg_clk
,
NULL
);
DEF_CLK
(
mmdc_ch0_axi_clk
,
CCGR3
,
CG10
,
&
periph_clk
,
&
mmdc_ch0_ipg_clk
);
DEF_CLK
(
mmdc_ch1_ipg_clk
,
CCGR3
,
CG13
,
&
ipg_clk
,
NULL
);
DEF_CLK
(
mmdc_ch1_axi_clk
,
CCGR3
,
CG11
,
&
periph2_clk
,
&
mmdc_ch1_ipg_clk
);
DEF_CLK
(
openvg_axi_clk
,
CCGR3
,
CG13
,
&
axi_clk
,
NULL
);
DEF_CLK
(
pwm1_clk
,
CCGR4
,
CG8
,
&
ipg_perclk
,
NULL
);
DEF_CLK
(
pwm2_clk
,
CCGR4
,
CG9
,
&
ipg_perclk
,
NULL
);
DEF_CLK
(
pwm3_clk
,
CCGR4
,
CG10
,
&
ipg_perclk
,
NULL
);
DEF_CLK
(
pwm4_clk
,
CCGR4
,
CG11
,
&
ipg_perclk
,
NULL
);
DEF_CLK
(
gpmi_bch_apb_clk
,
CCGR4
,
CG12
,
&
usdhc3_clk
,
NULL
);
DEF_CLK
(
gpmi_bch_clk
,
CCGR4
,
CG13
,
&
usdhc4_clk
,
&
gpmi_bch_apb_clk
);
DEF_CLK
(
gpmi_apb_clk
,
CCGR4
,
CG15
,
&
usdhc3_clk
,
&
gpmi_bch_clk
);
DEF_CLK
(
gpmi_io_clk
,
CCGR4
,
CG14
,
&
enfc_clk
,
&
gpmi_apb_clk
);
DEF_CLK
(
sdma_clk
,
CCGR5
,
CG3
,
&
ahb_clk
,
NULL
);
DEF_CLK
(
spba_clk
,
CCGR5
,
CG6
,
&
ipg_clk
,
NULL
);
DEF_CLK
(
spdif_clk
,
CCGR5
,
CG7
,
&
pll3_usb_otg
,
&
spba_clk
);
DEF_CLK
(
ssi1_clk
,
CCGR5
,
CG9
,
&
pll3_pfd_508m
,
NULL
);
DEF_CLK
(
ssi2_clk
,
CCGR5
,
CG10
,
&
pll3_pfd_508m
,
NULL
);
DEF_CLK
(
ssi3_clk
,
CCGR5
,
CG11
,
&
pll3_pfd_508m
,
NULL
);
DEF_CLK
(
uart_serial_clk
,
CCGR5
,
CG13
,
&
pll3_usb_otg
,
NULL
);
DEF_CLK
(
uart_clk
,
CCGR5
,
CG12
,
&
pll3_80m
,
&
uart_serial_clk
);
DEF_CLK
(
usboh3_clk
,
CCGR6
,
CG0
,
&
ipg_clk
,
NULL
);
DEF_CLK
(
usdhc1_clk
,
CCGR6
,
CG1
,
&
pll2_pfd_400m
,
NULL
);
DEF_CLK
(
usdhc2_clk
,
CCGR6
,
CG2
,
&
pll2_pfd_400m
,
NULL
);
DEF_CLK
(
usdhc3_clk
,
CCGR6
,
CG3
,
&
pll2_pfd_400m
,
NULL
);
DEF_CLK
(
usdhc4_clk
,
CCGR6
,
CG4
,
&
pll2_pfd_400m
,
NULL
);
DEF_CLK
(
emi_slow_clk
,
CCGR6
,
CG5
,
&
axi_clk
,
NULL
);
DEF_CLK
(
vdo_axi_clk
,
CCGR6
,
CG6
,
&
axi_clk
,
NULL
);
DEF_CLK
(
vpu_clk
,
CCGR6
,
CG7
,
&
axi_clk
,
NULL
);
DEF_CLK_1B
(
cko1_clk
,
CCOSR
,
BP_CCOSR_CKO1_EN
,
&
pll2_bus
,
NULL
);
static
int
pcie_clk_enable
(
struct
clk
*
clk
)
{
u32
val
;
val
=
readl_relaxed
(
PLL8_ENET
);
val
|=
BM_PLL_ENET_EN_PCIE
;
writel_relaxed
(
val
,
PLL8_ENET
);
return
_clk_enable
(
clk
);
}
static
void
pcie_clk_disable
(
struct
clk
*
clk
)
{
u32
val
;
_clk_disable
(
clk
);
val
=
readl_relaxed
(
PLL8_ENET
);
val
&=
BM_PLL_ENET_EN_PCIE
;
writel_relaxed
(
val
,
PLL8_ENET
);
}
static
struct
clk
pcie_clk
=
{
.
enable_reg
=
CCGR4
,
.
enable_shift
=
CG0
,
.
enable
=
pcie_clk_enable
,
.
disable
=
pcie_clk_disable
,
.
set_parent
=
_clk_set_parent
,
.
parent
=
&
axi_clk
,
.
secondary
=
&
pll8_enet
,
};
static
int
sata_clk_enable
(
struct
clk
*
clk
)
{
u32
val
;
val
=
readl_relaxed
(
PLL8_ENET
);
val
|=
BM_PLL_ENET_EN_SATA
;
writel_relaxed
(
val
,
PLL8_ENET
);
return
_clk_enable
(
clk
);
}
static
void
sata_clk_disable
(
struct
clk
*
clk
)
{
u32
val
;
_clk_disable
(
clk
);
val
=
readl_relaxed
(
PLL8_ENET
);
val
&=
BM_PLL_ENET_EN_SATA
;
writel_relaxed
(
val
,
PLL8_ENET
);
}
static
struct
clk
sata_clk
=
{
.
enable_reg
=
CCGR5
,
.
enable_shift
=
CG2
,
.
enable
=
sata_clk_enable
,
.
disable
=
sata_clk_disable
,
.
parent
=
&
ipg_clk
,
.
secondary
=
&
pll8_enet
,
};
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
}
static
struct
clk_lookup
lookups
[]
=
{
_REGISTER_CLOCK
(
"2020000.uart"
,
NULL
,
uart_clk
),
_REGISTER_CLOCK
(
"21e8000.uart"
,
NULL
,
uart_clk
),
_REGISTER_CLOCK
(
"21ec000.uart"
,
NULL
,
uart_clk
),
_REGISTER_CLOCK
(
"21f0000.uart"
,
NULL
,
uart_clk
),
_REGISTER_CLOCK
(
"21f4000.uart"
,
NULL
,
uart_clk
),
_REGISTER_CLOCK
(
"2188000.enet"
,
NULL
,
enet_clk
),
_REGISTER_CLOCK
(
"2190000.usdhc"
,
NULL
,
usdhc1_clk
),
_REGISTER_CLOCK
(
"2194000.usdhc"
,
NULL
,
usdhc2_clk
),
_REGISTER_CLOCK
(
"2198000.usdhc"
,
NULL
,
usdhc3_clk
),
_REGISTER_CLOCK
(
"219c000.usdhc"
,
NULL
,
usdhc4_clk
),
_REGISTER_CLOCK
(
"21a0000.i2c"
,
NULL
,
i2c1_clk
),
_REGISTER_CLOCK
(
"21a4000.i2c"
,
NULL
,
i2c2_clk
),
_REGISTER_CLOCK
(
"21a8000.i2c"
,
NULL
,
i2c3_clk
),
_REGISTER_CLOCK
(
"2008000.ecspi"
,
NULL
,
ecspi1_clk
),
_REGISTER_CLOCK
(
"200c000.ecspi"
,
NULL
,
ecspi2_clk
),
_REGISTER_CLOCK
(
"2010000.ecspi"
,
NULL
,
ecspi3_clk
),
_REGISTER_CLOCK
(
"2014000.ecspi"
,
NULL
,
ecspi4_clk
),
_REGISTER_CLOCK
(
"2018000.ecspi"
,
NULL
,
ecspi5_clk
),
_REGISTER_CLOCK
(
"20ec000.sdma"
,
NULL
,
sdma_clk
),
_REGISTER_CLOCK
(
"20bc000.wdog"
,
NULL
,
dummy_clk
),
_REGISTER_CLOCK
(
"20c0000.wdog"
,
NULL
,
dummy_clk
),
_REGISTER_CLOCK
(
"smp_twd"
,
NULL
,
twd_clk
),
_REGISTER_CLOCK
(
NULL
,
"ckih"
,
ckih_clk
),
_REGISTER_CLOCK
(
NULL
,
"ckil_clk"
,
ckil_clk
),
_REGISTER_CLOCK
(
NULL
,
"aips_tz1_clk"
,
aips_tz1_clk
),
_REGISTER_CLOCK
(
NULL
,
"aips_tz2_clk"
,
aips_tz2_clk
),
_REGISTER_CLOCK
(
NULL
,
"asrc_clk"
,
asrc_clk
),
_REGISTER_CLOCK
(
NULL
,
"can2_clk"
,
can2_clk
),
_REGISTER_CLOCK
(
NULL
,
"hdmi_isfr_clk"
,
hdmi_isfr_clk
),
_REGISTER_CLOCK
(
NULL
,
"iim_clk"
,
iim_clk
),
_REGISTER_CLOCK
(
NULL
,
"mlb_clk"
,
mlb_clk
),
_REGISTER_CLOCK
(
NULL
,
"openvg_axi_clk"
,
openvg_axi_clk
),
_REGISTER_CLOCK
(
NULL
,
"pwm1_clk"
,
pwm1_clk
),
_REGISTER_CLOCK
(
NULL
,
"pwm2_clk"
,
pwm2_clk
),
_REGISTER_CLOCK
(
NULL
,
"pwm3_clk"
,
pwm3_clk
),
_REGISTER_CLOCK
(
NULL
,
"pwm4_clk"
,
pwm4_clk
),
_REGISTER_CLOCK
(
NULL
,
"gpmi_io_clk"
,
gpmi_io_clk
),
_REGISTER_CLOCK
(
NULL
,
"usboh3_clk"
,
usboh3_clk
),
_REGISTER_CLOCK
(
NULL
,
"sata_clk"
,
sata_clk
),
_REGISTER_CLOCK
(
NULL
,
"cko1_clk"
,
cko1_clk
),
};
int
imx6q_set_lpm
(
enum
mxc_cpu_pwr_mode
mode
)
{
u32
val
=
readl_relaxed
(
CLPCR
);
val
&=
~
BM_CLPCR_LPM
;
switch
(
mode
)
{
case
WAIT_CLOCKED
:
break
;
case
WAIT_UNCLOCKED
:
val
|=
0x1
<<
BP_CLPCR_LPM
;
break
;
case
STOP_POWER_ON
:
val
|=
0x2
<<
BP_CLPCR_LPM
;
break
;
case
WAIT_UNCLOCKED_POWER_OFF
:
val
|=
0x1
<<
BP_CLPCR_LPM
;
val
&=
~
BM_CLPCR_VSTBY
;
val
&=
~
BM_CLPCR_SBYOS
;
break
;
case
STOP_POWER_OFF
:
val
|=
0x2
<<
BP_CLPCR_LPM
;
val
|=
0x3
<<
BP_CLPCR_STBY_COUNT
;
val
|=
BM_CLPCR_VSTBY
;
val
|=
BM_CLPCR_SBYOS
;
break
;
default:
return
-
EINVAL
;
}
writel_relaxed
(
val
,
CLPCR
);
return
0
;
}
static
struct
map_desc
imx6q_clock_desc
[]
=
{
imx_map_entry
(
MX6Q
,
CCM
,
MT_DEVICE
),
imx_map_entry
(
MX6Q
,
ANATOP
,
MT_DEVICE
),
};
void
__init
imx6q_clock_map_io
(
void
)
{
iotable_init
(
imx6q_clock_desc
,
ARRAY_SIZE
(
imx6q_clock_desc
));
}
int
__init
mx6q_clocks_init
(
void
)
{
struct
device_node
*
np
;
void
__iomem
*
base
;
int
i
,
irq
;
/* retrieve the freqency of fixed clocks from device tree */
for_each_compatible_node
(
np
,
NULL
,
"fixed-clock"
)
{
u32
rate
;
if
(
of_property_read_u32
(
np
,
"clock-frequency"
,
&
rate
))
continue
;
if
(
of_device_is_compatible
(
np
,
"fsl,imx-ckil"
))
external_low_reference
=
rate
;
else
if
(
of_device_is_compatible
(
np
,
"fsl,imx-ckih1"
))
external_high_reference
=
rate
;
else
if
(
of_device_is_compatible
(
np
,
"fsl,imx-osc"
))
oscillator_reference
=
rate
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
lookups
);
i
++
)
clkdev_add
(
&
lookups
[
i
]);
/* only keep necessary clocks on */
writel_relaxed
(
0x3
<<
CG0
|
0x3
<<
CG1
|
0x3
<<
CG2
,
CCGR0
);
writel_relaxed
(
0x3
<<
CG8
|
0x3
<<
CG9
|
0x3
<<
CG10
,
CCGR2
);
writel_relaxed
(
0x3
<<
CG10
|
0x3
<<
CG12
,
CCGR3
);
writel_relaxed
(
0x3
<<
CG4
|
0x3
<<
CG6
|
0x3
<<
CG7
,
CCGR4
);
writel_relaxed
(
0x3
<<
CG0
,
CCGR5
);
writel_relaxed
(
0
,
CCGR6
);
writel_relaxed
(
0
,
CCGR7
);
clk_enable
(
&
uart_clk
);
clk_enable
(
&
mmdc_ch0_axi_clk
);
clk_set_rate
(
&
pll4_audio
,
FREQ_650M
);
clk_set_rate
(
&
pll5_video
,
FREQ_650M
);
clk_set_parent
(
&
ipu1_di0_clk
,
&
ipu1_di0_pre_clk
);
clk_set_parent
(
&
ipu1_di0_pre_clk
,
&
pll5_video
);
clk_set_parent
(
&
gpu3d_shader_clk
,
&
pll2_pfd_594m
);
clk_set_rate
(
&
gpu3d_shader_clk
,
FREQ_594M
);
clk_set_parent
(
&
gpu3d_core_clk
,
&
mmdc_ch0_axi_clk
);
clk_set_rate
(
&
gpu3d_core_clk
,
FREQ_528M
);
clk_set_parent
(
&
asrc_serial_clk
,
&
pll3_usb_otg
);
clk_set_rate
(
&
asrc_serial_clk
,
1500000
);
clk_set_rate
(
&
enfc_clk
,
11000000
);
/*
* Before pinctrl API is available, we have to rely on the pad
* configuration set up by bootloader. For usdhc example here,
* u-boot sets up the pads for 49.5 MHz case, and we have to lower
* the usdhc clock from 198 to 49.5 MHz to match the pad configuration.
*
* FIXME: This is should be removed after pinctrl API is available.
* At that time, usdhc driver can call pinctrl API to change pad
* configuration dynamically per different usdhc clock settings.
*/
clk_set_rate
(
&
usdhc1_clk
,
49500000
);
clk_set_rate
(
&
usdhc2_clk
,
49500000
);
clk_set_rate
(
&
usdhc3_clk
,
49500000
);
clk_set_rate
(
&
usdhc4_clk
,
49500000
);
clk_set_parent
(
&
cko1_clk
,
&
ahb_clk
);
np
=
of_find_compatible_node
(
NULL
,
NULL
,
"fsl,imx6q-gpt"
);
base
=
of_iomap
(
np
,
0
);
WARN_ON
(
!
base
);
irq
=
irq_of_parse_and_map
(
np
,
0
);
mxc_timer_init
(
&
gpt_clk
,
base
,
irq
);
return
0
;
}
arch/arm/mach-imx/clock-mx51-mx53.c
已删除
100644 → 0
浏览文件 @
2acd1b6f
/*
* Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/clkdev.h>
#include <linux/of.h>
#include <asm/div64.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/clock.h>
#include "crm-regs-imx5.h"
/* External clock values passed-in by the board code */
static
unsigned
long
external_high_reference
,
external_low_reference
;
static
unsigned
long
oscillator_reference
,
ckih2_reference
;
static
struct
clk
osc_clk
;
static
struct
clk
pll1_main_clk
;
static
struct
clk
pll1_sw_clk
;
static
struct
clk
pll2_sw_clk
;
static
struct
clk
pll3_sw_clk
;
static
struct
clk
mx53_pll4_sw_clk
;
static
struct
clk
lp_apm_clk
;
static
struct
clk
periph_apm_clk
;
static
struct
clk
ahb_clk
;
static
struct
clk
ipg_clk
;
static
struct
clk
usboh3_clk
;
static
struct
clk
emi_fast_clk
;
static
struct
clk
ipu_clk
;
static
struct
clk
mipi_hsc1_clk
;
static
struct
clk
esdhc1_clk
;
static
struct
clk
esdhc2_clk
;
static
struct
clk
esdhc3_mx53_clk
;
#define MAX_DPLL_WAIT_TRIES 1000
/* 1000 * udelay(1) = 1ms */
/* calculate best pre and post dividers to get the required divider */
static
void
__calc_pre_post_dividers
(
u32
div
,
u32
*
pre
,
u32
*
post
,
u32
max_pre
,
u32
max_post
)
{
if
(
div
>=
max_pre
*
max_post
)
{
*
pre
=
max_pre
;
*
post
=
max_post
;
}
else
if
(
div
>=
max_pre
)
{
u32
min_pre
,
temp_pre
,
old_err
,
err
;
min_pre
=
DIV_ROUND_UP
(
div
,
max_post
);
old_err
=
max_pre
;
for
(
temp_pre
=
max_pre
;
temp_pre
>=
min_pre
;
temp_pre
--
)
{
err
=
div
%
temp_pre
;
if
(
err
==
0
)
{
*
pre
=
temp_pre
;
break
;
}
err
=
temp_pre
-
err
;
if
(
err
<
old_err
)
{
old_err
=
err
;
*
pre
=
temp_pre
;
}
}
*
post
=
DIV_ROUND_UP
(
div
,
*
pre
);
}
else
{
*
pre
=
div
;
*
post
=
1
;
}
}
static
void
_clk_ccgr_setclk
(
struct
clk
*
clk
,
unsigned
mode
)
{
u32
reg
=
__raw_readl
(
clk
->
enable_reg
);
reg
&=
~
(
MXC_CCM_CCGRx_CG_MASK
<<
clk
->
enable_shift
);
reg
|=
mode
<<
clk
->
enable_shift
;
__raw_writel
(
reg
,
clk
->
enable_reg
);
}
static
int
_clk_ccgr_enable
(
struct
clk
*
clk
)
{
_clk_ccgr_setclk
(
clk
,
MXC_CCM_CCGRx_MOD_ON
);
return
0
;
}
static
void
_clk_ccgr_disable
(
struct
clk
*
clk
)
{
_clk_ccgr_setclk
(
clk
,
MXC_CCM_CCGRx_MOD_OFF
);
}
static
int
_clk_ccgr_enable_inrun
(
struct
clk
*
clk
)
{
_clk_ccgr_setclk
(
clk
,
MXC_CCM_CCGRx_MOD_IDLE
);
return
0
;
}
static
void
_clk_ccgr_disable_inwait
(
struct
clk
*
clk
)
{
_clk_ccgr_setclk
(
clk
,
MXC_CCM_CCGRx_MOD_IDLE
);
}
/*
* For the 4-to-1 muxed input clock
*/
static
inline
u32
_get_mux
(
struct
clk
*
parent
,
struct
clk
*
m0
,
struct
clk
*
m1
,
struct
clk
*
m2
,
struct
clk
*
m3
)
{
if
(
parent
==
m0
)
return
0
;
else
if
(
parent
==
m1
)
return
1
;
else
if
(
parent
==
m2
)
return
2
;
else
if
(
parent
==
m3
)
return
3
;
else
BUG
();
return
-
EINVAL
;
}
static
inline
void
__iomem
*
_mx51_get_pll_base
(
struct
clk
*
pll
)
{
if
(
pll
==
&
pll1_main_clk
)
return
MX51_DPLL1_BASE
;
else
if
(
pll
==
&
pll2_sw_clk
)
return
MX51_DPLL2_BASE
;
else
if
(
pll
==
&
pll3_sw_clk
)
return
MX51_DPLL3_BASE
;
else
BUG
();
return
NULL
;
}
static
inline
void
__iomem
*
_mx53_get_pll_base
(
struct
clk
*
pll
)
{
if
(
pll
==
&
pll1_main_clk
)
return
MX53_DPLL1_BASE
;
else
if
(
pll
==
&
pll2_sw_clk
)
return
MX53_DPLL2_BASE
;
else
if
(
pll
==
&
pll3_sw_clk
)
return
MX53_DPLL3_BASE
;
else
if
(
pll
==
&
mx53_pll4_sw_clk
)
return
MX53_DPLL4_BASE
;
else
BUG
();
return
NULL
;
}
static
inline
void
__iomem
*
_get_pll_base
(
struct
clk
*
pll
)
{
if
(
cpu_is_mx51
())
return
_mx51_get_pll_base
(
pll
);
else
return
_mx53_get_pll_base
(
pll
);
}
static
unsigned
long
clk_pll_get_rate
(
struct
clk
*
clk
)
{
long
mfi
,
mfn
,
mfd
,
pdf
,
ref_clk
,
mfn_abs
;
unsigned
long
dp_op
,
dp_mfd
,
dp_mfn
,
dp_ctl
,
pll_hfsm
,
dbl
;
void
__iomem
*
pllbase
;
s64
temp
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
pllbase
=
_get_pll_base
(
clk
);
dp_ctl
=
__raw_readl
(
pllbase
+
MXC_PLL_DP_CTL
);
pll_hfsm
=
dp_ctl
&
MXC_PLL_DP_CTL_HFSM
;
dbl
=
dp_ctl
&
MXC_PLL_DP_CTL_DPDCK0_2_EN
;
if
(
pll_hfsm
==
0
)
{
dp_op
=
__raw_readl
(
pllbase
+
MXC_PLL_DP_OP
);
dp_mfd
=
__raw_readl
(
pllbase
+
MXC_PLL_DP_MFD
);
dp_mfn
=
__raw_readl
(
pllbase
+
MXC_PLL_DP_MFN
);
}
else
{
dp_op
=
__raw_readl
(
pllbase
+
MXC_PLL_DP_HFS_OP
);
dp_mfd
=
__raw_readl
(
pllbase
+
MXC_PLL_DP_HFS_MFD
);
dp_mfn
=
__raw_readl
(
pllbase
+
MXC_PLL_DP_HFS_MFN
);
}
pdf
=
dp_op
&
MXC_PLL_DP_OP_PDF_MASK
;
mfi
=
(
dp_op
&
MXC_PLL_DP_OP_MFI_MASK
)
>>
MXC_PLL_DP_OP_MFI_OFFSET
;
mfi
=
(
mfi
<=
5
)
?
5
:
mfi
;
mfd
=
dp_mfd
&
MXC_PLL_DP_MFD_MASK
;
mfn
=
mfn_abs
=
dp_mfn
&
MXC_PLL_DP_MFN_MASK
;
/* Sign extend to 32-bits */
if
(
mfn
>=
0x04000000
)
{
mfn
|=
0xFC000000
;
mfn_abs
=
-
mfn
;
}
ref_clk
=
2
*
parent_rate
;
if
(
dbl
!=
0
)
ref_clk
*=
2
;
ref_clk
/=
(
pdf
+
1
);
temp
=
(
u64
)
ref_clk
*
mfn_abs
;
do_div
(
temp
,
mfd
+
1
);
if
(
mfn
<
0
)
temp
=
-
temp
;
temp
=
(
ref_clk
*
mfi
)
+
temp
;
return
temp
;
}
static
int
_clk_pll_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
reg
;
void
__iomem
*
pllbase
;
long
mfi
,
pdf
,
mfn
,
mfd
=
999999
;
s64
temp64
;
unsigned
long
quad_parent_rate
;
unsigned
long
pll_hfsm
,
dp_ctl
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
pllbase
=
_get_pll_base
(
clk
);
quad_parent_rate
=
4
*
parent_rate
;
pdf
=
mfi
=
-
1
;
while
(
++
pdf
<
16
&&
mfi
<
5
)
mfi
=
rate
*
(
pdf
+
1
)
/
quad_parent_rate
;
if
(
mfi
>
15
)
return
-
EINVAL
;
pdf
--
;
temp64
=
rate
*
(
pdf
+
1
)
-
quad_parent_rate
*
mfi
;
do_div
(
temp64
,
quad_parent_rate
/
1000000
);
mfn
=
(
long
)
temp64
;
dp_ctl
=
__raw_readl
(
pllbase
+
MXC_PLL_DP_CTL
);
/* use dpdck0_2 */
__raw_writel
(
dp_ctl
|
0x1000L
,
pllbase
+
MXC_PLL_DP_CTL
);
pll_hfsm
=
dp_ctl
&
MXC_PLL_DP_CTL_HFSM
;
if
(
pll_hfsm
==
0
)
{
reg
=
mfi
<<
4
|
pdf
;
__raw_writel
(
reg
,
pllbase
+
MXC_PLL_DP_OP
);
__raw_writel
(
mfd
,
pllbase
+
MXC_PLL_DP_MFD
);
__raw_writel
(
mfn
,
pllbase
+
MXC_PLL_DP_MFN
);
}
else
{
reg
=
mfi
<<
4
|
pdf
;
__raw_writel
(
reg
,
pllbase
+
MXC_PLL_DP_HFS_OP
);
__raw_writel
(
mfd
,
pllbase
+
MXC_PLL_DP_HFS_MFD
);
__raw_writel
(
mfn
,
pllbase
+
MXC_PLL_DP_HFS_MFN
);
}
return
0
;
}
static
int
_clk_pll_enable
(
struct
clk
*
clk
)
{
u32
reg
;
void
__iomem
*
pllbase
;
int
i
=
0
;
pllbase
=
_get_pll_base
(
clk
);
reg
=
__raw_readl
(
pllbase
+
MXC_PLL_DP_CTL
);
if
(
reg
&
MXC_PLL_DP_CTL_UPEN
)
return
0
;
reg
|=
MXC_PLL_DP_CTL_UPEN
;
__raw_writel
(
reg
,
pllbase
+
MXC_PLL_DP_CTL
);
/* Wait for lock */
do
{
reg
=
__raw_readl
(
pllbase
+
MXC_PLL_DP_CTL
);
if
(
reg
&
MXC_PLL_DP_CTL_LRF
)
break
;
udelay
(
1
);
}
while
(
++
i
<
MAX_DPLL_WAIT_TRIES
);
if
(
i
==
MAX_DPLL_WAIT_TRIES
)
{
pr_err
(
"MX5: pll locking failed
\n
"
);
return
-
EINVAL
;
}
return
0
;
}
static
void
_clk_pll_disable
(
struct
clk
*
clk
)
{
u32
reg
;
void
__iomem
*
pllbase
;
pllbase
=
_get_pll_base
(
clk
);
reg
=
__raw_readl
(
pllbase
+
MXC_PLL_DP_CTL
)
&
~
MXC_PLL_DP_CTL_UPEN
;
__raw_writel
(
reg
,
pllbase
+
MXC_PLL_DP_CTL
);
}
static
int
_clk_pll1_sw_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
u32
reg
,
step
;
reg
=
__raw_readl
(
MXC_CCM_CCSR
);
/* When switching from pll_main_clk to a bypass clock, first select a
* multiplexed clock in 'step_sel', then shift the glitchless mux
* 'pll1_sw_clk_sel'.
*
* When switching back, do it in reverse order
*/
if
(
parent
==
&
pll1_main_clk
)
{
/* Switch to pll1_main_clk */
reg
&=
~
MXC_CCM_CCSR_PLL1_SW_CLK_SEL
;
__raw_writel
(
reg
,
MXC_CCM_CCSR
);
/* step_clk mux switched to lp_apm, to save power. */
reg
=
__raw_readl
(
MXC_CCM_CCSR
);
reg
&=
~
MXC_CCM_CCSR_STEP_SEL_MASK
;
reg
|=
(
MXC_CCM_CCSR_STEP_SEL_LP_APM
<<
MXC_CCM_CCSR_STEP_SEL_OFFSET
);
}
else
{
if
(
parent
==
&
lp_apm_clk
)
{
step
=
MXC_CCM_CCSR_STEP_SEL_LP_APM
;
}
else
if
(
parent
==
&
pll2_sw_clk
)
{
step
=
MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED
;
}
else
if
(
parent
==
&
pll3_sw_clk
)
{
step
=
MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED
;
}
else
return
-
EINVAL
;
reg
&=
~
MXC_CCM_CCSR_STEP_SEL_MASK
;
reg
|=
(
step
<<
MXC_CCM_CCSR_STEP_SEL_OFFSET
);
__raw_writel
(
reg
,
MXC_CCM_CCSR
);
/* Switch to step_clk */
reg
=
__raw_readl
(
MXC_CCM_CCSR
);
reg
|=
MXC_CCM_CCSR_PLL1_SW_CLK_SEL
;
}
__raw_writel
(
reg
,
MXC_CCM_CCSR
);
return
0
;
}
static
unsigned
long
clk_pll1_sw_get_rate
(
struct
clk
*
clk
)
{
u32
reg
,
div
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
reg
=
__raw_readl
(
MXC_CCM_CCSR
);
if
(
clk
->
parent
==
&
pll2_sw_clk
)
{
div
=
((
reg
&
MXC_CCM_CCSR_PLL2_PODF_MASK
)
>>
MXC_CCM_CCSR_PLL2_PODF_OFFSET
)
+
1
;
}
else
if
(
clk
->
parent
==
&
pll3_sw_clk
)
{
div
=
((
reg
&
MXC_CCM_CCSR_PLL3_PODF_MASK
)
>>
MXC_CCM_CCSR_PLL3_PODF_OFFSET
)
+
1
;
}
else
div
=
1
;
return
parent_rate
/
div
;
}
static
int
_clk_pll2_sw_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
u32
reg
;
reg
=
__raw_readl
(
MXC_CCM_CCSR
);
if
(
parent
==
&
pll2_sw_clk
)
reg
&=
~
MXC_CCM_CCSR_PLL2_SW_CLK_SEL
;
else
reg
|=
MXC_CCM_CCSR_PLL2_SW_CLK_SEL
;
__raw_writel
(
reg
,
MXC_CCM_CCSR
);
return
0
;
}
static
int
_clk_lp_apm_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
u32
reg
;
if
(
parent
==
&
osc_clk
)
reg
=
__raw_readl
(
MXC_CCM_CCSR
)
&
~
MXC_CCM_CCSR_LP_APM_SEL
;
else
return
-
EINVAL
;
__raw_writel
(
reg
,
MXC_CCM_CCSR
);
return
0
;
}
static
unsigned
long
clk_cpu_get_rate
(
struct
clk
*
clk
)
{
u32
cacrr
,
div
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
cacrr
=
__raw_readl
(
MXC_CCM_CACRR
);
div
=
(
cacrr
&
MXC_CCM_CACRR_ARM_PODF_MASK
)
+
1
;
return
parent_rate
/
div
;
}
static
int
clk_cpu_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
reg
,
cpu_podf
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
cpu_podf
=
parent_rate
/
rate
-
1
;
/* use post divider to change freq */
reg
=
__raw_readl
(
MXC_CCM_CACRR
);
reg
&=
~
MXC_CCM_CACRR_ARM_PODF_MASK
;
reg
|=
cpu_podf
<<
MXC_CCM_CACRR_ARM_PODF_OFFSET
;
__raw_writel
(
reg
,
MXC_CCM_CACRR
);
return
0
;
}
static
int
_clk_periph_apm_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
u32
reg
,
mux
;
int
i
=
0
;
mux
=
_get_mux
(
parent
,
&
pll1_sw_clk
,
&
pll3_sw_clk
,
&
lp_apm_clk
,
NULL
);
reg
=
__raw_readl
(
MXC_CCM_CBCMR
)
&
~
MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK
;
reg
|=
mux
<<
MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET
;
__raw_writel
(
reg
,
MXC_CCM_CBCMR
);
/* Wait for lock */
do
{
reg
=
__raw_readl
(
MXC_CCM_CDHIPR
);
if
(
!
(
reg
&
MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY
))
break
;
udelay
(
1
);
}
while
(
++
i
<
MAX_DPLL_WAIT_TRIES
);
if
(
i
==
MAX_DPLL_WAIT_TRIES
)
{
pr_err
(
"MX5: Set parent for periph_apm clock failed
\n
"
);
return
-
EINVAL
;
}
return
0
;
}
static
int
_clk_main_bus_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
u32
reg
;
reg
=
__raw_readl
(
MXC_CCM_CBCDR
);
if
(
parent
==
&
pll2_sw_clk
)
reg
&=
~
MXC_CCM_CBCDR_PERIPH_CLK_SEL
;
else
if
(
parent
==
&
periph_apm_clk
)
reg
|=
MXC_CCM_CBCDR_PERIPH_CLK_SEL
;
else
return
-
EINVAL
;
__raw_writel
(
reg
,
MXC_CCM_CBCDR
);
return
0
;
}
static
struct
clk
main_bus_clk
=
{
.
parent
=
&
pll2_sw_clk
,
.
set_parent
=
_clk_main_bus_set_parent
,
};
static
unsigned
long
clk_ahb_get_rate
(
struct
clk
*
clk
)
{
u32
reg
,
div
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
reg
=
__raw_readl
(
MXC_CCM_CBCDR
);
div
=
((
reg
&
MXC_CCM_CBCDR_AHB_PODF_MASK
)
>>
MXC_CCM_CBCDR_AHB_PODF_OFFSET
)
+
1
;
return
parent_rate
/
div
;
}
static
int
_clk_ahb_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
reg
,
div
;
unsigned
long
parent_rate
;
int
i
=
0
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
div
=
parent_rate
/
rate
;
if
(
div
>
8
||
div
<
1
||
((
parent_rate
/
div
)
!=
rate
))
return
-
EINVAL
;
reg
=
__raw_readl
(
MXC_CCM_CBCDR
);
reg
&=
~
MXC_CCM_CBCDR_AHB_PODF_MASK
;
reg
|=
(
div
-
1
)
<<
MXC_CCM_CBCDR_AHB_PODF_OFFSET
;
__raw_writel
(
reg
,
MXC_CCM_CBCDR
);
/* Wait for lock */
do
{
reg
=
__raw_readl
(
MXC_CCM_CDHIPR
);
if
(
!
(
reg
&
MXC_CCM_CDHIPR_AHB_PODF_BUSY
))
break
;
udelay
(
1
);
}
while
(
++
i
<
MAX_DPLL_WAIT_TRIES
);
if
(
i
==
MAX_DPLL_WAIT_TRIES
)
{
pr_err
(
"MX5: clk_ahb_set_rate failed
\n
"
);
return
-
EINVAL
;
}
return
0
;
}
static
unsigned
long
_clk_ahb_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
div
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
div
=
parent_rate
/
rate
;
if
(
div
>
8
)
div
=
8
;
else
if
(
div
==
0
)
div
++
;
return
parent_rate
/
div
;
}
static
int
_clk_max_enable
(
struct
clk
*
clk
)
{
u32
reg
;
_clk_ccgr_enable
(
clk
);
/* Handshake with MAX when LPM is entered. */
reg
=
__raw_readl
(
MXC_CCM_CLPCR
);
if
(
cpu_is_mx51
())
reg
&=
~
MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS
;
else
if
(
cpu_is_mx53
())
reg
&=
~
MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS
;
__raw_writel
(
reg
,
MXC_CCM_CLPCR
);
return
0
;
}
static
void
_clk_max_disable
(
struct
clk
*
clk
)
{
u32
reg
;
_clk_ccgr_disable_inwait
(
clk
);
/* No Handshake with MAX when LPM is entered as its disabled. */
reg
=
__raw_readl
(
MXC_CCM_CLPCR
);
if
(
cpu_is_mx51
())
reg
|=
MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS
;
else
if
(
cpu_is_mx53
())
reg
&=
~
MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS
;
__raw_writel
(
reg
,
MXC_CCM_CLPCR
);
}
static
unsigned
long
clk_ipg_get_rate
(
struct
clk
*
clk
)
{
u32
reg
,
div
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
reg
=
__raw_readl
(
MXC_CCM_CBCDR
);
div
=
((
reg
&
MXC_CCM_CBCDR_IPG_PODF_MASK
)
>>
MXC_CCM_CBCDR_IPG_PODF_OFFSET
)
+
1
;
return
parent_rate
/
div
;
}
static
unsigned
long
clk_ipg_per_get_rate
(
struct
clk
*
clk
)
{
u32
reg
,
prediv1
,
prediv2
,
podf
;
unsigned
long
parent_rate
;
parent_rate
=
clk_get_rate
(
clk
->
parent
);
if
(
clk
->
parent
==
&
main_bus_clk
||
clk
->
parent
==
&
lp_apm_clk
)
{
/* the main_bus_clk is the one before the DVFS engine */
reg
=
__raw_readl
(
MXC_CCM_CBCDR
);
prediv1
=
((
reg
&
MXC_CCM_CBCDR_PERCLK_PRED1_MASK
)
>>
MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET
)
+
1
;
prediv2
=
((
reg
&
MXC_CCM_CBCDR_PERCLK_PRED2_MASK
)
>>
MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET
)
+
1
;
podf
=
((
reg
&
MXC_CCM_CBCDR_PERCLK_PODF_MASK
)
>>
MXC_CCM_CBCDR_PERCLK_PODF_OFFSET
)
+
1
;
return
parent_rate
/
(
prediv1
*
prediv2
*
podf
);
}
else
if
(
clk
->
parent
==
&
ipg_clk
)
return
parent_rate
;
else
BUG
();
}
static
int
_clk_ipg_per_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
u32
reg
;
reg
=
__raw_readl
(
MXC_CCM_CBCMR
);
reg
&=
~
MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL
;
reg
&=
~
MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL
;
if
(
parent
==
&
ipg_clk
)
reg
|=
MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL
;
else
if
(
parent
==
&
lp_apm_clk
)
reg
|=
MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL
;
else
if
(
parent
!=
&
main_bus_clk
)
return
-
EINVAL
;
__raw_writel
(
reg
,
MXC_CCM_CBCMR
);
return
0
;
}
#define clk_nfc_set_parent NULL
static
unsigned
long
clk_nfc_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
rate
;
u32
reg
,
div
;
reg
=
__raw_readl
(
MXC_CCM_CBCDR
);
div
=
((
reg
&
MXC_CCM_CBCDR_NFC_PODF_MASK
)
>>
MXC_CCM_CBCDR_NFC_PODF_OFFSET
)
+
1
;
rate
=
clk_get_rate
(
clk
->
parent
)
/
div
;
WARN_ON
(
rate
==
0
);
return
rate
;
}
static
unsigned
long
clk_nfc_round_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
div
;
unsigned
long
parent_rate
=
clk_get_rate
(
clk
->
parent
);
if
(
!
rate
)
return
-
EINVAL
;
div
=
parent_rate
/
rate
;
if
(
parent_rate
%
rate
)
div
++
;
if
(
div
>
8
)
return
-
EINVAL
;
return
parent_rate
/
div
;
}
static
int
clk_nfc_set_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
{
u32
reg
,
div
;
div
=
clk_get_rate
(
clk
->
parent
)
/
rate
;
if
(
div
==
0
)
div
++
;
if
(((
clk_get_rate
(
clk
->
parent
)
/
div
)
!=
rate
)
||
(
div
>
8
))
return
-
EINVAL
;
reg
=
__raw_readl
(
MXC_CCM_CBCDR
);
reg
&=
~
MXC_CCM_CBCDR_NFC_PODF_MASK
;
reg
|=
(
div
-
1
)
<<
MXC_CCM_CBCDR_NFC_PODF_OFFSET
;
__raw_writel
(
reg
,
MXC_CCM_CBCDR
);
while
(
__raw_readl
(
MXC_CCM_CDHIPR
)
&
MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY
){
}
return
0
;
}
static
unsigned
long
get_high_reference_clock_rate
(
struct
clk
*
clk
)
{
return
external_high_reference
;
}
static
unsigned
long
get_low_reference_clock_rate
(
struct
clk
*
clk
)
{
return
external_low_reference
;
}
static
unsigned
long
get_oscillator_reference_clock_rate
(
struct
clk
*
clk
)
{
return
oscillator_reference
;
}
static
unsigned
long
get_ckih2_reference_clock_rate
(
struct
clk
*
clk
)
{
return
ckih2_reference
;
}
static
unsigned
long
clk_emi_slow_get_rate
(
struct
clk
*
clk
)
{
u32
reg
,
div
;
reg
=
__raw_readl
(
MXC_CCM_CBCDR
);
div
=
((
reg
&
MXC_CCM_CBCDR_EMI_PODF_MASK
)
>>
MXC_CCM_CBCDR_EMI_PODF_OFFSET
)
+
1
;
return
clk_get_rate
(
clk
->
parent
)
/
div
;
}
static
unsigned
long
_clk_ddr_hf_get_rate
(
struct
clk
*
clk
)
{
unsigned
long
rate
;
u32
reg
,
div
;
reg
=
__raw_readl
(
MXC_CCM_CBCDR
);
div
=
((
reg
&
MXC_CCM_CBCDR_DDR_PODF_MASK
)
>>
MXC_CCM_CBCDR_DDR_PODF_OFFSET
)
+
1
;
rate
=
clk_get_rate
(
clk
->
parent
)
/
div
;
return
rate
;
}
/* External high frequency clock */
static
struct
clk
ckih_clk
=
{
.
get_rate
=
get_high_reference_clock_rate
,
};
static
struct
clk
ckih2_clk
=
{
.
get_rate
=
get_ckih2_reference_clock_rate
,
};
static
struct
clk
osc_clk
=
{
.
get_rate
=
get_oscillator_reference_clock_rate
,
};
/* External low frequency (32kHz) clock */
static
struct
clk
ckil_clk
=
{
.
get_rate
=
get_low_reference_clock_rate
,
};
static
struct
clk
pll1_main_clk
=
{
.
parent
=
&
osc_clk
,
.
get_rate
=
clk_pll_get_rate
,
.
enable
=
_clk_pll_enable
,
.
disable
=
_clk_pll_disable
,
};
/* Clock tree block diagram (WIP):
* CCM: Clock Controller Module
*
* PLL output -> |
* | CCM Switcher -> CCM_CLK_ROOT_GEN ->
* PLL bypass -> |
*
*/
/* PLL1 SW supplies to ARM core */
static
struct
clk
pll1_sw_clk
=
{
.
parent
=
&
pll1_main_clk
,
.
set_parent
=
_clk_pll1_sw_set_parent
,
.
get_rate
=
clk_pll1_sw_get_rate
,
};
/* PLL2 SW supplies to AXI/AHB/IP buses */
static
struct
clk
pll2_sw_clk
=
{
.
parent
=
&
osc_clk
,
.
get_rate
=
clk_pll_get_rate
,
.
set_rate
=
_clk_pll_set_rate
,
.
set_parent
=
_clk_pll2_sw_set_parent
,
.
enable
=
_clk_pll_enable
,
.
disable
=
_clk_pll_disable
,
};
/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */
static
struct
clk
pll3_sw_clk
=
{
.
parent
=
&
osc_clk
,
.
set_rate
=
_clk_pll_set_rate
,
.
get_rate
=
clk_pll_get_rate
,
.
enable
=
_clk_pll_enable
,
.
disable
=
_clk_pll_disable
,
};
/* PLL4 SW supplies to LVDS Display Bridge(LDB) */
static
struct
clk
mx53_pll4_sw_clk
=
{
.
parent
=
&
osc_clk
,
.
set_rate
=
_clk_pll_set_rate
,
.
enable
=
_clk_pll_enable
,
.
disable
=
_clk_pll_disable
,
};
/* Low-power Audio Playback Mode clock */
static
struct
clk
lp_apm_clk
=
{
.
parent
=
&
osc_clk
,
.
set_parent
=
_clk_lp_apm_set_parent
,
};
static
struct
clk
periph_apm_clk
=
{
.
parent
=
&
pll1_sw_clk
,
.
set_parent
=
_clk_periph_apm_set_parent
,
};
static
struct
clk
cpu_clk
=
{
.
parent
=
&
pll1_sw_clk
,
.
get_rate
=
clk_cpu_get_rate
,
.
set_rate
=
clk_cpu_set_rate
,
};
static
struct
clk
ahb_clk
=
{
.
parent
=
&
main_bus_clk
,
.
get_rate
=
clk_ahb_get_rate
,
.
set_rate
=
_clk_ahb_set_rate
,
.
round_rate
=
_clk_ahb_round_rate
,
};
static
struct
clk
iim_clk
=
{
.
parent
=
&
ipg_clk
,
.
enable_reg
=
MXC_CCM_CCGR0
,
.
enable_shift
=
MXC_CCM_CCGRx_CG15_OFFSET
,
};
/* Main IP interface clock for access to registers */
static
struct
clk
ipg_clk
=
{
.
parent
=
&
ahb_clk
,
.
get_rate
=
clk_ipg_get_rate
,
};
static
struct
clk
ipg_perclk
=
{
.
parent
=
&
lp_apm_clk
,
.
get_rate
=
clk_ipg_per_get_rate
,
.
set_parent
=
_clk_ipg_per_set_parent
,
};
static
struct
clk
ahb_max_clk
=
{
.
parent
=
&
ahb_clk
,
.
enable_reg
=
MXC_CCM_CCGR0
,
.
enable_shift
=
MXC_CCM_CCGRx_CG14_OFFSET
,
.
enable
=
_clk_max_enable
,
.
disable
=
_clk_max_disable
,
};
static
struct
clk
aips_tz1_clk
=
{
.
parent
=
&
ahb_clk
,
.
secondary
=
&
ahb_max_clk
,
.
enable_reg
=
MXC_CCM_CCGR0
,
.
enable_shift
=
MXC_CCM_CCGRx_CG12_OFFSET
,
.
enable
=
_clk_ccgr_enable
,
.
disable
=
_clk_ccgr_disable_inwait
,
};
static
struct
clk
aips_tz2_clk
=
{
.
parent
=
&
ahb_clk
,
.
secondary
=
&
ahb_max_clk
,
.
enable_reg
=
MXC_CCM_CCGR0
,
.
enable_shift
=
MXC_CCM_CCGRx_CG13_OFFSET
,
.
enable
=
_clk_ccgr_enable
,
.
disable
=
_clk_ccgr_disable_inwait
,
};
static
struct
clk
gpc_dvfs_clk
=
{
.
enable_reg
=
MXC_CCM_CCGR5
,
.
enable_shift
=
MXC_CCM_CCGRx_CG12_OFFSET
,
.
enable
=
_clk_ccgr_enable
,
.
disable
=
_clk_ccgr_disable
,
};
static
struct
clk
gpt_32k_clk
=
{
.
id
=
0
,
.
parent
=
&
ckil_clk
,
};
static
struct
clk
dummy_clk
=
{
.
id
=
0
,
};
static
struct
clk
emi_slow_clk
=
{
.
parent
=
&
pll2_sw_clk
,
.
enable_reg
=
MXC_CCM_CCGR5
,
.
enable_shift
=
MXC_CCM_CCGRx_CG8_OFFSET
,
.
enable
=
_clk_ccgr_enable
,
.
disable
=
_clk_ccgr_disable_inwait
,
.
get_rate
=
clk_emi_slow_get_rate
,
};
static
int
clk_ipu_enable
(
struct
clk
*
clk
)
{
u32
reg
;
_clk_ccgr_enable
(
clk
);
/* Enable handshake with IPU when certain clock rates are changed */
reg
=
__raw_readl
(
MXC_CCM_CCDR
);
reg
&=
~
MXC_CCM_CCDR_IPU_HS_MASK
;
__raw_writel
(
reg
,
MXC_CCM_CCDR
);
/* Enable handshake with IPU when LPM is entered */
reg
=
__raw_readl
(
MXC_CCM_CLPCR
);
reg
&=
~
MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS
;
__raw_writel
(
reg
,
MXC_CCM_CLPCR
);
return
0
;
}
static
void
clk_ipu_disable
(
struct
clk
*
clk
)
{
u32
reg
;
_clk_ccgr_disable
(
clk
);
/* Disable handshake with IPU whe dividers are changed */
reg
=
__raw_readl
(
MXC_CCM_CCDR
);
reg
|=
MXC_CCM_CCDR_IPU_HS_MASK
;
__raw_writel
(
reg
,
MXC_CCM_CCDR
);
/* Disable handshake with IPU when LPM is entered */
reg
=
__raw_readl
(
MXC_CCM_CLPCR
);
reg
|=
MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS
;
__raw_writel
(
reg
,
MXC_CCM_CLPCR
);
}
static
struct
clk
ahbmux1_clk
=
{
.
parent
=
&
ahb_clk
,
.
secondary
=
&
ahb_max_clk
,
.
enable_reg
=
MXC_CCM_CCGR0
,
.
enable_shift
=
MXC_CCM_CCGRx_CG8_OFFSET
,
.
enable
=
_clk_ccgr_enable
,
.
disable
=
_clk_ccgr_disable_inwait
,
};
static
struct
clk
ipu_sec_clk
=
{
.
parent
=
&
emi_fast_clk
,
.
secondary
=
&
ahbmux1_clk
,
};
static
struct
clk
ddr_hf_clk
=
{
.
parent
=
&
pll1_sw_clk
,
.
get_rate
=
_clk_ddr_hf_get_rate
,
};
static
struct
clk
ddr_clk
=
{
.
parent
=
&
ddr_hf_clk
,
};
/* clock definitions for MIPI HSC unit which has been removed
* from documentation, but not from hardware
*/
static
int
_clk_hsc_enable
(
struct
clk
*
clk
)
{
u32
reg
;
_clk_ccgr_enable
(
clk
);
/* Handshake with IPU when certain clock rates are changed. */
reg
=
__raw_readl
(
MXC_CCM_CCDR
);
reg
&=
~
MXC_CCM_CCDR_HSC_HS_MASK
;
__raw_writel
(
reg
,
MXC_CCM_CCDR
);
reg
=
__raw_readl
(
MXC_CCM_CLPCR
);
reg
&=
~
MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS
;
__raw_writel
(
reg
,
MXC_CCM_CLPCR
);
return
0
;
}
static
void
_clk_hsc_disable
(
struct
clk
*
clk
)
{
u32
reg
;
_clk_ccgr_disable
(
clk
);
/* No handshake with HSC as its not enabled. */
reg
=
__raw_readl
(
MXC_CCM_CCDR
);
reg
|=
MXC_CCM_CCDR_HSC_HS_MASK
;
__raw_writel
(
reg
,
MXC_CCM_CCDR
);
reg
=
__raw_readl
(
MXC_CCM_CLPCR
);
reg
|=
MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS
;
__raw_writel
(
reg
,
MXC_CCM_CLPCR
);
}
static
struct
clk
mipi_hsp_clk
=
{
.
parent
=
&
ipu_clk
,
.
enable_reg
=
MXC_CCM_CCGR4
,
.
enable_shift
=
MXC_CCM_CCGRx_CG6_OFFSET
,
.
enable
=
_clk_hsc_enable
,
.
disable
=
_clk_hsc_disable
,
.
secondary
=
&
mipi_hsc1_clk
,
};
#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s) \
static struct clk name = { \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
.get_rate = pfx##_get_rate, \
.set_rate = pfx##_set_rate, \
.round_rate = pfx##_round_rate, \
.set_parent = pfx##_set_parent, \
.enable = _clk_ccgr_enable, \
.disable = _clk_ccgr_disable, \
.parent = p, \
.secondary = s, \
}
#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \
static struct clk name = { \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
.get_rate = pfx##_get_rate, \
.set_rate = pfx##_set_rate, \
.set_parent = pfx##_set_parent, \
.enable = _clk_max_enable, \
.disable = _clk_max_disable, \
.parent = p, \
.secondary = s, \
}
#define CLK_GET_RATE(name, nr, bitsname) \
static unsigned long clk_##name##_get_rate(struct clk *clk) \
{ \
u32 reg, pred, podf; \
\
reg = __raw_readl(MXC_CCM_CSCDR##nr); \
pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK) \
>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK) \
>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
\
return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), \
(pred + 1) * (podf + 1)); \
}
#define CLK_SET_PARENT(name, nr, bitsname) \
static int clk_##name##_set_parent(struct clk *clk, struct clk *parent) \
{ \
u32 reg, mux; \
\
mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, \
&pll3_sw_clk, &lp_apm_clk); \
reg = __raw_readl(MXC_CCM_CSCMR##nr) & \
~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK; \
reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET; \
__raw_writel(reg, MXC_CCM_CSCMR##nr); \
\
return 0; \
}
#define CLK_SET_RATE(name, nr, bitsname) \
static int clk_##name##_set_rate(struct clk *clk, unsigned long rate) \
{ \
u32 reg, div, parent_rate; \
u32 pre = 0, post = 0; \
\
parent_rate = clk_get_rate(clk->parent); \
div = parent_rate / rate; \
\
if ((parent_rate / div) != rate) \
return -EINVAL; \
\
__calc_pre_post_dividers(div, &pre, &post, \
(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >> \
MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1, \
(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >> \
MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
\
/* Set sdhc1 clock divider */
\
reg = __raw_readl(MXC_CCM_CSCDR##nr) & \
~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK \
| MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK); \
reg |= (post - 1) << \
MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
reg |= (pre - 1) << \
MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
__raw_writel(reg, MXC_CCM_CSCDR##nr); \
\
return 0; \
}
/* UART */
CLK_GET_RATE
(
uart
,
1
,
UART
)
CLK_SET_PARENT
(
uart
,
1
,
UART
)
static
struct
clk
uart_root_clk
=
{
.
parent
=
&
pll2_sw_clk
,
.
get_rate
=
clk_uart_get_rate
,
.
set_parent
=
clk_uart_set_parent
,
};
/* USBOH3 */
CLK_GET_RATE
(
usboh3
,
1
,
USBOH3
)
CLK_SET_PARENT
(
usboh3
,
1
,
USBOH3
)
static
struct
clk
usboh3_clk
=
{
.
parent
=
&
pll2_sw_clk
,
.
get_rate
=
clk_usboh3_get_rate
,
.
set_parent
=
clk_usboh3_set_parent
,
.
enable
=
_clk_ccgr_enable
,
.
disable
=
_clk_ccgr_disable
,
.
enable_reg
=
MXC_CCM_CCGR2
,
.
enable_shift
=
MXC_CCM_CCGRx_CG14_OFFSET
,
};
static
struct
clk
usb_ahb_clk
=
{
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_ccgr_enable
,
.
disable
=
_clk_ccgr_disable
,
.
enable_reg
=
MXC_CCM_CCGR2
,
.
enable_shift
=
MXC_CCM_CCGRx_CG13_OFFSET
,
};
static
int
clk_usb_phy1_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
u32
reg
;
reg
=
__raw_readl
(
MXC_CCM_CSCMR1
)
&
~
MXC_CCM_CSCMR1_USB_PHY_CLK_SEL
;
if
(
parent
==
&
pll3_sw_clk
)
reg
|=
1
<<
MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET
;
__raw_writel
(
reg
,
MXC_CCM_CSCMR1
);
return
0
;
}
static
struct
clk
usb_phy1_clk
=
{
.
parent
=
&
pll3_sw_clk
,
.
set_parent
=
clk_usb_phy1_set_parent
,
.
enable
=
_clk_ccgr_enable
,
.
enable_reg
=
MXC_CCM_CCGR2
,
.
enable_shift
=
MXC_CCM_CCGRx_CG0_OFFSET
,
.
disable
=
_clk_ccgr_disable
,
};
/* eCSPI */
CLK_GET_RATE
(
ecspi
,
2
,
CSPI
)
CLK_SET_PARENT
(
ecspi
,
1
,
CSPI
)
static
struct
clk
ecspi_main_clk
=
{
.
parent
=
&
pll3_sw_clk
,
.
get_rate
=
clk_ecspi_get_rate
,
.
set_parent
=
clk_ecspi_set_parent
,
};
/* eSDHC */
CLK_GET_RATE
(
esdhc1
,
1
,
ESDHC1_MSHC1
)
CLK_SET_PARENT
(
esdhc1
,
1
,
ESDHC1_MSHC1
)
CLK_SET_RATE
(
esdhc1
,
1
,
ESDHC1_MSHC1
)
/* mx51 specific */
CLK_GET_RATE
(
esdhc2
,
1
,
ESDHC2_MSHC2
)
CLK_SET_PARENT
(
esdhc2
,
1
,
ESDHC2_MSHC2
)
CLK_SET_RATE
(
esdhc2
,
1
,
ESDHC2_MSHC2
)
static
int
clk_esdhc3_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
u32
reg
;
reg
=
__raw_readl
(
MXC_CCM_CSCMR1
);
if
(
parent
==
&
esdhc1_clk
)
reg
&=
~
MXC_CCM_CSCMR1_ESDHC3_CLK_SEL
;
else
if
(
parent
==
&
esdhc2_clk
)
reg
|=
MXC_CCM_CSCMR1_ESDHC3_CLK_SEL
;
else
return
-
EINVAL
;
__raw_writel
(
reg
,
MXC_CCM_CSCMR1
);
return
0
;
}
static
int
clk_esdhc4_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
u32
reg
;
reg
=
__raw_readl
(
MXC_CCM_CSCMR1
);
if
(
parent
==
&
esdhc1_clk
)
reg
&=
~
MXC_CCM_CSCMR1_ESDHC4_CLK_SEL
;
else
if
(
parent
==
&
esdhc2_clk
)
reg
|=
MXC_CCM_CSCMR1_ESDHC4_CLK_SEL
;
else
return
-
EINVAL
;
__raw_writel
(
reg
,
MXC_CCM_CSCMR1
);
return
0
;
}
/* mx53 specific */
static
int
clk_esdhc2_mx53_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
u32
reg
;
reg
=
__raw_readl
(
MXC_CCM_CSCMR1
);
if
(
parent
==
&
esdhc1_clk
)
reg
&=
~
MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL
;
else
if
(
parent
==
&
esdhc3_mx53_clk
)
reg
|=
MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL
;
else
return
-
EINVAL
;
__raw_writel
(
reg
,
MXC_CCM_CSCMR1
);
return
0
;
}
CLK_GET_RATE
(
esdhc3_mx53
,
1
,
ESDHC3_MX53
)
CLK_SET_PARENT
(
esdhc3_mx53
,
1
,
ESDHC3_MX53
)
CLK_SET_RATE
(
esdhc3_mx53
,
1
,
ESDHC3_MX53
)
static
int
clk_esdhc4_mx53_set_parent
(
struct
clk
*
clk
,
struct
clk
*
parent
)
{
u32
reg
;
reg
=
__raw_readl
(
MXC_CCM_CSCMR1
);
if
(
parent
==
&
esdhc1_clk
)
reg
&=
~
MXC_CCM_CSCMR1_ESDHC4_CLK_SEL
;
else
if
(
parent
==
&
esdhc3_mx53_clk
)
reg
|=
MXC_CCM_CSCMR1_ESDHC4_CLK_SEL
;
else
return
-
EINVAL
;
__raw_writel
(
reg
,
MXC_CCM_CSCMR1
);
return
0
;
}
#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \
static struct clk name = { \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
.get_rate = gr, \
.set_rate = sr, \
.enable = e, \
.disable = d, \
.parent = p, \
.secondary = s, \
}
#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \
DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
/* Shared peripheral bus arbiter */
DEFINE_CLOCK
(
spba_clk
,
0
,
MXC_CCM_CCGR5
,
MXC_CCM_CCGRx_CG0_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
NULL
);
/* UART */
DEFINE_CLOCK
(
uart1_ipg_clk
,
0
,
MXC_CCM_CCGR1
,
MXC_CCM_CCGRx_CG3_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
&
aips_tz1_clk
);
DEFINE_CLOCK
(
uart2_ipg_clk
,
1
,
MXC_CCM_CCGR1
,
MXC_CCM_CCGRx_CG5_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
&
aips_tz1_clk
);
DEFINE_CLOCK
(
uart3_ipg_clk
,
2
,
MXC_CCM_CCGR1
,
MXC_CCM_CCGRx_CG7_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
&
spba_clk
);
DEFINE_CLOCK
(
uart4_ipg_clk
,
3
,
MXC_CCM_CCGR7
,
MXC_CCM_CCGRx_CG4_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
&
spba_clk
);
DEFINE_CLOCK
(
uart5_ipg_clk
,
4
,
MXC_CCM_CCGR7
,
MXC_CCM_CCGRx_CG6_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
&
spba_clk
);
DEFINE_CLOCK
(
uart1_clk
,
0
,
MXC_CCM_CCGR1
,
MXC_CCM_CCGRx_CG4_OFFSET
,
NULL
,
NULL
,
&
uart_root_clk
,
&
uart1_ipg_clk
);
DEFINE_CLOCK
(
uart2_clk
,
1
,
MXC_CCM_CCGR1
,
MXC_CCM_CCGRx_CG6_OFFSET
,
NULL
,
NULL
,
&
uart_root_clk
,
&
uart2_ipg_clk
);
DEFINE_CLOCK
(
uart3_clk
,
2
,
MXC_CCM_CCGR1
,
MXC_CCM_CCGRx_CG8_OFFSET
,
NULL
,
NULL
,
&
uart_root_clk
,
&
uart3_ipg_clk
);
DEFINE_CLOCK
(
uart4_clk
,
3
,
MXC_CCM_CCGR7
,
MXC_CCM_CCGRx_CG5_OFFSET
,
NULL
,
NULL
,
&
uart_root_clk
,
&
uart4_ipg_clk
);
DEFINE_CLOCK
(
uart5_clk
,
4
,
MXC_CCM_CCGR7
,
MXC_CCM_CCGRx_CG7_OFFSET
,
NULL
,
NULL
,
&
uart_root_clk
,
&
uart5_ipg_clk
);
/* GPT */
DEFINE_CLOCK
(
gpt_ipg_clk
,
0
,
MXC_CCM_CCGR2
,
MXC_CCM_CCGRx_CG10_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
NULL
);
DEFINE_CLOCK
(
gpt_clk
,
0
,
MXC_CCM_CCGR2
,
MXC_CCM_CCGRx_CG9_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
&
gpt_ipg_clk
);
DEFINE_CLOCK
(
pwm1_clk
,
0
,
MXC_CCM_CCGR2
,
MXC_CCM_CCGRx_CG6_OFFSET
,
NULL
,
NULL
,
&
ipg_perclk
,
NULL
);
DEFINE_CLOCK
(
pwm2_clk
,
0
,
MXC_CCM_CCGR2
,
MXC_CCM_CCGRx_CG8_OFFSET
,
NULL
,
NULL
,
&
ipg_perclk
,
NULL
);
/* I2C */
DEFINE_CLOCK
(
i2c1_clk
,
0
,
MXC_CCM_CCGR1
,
MXC_CCM_CCGRx_CG9_OFFSET
,
NULL
,
NULL
,
&
ipg_perclk
,
NULL
);
DEFINE_CLOCK
(
i2c2_clk
,
1
,
MXC_CCM_CCGR1
,
MXC_CCM_CCGRx_CG10_OFFSET
,
NULL
,
NULL
,
&
ipg_perclk
,
NULL
);
DEFINE_CLOCK
(
hsi2c_clk
,
0
,
MXC_CCM_CCGR1
,
MXC_CCM_CCGRx_CG11_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
NULL
);
DEFINE_CLOCK
(
i2c3_mx53_clk
,
0
,
MXC_CCM_CCGR1
,
MXC_CCM_CCGRx_CG11_OFFSET
,
NULL
,
NULL
,
&
ipg_perclk
,
NULL
);
/* FEC */
DEFINE_CLOCK
(
fec_clk
,
0
,
MXC_CCM_CCGR2
,
MXC_CCM_CCGRx_CG12_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
NULL
);
/* NFC */
DEFINE_CLOCK_CCGR
(
nfc_clk
,
0
,
MXC_CCM_CCGR5
,
MXC_CCM_CCGRx_CG10_OFFSET
,
clk_nfc
,
&
emi_slow_clk
,
NULL
);
/* SSI */
DEFINE_CLOCK
(
ssi1_ipg_clk
,
0
,
MXC_CCM_CCGR3
,
MXC_CCM_CCGRx_CG8_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
NULL
);
DEFINE_CLOCK
(
ssi1_clk
,
0
,
MXC_CCM_CCGR3
,
MXC_CCM_CCGRx_CG9_OFFSET
,
NULL
,
NULL
,
&
pll3_sw_clk
,
&
ssi1_ipg_clk
);
DEFINE_CLOCK
(
ssi2_ipg_clk
,
1
,
MXC_CCM_CCGR3
,
MXC_CCM_CCGRx_CG10_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
NULL
);
DEFINE_CLOCK
(
ssi2_clk
,
1
,
MXC_CCM_CCGR3
,
MXC_CCM_CCGRx_CG11_OFFSET
,
NULL
,
NULL
,
&
pll3_sw_clk
,
&
ssi2_ipg_clk
);
DEFINE_CLOCK
(
ssi3_ipg_clk
,
2
,
MXC_CCM_CCGR3
,
MXC_CCM_CCGRx_CG12_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
NULL
);
DEFINE_CLOCK
(
ssi3_clk
,
2
,
MXC_CCM_CCGR3
,
MXC_CCM_CCGRx_CG13_OFFSET
,
NULL
,
NULL
,
&
pll3_sw_clk
,
&
ssi3_ipg_clk
);
/* eCSPI */
DEFINE_CLOCK_FULL
(
ecspi1_ipg_clk
,
0
,
MXC_CCM_CCGR4
,
MXC_CCM_CCGRx_CG9_OFFSET
,
NULL
,
NULL
,
_clk_ccgr_enable_inrun
,
_clk_ccgr_disable
,
&
ipg_clk
,
&
spba_clk
);
DEFINE_CLOCK
(
ecspi1_clk
,
0
,
MXC_CCM_CCGR4
,
MXC_CCM_CCGRx_CG10_OFFSET
,
NULL
,
NULL
,
&
ecspi_main_clk
,
&
ecspi1_ipg_clk
);
DEFINE_CLOCK_FULL
(
ecspi2_ipg_clk
,
0
,
MXC_CCM_CCGR4
,
MXC_CCM_CCGRx_CG11_OFFSET
,
NULL
,
NULL
,
_clk_ccgr_enable_inrun
,
_clk_ccgr_disable
,
&
ipg_clk
,
&
aips_tz2_clk
);
DEFINE_CLOCK
(
ecspi2_clk
,
0
,
MXC_CCM_CCGR4
,
MXC_CCM_CCGRx_CG12_OFFSET
,
NULL
,
NULL
,
&
ecspi_main_clk
,
&
ecspi2_ipg_clk
);
/* CSPI */
DEFINE_CLOCK
(
cspi_ipg_clk
,
0
,
MXC_CCM_CCGR4
,
MXC_CCM_CCGRx_CG9_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
&
aips_tz2_clk
);
DEFINE_CLOCK
(
cspi_clk
,
0
,
MXC_CCM_CCGR4
,
MXC_CCM_CCGRx_CG13_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
&
cspi_ipg_clk
);
/* SDMA */
DEFINE_CLOCK
(
sdma_clk
,
1
,
MXC_CCM_CCGR4
,
MXC_CCM_CCGRx_CG15_OFFSET
,
NULL
,
NULL
,
&
ahb_clk
,
NULL
);
/* eSDHC */
DEFINE_CLOCK_FULL
(
esdhc1_ipg_clk
,
0
,
MXC_CCM_CCGR3
,
MXC_CCM_CCGRx_CG0_OFFSET
,
NULL
,
NULL
,
_clk_max_enable
,
_clk_max_disable
,
&
ipg_clk
,
NULL
);
DEFINE_CLOCK_MAX
(
esdhc1_clk
,
0
,
MXC_CCM_CCGR3
,
MXC_CCM_CCGRx_CG1_OFFSET
,
clk_esdhc1
,
&
pll2_sw_clk
,
&
esdhc1_ipg_clk
);
DEFINE_CLOCK_FULL
(
esdhc2_ipg_clk
,
1
,
MXC_CCM_CCGR3
,
MXC_CCM_CCGRx_CG2_OFFSET
,
NULL
,
NULL
,
_clk_max_enable
,
_clk_max_disable
,
&
ipg_clk
,
NULL
);
DEFINE_CLOCK_FULL
(
esdhc3_ipg_clk
,
2
,
MXC_CCM_CCGR3
,
MXC_CCM_CCGRx_CG4_OFFSET
,
NULL
,
NULL
,
_clk_max_enable
,
_clk_max_disable
,
&
ipg_clk
,
NULL
);
DEFINE_CLOCK_FULL
(
esdhc4_ipg_clk
,
3
,
MXC_CCM_CCGR3
,
MXC_CCM_CCGRx_CG6_OFFSET
,
NULL
,
NULL
,
_clk_max_enable
,
_clk_max_disable
,
&
ipg_clk
,
NULL
);
/* mx51 specific */
DEFINE_CLOCK_MAX
(
esdhc2_clk
,
1
,
MXC_CCM_CCGR3
,
MXC_CCM_CCGRx_CG3_OFFSET
,
clk_esdhc2
,
&
pll2_sw_clk
,
&
esdhc2_ipg_clk
);
static
struct
clk
esdhc3_clk
=
{
.
id
=
2
,
.
parent
=
&
esdhc1_clk
,
.
set_parent
=
clk_esdhc3_set_parent
,
.
enable_reg
=
MXC_CCM_CCGR3
,
.
enable_shift
=
MXC_CCM_CCGRx_CG5_OFFSET
,
.
enable
=
_clk_max_enable
,
.
disable
=
_clk_max_disable
,
.
secondary
=
&
esdhc3_ipg_clk
,
};
static
struct
clk
esdhc4_clk
=
{
.
id
=
3
,
.
parent
=
&
esdhc1_clk
,
.
set_parent
=
clk_esdhc4_set_parent
,
.
enable_reg
=
MXC_CCM_CCGR3
,
.
enable_shift
=
MXC_CCM_CCGRx_CG7_OFFSET
,
.
enable
=
_clk_max_enable
,
.
disable
=
_clk_max_disable
,
.
secondary
=
&
esdhc4_ipg_clk
,
};
/* mx53 specific */
static
struct
clk
esdhc2_mx53_clk
=
{
.
id
=
2
,
.
parent
=
&
esdhc1_clk
,
.
set_parent
=
clk_esdhc2_mx53_set_parent
,
.
enable_reg
=
MXC_CCM_CCGR3
,
.
enable_shift
=
MXC_CCM_CCGRx_CG3_OFFSET
,
.
enable
=
_clk_max_enable
,
.
disable
=
_clk_max_disable
,
.
secondary
=
&
esdhc3_ipg_clk
,
};
DEFINE_CLOCK_MAX
(
esdhc3_mx53_clk
,
2
,
MXC_CCM_CCGR3
,
MXC_CCM_CCGRx_CG5_OFFSET
,
clk_esdhc3_mx53
,
&
pll2_sw_clk
,
&
esdhc2_ipg_clk
);
static
struct
clk
esdhc4_mx53_clk
=
{
.
id
=
3
,
.
parent
=
&
esdhc1_clk
,
.
set_parent
=
clk_esdhc4_mx53_set_parent
,
.
enable_reg
=
MXC_CCM_CCGR3
,
.
enable_shift
=
MXC_CCM_CCGRx_CG7_OFFSET
,
.
enable
=
_clk_max_enable
,
.
disable
=
_clk_max_disable
,
.
secondary
=
&
esdhc4_ipg_clk
,
};
static
struct
clk
sata_clk
=
{
.
parent
=
&
ipg_clk
,
.
enable
=
_clk_max_enable
,
.
enable_reg
=
MXC_CCM_CCGR4
,
.
enable_shift
=
MXC_CCM_CCGRx_CG1_OFFSET
,
.
disable
=
_clk_max_disable
,
};
static
struct
clk
ahci_phy_clk
=
{
.
parent
=
&
usb_phy1_clk
,
};
static
struct
clk
ahci_dma_clk
=
{
.
parent
=
&
ahb_clk
,
};
DEFINE_CLOCK
(
mipi_esc_clk
,
0
,
MXC_CCM_CCGR4
,
MXC_CCM_CCGRx_CG5_OFFSET
,
NULL
,
NULL
,
NULL
,
&
pll2_sw_clk
);
DEFINE_CLOCK
(
mipi_hsc2_clk
,
0
,
MXC_CCM_CCGR4
,
MXC_CCM_CCGRx_CG4_OFFSET
,
NULL
,
NULL
,
&
mipi_esc_clk
,
&
pll2_sw_clk
);
DEFINE_CLOCK
(
mipi_hsc1_clk
,
0
,
MXC_CCM_CCGR4
,
MXC_CCM_CCGRx_CG3_OFFSET
,
NULL
,
NULL
,
&
mipi_hsc2_clk
,
&
pll2_sw_clk
);
/* IPU */
DEFINE_CLOCK_FULL
(
ipu_clk
,
0
,
MXC_CCM_CCGR5
,
MXC_CCM_CCGRx_CG5_OFFSET
,
NULL
,
NULL
,
clk_ipu_enable
,
clk_ipu_disable
,
&
ahb_clk
,
&
ipu_sec_clk
);
DEFINE_CLOCK_FULL
(
emi_fast_clk
,
0
,
MXC_CCM_CCGR5
,
MXC_CCM_CCGRx_CG7_OFFSET
,
NULL
,
NULL
,
_clk_ccgr_enable
,
_clk_ccgr_disable_inwait
,
&
ddr_clk
,
NULL
);
DEFINE_CLOCK
(
ipu_di0_clk
,
0
,
MXC_CCM_CCGR6
,
MXC_CCM_CCGRx_CG5_OFFSET
,
NULL
,
NULL
,
&
pll3_sw_clk
,
NULL
);
DEFINE_CLOCK
(
ipu_di1_clk
,
0
,
MXC_CCM_CCGR6
,
MXC_CCM_CCGRx_CG6_OFFSET
,
NULL
,
NULL
,
&
pll3_sw_clk
,
NULL
);
/* PATA */
DEFINE_CLOCK
(
pata_clk
,
0
,
MXC_CCM_CCGR4
,
MXC_CCM_CCGRx_CG0_OFFSET
,
NULL
,
NULL
,
&
ipg_clk
,
&
spba_clk
);
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = &c, \
},
static
struct
clk_lookup
mx51_lookups
[]
=
{
/* i.mx51 has the i.mx21 type uart */
_REGISTER_CLOCK
(
"imx21-uart.0"
,
NULL
,
uart1_clk
)
_REGISTER_CLOCK
(
"imx21-uart.1"
,
NULL
,
uart2_clk
)
_REGISTER_CLOCK
(
"imx21-uart.2"
,
NULL
,
uart3_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpt"
,
gpt_clk
)
/* i.mx51 has the i.mx27 type fec */
_REGISTER_CLOCK
(
"imx27-fec.0"
,
NULL
,
fec_clk
)
_REGISTER_CLOCK
(
"mxc_pwm.0"
,
"pwm"
,
pwm1_clk
)
_REGISTER_CLOCK
(
"mxc_pwm.1"
,
"pwm"
,
pwm2_clk
)
_REGISTER_CLOCK
(
"imx-i2c.0"
,
NULL
,
i2c1_clk
)
_REGISTER_CLOCK
(
"imx-i2c.1"
,
NULL
,
i2c2_clk
)
_REGISTER_CLOCK
(
"imx-i2c.2"
,
NULL
,
hsi2c_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.0"
,
"usb"
,
usboh3_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.0"
,
"usb_ahb"
,
usb_ahb_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.0"
,
"usb_phy1"
,
usb_phy1_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.1"
,
"usb"
,
usboh3_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.1"
,
"usb_ahb"
,
usb_ahb_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.2"
,
"usb"
,
usboh3_clk
)
_REGISTER_CLOCK
(
"mxc-ehci.2"
,
"usb_ahb"
,
usb_ahb_clk
)
_REGISTER_CLOCK
(
"fsl-usb2-udc"
,
"usb"
,
usboh3_clk
)
_REGISTER_CLOCK
(
"fsl-usb2-udc"
,
"usb_ahb"
,
ahb_clk
)
_REGISTER_CLOCK
(
"imx-keypad"
,
NULL
,
dummy_clk
)
_REGISTER_CLOCK
(
"mxc_nand"
,
NULL
,
nfc_clk
)
_REGISTER_CLOCK
(
"imx-ssi.0"
,
NULL
,
ssi1_clk
)
_REGISTER_CLOCK
(
"imx-ssi.1"
,
NULL
,
ssi2_clk
)
_REGISTER_CLOCK
(
"imx-ssi.2"
,
NULL
,
ssi3_clk
)
/* i.mx51 has the i.mx35 type sdma */
_REGISTER_CLOCK
(
"imx35-sdma"
,
NULL
,
sdma_clk
)
_REGISTER_CLOCK
(
NULL
,
"ckih"
,
ckih_clk
)
_REGISTER_CLOCK
(
NULL
,
"ckih2"
,
ckih2_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpt_32k"
,
gpt_32k_clk
)
_REGISTER_CLOCK
(
"imx51-ecspi.0"
,
NULL
,
ecspi1_clk
)
_REGISTER_CLOCK
(
"imx51-ecspi.1"
,
NULL
,
ecspi2_clk
)
/* i.mx51 has the i.mx35 type cspi */
_REGISTER_CLOCK
(
"imx35-cspi.0"
,
NULL
,
cspi_clk
)
_REGISTER_CLOCK
(
"sdhci-esdhc-imx51.0"
,
NULL
,
esdhc1_clk
)
_REGISTER_CLOCK
(
"sdhci-esdhc-imx51.1"
,
NULL
,
esdhc2_clk
)
_REGISTER_CLOCK
(
"sdhci-esdhc-imx51.2"
,
NULL
,
esdhc3_clk
)
_REGISTER_CLOCK
(
"sdhci-esdhc-imx51.3"
,
NULL
,
esdhc4_clk
)
_REGISTER_CLOCK
(
NULL
,
"cpu_clk"
,
cpu_clk
)
_REGISTER_CLOCK
(
NULL
,
"iim_clk"
,
iim_clk
)
_REGISTER_CLOCK
(
"imx2-wdt.0"
,
NULL
,
dummy_clk
)
_REGISTER_CLOCK
(
"imx2-wdt.1"
,
NULL
,
dummy_clk
)
_REGISTER_CLOCK
(
NULL
,
"mipi_hsp"
,
mipi_hsp_clk
)
_REGISTER_CLOCK
(
"imx-ipuv3"
,
NULL
,
ipu_clk
)
_REGISTER_CLOCK
(
"imx-ipuv3"
,
"di0"
,
ipu_di0_clk
)
_REGISTER_CLOCK
(
"imx-ipuv3"
,
"di1"
,
ipu_di1_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpc_dvfs"
,
gpc_dvfs_clk
)
_REGISTER_CLOCK
(
"pata_imx"
,
NULL
,
pata_clk
)
};
static
struct
clk_lookup
mx53_lookups
[]
=
{
/* i.mx53 has the i.mx21 type uart */
_REGISTER_CLOCK
(
"imx21-uart.0"
,
NULL
,
uart1_clk
)
_REGISTER_CLOCK
(
"imx21-uart.1"
,
NULL
,
uart2_clk
)
_REGISTER_CLOCK
(
"imx21-uart.2"
,
NULL
,
uart3_clk
)
_REGISTER_CLOCK
(
"imx21-uart.3"
,
NULL
,
uart4_clk
)
_REGISTER_CLOCK
(
"imx21-uart.4"
,
NULL
,
uart5_clk
)
_REGISTER_CLOCK
(
NULL
,
"gpt"
,
gpt_clk
)
/* i.mx53 has the i.mx25 type fec */
_REGISTER_CLOCK
(
"imx25-fec.0"
,
NULL
,
fec_clk
)
_REGISTER_CLOCK
(
NULL
,
"iim_clk"
,
iim_clk
)
_REGISTER_CLOCK
(
"imx-i2c.0"
,
NULL
,
i2c1_clk
)
_REGISTER_CLOCK
(
"imx-i2c.1"
,
NULL
,
i2c2_clk
)
_REGISTER_CLOCK
(
"imx-i2c.2"
,
NULL
,
i2c3_mx53_clk
)
/* i.mx53 has the i.mx51 type ecspi */
_REGISTER_CLOCK
(
"imx51-ecspi.0"
,
NULL
,
ecspi1_clk
)
_REGISTER_CLOCK
(
"imx51-ecspi.1"
,
NULL
,
ecspi2_clk
)
/* i.mx53 has the i.mx25 type cspi */
_REGISTER_CLOCK
(
"imx35-cspi.0"
,
NULL
,
cspi_clk
)
_REGISTER_CLOCK
(
"sdhci-esdhc-imx53.0"
,
NULL
,
esdhc1_clk
)
_REGISTER_CLOCK
(
"sdhci-esdhc-imx53.1"
,
NULL
,
esdhc2_mx53_clk
)
_REGISTER_CLOCK
(
"sdhci-esdhc-imx53.2"
,
NULL
,
esdhc3_mx53_clk
)
_REGISTER_CLOCK
(
"sdhci-esdhc-imx53.3"
,
NULL
,
esdhc4_mx53_clk
)
_REGISTER_CLOCK
(
"imx2-wdt.0"
,
NULL
,
dummy_clk
)
_REGISTER_CLOCK
(
"imx2-wdt.1"
,
NULL
,
dummy_clk
)
/* i.mx53 has the i.mx35 type sdma */
_REGISTER_CLOCK
(
"imx35-sdma"
,
NULL
,
sdma_clk
)
_REGISTER_CLOCK
(
"imx-ssi.0"
,
NULL
,
ssi1_clk
)
_REGISTER_CLOCK
(
"imx-ssi.1"
,
NULL
,
ssi2_clk
)
_REGISTER_CLOCK
(
"imx-ssi.2"
,
NULL
,
ssi3_clk
)
_REGISTER_CLOCK
(
"imx-keypad"
,
NULL
,
dummy_clk
)
_REGISTER_CLOCK
(
"pata_imx"
,
NULL
,
pata_clk
)
_REGISTER_CLOCK
(
"imx53-ahci.0"
,
"ahci"
,
sata_clk
)
_REGISTER_CLOCK
(
"imx53-ahci.0"
,
"ahci_phy"
,
ahci_phy_clk
)
_REGISTER_CLOCK
(
"imx53-ahci.0"
,
"ahci_dma"
,
ahci_dma_clk
)
};
static
void
clk_tree_init
(
void
)
{
u32
reg
;
ipg_perclk
.
set_parent
(
&
ipg_perclk
,
&
lp_apm_clk
);
/*
* Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
* 8MHz, its derived from lp_apm.
*
* FIXME: Verify if true for all boards
*/
reg
=
__raw_readl
(
MXC_CCM_CBCDR
);
reg
&=
~
MXC_CCM_CBCDR_PERCLK_PRED1_MASK
;
reg
&=
~
MXC_CCM_CBCDR_PERCLK_PRED2_MASK
;
reg
&=
~
MXC_CCM_CBCDR_PERCLK_PODF_MASK
;
reg
|=
(
2
<<
MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET
);
__raw_writel
(
reg
,
MXC_CCM_CBCDR
);
}
int
__init
mx51_clocks_init
(
unsigned
long
ckil
,
unsigned
long
osc
,
unsigned
long
ckih1
,
unsigned
long
ckih2
)
{
int
i
;
external_low_reference
=
ckil
;
external_high_reference
=
ckih1
;
ckih2_reference
=
ckih2
;
oscillator_reference
=
osc
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
mx51_lookups
);
i
++
)
clkdev_add
(
&
mx51_lookups
[
i
]);
clk_tree_init
();
clk_enable
(
&
cpu_clk
);
clk_enable
(
&
main_bus_clk
);
clk_enable
(
&
iim_clk
);
imx_print_silicon_rev
(
"i.MX51"
,
mx51_revision
());
clk_disable
(
&
iim_clk
);
/* move usb_phy_clk to 24MHz */
clk_set_parent
(
&
usb_phy1_clk
,
&
osc_clk
);
/* set the usboh3_clk parent to pll2_sw_clk */
clk_set_parent
(
&
usboh3_clk
,
&
pll2_sw_clk
);
/* Set SDHC parents to be PLL2 */
clk_set_parent
(
&
esdhc1_clk
,
&
pll2_sw_clk
);
clk_set_parent
(
&
esdhc2_clk
,
&
pll2_sw_clk
);
/* set SDHC root clock as 166.25MHZ*/
clk_set_rate
(
&
esdhc1_clk
,
166250000
);
clk_set_rate
(
&
esdhc2_clk
,
166250000
);
/* System timer */
mxc_timer_init
(
&
gpt_clk
,
MX51_IO_ADDRESS
(
MX51_GPT1_BASE_ADDR
),
MX51_INT_GPT
);
return
0
;
}
int
__init
mx53_clocks_init
(
unsigned
long
ckil
,
unsigned
long
osc
,
unsigned
long
ckih1
,
unsigned
long
ckih2
)
{
int
i
;
external_low_reference
=
ckil
;
external_high_reference
=
ckih1
;
ckih2_reference
=
ckih2
;
oscillator_reference
=
osc
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
mx53_lookups
);
i
++
)
clkdev_add
(
&
mx53_lookups
[
i
]);
clk_tree_init
();
clk_set_parent
(
&
uart_root_clk
,
&
pll3_sw_clk
);
clk_enable
(
&
cpu_clk
);
clk_enable
(
&
main_bus_clk
);
clk_enable
(
&
iim_clk
);
imx_print_silicon_rev
(
"i.MX53"
,
mx53_revision
());
clk_disable
(
&
iim_clk
);
/* Set SDHC parents to be PLL2 */
clk_set_parent
(
&
esdhc1_clk
,
&
pll2_sw_clk
);
clk_set_parent
(
&
esdhc3_mx53_clk
,
&
pll2_sw_clk
);
/* set SDHC root clock as 200MHZ*/
clk_set_rate
(
&
esdhc1_clk
,
200000000
);
clk_set_rate
(
&
esdhc3_mx53_clk
,
200000000
);
/* System timer */
mxc_timer_init
(
&
gpt_clk
,
MX53_IO_ADDRESS
(
MX53_GPT1_BASE_ADDR
),
MX53_INT_GPT
);
return
0
;
}
#ifdef CONFIG_OF
static
void
__init
clk_get_freq_dt
(
unsigned
long
*
ckil
,
unsigned
long
*
osc
,
unsigned
long
*
ckih1
,
unsigned
long
*
ckih2
)
{
struct
device_node
*
np
;
/* retrieve the freqency of fixed clocks from device tree */
for_each_compatible_node
(
np
,
NULL
,
"fixed-clock"
)
{
u32
rate
;
if
(
of_property_read_u32
(
np
,
"clock-frequency"
,
&
rate
))
continue
;
if
(
of_device_is_compatible
(
np
,
"fsl,imx-ckil"
))
*
ckil
=
rate
;
else
if
(
of_device_is_compatible
(
np
,
"fsl,imx-osc"
))
*
osc
=
rate
;
else
if
(
of_device_is_compatible
(
np
,
"fsl,imx-ckih1"
))
*
ckih1
=
rate
;
else
if
(
of_device_is_compatible
(
np
,
"fsl,imx-ckih2"
))
*
ckih2
=
rate
;
}
}
int
__init
mx51_clocks_init_dt
(
void
)
{
unsigned
long
ckil
,
osc
,
ckih1
,
ckih2
;
clk_get_freq_dt
(
&
ckil
,
&
osc
,
&
ckih1
,
&
ckih2
);
return
mx51_clocks_init
(
ckil
,
osc
,
ckih1
,
ckih2
);
}
int
__init
mx53_clocks_init_dt
(
void
)
{
unsigned
long
ckil
,
osc
,
ckih1
,
ckih2
;
clk_get_freq_dt
(
&
ckil
,
&
osc
,
&
ckih1
,
&
ckih2
);
return
mx53_clocks_init
(
ckil
,
osc
,
ckih1
,
ckih2
);
}
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录