mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-29 09:13:38 +00:00
clk: twl: add TWL6030 support
The TWL6030 has similar clocks, so add support for it. Take care of the resource grouping handling needed. Signed-off-by: Andreas Kemnade <andreas@kemnade.info> Link: https://lore.kernel.org/r/20241014161109.2222-4-andreas@kemnade.info Reviewed-by: Roger Quadros <rogerq@kernel.org> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
This commit is contained in:
parent
990161eb32
commit
9abc1eb62a
@ -291,7 +291,7 @@ config CLK_TWL
|
||||
help
|
||||
Enable support for controlling the clock resources on TWL family
|
||||
PMICs. These devices have some 32K clock outputs which can be
|
||||
controlled by software. For now, only the TWL6032 clocks are
|
||||
controlled by software. For now, the TWL6032 and TWL6030 clocks are
|
||||
supported.
|
||||
|
||||
config CLK_TWL6040
|
||||
|
@ -12,12 +12,28 @@
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define VREG_STATE 2
|
||||
#define VREG_GRP 0
|
||||
#define TWL6030_CFG_STATE_OFF 0x00
|
||||
#define TWL6030_CFG_STATE_ON 0x01
|
||||
#define TWL6030_CFG_STATE_MASK 0x03
|
||||
#define TWL6030_CFG_STATE_GRP_SHIFT 5
|
||||
#define TWL6030_CFG_STATE_APP_SHIFT 2
|
||||
#define TWL6030_CFG_STATE_APP_MASK (0x03 << TWL6030_CFG_STATE_APP_SHIFT)
|
||||
#define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\
|
||||
TWL6030_CFG_STATE_APP_SHIFT)
|
||||
#define P1_GRP BIT(0) /* processor power group */
|
||||
#define P2_GRP BIT(1)
|
||||
#define P3_GRP BIT(2)
|
||||
#define ALL_GRP (P1_GRP | P2_GRP | P3_GRP)
|
||||
|
||||
enum twl_type {
|
||||
TWL_TYPE_6030,
|
||||
TWL_TYPE_6032,
|
||||
};
|
||||
|
||||
struct twl_clock_info {
|
||||
struct device *dev;
|
||||
enum twl_type type;
|
||||
u8 base;
|
||||
struct clk_hw hw;
|
||||
};
|
||||
@ -56,14 +72,21 @@ static unsigned long twl_clks_recalc_rate(struct clk_hw *hw,
|
||||
static int twl6032_clks_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct twl_clock_info *cinfo = to_twl_clks_info(hw);
|
||||
int ret;
|
||||
|
||||
ret = twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
|
||||
if (cinfo->type == TWL_TYPE_6030) {
|
||||
int grp;
|
||||
|
||||
grp = twlclk_read(cinfo, TWL_MODULE_PM_RECEIVER, VREG_GRP);
|
||||
if (grp < 0)
|
||||
return grp;
|
||||
|
||||
return twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
|
||||
grp << TWL6030_CFG_STATE_GRP_SHIFT |
|
||||
TWL6030_CFG_STATE_ON);
|
||||
if (ret < 0)
|
||||
dev_err(cinfo->dev, "clk prepare failed\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
return twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
|
||||
TWL6030_CFG_STATE_ON);
|
||||
}
|
||||
|
||||
static void twl6032_clks_unprepare(struct clk_hw *hw)
|
||||
@ -71,8 +94,14 @@ static void twl6032_clks_unprepare(struct clk_hw *hw)
|
||||
struct twl_clock_info *cinfo = to_twl_clks_info(hw);
|
||||
int ret;
|
||||
|
||||
if (cinfo->type == TWL_TYPE_6030)
|
||||
ret = twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
|
||||
ALL_GRP << TWL6030_CFG_STATE_GRP_SHIFT |
|
||||
TWL6030_CFG_STATE_OFF);
|
||||
else
|
||||
ret = twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
|
||||
TWL6030_CFG_STATE_OFF);
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(cinfo->dev, "clk unprepare failed\n");
|
||||
}
|
||||
@ -138,6 +167,7 @@ static int twl_clks_probe(struct platform_device *pdev)
|
||||
for (i = 0; i < count; i++) {
|
||||
cinfo[i].base = hw_data[i].base;
|
||||
cinfo[i].dev = &pdev->dev;
|
||||
cinfo[i].type = platform_get_device_id(pdev)->driver_data;
|
||||
cinfo[i].hw.init = &hw_data[i].init;
|
||||
ret = devm_clk_hw_register(&pdev->dev, &cinfo[i].hw);
|
||||
if (ret) {
|
||||
@ -159,7 +189,11 @@ static int twl_clks_probe(struct platform_device *pdev)
|
||||
|
||||
static const struct platform_device_id twl_clks_id[] = {
|
||||
{
|
||||
.name = "twl6030-clk",
|
||||
.driver_data = TWL_TYPE_6030,
|
||||
}, {
|
||||
.name = "twl6032-clk",
|
||||
.driver_data = TWL_TYPE_6032,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user