0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include <linux/init.h>
0038 #include <linux/io.h>
0039 #include <linux/clk.h>
0040 #include <linux/clk-provider.h>
0041 #include <linux/clkdev.h>
0042 #include <linux/slab.h>
0043 #include <linux/spinlock.h>
0044 #include <linux/types.h>
0045 #include <asm/mach-au1x00/au1000.h>
0046
0047
0048
0049
0050 #define ALCHEMY_ROOTCLK_RATE 12000000
0051
0052
0053
0054
0055
0056
0057 static const char * const alchemy_au1300_intclknames[] = {
0058 "lcd_intclk", "gpemgp_clk", "maempe_clk", "maebsa_clk",
0059 "EXTCLK0", "EXTCLK1"
0060 };
0061
0062 static const char * const alchemy_au1200_intclknames[] = {
0063 "lcd_intclk", NULL, NULL, NULL, "EXTCLK0", "EXTCLK1"
0064 };
0065
0066 static const char * const alchemy_au1550_intclknames[] = {
0067 "usb_clk", "psc0_intclk", "psc1_intclk", "pci_clko",
0068 "EXTCLK0", "EXTCLK1"
0069 };
0070
0071 static const char * const alchemy_au1100_intclknames[] = {
0072 "usb_clk", "lcd_intclk", NULL, "i2s_clk", "EXTCLK0", "EXTCLK1"
0073 };
0074
0075 static const char * const alchemy_au1500_intclknames[] = {
0076 NULL, "usbd_clk", "usbh_clk", "pci_clko", "EXTCLK0", "EXTCLK1"
0077 };
0078
0079 static const char * const alchemy_au1000_intclknames[] = {
0080 "irda_clk", "usbd_clk", "usbh_clk", "i2s_clk", "EXTCLK0",
0081 "EXTCLK1"
0082 };
0083
0084
0085
0086
0087 static struct clk_aliastable {
0088 char *alias;
0089 char *base;
0090 int cputype;
0091 } alchemy_clk_aliases[] __initdata = {
0092 { "usbh_clk", "usb_clk", ALCHEMY_CPU_AU1100 },
0093 { "usbd_clk", "usb_clk", ALCHEMY_CPU_AU1100 },
0094 { "irda_clk", "usb_clk", ALCHEMY_CPU_AU1100 },
0095 { "usbh_clk", "usb_clk", ALCHEMY_CPU_AU1550 },
0096 { "usbd_clk", "usb_clk", ALCHEMY_CPU_AU1550 },
0097 { "psc2_intclk", "usb_clk", ALCHEMY_CPU_AU1550 },
0098 { "psc3_intclk", "EXTCLK0", ALCHEMY_CPU_AU1550 },
0099 { "psc0_intclk", "EXTCLK0", ALCHEMY_CPU_AU1200 },
0100 { "psc1_intclk", "EXTCLK1", ALCHEMY_CPU_AU1200 },
0101 { "psc0_intclk", "EXTCLK0", ALCHEMY_CPU_AU1300 },
0102 { "psc2_intclk", "EXTCLK0", ALCHEMY_CPU_AU1300 },
0103 { "psc1_intclk", "EXTCLK1", ALCHEMY_CPU_AU1300 },
0104 { "psc3_intclk", "EXTCLK1", ALCHEMY_CPU_AU1300 },
0105
0106 { NULL, NULL, 0 },
0107 };
0108
0109 #define IOMEM(x) ((void __iomem *)(KSEG1ADDR(CPHYSADDR(x))))
0110
0111
0112 static spinlock_t alchemy_clk_fg0_lock;
0113 static spinlock_t alchemy_clk_fg1_lock;
0114 static DEFINE_SPINLOCK(alchemy_clk_csrc_lock);
0115
0116
0117
0118 static unsigned long alchemy_clk_cpu_recalc(struct clk_hw *hw,
0119 unsigned long parent_rate)
0120 {
0121 unsigned long t;
0122
0123
0124
0125
0126
0127
0128 if (unlikely(au1xxx_cpu_has_pll_wo()))
0129 t = 396000000;
0130 else {
0131 t = alchemy_rdsys(AU1000_SYS_CPUPLL) & 0x7f;
0132 if (alchemy_get_cputype() < ALCHEMY_CPU_AU1300)
0133 t &= 0x3f;
0134 t *= parent_rate;
0135 }
0136
0137 return t;
0138 }
0139
0140 void __init alchemy_set_lpj(void)
0141 {
0142 preset_lpj = alchemy_clk_cpu_recalc(NULL, ALCHEMY_ROOTCLK_RATE);
0143 preset_lpj /= 2 * HZ;
0144 }
0145
0146 static const struct clk_ops alchemy_clkops_cpu = {
0147 .recalc_rate = alchemy_clk_cpu_recalc,
0148 };
0149
0150 static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name,
0151 int ctype)
0152 {
0153 struct clk_init_data id;
0154 struct clk_hw *h;
0155 struct clk *clk;
0156
0157 h = kzalloc(sizeof(*h), GFP_KERNEL);
0158 if (!h)
0159 return ERR_PTR(-ENOMEM);
0160
0161 id.name = ALCHEMY_CPU_CLK;
0162 id.parent_names = &parent_name;
0163 id.num_parents = 1;
0164 id.flags = 0;
0165 id.ops = &alchemy_clkops_cpu;
0166 h->init = &id;
0167
0168 clk = clk_register(NULL, h);
0169 if (IS_ERR(clk)) {
0170 pr_err("failed to register clock\n");
0171 kfree(h);
0172 }
0173
0174 return clk;
0175 }
0176
0177
0178
0179 struct alchemy_auxpll_clk {
0180 struct clk_hw hw;
0181 unsigned long reg;
0182 int maxmult;
0183 };
0184 #define to_auxpll_clk(x) container_of(x, struct alchemy_auxpll_clk, hw)
0185
0186 static unsigned long alchemy_clk_aux_recalc(struct clk_hw *hw,
0187 unsigned long parent_rate)
0188 {
0189 struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
0190
0191 return (alchemy_rdsys(a->reg) & 0xff) * parent_rate;
0192 }
0193
0194 static int alchemy_clk_aux_setr(struct clk_hw *hw,
0195 unsigned long rate,
0196 unsigned long parent_rate)
0197 {
0198 struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
0199 unsigned long d = rate;
0200
0201 if (rate)
0202 d /= parent_rate;
0203 else
0204 d = 0;
0205
0206
0207 if (((d < 7) && (d != 0)) || (d > a->maxmult))
0208 return -EINVAL;
0209
0210 alchemy_wrsys(d, a->reg);
0211 return 0;
0212 }
0213
0214 static long alchemy_clk_aux_roundr(struct clk_hw *hw,
0215 unsigned long rate,
0216 unsigned long *parent_rate)
0217 {
0218 struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
0219 unsigned long mult;
0220
0221 if (!rate || !*parent_rate)
0222 return 0;
0223
0224 mult = rate / (*parent_rate);
0225
0226 if (mult && (mult < 7))
0227 mult = 7;
0228 if (mult > a->maxmult)
0229 mult = a->maxmult;
0230
0231 return (*parent_rate) * mult;
0232 }
0233
0234 static const struct clk_ops alchemy_clkops_aux = {
0235 .recalc_rate = alchemy_clk_aux_recalc,
0236 .set_rate = alchemy_clk_aux_setr,
0237 .round_rate = alchemy_clk_aux_roundr,
0238 };
0239
0240 static struct clk __init *alchemy_clk_setup_aux(const char *parent_name,
0241 char *name, int maxmult,
0242 unsigned long reg)
0243 {
0244 struct clk_init_data id;
0245 struct clk *c;
0246 struct alchemy_auxpll_clk *a;
0247
0248 a = kzalloc(sizeof(*a), GFP_KERNEL);
0249 if (!a)
0250 return ERR_PTR(-ENOMEM);
0251
0252 id.name = name;
0253 id.parent_names = &parent_name;
0254 id.num_parents = 1;
0255 id.flags = CLK_GET_RATE_NOCACHE;
0256 id.ops = &alchemy_clkops_aux;
0257
0258 a->reg = reg;
0259 a->maxmult = maxmult;
0260 a->hw.init = &id;
0261
0262 c = clk_register(NULL, &a->hw);
0263 if (!IS_ERR(c))
0264 clk_register_clkdev(c, name, NULL);
0265 else
0266 kfree(a);
0267
0268 return c;
0269 }
0270
0271
0272
0273 static struct clk __init *alchemy_clk_setup_sysbus(const char *pn)
0274 {
0275 unsigned long v = (alchemy_rdsys(AU1000_SYS_POWERCTRL) & 3) + 2;
0276 struct clk *c;
0277
0278 c = clk_register_fixed_factor(NULL, ALCHEMY_SYSBUS_CLK,
0279 pn, 0, 1, v);
0280 if (!IS_ERR(c))
0281 clk_register_clkdev(c, ALCHEMY_SYSBUS_CLK, NULL);
0282 return c;
0283 }
0284
0285
0286
0287 static struct clk __init *alchemy_clk_setup_periph(const char *pn)
0288 {
0289
0290 struct clk *c;
0291
0292 c = clk_register_fixed_factor(NULL, ALCHEMY_PERIPH_CLK,
0293 pn, 0, 1, 2);
0294 if (!IS_ERR(c))
0295 clk_register_clkdev(c, ALCHEMY_PERIPH_CLK, NULL);
0296 return c;
0297 }
0298
0299
0300
0301 static struct clk __init *alchemy_clk_setup_mem(const char *pn, int ct)
0302 {
0303 void __iomem *addr = IOMEM(AU1000_MEM_PHYS_ADDR);
0304 unsigned long v;
0305 struct clk *c;
0306 int div;
0307
0308 switch (ct) {
0309 case ALCHEMY_CPU_AU1550:
0310 case ALCHEMY_CPU_AU1200:
0311 v = __raw_readl(addr + AU1550_MEM_SDCONFIGB);
0312 div = (v & (1 << 15)) ? 1 : 2;
0313 break;
0314 case ALCHEMY_CPU_AU1300:
0315 v = __raw_readl(addr + AU1550_MEM_SDCONFIGB);
0316 div = (v & (1 << 31)) ? 1 : 2;
0317 break;
0318 case ALCHEMY_CPU_AU1000:
0319 case ALCHEMY_CPU_AU1500:
0320 case ALCHEMY_CPU_AU1100:
0321 default:
0322 div = 2;
0323 break;
0324 }
0325
0326 c = clk_register_fixed_factor(NULL, ALCHEMY_MEM_CLK, pn,
0327 0, 1, div);
0328 if (!IS_ERR(c))
0329 clk_register_clkdev(c, ALCHEMY_MEM_CLK, NULL);
0330 return c;
0331 }
0332
0333
0334
0335 static struct clk __init *alchemy_clk_setup_lrclk(const char *pn, int t)
0336 {
0337
0338
0339
0340
0341
0342
0343
0344 struct clk *c;
0345 unsigned long v = alchemy_rdsmem(AU1000_MEM_STCFG0);
0346
0347 switch (t) {
0348 case ALCHEMY_CPU_AU1000:
0349 case ALCHEMY_CPU_AU1500:
0350 v = 4 + ((v >> 11) & 1);
0351 break;
0352 default:
0353 v = ((v >> 13) & 7) + 1;
0354 }
0355 c = clk_register_fixed_factor(NULL, ALCHEMY_LR_CLK,
0356 pn, 0, 1, v);
0357 if (!IS_ERR(c))
0358 clk_register_clkdev(c, ALCHEMY_LR_CLK, NULL);
0359 return c;
0360 }
0361
0362
0363
0364
0365 struct alchemy_fgcs_clk {
0366 struct clk_hw hw;
0367 spinlock_t *reglock;
0368 unsigned long reg;
0369 int shift;
0370 int parent;
0371 int isen;
0372 int *dt;
0373 };
0374 #define to_fgcs_clk(x) container_of(x, struct alchemy_fgcs_clk, hw)
0375
0376 static long alchemy_calc_div(unsigned long rate, unsigned long prate,
0377 int scale, int maxdiv, unsigned long *rv)
0378 {
0379 long div1, div2;
0380
0381 div1 = prate / rate;
0382 if ((prate / div1) > rate)
0383 div1++;
0384
0385 if (scale == 2) {
0386 if (div1 & 1)
0387 div1++;
0388 }
0389
0390 div2 = (div1 / scale) - 1;
0391
0392 if (div2 > maxdiv)
0393 div2 = maxdiv;
0394 if (rv)
0395 *rv = div2;
0396
0397 div1 = ((div2 + 1) * scale);
0398 return div1;
0399 }
0400
0401 static int alchemy_clk_fgcs_detr(struct clk_hw *hw,
0402 struct clk_rate_request *req,
0403 int scale, int maxdiv)
0404 {
0405 struct clk_hw *pc, *bpc, *free;
0406 long tdv, tpr, pr, nr, br, bpr, diff, lastdiff;
0407 int j;
0408
0409 lastdiff = INT_MAX;
0410 bpr = 0;
0411 bpc = NULL;
0412 br = -EINVAL;
0413 free = NULL;
0414
0415
0416
0417
0418 for (j = 0; j < 7; j++) {
0419 pc = clk_hw_get_parent_by_index(hw, j);
0420 if (!pc)
0421 break;
0422
0423
0424
0425
0426
0427 if (!clk_hw_is_prepared(pc)) {
0428 if (!free)
0429 free = pc;
0430 }
0431
0432 pr = clk_hw_get_rate(pc);
0433 if (pr < req->rate)
0434 continue;
0435
0436
0437 tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv, NULL);
0438 nr = pr / tdv;
0439 diff = req->rate - nr;
0440 if (nr > req->rate)
0441 continue;
0442
0443 if (diff < lastdiff) {
0444 lastdiff = diff;
0445 bpr = pr;
0446 bpc = pc;
0447 br = nr;
0448 }
0449 if (diff == 0)
0450 break;
0451 }
0452
0453
0454
0455
0456
0457 if (lastdiff && free) {
0458 for (j = (maxdiv == 4) ? 1 : scale; j <= maxdiv; j += scale) {
0459 tpr = req->rate * j;
0460 if (tpr < 0)
0461 break;
0462 pr = clk_hw_round_rate(free, tpr);
0463
0464 tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv,
0465 NULL);
0466 nr = pr / tdv;
0467 diff = req->rate - nr;
0468 if (nr > req->rate)
0469 continue;
0470 if (diff < lastdiff) {
0471 lastdiff = diff;
0472 bpr = pr;
0473 bpc = free;
0474 br = nr;
0475 }
0476 if (diff == 0)
0477 break;
0478 }
0479 }
0480
0481 if (br < 0)
0482 return br;
0483
0484 req->best_parent_rate = bpr;
0485 req->best_parent_hw = bpc;
0486 req->rate = br;
0487
0488 return 0;
0489 }
0490
0491 static int alchemy_clk_fgv1_en(struct clk_hw *hw)
0492 {
0493 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0494 unsigned long v, flags;
0495
0496 spin_lock_irqsave(c->reglock, flags);
0497 v = alchemy_rdsys(c->reg);
0498 v |= (1 << 1) << c->shift;
0499 alchemy_wrsys(v, c->reg);
0500 spin_unlock_irqrestore(c->reglock, flags);
0501
0502 return 0;
0503 }
0504
0505 static int alchemy_clk_fgv1_isen(struct clk_hw *hw)
0506 {
0507 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0508 unsigned long v = alchemy_rdsys(c->reg) >> (c->shift + 1);
0509
0510 return v & 1;
0511 }
0512
0513 static void alchemy_clk_fgv1_dis(struct clk_hw *hw)
0514 {
0515 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0516 unsigned long v, flags;
0517
0518 spin_lock_irqsave(c->reglock, flags);
0519 v = alchemy_rdsys(c->reg);
0520 v &= ~((1 << 1) << c->shift);
0521 alchemy_wrsys(v, c->reg);
0522 spin_unlock_irqrestore(c->reglock, flags);
0523 }
0524
0525 static int alchemy_clk_fgv1_setp(struct clk_hw *hw, u8 index)
0526 {
0527 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0528 unsigned long v, flags;
0529
0530 spin_lock_irqsave(c->reglock, flags);
0531 v = alchemy_rdsys(c->reg);
0532 if (index)
0533 v |= (1 << c->shift);
0534 else
0535 v &= ~(1 << c->shift);
0536 alchemy_wrsys(v, c->reg);
0537 spin_unlock_irqrestore(c->reglock, flags);
0538
0539 return 0;
0540 }
0541
0542 static u8 alchemy_clk_fgv1_getp(struct clk_hw *hw)
0543 {
0544 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0545
0546 return (alchemy_rdsys(c->reg) >> c->shift) & 1;
0547 }
0548
0549 static int alchemy_clk_fgv1_setr(struct clk_hw *hw, unsigned long rate,
0550 unsigned long parent_rate)
0551 {
0552 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0553 unsigned long div, v, flags, ret;
0554 int sh = c->shift + 2;
0555
0556 if (!rate || !parent_rate || rate > (parent_rate / 2))
0557 return -EINVAL;
0558 ret = alchemy_calc_div(rate, parent_rate, 2, 512, &div);
0559 spin_lock_irqsave(c->reglock, flags);
0560 v = alchemy_rdsys(c->reg);
0561 v &= ~(0xff << sh);
0562 v |= div << sh;
0563 alchemy_wrsys(v, c->reg);
0564 spin_unlock_irqrestore(c->reglock, flags);
0565
0566 return 0;
0567 }
0568
0569 static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
0570 unsigned long parent_rate)
0571 {
0572 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0573 unsigned long v = alchemy_rdsys(c->reg) >> (c->shift + 2);
0574
0575 v = ((v & 0xff) + 1) * 2;
0576 return parent_rate / v;
0577 }
0578
0579 static int alchemy_clk_fgv1_detr(struct clk_hw *hw,
0580 struct clk_rate_request *req)
0581 {
0582 return alchemy_clk_fgcs_detr(hw, req, 2, 512);
0583 }
0584
0585
0586 static const struct clk_ops alchemy_clkops_fgenv1 = {
0587 .recalc_rate = alchemy_clk_fgv1_recalc,
0588 .determine_rate = alchemy_clk_fgv1_detr,
0589 .set_rate = alchemy_clk_fgv1_setr,
0590 .set_parent = alchemy_clk_fgv1_setp,
0591 .get_parent = alchemy_clk_fgv1_getp,
0592 .enable = alchemy_clk_fgv1_en,
0593 .disable = alchemy_clk_fgv1_dis,
0594 .is_enabled = alchemy_clk_fgv1_isen,
0595 };
0596
0597 static void __alchemy_clk_fgv2_en(struct alchemy_fgcs_clk *c)
0598 {
0599 unsigned long v = alchemy_rdsys(c->reg);
0600
0601 v &= ~(3 << c->shift);
0602 v |= (c->parent & 3) << c->shift;
0603 alchemy_wrsys(v, c->reg);
0604 c->isen = 1;
0605 }
0606
0607 static int alchemy_clk_fgv2_en(struct clk_hw *hw)
0608 {
0609 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0610 unsigned long flags;
0611
0612
0613 spin_lock_irqsave(c->reglock, flags);
0614 __alchemy_clk_fgv2_en(c);
0615 spin_unlock_irqrestore(c->reglock, flags);
0616
0617 return 0;
0618 }
0619
0620 static int alchemy_clk_fgv2_isen(struct clk_hw *hw)
0621 {
0622 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0623
0624 return ((alchemy_rdsys(c->reg) >> c->shift) & 3) != 0;
0625 }
0626
0627 static void alchemy_clk_fgv2_dis(struct clk_hw *hw)
0628 {
0629 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0630 unsigned long v, flags;
0631
0632 spin_lock_irqsave(c->reglock, flags);
0633 v = alchemy_rdsys(c->reg);
0634 v &= ~(3 << c->shift);
0635 alchemy_wrsys(v, c->reg);
0636 c->isen = 0;
0637 spin_unlock_irqrestore(c->reglock, flags);
0638 }
0639
0640 static int alchemy_clk_fgv2_setp(struct clk_hw *hw, u8 index)
0641 {
0642 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0643 unsigned long flags;
0644
0645 spin_lock_irqsave(c->reglock, flags);
0646 c->parent = index + 1;
0647 if (c->isen)
0648 __alchemy_clk_fgv2_en(c);
0649 spin_unlock_irqrestore(c->reglock, flags);
0650
0651 return 0;
0652 }
0653
0654 static u8 alchemy_clk_fgv2_getp(struct clk_hw *hw)
0655 {
0656 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0657 unsigned long flags, v;
0658
0659 spin_lock_irqsave(c->reglock, flags);
0660 v = c->parent - 1;
0661 spin_unlock_irqrestore(c->reglock, flags);
0662 return v;
0663 }
0664
0665
0666
0667
0668
0669
0670 static int alchemy_clk_fgv2_setr(struct clk_hw *hw, unsigned long rate,
0671 unsigned long parent_rate)
0672 {
0673 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0674 int sh = c->shift + 2;
0675 unsigned long div, v, flags, ret;
0676
0677 if (!rate || !parent_rate || rate > parent_rate)
0678 return -EINVAL;
0679
0680 v = alchemy_rdsys(c->reg) & (1 << 30);
0681 ret = alchemy_calc_div(rate, parent_rate, v ? 1 : 2,
0682 v ? 256 : 512, &div);
0683
0684 spin_lock_irqsave(c->reglock, flags);
0685 v = alchemy_rdsys(c->reg);
0686 v &= ~(0xff << sh);
0687 v |= (div & 0xff) << sh;
0688 alchemy_wrsys(v, c->reg);
0689 spin_unlock_irqrestore(c->reglock, flags);
0690
0691 return 0;
0692 }
0693
0694 static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
0695 unsigned long parent_rate)
0696 {
0697 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0698 int sh = c->shift + 2;
0699 unsigned long v, t;
0700
0701 v = alchemy_rdsys(c->reg);
0702 t = parent_rate / (((v >> sh) & 0xff) + 1);
0703 if ((v & (1 << 30)) == 0)
0704 t /= 2;
0705
0706 return t;
0707 }
0708
0709 static int alchemy_clk_fgv2_detr(struct clk_hw *hw,
0710 struct clk_rate_request *req)
0711 {
0712 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0713 int scale, maxdiv;
0714
0715 if (alchemy_rdsys(c->reg) & (1 << 30)) {
0716 scale = 1;
0717 maxdiv = 256;
0718 } else {
0719 scale = 2;
0720 maxdiv = 512;
0721 }
0722
0723 return alchemy_clk_fgcs_detr(hw, req, scale, maxdiv);
0724 }
0725
0726
0727 static const struct clk_ops alchemy_clkops_fgenv2 = {
0728 .recalc_rate = alchemy_clk_fgv2_recalc,
0729 .determine_rate = alchemy_clk_fgv2_detr,
0730 .set_rate = alchemy_clk_fgv2_setr,
0731 .set_parent = alchemy_clk_fgv2_setp,
0732 .get_parent = alchemy_clk_fgv2_getp,
0733 .enable = alchemy_clk_fgv2_en,
0734 .disable = alchemy_clk_fgv2_dis,
0735 .is_enabled = alchemy_clk_fgv2_isen,
0736 };
0737
0738 static const char * const alchemy_clk_fgv1_parents[] = {
0739 ALCHEMY_CPU_CLK, ALCHEMY_AUXPLL_CLK
0740 };
0741
0742 static const char * const alchemy_clk_fgv2_parents[] = {
0743 ALCHEMY_AUXPLL2_CLK, ALCHEMY_CPU_CLK, ALCHEMY_AUXPLL_CLK
0744 };
0745
0746 static const char * const alchemy_clk_fgen_names[] = {
0747 ALCHEMY_FG0_CLK, ALCHEMY_FG1_CLK, ALCHEMY_FG2_CLK,
0748 ALCHEMY_FG3_CLK, ALCHEMY_FG4_CLK, ALCHEMY_FG5_CLK };
0749
0750 static int __init alchemy_clk_init_fgens(int ctype)
0751 {
0752 struct clk *c;
0753 struct clk_init_data id;
0754 struct alchemy_fgcs_clk *a;
0755 unsigned long v;
0756 int i, ret;
0757
0758 switch (ctype) {
0759 case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200:
0760 id.ops = &alchemy_clkops_fgenv1;
0761 id.parent_names = alchemy_clk_fgv1_parents;
0762 id.num_parents = 2;
0763 break;
0764 case ALCHEMY_CPU_AU1300:
0765 id.ops = &alchemy_clkops_fgenv2;
0766 id.parent_names = alchemy_clk_fgv2_parents;
0767 id.num_parents = 3;
0768 break;
0769 default:
0770 return -ENODEV;
0771 }
0772 id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
0773
0774 a = kzalloc((sizeof(*a)) * 6, GFP_KERNEL);
0775 if (!a)
0776 return -ENOMEM;
0777
0778 spin_lock_init(&alchemy_clk_fg0_lock);
0779 spin_lock_init(&alchemy_clk_fg1_lock);
0780 ret = 0;
0781 for (i = 0; i < 6; i++) {
0782 id.name = alchemy_clk_fgen_names[i];
0783 a->shift = 10 * (i < 3 ? i : i - 3);
0784 if (i > 2) {
0785 a->reg = AU1000_SYS_FREQCTRL1;
0786 a->reglock = &alchemy_clk_fg1_lock;
0787 } else {
0788 a->reg = AU1000_SYS_FREQCTRL0;
0789 a->reglock = &alchemy_clk_fg0_lock;
0790 }
0791
0792
0793
0794
0795 if (ctype == ALCHEMY_CPU_AU1300) {
0796 v = alchemy_rdsys(a->reg);
0797 a->parent = (v >> a->shift) & 3;
0798 if (!a->parent) {
0799 a->parent = 1;
0800 a->isen = 0;
0801 } else
0802 a->isen = 1;
0803 }
0804
0805 a->hw.init = &id;
0806 c = clk_register(NULL, &a->hw);
0807 if (IS_ERR(c))
0808 ret++;
0809 else
0810 clk_register_clkdev(c, id.name, NULL);
0811 a++;
0812 }
0813
0814 return ret;
0815 }
0816
0817
0818
0819 static int alchemy_clk_csrc_isen(struct clk_hw *hw)
0820 {
0821 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0822 unsigned long v = alchemy_rdsys(c->reg);
0823
0824 return (((v >> c->shift) >> 2) & 7) != 0;
0825 }
0826
0827 static void __alchemy_clk_csrc_en(struct alchemy_fgcs_clk *c)
0828 {
0829 unsigned long v = alchemy_rdsys(c->reg);
0830
0831 v &= ~((7 << 2) << c->shift);
0832 v |= ((c->parent & 7) << 2) << c->shift;
0833 alchemy_wrsys(v, c->reg);
0834 c->isen = 1;
0835 }
0836
0837 static int alchemy_clk_csrc_en(struct clk_hw *hw)
0838 {
0839 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0840 unsigned long flags;
0841
0842
0843 spin_lock_irqsave(c->reglock, flags);
0844 __alchemy_clk_csrc_en(c);
0845 spin_unlock_irqrestore(c->reglock, flags);
0846
0847 return 0;
0848 }
0849
0850 static void alchemy_clk_csrc_dis(struct clk_hw *hw)
0851 {
0852 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0853 unsigned long v, flags;
0854
0855 spin_lock_irqsave(c->reglock, flags);
0856 v = alchemy_rdsys(c->reg);
0857 v &= ~((3 << 2) << c->shift);
0858 alchemy_wrsys(v, c->reg);
0859 c->isen = 0;
0860 spin_unlock_irqrestore(c->reglock, flags);
0861 }
0862
0863 static int alchemy_clk_csrc_setp(struct clk_hw *hw, u8 index)
0864 {
0865 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0866 unsigned long flags;
0867
0868 spin_lock_irqsave(c->reglock, flags);
0869 c->parent = index + 1;
0870 if (c->isen)
0871 __alchemy_clk_csrc_en(c);
0872 spin_unlock_irqrestore(c->reglock, flags);
0873
0874 return 0;
0875 }
0876
0877 static u8 alchemy_clk_csrc_getp(struct clk_hw *hw)
0878 {
0879 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0880
0881 return c->parent - 1;
0882 }
0883
0884 static unsigned long alchemy_clk_csrc_recalc(struct clk_hw *hw,
0885 unsigned long parent_rate)
0886 {
0887 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0888 unsigned long v = (alchemy_rdsys(c->reg) >> c->shift) & 3;
0889
0890 return parent_rate / c->dt[v];
0891 }
0892
0893 static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
0894 unsigned long parent_rate)
0895 {
0896 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0897 unsigned long d, v, flags;
0898 int i;
0899
0900 if (!rate || !parent_rate || rate > parent_rate)
0901 return -EINVAL;
0902
0903 d = (parent_rate + (rate / 2)) / rate;
0904 if (d > 4)
0905 return -EINVAL;
0906 if ((d == 3) && (c->dt[2] != 3))
0907 d = 4;
0908
0909 for (i = 0; i < 4; i++)
0910 if (c->dt[i] == d)
0911 break;
0912
0913 if (i >= 4)
0914 return -EINVAL;
0915
0916 spin_lock_irqsave(c->reglock, flags);
0917 v = alchemy_rdsys(c->reg);
0918 v &= ~(3 << c->shift);
0919 v |= (i & 3) << c->shift;
0920 alchemy_wrsys(v, c->reg);
0921 spin_unlock_irqrestore(c->reglock, flags);
0922
0923 return 0;
0924 }
0925
0926 static int alchemy_clk_csrc_detr(struct clk_hw *hw,
0927 struct clk_rate_request *req)
0928 {
0929 struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
0930 int scale = c->dt[2] == 3 ? 1 : 2;
0931
0932 return alchemy_clk_fgcs_detr(hw, req, scale, 4);
0933 }
0934
0935 static const struct clk_ops alchemy_clkops_csrc = {
0936 .recalc_rate = alchemy_clk_csrc_recalc,
0937 .determine_rate = alchemy_clk_csrc_detr,
0938 .set_rate = alchemy_clk_csrc_setr,
0939 .set_parent = alchemy_clk_csrc_setp,
0940 .get_parent = alchemy_clk_csrc_getp,
0941 .enable = alchemy_clk_csrc_en,
0942 .disable = alchemy_clk_csrc_dis,
0943 .is_enabled = alchemy_clk_csrc_isen,
0944 };
0945
0946 static const char * const alchemy_clk_csrc_parents[] = {
0947 ALCHEMY_AUXPLL_CLK,
0948 ALCHEMY_FG0_CLK, ALCHEMY_FG1_CLK, ALCHEMY_FG2_CLK,
0949 ALCHEMY_FG3_CLK, ALCHEMY_FG4_CLK, ALCHEMY_FG5_CLK
0950 };
0951
0952
0953 static int alchemy_csrc_dt1[] = { 1, 4, 1, 2 };
0954 static int alchemy_csrc_dt2[] = { 1, 4, 3, 2 };
0955
0956 static int __init alchemy_clk_setup_imux(int ctype)
0957 {
0958 struct alchemy_fgcs_clk *a;
0959 const char * const *names;
0960 struct clk_init_data id;
0961 unsigned long v;
0962 int i, ret, *dt;
0963 struct clk *c;
0964
0965 id.ops = &alchemy_clkops_csrc;
0966 id.parent_names = alchemy_clk_csrc_parents;
0967 id.num_parents = 7;
0968 id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
0969
0970 dt = alchemy_csrc_dt1;
0971 switch (ctype) {
0972 case ALCHEMY_CPU_AU1000:
0973 names = alchemy_au1000_intclknames;
0974 break;
0975 case ALCHEMY_CPU_AU1500:
0976 names = alchemy_au1500_intclknames;
0977 break;
0978 case ALCHEMY_CPU_AU1100:
0979 names = alchemy_au1100_intclknames;
0980 break;
0981 case ALCHEMY_CPU_AU1550:
0982 names = alchemy_au1550_intclknames;
0983 break;
0984 case ALCHEMY_CPU_AU1200:
0985 names = alchemy_au1200_intclknames;
0986 break;
0987 case ALCHEMY_CPU_AU1300:
0988 dt = alchemy_csrc_dt2;
0989 names = alchemy_au1300_intclknames;
0990 break;
0991 default:
0992 return -ENODEV;
0993 }
0994
0995 a = kcalloc(6, sizeof(*a), GFP_KERNEL);
0996 if (!a)
0997 return -ENOMEM;
0998
0999 ret = 0;
1000
1001 for (i = 0; i < 6; i++) {
1002 id.name = names[i];
1003 if (!id.name)
1004 goto next;
1005
1006 a->shift = i * 5;
1007 a->reg = AU1000_SYS_CLKSRC;
1008 a->reglock = &alchemy_clk_csrc_lock;
1009 a->dt = dt;
1010
1011
1012
1013
1014 v = alchemy_rdsys(a->reg);
1015 a->parent = ((v >> a->shift) >> 2) & 7;
1016 if (!a->parent) {
1017 a->parent = 1;
1018 a->isen = 0;
1019 } else
1020 a->isen = 1;
1021
1022 a->hw.init = &id;
1023 c = clk_register(NULL, &a->hw);
1024 if (IS_ERR(c))
1025 ret++;
1026 else
1027 clk_register_clkdev(c, id.name, NULL);
1028 next:
1029 a++;
1030 }
1031
1032 return ret;
1033 }
1034
1035
1036
1037
1038
1039 #define ERRCK(x) \
1040 if (IS_ERR(x)) { \
1041 ret = PTR_ERR(x); \
1042 goto out; \
1043 }
1044
1045 static int __init alchemy_clk_init(void)
1046 {
1047 int ctype = alchemy_get_cputype(), ret, i;
1048 struct clk_aliastable *t = alchemy_clk_aliases;
1049 struct clk *c;
1050
1051
1052 c = clk_register_fixed_rate(NULL, ALCHEMY_ROOT_CLK, NULL,
1053 0, ALCHEMY_ROOTCLK_RATE);
1054 ERRCK(c)
1055
1056
1057 c = alchemy_clk_setup_cpu(ALCHEMY_ROOT_CLK, ctype);
1058 ERRCK(c)
1059
1060
1061 i = (ctype == ALCHEMY_CPU_AU1300) ? 84 : 63;
1062 c = alchemy_clk_setup_aux(ALCHEMY_ROOT_CLK, ALCHEMY_AUXPLL_CLK,
1063 i, AU1000_SYS_AUXPLL);
1064 ERRCK(c)
1065
1066 if (ctype == ALCHEMY_CPU_AU1300) {
1067 c = alchemy_clk_setup_aux(ALCHEMY_ROOT_CLK,
1068 ALCHEMY_AUXPLL2_CLK, i,
1069 AU1300_SYS_AUXPLL2);
1070 ERRCK(c)
1071 }
1072
1073
1074 c = alchemy_clk_setup_sysbus(ALCHEMY_CPU_CLK);
1075 ERRCK(c)
1076
1077
1078 c = alchemy_clk_setup_periph(ALCHEMY_SYSBUS_CLK);
1079 ERRCK(c)
1080
1081
1082 c = alchemy_clk_setup_mem(ALCHEMY_SYSBUS_CLK, ctype);
1083 ERRCK(c)
1084
1085
1086 c = alchemy_clk_setup_lrclk(ALCHEMY_PERIPH_CLK, ctype);
1087 ERRCK(c)
1088
1089
1090 ret = alchemy_clk_init_fgens(ctype);
1091 if (ret) {
1092 ret = -ENODEV;
1093 goto out;
1094 }
1095
1096
1097 ret = alchemy_clk_setup_imux(ctype);
1098 if (ret) {
1099 ret = -ENODEV;
1100 goto out;
1101 }
1102
1103
1104 while (t->base) {
1105 if (t->cputype == ctype)
1106 clk_add_alias(t->alias, NULL, t->base, NULL);
1107 t++;
1108 }
1109
1110 pr_info("Alchemy clocktree installed\n");
1111 return 0;
1112
1113 out:
1114 return ret;
1115 }
1116 postcore_initcall(alchemy_clk_init);