diff options
author | Olof Johansson <olof@lixom.net> | 2013-06-27 17:04:27 -0700 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-06-27 17:04:27 -0700 |
commit | 8c3d913888cfb0066d62831969c3a992f7e4aba5 (patch) | |
tree | 0b52b0b71cb6b7c141ffa050b36245a13cff4f54 | |
parent | fbd1a04b210d56ef84200df56fc0291746d4d4dc (diff) | |
parent | 8cc7f5338e729b79194e6c22e3c794faaef974b8 (diff) |
Merge tag 'msm-clock-for-3.11b' of git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm into next/late
From David Brown:
MSM clock updates for 3.11.
Per Stephen Boyd's coverletter:
Resending to collect higher level maintainer acks per Olof's request.
The plan is to push this patchset through MSM to the arm-soc tree.
This patchset moves the existing MSM clock code and affected drivers
to the common clock framework. A prerequisite of moving to the common
clock framework is to use clk_prepare() and clk_enable() so the first
few patches migrate drivers to that call (clk_prepare() is a no-op on
MSM right now). It also removes some custom clock APIs that MSM
provides and finally moves the proc_comm clock code to the common
struct clk.
This patch series will be used as the foundation of the MSM 8660/8960
clock code that I plan to send out after this series.
* tag 'msm-clock-for-3.11b' of git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm:
ARM: msm: Migrate to common clock framework
ARM: msm: Make proc_comm clock control into a platform driver
ARM: msm: Prepare clk_get() users in mach-msm for clock-pcom driver
ARM: msm: Remove clock-7x30.h include file
ARM: msm: Remove custom clk_set_{max,min}_rate() API
ARM: msm: Remove custom clk_set_flags() API
msm: iommu: Use clk_set_rate() instead of clk_set_min_rate()
msm: iommu: Convert to clk_prepare/unprepare
msm_sdcc: Convert to clk_prepare/unprepare
usb: otg: msm: Convert to clk_prepare/unprepare
msm_serial: Use devm_clk_get() and properly return errors
msm_serial: Convert to clk_prepare/unprepare
Acked-by: Chris Ball <cjb@laptop.org> # for msm_sdcc.c
Signed-off-by: Olof Johansson <olof@lixom.net>
24 files changed, 243 insertions, 659 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9fbdc10fe835..45230dec9ebf 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -623,8 +623,8 @@ config ARCH_MSM bool "Qualcomm MSM" select ARCH_REQUIRE_GPIOLIB select CLKDEV_LOOKUP + select COMMON_CLK select GENERIC_CLOCKEVENTS - select HAVE_CLK help Support for Qualcomm MSM/QSD based systems. This runs on the apps processor of the MSM/QSD and depends on a shared memory diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 17519faf082f..700d77b7eb1a 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -1,16 +1,18 @@ obj-y += io.o timer.o obj-y += clock.o -obj-$(CONFIG_DEBUG_FS) += clock-debug.o obj-$(CONFIG_MSM_VIC) += irq-vic.o obj-$(CONFIG_MSM_IOMMU) += devices-iommu.o -obj-$(CONFIG_ARCH_MSM7X00A) += dma.o irq.o -obj-$(CONFIG_ARCH_MSM7X30) += dma.o -obj-$(CONFIG_ARCH_QSD8X50) += dma.o sirc.o +obj-$(CONFIG_ARCH_MSM7X00A) += irq.o +obj-$(CONFIG_ARCH_QSD8X50) += sirc.o obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o clock-pcom.o vreg.o +obj-$(CONFIG_ARCH_MSM7X00A) += dma.o +obj-$(CONFIG_ARCH_MSM7X30) += dma.o +obj-$(CONFIG_ARCH_QSD8X50) += dma.o + obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o obj-$(CONFIG_MSM_SMD) += last_radio_log.o obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c index 82eaf88d2026..803651ad4f62 100644 --- a/arch/arm/mach-msm/board-halibut.c +++ b/arch/arm/mach-msm/board-halibut.c @@ -59,6 +59,7 @@ static struct platform_device smc91x_device = { }; static struct platform_device *devices[] __initdata = { + &msm_clock_7x01a, &msm_device_gpio_7201, &msm_device_uart3, &msm_device_smd, @@ -91,7 +92,6 @@ static void __init halibut_fixup(struct tag *tags, char **cmdline, static void __init halibut_map_io(void) { msm_map_common_io(); - msm_clock_init(msm_clocks_7x01a, msm_num_clocks_7x01a); } static void __init halibut_init_late(void) diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c index 520c141acd03..db3d8c0bc8a4 100644 --- a/arch/arm/mach-msm/board-msm7x30.c +++ b/arch/arm/mach-msm/board-msm7x30.c @@ -89,6 +89,7 @@ struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = { }; static struct platform_device *devices[] __initdata = { + &msm_clock_7x30, &msm_device_gpio_7x30, #if defined(CONFIG_SERIAL_MSM) || defined(CONFIG_MSM_SERIAL_DEBUGGER) &msm_device_uart2, @@ -116,7 +117,6 @@ static void __init msm7x30_init(void) static void __init msm7x30_map_io(void) { msm_map_msm7x30_io(); - msm_clock_init(msm_clocks_7x30, msm_num_clocks_7x30); } static void __init msm7x30_init_late(void) diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c index 38a532d6937c..f14a73d86bc0 100644 --- a/arch/arm/mach-msm/board-qsd8x50.c +++ b/arch/arm/mach-msm/board-qsd8x50.c @@ -89,6 +89,7 @@ static struct msm_otg_platform_data msm_otg_pdata = { }; static struct platform_device *devices[] __initdata = { + &msm_clock_8x50, &msm_device_gpio_8x50, &msm_device_uart3, &msm_device_smd, @@ -172,7 +173,6 @@ static void __init qsd8x50_init_mmc(void) static void __init qsd8x50_map_io(void) { msm_map_qsd8x50_io(); - msm_clock_init(msm_clocks_8x50, msm_num_clocks_8x50); } static void __init qsd8x50_init_irq(void) diff --git a/arch/arm/mach-msm/board-trout-panel.c b/arch/arm/mach-msm/board-trout-panel.c index f9a5db6d2ced..77b0a26f897f 100644 --- a/arch/arm/mach-msm/board-trout-panel.c +++ b/arch/arm/mach-msm/board-trout-panel.c @@ -7,7 +7,6 @@ #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/leds.h> -#include <linux/clk.h> #include <linux/err.h> #include <asm/io.h> @@ -19,6 +18,7 @@ #include "board-trout.h" #include "proc_comm.h" +#include "clock-pcom.h" #include "devices.h" #define TROUT_DEFAULT_BACKLIGHT_BRIGHTNESS 255 @@ -170,7 +170,6 @@ static struct mddi_table mddi_toshiba_init_table[] = { #define INTMASK_VWAKEOUT (1U << 0) -static struct clk *gp_clk; static int trout_new_backlight = 1; static struct vreg *vreg_mddi_1v5; static struct vreg *vreg_lcm_2v85; @@ -273,18 +272,14 @@ int __init trout_init_panel(void) } else { uint32_t config = PCOM_GPIO_CFG(27, 1, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA); + uint32_t id = P_GP_CLK; + uint32_t rate = 19200000; + msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &config, 0); - gp_clk = clk_get(NULL, "gp_clk"); - if (IS_ERR(gp_clk)) { - printk(KERN_ERR "trout_init_panel: could not get gp" - "clock\n"); - gp_clk = NULL; - } - rc = clk_set_rate(gp_clk, 19200000); - if (rc) - printk(KERN_ERR "trout_init_panel: set clock rate " - "failed\n"); + msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate); + if (id < 0) + pr_err("trout_init_panel: set clock rate failed\n"); } rc = platform_device_register(&msm_device_mdp); diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c index 80fe1c5ff5c1..64a46eb4fc49 100644 --- a/arch/arm/mach-msm/board-trout.c +++ b/arch/arm/mach-msm/board-trout.c @@ -36,6 +36,7 @@ extern int trout_init_mmc(unsigned int); static struct platform_device *devices[] __initdata = { + &msm_clock_7x01a, &msm_device_gpio_7201, &msm_device_uart3, &msm_device_smd, @@ -94,8 +95,6 @@ static void __init trout_map_io(void) /* route UART3 to the "H2W" extended usb connector */ writeb(0x80, TROUT_CPLD_BASE + 0x00); #endif - - msm_clock_init(msm_clocks_7x01a, msm_num_clocks_7x01a); } static void __init trout_init_late(void) diff --git a/arch/arm/mach-msm/clock-7x30.h b/arch/arm/mach-msm/clock-7x30.h deleted file mode 100644 index 14104453688b..000000000000 --- a/arch/arm/mach-msm/clock-7x30.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __ARCH_ARM_MACH_MSM_CLOCK_7X30_H -#define __ARCH_ARM_MACH_MSM_CLOCK_7X30_H - -enum { - L_7X30_NONE_CLK = -1, - L_7X30_ADM_CLK, - L_7X30_I2C_CLK, - L_7X30_I2C_2_CLK, - L_7X30_QUP_I2C_CLK, - L_7X30_UART1DM_CLK, - L_7X30_UART1DM_P_CLK, - L_7X30_UART2DM_CLK, - L_7X30_UART2DM_P_CLK, - L_7X30_EMDH_CLK, - L_7X30_EMDH_P_CLK, - L_7X30_PMDH_CLK, - L_7X30_PMDH_P_CLK, - L_7X30_GRP_2D_CLK, - L_7X30_GRP_2D_P_CLK, - L_7X30_GRP_3D_SRC_CLK, - L_7X30_GRP_3D_CLK, - L_7X30_GRP_3D_P_CLK, - L_7X30_IMEM_CLK, - L_7X30_SDC1_CLK, - L_7X30_SDC1_P_CLK, - L_7X30_SDC2_CLK, - L_7X30_SDC2_P_CLK, - L_7X30_SDC3_CLK, - L_7X30_SDC3_P_CLK, - L_7X30_SDC4_CLK, - L_7X30_SDC4_P_CLK, - L_7X30_MDP_CLK, - L_7X30_MDP_P_CLK, - L_7X30_MDP_LCDC_PCLK_CLK, - L_7X30_MDP_LCDC_PAD_PCLK_CLK, - L_7X30_MDP_VSYNC_CLK, - L_7X30_MI2S_CODEC_RX_M_CLK, - L_7X30_MI2S_CODEC_RX_S_CLK, - L_7X30_MI2S_CODEC_TX_M_CLK, - L_7X30_MI2S_CODEC_TX_S_CLK, - L_7X30_MI2S_M_CLK, - L_7X30_MI2S_S_CLK, - L_7X30_LPA_CODEC_CLK, - L_7X30_LPA_CORE_CLK, - L_7X30_LPA_P_CLK, - L_7X30_MIDI_CLK, - L_7X30_MDC_CLK, - L_7X30_ROTATOR_IMEM_CLK, - L_7X30_ROTATOR_P_CLK, - L_7X30_SDAC_M_CLK, - L_7X30_SDAC_CLK, - L_7X30_UART1_CLK, - L_7X30_UART2_CLK, - L_7X30_UART3_CLK, - L_7X30_TV_CLK, - L_7X30_TV_DAC_CLK, - L_7X30_TV_ENC_CLK, - L_7X30_HDMI_CLK, - L_7X30_TSIF_REF_CLK, - L_7X30_TSIF_P_CLK, - L_7X30_USB_HS_SRC_CLK, - L_7X30_USB_HS_CLK, - L_7X30_USB_HS_CORE_CLK, - L_7X30_USB_HS_P_CLK, - L_7X30_USB_HS2_CLK, - L_7X30_USB_HS2_CORE_CLK, - L_7X30_USB_HS2_P_CLK, - L_7X30_USB_HS3_CLK, - L_7X30_USB_HS3_CORE_CLK, - L_7X30_USB_HS3_P_CLK, - L_7X30_VFE_CLK, - L_7X30_VFE_P_CLK, - L_7X30_VFE_MDC_CLK, - L_7X30_VFE_CAMIF_CLK, - L_7X30_CAMIF_PAD_P_CLK, - L_7X30_CAM_M_CLK, - L_7X30_JPEG_CLK, - L_7X30_JPEG_P_CLK, - L_7X30_VPE_CLK, - L_7X30_MFC_CLK, - L_7X30_MFC_DIV2_CLK, - L_7X30_MFC_P_CLK, - L_7X30_SPI_CLK, - L_7X30_SPI_P_CLK, - L_7X30_CSI0_CLK, - L_7X30_CSI0_VFE_CLK, - L_7X30_CSI0_P_CLK, - L_7X30_CSI1_CLK, - L_7X30_CSI1_VFE_CLK, - L_7X30_CSI1_P_CLK, - L_7X30_GLBL_ROOT_CLK, - - L_7X30_AXI_LI_VG_CLK, - L_7X30_AXI_LI_GRP_CLK, - L_7X30_AXI_LI_JPEG_CLK, - L_7X30_AXI_GRP_2D_CLK, - L_7X30_AXI_MFC_CLK, - L_7X30_AXI_VPE_CLK, - L_7X30_AXI_LI_VFE_CLK, - L_7X30_AXI_LI_APPS_CLK, - L_7X30_AXI_MDP_CLK, - L_7X30_AXI_IMEM_CLK, - L_7X30_AXI_LI_ADSP_A_CLK, - L_7X30_AXI_ROTATOR_CLK, - - L_7X30_NR_CLKS -}; - -struct clk_ops; -extern struct clk_ops clk_ops_7x30; - -struct clk_ops *clk_7x30_is_local(uint32_t id); -int clk_7x30_init(void); - -void pll_enable(uint32_t pll); -void pll_disable(uint32_t pll); - -extern int internal_pwr_rail_ctl_auto(unsigned rail_id, bool enable); - -#define CLK_7X30(clk_name, clk_id, clk_dev, clk_flags) { \ - .con_id = clk_name, \ - .dev_id = clk_dev, \ - .clk = &(struct clk){ \ - .id = L_7X30_##clk_id, \ - .remote_id = P_##clk_id, \ - .flags = clk_flags, \ - .dbg_name = #clk_id, \ - }, \ - } - -#define CLK_7X30S(clk_name, l_id, r_id, clk_dev, clk_flags) { \ - .con_id = clk_name, \ - .dev_id = clk_dev, \ - .clk = &(struct clk){ \ - .id = L_7X30_##l_id, \ - .remote_id = P_##r_id, \ - .flags = clk_flags, \ - .dbg_name = #l_id, \ - .ops = &clk_ops_pcom, \ - }, \ - } - -#endif diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c deleted file mode 100644 index b0fbdf1cbdd1..000000000000 --- a/arch/arm/mach-msm/clock-debug.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2007 Google, Inc. - * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/ctype.h> -#include <linux/debugfs.h> -#include <linux/clk.h> -#include "clock.h" - -static int clock_debug_rate_set(void *data, u64 val) -{ - struct clk *clock = data; - int ret; - - /* Only increases to max rate will succeed, but that's actually good - * for debugging purposes so we don't check for error. */ - if (clock->flags & CLK_MAX) - clk_set_max_rate(clock, val); - if (clock->flags & CLK_MIN) - ret = clk_set_min_rate(clock, val); - else - ret = clk_set_rate(clock, val); - if (ret != 0) - printk(KERN_ERR "clk_set%s_rate failed (%d)\n", - (clock->flags & CLK_MIN) ? "_min" : "", ret); - return ret; -} - -static int clock_debug_rate_get(void *data, u64 *val) -{ - struct clk *clock = data; - *val = clk_get_rate(clock); - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_debug_rate_get, - clock_debug_rate_set, "%llu\n"); - -static int clock_debug_enable_set(void *data, u64 val) -{ - struct clk *clock = data; - int rc = 0; - - if (val) - rc = clock->ops->enable(clock->id); - else - clock->ops->disable(clock->id); - - return rc; -} - -static int clock_debug_enable_get(void *data, u64 *val) -{ - struct clk *clock = data; - - *val = clock->ops->is_enabled(clock->id); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(clock_enable_fops, clock_debug_enable_get, - clock_debug_enable_set, "%llu\n"); - -static int clock_debug_local_get(void *data, u64 *val) -{ - struct clk *clock = data; - - *val = clock->ops->is_local(clock->id); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(clock_local_fops, clock_debug_local_get, - NULL, "%llu\n"); - -static struct dentry *debugfs_base; - -int __init clock_debug_init(void) -{ - debugfs_base = debugfs_create_dir("clk", NULL); - if (!debugfs_base) - return -ENOMEM; - return 0; -} - -int __init clock_debug_add(struct clk *clock) -{ - char temp[50], *ptr; - struct dentry *clk_dir; - - if (!debugfs_base) - return -ENOMEM; - - strlcpy(temp, clock->dbg_name, ARRAY_SIZE(temp)); - for (ptr = temp; *ptr; ptr++) - *ptr = tolower(*ptr); - - clk_dir = debugfs_create_dir(temp, debugfs_base); - if (!clk_dir) - return -ENOMEM; - - if (!debugfs_create_file("rate", S_IRUGO | S_IWUSR, clk_dir, - clock, &clock_rate_fops)) - goto error; - - if (!debugfs_create_file("enable", S_IRUGO | S_IWUSR, clk_dir, - clock, &clock_enable_fops)) - goto error; - - if (!debugfs_create_file("is_local", S_IRUGO, clk_dir, clock, - &clock_local_fops)) - goto error; - return 0; -error: - debugfs_remove_recursive(clk_dir); - return -ENOMEM; -} diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c index a52c970df157..9a80449518e6 100644 --- a/arch/arm/mach-msm/clock-pcom.c +++ b/arch/arm/mach-msm/clock-pcom.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Google, Inc. - * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. + * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -13,20 +13,33 @@ * */ +#include <linux/kernel.h> #include <linux/err.h> -#include <linux/ctype.h> -#include <linux/stddef.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/clk-provider.h> +#include <linux/clkdev.h> + #include <mach/clk.h> #include "proc_comm.h" #include "clock.h" #include "clock-pcom.h" -/* - * glue for the proc_comm interface - */ -static int pc_clk_enable(unsigned id) +struct clk_pcom { + unsigned id; + unsigned long flags; + struct msm_clk msm_clk; +}; + +static inline struct clk_pcom *to_clk_pcom(struct clk_hw *hw) { + return container_of(to_msm_clk(hw), struct clk_pcom, msm_clk); +} + +static int pc_clk_enable(struct clk_hw *hw) +{ + unsigned id = to_clk_pcom(hw)->id; int rc = msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL); if (rc < 0) return rc; @@ -34,14 +47,16 @@ static int pc_clk_enable(unsigned id) return (int)id < 0 ? -EINVAL : 0; } -static void pc_clk_disable(unsigned id) +static void pc_clk_disable(struct clk_hw *hw) { + unsigned id = to_clk_pcom(hw)->id; msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL); } -int pc_clk_reset(unsigned id, enum clk_reset_action action) +static int pc_clk_reset(struct clk_hw *hw, enum clk_reset_action action) { int rc; + unsigned id = to_clk_pcom(hw)->id; if (action == CLK_RESET_ASSERT) rc = msm_proc_comm(PCOM_CLKCTL_RPC_RESET_ASSERT, &id, NULL); @@ -54,85 +69,109 @@ int pc_clk_reset(unsigned id, enum clk_reset_action action) return (int)id < 0 ? -EINVAL : 0; } -static int pc_clk_set_rate(unsigned id, unsigned rate) +static int pc_clk_set_rate(struct clk_hw *hw, unsigned long new_rate, + unsigned long p_rate) { - /* The rate _might_ be rounded off to the nearest KHz value by the + struct clk_pcom *p = to_clk_pcom(hw); + unsigned id = p->id, rate = new_rate; + int rc; + + /* + * The rate _might_ be rounded off to the nearest KHz value by the * remote function. So a return value of 0 doesn't necessarily mean * that the exact rate was set successfully. */ - int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate); - if (rc < 0) - return rc; - else - return (int)id < 0 ? -EINVAL : 0; -} - -static int pc_clk_set_min_rate(unsigned id, unsigned rate) -{ - int rc = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate); - if (rc < 0) - return rc; - else - return (int)id < 0 ? -EINVAL : 0; -} - -static int pc_clk_set_max_rate(unsigned id, unsigned rate) -{ - int rc = msm_proc_comm(PCOM_CLKCTL_RPC_MAX_RATE, &id, &rate); - if (rc < 0) - return rc; + if (p->flags & CLKFLAG_MIN) + rc = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate); else - return (int)id < 0 ? -EINVAL : 0; -} - -static int pc_clk_set_flags(unsigned id, unsigned flags) -{ - int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_FLAGS, &id, &flags); + rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate); if (rc < 0) return rc; else return (int)id < 0 ? -EINVAL : 0; } -static unsigned pc_clk_get_rate(unsigned id) +static unsigned long pc_clk_recalc_rate(struct clk_hw *hw, unsigned long p_rate) { + unsigned id = to_clk_pcom(hw)->id; if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, NULL)) return 0; else return id; } -static unsigned pc_clk_is_enabled(unsigned id) +static int pc_clk_is_enabled(struct clk_hw *hw) { + unsigned id = to_clk_pcom(hw)->id; if (msm_proc_comm(PCOM_CLKCTL_RPC_ENABLED, &id, NULL)) return 0; else return id; } -static long pc_clk_round_rate(unsigned id, unsigned rate) +static long pc_clk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *p_rate) { - /* Not really supported; pc_clk_set_rate() does rounding on it's own. */ return rate; } -static bool pc_clk_is_local(unsigned id) -{ - return false; -} - -struct clk_ops clk_ops_pcom = { +static struct clk_ops clk_ops_pcom = { .enable = pc_clk_enable, .disable = pc_clk_disable, - .auto_off = pc_clk_disable, - .reset = pc_clk_reset, .set_rate = pc_clk_set_rate, - .set_min_rate = pc_clk_set_min_rate, - .set_max_rate = pc_clk_set_max_rate, - .set_flags = pc_clk_set_flags, - .get_rate = pc_clk_get_rate, + .recalc_rate = pc_clk_recalc_rate, .is_enabled = pc_clk_is_enabled, .round_rate = pc_clk_round_rate, - .is_local = pc_clk_is_local, }; + +static int msm_clock_pcom_probe(struct platform_device *pdev) +{ + const struct pcom_clk_pdata *pdata = pdev->dev.platform_data; + int i, ret; + + for (i = 0; i < pdata->num_lookups; i++) { + const struct clk_pcom_desc *desc = &pdata->lookup[i]; + struct clk *c; + struct clk_pcom *p; + struct clk_hw *hw; + struct clk_init_data init; + + p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + + p->id = desc->id; + p->flags = desc->flags; + p->msm_clk.reset = pc_clk_reset; + + hw = &p->msm_clk.hw; + hw->init = &init; + + init.name = desc->name; + init.ops = &clk_ops_pcom; + init.num_parents = 0; + init.flags = CLK_IS_ROOT; + + if (!(p->flags & CLKFLAG_AUTO_OFF)) + init.flags |= CLK_IGNORE_UNUSED; + + c = devm_clk_register(&pdev->dev, hw); + ret = clk_register_clkdev(c, desc->con, desc->dev); + if (ret) + return ret; + } + + return 0; +} + +static struct platform_driver msm_clock_pcom_driver = { + .probe = msm_clock_pcom_probe, + .driver = { + .name = "msm-clock-pcom", + .owner = THIS_MODULE, + }, +}; +module_platform_driver(msm_clock_pcom_driver); + +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/mach-msm/clock-pcom.h b/arch/arm/mach-msm/clock-pcom.h index 974d0032f3a3..5bb164fd46a8 100644 --- a/arch/arm/mach-msm/clock-pcom.h +++ b/arch/arm/mach-msm/clock-pcom.h @@ -1,4 +1,5 @@ -/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. +/* + * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -120,21 +121,25 @@ #define P_NR_CLKS 102 -struct clk_ops; -extern struct clk_ops clk_ops_pcom; +struct clk_pcom_desc { + unsigned id; + const char *name; + const char *con; + const char *dev; + unsigned long flags; +}; -int pc_clk_reset(unsigned id, enum clk_reset_action action); +struct pcom_clk_pdata { + struct clk_pcom_desc *lookup; + u32 num_lookups; +}; #define CLK_PCOM(clk_name, clk_id, clk_dev, clk_flags) { \ - .con_id = clk_name, \ - .dev_id = clk_dev, \ - .clk = &(struct clk){ \ - .id = P_##clk_id, \ - .remote_id = P_##clk_id, \ - .ops = &clk_ops_pcom, \ - .flags = clk_flags, \ - .dbg_name = #clk_id, \ - }, \ + .id = P_##clk_id, \ + .name = #clk_id, \ + .con = clk_name, \ + .dev = clk_dev, \ + .flags = clk_flags, \ } #endif diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c index d9145dfc2a3b..35ea02b52483 100644 --- a/arch/arm/mach-msm/clock.c +++ b/arch/arm/mach-msm/clock.c @@ -1,7 +1,7 @@ /* arch/arm/mach-msm/clock.c * * Copyright (C) 2007 Google, Inc. - * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. + * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -14,171 +14,15 @@ * */ -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/err.h> -#include <linux/spinlock.h> -#include <linux/pm_qos.h> -#include <linux/mutex.h> -#include <linux/clk.h> -#include <linux/string.h> +#include <linux/clk-provider.h> #include <linux/module.h> -#include <linux/clkdev.h> #include "clock.h" -static DEFINE_MUTEX(clocks_mutex); -static DEFINE_SPINLOCK(clocks_lock); -static LIST_HEAD(clocks); - -/* - * Standard clock functions defined in include/linux/clk.h - */ -int clk_enable(struct clk *clk) -{ - unsigned long flags; - spin_lock_irqsave(&clocks_lock, flags); - clk->count++; - if (clk->count == 1) - clk->ops->enable(clk->id); - spin_unlock_irqrestore(&clocks_lock, flags); - return 0; -} -EXPORT_SYMBOL(clk_enable); - -void clk_disable(struct clk *clk) -{ - unsigned long flags; - spin_lock_irqsave(&clocks_lock, flags); - BUG_ON(clk->count == 0); - clk->count--; - if (clk->count == 0) - clk->ops->disable(clk->id); - spin_unlock_irqrestore(&clocks_lock, flags); -} -EXPORT_SYMBOL(clk_disable); - int clk_reset(struct clk *clk, enum clk_reset_action action) { - return clk->ops->reset(clk->remote_id, action); + struct clk_hw *hw = __clk_get_hw(clk); + struct msm_clk *m = to_msm_clk(hw); + return m->reset(hw, action); } EXPORT_SYMBOL(clk_reset); - -unsigned long clk_get_rate(struct clk *clk) -{ - return clk->ops->get_rate(clk->id); -} -EXPORT_SYMBOL(clk_get_rate); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - int ret; - if (clk->flags & CLKFLAG_MAX) { - ret = clk->ops->set_max_rate(clk->id, rate); - if (ret) - return ret; - } - if (clk->flags & CLKFLAG_MIN) { - ret = clk->ops->set_min_rate(clk->id, rate); - if (ret) - return ret; - } - - if (clk->flags & CLKFLAG_MAX || clk->flags & CLKFLAG_MIN) - return ret; - - return clk->ops->set_rate(clk->id, rate); -} -EXPORT_SYMBOL(clk_set_rate); - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - return clk->ops->round_rate(clk->id, rate); -} -EXPORT_SYMBOL(clk_round_rate); - -int clk_set_min_rate(struct clk *clk, unsigned long rate) -{ - return clk->ops->set_min_rate(clk->id, rate); -} -EXPORT_SYMBOL(clk_set_min_rate); - -int clk_set_max_rate(struct clk *clk, unsigned long rate) -{ - return clk->ops->set_max_rate(clk->id, rate); -} -EXPORT_SYMBOL(clk_set_max_rate); - -int clk_set_parent(struct clk *clk, struct clk *parent) -{ - return -ENOSYS; -} -EXPORT_SYMBOL(clk_set_parent); - -struct clk *clk_get_parent(struct clk *clk) -{ - return ERR_PTR(-ENOSYS); -} -EXPORT_SYMBOL(clk_get_parent); - -int clk_set_flags(struct clk *clk, unsigned long flags) -{ - if (clk == NULL || IS_ERR(clk)) - return -EINVAL; - return clk->ops->set_flags(clk->id, flags); -} -EXPORT_SYMBOL(clk_set_flags); - -/* EBI1 is the only shared clock that several clients want to vote on as of - * this commit. If this changes in the future, then it might be better to - * make clk_min_rate handle the voting or make ebi1_clk_set_min_rate more - * generic to support different clocks. - */ -static struct clk *ebi1_clk; - -void __init msm_clock_init(struct clk_lookup *clock_tbl, unsigned num_clocks) -{ - unsigned n; - - mutex_lock(&clocks_mutex); - for (n = 0; n < num_clocks; n++) { - clkdev_add(&clock_tbl[n]); - list_add_tail(&clock_tbl[n].clk->list, &clocks); - } - mutex_unlock(&clocks_mutex); - - ebi1_clk = clk_get(NULL, "ebi1_clk"); - BUG_ON(ebi1_clk == NULL); - -} - -/* The bootloader and/or AMSS may have left various clocks enabled. - * Disable any clocks that belong to us (CLKFLAG_AUTO_OFF) but have - * not been explicitly enabled by a clk_enable() call. - */ -static int __init clock_late_init(void) -{ - unsigned long flags; - struct clk *clk; - unsigned count = 0; - - clock_debug_init(); - mutex_lock(&clocks_mutex); - list_for_each_entry(clk, &clocks, list) { - clock_debug_add(clk); - if (clk->flags & CLKFLAG_AUTO_OFF) { - spin_lock_irqsave(&clocks_lock, flags); - if (!clk->count) { - count++; - clk->ops->auto_off(clk->id); - } - spin_unlock_irqrestore(&clocks_lock, flags); - } - } - mutex_unlock(&clocks_mutex); - pr_info("clock_late_init() disabled %d unused clocks\n", count); - return 0; -} - -late_initcall(clock_late_init); - diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h index 2c007f606d29..42d29dd7aafc 100644 --- a/arch/arm/mach-msm/clock.h +++ b/arch/arm/mach-msm/clock.h @@ -1,7 +1,7 @@ /* arch/arm/mach-msm/clock.h * * Copyright (C) 2007 Google, Inc. - * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. + * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -17,56 +17,27 @@ #ifndef __ARCH_ARM_MACH_MSM_CLOCK_H #define __ARCH_ARM_MACH_MSM_CLOCK_H -#include <linux/init.h> -#include <linux/list.h> +#include <linux/clk-provider.h> #include <mach/clk.h> -#define CLKFLAG_INVERT 0x00000001 -#define CLKFLAG_NOINVERT 0x00000002 -#define CLKFLAG_NONEST 0x00000004 -#define CLKFLAG_NORESET 0x00000008 - #define CLK_FIRST_AVAILABLE_FLAG 0x00000100 #define CLKFLAG_AUTO_OFF 0x00000200 #define CLKFLAG_MIN 0x00000400 #define CLKFLAG_MAX 0x00000800 -struct clk_ops { - int (*enable)(unsigned id); - void (*disable)(unsigned id); - void (*auto_off)(unsigned id); - int (*reset)(unsigned id, enum clk_reset_action action); - int (*set_rate)(unsigned id, unsigned rate); - int (*set_min_rate)(unsigned id, unsigned rate); - int (*set_max_rate)(unsigned id, unsigned rate); - int (*set_flags)(unsigned id, unsigned flags); - unsigned (*get_rate)(unsigned id); - unsigned (*is_enabled)(unsigned id); - long (*round_rate)(unsigned id, unsigned rate); - bool (*is_local)(unsigned id); -}; - -struct clk { - uint32_t id; - uint32_t remote_id; - uint32_t count; - uint32_t flags; - struct clk_ops *ops; - const char *dbg_name; - struct list_head list; -}; - #define OFF CLKFLAG_AUTO_OFF #define CLK_MIN CLKFLAG_MIN #define CLK_MAX CLKFLAG_MAX #define CLK_MINMAX (CLK_MIN | CLK_MAX) -#ifdef CONFIG_DEBUG_FS -int __init clock_debug_init(void); -int __init clock_debug_add(struct clk *clock); -#else -static inline int __init clock_debug_init(void) { return 0; } -static inline int __init clock_debug_add(struct clk *clock) { return 0; } -#endif +struct msm_clk { + int (*reset)(struct clk_hw *hw, enum clk_reset_action action); + struct clk_hw hw; +}; + +static inline struct msm_clk *to_msm_clk(struct clk_hw *hw) +{ + return container_of(hw, struct msm_clk, hw); +} #endif diff --git a/arch/arm/mach-msm/devices-msm7x00.c b/arch/arm/mach-msm/devices-msm7x00.c index 1a0a2306b115..6d50fb964863 100644 --- a/arch/arm/mach-msm/devices-msm7x00.c +++ b/arch/arm/mach-msm/devices-msm7x00.c @@ -425,7 +425,7 @@ struct platform_device msm_device_mdp = { .resource = resources_mdp, }; -struct clk_lookup msm_clocks_7x01a[] = { +static struct clk_pcom_desc msm_clocks_7x01a[] = { CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0), CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, 0), @@ -469,4 +469,12 @@ struct clk_lookup msm_clocks_7x01a[] = { CLK_PCOM("vfe_mdc_clk", VFE_MDC_CLK, NULL, OFF), }; -unsigned msm_num_clocks_7x01a = ARRAY_SIZE(msm_clocks_7x01a); +static struct pcom_clk_pdata msm_clock_7x01a_pdata = { + .lookup = msm_clocks_7x01a, + .num_lookups = ARRAY_SIZE(msm_clocks_7x01a), +}; + +struct platform_device msm_clock_7x01a = { + .name = "msm-clock-pcom", + .dev.platform_data = &msm_clock_7x01a_pdata, +}; diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c index 12f482c07740..d4db75acff56 100644 --- a/arch/arm/mach-msm/devices-msm7x30.c +++ b/arch/arm/mach-msm/devices-msm7x30.c @@ -28,8 +28,8 @@ #include <asm/mach/flash.h> +#include "clock.h" #include "clock-pcom.h" -#include "clock-7x30.h" #include <linux/platform_data/mmc-msm_sdcc.h> @@ -161,7 +161,7 @@ struct platform_device msm_device_hsusb_host = { }, }; -struct clk_lookup msm_clocks_7x30[] = { +static struct clk_pcom_desc msm_clocks_7x30[] = { CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0), CLK_PCOM("cam_m_clk", CAM_M_CLK, NULL, 0), @@ -177,7 +177,6 @@ struct clk_lookup msm_clocks_7x30[] = { CLK_PCOM("grp_2d_pclk", GRP_2D_P_CLK, NULL, 0), CLK_PCOM("grp_clk", GRP_3D_CLK, NULL, 0), CLK_PCOM("grp_pclk", GRP_3D_P_CLK, NULL, 0), - CLK_7X30S("grp_src_clk", GRP_3D_SRC_CLK, GRP_3D_CLK, NULL, 0), CLK_PCOM("hdmi_clk", HDMI_CLK, NULL, 0), CLK_PCOM("imem_clk", IMEM_CLK, NULL, OFF), CLK_PCOM("jpeg_clk", JPEG_CLK, NULL, OFF), @@ -210,7 +209,6 @@ struct clk_lookup msm_clocks_7x30[] = { CLK_PCOM("sdac_clk", SDAC_CLK, NULL, OFF), CLK_PCOM("spi_clk", SPI_CLK, NULL, 0), CLK_PCOM("spi_pclk", SPI_P_CLK, NULL, 0), - CLK_7X30S("tv_src_clk", TV_CLK, TV_ENC_CLK, NULL, 0), CLK_PCOM("tv_dac_clk", TV_DAC_CLK, NULL, 0), CLK_PCOM("tv_enc_clk", TV_ENC_CLK, NULL, 0), CLK_PCOM("uart_clk", UART2_CLK, "msm_serial.1", 0), @@ -237,5 +235,12 @@ struct clk_lookup msm_clocks_7x30[] = { CLK_PCOM("csi_vfe_clk", CSI0_VFE_CLK, NULL, 0), }; -unsigned msm_num_clocks_7x30 = ARRAY_SIZE(msm_clocks_7x30); +static struct pcom_clk_pdata msm_clock_7x30_pdata = { + .lookup = msm_clocks_7x30, + .num_lookups = ARRAY_SIZE(msm_clocks_7x30), +}; +struct platform_device msm_clock_7x30 = { + .name = "msm-clock-pcom", + .dev.platform_data = &msm_clock_7x30_pdata, +}; diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c index 2e1b3ec9dfc7..f5518112284b 100644 --- a/arch/arm/mach-msm/devices-qsd8x50.c +++ b/arch/arm/mach-msm/devices-qsd8x50.c @@ -28,6 +28,7 @@ #include <asm/mach/flash.h> #include <linux/platform_data/mmc-msm_sdcc.h> +#include "clock.h" #include "clock-pcom.h" static struct resource msm_gpio_resources[] = { @@ -322,7 +323,7 @@ int __init msm_add_sdcc(unsigned int controller, return platform_device_register(pdev); } -struct clk_lookup msm_clocks_8x50[] = { +static struct clk_pcom_desc msm_clocks_8x50[] = { CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), CLK_PCOM("ce_clk", CE_CLK, NULL, 0), CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN), @@ -376,5 +377,12 @@ struct clk_lookup msm_clocks_8x50[] = { CLK_PCOM("usb_phy_clk", USB_PHY_CLK, NULL, 0), }; -unsigned msm_num_clocks_8x50 = ARRAY_SIZE(msm_clocks_8x50); +static struct pcom_clk_pdata msm_clock_8x50_pdata = { + .lookup = msm_clocks_8x50, + .num_lookups = ARRAY_SIZE(msm_clocks_8x50), +}; +struct platform_device msm_clock_8x50 = { + .name = "msm-clock-pcom", + .dev.platform_data = &msm_clock_8x50_pdata, +}; diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h index da902cf51161..dccefad9f9b9 100644 --- a/arch/arm/mach-msm/devices.h +++ b/arch/arm/mach-msm/devices.h @@ -16,10 +16,6 @@ #ifndef __ARCH_ARM_MACH_MSM_DEVICES_H #define __ARCH_ARM_MACH_MSM_DEVICES_H -#include <linux/clkdev.h> - -#include "clock.h" - extern struct platform_device msm_device_gpio_7201; extern struct platform_device msm_device_gpio_7x30; extern struct platform_device msm_device_gpio_8x50; @@ -50,13 +46,8 @@ extern struct platform_device msm_device_mddi0; extern struct platform_device msm_device_mddi1; extern struct platform_device msm_device_mdp; -extern struct clk_lookup msm_clocks_7x01a[]; -extern unsigned msm_num_clocks_7x01a; - -extern struct clk_lookup msm_clocks_7x30[]; -extern unsigned msm_num_clocks_7x30; - -extern struct clk_lookup msm_clocks_8x50[]; -extern unsigned msm_num_clocks_8x50; +extern struct platform_device msm_clock_7x01a; +extern struct platform_device msm_clock_7x30; +extern struct platform_device msm_clock_8x50; #endif diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c index b279fd8a31b1..f8f6adfa07c6 100644 --- a/arch/arm/mach-msm/dma.c +++ b/arch/arm/mach-msm/dma.c @@ -284,6 +284,7 @@ static int __init msm_init_datamover(void) clk = clk_get(NULL, "adm_clk"); if (IS_ERR(clk)) return PTR_ERR(clk); + clk_prepare(clk); msm_dmov_clk = clk; ret = request_irq(INT_ADM_AARM, msm_datamover_irq_handler, 0, "msmdatamover", NULL); if (ret) @@ -291,6 +292,4 @@ static int __init msm_init_datamover(void) disable_irq(INT_ADM_AARM); return 0; } - -arch_initcall(msm_init_datamover); - +module_init(msm_init_datamover); diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h index 8cebedb11233..c34e246a3e07 100644 --- a/arch/arm/mach-msm/include/mach/board.h +++ b/arch/arm/mach-msm/include/mach/board.h @@ -20,16 +20,11 @@ #include <linux/types.h> #include <linux/platform_data/mmc-msm_sdcc.h> -/* platform device data structures */ - -struct clk_lookup; - /* common init routines for use by arch/arm/mach-msm/board-*.c */ void __init msm_add_devices(void); void __init msm_init_irq(void); void __init msm_init_gpio(void); -void __init msm_clock_init(struct clk_lookup *clock_tbl, unsigned num_clocks); int __init msm_add_sdcc(unsigned int controller, struct msm_mmc_platform_data *plat, unsigned int stat_irq, unsigned long stat_irq_flags); diff --git a/arch/arm/mach-msm/include/mach/clk.h b/arch/arm/mach-msm/include/mach/clk.h index e8d38428d813..fd4f4a7a83b3 100644 --- a/arch/arm/mach-msm/include/mach/clk.h +++ b/arch/arm/mach-msm/include/mach/clk.h @@ -25,16 +25,7 @@ enum clk_reset_action { struct clk; -/* Rate is minimum clock rate in Hz */ -int clk_set_min_rate(struct clk *clk, unsigned long rate); - -/* Rate is maximum clock rate in Hz */ -int clk_set_max_rate(struct clk *clk, unsigned long rate); - /* Assert/Deassert reset to a hardware block associated with a clock */ int clk_reset(struct clk *clk, enum clk_reset_action action); -/* Set clock-specific configuration parameters */ -int clk_set_flags(struct clk *clk, unsigned long flags); - #endif diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c index 8e8fb079852d..9144a6beed92 100644 --- a/drivers/iommu/msm_iommu_dev.c +++ b/drivers/iommu/msm_iommu_dev.c @@ -29,7 +29,6 @@ #include <mach/iommu_hw-8xxx.h> #include <mach/iommu.h> -#include <mach/clk.h> struct iommu_ctx_iter_data { /* input */ @@ -160,7 +159,7 @@ static int msm_iommu_probe(struct platform_device *pdev) goto fail; } - ret = clk_enable(iommu_pclk); + ret = clk_prepare_enable(iommu_pclk); if (ret) goto fail_enable; @@ -168,9 +167,9 @@ static int msm_iommu_probe(struct platform_device *pdev) if (!IS_ERR(iommu_clk)) { if (clk_get_rate(iommu_clk) == 0) - clk_set_min_rate(iommu_clk, 1); + clk_set_rate(iommu_clk, 1); - ret = clk_enable(iommu_clk); + ret = clk_prepare_enable(iommu_clk); if (ret) { clk_put(iommu_clk); goto fail_pclk; @@ -261,7 +260,7 @@ fail_clk: clk_put(iommu_clk); } fail_pclk: - clk_disable(iommu_pclk); + clk_disable_unprepare(iommu_pclk); fail_enable: clk_put(iommu_pclk); fail: @@ -275,8 +274,11 @@ static int msm_iommu_remove(struct platform_device *pdev) drv = platform_get_drvdata(pdev); if (drv) { - if (drv->clk) + if (drv->clk) { + clk_unprepare(drv->clk); clk_put(drv->clk); + } + clk_unprepare(drv->pclk); clk_put(drv->pclk); memset(drv, 0, sizeof(*drv)); kfree(drv); @@ -314,14 +316,14 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev) INIT_LIST_HEAD(&ctx_drvdata->attached_elm); platform_set_drvdata(pdev, ctx_drvdata); - ret = clk_enable(drvdata->pclk); + ret = clk_prepare_enable(drvdata->pclk); if (ret) goto fail; if (drvdata->clk) { - ret = clk_enable(drvdata->clk); + ret = clk_prepare_enable(drvdata->clk); if (ret) { - clk_disable(drvdata->pclk); + clk_disable_unprepare(drvdata->pclk); goto fail; } } diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index 0ee4a57fe6b2..b900de4e7e94 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c @@ -1268,10 +1268,18 @@ msmsdcc_probe(struct platform_device *pdev) goto clk_put; } + ret = clk_prepare(host->pclk); + if (ret) + goto clk_put; + + ret = clk_prepare(host->clk); + if (ret) + goto clk_unprepare_p; + /* Enable clocks */ ret = msmsdcc_enable_clocks(host); if (ret) - goto clk_put; + goto clk_unprepare; host->pclk_rate = clk_get_rate(host->pclk); host->clk_rate = clk_get_rate(host->clk); @@ -1386,6 +1394,10 @@ msmsdcc_probe(struct platform_device *pdev) free_irq(host->stat_irq, host); clk_disable: msmsdcc_disable_clocks(host, 0); + clk_unprepare: + clk_unprepare(host->clk); + clk_unprepare_p: + clk_unprepare(host->pclk); clk_put: clk_put(host->clk); pclk_put: diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index b11e99797fd8..2c6cfb3cf032 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -408,9 +408,9 @@ static void msm_init_clock(struct uart_port *port) { struct msm_port *msm_port = UART_TO_MSM(port); - clk_enable(msm_port->clk); + clk_prepare_enable(msm_port->clk); if (!IS_ERR(msm_port->pclk)) - clk_enable(msm_port->pclk); + clk_prepare_enable(msm_port->pclk); msm_serial_set_mnd_regs(port); } @@ -486,7 +486,7 @@ static void msm_shutdown(struct uart_port *port) msm_port->imr = 0; msm_write(port, 0, UART_IMR); /* disable interrupts */ - clk_disable(msm_port->clk); + clk_disable_unprepare(msm_port->clk); free_irq(port->irq, port); } @@ -688,14 +688,14 @@ static void msm_power(struct uart_port *port, unsigned int state, switch (state) { case 0: - clk_enable(msm_port->clk); + clk_prepare_enable(msm_port->clk); if (!IS_ERR(msm_port->pclk)) - clk_enable(msm_port->pclk); + clk_prepare_enable(msm_port->pclk); break; case 3: - clk_disable(msm_port->clk); + clk_disable_unprepare(msm_port->clk); if (!IS_ERR(msm_port->pclk)) - clk_disable(msm_port->pclk); + clk_disable_unprepare(msm_port->pclk); break; default: printk(KERN_ERR "msm_serial: Unknown PM state %d\n", state); @@ -884,19 +884,22 @@ static int __init msm_serial_probe(struct platform_device *pdev) msm_port->is_uartdm = 0; if (msm_port->is_uartdm) { - msm_port->clk = clk_get(&pdev->dev, "gsbi_uart_clk"); - msm_port->pclk = clk_get(&pdev->dev, "gsbi_pclk"); + msm_port->clk = devm_clk_get(&pdev->dev, "gsbi_uart_clk"); + msm_port->pclk = devm_clk_get(&pdev->dev, "gsbi_pclk"); } else { - msm_port->clk = clk_get(&pdev->dev, "uart_clk"); + msm_port->clk = devm_clk_get(&pdev->dev, "uart_clk"); msm_port->pclk = ERR_PTR(-ENOENT); } - if (unlikely(IS_ERR(msm_port->clk) || (IS_ERR(msm_port->pclk) && - msm_port->is_uartdm))) - return PTR_ERR(msm_port->clk); + if (IS_ERR(msm_port->clk)) + return PTR_ERR(msm_port->clk); + + if (msm_port->is_uartdm) { + if (IS_ERR(msm_port->pclk)) + return PTR_ERR(msm_port->pclk); - if (msm_port->is_uartdm) clk_set_rate(msm_port->clk, 1843200); + } port->uartclk = clk_get_rate(msm_port->clk); printk(KERN_INFO "uartclk = %d\n", port->uartclk); @@ -919,9 +922,9 @@ static int __init msm_serial_probe(struct platform_device *pdev) static int msm_serial_remove(struct platform_device *pdev) { - struct msm_port *msm_port = platform_get_drvdata(pdev); + struct uart_port *port = platform_get_drvdata(pdev); - clk_put(msm_port->clk); + uart_remove_one_port(&msm_uart_driver, port); return 0; } diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 749fbf41fb6f..d08f33435e96 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -514,13 +514,13 @@ static int msm_otg_suspend(struct msm_otg *motg) motg->pdata->otg_control == OTG_PMIC_CONTROL) writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL); - clk_disable(motg->pclk); - clk_disable(motg->clk); + clk_disable_unprepare(motg->pclk); + clk_disable_unprepare(motg->clk); if (motg->core_clk) - clk_disable(motg->core_clk); + clk_disable_unprepare(motg->core_clk); if (!IS_ERR(motg->pclk_src)) - clk_disable(motg->pclk_src); + clk_disable_unprepare(motg->pclk_src); if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY && motg->pdata->otg_control == OTG_PMIC_CONTROL) { @@ -552,12 +552,12 @@ static int msm_otg_resume(struct msm_otg *motg) return 0; if (!IS_ERR(motg->pclk_src)) - clk_enable(motg->pclk_src); + clk_prepare_enable(motg->pclk_src); - clk_enable(motg->pclk); - clk_enable(motg->clk); + clk_prepare_enable(motg->pclk); + clk_prepare_enable(motg->clk); if (motg->core_clk) - clk_enable(motg->core_clk); + clk_prepare_enable(motg->core_clk); if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY && motg->pdata->otg_control == OTG_PMIC_CONTROL) { @@ -1468,7 +1468,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) if (IS_ERR(motg->pclk_src)) goto put_clk; clk_set_rate(motg->pclk_src, INT_MAX); - clk_enable(motg->pclk_src); + clk_prepare_enable(motg->pclk_src); } else motg->pclk_src = ERR_PTR(-ENOENT); @@ -1511,8 +1511,8 @@ static int __init msm_otg_probe(struct platform_device *pdev) goto free_regs; } - clk_enable(motg->clk); - clk_enable(motg->pclk); + clk_prepare_enable(motg->clk); + clk_prepare_enable(motg->pclk); ret = msm_hsusb_init_vddcx(motg, 1); if (ret) { @@ -1532,7 +1532,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) } if (motg->core_clk) - clk_enable(motg->core_clk); + clk_prepare_enable(motg->core_clk); writel(0, USB_USBINTR); writel(0, USB_OTGSC); @@ -1579,8 +1579,8 @@ static int __init msm_otg_probe(struct platform_device *pdev) free_irq: free_irq(motg->irq, motg); disable_clks: - clk_disable(motg->pclk); - clk_disable(motg->clk); + clk_disable_unprepare(motg->pclk); + clk_disable_unprepare(motg->clk); ldo_exit: msm_hsusb_ldo_init(motg, 0); vddcx_exit: @@ -1593,7 +1593,7 @@ put_core_clk: clk_put(motg->pclk); put_pclk_src: if (!IS_ERR(motg->pclk_src)) { - clk_disable(motg->pclk_src); + clk_disable_unprepare(motg->pclk_src); clk_put(motg->pclk_src); } put_clk: @@ -1643,12 +1643,12 @@ static int msm_otg_remove(struct platform_device *pdev) if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) dev_err(phy->dev, "Unable to suspend PHY\n"); - clk_disable(motg->pclk); - clk_disable(motg->clk); + clk_disable_unprepare(motg->pclk); + clk_disable_unprepare(motg->clk); if (motg->core_clk) - clk_disable(motg->core_clk); + clk_disable_unprepare(motg->core_clk); if (!IS_ERR(motg->pclk_src)) { - clk_disable(motg->pclk_src); + clk_disable_unprepare(motg->pclk_src); clk_put(motg->pclk_src); } msm_hsusb_ldo_init(motg, 0); |