blob: 34952fbd6778d50eb6751b59442e6172fa61df5a [file] [log] [blame]
Tianyi Gou7395a7e2012-10-19 14:12:21 -07001/*
Patrick Daly985c14b2012-12-03 17:12:37 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Tianyi Gou7395a7e2012-10-19 14:12:21 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#define pr_fmt(fmt) "%s: " fmt, __func__
15
16#include <linux/kernel.h>
17#include <linux/module.h>
Tianyi Gou7395a7e2012-10-19 14:12:21 -070018#include <linux/io.h>
Tianyi Gou7395a7e2012-10-19 14:12:21 -070019#include <linux/errno.h>
Tianyi Gou7395a7e2012-10-19 14:12:21 -070020#include <linux/platform_device.h>
Patrick Daly985c14b2012-12-03 17:12:37 -080021#include <linux/regulator/consumer.h>
Tianyi Gou7395a7e2012-10-19 14:12:21 -070022
Tianyi Gou7395a7e2012-10-19 14:12:21 -070023#include <mach/msm_bus.h>
24#include <mach/msm_bus_board.h>
Tianyi Gou7395a7e2012-10-19 14:12:21 -070025#include <mach/clk-provider.h>
26#include <mach/rpm-regulator-smd.h>
27
Patrick Daly985c14b2012-12-03 17:12:37 -080028#include "acpuclock-cortex.h"
Tianyi Gou7395a7e2012-10-19 14:12:21 -070029
Tianyi Gou7395a7e2012-10-19 14:12:21 -070030#define RCG_CONFIG_PGM_DATA_BIT BIT(11)
31#define RCG_CONFIG_PGM_ENA_BIT BIT(10)
Tianyi Gou7395a7e2012-10-19 14:12:21 -070032#define GPLL0_TO_A5_ALWAYS_ENABLE BIT(18)
33
Tianyi Gou7395a7e2012-10-19 14:12:21 -070034static struct msm_bus_paths bw_level_tbl[] = {
35 [0] = BW_MBPS(152), /* At least 19 MHz on bus. */
36 [1] = BW_MBPS(264), /* At least 33 MHz on bus. */
37 [2] = BW_MBPS(528), /* At least 66 MHz on bus. */
38 [3] = BW_MBPS(664), /* At least 83 MHz on bus. */
39 [4] = BW_MBPS(1064), /* At least 133 MHz on bus. */
40 [5] = BW_MBPS(1328), /* At least 166 MHz on bus. */
41 [6] = BW_MBPS(2128), /* At least 266 MHz on bus. */
42 [7] = BW_MBPS(2664), /* At least 333 MHz on bus. */
43};
44
45static struct msm_bus_scale_pdata bus_client_pdata = {
46 .usecase = bw_level_tbl,
47 .num_usecases = ARRAY_SIZE(bw_level_tbl),
48 .active_only = 1,
49 .name = "acpuclock",
50};
51
Tianyi Gou7395a7e2012-10-19 14:12:21 -070052/* TODO:
53 * 1) Update MX voltage when they are avaiable
54 * 2) Update bus bandwidth
55 */
56static struct clkctl_acpu_speed acpu_freq_tbl[] = {
57 { 0, 19200, CXO, 0, 0, LVL_LOW, 950000, 0 },
58 { 1, 300000, PLL0, 1, 2, LVL_LOW, 950000, 4 },
59 { 1, 600000, PLL0, 1, 0, LVL_NOM, 950000, 4 },
60 { 1, 748800, ACPUPLL, 5, 0, LVL_HIGH, 1050000, 7 },
61 { 1, 998400, ACPUPLL, 5, 0, LVL_HIGH, 1050000, 7 },
62 { 0 }
63};
64
Patrick Daly985c14b2012-12-03 17:12:37 -080065static struct acpuclk_drv_data drv_data = {
66 .freq_tbl = acpu_freq_tbl,
67 .current_speed = &(struct clkctl_acpu_speed){ 0 },
68 .bus_scale = &bus_client_pdata,
69 .vdd_max_cpu = LVL_HIGH,
70 .vdd_max_mem = 1050000,
71 .src_clocks = {
72 [PLL0].name = "pll0",
73 [ACPUPLL].name = "pll14",
74 },
75 .reg_data = {
76 .cfg_src_mask = BM(2, 0),
77 .cfg_src_shift = 0,
78 .cfg_div_mask = BM(7, 3),
79 .cfg_div_shift = 3,
80 .update_mask = RCG_CONFIG_PGM_DATA_BIT | RCG_CONFIG_PGM_ENA_BIT,
81 .poll_mask = RCG_CONFIG_PGM_DATA_BIT,
82 },
Tianyi Gou7395a7e2012-10-19 14:12:21 -070083};
84
85static int __init acpuclk_9625_probe(struct platform_device *pdev)
86{
Tianyi Gou7395a7e2012-10-19 14:12:21 -070087 struct resource *res;
Tianyi Gou7395a7e2012-10-19 14:12:21 -070088 u32 regval;
89
Tianyi Gou7395a7e2012-10-19 14:12:21 -070090 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rcg_base");
91 if (!res)
92 return -EINVAL;
93
94 drv_data.apcs_rcg_config = ioremap(res->start, resource_size(res));
95 if (!drv_data.apcs_rcg_config)
96 return -ENOMEM;
97
Patrick Daly985c14b2012-12-03 17:12:37 -080098 drv_data.apcs_rcg_cmd = drv_data.apcs_rcg_config;
99
Tianyi Gou7395a7e2012-10-19 14:12:21 -0700100 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwr_base");
101 if (!res)
102 return -EINVAL;
103
104 drv_data.apcs_cpu_pwr_ctl = ioremap(res->start, resource_size(res));
105 if (!drv_data.apcs_cpu_pwr_ctl)
106 return -ENOMEM;
107
Patrick Daly0962ada2013-03-13 16:37:40 -0700108 drv_data.vdd_cpu = devm_regulator_get(&pdev->dev, "a5_cpu");
Tianyi Gou7395a7e2012-10-19 14:12:21 -0700109 if (IS_ERR(drv_data.vdd_cpu)) {
110 dev_err(&pdev->dev, "regulator for %s get failed\n", "a5_cpu");
111 return PTR_ERR(drv_data.vdd_cpu);
112 }
113
Patrick Daly0962ada2013-03-13 16:37:40 -0700114 drv_data.vdd_mem = devm_regulator_get(&pdev->dev, "a5_mem");
Tianyi Gou7395a7e2012-10-19 14:12:21 -0700115 if (IS_ERR(drv_data.vdd_mem)) {
116 dev_err(&pdev->dev, "regulator for %s get failed\n", "a5_mem");
117 return PTR_ERR(drv_data.vdd_mem);
118 }
119
120 /* Disable hardware gating of gpll0 to A5SS */
121 regval = readl_relaxed(drv_data.apcs_cpu_pwr_ctl);
122 regval |= GPLL0_TO_A5_ALWAYS_ENABLE;
123 writel_relaxed(regval, drv_data.apcs_cpu_pwr_ctl);
124
Patrick Daly985c14b2012-12-03 17:12:37 -0800125 return acpuclk_cortex_init(pdev, &drv_data);
Tianyi Gou7395a7e2012-10-19 14:12:21 -0700126}
127
128static struct of_device_id acpuclk_9625_match_table[] = {
129 {.compatible = "qcom,acpuclk-9625"},
130 {}
131};
132
133static struct platform_driver acpuclk_9625_driver = {
134 .driver = {
135 .name = "acpuclk-9625",
136 .of_match_table = acpuclk_9625_match_table,
137 .owner = THIS_MODULE,
138 },
139};
140
141static int __init acpuclk_9625_init(void)
142{
143 return platform_driver_probe(&acpuclk_9625_driver, acpuclk_9625_probe);
144}
145device_initcall(acpuclk_9625_init);