Cleanup clock module a bit and replace last users of __cpm_*

SVN-Revision: 19281
lede-17.01
Lars-Peter Clausen 2010-01-22 18:13:02 +00:00
parent 275f0556a8
commit ad8700a22a
6 changed files with 271 additions and 642 deletions

View File

@ -17,282 +17,16 @@
#include <asm/mach-jz4740/regs.h> #include <asm/mach-jz4740/regs.h>
/*************************************************************************** enum jz4740_wait_mode
* CPM
***************************************************************************/
#define __cpm_get_pllm() \
((REG_CPM_CPPCR & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT)
#define __cpm_get_plln() \
((REG_CPM_CPPCR & CPM_CPPCR_PLLN_MASK) >> CPM_CPPCR_PLLN_BIT)
#define __cpm_get_pllod() \
((REG_CPM_CPPCR & CPM_CPPCR_PLLOD_MASK) >> CPM_CPPCR_PLLOD_BIT)
#define __cpm_get_cdiv() \
((REG_CPM_CPCCR & CPM_CPCCR_CDIV_MASK) >> CPM_CPCCR_CDIV_BIT)
#define __cpm_get_hdiv() \
((REG_CPM_CPCCR & CPM_CPCCR_HDIV_MASK) >> CPM_CPCCR_HDIV_BIT)
#define __cpm_get_pdiv() \
((REG_CPM_CPCCR & CPM_CPCCR_PDIV_MASK) >> CPM_CPCCR_PDIV_BIT)
#define __cpm_get_mdiv() \
((REG_CPM_CPCCR & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT)
#define __cpm_get_ldiv() \
((REG_CPM_CPCCR & CPM_CPCCR_LDIV_MASK) >> CPM_CPCCR_LDIV_BIT)
#define __cpm_get_udiv() \
((REG_CPM_CPCCR & CPM_CPCCR_UDIV_MASK) >> CPM_CPCCR_UDIV_BIT)
#define __cpm_get_i2sdiv() \
((REG_CPM_I2SCDR & CPM_I2SCDR_I2SDIV_MASK) >> CPM_I2SCDR_I2SDIV_BIT)
#define __cpm_get_pixdiv() \
((REG_CPM_LPCDR & CPM_LPCDR_PIXDIV_MASK) >> CPM_LPCDR_PIXDIV_BIT)
#define __cpm_get_mscdiv() \
((REG_CPM_MSCCDR & CPM_MSCCDR_MSCDIV_MASK) >> CPM_MSCCDR_MSCDIV_BIT)
#define __cpm_get_uhcdiv() \
((REG_CPM_UHCCDR & CPM_UHCCDR_UHCDIV_MASK) >> CPM_UHCCDR_UHCDIV_BIT)
#define __cpm_get_ssidiv() \
((REG_CPM_SSICCDR & CPM_SSICDR_SSICDIV_MASK) >> CPM_SSICDR_SSIDIV_BIT)
#define __cpm_set_cdiv(v) \
(REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | ((v) << (CPM_CPCCR_CDIV_BIT)))
#define __cpm_set_hdiv(v) \
(REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | ((v) << (CPM_CPCCR_HDIV_BIT)))
#define __cpm_set_pdiv(v) \
(REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | ((v) << (CPM_CPCCR_PDIV_BIT)))
#define __cpm_set_mdiv(v) \
(REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | ((v) << (CPM_CPCCR_MDIV_BIT)))
#define __cpm_set_ldiv(v) \
(REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | ((v) << (CPM_CPCCR_LDIV_BIT)))
#define __cpm_set_udiv(v) \
(REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | ((v) << (CPM_CPCCR_UDIV_BIT)))
#define __cpm_set_i2sdiv(v) \
(REG_CPM_I2SCDR = (REG_CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | ((v) << (CPM_I2SCDR_I2SDIV_BIT)))
#define __cpm_set_pixdiv(v) \
(REG_CPM_LPCDR = (REG_CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | ((v) << (CPM_LPCDR_PIXDIV_BIT)))
#define __cpm_set_mscdiv(v) \
(REG_CPM_MSCCDR = (REG_CPM_MSCCDR & ~CPM_MSCCDR_MSCDIV_MASK) | ((v) << (CPM_MSCCDR_MSCDIV_BIT)))
#define __cpm_set_uhcdiv(v) \
(REG_CPM_UHCCDR = (REG_CPM_UHCCDR & ~CPM_UHCCDR_UHCDIV_MASK) | ((v) << (CPM_UHCCDR_UHCDIV_BIT)))
#define __cpm_ssiclk_select_exclk() \
(REG_CPM_SSICDR &= ~CPM_SSICDR_SCS)
#define __cpm_ssiclk_select_pllout() \
(REG_CPM_SSICDR |= CPM_SSICDR_SCS)
#define __cpm_set_ssidiv(v) \
(REG_CPM_SSICDR = (REG_CPM_SSICDR & ~CPM_SSICDR_SSIDIV_MASK) | ((v) << (CPM_SSICDR_SSIDIV_BIT)))
#define __cpm_select_i2sclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_I2CS)
#define __cpm_select_i2sclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_I2CS)
#define __cpm_enable_cko() (REG_CPM_CPCCR |= CPM_CPCCR_CLKOEN)
#define __cpm_select_usbclk_exclk() (REG_CPM_CPCCR &= ~CPM_CPCCR_UCS)
#define __cpm_select_usbclk_pll() (REG_CPM_CPCCR |= CPM_CPCCR_UCS)
#define __cpm_enable_pll_change() (REG_CPM_CPCCR |= CPM_CPCCR_CE)
#define __cpm_pllout_direct() (REG_CPM_CPCCR |= CPM_CPCCR_PCS)
#define __cpm_pllout_div2() (REG_CPM_CPCCR &= ~CPM_CPCCR_PCS)
#define __cpm_pll_is_on() (REG_CPM_CPPCR & CPM_CPPCR_PLLS)
#define __cpm_pll_bypass() (REG_CPM_CPPCR |= CPM_CPPCR_PLLBP)
#define __cpm_pll_enable() (REG_CPM_CPPCR |= CPM_CPPCR_PLLEN)
#define __cpm_get_cclk_doze_duty() \
((REG_CPM_LCR & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT)
#define __cpm_set_cclk_doze_duty(v) \
(REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_DOZE_DUTY_MASK) | ((v) << (CPM_LCR_DOZE_DUTY_BIT)))
#define __cpm_doze_mode() (REG_CPM_LCR |= CPM_LCR_DOZE_ON)
#define __cpm_idle_mode() \
(REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_IDLE)
#define __cpm_sleep_mode() \
(REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_SLEEP)
#define __cpm_stop_all() (REG_CPM_CLKGR = 0x7fff)
#define __cpm_stop_uart1() (REG_CPM_CLKGR |= CPM_CLKGR_UART1)
#define __cpm_stop_uhc() (REG_CPM_CLKGR |= CPM_CLKGR_UHC)
#define __cpm_stop_ipu() (REG_CPM_CLKGR |= CPM_CLKGR_IPU)
#define __cpm_stop_dmac() (REG_CPM_CLKGR |= CPM_CLKGR_DMAC)
#define __cpm_stop_udc() (REG_CPM_CLKGR |= CPM_CLKGR_UDC)
#define __cpm_stop_lcd() (REG_CPM_CLKGR |= CPM_CLKGR_LCD)
#define __cpm_stop_cim() (REG_CPM_CLKGR |= CPM_CLKGR_CIM)
#define __cpm_stop_sadc() (REG_CPM_CLKGR |= CPM_CLKGR_SADC)
#define __cpm_stop_msc() (REG_CPM_CLKGR |= CPM_CLKGR_MSC)
#define __cpm_stop_aic1() (REG_CPM_CLKGR |= CPM_CLKGR_AIC1)
#define __cpm_stop_aic2() (REG_CPM_CLKGR |= CPM_CLKGR_AIC2)
#define __cpm_stop_ssi() (REG_CPM_CLKGR |= CPM_CLKGR_SSI)
#define __cpm_stop_i2c() (REG_CPM_CLKGR |= CPM_CLKGR_I2C)
#define __cpm_stop_rtc() (REG_CPM_CLKGR |= CPM_CLKGR_RTC)
#define __cpm_stop_tcu() (REG_CPM_CLKGR |= CPM_CLKGR_TCU)
#define __cpm_stop_uart0() (REG_CPM_CLKGR |= CPM_CLKGR_UART0)
#define __cpm_start_all() (REG_CPM_CLKGR = 0x0)
#define __cpm_start_uart1() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART1)
#define __cpm_start_uhc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UHC)
#define __cpm_start_ipu() (REG_CPM_CLKGR &= ~CPM_CLKGR_IPU)
#define __cpm_start_dmac() (REG_CPM_CLKGR &= ~CPM_CLKGR_DMAC)
#define __cpm_start_udc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UDC)
#define __cpm_start_lcd() (REG_CPM_CLKGR &= ~CPM_CLKGR_LCD)
#define __cpm_start_cim() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIM)
#define __cpm_start_sadc() (REG_CPM_CLKGR &= ~CPM_CLKGR_SADC)
#define __cpm_start_msc() (REG_CPM_CLKGR &= ~CPM_CLKGR_MSC)
#define __cpm_start_aic1() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC1)
#define __cpm_start_aic2() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC2)
#define __cpm_start_ssi() (REG_CPM_CLKGR &= ~CPM_CLKGR_SSI)
#define __cpm_start_i2c() (REG_CPM_CLKGR &= ~CPM_CLKGR_I2C)
#define __cpm_start_rtc() (REG_CPM_CLKGR &= ~CPM_CLKGR_RTC)
#define __cpm_start_tcu() (REG_CPM_CLKGR &= ~CPM_CLKGR_TCU)
#define __cpm_start_uart0() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART0)
#define __cpm_get_o1st() \
((REG_CPM_SCR & CPM_SCR_O1ST_MASK) >> CPM_SCR_O1ST_BIT)
#define __cpm_set_o1st(v) \
(REG_CPM_SCR = (REG_CPM_SCR & ~CPM_SCR_O1ST_MASK) | ((v) << (CPM_SCR_O1ST_BIT)))
#define __cpm_suspend_usbphy() (REG_CPM_SCR |= CPM_SCR_USBPHY_SUSPEND)
#define __cpm_enable_osc_in_sleep() (REG_CPM_SCR |= CPM_SCR_OSC_ENABLE)
/*
* JZ4740 clocks structure
*/
typedef struct {
unsigned int cclk; /* CPU clock */
unsigned int hclk; /* System bus clock */
unsigned int pclk; /* Peripheral bus clock */
unsigned int mclk; /* Flash/SRAM/SDRAM clock */
unsigned int lcdclk; /* LCDC module clock */
unsigned int pixclk; /* LCD pixel clock */
unsigned int i2sclk; /* AIC module clock */
unsigned int usbclk; /* USB module clock */
unsigned int mscclk; /* MSC module clock */
unsigned int extalclk; /* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */
unsigned int rtcclk; /* RTC clock for CPM,INTC,RTC,TCU,WDT */
} jz_clocks_t;
extern jz_clocks_t jz_clocks;
/* PLL output frequency */
static __inline__ unsigned int __cpm_get_pllout(void)
{ {
unsigned long m, n, no, pllout; JZ4740_WAIT_MODE_IDLE,
unsigned long cppcr = REG_CPM_CPPCR; JZ4740_WAIT_MODE_SLEEP,
unsigned long od[4] = {1, 2, 2, 4}; };
if ((cppcr & CPM_CPPCR_PLLEN) && !(cppcr & CPM_CPPCR_PLLBP)) {
m = __cpm_get_pllm() + 2;
n = __cpm_get_plln() + 2;
no = od[__cpm_get_pllod()];
pllout = ((JZ_EXTAL) / (n * no)) * m;
} else
pllout = JZ_EXTAL;
return pllout;
}
/* PLL output frequency for MSC/I2S/LCD/USB */
static __inline__ unsigned int __cpm_get_pllout2(void)
{
if (REG_CPM_CPCCR & CPM_CPCCR_PCS)
return __cpm_get_pllout();
else
return __cpm_get_pllout()/2;
}
/* CPU core clock */
static __inline__ unsigned int __cpm_get_cclk(void)
{
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
return __cpm_get_pllout() / div[__cpm_get_cdiv()];
}
/* AHB system bus clock */
static __inline__ unsigned int __cpm_get_hclk(void)
{
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
return __cpm_get_pllout() / div[__cpm_get_hdiv()];
}
/* Memory bus clock */
static __inline__ unsigned int __cpm_get_mclk(void)
{
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
return __cpm_get_pllout() / div[__cpm_get_mdiv()];
}
/* APB peripheral bus clock */
static __inline__ unsigned int __cpm_get_pclk(void)
{
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
return __cpm_get_pllout() / div[__cpm_get_pdiv()];
}
/* LCDC module clock */
static __inline__ unsigned int __cpm_get_lcdclk(void)
{
return __cpm_get_pllout2() / (__cpm_get_ldiv() + 1);
}
/* LCD pixel clock */
static __inline__ unsigned int __cpm_get_pixclk(void)
{
return __cpm_get_pllout2() / (__cpm_get_pixdiv() + 1);
}
/* I2S clock */
static __inline__ unsigned int __cpm_get_i2sclk(void)
{
if (REG_CPM_CPCCR & CPM_CPCCR_I2CS) {
return __cpm_get_pllout2() / (__cpm_get_i2sdiv() + 1);
}
else {
return JZ_EXTAL;
}
}
/* USB clock */
static __inline__ unsigned int __cpm_get_usbclk(void)
{
if (REG_CPM_CPCCR & CPM_CPCCR_UCS) {
return __cpm_get_pllout2() / (__cpm_get_udiv() + 1);
}
else {
return JZ_EXTAL;
}
}
/* MSC clock */
static __inline__ unsigned int __cpm_get_mscclk(void)
{
return __cpm_get_pllout2() / (__cpm_get_mscdiv() + 1);
}
/* EXTAL clock for UART,I2C,SSI,TCU,USB-PHY */
static __inline__ unsigned int __cpm_get_extalclk(void)
{
return JZ_EXTAL;
}
/* RTC clock for CPM,INTC,RTC,TCU,WDT */
static __inline__ unsigned int __cpm_get_rtcclk(void)
{
return JZ_EXTAL_RTC;
}
/*
* Output 24MHz for SD and 16MHz for MMC.
*/
static inline void __cpm_select_msc_clk(int sd)
{
unsigned int pllout2 = __cpm_get_pllout2();
unsigned int div = 0;
if (sd) {
div = pllout2 / 24000000;
}
else {
div = pllout2 / 16000000;
}
REG_CPM_MSCCDR = div - 1;
}
int jz_init_clocks(unsigned long ext_rate); int jz_init_clocks(unsigned long ext_rate);
void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode);
void jz4740_clock_udc_enable_auto_suspend(void);
void jz4740_clock_udc_disable_auto_suspend(void);
#endif /* __ASM_JZ4740_CLOCK_H__ */ #endif /* __ASM_JZ4740_CLOCK_H__ */

View File

@ -52,162 +52,6 @@
#define IPU_BASE 0xB3080000 #define IPU_BASE 0xB3080000
#define ETH_BASE 0xB3100000 #define ETH_BASE 0xB3100000
/*************************************************************************
* CPM (Clock reset and Power control Management)
*************************************************************************/
#define CPM_CPCCR (CPM_BASE+0x00)
#define CPM_CPPCR (CPM_BASE+0x10)
#define CPM_I2SCDR (CPM_BASE+0x60)
#define CPM_LPCDR (CPM_BASE+0x64)
#define CPM_MSCCDR (CPM_BASE+0x68)
#define CPM_UHCCDR (CPM_BASE+0x6C)
#define CPM_SSICDR (CPM_BASE+0x74)
#define CPM_LCR (CPM_BASE+0x04)
#define CPM_CLKGR (CPM_BASE+0x20)
#define CPM_SCR (CPM_BASE+0x24)
#define CPM_HCR (CPM_BASE+0x30)
#define CPM_HWFCR (CPM_BASE+0x34)
#define CPM_HRCR (CPM_BASE+0x38)
#define CPM_HWCR (CPM_BASE+0x3c)
#define CPM_HWSR (CPM_BASE+0x40)
#define CPM_HSPR (CPM_BASE+0x44)
#define CPM_RSR (CPM_BASE+0x08)
#define REG_CPM_CPCCR REG32(CPM_CPCCR)
#define REG_CPM_CPPCR REG32(CPM_CPPCR)
#define REG_CPM_I2SCDR REG32(CPM_I2SCDR)
#define REG_CPM_LPCDR REG32(CPM_LPCDR)
#define REG_CPM_MSCCDR REG32(CPM_MSCCDR)
#define REG_CPM_UHCCDR REG32(CPM_UHCCDR)
#define REG_CPM_SSICDR REG32(CPM_SSICDR)
#define REG_CPM_LCR REG32(CPM_LCR)
#define REG_CPM_CLKGR REG32(CPM_CLKGR)
#define REG_CPM_SCR REG32(CPM_SCR)
#define REG_CPM_HCR REG32(CPM_HCR)
#define REG_CPM_HWFCR REG32(CPM_HWFCR)
#define REG_CPM_HRCR REG32(CPM_HRCR)
#define REG_CPM_HWCR REG32(CPM_HWCR)
#define REG_CPM_HWSR REG32(CPM_HWSR)
#define REG_CPM_HSPR REG32(CPM_HSPR)
#define REG_CPM_RSR REG32(CPM_RSR)
/* Clock Control Register */
#define CPM_CPCCR_I2CS (1 << 31)
#define CPM_CPCCR_CLKOEN (1 << 30)
#define CPM_CPCCR_UCS (1 << 29)
#define CPM_CPCCR_UDIV_BIT 23
#define CPM_CPCCR_UDIV_MASK (0x3f << CPM_CPCCR_UDIV_BIT)
#define CPM_CPCCR_CE (1 << 22)
#define CPM_CPCCR_PCS (1 << 21)
#define CPM_CPCCR_LDIV_BIT 16
#define CPM_CPCCR_LDIV_MASK (0x1f << CPM_CPCCR_LDIV_BIT)
#define CPM_CPCCR_MDIV_BIT 12
#define CPM_CPCCR_MDIV_MASK (0x0f << CPM_CPCCR_MDIV_BIT)
#define CPM_CPCCR_PDIV_BIT 8
#define CPM_CPCCR_PDIV_MASK (0x0f << CPM_CPCCR_PDIV_BIT)
#define CPM_CPCCR_HDIV_BIT 4
#define CPM_CPCCR_HDIV_MASK (0x0f << CPM_CPCCR_HDIV_BIT)
#define CPM_CPCCR_CDIV_BIT 0
#define CPM_CPCCR_CDIV_MASK (0x0f << CPM_CPCCR_CDIV_BIT)
/* I2S Clock Divider Register */
#define CPM_I2SCDR_I2SDIV_BIT 0
#define CPM_I2SCDR_I2SDIV_MASK (0x1ff << CPM_I2SCDR_I2SDIV_BIT)
/* LCD Pixel Clock Divider Register */
#define CPM_LPCDR_PIXDIV_BIT 0
#define CPM_LPCDR_PIXDIV_MASK (0x7ff << CPM_LPCDR_PIXDIV_BIT)
/* MSC Clock Divider Register */
#define CPM_MSCCDR_MSCDIV_BIT 0
#define CPM_MSCCDR_MSCDIV_MASK (0x1f << CPM_MSCCDR_MSCDIV_BIT)
/* UHC Clock Divider Register */
#define CPM_UHCCDR_UHCDIV_BIT 0
#define CPM_UHCCDR_UHCDIV_MASK (0xf << CPM_UHCCDR_UHCDIV_BIT)
/* SSI Clock Divider Register */
#define CPM_SSICDR_SCS (1<<31) /* SSI clock source selection, 0:EXCLK, 1: PLL */
#define CPM_SSICDR_SSIDIV_BIT 0
#define CPM_SSICDR_SSIDIV_MASK (0xf << CPM_SSICDR_SSIDIV_BIT)
/* PLL Control Register */
#define CPM_CPPCR_PLLM_BIT 23
#define CPM_CPPCR_PLLM_MASK (0x1ff << CPM_CPPCR_PLLM_BIT)
#define CPM_CPPCR_PLLN_BIT 18
#define CPM_CPPCR_PLLN_MASK (0x1f << CPM_CPPCR_PLLN_BIT)
#define CPM_CPPCR_PLLOD_BIT 16
#define CPM_CPPCR_PLLOD_MASK (0x03 << CPM_CPPCR_PLLOD_BIT)
#define CPM_CPPCR_PLLS (1 << 10)
#define CPM_CPPCR_PLLBP (1 << 9)
#define CPM_CPPCR_PLLEN (1 << 8)
#define CPM_CPPCR_PLLST_BIT 0
#define CPM_CPPCR_PLLST_MASK (0xff << CPM_CPPCR_PLLST_BIT)
/* Low Power Control Register */
#define CPM_LCR_DOZE_DUTY_BIT 3
#define CPM_LCR_DOZE_DUTY_MASK (0x1f << CPM_LCR_DOZE_DUTY_BIT)
#define CPM_LCR_DOZE_ON (1 << 2)
#define CPM_LCR_LPM_BIT 0
#define CPM_LCR_LPM_MASK (0x3 << CPM_LCR_LPM_BIT)
#define CPM_LCR_LPM_IDLE (0x0 << CPM_LCR_LPM_BIT)
#define CPM_LCR_LPM_SLEEP (0x1 << CPM_LCR_LPM_BIT)
/* Clock Gate Register */
#define CPM_CLKGR_UART1 (1 << 15)
#define CPM_CLKGR_UHC (1 << 14)
#define CPM_CLKGR_IPU (1 << 13)
#define CPM_CLKGR_DMAC (1 << 12)
#define CPM_CLKGR_UDC (1 << 11)
#define CPM_CLKGR_LCD (1 << 10)
#define CPM_CLKGR_CIM (1 << 9)
#define CPM_CLKGR_SADC (1 << 8)
#define CPM_CLKGR_MSC (1 << 7)
#define CPM_CLKGR_AIC1 (1 << 6)
#define CPM_CLKGR_AIC2 (1 << 5)
#define CPM_CLKGR_SSI (1 << 4)
#define CPM_CLKGR_I2C (1 << 3)
#define CPM_CLKGR_RTC (1 << 2)
#define CPM_CLKGR_TCU (1 << 1)
#define CPM_CLKGR_UART0 (1 << 0)
/* Sleep Control Register */
#define CPM_SCR_O1ST_BIT 8
#define CPM_SCR_O1ST_MASK (0xff << CPM_SCR_O1ST_BIT)
#define CPM_SCR_USBPHY_ENABLE (1 << 6)
#define CPM_SCR_OSC_ENABLE (1 << 4)
/* Hibernate Control Register */
#define CPM_HCR_PD (1 << 0)
/* Wakeup Filter Counter Register in Hibernate Mode */
#define CPM_HWFCR_TIME_BIT 0
#define CPM_HWFCR_TIME_MASK (0x3ff << CPM_HWFCR_TIME_BIT)
/* Reset Counter Register in Hibernate Mode */
#define CPM_HRCR_TIME_BIT 0
#define CPM_HRCR_TIME_MASK (0x7f << CPM_HRCR_TIME_BIT)
/* Wakeup Control Register in Hibernate Mode */
#define CPM_HWCR_WLE_LOW (0 << 2)
#define CPM_HWCR_WLE_HIGH (1 << 2)
#define CPM_HWCR_PIN_WAKEUP (1 << 1)
#define CPM_HWCR_RTC_WAKEUP (1 << 0)
/* Wakeup Status Register in Hibernate Mode */
#define CPM_HWSR_WSR_PIN (1 << 1)
#define CPM_HWSR_WSR_RTC (1 << 0)
/* Reset Status Register */
#define CPM_RSR_HR (1 << 2)
#define CPM_RSR_WR (1 << 1)
#define CPM_RSR_PR (1 << 0)
/************************************************************************* /*************************************************************************
* UART * UART
*************************************************************************/ *************************************************************************/

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
* JZ4740 SoC TCU support * JZ4740 SoC clock support
* *
* This program is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by the
@ -22,7 +22,11 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/err.h> #include <linux/err.h>
#include <asm/mach-jz4740/clock.h>
#define JZ_REG_CLOCK_CTRL 0x00 #define JZ_REG_CLOCK_CTRL 0x00
#define JZ_REG_CLOCK_LOW_POWER 0x04
#define JZ_REG_CLOCK_SLEEP_CTRL 0x08
#define JZ_REG_CLOCK_PLL 0x10 #define JZ_REG_CLOCK_PLL 0x10
#define JZ_REG_CLOCK_GATE 0x20 #define JZ_REG_CLOCK_GATE 0x20
#define JZ_REG_CLOCK_I2S 0x60 #define JZ_REG_CLOCK_I2S 0x60
@ -84,16 +88,17 @@
#define JZ_CLOCK_PLL_N_OFFSET 18 #define JZ_CLOCK_PLL_N_OFFSET 18
#define JZ_CLOCK_PLL_OD_OFFSET 16 #define JZ_CLOCK_PLL_OD_OFFSET 16
#define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2)
#define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0)
#define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7)
#define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6)
static void __iomem *jz_clock_base; static void __iomem *jz_clock_base;
static spinlock_t jz_clock_lock; static spinlock_t jz_clock_lock;
static LIST_HEAD(jz_clocks); static LIST_HEAD(jz_clocks);
struct clk { struct clk_ops {
const char *name;
struct clk* parent;
uint32_t gate_bit;
unsigned long (*get_rate)(struct clk* clk); unsigned long (*get_rate)(struct clk* clk);
unsigned long (*round_rate)(struct clk *clk, unsigned long rate); unsigned long (*round_rate)(struct clk *clk, unsigned long rate);
int (*set_rate)(struct clk* clk, unsigned long rate); int (*set_rate)(struct clk* clk, unsigned long rate);
@ -101,6 +106,16 @@ struct clk {
int (*disable)(struct clk* clk); int (*disable)(struct clk* clk);
int (*set_parent)(struct clk* clk, struct clk *parent); int (*set_parent)(struct clk* clk, struct clk *parent);
};
struct clk {
const char *name;
struct clk* parent;
uint32_t gate_bit;
const struct clk_ops *ops;
struct list_head list; struct list_head list;
}; };
@ -220,8 +235,6 @@ static unsigned long jz_clk_pll_half_get_rate(struct clk *clk)
return jz_clk_pll_get_rate(clk->parent) >> 1; return jz_clk_pll_get_rate(clk->parent) >> 1;
} }
static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate) static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate)
@ -276,33 +289,51 @@ static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate)
return 0; return 0;
} }
static struct clk_ops jz_clk_static_ops = {
.get_rate = jz_clk_static_get_rate,
.enable = jz_clk_enable_gating,
.disable = jz_clk_disable_gating,
};
static struct static_clk jz_clk_ext = { static struct static_clk jz_clk_ext = {
.clk = { .clk = {
.name = "ext", .name = "ext",
.get_rate = jz_clk_static_get_rate, .gate_bit = (uint32_t)-1,
.ops = &jz_clk_static_ops,
}, },
}; };
static struct clk_ops jz_clk_pll_ops = {
.get_rate = jz_clk_static_get_rate,
};
static struct clk jz_clk_pll = { static struct clk jz_clk_pll = {
.name = "pll", .name = "pll",
.parent = &jz_clk_ext.clk, .parent = &jz_clk_ext.clk,
.get_rate = jz_clk_pll_get_rate, .ops = &jz_clk_pll_ops,
};
static struct clk_ops jz_clk_pll_half_ops = {
.get_rate = jz_clk_pll_half_get_rate,
}; };
static struct clk jz_clk_pll_half = { static struct clk jz_clk_pll_half = {
.name = "pll half", .name = "pll half",
.parent = &jz_clk_pll, .parent = &jz_clk_pll,
.get_rate = jz_clk_pll_half_get_rate, .ops = &jz_clk_pll_half_ops,
};
static const struct clk_ops jz_clk_main_ops = {
.get_rate = jz_clk_main_get_rate,
.set_rate = jz_clk_main_set_rate,
.round_rate = jz_clk_main_round_rate,
}; };
static struct main_clk jz_clk_cpu = { static struct main_clk jz_clk_cpu = {
.clk = { .clk = {
.name = "cclk", .name = "cclk",
.parent = &jz_clk_pll, .parent = &jz_clk_pll,
.get_rate = jz_clk_main_get_rate, .ops = &jz_clk_main_ops,
.set_rate = jz_clk_main_set_rate,
.round_rate = jz_clk_main_round_rate,
}, },
.div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET, .div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET,
}; };
@ -311,9 +342,7 @@ static struct main_clk jz_clk_memory = {
.clk = { .clk = {
.name = "mclk", .name = "mclk",
.parent = &jz_clk_pll, .parent = &jz_clk_pll,
.get_rate = jz_clk_main_get_rate, .ops = &jz_clk_main_ops,
.set_rate = jz_clk_main_set_rate,
.round_rate = jz_clk_main_round_rate,
}, },
.div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET, .div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET,
}; };
@ -322,9 +351,7 @@ static struct main_clk jz_clk_high_speed_peripheral = {
.clk = { .clk = {
.name = "hclk", .name = "hclk",
.parent = &jz_clk_pll, .parent = &jz_clk_pll,
.get_rate = jz_clk_main_get_rate, .ops = &jz_clk_main_ops,
.set_rate = jz_clk_main_set_rate,
.round_rate = jz_clk_main_round_rate,
}, },
.div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET, .div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET,
}; };
@ -334,17 +361,20 @@ static struct main_clk jz_clk_low_speed_peripheral = {
.clk = { .clk = {
.name = "pclk", .name = "pclk",
.parent = &jz_clk_pll, .parent = &jz_clk_pll,
.get_rate = jz_clk_main_get_rate, .ops = &jz_clk_main_ops,
.set_rate = jz_clk_main_set_rate,
}, },
.div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET, .div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET,
}; };
static const struct clk_ops jz_clk_ko_ops = {
.enable = jz_clk_ko_enable,
.disable = jz_clk_ko_disable,
};
static struct clk jz_clk_ko = { static struct clk jz_clk_ko = {
.name = "cko", .name = "cko",
.parent = &jz_clk_memory.clk, .parent = &jz_clk_memory.clk,
.enable = jz_clk_ko_enable, .ops = &jz_clk_ko_ops,
.disable = jz_clk_ko_disable,
}; };
static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent) static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent)
@ -375,6 +405,22 @@ static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent)
return 0; return 0;
} }
static int jz_clk_udc_disable(struct clk *clk)
{
jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL,
JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
return 0;
}
static int jz_clk_udc_enable(struct clk *clk)
{
jz_clk_reg_set_bits(JZ_REG_CLOCK_SLEEP_CTRL,
JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
return 0;
}
static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent) static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent)
{ {
if (parent == &jz_clk_pll_half) if (parent == &jz_clk_pll_half)
@ -501,14 +547,18 @@ static unsigned long jz_clk_ldclk_get_rate(struct clk *clk)
return jz_clk_pll_half_get_rate(clk->parent) / (div + 1); return jz_clk_pll_half_get_rate(clk->parent) / (div + 1);
} }
static struct clk jz_clk_ld = { static const struct clk_ops jz_clk_ops_ld = {
.name = "lcd",
.parent = &jz_clk_pll_half,
.set_rate = jz_clk_ldclk_set_rate, .set_rate = jz_clk_ldclk_set_rate,
.get_rate = jz_clk_ldclk_get_rate, .get_rate = jz_clk_ldclk_get_rate,
.round_rate = jz_clk_ldclk_round_rate, .round_rate = jz_clk_ldclk_round_rate,
}; };
static struct clk jz_clk_ld = {
.name = "lcd",
.parent = &jz_clk_pll_half,
.ops= &jz_clk_ops_ld,
};
static struct divided_clk jz_clk_lp = { static struct divided_clk jz_clk_lp = {
.clk = { .clk = {
.name = "lcd_pclk", .name = "lcd_pclk",
@ -527,156 +577,165 @@ static struct static_clk jz_clk_cim_pclk = {
.clk = { .clk = {
.name = "cim_pclk", .name = "cim_pclk",
.gate_bit = JZ_CLOCK_GATE_CIM, .gate_bit = JZ_CLOCK_GATE_CIM,
.get_rate = jz_clk_static_get_rate, .ops = &jz_clk_static_ops,
.enable = jz_clk_enable_gating,
.disable = jz_clk_disable_gating,
}, },
}; };
static struct divided_clk jz_clk_i2s = { static const struct clk_ops jz_clk_i2s_ops =
.clk = { {
.name = "i2s", .set_rate = jz_clk_divided_set_rate,
.parent = &jz_clk_ext.clk, .get_rate = jz_clk_divided_get_rate,
.gate_bit = JZ_CLOCK_GATE_AIC, .enable = jz_clk_enable_gating,
.set_rate = jz_clk_divided_set_rate, .disable = jz_clk_disable_gating,
.get_rate = jz_clk_divided_get_rate, .set_parent = jz_clk_i2s_set_parent,
.enable = jz_clk_enable_gating,
.disable = jz_clk_disable_gating,
.set_parent = jz_clk_i2s_set_parent,
},
.reg = JZ_REG_CLOCK_I2S,
.mask = JZ_CLOCK_I2S_DIV_MASK,
}; };
static struct divided_clk jz_clk_mmc = { static const struct clk_ops jz_clk_spi_ops =
.clk = { {
.name = "mmc", .set_rate = jz_clk_divided_set_rate,
.parent = &jz_clk_pll_half, .get_rate = jz_clk_divided_get_rate,
.gate_bit = JZ_CLOCK_GATE_MMC, .enable = jz_clk_enable_gating,
.set_rate = jz_clk_divided_set_rate, .disable = jz_clk_disable_gating,
.get_rate = jz_clk_divided_get_rate, .set_parent = jz_clk_spi_set_parent,
.enable = jz_clk_enable_gating,
.disable = jz_clk_disable_gating,
},
.reg = JZ_REG_CLOCK_MMC,
.mask = JZ_CLOCK_MMC_DIV_MASK,
}; };
static struct divided_clk jz_clk_uhc = { static const struct clk_ops jz_clk_divided_ops =
.clk = { {
.name = "uhc", .set_rate = jz_clk_divided_set_rate,
.parent = &jz_clk_pll_half, .get_rate = jz_clk_divided_get_rate,
.gate_bit = JZ_CLOCK_GATE_UHC, .enable = jz_clk_enable_gating,
.set_rate = jz_clk_divided_set_rate, .disable = jz_clk_disable_gating,
.get_rate = jz_clk_divided_get_rate,
.enable = jz_clk_enable_gating,
.disable = jz_clk_disable_gating,
},
.reg = JZ_REG_CLOCK_UHC,
.mask = JZ_CLOCK_UHC_DIV_MASK,
}; };
static struct clk jz_clk_udc = { static struct divided_clk jz4740_clock_divided_clks[] = {
.name = "udc", {
.parent = &jz_clk_ext.clk, .clk = {
.name = "i2s",
.parent = &jz_clk_ext.clk,
.gate_bit = JZ_CLOCK_GATE_AIC,
.ops = &jz_clk_i2s_ops,
},
.reg = JZ_REG_CLOCK_I2S,
.mask = JZ_CLOCK_I2S_DIV_MASK,
},
{
.clk = {
.name = "spi",
.parent = &jz_clk_ext.clk,
.gate_bit = JZ_CLOCK_GATE_SPI,
.ops = &jz_clk_spi_ops,
},
.reg = JZ_REG_CLOCK_SPI,
.mask = JZ_CLOCK_SPI_DIV_MASK,
},
{
.clk = {
.name = "mmc",
.parent = &jz_clk_pll_half,
.gate_bit = JZ_CLOCK_GATE_MMC,
.ops = &jz_clk_divided_ops,
},
.reg = JZ_REG_CLOCK_MMC,
.mask = JZ_CLOCK_MMC_DIV_MASK,
},
{
.clk = {
.name = "uhc",
.parent = &jz_clk_pll_half,
.gate_bit = JZ_CLOCK_GATE_UHC,
.ops = &jz_clk_divided_ops,
},
.reg = JZ_REG_CLOCK_UHC,
.mask = JZ_CLOCK_UHC_DIV_MASK,
},
};
static const struct clk_ops jz_clk_udc_ops = {
.set_parent = jz_clk_udc_set_parent, .set_parent = jz_clk_udc_set_parent,
.set_rate = jz_clk_udc_set_rate, .set_rate = jz_clk_udc_set_rate,
.get_rate = jz_clk_udc_get_rate, .get_rate = jz_clk_udc_get_rate,
.enable = jz_clk_udc_enable,
.disable = jz_clk_udc_disable,
}; };
static struct divided_clk jz_clk_spi = { static const struct clk_ops jz_clk_simple_ops = {
.clk = { .enable = jz_clk_enable_gating,
.name = "spi", .disable = jz_clk_disable_gating,
};
static struct clk jz4740_clock_simple_clks[] = {
{
.name = "udc",
.parent = &jz_clk_ext.clk, .parent = &jz_clk_ext.clk,
.gate_bit = JZ_CLOCK_GATE_SPI, .ops = &jz_clk_udc_ops,
.set_rate = jz_clk_divided_set_rate, },
.get_rate = jz_clk_divided_get_rate, {
.enable = jz_clk_enable_gating, .name = "uart0",
.disable = jz_clk_disable_gating, .parent = &jz_clk_ext.clk,
.set_parent = jz_clk_spi_set_parent, .gate_bit = JZ_CLOCK_GATE_UART0,
.ops = &jz_clk_simple_ops,
},
{
.name = "uart1",
.parent = &jz_clk_ext.clk,
.gate_bit = JZ_CLOCK_GATE_UART1,
.ops = &jz_clk_simple_ops,
},
{
.name = "dma",
.parent = &jz_clk_high_speed_peripheral.clk,
.gate_bit = JZ_CLOCK_GATE_UART0,
.ops = &jz_clk_simple_ops,
},
{
.name = "ipu",
.parent = &jz_clk_high_speed_peripheral.clk,
.gate_bit = JZ_CLOCK_GATE_IPU,
.ops = &jz_clk_simple_ops,
},
{
.name = "adc",
.parent = &jz_clk_ext.clk,
.gate_bit = JZ_CLOCK_GATE_ADC,
.ops = &jz_clk_simple_ops,
},
{
.name = "i2c",
.parent = &jz_clk_ext.clk,
.gate_bit = JZ_CLOCK_GATE_I2C,
.ops = &jz_clk_simple_ops,
}, },
.reg = JZ_REG_CLOCK_SPI,
.mask = JZ_CLOCK_SPI_DIV_MASK,
};
static struct clk jz_clk_uart0 = {
.name = "uart0",
.parent = &jz_clk_ext.clk,
.gate_bit = JZ_CLOCK_GATE_UART0,
.enable = jz_clk_enable_gating,
.disable = jz_clk_disable_gating,
};
static struct clk jz_clk_uart1 = {
.name = "uart1",
.parent = &jz_clk_ext.clk,
.gate_bit = JZ_CLOCK_GATE_UART1,
.enable = jz_clk_enable_gating,
.disable = jz_clk_disable_gating,
};
static struct clk jz_clk_dma = {
.name = "dma",
.parent = &jz_clk_high_speed_peripheral.clk,
.gate_bit = JZ_CLOCK_GATE_UART0,
.enable = jz_clk_enable_gating,
.disable = jz_clk_disable_gating,
};
static struct clk jz_clk_ipu = {
.name = "ipu",
.parent = &jz_clk_high_speed_peripheral.clk,
.gate_bit = JZ_CLOCK_GATE_IPU,
.enable = jz_clk_enable_gating,
.disable = jz_clk_disable_gating,
};
static struct clk jz_clk_adc = {
.name = "adc",
.parent = &jz_clk_ext.clk,
.gate_bit = JZ_CLOCK_GATE_ADC,
.enable = jz_clk_enable_gating,
.disable = jz_clk_disable_gating,
};
static struct clk jz_clk_i2c = {
.name = "i2c",
.parent = &jz_clk_ext.clk,
.gate_bit = JZ_CLOCK_GATE_I2C,
.enable = jz_clk_enable_gating,
.disable = jz_clk_disable_gating,
}; };
static struct static_clk jz_clk_rtc = { static struct static_clk jz_clk_rtc = {
.clk = { .clk = {
.name = "rtc", .name = "rtc",
.gate_bit = JZ_CLOCK_GATE_RTC, .gate_bit = JZ_CLOCK_GATE_RTC,
.enable = jz_clk_enable_gating, .ops = &jz_clk_static_ops,
.disable = jz_clk_disable_gating,
}, },
.rate = 32768, .rate = 32768,
}; };
int clk_enable(struct clk *clk) int clk_enable(struct clk *clk)
{ {
if (!clk->enable) if (!clk->ops->enable)
return -EINVAL; return -EINVAL;
return clk->enable(clk); return clk->ops->enable(clk);
} }
EXPORT_SYMBOL_GPL(clk_enable); EXPORT_SYMBOL_GPL(clk_enable);
void clk_disable(struct clk *clk) void clk_disable(struct clk *clk)
{ {
if (clk->disable) if (clk->ops->disable)
clk->disable(clk); clk->ops->disable(clk);
} }
EXPORT_SYMBOL_GPL(clk_disable); EXPORT_SYMBOL_GPL(clk_disable);
unsigned long clk_get_rate(struct clk *clk) unsigned long clk_get_rate(struct clk *clk)
{ {
if (clk->get_rate) if (clk->ops->get_rate)
return clk->get_rate(clk); return clk->ops->get_rate(clk);
if (clk->parent) if (clk->parent)
return clk_get_rate(clk->parent); return clk_get_rate(clk->parent);
@ -686,16 +745,16 @@ EXPORT_SYMBOL_GPL(clk_get_rate);
int clk_set_rate(struct clk *clk, unsigned long rate) int clk_set_rate(struct clk *clk, unsigned long rate)
{ {
if (!clk->set_rate) if (!clk->ops->set_rate)
return -EINVAL; return -EINVAL;
return clk->set_rate(clk, rate); return clk->ops->set_rate(clk, rate);
} }
EXPORT_SYMBOL_GPL(clk_set_rate); EXPORT_SYMBOL_GPL(clk_set_rate);
long clk_round_rate(struct clk *clk, unsigned long rate) long clk_round_rate(struct clk *clk, unsigned long rate)
{ {
if (clk->round_rate) if (clk->ops->round_rate)
return clk->round_rate(clk, rate); return clk->ops->round_rate(clk, rate);
return -EINVAL; return -EINVAL;
} }
@ -705,18 +764,17 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
{ {
int ret; int ret;
if (!clk->set_parent) if (!clk->ops->set_parent)
return -EINVAL; return -EINVAL;
clk->disable(clk); clk_disable(clk);
ret = clk->set_parent(clk, parent); ret = clk->ops->set_parent(clk, parent);
clk->enable(clk); clk_enable(clk);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(clk_set_parent); EXPORT_SYMBOL_GPL(clk_set_parent);
struct clk *clk_get(struct device *dev, const char *name) struct clk *clk_get(struct device *dev, const char *name)
{ {
struct clk *clk; struct clk *clk;
@ -741,6 +799,8 @@ inline static void clk_add(struct clk *clk)
static void clk_register_clks(void) static void clk_register_clks(void)
{ {
size_t i;
clk_add(&jz_clk_ext.clk); clk_add(&jz_clk_ext.clk);
clk_add(&jz_clk_pll); clk_add(&jz_clk_pll);
clk_add(&jz_clk_pll_half); clk_add(&jz_clk_pll_half);
@ -752,41 +812,63 @@ static void clk_register_clks(void)
clk_add(&jz_clk_lp.clk); clk_add(&jz_clk_lp.clk);
clk_add(&jz_clk_cim_mclk); clk_add(&jz_clk_cim_mclk);
clk_add(&jz_clk_cim_pclk.clk); clk_add(&jz_clk_cim_pclk.clk);
clk_add(&jz_clk_i2s.clk);
clk_add(&jz_clk_mmc.clk);
clk_add(&jz_clk_uhc.clk);
clk_add(&jz_clk_udc);
clk_add(&jz_clk_uart0);
clk_add(&jz_clk_uart1);
clk_add(&jz_clk_dma);
clk_add(&jz_clk_ipu);
clk_add(&jz_clk_adc);
clk_add(&jz_clk_i2c);
clk_add(&jz_clk_rtc.clk); clk_add(&jz_clk_rtc.clk);
for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i)
clk_add(&jz4740_clock_divided_clks[i].clk);
for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i)
clk_add(&jz4740_clock_simple_clks[i]);
} }
void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
{
switch (mode) {
case JZ4740_WAIT_MODE_IDLE:
jz_clk_reg_clear_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
break;
case JZ4740_WAIT_MODE_SLEEP:
jz_clk_reg_set_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
break;
}
}
void jz4740_clock_udc_disable_auto_suspend(void)
{
jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
}
EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend);
void jz4740_clock_udc_enable_auto_suspend(void)
{
jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
}
EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
int jz_init_clocks(unsigned long ext_rate) int jz_init_clocks(unsigned long ext_rate)
{ {
uint32_t val; uint32_t val;
jz_clock_base = ioremap(0x10000000, 0x100); jz_clock_base = ioremap(CPHYSADDR(CPM_BASE), 0x100);
if (!jz_clock_base) if (!jz_clock_base)
return -EBUSY; return -EBUSY;
spin_lock_init(&jz_clock_lock);
jz_clk_ext.rate = ext_rate; jz_clk_ext.rate = ext_rate;
val = jz_clk_reg_read(JZ_REG_CLOCK_SPI); val = jz_clk_reg_read(JZ_REG_CLOCK_SPI);
if (val & JZ_CLOCK_SPI_SRC_PLL) if (val & JZ_CLOCK_SPI_SRC_PLL)
jz_clk_spi.clk.parent = &jz_clk_pll_half; jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half;
val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL); val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL) if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL)
jz_clk_i2s.clk.parent = &jz_clk_pll_half; jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half;
if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL) if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL)
jz_clk_udc.parent = &jz_clk_pll_half; jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half;
clk_register_clks(); clk_register_clks();

View File

@ -18,45 +18,25 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <asm/mach-jz4740/regs.h> #include <asm/mach-jz4740/regs.h>
#include <asm/mach-jz4740/clock.h>
extern void jz4740_intc_suspend(void); extern void jz4740_intc_suspend(void);
extern void jz4740_intc_resume(void); extern void jz4740_intc_resume(void);
static int jz_pm_enter(suspend_state_t state) static int jz_pm_enter(suspend_state_t state)
{ {
unsigned long nfcsr = REG_EMC_NFCSR;
uint32_t scr = REG_CPM_SCR;
/* Disable nand flash */
REG_EMC_NFCSR = ~0xff;
udelay(100);
/*stop udc and usb*/
REG_CPM_SCR &= ~( 1<<6 | 1<<7);
REG_CPM_SCR |= 0<<6 | 1<<7;
jz4740_intc_suspend(); jz4740_intc_suspend();
/* Enter SLEEP mode */ jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_SLEEP);
REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;
REG_CPM_LCR |= CPM_LCR_LPM_SLEEP;
__asm__(".set\tmips3\n\t" __asm__(".set\tmips3\n\t"
"wait\n\t" "wait\n\t"
".set\tmips0"); ".set\tmips0");
/* Restore to IDLE mode */ jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_IDLE);
REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;
REG_CPM_LCR |= CPM_LCR_LPM_IDLE;
/* Restore nand flash control register */
REG_EMC_NFCSR = nfcsr;
jz4740_intc_resume(); jz4740_intc_resume();
/* Restore sleep control register */
REG_CPM_SCR = scr;
return 0; return 0;
} }

View File

@ -48,16 +48,6 @@ extern void jz_halt(void);
extern void jz_power_off(void); extern void jz_power_off(void);
extern void jz_time_init(void); extern void jz_time_init(void);
static void __init soc_cpm_setup(void)
{
/* Enable CKO to external memory */
__cpm_enable_cko();
/* CPU enters IDLE mode when executing 'wait' instruction */
__cpm_idle_mode();
}
static void __init jz_serial_setup(void) static void __init jz_serial_setup(void)
{ {
#ifdef CONFIG_SERIAL_8250 #ifdef CONFIG_SERIAL_8250
@ -102,7 +92,6 @@ void __init plat_mem_setup(void)
_machine_restart = jz_restart; _machine_restart = jz_restart;
_machine_halt = jz_halt; _machine_halt = jz_halt;
pm_power_off = jz_power_off; pm_power_off = jz_power_off;
soc_cpm_setup();
jz_serial_setup(); jz_serial_setup();
} }

View File

@ -32,6 +32,7 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb/gadget.h> #include <linux/usb/gadget.h>
#include <linux/clk.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/io.h> #include <asm/io.h>
@ -345,11 +346,7 @@ static void udc_disable(struct jz4740_udc *dev)
usb_clearb(dev, JZ_REG_UDC_POWER, USB_POWER_SOFTCONN); usb_clearb(dev, JZ_REG_UDC_POWER, USB_POWER_SOFTCONN);
/* Disable the USB PHY */ /* Disable the USB PHY */
#ifdef CONFIG_SOC_JZ4740 clk_disable(dev->clk);
REG_CPM_SCR &= ~CPM_SCR_USBPHY_ENABLE;
#elif defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D)
REG_CPM_OPCR &= ~CPM_OPCR_UDCPHY_ENABLE;
#endif
dev->ep0state = WAIT_FOR_SETUP; dev->ep0state = WAIT_FOR_SETUP;
dev->gadget.speed = USB_SPEED_UNKNOWN; dev->gadget.speed = USB_SPEED_UNKNOWN;
@ -410,14 +407,10 @@ static void udc_enable(struct jz4740_udc *dev)
* there are no actions on the USB bus. * there are no actions on the USB bus.
* UDC still works during this bit was set. * UDC still works during this bit was set.
*/ */
__cpm_stop_udc(); jz4740_clock_udc_enable_auto_suspend();
/* Enable the USB PHY */ /* Enable the USB PHY */
#ifdef CONFIG_SOC_JZ4740 clk_enable(dev->clk);
REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE;
#elif defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D)
REG_CPM_OPCR |= CPM_OPCR_UDCPHY_ENABLE;
#endif
/* Disable interrupts */ /* Disable interrupts */
/* usb_writew(dev, JZ_REG_UDC_INTRINE, 0); /* usb_writew(dev, JZ_REG_UDC_INTRINE, 0);
@ -2302,9 +2295,16 @@ static int jz4740_udc_probe(struct platform_device *pdev)
dev->gadget.dev.release = gadget_release; dev->gadget.dev.release = gadget_release;
ret = device_register(&dev->gadget.dev); ret = device_register(&dev->gadget.dev);
if (ret) if (ret)
return ret; return ret;
dev->clk = clk_get(&pdev->dev, "udc");
if (IS_ERR(dev->clk)) {
ret = PTR_ERR(dev->clk);
dev_err(&pdev->dev, "Failed to get udc clock: %d\n", ret);
goto err_device_unregister;
}
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
dev->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); dev->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -2312,7 +2312,7 @@ static int jz4740_udc_probe(struct platform_device *pdev)
if (!dev->mem) { if (!dev->mem) {
ret = -ENOENT; ret = -ENOENT;
dev_err(&pdev->dev, "Failed to get mmio memory resource\n"); dev_err(&pdev->dev, "Failed to get mmio memory resource\n");
goto err_device_unregister; goto err_clk_put;
} }
dev->mem = request_mem_region(dev->mem->start, resource_size(dev->mem), pdev->name); dev->mem = request_mem_region(dev->mem->start, resource_size(dev->mem), pdev->name);
@ -2349,6 +2349,8 @@ err_iounmap:
iounmap(dev->base); iounmap(dev->base);
err_release_mem_region: err_release_mem_region:
release_mem_region(dev->mem->start, resource_size(dev->mem)); release_mem_region(dev->mem->start, resource_size(dev->mem));
err_clk_put:
clk_put(dev->clk);
err_device_unregister: err_device_unregister:
device_unregister(&dev->gadget.dev); device_unregister(&dev->gadget.dev);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
@ -2366,13 +2368,11 @@ static int jz4740_udc_remove(struct platform_device *pdev)
return -EBUSY; return -EBUSY;
udc_disable(dev); udc_disable(dev);
#ifdef UDC_PROC_FILE
remove_proc_entry(proc_node_name, NULL);
#endif
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
iounmap(dev->base); iounmap(dev->base);
release_mem_region(dev->mem->start, resource_size(dev->mem)); release_mem_region(dev->mem->start, resource_size(dev->mem));
clk_put(dev->clk);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
device_unregister(&dev->gadget.dev); device_unregister(&dev->gadget.dev);