0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/clk.h>
0015 #include <linux/delay.h>
0016 #include <linux/io.h>
0017 #include <linux/module.h>
0018 #include <linux/of.h>
0019 #include <linux/of_platform.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/pm_runtime.h>
0022 #include <linux/regmap.h>
0023 #include <linux/soc/samsung/exynos-regs-pmu.h>
0024 #include <linux/types.h>
0025
0026
0027 #define SFR_LPASS_CORE_SW_RESET 0x08
0028 #define LPASS_SB_SW_RESET BIT(11)
0029 #define LPASS_UART_SW_RESET BIT(10)
0030 #define LPASS_PCM_SW_RESET BIT(9)
0031 #define LPASS_I2S_SW_RESET BIT(8)
0032 #define LPASS_WDT1_SW_RESET BIT(4)
0033 #define LPASS_WDT0_SW_RESET BIT(3)
0034 #define LPASS_TIMER_SW_RESET BIT(2)
0035 #define LPASS_MEM_SW_RESET BIT(1)
0036 #define LPASS_DMA_SW_RESET BIT(0)
0037
0038 #define SFR_LPASS_INTR_CA5_MASK 0x48
0039 #define SFR_LPASS_INTR_CPU_MASK 0x58
0040 #define LPASS_INTR_APM BIT(9)
0041 #define LPASS_INTR_MIF BIT(8)
0042 #define LPASS_INTR_TIMER BIT(7)
0043 #define LPASS_INTR_DMA BIT(6)
0044 #define LPASS_INTR_GPIO BIT(5)
0045 #define LPASS_INTR_I2S BIT(4)
0046 #define LPASS_INTR_PCM BIT(3)
0047 #define LPASS_INTR_SLIMBUS BIT(2)
0048 #define LPASS_INTR_UART BIT(1)
0049 #define LPASS_INTR_SFR BIT(0)
0050
0051 struct exynos_lpass {
0052
0053 struct regmap *top;
0054 struct clk *sfr0_clk;
0055 };
0056
0057 static void exynos_lpass_core_sw_reset(struct exynos_lpass *lpass, int mask)
0058 {
0059 unsigned int val = 0;
0060
0061 regmap_read(lpass->top, SFR_LPASS_CORE_SW_RESET, &val);
0062
0063 val &= ~mask;
0064 regmap_write(lpass->top, SFR_LPASS_CORE_SW_RESET, val);
0065
0066 usleep_range(100, 150);
0067
0068 val |= mask;
0069 regmap_write(lpass->top, SFR_LPASS_CORE_SW_RESET, val);
0070 }
0071
0072 static void exynos_lpass_enable(struct exynos_lpass *lpass)
0073 {
0074 clk_prepare_enable(lpass->sfr0_clk);
0075
0076
0077 regmap_write(lpass->top, SFR_LPASS_INTR_CA5_MASK,
0078 LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S);
0079
0080 regmap_write(lpass->top, SFR_LPASS_INTR_CPU_MASK,
0081 LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S |
0082 LPASS_INTR_UART);
0083
0084 exynos_lpass_core_sw_reset(lpass, LPASS_I2S_SW_RESET);
0085 exynos_lpass_core_sw_reset(lpass, LPASS_DMA_SW_RESET);
0086 exynos_lpass_core_sw_reset(lpass, LPASS_MEM_SW_RESET);
0087 exynos_lpass_core_sw_reset(lpass, LPASS_UART_SW_RESET);
0088 }
0089
0090 static void exynos_lpass_disable(struct exynos_lpass *lpass)
0091 {
0092
0093 regmap_write(lpass->top, SFR_LPASS_INTR_CPU_MASK, 0);
0094 regmap_write(lpass->top, SFR_LPASS_INTR_CA5_MASK, 0);
0095
0096 clk_disable_unprepare(lpass->sfr0_clk);
0097 }
0098
0099 static const struct regmap_config exynos_lpass_reg_conf = {
0100 .reg_bits = 32,
0101 .reg_stride = 4,
0102 .val_bits = 32,
0103 .max_register = 0xfc,
0104 .fast_io = true,
0105 };
0106
0107 static int exynos_lpass_probe(struct platform_device *pdev)
0108 {
0109 struct device *dev = &pdev->dev;
0110 struct exynos_lpass *lpass;
0111 void __iomem *base_top;
0112 struct resource *res;
0113
0114 lpass = devm_kzalloc(dev, sizeof(*lpass), GFP_KERNEL);
0115 if (!lpass)
0116 return -ENOMEM;
0117
0118 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0119 base_top = devm_ioremap_resource(dev, res);
0120 if (IS_ERR(base_top))
0121 return PTR_ERR(base_top);
0122
0123 lpass->sfr0_clk = devm_clk_get(dev, "sfr0_ctrl");
0124 if (IS_ERR(lpass->sfr0_clk))
0125 return PTR_ERR(lpass->sfr0_clk);
0126
0127 lpass->top = regmap_init_mmio(dev, base_top,
0128 &exynos_lpass_reg_conf);
0129 if (IS_ERR(lpass->top)) {
0130 dev_err(dev, "LPASS top regmap initialization failed\n");
0131 return PTR_ERR(lpass->top);
0132 }
0133
0134 platform_set_drvdata(pdev, lpass);
0135 pm_runtime_set_active(dev);
0136 pm_runtime_enable(dev);
0137 exynos_lpass_enable(lpass);
0138
0139 return devm_of_platform_populate(dev);
0140 }
0141
0142 static int exynos_lpass_remove(struct platform_device *pdev)
0143 {
0144 struct exynos_lpass *lpass = platform_get_drvdata(pdev);
0145
0146 exynos_lpass_disable(lpass);
0147 pm_runtime_disable(&pdev->dev);
0148 if (!pm_runtime_status_suspended(&pdev->dev))
0149 exynos_lpass_disable(lpass);
0150 regmap_exit(lpass->top);
0151
0152 return 0;
0153 }
0154
0155 static int __maybe_unused exynos_lpass_suspend(struct device *dev)
0156 {
0157 struct exynos_lpass *lpass = dev_get_drvdata(dev);
0158
0159 exynos_lpass_disable(lpass);
0160
0161 return 0;
0162 }
0163
0164 static int __maybe_unused exynos_lpass_resume(struct device *dev)
0165 {
0166 struct exynos_lpass *lpass = dev_get_drvdata(dev);
0167
0168 exynos_lpass_enable(lpass);
0169
0170 return 0;
0171 }
0172
0173 static const struct dev_pm_ops lpass_pm_ops = {
0174 SET_RUNTIME_PM_OPS(exynos_lpass_suspend, exynos_lpass_resume, NULL)
0175 SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
0176 pm_runtime_force_resume)
0177 };
0178
0179 static const struct of_device_id exynos_lpass_of_match[] = {
0180 { .compatible = "samsung,exynos5433-lpass" },
0181 { },
0182 };
0183 MODULE_DEVICE_TABLE(of, exynos_lpass_of_match);
0184
0185 static struct platform_driver exynos_lpass_driver = {
0186 .driver = {
0187 .name = "exynos-lpass",
0188 .pm = &lpass_pm_ops,
0189 .of_match_table = exynos_lpass_of_match,
0190 },
0191 .probe = exynos_lpass_probe,
0192 .remove = exynos_lpass_remove,
0193 };
0194 module_platform_driver(exynos_lpass_driver);
0195
0196 MODULE_DESCRIPTION("Samsung Low Power Audio Subsystem driver");
0197 MODULE_LICENSE("GPL v2");