diff options
Diffstat (limited to 'drivers/clk')
-rw-r--r-- | drivers/clk/Kconfig | 15 | ||||
-rw-r--r-- | drivers/clk/clk-bd718x7.c | 24 | ||||
-rw-r--r-- | drivers/clk/clk-rk808.c | 64 |
3 files changed, 88 insertions, 15 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index fc1e0cf44995..7376af25f947 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -53,13 +53,12 @@ config COMMON_CLK_MAX9485 This driver supports Maxim 9485 Programmable Audio Clock Generator config COMMON_CLK_RK808 - tristate "Clock driver for RK805/RK808/RK818" + tristate "Clock driver for RK805/RK808/RK809/RK817/RK818" depends on MFD_RK808 ---help--- - This driver supports RK805, RK808 and RK818 crystal oscillator clock. These - multi-function devices have two fixed-rate oscillators, - clocked at 32KHz each. Clkout1 is always on, Clkout2 can off - by control register. + This driver supports RK805, RK809 and RK817, RK808 and RK818 crystal oscillator clock. + These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each. + Clkout1 is always on, Clkout2 can off by control register. config COMMON_CLK_HI655X tristate "Clock driver for Hi655x" if EXPERT @@ -293,10 +292,10 @@ config COMMON_CLK_STM32H7 config COMMON_CLK_BD718XX tristate "Clock driver for ROHM BD718x7 PMIC" - depends on MFD_ROHM_BD718XX + depends on MFD_ROHM_BD718XX || MFD_ROHM_BD70528 help - This driver supports ROHM BD71837 and ROHM BD71847 - PMICs clock gates. + This driver supports ROHM BD71837, ROHM BD71847 and + ROHM BD70528 PMICs clock gates. config COMMON_CLK_FIXED_MMIO bool "Clock driver for Memory Mapped Fixed values" diff --git a/drivers/clk/clk-bd718x7.c b/drivers/clk/clk-bd718x7.c index 60422c72d142..ae6e5baee330 100644 --- a/drivers/clk/clk-bd718x7.c +++ b/drivers/clk/clk-bd718x7.c @@ -8,6 +8,7 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/mfd/rohm-bd718x7.h> +#include <linux/mfd/rohm-bd70528.h> #include <linux/clk-provider.h> #include <linux/clkdev.h> #include <linux/regmap.h> @@ -17,7 +18,7 @@ struct bd718xx_clk { u8 reg; u8 mask; struct platform_device *pdev; - struct bd718xx *mfd; + struct rohm_regmap_dev *mfd; }; static int bd71837_clk_set(struct clk_hw *hw, int status) @@ -68,7 +69,7 @@ static int bd71837_clk_probe(struct platform_device *pdev) int rval = -ENOMEM; const char *parent_clk; struct device *parent = pdev->dev.parent; - struct bd718xx *mfd = dev_get_drvdata(parent); + struct rohm_regmap_dev *mfd = dev_get_drvdata(parent); struct clk_init_data init = { .name = "bd718xx-32k-out", .ops = &bd71837_clk_ops, @@ -86,9 +87,20 @@ static int bd71837_clk_probe(struct platform_device *pdev) dev_err(&pdev->dev, "No parent clk found\n"); return -EINVAL; } - - c->reg = BD718XX_REG_OUT32K; - c->mask = BD718XX_OUT32K_EN; + switch (mfd->chip_type) { + case ROHM_CHIP_TYPE_BD71837: + case ROHM_CHIP_TYPE_BD71847: + c->reg = BD718XX_REG_OUT32K; + c->mask = BD718XX_OUT32K_EN; + break; + case ROHM_CHIP_TYPE_BD70528: + c->reg = BD70528_REG_CLK_OUT; + c->mask = BD70528_CLK_OUT_EN_MASK; + break; + default: + dev_err(&pdev->dev, "Unknown clk chip\n"); + return -EINVAL; + } c->mfd = mfd; c->pdev = pdev; c->hw.init = &init; @@ -119,5 +131,5 @@ static struct platform_driver bd71837_clk = { module_platform_driver(bd71837_clk); MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); -MODULE_DESCRIPTION("BD71837 chip clk driver"); +MODULE_DESCRIPTION("BD71837/BD71847/BD70528 chip clk driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/clk/clk-rk808.c b/drivers/clk/clk-rk808.c index b1d7e4a296ef..32f833d732ed 100644 --- a/drivers/clk/clk-rk808.c +++ b/drivers/clk/clk-rk808.c @@ -88,6 +88,68 @@ of_clk_rk808_get(struct of_phandle_args *clkspec, void *data) return idx ? &rk808_clkout->clkout2_hw : &rk808_clkout->clkout1_hw; } +static int rk817_clkout2_enable(struct clk_hw *hw, bool enable) +{ + struct rk808_clkout *rk808_clkout = container_of(hw, + struct rk808_clkout, + clkout2_hw); + struct rk808 *rk808 = rk808_clkout->rk808; + + return regmap_update_bits(rk808->regmap, RK817_SYS_CFG(1), + RK817_CLK32KOUT2_EN, + enable ? RK817_CLK32KOUT2_EN : 0); +} + +static int rk817_clkout2_prepare(struct clk_hw *hw) +{ + return rk817_clkout2_enable(hw, true); +} + +static void rk817_clkout2_unprepare(struct clk_hw *hw) +{ + rk817_clkout2_enable(hw, false); +} + +static int rk817_clkout2_is_prepared(struct clk_hw *hw) +{ + struct rk808_clkout *rk808_clkout = container_of(hw, + struct rk808_clkout, + clkout2_hw); + struct rk808 *rk808 = rk808_clkout->rk808; + unsigned int val; + + int ret = regmap_read(rk808->regmap, RK817_SYS_CFG(1), &val); + + if (ret < 0) + return 0; + + return (val & RK817_CLK32KOUT2_EN) ? 1 : 0; +} + +static const struct clk_ops rk817_clkout2_ops = { + .prepare = rk817_clkout2_prepare, + .unprepare = rk817_clkout2_unprepare, + .is_prepared = rk817_clkout2_is_prepared, + .recalc_rate = rk808_clkout_recalc_rate, +}; + +static const struct clk_ops *rkpmic_get_ops(long variant) +{ + switch (variant) { + case RK809_ID: + case RK817_ID: + return &rk817_clkout2_ops; + /* + * For the default case, it match the following PMIC type. + * RK805_ID + * RK808_ID + * RK818_ID + */ + default: + return &rk808_clkout2_ops; + } +} + static int rk808_clkout_probe(struct platform_device *pdev) { struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); @@ -119,7 +181,7 @@ static int rk808_clkout_probe(struct platform_device *pdev) return ret; init.name = "rk808-clkout2"; - init.ops = &rk808_clkout2_ops; + init.ops = rkpmic_get_ops(rk808->variant); rk808_clkout->clkout2_hw.init = &init; /* optional override of the clockname */ |