clk: qcom: rpmcc: Add support to XO buffered clocks
XO is onchip buffer clock to generate 19.2MHz. This patch adds support to 5 XO buffer clocks found on PMIC8921, these buffer clocks can be controlled from external pin or in manual mode. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
This commit is contained in:
parent
7928b2cbe5
commit
8bcde6582c
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
#define QCOM_RPM_MISC_CLK_TYPE 0x306b6c63
|
#define QCOM_RPM_MISC_CLK_TYPE 0x306b6c63
|
||||||
#define QCOM_RPM_SCALING_ENABLE_ID 0x2
|
#define QCOM_RPM_SCALING_ENABLE_ID 0x2
|
||||||
|
#define QCOM_RPM_XO_MODE_ON 0x2
|
||||||
|
|
||||||
#define DEFINE_CLK_RPM(_platform, _name, _active, r_id) \
|
#define DEFINE_CLK_RPM(_platform, _name, _active, r_id) \
|
||||||
static struct clk_rpm _platform##_##_active; \
|
static struct clk_rpm _platform##_##_active; \
|
||||||
|
@ -56,6 +57,18 @@
|
||||||
}, \
|
}, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DEFINE_CLK_RPM_XO_BUFFER(_platform, _name, _active, offset) \
|
||||||
|
static struct clk_rpm _platform##_##_name = { \
|
||||||
|
.rpm_clk_id = QCOM_RPM_CXO_BUFFERS, \
|
||||||
|
.xo_offset = (offset), \
|
||||||
|
.hw.init = &(struct clk_init_data){ \
|
||||||
|
.ops = &clk_rpm_xo_ops, \
|
||||||
|
.name = #_name, \
|
||||||
|
.parent_names = (const char *[]){ "cxo_board" }, \
|
||||||
|
.num_parents = 1, \
|
||||||
|
}, \
|
||||||
|
}
|
||||||
|
|
||||||
#define DEFINE_CLK_RPM_FIXED(_platform, _name, _active, r_id, r) \
|
#define DEFINE_CLK_RPM_FIXED(_platform, _name, _active, r_id, r) \
|
||||||
static struct clk_rpm _platform##_##_name = { \
|
static struct clk_rpm _platform##_##_name = { \
|
||||||
.rpm_clk_id = (r_id), \
|
.rpm_clk_id = (r_id), \
|
||||||
|
@ -126,8 +139,11 @@
|
||||||
|
|
||||||
#define to_clk_rpm(_hw) container_of(_hw, struct clk_rpm, hw)
|
#define to_clk_rpm(_hw) container_of(_hw, struct clk_rpm, hw)
|
||||||
|
|
||||||
|
struct rpm_cc;
|
||||||
|
|
||||||
struct clk_rpm {
|
struct clk_rpm {
|
||||||
const int rpm_clk_id;
|
const int rpm_clk_id;
|
||||||
|
const int xo_offset;
|
||||||
const bool active_only;
|
const bool active_only;
|
||||||
unsigned long rate;
|
unsigned long rate;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
|
@ -135,12 +151,15 @@ struct clk_rpm {
|
||||||
struct clk_rpm *peer;
|
struct clk_rpm *peer;
|
||||||
struct clk_hw hw;
|
struct clk_hw hw;
|
||||||
struct qcom_rpm *rpm;
|
struct qcom_rpm *rpm;
|
||||||
|
struct rpm_cc *rpm_cc;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rpm_cc {
|
struct rpm_cc {
|
||||||
struct qcom_rpm *rpm;
|
struct qcom_rpm *rpm;
|
||||||
struct clk_rpm **clks;
|
struct clk_rpm **clks;
|
||||||
size_t num_clks;
|
size_t num_clks;
|
||||||
|
u32 xo_buffer_value;
|
||||||
|
struct mutex xo_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rpm_clk_desc {
|
struct rpm_clk_desc {
|
||||||
|
@ -159,7 +178,8 @@ static int clk_rpm_handoff(struct clk_rpm *r)
|
||||||
* The vendor tree simply reads the status for this
|
* The vendor tree simply reads the status for this
|
||||||
* RPM clock.
|
* RPM clock.
|
||||||
*/
|
*/
|
||||||
if (r->rpm_clk_id == QCOM_RPM_PLL_4)
|
if (r->rpm_clk_id == QCOM_RPM_PLL_4 ||
|
||||||
|
r->rpm_clk_id == QCOM_RPM_CXO_BUFFERS)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
|
ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
|
||||||
|
@ -288,6 +308,46 @@ out:
|
||||||
mutex_unlock(&rpm_clk_lock);
|
mutex_unlock(&rpm_clk_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int clk_rpm_xo_prepare(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct clk_rpm *r = to_clk_rpm(hw);
|
||||||
|
struct rpm_cc *rcc = r->rpm_cc;
|
||||||
|
int ret, clk_id = r->rpm_clk_id;
|
||||||
|
u32 value;
|
||||||
|
|
||||||
|
mutex_lock(&rcc->xo_lock);
|
||||||
|
|
||||||
|
value = rcc->xo_buffer_value | (QCOM_RPM_XO_MODE_ON << r->xo_offset);
|
||||||
|
ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, clk_id, &value, 1);
|
||||||
|
if (!ret) {
|
||||||
|
r->enabled = true;
|
||||||
|
rcc->xo_buffer_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&rcc->xo_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clk_rpm_xo_unprepare(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct clk_rpm *r = to_clk_rpm(hw);
|
||||||
|
struct rpm_cc *rcc = r->rpm_cc;
|
||||||
|
int ret, clk_id = r->rpm_clk_id;
|
||||||
|
u32 value;
|
||||||
|
|
||||||
|
mutex_lock(&rcc->xo_lock);
|
||||||
|
|
||||||
|
value = rcc->xo_buffer_value & ~(QCOM_RPM_XO_MODE_ON << r->xo_offset);
|
||||||
|
ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, clk_id, &value, 1);
|
||||||
|
if (!ret) {
|
||||||
|
r->enabled = false;
|
||||||
|
rcc->xo_buffer_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&rcc->xo_lock);
|
||||||
|
}
|
||||||
|
|
||||||
static int clk_rpm_fixed_prepare(struct clk_hw *hw)
|
static int clk_rpm_fixed_prepare(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
struct clk_rpm *r = to_clk_rpm(hw);
|
struct clk_rpm *r = to_clk_rpm(hw);
|
||||||
|
@ -378,6 +438,11 @@ static unsigned long clk_rpm_recalc_rate(struct clk_hw *hw,
|
||||||
return r->rate;
|
return r->rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct clk_ops clk_rpm_xo_ops = {
|
||||||
|
.prepare = clk_rpm_xo_prepare,
|
||||||
|
.unprepare = clk_rpm_xo_unprepare,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct clk_ops clk_rpm_fixed_ops = {
|
static const struct clk_ops clk_rpm_fixed_ops = {
|
||||||
.prepare = clk_rpm_fixed_prepare,
|
.prepare = clk_rpm_fixed_prepare,
|
||||||
.unprepare = clk_rpm_fixed_unprepare,
|
.unprepare = clk_rpm_fixed_unprepare,
|
||||||
|
@ -449,6 +514,11 @@ DEFINE_CLK_RPM(apq8064, mmfpb_clk, mmfpb_a_clk, QCOM_RPM_MMFPB_CLK);
|
||||||
DEFINE_CLK_RPM(apq8064, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK);
|
DEFINE_CLK_RPM(apq8064, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK);
|
||||||
DEFINE_CLK_RPM(apq8064, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK);
|
DEFINE_CLK_RPM(apq8064, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK);
|
||||||
DEFINE_CLK_RPM(apq8064, qdss_clk, qdss_a_clk, QCOM_RPM_QDSS_CLK);
|
DEFINE_CLK_RPM(apq8064, qdss_clk, qdss_a_clk, QCOM_RPM_QDSS_CLK);
|
||||||
|
DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_d0_clk, xo_d0_a_clk, 0);
|
||||||
|
DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_d1_clk, xo_d1_a_clk, 8);
|
||||||
|
DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a0_clk, xo_a0_a_clk, 16);
|
||||||
|
DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a1_clk, xo_a1_a_clk, 24);
|
||||||
|
DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a2_clk, xo_a2_a_clk, 28);
|
||||||
|
|
||||||
static struct clk_rpm *apq8064_clks[] = {
|
static struct clk_rpm *apq8064_clks[] = {
|
||||||
[RPM_APPS_FABRIC_CLK] = &apq8064_afab_clk,
|
[RPM_APPS_FABRIC_CLK] = &apq8064_afab_clk,
|
||||||
|
@ -469,6 +539,11 @@ static struct clk_rpm *apq8064_clks[] = {
|
||||||
[RPM_SFPB_A_CLK] = &apq8064_sfpb_a_clk,
|
[RPM_SFPB_A_CLK] = &apq8064_sfpb_a_clk,
|
||||||
[RPM_QDSS_CLK] = &apq8064_qdss_clk,
|
[RPM_QDSS_CLK] = &apq8064_qdss_clk,
|
||||||
[RPM_QDSS_A_CLK] = &apq8064_qdss_a_clk,
|
[RPM_QDSS_A_CLK] = &apq8064_qdss_a_clk,
|
||||||
|
[RPM_XO_D0] = &apq8064_xo_d0_clk,
|
||||||
|
[RPM_XO_D1] = &apq8064_xo_d1_clk,
|
||||||
|
[RPM_XO_A0] = &apq8064_xo_a0_clk,
|
||||||
|
[RPM_XO_A1] = &apq8064_xo_a1_clk,
|
||||||
|
[RPM_XO_A2] = &apq8064_xo_a2_clk,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct rpm_clk_desc rpm_clk_apq8064 = {
|
static const struct rpm_clk_desc rpm_clk_apq8064 = {
|
||||||
|
@ -526,12 +601,14 @@ static int rpm_clk_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
rcc->clks = rpm_clks;
|
rcc->clks = rpm_clks;
|
||||||
rcc->num_clks = num_clks;
|
rcc->num_clks = num_clks;
|
||||||
|
mutex_init(&rcc->xo_lock);
|
||||||
|
|
||||||
for (i = 0; i < num_clks; i++) {
|
for (i = 0; i < num_clks; i++) {
|
||||||
if (!rpm_clks[i])
|
if (!rpm_clks[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rpm_clks[i]->rpm = rpm;
|
rpm_clks[i]->rpm = rpm;
|
||||||
|
rpm_clks[i]->rpm_cc = rcc;
|
||||||
|
|
||||||
ret = clk_rpm_handoff(rpm_clks[i]);
|
ret = clk_rpm_handoff(rpm_clks[i]);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
|
@ -40,6 +40,11 @@
|
||||||
#define RPM_SMI_CLK 22
|
#define RPM_SMI_CLK 22
|
||||||
#define RPM_SMI_A_CLK 23
|
#define RPM_SMI_A_CLK 23
|
||||||
#define RPM_PLL4_CLK 24
|
#define RPM_PLL4_CLK 24
|
||||||
|
#define RPM_XO_D0 25
|
||||||
|
#define RPM_XO_D1 26
|
||||||
|
#define RPM_XO_A0 27
|
||||||
|
#define RPM_XO_A1 28
|
||||||
|
#define RPM_XO_A2 29
|
||||||
|
|
||||||
/* SMD RPM clocks */
|
/* SMD RPM clocks */
|
||||||
#define RPM_SMD_XO_CLK_SRC 0
|
#define RPM_SMD_XO_CLK_SRC 0
|
||||||
|
|
Loading…
Reference in a new issue