0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk.h>
0009 #include <linux/clk-provider.h>
0010 #include <linux/io.h>
0011 #include <linux/of_address.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/slab.h>
0014
0015 #include "clk-factors.h"
0016
0017
0018
0019
0020
0021
0022
0023 static void sun4i_a10_get_mod0_factors(struct factors_request *req)
0024 {
0025 u8 div, calcm, calcp;
0026
0027
0028
0029 if (req->rate > req->parent_rate)
0030 req->rate = req->parent_rate;
0031
0032 div = DIV_ROUND_UP(req->parent_rate, req->rate);
0033
0034 if (div < 16)
0035 calcp = 0;
0036 else if (div / 2 < 16)
0037 calcp = 1;
0038 else if (div / 4 < 16)
0039 calcp = 2;
0040 else
0041 calcp = 3;
0042
0043 calcm = DIV_ROUND_UP(div, 1 << calcp);
0044
0045 req->rate = (req->parent_rate >> calcp) / calcm;
0046 req->m = calcm - 1;
0047 req->p = calcp;
0048 }
0049
0050
0051 static const struct clk_factors_config sun4i_a10_mod0_config = {
0052 .mshift = 0,
0053 .mwidth = 4,
0054 .pshift = 16,
0055 .pwidth = 2,
0056 };
0057
0058 static const struct factors_data sun4i_a10_mod0_data = {
0059 .enable = 31,
0060 .mux = 24,
0061 .muxmask = BIT(1) | BIT(0),
0062 .table = &sun4i_a10_mod0_config,
0063 .getter = sun4i_a10_get_mod0_factors,
0064 };
0065
0066 static DEFINE_SPINLOCK(sun4i_a10_mod0_lock);
0067
0068 static void __init sun4i_a10_mod0_setup(struct device_node *node)
0069 {
0070 void __iomem *reg;
0071
0072 reg = of_iomap(node, 0);
0073 if (!reg) {
0074
0075
0076
0077
0078
0079 return;
0080 }
0081
0082 sunxi_factors_register(node, &sun4i_a10_mod0_data,
0083 &sun4i_a10_mod0_lock, reg);
0084 }
0085 CLK_OF_DECLARE_DRIVER(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk",
0086 sun4i_a10_mod0_setup);
0087
0088 static int sun4i_a10_mod0_clk_probe(struct platform_device *pdev)
0089 {
0090 struct device_node *np = pdev->dev.of_node;
0091 void __iomem *reg;
0092
0093 if (!np)
0094 return -ENODEV;
0095
0096 reg = devm_platform_ioremap_resource(pdev, 0);
0097 if (IS_ERR(reg))
0098 return PTR_ERR(reg);
0099
0100 sunxi_factors_register(np, &sun4i_a10_mod0_data,
0101 &sun4i_a10_mod0_lock, reg);
0102 return 0;
0103 }
0104
0105 static const struct of_device_id sun4i_a10_mod0_clk_dt_ids[] = {
0106 { .compatible = "allwinner,sun4i-a10-mod0-clk" },
0107 { }
0108 };
0109
0110 static struct platform_driver sun4i_a10_mod0_clk_driver = {
0111 .driver = {
0112 .name = "sun4i-a10-mod0-clk",
0113 .of_match_table = sun4i_a10_mod0_clk_dt_ids,
0114 },
0115 .probe = sun4i_a10_mod0_clk_probe,
0116 };
0117 builtin_platform_driver(sun4i_a10_mod0_clk_driver);
0118
0119 static const struct factors_data sun9i_a80_mod0_data __initconst = {
0120 .enable = 31,
0121 .mux = 24,
0122 .muxmask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
0123 .table = &sun4i_a10_mod0_config,
0124 .getter = sun4i_a10_get_mod0_factors,
0125 };
0126
0127 static void __init sun9i_a80_mod0_setup(struct device_node *node)
0128 {
0129 void __iomem *reg;
0130
0131 reg = of_io_request_and_map(node, 0, of_node_full_name(node));
0132 if (IS_ERR(reg)) {
0133 pr_err("Could not get registers for mod0-clk: %pOFn\n",
0134 node);
0135 return;
0136 }
0137
0138 sunxi_factors_register(node, &sun9i_a80_mod0_data,
0139 &sun4i_a10_mod0_lock, reg);
0140 }
0141 CLK_OF_DECLARE(sun9i_a80_mod0, "allwinner,sun9i-a80-mod0-clk", sun9i_a80_mod0_setup);
0142
0143 static DEFINE_SPINLOCK(sun5i_a13_mbus_lock);
0144
0145 static void __init sun5i_a13_mbus_setup(struct device_node *node)
0146 {
0147 void __iomem *reg;
0148
0149 reg = of_iomap(node, 0);
0150 if (!reg) {
0151 pr_err("Could not get registers for a13-mbus-clk\n");
0152 return;
0153 }
0154
0155
0156 sunxi_factors_register_critical(node, &sun4i_a10_mod0_data,
0157 &sun5i_a13_mbus_lock, reg);
0158 }
0159 CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup);
0160
0161 struct mmc_phase {
0162 struct clk_hw hw;
0163 u8 offset;
0164 void __iomem *reg;
0165 spinlock_t *lock;
0166 };
0167
0168 #define to_mmc_phase(_hw) container_of(_hw, struct mmc_phase, hw)
0169
0170 static int mmc_get_phase(struct clk_hw *hw)
0171 {
0172 struct clk *mmc, *mmc_parent, *clk = hw->clk;
0173 struct mmc_phase *phase = to_mmc_phase(hw);
0174 unsigned int mmc_rate, mmc_parent_rate;
0175 u16 step, mmc_div;
0176 u32 value;
0177 u8 delay;
0178
0179 value = readl(phase->reg);
0180 delay = (value >> phase->offset) & 0x3;
0181
0182 if (!delay)
0183 return 180;
0184
0185
0186 mmc = clk_get_parent(clk);
0187 if (!mmc)
0188 return -EINVAL;
0189
0190
0191 mmc_rate = clk_get_rate(mmc);
0192 if (!mmc_rate)
0193 return -EINVAL;
0194
0195
0196 mmc_parent = clk_get_parent(mmc);
0197 if (!mmc_parent)
0198 return -EINVAL;
0199
0200
0201 mmc_parent_rate = clk_get_rate(mmc_parent);
0202 if (!mmc_parent_rate)
0203 return -EINVAL;
0204
0205
0206 mmc_div = mmc_parent_rate / mmc_rate;
0207
0208 step = DIV_ROUND_CLOSEST(360, mmc_div);
0209 return delay * step;
0210 }
0211
0212 static int mmc_set_phase(struct clk_hw *hw, int degrees)
0213 {
0214 struct clk *mmc, *mmc_parent, *clk = hw->clk;
0215 struct mmc_phase *phase = to_mmc_phase(hw);
0216 unsigned int mmc_rate, mmc_parent_rate;
0217 unsigned long flags;
0218 u32 value;
0219 u8 delay;
0220
0221
0222 mmc = clk_get_parent(clk);
0223 if (!mmc)
0224 return -EINVAL;
0225
0226
0227 mmc_rate = clk_get_rate(mmc);
0228 if (!mmc_rate)
0229 return -EINVAL;
0230
0231
0232 mmc_parent = clk_get_parent(mmc);
0233 if (!mmc_parent)
0234 return -EINVAL;
0235
0236
0237 mmc_parent_rate = clk_get_rate(mmc_parent);
0238 if (!mmc_parent_rate)
0239 return -EINVAL;
0240
0241 if (degrees != 180) {
0242 u16 step, mmc_div;
0243
0244
0245 mmc_div = mmc_parent_rate / mmc_rate;
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260 step = DIV_ROUND_CLOSEST(360, mmc_div);
0261 delay = DIV_ROUND_CLOSEST(degrees, step);
0262 } else {
0263 delay = 0;
0264 }
0265
0266 spin_lock_irqsave(phase->lock, flags);
0267 value = readl(phase->reg);
0268 value &= ~GENMASK(phase->offset + 3, phase->offset);
0269 value |= delay << phase->offset;
0270 writel(value, phase->reg);
0271 spin_unlock_irqrestore(phase->lock, flags);
0272
0273 return 0;
0274 }
0275
0276 static const struct clk_ops mmc_clk_ops = {
0277 .get_phase = mmc_get_phase,
0278 .set_phase = mmc_set_phase,
0279 };
0280
0281
0282
0283
0284
0285
0286
0287
0288 static void __init sunxi_mmc_setup(struct device_node *node,
0289 const struct factors_data *data,
0290 spinlock_t *lock)
0291 {
0292 struct clk_onecell_data *clk_data;
0293 const char *parent;
0294 void __iomem *reg;
0295 int i;
0296
0297 reg = of_io_request_and_map(node, 0, of_node_full_name(node));
0298 if (IS_ERR(reg)) {
0299 pr_err("Couldn't map the %pOFn clock registers\n", node);
0300 return;
0301 }
0302
0303 clk_data = kmalloc(sizeof(*clk_data), GFP_KERNEL);
0304 if (!clk_data)
0305 return;
0306
0307 clk_data->clks = kcalloc(3, sizeof(*clk_data->clks), GFP_KERNEL);
0308 if (!clk_data->clks)
0309 goto err_free_data;
0310
0311 clk_data->clk_num = 3;
0312 clk_data->clks[0] = sunxi_factors_register(node, data, lock, reg);
0313 if (!clk_data->clks[0])
0314 goto err_free_clks;
0315
0316 parent = __clk_get_name(clk_data->clks[0]);
0317
0318 for (i = 1; i < 3; i++) {
0319 struct clk_init_data init = {
0320 .num_parents = 1,
0321 .parent_names = &parent,
0322 .ops = &mmc_clk_ops,
0323 };
0324 struct mmc_phase *phase;
0325
0326 phase = kmalloc(sizeof(*phase), GFP_KERNEL);
0327 if (!phase)
0328 continue;
0329
0330 phase->hw.init = &init;
0331 phase->reg = reg;
0332 phase->lock = lock;
0333
0334 if (i == 1)
0335 phase->offset = 8;
0336 else
0337 phase->offset = 20;
0338
0339 if (of_property_read_string_index(node, "clock-output-names",
0340 i, &init.name))
0341 init.name = node->name;
0342
0343 clk_data->clks[i] = clk_register(NULL, &phase->hw);
0344 if (IS_ERR(clk_data->clks[i])) {
0345 kfree(phase);
0346 continue;
0347 }
0348 }
0349
0350 of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
0351
0352 return;
0353
0354 err_free_clks:
0355 kfree(clk_data->clks);
0356 err_free_data:
0357 kfree(clk_data);
0358 }
0359
0360 static DEFINE_SPINLOCK(sun4i_a10_mmc_lock);
0361
0362 static void __init sun4i_a10_mmc_setup(struct device_node *node)
0363 {
0364 sunxi_mmc_setup(node, &sun4i_a10_mod0_data, &sun4i_a10_mmc_lock);
0365 }
0366 CLK_OF_DECLARE(sun4i_a10_mmc, "allwinner,sun4i-a10-mmc-clk", sun4i_a10_mmc_setup);
0367
0368 static DEFINE_SPINLOCK(sun9i_a80_mmc_lock);
0369
0370 static void __init sun9i_a80_mmc_setup(struct device_node *node)
0371 {
0372 sunxi_mmc_setup(node, &sun9i_a80_mod0_data, &sun9i_a80_mmc_lock);
0373 }
0374 CLK_OF_DECLARE(sun9i_a80_mmc, "allwinner,sun9i-a80-mmc-clk", sun9i_a80_mmc_setup);