From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:37711) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SldJo-0002Oa-CP for qemu-devel@nongnu.org; Mon, 02 Jul 2012 05:53:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SldJj-0000vX-5k for qemu-devel@nongnu.org; Mon, 02 Jul 2012 05:53:19 -0400 Received: from mailout4.w1.samsung.com ([210.118.77.14]:9329) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SldJi-0000vL-MM for qemu-devel@nongnu.org; Mon, 02 Jul 2012 05:53:15 -0400 Received: from eusync2.samsung.com (mailout4.w1.samsung.com [210.118.77.14]) by mailout4.w1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0M6J00JDI25QH000@mailout4.w1.samsung.com> for qemu-devel@nongnu.org; Mon, 02 Jul 2012 10:53:50 +0100 (BST) Received: from [106.109.9.187] by eusync2.samsung.com (Oracle Communications Messaging Server 7u4-23.01(7.0.4.23.0) 64bit (built Aug 10 2011)) with ESMTPA id <0M6J00MC624KM930@eusync2.samsung.com> for qemu-devel@nongnu.org; Mon, 02 Jul 2012 10:53:09 +0100 (BST) Date: Mon, 02 Jul 2012 13:53:06 +0400 From: Maksim Kozlov In-reply-to: Message-id: <4FF16F82.2010808@samsung.com> MIME-version: 1.0 Content-type: text/plain; charset=UTF-8; format=flowed Content-transfer-encoding: QUOTED-PRINTABLE References: <1340985860-23147-1-git-send-email-m.kozlov@samsung.com> <1340985860-23147-2-git-send-email-m.kozlov@samsung.com> Subject: Re: [Qemu-devel] [PATCH 1/2] ARM: exynos4210: CMU support List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Blue Swirl Cc: peter.maydell@linaro.org, kyungmin.park@samsung.com, qemu-devel@nongnu.org Ok. Thanks for your remarks. 30.06.2012 00:26, Blue Swirl =D0=BF=D0=B8=D1=88=D0=B5=D1=82: > On Fri, Jun 29, 2012 at 4:04 PM, Maksim Kozlov wrote: >> Add exynos4210 Clock Management Units emulation >> >> Signed-off-by: Maksim Kozlov >> --- >> hw/arm/Makefile.objs | 1 + >> hw/exynos4210.c | 16 + >> hw/exynos4210.h | 42 ++ >> hw/exynos4210_cmu.c | 1462 ++++++++++++++++++++++++++++++++++++= ++++++++++++++ >> 4 files changed, 1521 insertions(+), 0 deletions(-) >> create mode 100644 hw/exynos4210_cmu.c >> >> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs >> index 88ff47d..20d19f2 100644 >> --- a/hw/arm/Makefile.objs >> +++ b/hw/arm/Makefile.objs >> @@ -11,6 +11,7 @@ obj-y +=3D realview_gic.o realview.o arm_sysctl.= o arm11mpcore.o a9mpcore.o >> obj-y +=3D exynos4210_gic.o exynos4210_combiner.o exynos4210.o >> obj-y +=3D exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o >> obj-y +=3D exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o >> +obj-y +=3D exynos4210_cmu.o >> obj-y +=3D arm_l2x0.o >> obj-y +=3D arm_mptimer.o a15mpcore.o >> obj-y +=3D armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_= enet.o >> diff --git a/hw/exynos4210.c b/hw/exynos4210.c >> index 9c20b3f..55b8e24 100644 >> --- a/hw/exynos4210.c >> +++ b/hw/exynos4210.c >> @@ -30,6 +30,13 @@ >> >> #define EXYNOS4210_CHIPID_ADDR 0x10000000 >> >> +/* CMUs */ >> +#define EXYNOS4210_CMU_LEFTBUS_BASE_ADDR 0x10034000 >> +#define EXYNOS4210_CMU_RIGHTBUS_BASE_ADDR 0x10038000 >> +#define EXYNOS4210_CMU_TOP_BASE_ADDR 0x1003C000 >> +#define EXYNOS4210_CMU_DMC_BASE_ADDR 0x10040000 >> +#define EXYNOS4210_CMU_CPU_BASE_ADDR 0x10044000 >> + >> /* PWM */ >> #define EXYNOS4210_PWM_BASE_ADDR 0x139D0000 >> >> @@ -250,6 +257,15 @@ Exynos4210State *exynos4210_init(MemoryRegion= *system_mem, >> */ >> sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_AD= DR, NULL); >> >> + /* CMUs */ >> + exynos4210_cmu_create(EXYNOS4210_CMU_LEFTBUS_BASE_ADDR, >> + EXYNOS4210= _CMU_LEFTBUS); >> + exynos4210_cmu_create(EXYNOS4210_CMU_RIGHTBUS_BASE_ADDR, >> + EXYNOS4210_= CMU_RIGHTBUS); >> + exynos4210_cmu_create(EXYNOS4210_CMU_TOP_BASE_ADDR, EXYNOS421= 0_CMU_TOP); >> + exynos4210_cmu_create(EXYNOS4210_CMU_DMC_BASE_ADDR, EXYNOS421= 0_CMU_DMC); >> + exynos4210_cmu_create(EXYNOS4210_CMU_CPU_BASE_ADDR, EXYNOS421= 0_CMU_CPU); >> + >> /* PWM */ >> sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_A= DDR, >> s->irq_table[exynos4210_get_irq(22, 0)]= , >> diff --git a/hw/exynos4210.h b/hw/exynos4210.h >> index 9b1ae4c..fbdff7a 100644 >> --- a/hw/exynos4210.h >> +++ b/hw/exynos4210.h >> @@ -123,6 +123,48 @@ void exynos4210_combiner_get_gpioin(Exynos421= 0Irq *irqs, DeviceState *dev, >> int ext); >> >> /* >> + * Interface for exynos4210 Clock Management Units (CMUs) >> + */ >> +typedef enum { >> + UNSPECIFIED_CMU =3D -1, >> + EXYNOS4210_CMU_LEFTBUS, >> + EXYNOS4210_CMU_RIGHTBUS, >> + EXYNOS4210_CMU_TOP, >> + EXYNOS4210_CMU_DMC, >> + EXYNOS4210_CMU_CPU, >> + EXYNOS4210_CMU_NUMBER >> +} Exynos4210Cmu; >> + >> +typedef enum { >> + UNSPECIFIED_CLOCK, >> + EXYNOS4210_XXTI, >> + EXYNOS4210_XUSBXTI, >> + EXYNOS4210_APLL, >> + EXYNOS4210_MPLL, >> + EXYNOS4210_SCLK_HDMI24M, >> + EXYNOS4210_SCLK_USBPHY0, >> + EXYNOS4210_SCLK_USBPHY1, >> + EXYNOS4210_SCLK_HDMIPHY, >> + EXYNOS4210_SCLK_APLL, >> + EXYNOS4210_SCLK_MPLL, >> + EXYNOS4210_ACLK_100, >> + EXYNOS4210_SCLK_UART0, >> + EXYNOS4210_SCLK_UART1, >> + EXYNOS4210_SCLK_UART2, >> + EXYNOS4210_SCLK_UART3, >> + EXYNOS4210_SCLK_UART4, >> + EXYNOS4210_CLOCKS_NUMBER >> +} Exynos4210Clock; >> + >> +typedef void ClockChangeHandler(void *opaque); >> + >> +DeviceState *exynos4210_cmu_create(target_phys_addr_t addr, Exyno= s4210Cmu cmu); >> +uint64_t exynos4210_cmu_get_rate(Exynos4210Clock clock_id); >> +void exynos4210_register_clock_handler(ClockChangeHandler *func, >> + Exynos4210Clock clock_id, >> + void *opaque); >> + >> +/* >> * exynos4210 UART >> */ >> DeviceState *exynos4210_uart_create(target_phys_addr_t addr, >> diff --git a/hw/exynos4210_cmu.c b/hw/exynos4210_cmu.c >> new file mode 100644 >> index 0000000..f3e5a30 >> --- /dev/null >> +++ b/hw/exynos4210_cmu.c >> @@ -0,0 +1,1462 @@ >> +/* >> + * exynos4210 Clock Management Units (CMUs) Emulation >> + * >> + * Copyright (C) 2011 Samsung Electronics Co Ltd. >> + * Maksim Kozlov, >> + * >> + * This program is free software; you can redistribute it and/or= modify it >> + * under the terms of the GNU General Public License as publishe= d 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 usefu= l, but WITHOUT >> + * ANY WARRANTY; without even the implied warranty of MERCHANTAB= ILITY 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 Lic= ense along >> + * with this program; if not, see. >> + * >> + */ >> + >> +#include "sysbus.h" >> + >> +#include "exynos4210.h" >> + >> + >> +#define DEBUG_CMU 0 >> +#define DEBUG_CMU_EXTEND 0 >> + >> +#if DEBUG_CMU || DEBUG_CMU_EXTEND >> + >> + #define PRINT_DEBUG(fmt, args...) \ >> + do { \ >> + fprintf(stderr, " [%s:%d] "fmt, __func__, __LINE__= , ##args); \ >> + } while (0) >> + >> + #define PRINT_DEBUG_SIMPLE(fmt, args...) \ >> + do { \ >> + fprintf(stderr, fmt, ## args); \ >> + } while (0) >> + >> +#if DEBUG_CMU_EXTEND >> + >> + #define PRINT_DEBUG_EXTEND(fmt, args...) \ >> + do { \ >> + fprintf(stderr, " [%s:%d] "fmt, __func__, __LINE__= , ##args); \ >> + } while (0) >> +#else >> + #define PRINT_DEBUG_EXTEND(fmt, args...) \ >> + do {} while (0) >> +#endif /* EXTEND */ >> + >> +#else >> + #define PRINT_DEBUG(fmt, args...) \ >> + do {} while (0) >> + #define PRINT_DEBUG_SIMPLE(fmt, args...) \ >> + do {} while (0) >> + #define PRINT_DEBUG_EXTEND(fmt, args...) \ >> + do {} while (0) >> +#endif >> + >> +#define PRINT_ERROR(fmt, args...) = \ >> + do { = \ >> + fprintf(stderr, " [%s:%d] "fmt, __func__, __LINE__= , ##args); \ >> + } while (0) >> + >> + >> + >> +/* function blocks */ >> +#define LEFTBUS_BLK 0x0 >> +#define RIGHTBUS_BLK 0x0 >> +#define TOP_BLK 0x10 >> +#define TOP0_BLK 0x10 >> +#define TOP1_BLK 0x14 >> +#define DMC_BLK 0x0 >> +#define DMC0_BLK 0x0 >> +#define DMC1_BLK 0x4 >> +#define CPU_BLK 0x0 >> +#define CPU0_BLK 0x0 >> +#define CPU1_BLK 0x4 >> + >> +#define CAM_BLK 0x20 >> +#define TV_BLK 0x24 >> +#define MFC_BLK 0x28 >> +#define G3D_BLK 0x2C >> +#define IMAGE_BLK 0x30 >> +#define LCD0_BLK 0x34 >> +#define LCD1_BLK 0x38 >> +#define MAUDIO_BLK 0x3C >> +#define FSYS_BLK 0x40 >> +#define FSYS0_BLK 0x40 >> +#define FSYS1_BLK 0x44 >> +#define FSYS2_BLK 0x48 >> +#define FSYS3_BLK 0x4C >> +#define GPS_BLK 0x4C /* CLK_GATE_IP_GPS in CMU_TOP */ >> +#define PERIL_BLK 0x50 >> +#define PERIL0_BLK 0x50 >> +#define PERIL1_BLK 0x54 >> +#define PERIL2_BLK 0x58 >> +#define PERIL3_BLK 0x5C >> +#define PERIL4_BLK 0x60 >> +#define PERIR_BLK 0x60 /* CLK_GATE_IP_PERIR in CMU_TOP */ >> +#define PERIL5_BLK 0x64 >> + >> +#define BLOCK_MASK 0xFF >> + >> +/* PLLs */ >> +/* located in CMU_CPU block */ >> +#define APLL 0x00 >> +#define MPLL 0x08 >> +/* located in CMU_TOP block */ >> +#define EPLL 0x10 >> +#define VPLL 0x20 >> + >> +/* groups of registers */ >> +#define PLL_LOCK 0x000 >> +#define PLL_CON 0x100 >> +#define CLK_SRC 0x200 >> +#define CLK_SRC_MASK 0x300 >> +#define CLK_MUX_STAT 0x400 >> +#define CLK_DIV 0x500 >> +#define CLK_DIV_STAT 0x600 >> +#define CLK_GATE_SCLK 0x800 >> +#define CLK_GATE_IP 0x900 >> + >> +#define GROUP_MASK 0xF00 >> + >> +#define PLL_LOCK_(pll) (PLL_LOCK + pll) >> +#define PLL_CON0_(pll) (PLL_CON + pll) >> +#define PLL_CON1_(pll) (PLL_CON + pll + 4) >> + >> +#define CLK_SRC_(block) (CLK_SRC + block) >> +#define CLK_SRC_MASK_(block) (CLK_SRC_MASK + block) >> +#define CLK_MUX_STAT_(block) (CLK_MUX_STAT + block) >> +#define CLK_DIV_(block) (CLK_DIV + block) >> +#define CLKDIV2_RATIO 0x580 /* described for CMU_TOP on= ly */ >> +#define CLK_DIV_STAT_(block) (CLK_DIV_STAT + block) >> +#define CLKDIV2_STAT 0x680 /* described for CMU_TOP on= ly */ >> +#define CLK_GATE_SCLK_(block) (CLK_GATE_SCLK + block) >> +/* For CMU_LEFTBUS and CMU_RIGHTBUS, CLK_GATE_IP_XXX >> + registers are located at 0x800. */ >> +#define CLK_GATE_IP_LR_BUS 0x800 >> +#define CLK_GATE_IP_(block) (CLK_GATE_IP + block) >> +#define CLK_GATE_BLOCK 0x970 /* described for CMU_TOP on= ly */ >> +#define CLKOUT_CMU 0xA00 >> +#define CLKOUT_CMU_DIV_STAT 0xA04 >> + >> +/* >> + * registers which are located outside of 0xAFF region >> + */ >> +/* CMU_DMC */ >> +#define DCGIDX_MAP0 0x01000 >> +#define DCGIDX_MAP1 0x01004 >> +#define DCGIDX_MAP2 0x01008 >> +#define DCGPERF_MAP0 0x01020 >> +#define DCGPERF_MAP1 0x01024 >> +#define DVCIDX_MAP 0x01040 >> +#define FREQ_CPU 0x01060 >> +#define FREQ_DPM 0x01064 >> +#define DVSEMCLK_EN 0x01080 >> +#define MAXPERF 0x01084 >> +/* CMU_CPU */ >> +#define ARMCLK_STOPCTRL 0x01000 >> +#define ATCLK_STOPCTRL 0x01004 >> +#define PARITYFAIL_STATUS 0x01010 >> +#define PARITYFAIL_CLEAR 0x01014 >> +#define PWR_CTRL 0x01020 >> +#define APLL_CON0_L8 0x01100 >> +#define APLL_CON0_L7 0x01104 >> +#define APLL_CON0_L6 0x01108 >> +#define APLL_CON0_L5 0x0110C >> +#define APLL_CON0_L4 0x01110 >> +#define APLL_CON0_L3 0x01114 >> +#define APLL_CON0_L2 0x01118 >> +#define APLL_CON0_L1 0x0111C >> +#define IEM_CONTROL 0x01120 >> +#define APLL_CON1_L8 0x01200 >> +#define APLL_CON1_L7 0x01204 >> +#define APLL_CON1_L6 0x01208 >> +#define APLL_CON1_L5 0x0120C >> +#define APLL_CON1_L4 0x01210 >> +#define APLL_CON1_L3 0x01214 >> +#define APLL_CON1_L2 0x01218 >> +#define APLL_CON1_L1 0x0121C >> +#define CLKDIV_IEM_L8 0x01300 >> +#define CLKDIV_IEM_L7 0x01304 >> +#define CLKDIV_IEM_L6 0x01308 >> +#define CLKDIV_IEM_L5 0x0130C >> +#define CLKDIV_IEM_L4 0x01310 >> +#define CLKDIV_IEM_L3 0x01314 >> +#define CLKDIV_IEM_L2 0x01318 >> +#define CLKDIV_IEM_L1 0x0131C >> + >> +#define EXTENDED_REGION_MASK 0x1000 >> +#define EXTENDED_REGISTER_MASK 0xFFF >> + >> +typedef struct { >> + const char *name; /* for debugging */ >> + uint32_t offset; >> + uint32_t reset_value; >> +} Exynos4210CmuReg; >> + >> + >> +static Exynos4210CmuReg exynos4210_cmu_leftbus_regs[] =3D { > > All these structures could be const, I think. I hope you are not > attempting to use static state for the actual register contents. > >> + /* CMU_LEFTBUS registers */ >> + { "CLK_SRC_LEFTBUS", CLK_SRC_(LEFTBUS_BLK), = 0x00000000 }, >> + { "CLK_MUX_STAT_LEFTBUS", CLK_MUX_STAT_(LEFTBUS_BLK), = 0x00000001 }, >> + { "CLK_DIV_LEFTBUS", CLK_DIV_(LEFTBUS_BLK), = 0x00000000 }, >> + { "CLK_DIV_STAT_LEFTBUS", CLK_DIV_STAT_(LEFTBUS_BLK), = 0x00000000 }, >> + { "CLK_GATE_IP_LEFTBUS", CLK_GATE_IP_LR_BUS, = 0xFFFFFFFF }, >> + { "CLKOUT_CMU_LEFTBUS", CLKOUT_CMU, = 0x00010000 }, >> + { "CLKOUT_CMU_LEFTBUS_DIV_STAT", CLKOUT_CMU_DIV_STAT, = 0x00000000 }, >> +}; >> + >> +static Exynos4210CmuReg exynos4210_cmu_rightbus_regs[] =3D { >> + /* CMU_RIGHTBUS registers */ >> + { "CLK_SRC_RIGHTBUS", CLK_SRC_(RIGHTBUS_BLK), = 0x00000000 }, >> + { "CLK_MUX_STAT_RIGHTBUS", CLK_MUX_STAT_(RIGHTBUS_BLK)= , 0x00000001 }, >> + { "CLK_DIV_RIGHTBUS", CLK_DIV_(RIGHTBUS_BLK), = 0x00000000 }, >> + { "CLK_DIV_STAT_RIGHTBUS", CLK_DIV_STAT_(RIGHTBUS_BLK)= , 0x00000000 }, >> + { "CLK_GATE_IP_RIGHTBUS", CLK_GATE_IP_LR_BUS, = 0xFFFFFFFF }, >> + { "CLKOUT_CMU_RIGHTBUS", CLKOUT_CMU, = 0x00010000 }, >> + { "CLKOUT_CMU_RIGHTBUS_DIV_STAT", CLKOUT_CMU_DIV_STAT, = 0x00000000 }, >> +}; >> + >> +static Exynos4210CmuReg exynos4210_cmu_top_regs[] =3D { >> + /* CMU_TOP registers */ >> + { "EPLL_LOCK", PLL_LOCK_(EPLL), 0x= 00000FFF }, >> + { "VPLL_LOCK", PLL_LOCK_(VPLL), 0x= 00000FFF }, >> + { "EPLL_CON0", PLL_CON0_(EPLL), 0x= 00300301 }, >> + { "EPLL_CON1", PLL_CON1_(EPLL), 0x= 00000000 }, >> + { "VPLL_CON0", PLL_CON0_(VPLL), 0x= 00240201 }, >> + { "VPLL_CON1", PLL_CON1_(VPLL), 0x= 66010464 }, >> + { "CLK_SRC_TOP0", CLK_SRC_(TOP0_BLK), 0x= 00000000 }, >> + { "CLK_SRC_TOP1", CLK_SRC_(TOP1_BLK), 0x= 00000000 }, >> + { "CLK_SRC_CAM", CLK_SRC_(CAM_BLK), 0x= 11111111 }, >> + { "CLK_SRC_TV", CLK_SRC_(TV_BLK), 0x= 00000000 }, >> + { "CLK_SRC_MFC", CLK_SRC_(MFC_BLK), 0x= 00000000 }, >> + { "CLK_SRC_G3D", CLK_SRC_(G3D_BLK), 0x= 00000000 }, >> + { "CLK_SRC_IMAGE", CLK_SRC_(IMAGE_BLK), 0x= 00000000 }, >> + { "CLK_SRC_LCD0", CLK_SRC_(LCD0_BLK), 0x= 00001111 }, >> + { "CLK_SRC_LCD1", CLK_SRC_(LCD1_BLK), 0x= 00001111 }, >> + { "CLK_SRC_MAUDIO", CLK_SRC_(MAUDIO_BLK), 0x= 00000005 }, >> + { "CLK_SRC_FSYS", CLK_SRC_(FSYS_BLK), 0x= 00011111 }, >> + { "CLK_SRC_PERIL0", CLK_SRC_(PERIL0_BLK), 0x= 00011111 }, >> + { "CLK_SRC_PERIL1", CLK_SRC_(PERIL1_BLK), 0x= 01110055 }, >> + { "CLK_SRC_MASK_TOP", CLK_SRC_MASK_(TOP_BLK), 0x= 00000001 }, >> + { "CLK_SRC_MASK_CAM", CLK_SRC_MASK_(CAM_BLK), 0x= 11111111 }, >> + { "CLK_SRC_MASK_TV", CLK_SRC_MASK_(TV_BLK), 0x= 00000111 }, >> + { "CLK_SRC_MASK_LCD0", CLK_SRC_MASK_(LCD0_BLK), 0x= 00001111 }, >> + { "CLK_SRC_MASK_LCD1", CLK_SRC_MASK_(LCD1_BLK), 0x= 00001111 }, >> + { "CLK_SRC_MASK_MAUDIO", CLK_SRC_MASK_(MAUDIO_BLK), 0x= 00000001 }, >> + { "CLK_SRC_MASK_FSYS", CLK_SRC_MASK_(FSYS_BLK), 0x= 01011111 }, >> + { "CLK_SRC_MASK_PERIL0", CLK_SRC_MASK_(PERIL0_BLK), 0x= 00011111 }, >> + { "CLK_SRC_MASK_PERIL1", CLK_SRC_MASK_(PERIL1_BLK), 0x= 01110111 }, >> + { "CLK_MUX_STAT_TOP", CLK_MUX_STAT_(TOP_BLK), 0x= 11111111 }, >> + { "CLK_MUX_STAT_MFC", CLK_MUX_STAT_(MFC_BLK), 0x= 00000111 }, >> + { "CLK_MUX_STAT_G3D", CLK_MUX_STAT_(G3D_BLK), 0x= 00000111 }, >> + { "CLK_MUX_STAT_IMAGE", CLK_MUX_STAT_(IMAGE_BLK), 0x= 00000111 }, >> + { "CLK_DIV_TOP", CLK_DIV_(TOP_BLK), 0x= 00000000 }, >> + { "CLK_DIV_CAM", CLK_DIV_(CAM_BLK), 0x= 00000000 }, >> + { "CLK_DIV_TV", CLK_DIV_(TV_BLK), 0x= 00000000 }, >> + { "CLK_DIV_MFC", CLK_DIV_(MFC_BLK), 0x= 00000000 }, >> + { "CLK_DIV_G3D", CLK_DIV_(G3D_BLK), 0x= 00000000 }, >> + { "CLK_DIV_IMAGE", CLK_DIV_(IMAGE_BLK), 0x= 00000000 }, >> + { "CLK_DIV_LCD0", CLK_DIV_(LCD0_BLK), 0x= 00700000 }, >> + { "CLK_DIV_LCD1", CLK_DIV_(LCD1_BLK), 0x= 00700000 }, >> + { "CLK_DIV_MAUDIO", CLK_DIV_(MAUDIO_BLK), 0x= 00000000 }, >> + { "CLK_DIV_FSYS0", CLK_DIV_(FSYS0_BLK), 0x= 00B00000 }, >> + { "CLK_DIV_FSYS1", CLK_DIV_(FSYS1_BLK), 0x= 00000000 }, >> + { "CLK_DIV_FSYS2", CLK_DIV_(FSYS2_BLK), 0x= 00000000 }, >> + { "CLK_DIV_FSYS3", CLK_DIV_(FSYS3_BLK), 0x= 00000000 }, >> + { "CLK_DIV_PERIL0", CLK_DIV_(PERIL0_BLK), 0x= 00000000 }, >> + { "CLK_DIV_PERIL1", CLK_DIV_(PERIL1_BLK), 0x= 00000000 }, >> + { "CLK_DIV_PERIL2", CLK_DIV_(PERIL2_BLK), 0x= 00000000 }, >> + { "CLK_DIV_PERIL3", CLK_DIV_(PERIL3_BLK), 0x= 00000000 }, >> + { "CLK_DIV_PERIL4", CLK_DIV_(PERIL4_BLK), 0x= 00000000 }, >> + { "CLK_DIV_PERIL5", CLK_DIV_(PERIL5_BLK), 0x= 00000000 }, >> + { "CLKDIV2_RATIO", CLKDIV2_RATIO, 0x= 11111111 }, >> + { "CLK_DIV_STAT_TOP", CLK_DIV_STAT_(TOP_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_CAM", CLK_DIV_STAT_(CAM_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_TV", CLK_DIV_STAT_(TV_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_MFC", CLK_DIV_STAT_(MFC_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_G3D", CLK_DIV_STAT_(G3D_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_IMAGE", CLK_DIV_STAT_(IMAGE_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_LCD0", CLK_DIV_STAT_(LCD0_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_LCD1", CLK_DIV_STAT_(LCD1_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_MAUDIO", CLK_DIV_STAT_(MAUDIO_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_FSYS0", CLK_DIV_STAT_(FSYS0_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_FSYS1", CLK_DIV_STAT_(FSYS1_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_FSYS2", CLK_DIV_STAT_(FSYS2_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_FSYS3", CLK_DIV_STAT_(FSYS3_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_PERIL0", CLK_DIV_STAT_(PERIL0_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_PERIL1", CLK_DIV_STAT_(PERIL1_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_PERIL2", CLK_DIV_STAT_(PERIL2_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_PERIL3", CLK_DIV_STAT_(PERIL3_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_PERIL4", CLK_DIV_STAT_(PERIL4_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_PERIL5", CLK_DIV_STAT_(PERIL5_BLK), 0x= 00000000 }, >> + { "CLKDIV2_STAT", CLKDIV2_STAT, 0x= 00000000 }, >> + { "CLK_GATE_SCLK_CAM", CLK_GATE_SCLK_(CAM_BLK), 0x= FFFFFFFF }, >> + { "CLK_GATE_IP_CAM", CLK_GATE_IP_(CAM_BLK), 0x= FFFFFFFF }, >> + { "CLK_GATE_IP_TV", CLK_GATE_IP_(TV_BLK), 0x= FFFFFFFF }, >> + { "CLK_GATE_IP_MFC", CLK_GATE_IP_(MFC_BLK), 0x= FFFFFFFF }, >> + { "CLK_GATE_IP_G3D", CLK_GATE_IP_(G3D_BLK), 0x= FFFFFFFF }, >> + { "CLK_GATE_IP_IMAGE", CLK_GATE_IP_(IMAGE_BLK), 0x= FFFFFFFF }, >> + { "CLK_GATE_IP_LCD0", CLK_GATE_IP_(LCD0_BLK), 0x= FFFFFFFF }, >> + { "CLK_GATE_IP_LCD1", CLK_GATE_IP_(LCD1_BLK), 0x= FFFFFFFF }, >> + { "CLK_GATE_IP_FSYS", CLK_GATE_IP_(FSYS_BLK), 0x= FFFFFFFF }, >> + { "CLK_GATE_IP_GPS", CLK_GATE_IP_(GPS_BLK), 0x= FFFFFFFF }, >> + { "CLK_GATE_IP_PERIL", CLK_GATE_IP_(PERIL_BLK), 0x= FFFFFFFF }, >> + { "CLK_GATE_IP_PERIR", CLK_GATE_IP_(PERIR_BLK), 0x= FFFFFFFF }, >> + { "CLK_GATE_BLOCK", CLK_GATE_BLOCK, 0x= FFFFFFFF }, >> + { "CLKOUT_CMU_TOP", CLKOUT_CMU, 0x= 00010000 }, >> + { "CLKOUT_CMU_TOP_DIV_STAT", CLKOUT_CMU_DIV_STAT, 0x= 00000000 }, >> +}; >> + >> +static Exynos4210CmuReg exynos4210_cmu_dmc_regs[] =3D { >> + /* CMU_DMC registers */ >> + { "CLK_SRC_DMC", CLK_SRC_(DMC_BLK), 0x= 00010000 }, >> + { "CLK_SRC_MASK_DMC", CLK_SRC_MASK_(DMC_BLK), 0x= 00010000 }, >> + { "CLK_MUX_STAT_DMC", CLK_MUX_STAT_(DMC_BLK), 0x= 11100110 }, >> + { "CLK_DIV_DMC0", CLK_DIV_(DMC0_BLK), 0x= 00000000 }, >> + { "CLK_DIV_DMC1", CLK_DIV_(DMC1_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_DMC0", CLK_DIV_STAT_(DMC0_BLK), 0x= 00000000 }, >> + { "CLK_DIV_STAT_DMC1", CLK_DIV_STAT_(DMC1_BLK), 0x= 00000000 }, >> + { "CLK_GATE_IP_DMC", CLK_GATE_IP_(DMC_BLK), 0x= FFFFFFFF }, >> + { "CLKOUT_CMU_DMC", CLKOUT_CMU, 0x= 00010000 }, >> + { "CLKOUT_CMU_DMC_DIV_STAT", CLKOUT_CMU_DIV_STAT, 0x= 00000000 }, >> + { "DCGIDX_MAP0", DCGIDX_MAP0, 0x= FFFFFFFF }, >> + { "DCGIDX_MAP1", DCGIDX_MAP1, 0x= FFFFFFFF }, >> + { "DCGIDX_MAP2", DCGIDX_MAP2, 0x= FFFFFFFF }, >> + { "DCGPERF_MAP0", DCGPERF_MAP0, 0x= FFFFFFFF }, >> + { "DCGPERF_MAP1", DCGPERF_MAP1, 0x= FFFFFFFF }, >> + { "DVCIDX_MAP", DVCIDX_MAP, 0x= FFFFFFFF }, >> + { "FREQ_CPU", FREQ_CPU, 0x= 00000000 }, >> + { "FREQ_DPM", FREQ_DPM, 0x= 00000000 }, >> + { "DVSEMCLK_EN", DVSEMCLK_EN, 0x= 00000000 }, >> + { "MAXPERF", MAXPERF, 0x= 00000000 }, >> +}; >> + >> +static Exynos4210CmuReg exynos4210_cmu_cpu_regs[] =3D { >> + /* CMU_CPU registers */ >> + { "APLL_LOCK", PLL_LOCK_(APLL), 0x0= 0000FFF }, >> + { "MPLL_LOCK", PLL_LOCK_(MPLL), 0x0= 0000FFF }, >> + { "APLL_CON0", PLL_CON0_(APLL), 0x0= 0C80601 }, >> + { "APLL_CON1", PLL_CON1_(APLL), 0x0= 000001C }, >> + { "MPLL_CON0", PLL_CON0_(MPLL), 0x0= 0C80601 }, >> + { "MPLL_CON1", PLL_CON1_(MPLL), 0x0= 000001C }, >> + { "CLK_SRC_CPU", CLK_SRC_(CPU_BLK), 0x0= 0000000 }, >> + { "CLK_MUX_STAT_CPU", CLK_MUX_STAT_(CPU_BLK), 0x0= 0110101 }, >> + { "CLK_DIV_CPU0", CLK_DIV_(CPU0_BLK), 0x0= 0000000 }, >> + { "CLK_DIV_CPU1", CLK_DIV_(CPU1_BLK), 0x0= 0000000 }, >> + { "CLK_DIV_STAT_CPU0", CLK_DIV_STAT_(CPU0_BLK), 0x0= 0000000 }, >> + { "CLK_DIV_STAT_CPU1", CLK_DIV_STAT_(CPU1_BLK), 0x0= 0000000 }, >> + { "CLK_GATE_SCLK_CPU", CLK_GATE_SCLK_(CPU_BLK), 0xF= FFFFFFF }, >> + { "CLK_GATE_IP_CPU", CLK_GATE_IP_(CPU_BLK), 0xF= FFFFFFF }, >> + { "CLKOUT_CMU_CPU", CLKOUT_CMU, 0x0= 0010000 }, >> + { "CLKOUT_CMU_CPU_DIV_STAT", CLKOUT_CMU_DIV_STAT, 0x0= 0000000 }, >> + { "ARMCLK_STOPCTRL", ARMCLK_STOPCTRL, 0x0= 0000044 }, >> + { "ATCLK_STOPCTRL", ATCLK_STOPCTRL, 0x0= 0000044 }, >> + { "PARITYFAIL_STATUS", PARITYFAIL_STATUS, 0x0= 0000000 }, >> + { "PARITYFAIL_CLEAR", PARITYFAIL_CLEAR, 0x0= 0000000 }, >> + { "PWR_CTRL", PWR_CTRL, 0x0= 0000033 }, >> + { "APLL_CON0_L8", APLL_CON0_L8, 0x0= 0C80601 }, >> + { "APLL_CON0_L7", APLL_CON0_L7, 0x0= 0C80601 }, >> + { "APLL_CON0_L6", APLL_CON0_L6, 0x0= 0C80601 }, >> + { "APLL_CON0_L5", APLL_CON0_L5, 0x0= 0C80601 }, >> + { "APLL_CON0_L4", APLL_CON0_L4, 0x0= 0C80601 }, >> + { "APLL_CON0_L3", APLL_CON0_L3, 0x0= 0C80601 }, >> + { "APLL_CON0_L2", APLL_CON0_L2, 0x0= 0C80601 }, >> + { "APLL_CON0_L1", APLL_CON0_L1, 0x0= 0C80601 }, >> + { "IEM_CONTROL", IEM_CONTROL, 0x0= 0000000 }, >> + { "APLL_CON1_L8", APLL_CON1_L8, 0x0= 0000000 }, >> + { "APLL_CON1_L7", APLL_CON1_L7, 0x0= 0000000 }, >> + { "APLL_CON1_L6", APLL_CON1_L6, 0x0= 0000000 }, >> + { "APLL_CON1_L5", APLL_CON1_L5, 0x0= 0000000 }, >> + { "APLL_CON1_L4", APLL_CON1_L4, 0x0= 0000000 }, >> + { "APLL_CON1_L3", APLL_CON1_L3, 0x0= 0000000 }, >> + { "APLL_CON1_L2", APLL_CON1_L2, 0x0= 0000000 }, >> + { "APLL_CON1_L1", APLL_CON1_L1, 0x0= 0000000 }, >> + { "CLKDIV_IEM_L8", CLKDIV_IEM_L8, 0x0= 0000000 }, >> + { "CLKDIV_IEM_L7", CLKDIV_IEM_L7, 0x0= 0000000 }, >> + { "CLKDIV_IEM_L6", CLKDIV_IEM_L6, 0x0= 0000000 }, >> + { "CLKDIV_IEM_L5", CLKDIV_IEM_L5, 0x0= 0000000 }, >> + { "CLKDIV_IEM_L4", CLKDIV_IEM_L4, 0x0= 0000000 }, >> + { "CLKDIV_IEM_L3", CLKDIV_IEM_L3, 0x0= 0000000 }, >> + { "CLKDIV_IEM_L2", CLKDIV_IEM_L2, 0x0= 0000000 }, >> + { "CLKDIV_IEM_L1", CLKDIV_IEM_L1, 0x0= 0000000 }, >> +}; >> + >> +#define EXYNOS4210_CMU_REGS_MEM_SIZE 0x4000 >> + >> +/* >> + * for indexing register in the uint32_t array >> + * >> + * 'reg' - register offset (see offsets definitions above) >> + * >> + */ >> +#define I_(reg) (reg / sizeof(uint32_t)) >> + >> +#define XOM_0 1 /* Select XXTI (0) or XUSBXTI (1) base clock sour= ce */ >> + >> +/* >> + * Offsets in CLK_SRC_CPU register >> + * for control MUXMPLL and MUXAPLL >> + * >> + * 0 =3D FINPLL, 1 =3D MOUTM(A)PLLFOUT >> + */ >> +#define MUX_APLL_SEL_SHIFT 0 >> +#define MUX_MPLL_SEL_SHIFT 8 >> +#define MUX_CORE_SEL_SHIFT 16 >> +#define MUX_HPM_SEL_SHIFT 20 >> + >> +#define MUX_APLL_SEL (1<< MUX_APLL_SEL_SHIFT) >> +#define MUX_MPLL_SEL (1<< MUX_MPLL_SEL_SHIFT) >> +#define MUX_CORE_SEL (1<< MUX_CORE_SEL_SHIFT) >> +#define MUX_HPM_SEL (1<< MUX_HPM_SEL_SHIFT) >> + >> +/* Offsets for fields in CLK_MUX_STAT_CPU register */ >> +#define APLL_SEL_SHIFT 0 >> +#define APLL_SEL_MASK 0x00000007 >> +#define MPLL_SEL_SHIFT 8 >> +#define MPLL_SEL_MASK 0x00000700 >> +#define CORE_SEL_SHIFT 16 >> +#define CORE_SEL_MASK 0x00070000 >> +#define HPM_SEL_SHIFT 20 >> +#define HPM_SEL_MASK 0x00700000 >> + >> + >> +/* Offsets for fields in_CON0 register */ >> +#define PLL_ENABLE_SHIFT 31 >> +#define PLL_ENABLE_MASK 0x80000000 /* [31] bit */ >> +#define PLL_LOCKED_MASK 0x20000000 /* [29] bit */ >> +#define PLL_MDIV_SHIFT 16 >> +#define PLL_MDIV_MASK 0x03FF0000 /* [25:16] bits */ >> +#define PLL_PDIV_SHIFT 8 >> +#define PLL_PDIV_MASK 0x00003F00 /* [13:8] bits */ >> +#define PLL_SDIV_SHIFT 0 >> +#define PLL_SDIV_MASK 0x00000007 /* [2:0] bits */ >> + >> +/* >> + * Offset in CLK_DIV_CPU0 register >> + * for DIVAPLL clock divider ratio >> + */ >> +#define APLL_RATIO_SHIFT 24 >> +#define APLL_RATIO_MASK 0x07000000 /* [26:24] bits */ >> + >> +/* >> + * Offset in CLK_DIV_TOP register >> + * for DIVACLK_100 clock divider ratio >> + */ >> +#define ACLK_100_RATIO_SHIFT 4 >> +#define ACLK_100_RATIO_MASK 0x000000f0 /* [7:4] bits */ >> + >> +/* Offset in CLK_SRC_TOP0 register */ >> +#define MUX_ACLK_100_SEL_SHIFT 16 >> + >> +/* >> + * Offsets in CLK_SRC_PERIL0 register >> + * for clock sources of UARTs >> + */ >> +#define UART0_SEL_SHIFT 0 >> +#define UART1_SEL_SHIFT 4 >> +#define UART2_SEL_SHIFT 8 >> +#define UART3_SEL_SHIFT 12 >> +#define UART4_SEL_SHIFT 16 >> +/* >> + * Offsets in CLK_DIV_PERIL0 register >> + * for clock divider of UARTs >> + */ >> +#define UART0_DIV_SHIFT 0 >> +#define UART1_DIV_SHIFT 4 >> +#define UART2_DIV_SHIFT 8 >> +#define UART3_DIV_SHIFT 12 >> +#define UART4_DIV_SHIFT 16 >> + >> +#define SOURCES_NUMBER 9 >> + >> +typedef struct ClockChangeEntry { >> + QTAILQ_ENTRY(ClockChangeEntry) entry; >> + ClockChangeHandler *func; >> + void *opaque; >> +} ClockChangeEntry; >> + >> +#define TYPE_EXYNOS4210_CMU "exynos4210.cmu" >> +#define TYPE_EXYNOS4210_CLOCK "exynos4210.clock" >> + >> +typedef struct { >> + const char *name; >> + int32_t id; >> + uint64_t rate; >> + >> + /* Current source clock */ >> + int32_t src_id; >> + /* >> + * Available sources. Their order must correspond to CLK_SRC_= register >> + */ >> + int32_t src_ids[SOURCES_NUMBER]; >> + >> + uint32_t src_reg; /* Offset of CLK_SRC_<*> register */ >> + uint32_t div_reg; /* Offset of CLK_DIV_<*> register */ >> + >> + /* >> + * Shift for MUX__SEL value which is stored >> + * in appropriate CLK_MUX_STAT_ register >> + */ >> + uint8_t mux_shift; >> + >> + /* >> + * Shift for_RATIO value which is stored >> + * in appropriate CLK_DIV_ register >> + */ >> + uint8_t div_shift; >> + >> + /* Which CMU controls this clock */ >> + int32_t cmu_id; >> + >> + QTAILQ_HEAD(, ClockChangeEntry) clock_change_handler; >> +} Exynos4210ClockState; >> + >> +typedef struct { >> + SysBusDevice busdev; >> + MemoryRegion iomem; >> + >> + /* registers values */ >> + uint32_t reg[EXYNOS4210_CMU_REGS_MEM_SIZE / sizeof(uint32_t)]= ; >> + >> + /* which CMU it is */ >> + Exynos4210Cmu cmu_id; >> + >> + /* registers information for debugging and resetting */ >> + Exynos4210CmuReg *regs; >> + int regs_number; >> + >> + Exynos4210ClockState *clock; >> + int clock_number; /* how many clocks are controlled by given = CMU */ >> +} Exynos4210CmuState; >> + >> + >> +/* Clocks from Clock Pads */ >> +/* >> + * Two following clocks aren't controlled by any CMUs. These str= uctures are >> + * used directly from global space and their fields shouldn't b= e modified. >> + */ >> + >> +/* It should be used only for testing purposes. XOM_0 is 0 */ >> +static Exynos4210ClockState xxti =3D { >> + .name =3D "XXTI", >> + .id =3D EXYNOS4210_XXTI, >> + .rate =3D 24000000, >> + .cmu_id =3D UNSPECIFIED_CMU, >> +}; >> + >> +/* Main source. XOM_0 is 1 */ >> +static Exynos4210ClockState xusbxti =3D { >> + .name =3D "XUSBXTI", >> + .id =3D EXYNOS4210_XUSBXTI, >> + .rate =3D 24000000, >> + .cmu_id =3D UNSPECIFIED_CMU, >> +}; >> + >> +/* PLLs */ >> + >> +static Exynos4210ClockState mpll =3D { >> + .name =3D "MPLL", >> + .id =3D EXYNOS4210_MPLL, >> + .src_id =3D (XOM_0 ? EXYNOS4210_XUSBXTI : EXYNOS4210_XXTI= ), >> + .div_reg =3D PLL_CON0_(MPLL), >> + .cmu_id =3D EXYNOS4210_CMU_CPU, >> +}; >> + >> +static Exynos4210ClockState apll =3D { >> + .name =3D "APLL", >> + .id =3D EXYNOS4210_APLL, >> + .src_id =3D (XOM_0 ? EXYNOS4210_XUSBXTI : EXYNOS4210_XXTI= ), >> + .div_reg =3D PLL_CON0_(APLL), >> + .cmu_id =3D EXYNOS4210_CMU_CPU, >> +}; >> + >> + >> +/**/ >> + >> +static Exynos4210ClockState sclk_hdmi24m =3D { >> + .name =3D "SCLK_HDMI24M", >> + .id =3D EXYNOS4210_SCLK_HDMI24M, >> + .rate =3D 24000000, >> + .cmu_id =3D UNSPECIFIED_CMU, >> +}; >> + >> +static Exynos4210ClockState sclk_usbphy0 =3D { >> + .name =3D "SCLK_USBPHY0", >> + .id =3D EXYNOS4210_SCLK_USBPHY0, >> + .rate =3D 24000000, >> + .cmu_id =3D UNSPECIFIED_CMU, >> +}; >> + >> +static Exynos4210ClockState sclk_usbphy1 =3D { >> + .name =3D "SCLK_USBPHY1", >> + .id =3D EXYNOS4210_SCLK_USBPHY1, >> + .rate =3D 24000000, >> + .cmu_id =3D UNSPECIFIED_CMU, >> +}; >> + >> +static Exynos4210ClockState sclk_hdmiphy =3D { >> + .name =3D "SCLK_HDMIPHY", >> + .id =3D EXYNOS4210_SCLK_HDMIPHY, >> + .rate =3D 24000000, >> + .cmu_id =3D UNSPECIFIED_CMU, >> +}; >> + >> +static Exynos4210ClockState sclk_mpll =3D { >> + .name =3D "SCLK_MPLL", >> + .id =3D EXYNOS4210_SCLK_MPLL, >> + .src_ids =3D {XOM_0 ? EXYNOS4210_XUSBXTI : EXYNOS4210_XXTI= , >> + EXYNOS4210_MPLL}, >> + .src_reg =3D CLK_SRC_(CPU_BLK), >> + .mux_shift =3D MUX_MPLL_SEL_SHIFT, >> + .cmu_id =3D EXYNOS4210_CMU_CPU, >> +}; >> + >> +static Exynos4210ClockState sclk_apll =3D { >> + .name =3D "SCLK_APLL", >> + .id =3D EXYNOS4210_SCLK_APLL, >> + .src_ids =3D {XOM_0 ? EXYNOS4210_XUSBXTI : EXYNOS4210_XXTI= , >> + EXYNOS4210_APLL}, >> + .src_reg =3D CLK_SRC_(CPU_BLK), >> + .div_reg =3D CLK_DIV_(CPU0_BLK), >> + .mux_shift =3D MUX_APLL_SEL_SHIFT, >> + .div_shift =3D APLL_RATIO_SHIFT, >> + .cmu_id =3D EXYNOS4210_CMU_CPU, >> +}; >> + >> +static Exynos4210ClockState aclk_100 =3D { >> + .name =3D "ACLK_100", >> + .id =3D EXYNOS4210_ACLK_100, >> + .src_ids =3D {EXYNOS4210_SCLK_MPLL, EXYNOS4210_SCLK_APLL}, >> + .src_reg =3D CLK_SRC_(TOP0_BLK), >> + .div_reg =3D CLK_DIV_(TOP_BLK), >> + .mux_shift =3D MUX_ACLK_100_SEL_SHIFT, >> + .div_shift =3D ACLK_100_RATIO_SHIFT, >> + .cmu_id =3D EXYNOS4210_CMU_TOP, >> +}; >> + >> +static Exynos4210ClockState sclk_uart0 =3D { >> + .name =3D "SCLK_UART0", >> + .id =3D EXYNOS4210_SCLK_UART0, >> + .src_ids =3D {EXYNOS4210_XXTI, >> + EXYNOS4210_XUSBXTI, >> + EXYNOS4210_SCLK_HDMI24M, >> + EXYNOS4210_SCLK_USBPHY0, >> + EXYNOS4210_SCLK_USBPHY1, >> + EXYNOS4210_SCLK_HDMIPHY, >> + EXYNOS4210_SCLK_MPLL}, >> + .src_reg =3D CLK_SRC_(PERIL0_BLK), >> + .div_reg =3D CLK_DIV_(PERIL0_BLK), >> + .mux_shift =3D UART0_SEL_SHIFT, >> + .div_shift =3D UART0_DIV_SHIFT, >> + .cmu_id =3D EXYNOS4210_CMU_TOP, >> +}; >> + >> +static Exynos4210ClockState sclk_uart1 =3D { >> + .name =3D "SCLK_UART1", >> + .id =3D EXYNOS4210_SCLK_UART1, >> + .src_ids =3D {EXYNOS4210_XXTI, >> + EXYNOS4210_XUSBXTI, >> + EXYNOS4210_SCLK_HDMI24M, >> + EXYNOS4210_SCLK_USBPHY0, >> + EXYNOS4210_SCLK_USBPHY1, >> + EXYNOS4210_SCLK_HDMIPHY, >> + EXYNOS4210_SCLK_MPLL}, >> + .src_reg =3D CLK_SRC_(PERIL0_BLK), >> + .div_reg =3D CLK_DIV_(PERIL0_BLK), >> + .mux_shift =3D UART1_SEL_SHIFT, >> + .div_shift =3D UART1_DIV_SHIFT, >> + .cmu_id =3D EXYNOS4210_CMU_TOP, >> +}; >> + >> +static Exynos4210ClockState sclk_uart2 =3D { >> + .name =3D "SCLK_UART2", >> + .id =3D EXYNOS4210_SCLK_UART2, >> + .src_ids =3D {EXYNOS4210_XXTI, >> + EXYNOS4210_XUSBXTI, >> + EXYNOS4210_SCLK_HDMI24M, >> + EXYNOS4210_SCLK_USBPHY0, >> + EXYNOS4210_SCLK_USBPHY1, >> + EXYNOS4210_SCLK_HDMIPHY, >> + EXYNOS4210_SCLK_MPLL}, >> + .src_reg =3D CLK_SRC_(PERIL0_BLK), >> + .div_reg =3D CLK_DIV_(PERIL0_BLK), >> + .mux_shift =3D UART2_SEL_SHIFT, >> + .div_shift =3D UART2_DIV_SHIFT, >> + .cmu_id =3D EXYNOS4210_CMU_TOP, >> +}; >> + >> +static Exynos4210ClockState sclk_uart3 =3D { >> + .name =3D "SCLK_UART3", >> + .id =3D EXYNOS4210_SCLK_UART3, >> + .src_ids =3D {EXYNOS4210_XXTI, >> + EXYNOS4210_XUSBXTI, >> + EXYNOS4210_SCLK_HDMI24M, >> + EXYNOS4210_SCLK_USBPHY0, >> + EXYNOS4210_SCLK_USBPHY1, >> + EXYNOS4210_SCLK_HDMIPHY, >> + EXYNOS4210_SCLK_MPLL}, >> + .src_reg =3D CLK_SRC_(PERIL0_BLK), >> + .div_reg =3D CLK_DIV_(PERIL0_BLK), >> + .mux_shift =3D UART3_SEL_SHIFT, >> + .div_shift =3D UART3_DIV_SHIFT, >> + .cmu_id =3D EXYNOS4210_CMU_TOP, >> +}; >> + >> +static Exynos4210ClockState sclk_uart4 =3D { >> + .name =3D "SCLK_UART4", >> + .id =3D EXYNOS4210_SCLK_UART4, >> + .src_ids =3D {EXYNOS4210_XXTI, >> + EXYNOS4210_XUSBXTI, >> + EXYNOS4210_SCLK_HDMI24M, >> + EXYNOS4210_SCLK_USBPHY0, >> + EXYNOS4210_SCLK_USBPHY1, >> + EXYNOS4210_SCLK_HDMIPHY, >> + EXYNOS4210_SCLK_MPLL}, >> + .src_reg =3D CLK_SRC_(PERIL0_BLK), >> + .div_reg =3D CLK_DIV_(PERIL0_BLK), >> + .mux_shift =3D UART4_SEL_SHIFT, >> + .div_shift =3D UART4_DIV_SHIFT, >> + .cmu_id =3D EXYNOS4210_CMU_TOP, >> +}; >> + >> +/* >> + * This array must correspond to Exynos4210Clock enumerator >> + * which is defined in exynos4210.h file >> + * >> + */ >> +static Exynos4210ClockState *exynos4210_clock[] =3D { >> + NULL, >> +&xxti, >> +&xusbxti, >> +&apll, >> +&mpll, >> +&sclk_hdmi24m, >> +&sclk_usbphy0, >> +&sclk_usbphy1, >> +&sclk_hdmiphy, >> +&sclk_apll, >> +&sclk_mpll, >> +&aclk_100, >> +&sclk_uart0, >> +&sclk_uart1, >> +&sclk_uart2, >> +&sclk_uart3, >> +&sclk_uart4, >> + NULL, >> +}; >> + >> +/* >> + * This array must correspond to Exynos4210Cmu enumerator >> + * which is defined in exynos4210.h file >> + * >> + */ >> +static char exynos4210_cmu_path[][13] =3D { > > 'const' > >> + "cmu_leftbus", >> + "cmu_rightbus", >> + "cmu_top", >> + "cmu_dmc", >> + "cmu_cpu", >> +}; >> + >> +#if DEBUG_CMU_EXTEND >> +/* The only meaning of life - debugging. This function should be = only used >> + * inside PRINT_DEBUG_EXTEND macros >> + */ >> +static const char *exynos4210_cmu_regname(Exynos4210CmuState *s, >> + target_phys_addr_t off= set) >> +{ >> + int i; >> + >> + for (i =3D 0; i< s->regs_number; i++) { >> + if (offset =3D=3D s->regs[i].offset) { >> + return s->regs[i].name; >> + } >> + } >> + >> + return NULL; >> +} >> +#endif >> + >> + >> +static Exynos4210ClockState *exynos4210_clock_find(Exynos4210Cloc= k clock_id) >> +{ >> + int i; >> + int cmu_id; >> + Object *cmu; >> + Exynos4210CmuState *s; >> + >> + cmu_id =3D exynos4210_clock[clock_id]->cmu_id; >> + >> + if (cmu_id =3D=3D UNSPECIFIED_CMU) { >> + for (i =3D 1; i< EXYNOS4210_CLOCKS_NUMBER; i++) { >> + if (exynos4210_clock[i]->id =3D=3D clock_id) { >> + >> + PRINT_DEBUG("Clock %s [%p] in CMU %d have been fo= und\n", >> + exynos4210_clock[i]->name, >> + exynos4210_clock[i], >> + cmu_id); >> + >> + return exynos4210_clock[i]; >> + } >> + } >> + } >> + >> + cmu =3D object_resolve_path(exynos4210_cmu_path[cmu_id], NULL= ); >> + s =3D OBJECT_CHECK(Exynos4210CmuState, cmu, TYPE_EXYNOS4210_C= MU); >> + >> + for (i =3D 0; i< s->clock_number; i++) { >> + if (s->clock[i].id =3D=3D clock_id) { >> + >> + PRINT_DEBUG("Clock %s [%p] in CMU %d have been found\= n", >> + s->clock[i].name, >> +&s->clock[i], >> + s->clock[i].cmu_id); >> + return&s->clock[i]; >> + } >> + } >> + >> + PRINT_ERROR("Clock %d not found\n", clock_id); >> + >> + return NULL; >> +} >> + >> + >> +void exynos4210_register_clock_handler(ClockChangeHandler *func, >> + Exynos4210Clock clock_id, = void *opaque) >> +{ >> + ClockChangeEntry *cce =3D g_malloc0(sizeof(ClockChangeEntry))= ; >> + Exynos4210ClockState *clock =3D exynos4210_clock_find(clock_i= d); >> + >> + if (clock =3D=3D NULL) { >> + hw_error("We aren't be able to find clock %d\n", clock_id= ); >> + } else if (clock->cmu_id =3D=3D UNSPECIFIED_CMU) { >> + >> + PRINT_DEBUG("Clock %s never are changed. Handler won't be= set.", >> + exynos4210_clock[clock_id]->name); >> + >> + return; >> + } >> + >> + cce->func =3D func; >> + cce->opaque =3D opaque; >> + >> + QTAILQ_INSERT_TAIL(&clock->clock_change_handler, cce, entry); >> + >> + PRINT_DEBUG("For %s have been set handler [%p]\n", clock->nam= e, cce->func); >> + >> + return; >> +} >> + >> +uint64_t exynos4210_cmu_get_rate(Exynos4210Clock clock_id) >> +{ >> + Exynos4210ClockState *clock =3D exynos4210_clock_find(clock_i= d); >> + >> + if (clock =3D=3D NULL) { >> + hw_error("We aren't be able to find clock %d\n", clock_id= ); >> + } >> + >> + return clock->rate; >> +} >> + >> +static void exynos4210_cmu_set_pll(void *opaque, Exynos4210ClockS= tate *pll) >> +{ >> + Exynos4210CmuState *s =3D (Exynos4210CmuState *)opaque; > > Useless cast. > >> + Exynos4210ClockState *source; >> + target_phys_addr_t offset =3D pll->div_reg; >> + ClockChangeEntry *cce; >> + uint32_t pdiv, mdiv, sdiv, enable; >> + >> + source =3D exynos4210_clock_find(pll->src_id); >> + >> + if (source =3D=3D NULL) { >> + hw_error("We haven't find source clock %d (requested for = %s)\n", >> + pll->src_id, pll->name); >> + } >> + >> + /* >> + * FOUT =3D MDIV * FIN / (PDIV * 2^(SDIV-1)) >> + */ >> + >> + enable =3D (s->reg[I_(offset)]& PLL_ENABLE_MASK)>> PLL_ENAB= LE_SHIFT; >> + mdiv =3D (s->reg[I_(offset)]& PLL_MDIV_MASK)>> PLL_MDIV_S= HIFT; >> + pdiv =3D (s->reg[I_(offset)]& PLL_PDIV_MASK)>> PLL_PDIV_S= HIFT; >> + sdiv =3D (s->reg[I_(offset)]& PLL_SDIV_MASK)>> PLL_SDIV_S= HIFT; >> + >> + if (source) { >> + if (enable) { >> + pll->rate =3D mdiv * source->rate / (pdiv * (1<< (sd= iv-1))); >> + } else { >> + pll->rate =3D 0; >> + } >> + } else { >> + hw_error("%s: Source undefined for %s\n", __FUNCTION__, p= ll->name); >> + } >> + >> + QTAILQ_FOREACH(cce,&pll->clock_change_handler, entry) { >> + cce->func(cce->opaque); >> + } >> + >> + PRINT_DEBUG("%s rate: %llu\n", pll->name, pll->rate); >> + >> + s->reg[I_(offset)] |=3D PLL_LOCKED_MASK; >> +} >> + >> + >> +static void exynos4210_cmu_set_rate(void *opaque, Exynos4210Clock= clock_id) >> +{ >> + Exynos4210CmuState *s =3D (Exynos4210CmuState *)opaque; >> + Exynos4210ClockState *clock =3D exynos4210_clock_find(clock_i= d); >> + ClockChangeEntry *cce; >> + >> + if (clock =3D=3D NULL) { >> + hw_error("We haven't find source clock %d ", clock_id); >> + } >> + >> + if ((clock->id =3D=3D EXYNOS4210_MPLL) || (clock->id =3D=3D E= XYNOS4210_APLL)) { >> + >> + exynos4210_cmu_set_pll(s, clock); >> + >> + } else if ((clock->cmu_id !=3D UNSPECIFIED_CMU)) { >> + >> + Exynos4210ClockState *source; >> + >> + uint32_t src_index =3D I_(clock->src_reg); >> + uint32_t div_index =3D I_(clock->div_reg); >> + >> + clock->src_id =3D clock->src_ids[(s->reg[src_index]>> >> + clock->mux_= shift)& 0xf]; >> + >> + source =3D exynos4210_clock_find(clock->src_id); >> + if (source =3D=3D NULL) { >> + hw_error("We haven't find source clock %d (requested = for %s)\n", >> + clock->src_id, clock->name); >> + } >> + >> + clock->rate =3D muldiv64(source->rate, 1, >> + ((((clock->div_reg ? s->reg[div_= index] : 0)>> >> + clock->div_shift)= & 0xf) + 1)); >> + >> + QTAILQ_FOREACH(cce,&clock->clock_change_handler, entry) { >> + cce->func(cce->opaque); >> + } >> + >> + PRINT_DEBUG_EXTEND("SRC:<0x%05x> %s, SHIFT: %d\n", >> + clock->src_reg, >> + exynos4210_cmu_regname(s, clock->src_r= eg), >> + clock->mux_shift); >> + >> + PRINT_DEBUG("%s [%s:%llu]: %llu\n", >> + clock->name, >> + source->name, >> + (long long unsigned int)source->rate, >> + (long long unsigned int)clock->rate); >> + } >> +} >> + >> + >> +static uint64_t exynos4210_cmu_read(void *opaque, target_phys_add= r_t offset, >> + unsigned size) >> +{ >> + Exynos4210CmuState *s =3D (Exynos4210CmuState *)opaque; >> + >> + if (offset> (EXYNOS4210_CMU_REGS_MEM_SIZE - sizeof(uint32_t)= )) { >> + PRINT_ERROR("Bad offset: 0x%x\n", (int)offset); >> + return 0; >> + } >> + >> + if (offset& EXTENDED_REGION_MASK) { >> + if (s->cmu_id =3D=3D EXYNOS4210_CMU_DMC) { >> + switch (offset& 0xFFF) { >> + case DCGIDX_MAP0: >> + case DCGIDX_MAP1: >> + case DCGIDX_MAP2: >> + case DCGPERF_MAP0: >> + case DCGPERF_MAP1: >> + case DVCIDX_MAP: >> + case FREQ_CPU: >> + case FREQ_DPM: >> + case DVSEMCLK_EN: >> + case MAXPERF: >> + return s->reg[I_(offset)]; >> + default: >> + PRINT_ERROR("Bad offset: 0x%x\n", (int)offset); >> + return 0; >> + } >> + } >> + >> + if (s->cmu_id =3D=3D EXYNOS4210_CMU_CPU) { >> + switch (offset& 0xFFF) { >> + case ARMCLK_STOPCTRL: >> + case ATCLK_STOPCTRL: >> + case PARITYFAIL_STATUS: >> + case PARITYFAIL_CLEAR: >> + case PWR_CTRL: >> + case APLL_CON0_L8: >> + case APLL_CON0_L7: >> + case APLL_CON0_L6: >> + case APLL_CON0_L5: >> + case APLL_CON0_L4: >> + case APLL_CON0_L3: >> + case APLL_CON0_L2: >> + case APLL_CON0_L1: >> + case IEM_CONTROL: >> + case APLL_CON1_L8: >> + case APLL_CON1_L7: >> + case APLL_CON1_L6: >> + case APLL_CON1_L5: >> + case APLL_CON1_L4: >> + case APLL_CON1_L3: >> + case APLL_CON1_L2: >> + case APLL_CON1_L1: >> + case CLKDIV_IEM_L8: >> + case CLKDIV_IEM_L7: >> + case CLKDIV_IEM_L6: >> + case CLKDIV_IEM_L5: >> + case CLKDIV_IEM_L4: >> + case CLKDIV_IEM_L3: >> + case CLKDIV_IEM_L2: >> + case CLKDIV_IEM_L1: >> + return s->reg[I_(offset)]; >> + default: >> + PRINT_ERROR("Bad offset: 0x%x\n", (int)offset); >> + return 0; >> + } >> + } >> + } >> + >> + switch (offset& GROUP_MASK) { >> + case PLL_LOCK: >> + case PLL_CON: >> + case CLK_SRC: >> + case CLK_SRC_MASK: >> + case CLK_MUX_STAT: >> + case CLK_DIV: >> + case CLK_DIV_STAT: >> + case 0x700: /* Reserved */ >> + case CLK_GATE_SCLK: /* reserved? */ >> + case CLK_GATE_IP: >> + case CLKOUT_CMU: >> + return s->reg[I_(offset)]; >> + default: >> + PRINT_ERROR("Bad offset: 0x%x\n", (int)offset); >> + return 0; >> + } >> + >> + PRINT_DEBUG_EXTEND("<0x%05x> %s -> %08x\n", offset, >> + exynos4210_cmu_regname(s, offset), s->reg[= I_(offset)]); >> +} >> + >> + >> +static void exynos4210_cmu_write(void *opaque, target_phys_addr_t= offset, >> + uint64_t val, unsigned size) >> +{ >> + Exynos4210CmuState *s =3D (Exynos4210CmuState *)opaque; >> + uint32_t group, block; >> + >> + group =3D offset& GROUP_MASK; >> + block =3D offset& BLOCK_MASK; >> + >> + switch (group) { >> + case PLL_LOCK: >> + /* it's not necessary at this moment >> + * TODO: do it >> + */ >> + break; >> + case PLL_CON: >> + switch (block) { >> + case APLL: >> + { >> + uint32_t pre_val =3D s->reg[I_(offset)]; >> + s->reg[I_(offset)] =3D val; >> + val =3D (val& ~PLL_LOCKED_MASK) | (pre_val& PLL_LOC= KED_MASK); >> + s->reg[I_(offset)] =3D val; >> + exynos4210_cmu_set_rate(s, EXYNOS4210_APLL); >> + break; >> + } >> + case MPLL: >> + { >> + uint32_t pre_val =3D s->reg[I_(offset)]; >> + s->reg[I_(offset)] =3D val; >> + val =3D (val& ~PLL_LOCKED_MASK) | (pre_val& PLL_LOC= KED_MASK); >> + s->reg[I_(offset)] =3D val; >> + exynos4210_cmu_set_rate(s, EXYNOS4210_MPLL); >> + break; >> + } >> + case CLK_SRC: >> + switch (block) { >> + case CPU_BLK: >> + { >> + uint32_t pre_val =3D s->reg[I_(offset)]; >> + s->reg[I_(offset)] =3D val; >> + >> + if (val& MUX_APLL_SEL) { >> + s->reg[I_(CLK_MUX_STAT_(CPU_BLK))] =3D >> + (s->reg[I_(CLK_MUX_STAT_(CPU_BLK))]& ~(AP= LL_SEL_MASK)) | >> + (2<< APLL_SEL_SHIFT); >> + >> + if ((pre_val& MUX_APLL_SEL) !=3D >> + (s->reg[I_(offset)]& MUX_APLL_SEL)) { >> + exynos4210_cmu_set_rate(s, EXYNOS4210_APLL); >> + } >> + >> + } else { >> + s->reg[I_(CLK_MUX_STAT_(CPU_BLK))] =3D >> + (s->reg[I_(CLK_MUX_STAT_(CPU_BLK))]& ~(AP= LL_SEL_MASK)) | >> + (1<< APLL_SEL_SHIFT); >> + >> + if ((pre_val& MUX_APLL_SEL) !=3D >> + (s->reg[I_(offset)]& MUX_APLL_SEL)) { >> + exynos4210_cmu_set_rate(s, XOM_0 ? EXYNOS4210= _XUSBXTI : >> + EXY= NOS4210_XXTI); >> + } >> + } >> + >> + >> + if (val& MUX_MPLL_SEL) { >> + s->reg[I_(CLK_MUX_STAT_(CPU_BLK))] =3D >> + (s->reg[I_(CLK_MUX_STAT_(CPU_BLK))]& ~(MP= LL_SEL_MASK)) | >> + (2<< MPLL_SEL_SHIFT); >> + >> + if ((pre_val& MUX_MPLL_SEL) !=3D >> + (s->reg[I_(offset)]& MUX_MPLL_SEL)) { >> + exynos4210_cmu_set_rate(s, EXYNOS4210_MPLL); >> + } >> + >> + } else { >> + s->reg[I_(CLK_MUX_STAT_(CPU_BLK))] =3D >> + (s->reg[I_(CLK_MUX_STAT_(CPU_BLK))]& ~(MP= LL_SEL_MASK)) | >> + (1<< MPLL_SEL_SHIFT); >> + >> + if ((pre_val& MUX_MPLL_SEL) !=3D >> + (s->reg[I_(offset)]& MUX_MPLL_SEL)) { >> + exynos4210_cmu_set_rate(s, XOM_0 ? EXYNOS4210= _XUSBXTI : >> + EXY= NOS4210_XXTI); >> + } >> + } >> + >> + if (val& MUX_CORE_SEL) { >> + s->reg[I_(CLK_MUX_STAT_(CPU_BLK))] =3D >> + (s->reg[I_(CLK_MUX_STAT_(CPU_BLK))]& ~(CO= RE_SEL_MASK)) | >> + (2<< CORE_SEL_SHIFT); >> + >> + if ((pre_val& MUX_CORE_SEL) !=3D >> + (s->reg[I_(offset)]& MUX_CORE_SEL)) { >> + exynos4210_cmu_set_rate(s, EXYNOS4210_SCLK_MP= LL); >> + } >> + >> + } else { >> + s->reg[I_(CLK_MUX_STAT_(CPU_BLK))] =3D >> + (s->reg[I_(CLK_MUX_STAT_(CPU_BLK))]& ~(CO= RE_SEL_MASK)) | >> + (1<< CORE_SEL_SHIFT); >> + >> + if ((pre_val& MUX_CORE_SEL) !=3D >> + (s->reg[I_(offset)]& MUX_CORE_SEL)) { >> + exynos4210_cmu_set_rate(s, XOM_0 ? EXYNOS4210= _XUSBXTI : >> + EXY= NOS4210_XXTI); >> + } >> + } >> + >> + if (val& MUX_HPM_SEL) { >> + exynos4210_cmu_set_rate(s, EXYNOS4210_SCLK_MPLL); >> + s->reg[I_(CLK_MUX_STAT_(CPU_BLK))] =3D >> + (s->reg[I_(CLK_MUX_STAT_(CPU_BLK))]& ~(HP= M_SEL_MASK)) | >> + (2<< HPM_SEL_SHIFT); >> + >> + if ((pre_val& MUX_HPM_SEL) !=3D >> + (s->reg[I_(offset)]& M= UX_HPM_SEL)) { >> + exynos4210_cmu_set_rate(s, EXYNOS4210_SCLK_MP= LL); >> + } >> + >> + } else { >> + s->reg[I_(CLK_MUX_STAT_(CPU_BLK))] =3D >> + (s->reg[I_(CLK_MUX_STAT_(CPU_BLK))]& ~(H= PM_SEL_MASK)) | >> + (1<< HPM_SEL_SHIFT); >> + >> + if ((pre_val& MUX_HPM_SEL) !=3D >> + (s->reg[I_(offset)]& M= UX_HPM_SEL)) { >> + exynos4210_cmu_set_rate(s, XOM_0 ? EXYNOS4210= _XUSBXTI : >> + EXY= NOS4210_XXTI); >> + } >> + } >> + } >> + break; >> + case TOP0_BLK: >> + s->reg[I_(offset)] =3D val; >> + exynos4210_cmu_set_rate(s, EXYNOS4210_ACLK_100); >> + break; >> + default: >> + PRINT_ERROR("Unknown functional block: 0x%x\n", (int)= block); >> + } >> + break; >> + case CLK_SRC_MASK: >> + break; >> + case CLK_MUX_STAT: >> + break; >> + case CLK_DIV: >> + switch (block) { >> + case TOP_BLK: >> + s->reg[I_(offset)] =3D val; >> + exynos4210_cmu_set_rate(s, EXYNOS4210_ACLK_100); >> + break; >> + case CPU0_BLK: >> + s->reg[I_(offset)] =3D val; >> + exynos4210_cmu_set_rate(s, EXYNOS4210_SCLK_APLL); >> + exynos4210_cmu_set_rate(s, EXYNOS4210_SCLK_MPLL); >> + break; >> + } >> + case CLK_DIV_STAT: /* CLK_DIV_STAT */ >> + case 0x700: /* Reserved */ >> + case CLK_GATE_SCLK: /* reserved? */ >> + case CLK_GATE_IP: >> + case CLKOUT_CMU: >> + break; >> + default: >> + PRINT_ERROR("Bad offset: 0x%x\n", (int)offset); >> + } >> +} >> + >> +static const MemoryRegionOps exynos4210_cmu_ops =3D { >> + .read =3D exynos4210_cmu_read, >> + .write =3D exynos4210_cmu_write, >> + .endianness =3D DEVICE_NATIVE_ENDIAN, >> +}; >> + >> +static void clock_rate_changed(void *opaque) >> +{ >> + Exynos4210ClockState *cs =3D (Exynos4210ClockState *)opaque; >> + Object *cmu =3D object_resolve_path(exynos4210_cmu_path[cs->c= mu_id], NULL); >> + Exynos4210CmuState *s =3D OBJECT_CHECK(Exynos4210CmuState, cm= u, >> + TYPE_EX= YNOS4210_CMU); >> + >> + PRINT_DEBUG("Clock %s was changed\n", cs->name); >> + >> + exynos4210_cmu_set_rate(s, cs->id); >> + >> +} >> + >> +static void exynos4210_cmu_reset(DeviceState *dev) >> +{ >> + Exynos4210CmuState *s =3D OBJECT_CHECK(Exynos4210CmuState, OB= JECT(dev), >> + TYPE_EX= YNOS4210_CMU); >> + int i, j; >> + uint32_t index =3D 0; >> + >> + for (i =3D 0; i< s->regs_number; i++) { >> + index =3D (s->regs[i].offset) / sizeof(uint32_t); >> + s->reg[index] =3D s->regs[i].reset_value; >> + } >> + >> + for (i =3D 0; i< s->clock_number; i++) { >> + >> + for (j =3D 0; j< SOURCES_NUMBER; j++) { >> + >> + if (s->clock[i].src_ids[j] =3D=3D UNSPECIFIED_CLOCK) = { >> + >> + if (j =3D=3D 0) { >> + /* >> + * we have empty '.sources[]' array >> + */ >> + if (s->clock[i].src_id !=3D UNSPECIFIED_CLOCK= ) { >> + >> + s->clock[i].src_ids[j] =3D s->clock[i].sr= c_id; >> + >> + } else { >> + >> + if (s->clock[i].cmu_id !=3D UNSPECIFIED_C= MU) { >> + /* >> + * We haven't any defined sources for= this clock. >> + * Error during definition of appropr= iate clock >> + * structure >> + */ >> + hw_error("exynos4210_cmu_reset:" >> + "There aren't any sources fo= r %s clock!\n", >> + s->clock[i].name); >> + } else { >> + /* >> + * we don't need any sources for this= clock >> + * because it's a root clock >> + */ >> + break; >> + } >> + } >> + } else { >> + break; /* leave because there are no more sou= rces */ >> + } >> + } /* src_ids[j] =3D=3D UNSPECIFIED_CLOCK */ >> + >> + Exynos4210ClockState *source =3D >> + exynos4210_clock_find(s->clock[i= ].src_ids[j]); >> + >> + if (source =3D=3D NULL) { >> + hw_error("We aren't be able to find source clock = %d " >> + "(requested for %s)\n", >> + s->clock[i].src_ids[j], s->clock[i].name= ); >> + } >> + >> + if (source->cmu_id !=3D UNSPECIFIED_CMU) { >> + >> + exynos4210_register_clock_handler(clock_rate_chan= ged, >> + s->clock[i].src_ids[j],&= s->clock[i]); >> + } >> + } /* SOURCES_NUMBER */ >> + >> + exynos4210_cmu_set_rate(s, s->clock[i].id); >> + } >> + >> + PRINT_DEBUG("CMU %d reset completed\n", s->cmu_id); >> +} >> + >> +static const VMStateDescription vmstate_exynos4210_clock =3D { >> + .name =3D TYPE_EXYNOS4210_CLOCK, >> + .version_id =3D 1, >> + .minimum_version_id =3D 1, >> + .minimum_version_id_old =3D 1, >> + .fields =3D (VMStateField[]) { >> + VMSTATE_UINT64(rate, Exynos4210ClockState), >> + VMSTATE_INT32(src_id, Exynos4210ClockState), >> + VMSTATE_INT32_ARRAY(src_ids, Exynos4210ClockState, SOURCE= S_NUMBER), >> + VMSTATE_UINT32(src_reg, Exynos4210ClockState), >> + VMSTATE_UINT32(div_reg, Exynos4210ClockState), >> + VMSTATE_UINT8(mux_shift, Exynos4210ClockState), >> + VMSTATE_UINT8(div_shift, Exynos4210ClockState), >> + VMSTATE_END_OF_LIST() >> + } >> +}; >> + >> +static const VMStateDescription vmstate_exynos4210_cmu =3D { >> + .name =3D TYPE_EXYNOS4210_CMU, >> + .version_id =3D 1, >> + .minimum_version_id =3D 1, >> + .minimum_version_id_old =3D 1, >> + .fields =3D (VMStateField[]) { >> + VMSTATE_UINT32_ARRAY(reg, Exynos4210CmuState, >> + EXYNOS4210_CMU_REGS_MEM_SIZE / size= of(uint32_t)), >> + VMSTATE_STRUCT_VARRAY_INT32(clock, Exynos4210CmuState, >> + clock_number, 0, >> + vmstate_exynos4210_cloc= k, >> + Exynos4210ClockState), >> + VMSTATE_END_OF_LIST() >> + } >> +}; >> + >> +DeviceState *exynos4210_cmu_create(target_phys_addr_t addr, >> + Exynos4= 210Cmu cmu_id) >> +{ >> + DeviceState *dev; >> + SysBusDevice *bus; >> + >> + dev =3D qdev_create(NULL, TYPE_EXYNOS4210_CMU); >> + >> + qdev_prop_set_int32(dev, "cmu_id", cmu_id); >> + >> + bus =3D sysbus_from_qdev(dev); >> + qdev_init_nofail(dev); >> + if (addr !=3D (target_phys_addr_t)-1) { >> + sysbus_mmio_map(bus, 0, addr); >> + } >> + >> + return dev; >> +} >> + >> +static int exynos4210_cmu_init(SysBusDevice *dev) >> +{ >> + Exynos4210CmuState *s =3D FROM_SYSBUS(Exynos4210CmuState, dev= ); >> + int i, n; >> + >> + memory_region_init_io(&s->iomem,&exynos4210_cmu_ops, s, >> + TYPE_EXYNOS4210_CMU, EXYNOS4210_CMU_REG= S_MEM_SIZE); >> + sysbus_init_mmio(dev,&s->iomem); >> + >> + switch (s->cmu_id) { >> + case EXYNOS4210_CMU_LEFTBUS: >> + s->regs =3D exynos4210_cmu_leftbus_regs; >> + s->regs_number =3D ARRAY_SIZE(exynos4210_cmu_leftbus_regs= ); >> + break; >> + case EXYNOS4210_CMU_RIGHTBUS: >> + s->regs =3D exynos4210_cmu_rightbus_regs; >> + s->regs_number =3D ARRAY_SIZE(exynos4210_cmu_rightbus_reg= s); >> + break; >> + case EXYNOS4210_CMU_TOP: >> + s->regs =3D exynos4210_cmu_top_regs; >> + s->regs_number =3D ARRAY_SIZE(exynos4210_cmu_top_regs); >> + break; >> + case EXYNOS4210_CMU_DMC: >> + s->regs =3D exynos4210_cmu_dmc_regs; >> + s->regs_number =3D ARRAY_SIZE(exynos4210_cmu_dmc_regs); >> + break; >> + case EXYNOS4210_CMU_CPU: >> + s->regs =3D exynos4210_cmu_cpu_regs; >> + s->regs_number =3D ARRAY_SIZE(exynos4210_cmu_cpu_regs); >> + break; >> + default: >> + hw_error("Wrong CMU: %d\n", s->cmu_id); >> + } >> + >> + for (i =3D 1, n =3D 0; i< EXYNOS4210_CLOCKS_NUMBER; i++) { >> + if (s->cmu_id =3D=3D exynos4210_clock[i]->cmu_id) { >> + n++; >> + } >> + } >> + >> + s->clock =3D >> + (Exynos4210ClockState *)g_malloc0(n * sizeof(Exynos421= 0ClockState)); >> + >> + for (i =3D 1, s->clock_number =3D 0; i< EXYNOS4210_CLOCKS_NU= MBER; i++) { >> + >> + if (s->cmu_id =3D=3D exynos4210_clock[i]->cmu_id) { >> + >> + memcpy(&s->clock[s->clock_number], exynos4210_clock[i= ], >> + sizeof(Exynos4210ClockState)); >> + >> + QTAILQ_INIT(&s->clock[s->clock_number].clock_change_h= andler); >> + >> + PRINT_DEBUG("Clock %s was added to \"%s\"\n", >> + s->clock[s->clock_number].name, >> + exynos4210_cmu_path[s->cmu_id]); >> + >> + s->clock_number++; >> + } >> + } >> + >> + object_property_add_child(object_get_root(), exynos4210_cmu_p= ath[s->cmu_id], >> + OBJECT(dev), NULL); >> + >> + return 0; >> +} >> + >> +static Property exynos4210_cmu_properties[] =3D { >> + DEFINE_PROP_INT32("cmu_id", Exynos4210CmuState, cmu_id, UNSPE= CIFIED_CMU), >> + DEFINE_PROP_END_OF_LIST(), >> +}; >> + >> +static void exynos4210_cmu_class_init(ObjectClass *klass, void *d= ata) >> +{ >> + DeviceClass *dc =3D DEVICE_CLASS(klass); >> + SysBusDeviceClass *k =3D SYS_BUS_DEVICE_CLASS(klass); >> + >> + k->init =3D exynos4210_cmu_init; >> + dc->reset =3D exynos4210_cmu_reset; >> + dc->props =3D exynos4210_cmu_properties; >> + dc->vmsd =3D&vmstate_exynos4210_cmu; >> +} >> + >> +static const TypeInfo exynos4210_cmu_info =3D { >> + .name =3D TYPE_EXYNOS4210_CMU, >> + .parent =3D TYPE_SYS_BUS_DEVICE, >> + .instance_size =3D sizeof(Exynos4210CmuState), >> + .class_init =3D exynos4210_cmu_class_init, >> +}; >> + >> +static void exynos4210_cmu_register_types(void) >> +{ >> + type_register_static(&exynos4210_cmu_info); >> +} >> + >> +type_init(exynos4210_cmu_register_types) >> -- >> 1.7.5.4 >> >>