Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
c818f97b
Commit
c818f97b
authored
May 09, 2012
by
Sascha Hauer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ARM i.MX: remove now unused clock files
Signed-off-by:
Sascha Hauer
<
s.hauer@pengutronix.de
>
parent
2acd1b6f
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
0 additions
and
7958 deletions
+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
No files found.
arch/arm/mach-imx/clock-imx1.c
deleted
100644 → 0
View file @
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
deleted
100644 → 0
View file @
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
deleted
100644 → 0
View file @
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
deleted
100644 → 0
View file @
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
deleted
100644 → 0
View file @
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
deleted
100644 → 0
View file @
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
deleted
100644 → 0
View file @
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
deleted
100644 → 0
View file @
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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment