Re: [PATCH v9] i2c: exynos5: add High Speed I2C controller driver
On 17 May 2013 15:40, Naveen Krishna Chatradhi ch.nav...@samsung.com wrote: Adds support for High Speed I2C driver found in Exynos5 and later SoCs from Samsung. Driver only supports Device Tree method. Changes since v1: 1. Added FIFO functionality 2. Added High speed mode functionality 3. Remove SMBUS_QUICK 4. Remove the debugfs functionality 5. Use devm_* functions where ever possible 6. Driver is free from GPIO configs (only supports pinctrl method) 7. Use OF data string clock-frequency to get the bus operating frequencies 8. Split the clock divisor calculation function 9. Add resets for the failed transacton cases 10. few other bug fixes and cosmetic changes Signed-off-by: Taekgyun Ko taeggyun...@samsung.com Signed-off-by: Naveen Krishna Chatradhi ch.nav...@samsung.com Reviewed-by: Simon Glass s...@google.com Tested-by: Andrew Bresticker abres...@google.com Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com Signed-off-by: Andrew Bresticker abres...@google.com --- Changes since v8 1. improved the device tree bindings description page for i2c-exynos5 2. fixed the return value check for devm_ioremap_resource .../devicetree/bindings/i2c/i2c-exynos5.txt| 45 + drivers/i2c/busses/Kconfig |7 + drivers/i2c/busses/Makefile|1 + drivers/i2c/busses/i2c-exynos5.c | 888 4 files changed, 941 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/i2c-exynos5.txt create mode 100644 drivers/i2c/busses/i2c-exynos5.c diff --git a/Documentation/devicetree/bindings/i2c/i2c-exynos5.txt b/Documentation/devicetree/bindings/i2c/i2c-exynos5.txt new file mode 100644 index 000..29c01c0 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-exynos5.txt @@ -0,0 +1,45 @@ +* Samsung's High Speed I2C controller + +The Samsung's High Speed I2C controller is used to interface with I2C devices +at various speeds ranging from 100khz to 3.4Mhz. + +Required properties: + - compatible: value should be. + - samsung,exynos5-hsi2c, for i2c compatible with exynos5 hsi2c. + - reg: physical base address of the controller and length of memory mapped +region. + - interrupts: interrupt number to the cpu. + - #address-cells: always 1 (for i2c addresses) + - #size-cells: always 0 + + - Pinctrl: +- pinctrl-0: Pin control group to be used for this controller. +- pinctrl-names: Should contain only one value - default. + +Optional properties: + - samsung,hs-mode: Mode of operation, High speed or Fast speed mode. If not +specified, default value is 0. + - clock-frequency: Desired operating frequency in Hz of the bus. +If not specified, the default value in Hz is 10. + +Example: + +hsi2c@12ca { + compatible = samsung,exynos5-hsi2c; + reg = 0x12ca 0x100; + interrupts = 56; + clock-frequency = 10; + + /* Pinctrl variant begins here */ + pinctrl-0 = i2c4_bus; + pinctrl-names = default; + /* Pinctrl variant ends here */ + + #address-cells = 1; + #size-cells = 0; + + s2mps11_pmic@66 { + compatible = samsung,s2mps11-pmic; + reg = 0x66; + }; +}; diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index adfee98..49a665f 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -434,6 +434,13 @@ config I2C_EG20T ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series. ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH. +config I2C_EXYNOS5 + tristate Exynos5 high-speed I2C driver + depends on ARCH_EXYNOS5 OF + help + Say Y here to include support for high-speed I2C controller in the + Exynos5 based Samsung SoCs. + config I2C_GPIO tristate GPIO-based bitbanging I2C depends on GENERIC_GPIO diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 8f4fc23..b19366c 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -42,6 +42,7 @@ i2c-designware-platform-objs := i2c-designware-platdrv.o obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o i2c-designware-pci-objs := i2c-designware-pcidrv.o obj-$(CONFIG_I2C_EG20T)+= i2c-eg20t.o +obj-$(CONFIG_I2C_EXYNOS5) += i2c-exynos5.o obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c new file mode 100644 index 000..33c481d --- /dev/null +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -0,0 +1,888 @@ +/** + * i2c-exynos5.c - Samsung Exynos5 I2C Controller Driver + * + * Copyright (C) 2013 Samsung Electronics Co., Ltd. + * + * This program
Re: [PATCH] ARM: EXYNOS: Fix support of Exynos4210 rev0 SoC
Hi Kukjin, On Thursday 23 of May 2013 10:11:17 Kukjin Kim wrote: Kukjin Kim wrote: Tomasz Figa wrote: Hi Kukjin, Hi, On Wednesday 15 of May 2013 17:08:04 Tomasz Figa wrote: This patch extends exynos_init_time() function to handle Exynos4210 rev0 SoC, which differs in availability of system timers and needs different clocksource initialization. This makes it possible to use exynos_init_time() function as init_time callback for all Exynos-based boards, including Universal_C210, which originally had to use samsung_timer_init(). Signed-off-by: Tomasz Figa t.f...@samsung.com Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com --- arch/arm/mach-exynos/Kconfig | 3 ++- arch/arm/mach-exynos/common.c | 30 +- arch/arm/mach-exynos/common.h | 2 ++ arch/arm/mach-exynos/mach-universal_c210.c | 5 ++--- 4 files changed, 35 insertions(+), 5 deletions(-) Could you pick this patch to your fixes branch? Yeah, I will after looking at. This is a fix of a regression in handling Exynos4210 rev0 SoC (e.g. Universal C210 board) introduced by patches merged to 3.10. OK, I see but I didn't review yet and I will within a couple of days ;-) OK, looks fine, this will be sent to upstream during -rc for v3.10. Thanks. But, Tomasz, as you know, non-DT supporting files will be gone away in v3.11, just note. Sure. This is a good thing. In 3.11 Universal C210 will be supported only using device tree, but for 3.10 we need this patch to make the old board file still work. Best regards, -- Tomasz Figa Linux Kernel Developer Samsung RD Institute Poland Samsung Electronics -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] clk: exynos5250: Added MUX, DIV and GATE clocks for Gscaler and MFC
NAK In testing we have seen that, when sysmmu of mfc/gscl is used, the respective IP clock has to be ON, or else it was malfunctioning. So for smmu_mfcl and smmu_mfcr, the parent should be mfc so that we make sure the parent is turned on every time sysmmu is accessed. Same thing applies to gscl also. Regards Arun Kumar On Tue, Mar 26, 2013 at 9:56 AM, Prasanna Kumar prasanna...@samsung.com wrote: From: Prasanna Kumar prasanna...@samsung.com Gscaler : 1. For aclk_300_gscl,following clocks are added Mux clocks mout_aclk_300_gscl_mid, mout_aclk_300_gscl_mid1, mout_aclk_300_gscl Divider clock div_aclk300_gscl Sub-Mux clock ( driven from output of divider clock) mout_sub_aclk300 2. For aclk_266_gscl, Sub-Mux clock mout_sub_aclk266 added Divider clock has been modified to refer Sub-Mux clock MFC : For aclk_333 Sub-Mux clock mout_sub_aclk333 added Divider clock has been modified to refer Sub-Mux clock Signed-off-by: Prasanna Kumar prasanna...@samsung.com --- drivers/clk/samsung/clk-exynos5250.c | 57 + 1 files changed, 43 insertions(+), 14 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index e40d6af..40dff9d 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -24,7 +24,9 @@ #define DIV_CPU0 0x500 #define SRC_CORE1 0x4204 #define SRC_TOP0 0x10210 +#define SRC_TOP1 0x10214 #define SRC_TOP2 0x10218 +#define SRC_TOP3 0x1021C #define SRC_GSCL 0x10220 #define SRC_DISP1_00x1022c #define SRC_MAU0x10240 @@ -112,7 +114,9 @@ static __initdata unsigned long exynos5250_clk_regs[] = { DIV_CPU0, SRC_CORE1, SRC_TOP0, + SRC_TOP1, SRC_TOP2, + SRC_TOP3, SRC_GSCL, SRC_DISP1_0, SRC_MAU, @@ -167,6 +171,13 @@ PNAME(mout_mpll_user_p)= { fin_pll, sclk_mpll }; PNAME(mout_bpll_user_p)= { fin_pll, sclk_bpll }; PNAME(mout_aclk166_p) = { sclk_cpll, sclk_mpll_user }; PNAME(mout_aclk200_p) = { sclk_mpll_user, sclk_bpll_user }; +PNAME(mout_sub_aclk266_p) = { fin_pll, div_aclk266 }; +PNAME(mout_aclk_300_gscl_mid_p) = { sclk_mpll_user, sclk_bpll_user}; +PNAME(mout_aclk_300_gscl_mid1_p) = { sclk_vpll, sclk_cpll}; +PNAME(mout_aclk_300_gscl_p) = { mout_aclk_300_gscl_mid, + mout_aclk_300_gscl_mid1 }; +PNAME(mout_sub_aclk300_p) = { fin_pll, div_aclk300_gscl }; +PNAME(mout_sub_aclk333_p) = { fin_pll, div_aclk333 }; PNAME(mout_hdmi_p) = { div_hdmi_pixel, sclk_hdmiphy }; PNAME(mout_usb3_p) = { sclk_mpll_user, sclk_cpll }; PNAME(mout_group1_p) = { fin_pll, fin_pll, sclk_hdmi27m, @@ -220,8 +231,20 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = { MUX(none, sclk_mpll_user, mout_mpll_user_p, SRC_TOP2, 20, 1), MUX(none, sclk_bpll_user, mout_bpll_user_p, SRC_TOP2, 24, 1), MUX(none, mout_aclk166, mout_aclk166_p, SRC_TOP0, 8, 1), - MUX(none, mout_aclk333, mout_aclk166_p, SRC_TOP0, 16, 1), MUX(none, mout_aclk200, mout_aclk200_p, SRC_TOP0, 12, 1), + MUX_A(none, mout_sub_aclk266, mout_sub_aclk266_p, + SRC_TOP3, 8, 1, m_sub_aclk266), + MUX(none, mout_aclk_300_gscl, mout_aclk_300_gscl_p, + SRC_TOP0, 25, 1), + MUX(none, mout_aclk_300_gscl_mid, mout_aclk_300_gscl_mid_p, + SRC_TOP0, 24, 1), + MUX(none, mout_aclk_300_gscl_mid1, mout_aclk_300_gscl_mid1_p, + SRC_TOP1, 12, 1), + MUX_A(none, mout_sub_aclk300, mout_sub_aclk300_p, + SRC_TOP3, 10, 1, m_sub_aclk300), + MUX(none, mout_aclk333, mout_aclk166_p, SRC_TOP0, 16, 1), + MUX_A(none, mout_sub_aclk333, mout_sub_aclk333_p, + SRC_TOP3, 24, 1, m_sub_aclk333), MUX(none, mout_cam_bayer, mout_group1_p, SRC_GSCL, 12, 4), MUX(none, mout_cam0, mout_group1_p, SRC_GSCL, 16, 4), MUX(none, mout_cam1, mout_group1_p, SRC_GSCL, 20, 4), @@ -257,10 +280,12 @@ struct samsung_div_clock exynos5250_div_clks[] __initdata = { DIV(none, sclk_apll, mout_apll, DIV_CPU0, 24, 3), DIV(none, aclk66_pre, sclk_mpll_user, DIV_TOP1, 24, 3), DIV(none, aclk66, aclk66_pre, DIV_TOP0, 0, 3), - DIV(none, aclk266, sclk_mpll_user, DIV_TOP0, 16, 3), DIV(none, aclk166, mout_aclk166, DIV_TOP0, 8, 3), - DIV(none, aclk333, mout_aclk333, DIV_TOP0, 20, 3), DIV(none, aclk200, mout_aclk200, DIV_TOP0,
[PATCH] ARM: EXYNOS: fix software reset logic for EXYNOS5440 SOC
This patch fixes software reset logic. Software reset applies only to powered-on domains in SOC because software reset to all domains causes reboot failure. Signed-off-by: Jungseok Lee jays@samsung.com --- arch/arm/mach-exynos/common.c |6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 7f431dd..a22615d 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -317,9 +317,13 @@ void exynos5_restart(char mode, const char *cmd) val = 0x1; addr = EXYNOS_SWRESET; } else if (of_machine_is_compatible(samsung,exynos5440)) { + u32 status; np = of_find_compatible_node(NULL, NULL, samsung,exynos5440-clock); + addr = of_iomap(np, 0) + 0xbc; + status = __raw_readl(addr); addr = of_iomap(np, 0) + 0xcc; - val = (0xfff 20) | (0x1 16); + val = __raw_readl(addr); + val = (val 0x) | (status 0x); } else { pr_err(%s: cannot support non-DT\n, __func__); return; -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Pulls and drive strengths in the pinctrl world
On 05/18/2013 10:30 AM, Jean-Christophe PLAGNIOL-VILLARD wrote: On 16:57 Sat 18 May , Tomasz Figa wrote: ... Personally I'd prefer a solution with separate property for each parameter, because it's much more flexible and allows shorter lines, making device tree sources more readable. we already discuss this on the ML the one property perline will endup with 100s of node if not 1000s so we all do agree we do not want this in the DT If you introduce s second level of nodes into the DT like the Tegra bindings do, that's really not an issue. For Tegra, each pinctrl state is a node. Within this, there are a bunch of child nodes, each of which applies to n pins, and sets up an arbitrary set of parameters; some nodes can set up mux functions, some can set up e.g. pull-up, etc. The same pin can be affected by multiple of these nodes. This all allows you to group together common settings and avoid duplication and having too many nodes. Then, client drivers' pincrl-0 properties just reference a single top-level state node, not each of the 10/100/... child nodes. Take a look at something like nodes state_i2xmux_* in arch/arm/boot/dts/tegra20-seaboard.dts. -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Pulls and drive strengths in the pinctrl world
On 05/19/2013 03:17 AM, Jean-Christophe PLAGNIOL-VILLARD wrote: ... how a pin can not have mux? Well, if that's the way HW is designed, that's just the way it is. There are certainly pins on Tegra which don't have a mux in HW, but have some configuration options such as drive strength that can be configured. -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [rtc-linux] [PATCH] rtc: max8998: Check for pdata presence before dereferencing
On Wed, 15 May 2013 17:16:08 +0200 Tomasz Figa t.f...@samsung.com wrote: Currently the driver can crash with a NULL pointer dereference if no pdata is provided, despite of successful registration of MFD part. This patch fixes the problem by adding a NULL check before dereferencing the pdata pointer. ... --- a/drivers/rtc/rtc-max8998.c +++ b/drivers/rtc/rtc-max8998.c @@ -285,7 +285,7 @@ static int max8998_rtc_probe(struct platform_device *pdev) info-irq, ret); dev_info(pdev-dev, RTC CHIP NAME: %s\n, pdev-id_entry-name); - if (pdata-rtc_delay) { + if (pdata pdata-rtc_delay) { info-lp3974_bug_workaround = true; dev_warn(pdev-dev, LP3974 with RTC REGERR option. RTC updates will be extremely slow.\n); Looking at your description I'm unable to determine which kernel versions we should fix. This is because the changelog didn't describe the circumstances under which the bug triggers. It's pretty simple: when fixing a bug, include a full description of the bug! As if you were sending a bug report, not a patch. -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] clk: Exynos5250: Add clocks for G3D
Hi Tomasz, Thanks for your review. + DIV(aclk_400_g3d, aclk_400_g3d, mout_aclk400, DIV_TOP0, 24, 3), Do you need to export this div clock? If it's a parent of a gate clock, then you can simply add CLK_SET_RATE_PARENT flag to the gate clock and calling set_rate on it will reconfigure the divider. Yes this clock doesnt need to exported. But the current driver gets this clock and will fail if its not exported. So that will need some changes from the driver side also. DIV(none, div_cam_bayer, mout_cam_bayer, DIV_GSCL, 12, 4), DIV(none, div_cam0, mout_cam0, DIV_GSCL, 16, 4), DIV(none, div_cam1, mout_cam1, DIV_GSCL, 20, 4), @@ -462,6 +471,7 @@ struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { GATE(dp, dp, aclk200, GATE_IP_DISP1, 4, 0, 0), GATE(mixer, mixer, aclk200, GATE_IP_DISP1, 5, 0, 0), GATE(hdmi, hdmi, aclk200, GATE_IP_DISP1, 6, 0, 0), + GATE(g3d, g3d, aclk_400_g3d, GATE_IP_G3D, 0, 0, 0), This would be then: GATE(g3d, g3d, aclk_400_g3d, GATE_IP_G3D, 0, CLK_SET_RATE_PARENT, 0), Yes this would work. I will change it accordingly. Thanks Arun -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: clk: Exynos5250: Add clocks for G3D
Hi Doug, Thanks for the review. But as per Tomasz Figa's comment, I will remove the exporting of aclk_400_g3d to the driver. Regards Arun On Wed, May 22, 2013 at 4:13 AM, Doug Anderson diand...@chromium.org wrote: Arun, On Tue, May 21, 2013 at 5:36 AM, Arun Kumar K arun...@samsung.com wrote: @@ -262,6 +270,7 @@ struct samsung_div_clock exynos5250_div_clks[] __initdata = { DIV(none, aclk166, mout_aclk166, DIV_TOP0, 8, 3), DIV(none, aclk333, mout_aclk333, DIV_TOP0, 20, 3), DIV(none, aclk200, mout_aclk200, DIV_TOP0, 12, 3), + DIV(aclk_400_g3d, aclk_400_g3d, mout_aclk400, DIV_TOP0, 24, 3), Doh! I looked at this more and it looks like I missed something. You've added this clock to the range assigned for [Peripheral Clock Gates]. This is not a gate clock but is a div clock. Perhaps it should be in a different range? Could make IDs that start at 512 or something? -Doug -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/5] Add generic set_rate clk_ops for PLL35XX and PLL36XX for samsung SoCs
This patch series does the following: 1) Factors out possible common code, unifies the clk strutures used for PLL35XX PLL36XX and usues clk-base instead of clk-con0 2) Defines a common rate_table which will contain recommended p, m, s and k values for supported rates that needs to be changed for changing corresponding PLL's rate 3) Adds set_rate() and round_rate() clk_ops for PLL35XX and PLL36XXX Is rebased on branch kgene's for-next https://git.kernel.org/cgit/linux/kernel/git/kgene/linux-samsung.git/log/?h=for-next And tested these patch on chromebook for EPLL settings for Audio on our chrome tree. Vikas Sajjan (2): clk: samsung: Add set_rate() clk_ops for PLL36XX clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC Yadwinder Singh Brar (3): clk: samsung: Use clk-base instead of directly using clk-con0 for PLL3XXX clk: samsung: Add support to register rate_table for PLL3XXX clk: samsung: Add set_rate() clk_ops for PLL35XX drivers/clk/samsung/clk-exynos4.c| 10 +- drivers/clk/samsung/clk-exynos5250.c | 29 +++- drivers/clk/samsung/clk-pll.c| 243 ++ drivers/clk/samsung/clk-pll.h| 27 +++- 4 files changed, 272 insertions(+), 37 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/5] clk: samsung: Add set_rate() clk_ops for PLL35XX
From: Yadwinder Singh Brar yadi.b...@samsung.com Adds set_rate() and round_rate() clk_ops for PLL35XX The round_rate() implemenation as of now is dummy, it returns the same rate which is passed as input. Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com --- drivers/clk/samsung/clk-pll.c | 95 - 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index b8c0260..291cc9e 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -11,6 +11,7 @@ #include linux/errno.h #include linux/sort.h +#include linux/bsearch.h #include clk.h #include clk-pll.h @@ -36,6 +37,21 @@ static int samsung_compare_rate(const void *_a, const void *_b) return a-rate - b-rate; } +static struct samsung_pll_rate_table *samsung_get_pll_settings( + struct samsung_clk_pll *pll, unsigned long rate) +{ + struct samsung_pll_rate_table req_rate, *tmp; + + req_rate.rate = rate; + tmp = bsearch(req_rate, pll-rate_table, pll-rate_count, + sizeof(struct samsung_pll_rate_table), + samsung_compare_rate); + if (tmp) + return tmp; + + return NULL; +} + /* * PLL35xx Clock Type */ @@ -46,9 +62,15 @@ static int samsung_compare_rate(const void *_a, const void *_b) #define PLL35XX_MDIV_MASK (0x3FF) #define PLL35XX_PDIV_MASK (0x3F) #define PLL35XX_SDIV_MASK (0x7) +#define PLL35XX_LOCK_STAT_MASK (0x1) #define PLL35XX_MDIV_SHIFT (16) #define PLL35XX_PDIV_SHIFT (8) #define PLL35XX_SDIV_SHIFT (0) +#define PLL35XX_LOCK_STAT_SHIFT (29) + +#define PLL35XX_MDIV(_tmp) ((_tmp) (PLL35XX_MDIV_MASK PLL35XX_MDIV_SHIFT)) +#define PLL35XX_PDIV(_tmp) ((_tmp) (PLL35XX_PDIV_MASK PLL35XX_PDIV_SHIFT)) +#define PLL35XX_SDIV(_tmp) ((_tmp) (PLL35XX_SDIV_MASK PLL35XX_SDIV_SHIFT)) static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) @@ -68,8 +90,76 @@ static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw, return (unsigned long)fvco; } -static const struct clk_ops samsung_pll35xx_clk_ops = { +static inline bool samsung_pll35xx_mp_change(u32 mdiv, u32 pdiv, u32 pll_con) +{ + if ((mdiv != PLL35XX_MDIV(pll_con)) || (pdiv != PLL35XX_PDIV(pll_con))) + return 1; + else + return 0; +} + +static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + struct samsung_pll_rate_table *rate; + + u32 tmp, mdiv, pdiv, sdiv; + + /* Get required rate settings from table */ + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err(%s: Invalid rate : %lu for pll clk %s\n, __func__, + drate, __clk_get_name(hw-clk)); + return -EINVAL; + } + + mdiv = PLL35XX_MDIV(rate-pll_con0); + pdiv = PLL35XX_PDIV(rate-pll_con0); + sdiv = PLL35XX_SDIV(rate-pll_con0); + + tmp = pll_readl(pll, PLL35XX_CON0_OFFSET); + + if (!(samsung_pll35xx_mp_change(mdiv, pdiv, tmp))) { + /* If only s change, change just s value only*/ + tmp = ~(PLL35XX_SDIV_MASK PLL35XX_SDIV_SHIFT); + tmp |= sdiv; + pll_writel(pll, tmp, PLL35XX_CON0_OFFSET); + } else { + /* Set PLL lock time. + Maximum lock time can be 270 * PDIV cycles */ + pll_writel(pll, (pdiv PLL35XX_PDIV_SHIFT) * 270, + PLL35XX_LOCK_OFFSET); + + /* Change PLL PMS values */ + tmp = ~((PLL35XX_MDIV_MASK PLL35XX_MDIV_SHIFT) | + (PLL35XX_PDIV_MASK PLL35XX_PDIV_SHIFT) | + (PLL35XX_SDIV_MASK PLL35XX_SDIV_SHIFT)); + tmp |= mdiv | pdiv | sdiv; + pll_writel(pll, tmp, PLL35XX_CON0_OFFSET); + + /* wait_lock_time */ + do { + cpu_relax(); + tmp = pll_readl(pll, PLL35XX_CON0_OFFSET); + } while (!(tmp (PLL35XX_LOCK_STAT_MASK +PLL35XX_LOCK_STAT_SHIFT))); + } + + return 0; +} + +static long samsung_pll35xx_round_rate(struct clk_hw *hw, + unsigned long drate, unsigned long *prate) +{ + /* Clock framework cries without this, so implemented dummy */ + return drate; +} + +static struct clk_ops samsung_pll35xx_clk_ops = { .recalc_rate = samsung_pll35xx_recalc_rate, + .round_rate = samsung_pll35xx_round_rate, + .set_rate = samsung_pll35xx_set_rate, }; struct clk * __init samsung_clk_register_pll35xx(const char *name, @@ -102,6 +192,9
[PATCH 4/5] clk: samsung: Add set_rate() clk_ops for PLL36XX
This patch adds set_rate and round_rate clk_ops for PLL36XX. The round_rate() implementation as of now is dummy, it returns the same rate which is passed as input. Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org --- drivers/clk/samsung/clk-pll.c | 67 + 1 file changed, 67 insertions(+) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 291cc9e..55ff5fd 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -224,6 +224,13 @@ struct clk * __init samsung_clk_register_pll35xx(const char *name, #define PLL36XX_MDIV_SHIFT (16) #define PLL36XX_PDIV_SHIFT (8) #define PLL36XX_SDIV_SHIFT (0) +#define PLL36XX_KDIV_SHIFT (0) +#define PLL36XX_LOCK_STAT_SHIFT (29) + +#define PLL36XX_MDIV(_tmp) ((_tmp) (PLL36XX_MDIV_MASK PLL36XX_MDIV_SHIFT)) +#define PLL36XX_PDIV(_tmp) ((_tmp) (PLL36XX_PDIV_MASK PLL36XX_PDIV_SHIFT)) +#define PLL36XX_SDIV(_tmp) ((_tmp) (PLL36XX_SDIV_MASK PLL36XX_SDIV_SHIFT)) +#define PLL36XX_KDIV(_tmp) ((_tmp) (PLL36XX_KDIV_MASK PLL36XX_KDIV_SHIFT)) static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) @@ -246,8 +253,65 @@ static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw, return (unsigned long)fvco; } +static long samsung_pll36xx_round_rate(struct clk_hw *hw, unsigned long drate, + unsigned long *prate) +{ + /* retruns the same 'drate' whichs comes as input */ + return drate; +} + +static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 tmp, pll_con0, pll_con1, mdiv, pdiv, sdiv, kdiv; + struct samsung_pll_rate_table *rate; + + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err(%s: Invalid rate : %lu for pll clk %s\n, __func__, + drate, __clk_get_name(hw-clk)); + return -EINVAL; + } + + mdiv = PLL36XX_MDIV(rate-pll_con0); + pdiv = PLL36XX_PDIV(rate-pll_con0); + sdiv = PLL36XX_SDIV(rate-pll_con0); + kdiv = PLL36XX_KDIV(rate-pll_con1); + + pll_con0 = pll_readl(pll, PLL36XX_CON0_OFFSET); + pll_con1 = pll_readl(pll, PLL36XX_CON1_OFFSET); + + pll_con1 = ~(PLL36XX_KDIV_MASK PLL36XX_KDIV_SHIFT); + + /* Set PLL lock time. + Maximum lock time can be 3000 * PDIV cycles */ + pll_writel(pll, ((pdiv PLL36XX_PDIV_SHIFT) * 3000), + PLL36XX_LOCK_OFFSET); + +/* Change PLL PMS values */ + pll_con0 = ~((PLL36XX_MDIV_MASK PLL36XX_MDIV_SHIFT) | + (PLL36XX_PDIV_MASK PLL36XX_PDIV_SHIFT) | + (PLL36XX_SDIV_MASK PLL36XX_SDIV_SHIFT)); + pll_con0 |= mdiv | pdiv | sdiv; + pll_writel(pll, pll_con0, PLL36XX_CON0_OFFSET); + + pll_con1 |= kdiv; + pll_writel(pll, pll_con1, PLL36XX_CON1_OFFSET); + + /* wait_lock_time */ + do { + cpu_relax(); + tmp = pll_readl(pll, PLL36XX_CON0_OFFSET); + } while (!(tmp (1 PLL36XX_LOCK_STAT_SHIFT))); + + return 0; +} + static const struct clk_ops samsung_pll36xx_clk_ops = { .recalc_rate = samsung_pll36xx_recalc_rate, + .set_rate = samsung_pll36xx_set_rate, + .round_rate = samsung_pll36xx_round_rate, }; struct clk * __init samsung_clk_register_pll36xx(const char *name, @@ -280,6 +344,9 @@ struct clk * __init samsung_clk_register_pll36xx(const char *name, sort(pll-rate_table, pll-rate_count, sizeof(struct samsung_pll_rate_table), samsung_compare_rate, NULL); + } else { + samsung_pll35xx_clk_ops.round_rate = NULL; + samsung_pll35xx_clk_ops.set_rate = NULL; } clk = clk_register(NULL, pll-hw); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/5] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC
Adds the EPLL and VPLL freq table for exynos5250 SoC. Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org --- drivers/clk/samsung/clk-exynos5250.c | 19 +-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index ddf10ca..00d1fa6 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -469,6 +469,21 @@ static __initdata struct of_device_id ext_clk_match[] = { { }, }; +static struct samsung_pll_rate_table vpll_tbl[] = { + PLL_36XX_RATE(7050, 2, 94, 4, 0), +}; + +static struct samsung_pll_rate_table epll_tbl[] = { + PLL_36XX_RATE(19200, 48, 3, 1, 0), + PLL_36XX_RATE(18000, 45, 3, 1, 0), + PLL_36XX_RATE(73728000, 73, 3, 3, 47710), + PLL_36XX_RATE(67737600, 90, 4, 3, 20762), + PLL_36XX_RATE(49152000, 49, 3, 3, 9961), + PLL_36XX_RATE(45158400, 45, 3, 3, 10381), + PLL_36XX_RATE(180633600, 45, 3, 1, 10381), + PLL_36XX_RATE(32768000, 131, 3, 5, 4719), +}; + /* register exynox5250 clocks */ void __init exynos5250_clk_init(struct device_node *np) { @@ -501,9 +516,9 @@ void __init exynos5250_clk_init(struct device_node *np) cpll = samsung_clk_register_pll35xx(fout_cpll, fin_pll, reg_base + 0x10020, NULL, 0); epll = samsung_clk_register_pll36xx(fout_epll, fin_pll, - reg_base + 0x10030, NULL, 0); + reg_base + 0x10030, epll_tbl, ARRAY_SIZE(epll_tbl)); vpll = samsung_clk_register_pll36xx(fout_vpll, mout_vpllsrc, - reg_base + 0x10040, NULL, 0); + reg_base + 0x10040, vpll_tbl, ARRAY_SIZE(vpll_tbl)); samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks, ARRAY_SIZE(exynos5250_fixed_rate_clks)); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RESEND PATCH 0/5] Add generic set_rate clk_ops for PLL35XX and PLL36XX for samsung SoCs
This patch series does the following: 1) Factors out possible common code, unifies the clk strutures used for PLL35XX PLL36XX and usues clk-base instead of clk-con0 2) Defines a common rate_table which will contain recommended p, m, s and k values for supported rates that needs to be changed for changing corresponding PLL's rate 3) Adds set_rate() and round_rate() clk_ops for PLL35XX and PLL36XXX Is rebased on branch kgene's for-next https://git.kernel.org/cgit/linux/kernel/git/kgene/linux-samsung.git/log/?h=for-next And tested these patch on chromebook for EPLL settings for Audio on our chrome tree. Vikas Sajjan (2): clk: samsung: Add set_rate() clk_ops for PLL36XX clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC Yadwinder Singh Brar (3): clk: samsung: Use clk-base instead of directly using clk-con0 for PLL3XXX clk: samsung: Add support to register rate_table for PLL3XXX clk: samsung: Add set_rate() clk_ops for PLL35XX drivers/clk/samsung/clk-exynos4.c| 10 +- drivers/clk/samsung/clk-exynos5250.c | 29 +++- drivers/clk/samsung/clk-pll.c| 243 ++ drivers/clk/samsung/clk-pll.h| 27 +++- 4 files changed, 272 insertions(+), 37 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RESEND PATCH 2/5] clk: samsung: Add support to register rate_table for PLL3xxx
From: Yadwinder Singh Brar yadi.b...@samsung.com This patch defines a common rate_table which will contain recommended p, m, s and k values for supported rates that needs to be changed for changing corresponding PLL's rate. It also sorts the rate table while registering the PLL rate table. So that this sorted table can be used for making the searching of required rate efficient. Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com --- drivers/clk/samsung/clk-exynos4.c|8 drivers/clk/samsung/clk-exynos5250.c | 14 +++--- drivers/clk/samsung/clk-pll.c| 35 -- drivers/clk/samsung/clk-pll.h| 27 -- 4 files changed, 69 insertions(+), 15 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index cf7d4e7..beff8a1 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1021,13 +1021,13 @@ void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so reg_base + VPLL_CON0, pll_4650c); } else { apll = samsung_clk_register_pll35xx(fout_apll, fin_pll, - reg_base + APLL_LOCK); + reg_base + APLL_LOCK, NULL, 0); mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll, - reg_base + E4X12_MPLL_LOCK); + reg_base + E4X12_MPLL_LOCK, NULL, 0); epll = samsung_clk_register_pll36xx(fout_epll, fin_pll, - reg_base + EPLL_LOCK); + reg_base + EPLL_LOCK, NULL, 0); vpll = samsung_clk_register_pll36xx(fout_vpll, fin_pll, - reg_base + VPLL_LOCK); + reg_base + VPLL_LOCK, NULL, 0); } samsung_clk_add_lookup(apll, fout_apll); diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 687b580..ddf10ca 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -491,19 +491,19 @@ void __init exynos5250_clk_init(struct device_node *np) ext_clk_match); apll = samsung_clk_register_pll35xx(fout_apll, fin_pll, - reg_base); + reg_base, NULL, 0); mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll, - reg_base + 0x4000); + reg_base + 0x4000, NULL, 0); bpll = samsung_clk_register_pll35xx(fout_bpll, fin_pll, - reg_base + 0x20010); + reg_base + 0x20010, NULL, 0); gpll = samsung_clk_register_pll35xx(fout_gpll, fin_pll, - reg_base + 0x10050); + reg_base + 0x10050, NULL, 0); cpll = samsung_clk_register_pll35xx(fout_cpll, fin_pll, - reg_base + 0x10020); + reg_base + 0x10020, NULL, 0); epll = samsung_clk_register_pll36xx(fout_epll, fin_pll, - reg_base + 0x10030); + reg_base + 0x10030, NULL, 0); vpll = samsung_clk_register_pll36xx(fout_vpll, mout_vpllsrc, - reg_base + 0x10040); + reg_base + 0x10040, NULL, 0); samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks, ARRAY_SIZE(exynos5250_fixed_rate_clks)); diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 01f17cf..b8c0260 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -10,12 +10,15 @@ */ #include linux/errno.h +#include linux/sort.h #include clk.h #include clk-pll.h struct samsung_clk_pll { struct clk_hw hw; const void __iomem *base; + struct samsung_pll_rate_table *rate_table; + unsigned int rate_count; }; #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw) @@ -25,6 +28,14 @@ struct samsung_clk_pll { #define pll_writel(pll, val, offset) \ __raw_writel(val, (void __iomem *)(pll-base + (offset))); +static int samsung_compare_rate(const void *_a, const void *_b) +{ + const struct samsung_pll_rate_table *a = _a; + const struct samsung_pll_rate_table *b = _b; + + return a-rate - b-rate; +} + /* * PLL35xx Clock Type */ @@ -62,7 +73,9 @@ static const struct clk_ops samsung_pll35xx_clk_ops = { }; struct clk * __init samsung_clk_register_pll35xx(const char *name, - const char *pname, const void __iomem *base) + const char *pname, const void __iomem *base, + struct samsung_pll_rate_table *rate_table, +
[RESEND PATCH 3/5] clk: samsung: Add set_rate() clk_ops for PLL35xx
From: Yadwinder Singh Brar yadi.b...@samsung.com Adds set_rate() and round_rate() clk_ops for PLL35xx The round_rate() implemenation as of now is dummy, it returns the same rate which is passed as input. Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com --- drivers/clk/samsung/clk-pll.c | 95 - 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index b8c0260..291cc9e 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -11,6 +11,7 @@ #include linux/errno.h #include linux/sort.h +#include linux/bsearch.h #include clk.h #include clk-pll.h @@ -36,6 +37,21 @@ static int samsung_compare_rate(const void *_a, const void *_b) return a-rate - b-rate; } +static struct samsung_pll_rate_table *samsung_get_pll_settings( + struct samsung_clk_pll *pll, unsigned long rate) +{ + struct samsung_pll_rate_table req_rate, *tmp; + + req_rate.rate = rate; + tmp = bsearch(req_rate, pll-rate_table, pll-rate_count, + sizeof(struct samsung_pll_rate_table), + samsung_compare_rate); + if (tmp) + return tmp; + + return NULL; +} + /* * PLL35xx Clock Type */ @@ -46,9 +62,15 @@ static int samsung_compare_rate(const void *_a, const void *_b) #define PLL35XX_MDIV_MASK (0x3FF) #define PLL35XX_PDIV_MASK (0x3F) #define PLL35XX_SDIV_MASK (0x7) +#define PLL35XX_LOCK_STAT_MASK (0x1) #define PLL35XX_MDIV_SHIFT (16) #define PLL35XX_PDIV_SHIFT (8) #define PLL35XX_SDIV_SHIFT (0) +#define PLL35XX_LOCK_STAT_SHIFT (29) + +#define PLL35XX_MDIV(_tmp) ((_tmp) (PLL35XX_MDIV_MASK PLL35XX_MDIV_SHIFT)) +#define PLL35XX_PDIV(_tmp) ((_tmp) (PLL35XX_PDIV_MASK PLL35XX_PDIV_SHIFT)) +#define PLL35XX_SDIV(_tmp) ((_tmp) (PLL35XX_SDIV_MASK PLL35XX_SDIV_SHIFT)) static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) @@ -68,8 +90,76 @@ static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw, return (unsigned long)fvco; } -static const struct clk_ops samsung_pll35xx_clk_ops = { +static inline bool samsung_pll35xx_mp_change(u32 mdiv, u32 pdiv, u32 pll_con) +{ + if ((mdiv != PLL35XX_MDIV(pll_con)) || (pdiv != PLL35XX_PDIV(pll_con))) + return 1; + else + return 0; +} + +static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + struct samsung_pll_rate_table *rate; + + u32 tmp, mdiv, pdiv, sdiv; + + /* Get required rate settings from table */ + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err(%s: Invalid rate : %lu for pll clk %s\n, __func__, + drate, __clk_get_name(hw-clk)); + return -EINVAL; + } + + mdiv = PLL35XX_MDIV(rate-pll_con0); + pdiv = PLL35XX_PDIV(rate-pll_con0); + sdiv = PLL35XX_SDIV(rate-pll_con0); + + tmp = pll_readl(pll, PLL35XX_CON0_OFFSET); + + if (!(samsung_pll35xx_mp_change(mdiv, pdiv, tmp))) { + /* If only s change, change just s value only*/ + tmp = ~(PLL35XX_SDIV_MASK PLL35XX_SDIV_SHIFT); + tmp |= sdiv; + pll_writel(pll, tmp, PLL35XX_CON0_OFFSET); + } else { + /* Set PLL lock time. + Maximum lock time can be 270 * PDIV cycles */ + pll_writel(pll, (pdiv PLL35XX_PDIV_SHIFT) * 270, + PLL35XX_LOCK_OFFSET); + + /* Change PLL PMS values */ + tmp = ~((PLL35XX_MDIV_MASK PLL35XX_MDIV_SHIFT) | + (PLL35XX_PDIV_MASK PLL35XX_PDIV_SHIFT) | + (PLL35XX_SDIV_MASK PLL35XX_SDIV_SHIFT)); + tmp |= mdiv | pdiv | sdiv; + pll_writel(pll, tmp, PLL35XX_CON0_OFFSET); + + /* wait_lock_time */ + do { + cpu_relax(); + tmp = pll_readl(pll, PLL35XX_CON0_OFFSET); + } while (!(tmp (PLL35XX_LOCK_STAT_MASK +PLL35XX_LOCK_STAT_SHIFT))); + } + + return 0; +} + +static long samsung_pll35xx_round_rate(struct clk_hw *hw, + unsigned long drate, unsigned long *prate) +{ + /* Clock framework cries without this, so implemented dummy */ + return drate; +} + +static struct clk_ops samsung_pll35xx_clk_ops = { .recalc_rate = samsung_pll35xx_recalc_rate, + .round_rate = samsung_pll35xx_round_rate, + .set_rate = samsung_pll35xx_set_rate, }; struct clk * __init samsung_clk_register_pll35xx(const char *name, @@ -102,6 +192,9
[RESEND PATCH 4/5] clk: samsung: Add set_rate() clk_ops for PLL36xx
This patch adds set_rate and round_rate clk_ops for PLL36xx The round_rate() implementation as of now is dummy, it returns the same rate which is passed as input. Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org --- drivers/clk/samsung/clk-pll.c | 67 + 1 file changed, 67 insertions(+) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 291cc9e..55ff5fd 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -224,6 +224,13 @@ struct clk * __init samsung_clk_register_pll35xx(const char *name, #define PLL36XX_MDIV_SHIFT (16) #define PLL36XX_PDIV_SHIFT (8) #define PLL36XX_SDIV_SHIFT (0) +#define PLL36XX_KDIV_SHIFT (0) +#define PLL36XX_LOCK_STAT_SHIFT (29) + +#define PLL36XX_MDIV(_tmp) ((_tmp) (PLL36XX_MDIV_MASK PLL36XX_MDIV_SHIFT)) +#define PLL36XX_PDIV(_tmp) ((_tmp) (PLL36XX_PDIV_MASK PLL36XX_PDIV_SHIFT)) +#define PLL36XX_SDIV(_tmp) ((_tmp) (PLL36XX_SDIV_MASK PLL36XX_SDIV_SHIFT)) +#define PLL36XX_KDIV(_tmp) ((_tmp) (PLL36XX_KDIV_MASK PLL36XX_KDIV_SHIFT)) static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) @@ -246,8 +253,65 @@ static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw, return (unsigned long)fvco; } +static long samsung_pll36xx_round_rate(struct clk_hw *hw, unsigned long drate, + unsigned long *prate) +{ + /* retruns the same 'drate' whichs comes as input */ + return drate; +} + +static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 tmp, pll_con0, pll_con1, mdiv, pdiv, sdiv, kdiv; + struct samsung_pll_rate_table *rate; + + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err(%s: Invalid rate : %lu for pll clk %s\n, __func__, + drate, __clk_get_name(hw-clk)); + return -EINVAL; + } + + mdiv = PLL36XX_MDIV(rate-pll_con0); + pdiv = PLL36XX_PDIV(rate-pll_con0); + sdiv = PLL36XX_SDIV(rate-pll_con0); + kdiv = PLL36XX_KDIV(rate-pll_con1); + + pll_con0 = pll_readl(pll, PLL36XX_CON0_OFFSET); + pll_con1 = pll_readl(pll, PLL36XX_CON1_OFFSET); + + pll_con1 = ~(PLL36XX_KDIV_MASK PLL36XX_KDIV_SHIFT); + + /* Set PLL lock time. + Maximum lock time can be 3000 * PDIV cycles */ + pll_writel(pll, ((pdiv PLL36XX_PDIV_SHIFT) * 3000), + PLL36XX_LOCK_OFFSET); + +/* Change PLL PMS values */ + pll_con0 = ~((PLL36XX_MDIV_MASK PLL36XX_MDIV_SHIFT) | + (PLL36XX_PDIV_MASK PLL36XX_PDIV_SHIFT) | + (PLL36XX_SDIV_MASK PLL36XX_SDIV_SHIFT)); + pll_con0 |= mdiv | pdiv | sdiv; + pll_writel(pll, pll_con0, PLL36XX_CON0_OFFSET); + + pll_con1 |= kdiv; + pll_writel(pll, pll_con1, PLL36XX_CON1_OFFSET); + + /* wait_lock_time */ + do { + cpu_relax(); + tmp = pll_readl(pll, PLL36XX_CON0_OFFSET); + } while (!(tmp (1 PLL36XX_LOCK_STAT_SHIFT))); + + return 0; +} + static const struct clk_ops samsung_pll36xx_clk_ops = { .recalc_rate = samsung_pll36xx_recalc_rate, + .set_rate = samsung_pll36xx_set_rate, + .round_rate = samsung_pll36xx_round_rate, }; struct clk * __init samsung_clk_register_pll36xx(const char *name, @@ -280,6 +344,9 @@ struct clk * __init samsung_clk_register_pll36xx(const char *name, sort(pll-rate_table, pll-rate_count, sizeof(struct samsung_pll_rate_table), samsung_compare_rate, NULL); + } else { + samsung_pll35xx_clk_ops.round_rate = NULL; + samsung_pll35xx_clk_ops.set_rate = NULL; } clk = clk_register(NULL, pll-hw); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RESEND PATCH 5/5] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC
Adds the EPLL and VPLL freq table for exynos5250 SoC. Signed-off-by: Vikas Sajjan vikas.saj...@linaro.org --- drivers/clk/samsung/clk-exynos5250.c | 19 +-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index ddf10ca..00d1fa6 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -469,6 +469,21 @@ static __initdata struct of_device_id ext_clk_match[] = { { }, }; +static struct samsung_pll_rate_table vpll_tbl[] = { + PLL_36XX_RATE(7050, 2, 94, 4, 0), +}; + +static struct samsung_pll_rate_table epll_tbl[] = { + PLL_36XX_RATE(19200, 48, 3, 1, 0), + PLL_36XX_RATE(18000, 45, 3, 1, 0), + PLL_36XX_RATE(73728000, 73, 3, 3, 47710), + PLL_36XX_RATE(67737600, 90, 4, 3, 20762), + PLL_36XX_RATE(49152000, 49, 3, 3, 9961), + PLL_36XX_RATE(45158400, 45, 3, 3, 10381), + PLL_36XX_RATE(180633600, 45, 3, 1, 10381), + PLL_36XX_RATE(32768000, 131, 3, 5, 4719), +}; + /* register exynox5250 clocks */ void __init exynos5250_clk_init(struct device_node *np) { @@ -501,9 +516,9 @@ void __init exynos5250_clk_init(struct device_node *np) cpll = samsung_clk_register_pll35xx(fout_cpll, fin_pll, reg_base + 0x10020, NULL, 0); epll = samsung_clk_register_pll36xx(fout_epll, fin_pll, - reg_base + 0x10030, NULL, 0); + reg_base + 0x10030, epll_tbl, ARRAY_SIZE(epll_tbl)); vpll = samsung_clk_register_pll36xx(fout_vpll, mout_vpllsrc, - reg_base + 0x10040, NULL, 0); + reg_base + 0x10040, vpll_tbl, ARRAY_SIZE(vpll_tbl)); samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks, ARRAY_SIZE(exynos5250_fixed_rate_clks)); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RESEND PATCH 1/5] clk: samsung: Use clk-base instead of directly using clk-con0 for PLL3xxx
From: Yadwinder Singh Brar yadi.b...@samsung.com To factor out possible common code, this patch unifies the clk strutures used for PLL35xx PLL36xx and usues clk-base instead of clk-con0. Signed-off-by: Yadwinder Singh Brar yadi.b...@samsung.com --- drivers/clk/samsung/clk-exynos4.c| 10 --- drivers/clk/samsung/clk-exynos5250.c | 14 - drivers/clk/samsung/clk-pll.c| 54 ++ drivers/clk/samsung/clk-pll.h|4 +-- 4 files changed, 44 insertions(+), 38 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index d0940e6..cf7d4e7 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -97,12 +97,14 @@ #define GATE_IP_PERIL 0xc950 #define E4210_GATE_IP_PERIR0xc960 #define GATE_BLOCK 0xc970 +#define E4X12_MPLL_LOCK0x10008 #define E4X12_MPLL_CON00x10108 #define SRC_DMC0x10200 #define SRC_MASK_DMC 0x10300 #define DIV_DMC0 0x10500 #define DIV_DMC1 0x10504 #define GATE_IP_DMC0x10900 +#define APLL_LOCK 0x14000 #define APLL_CON0 0x14100 #define E4210_MPLL_CON00x14108 #define SRC_CPU0x14200 @@ -1019,13 +1021,13 @@ void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so reg_base + VPLL_CON0, pll_4650c); } else { apll = samsung_clk_register_pll35xx(fout_apll, fin_pll, - reg_base + APLL_CON0); + reg_base + APLL_LOCK); mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll, - reg_base + E4X12_MPLL_CON0); + reg_base + E4X12_MPLL_LOCK); epll = samsung_clk_register_pll36xx(fout_epll, fin_pll, - reg_base + EPLL_CON0); + reg_base + EPLL_LOCK); vpll = samsung_clk_register_pll36xx(fout_vpll, fin_pll, - reg_base + VPLL_CON0); + reg_base + VPLL_LOCK); } samsung_clk_add_lookup(apll, fout_apll); diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 5c97e75..687b580 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -491,19 +491,19 @@ void __init exynos5250_clk_init(struct device_node *np) ext_clk_match); apll = samsung_clk_register_pll35xx(fout_apll, fin_pll, - reg_base + 0x100); + reg_base); mpll = samsung_clk_register_pll35xx(fout_mpll, fin_pll, - reg_base + 0x4100); + reg_base + 0x4000); bpll = samsung_clk_register_pll35xx(fout_bpll, fin_pll, - reg_base + 0x20110); + reg_base + 0x20010); gpll = samsung_clk_register_pll35xx(fout_gpll, fin_pll, - reg_base + 0x10150); + reg_base + 0x10050); cpll = samsung_clk_register_pll35xx(fout_cpll, fin_pll, - reg_base + 0x10120); + reg_base + 0x10020); epll = samsung_clk_register_pll36xx(fout_epll, fin_pll, - reg_base + 0x10130); + reg_base + 0x10030); vpll = samsung_clk_register_pll36xx(fout_vpll, mout_vpllsrc, - reg_base + 0x10140); + reg_base + 0x10040); samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks, ARRAY_SIZE(exynos5250_fixed_rate_clks)); diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 89135f6..01f17cf 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -13,9 +13,24 @@ #include clk.h #include clk-pll.h +struct samsung_clk_pll { + struct clk_hw hw; + const void __iomem *base; +}; + +#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw) + +#define pll_readl(pll, offset) \ + __raw_readl((void __iomem *)(pll-base + (offset))); +#define pll_writel(pll, val, offset) \ + __raw_writel(val, (void __iomem *)(pll-base + (offset))); + /* * PLL35xx Clock Type */ +#define PLL35XX_LOCK_OFFSET 0x0 +#define PLL35XX_CON0_OFFSET 0x100 +#define PLL35XX_CON1_OFFSET 0x104 #define PLL35XX_MDIV_MASK (0x3FF) #define PLL35XX_PDIV_MASK (0x3F) @@ -24,21 +39,14 @@ #define PLL35XX_PDIV_SHIFT (8) #define PLL35XX_SDIV_SHIFT (0)