Path: blob/master/arch/powerpc/platforms/512x/clock.c
10820 views
/*1* Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.2*3* Author: John Rigby <[email protected]>4*5* Implements the clk api defined in include/linux/clk.h6*7* Original based on linux/arch/arm/mach-integrator/clock.c8*9* Copyright (C) 2004 ARM Limited.10* Written by Deep Blue Solutions Limited.11*12* This program is free software; you can redistribute it and/or modify13* it under the terms of the GNU General Public License version 2 as14* published by the Free Software Foundation.15*/16#include <linux/kernel.h>17#include <linux/list.h>18#include <linux/errno.h>19#include <linux/err.h>20#include <linux/string.h>21#include <linux/clk.h>22#include <linux/mutex.h>23#include <linux/io.h>2425#include <linux/of_platform.h>26#include <asm/mpc5xxx.h>27#include <asm/clk_interface.h>2829#undef CLK_DEBUG3031static int clocks_initialized;3233#define CLK_HAS_RATE 0x1 /* has rate in MHz */34#define CLK_HAS_CTRL 0x2 /* has control reg and bit */3536struct clk {37struct list_head node;38char name[32];39int flags;40struct device *dev;41unsigned long rate;42struct module *owner;43void (*calc) (struct clk *);44struct clk *parent;45int reg, bit; /* CLK_HAS_CTRL */46int div_shift; /* only used by generic_div_clk_calc */47};4849static LIST_HEAD(clocks);50static DEFINE_MUTEX(clocks_mutex);5152static struct clk *mpc5121_clk_get(struct device *dev, const char *id)53{54struct clk *p, *clk = ERR_PTR(-ENOENT);55int dev_match = 0;56int id_match = 0;5758if (dev == NULL || id == NULL)59return clk;6061mutex_lock(&clocks_mutex);62list_for_each_entry(p, &clocks, node) {63if (dev == p->dev)64dev_match++;65if (strcmp(id, p->name) == 0)66id_match++;67if ((dev_match || id_match) && try_module_get(p->owner)) {68clk = p;69break;70}71}72mutex_unlock(&clocks_mutex);7374return clk;75}7677#ifdef CLK_DEBUG78static void dump_clocks(void)79{80struct clk *p;8182mutex_lock(&clocks_mutex);83printk(KERN_INFO "CLOCKS:\n");84list_for_each_entry(p, &clocks, node) {85pr_info(" %s=%ld", p->name, p->rate);86if (p->parent)87pr_cont(" %s=%ld", p->parent->name,88p->parent->rate);89if (p->flags & CLK_HAS_CTRL)90pr_cont(" reg/bit=%d/%d", p->reg, p->bit);91pr_cont("\n");92}93mutex_unlock(&clocks_mutex);94}95#define DEBUG_CLK_DUMP() dump_clocks()96#else97#define DEBUG_CLK_DUMP()98#endif99100101static void mpc5121_clk_put(struct clk *clk)102{103module_put(clk->owner);104}105106#define NRPSC 12107108struct mpc512x_clockctl {109u32 spmr; /* System PLL Mode Reg */110u32 sccr[2]; /* System Clk Ctrl Reg 1 & 2 */111u32 scfr1; /* System Clk Freq Reg 1 */112u32 scfr2; /* System Clk Freq Reg 2 */113u32 reserved;114u32 bcr; /* Bread Crumb Reg */115u32 pccr[NRPSC]; /* PSC Clk Ctrl Reg 0-11 */116u32 spccr; /* SPDIF Clk Ctrl Reg */117u32 cccr; /* CFM Clk Ctrl Reg */118u32 dccr; /* DIU Clk Cnfg Reg */119};120121struct mpc512x_clockctl __iomem *clockctl;122123static int mpc5121_clk_enable(struct clk *clk)124{125unsigned int mask;126127if (clk->flags & CLK_HAS_CTRL) {128mask = in_be32(&clockctl->sccr[clk->reg]);129mask |= 1 << clk->bit;130out_be32(&clockctl->sccr[clk->reg], mask);131}132return 0;133}134135static void mpc5121_clk_disable(struct clk *clk)136{137unsigned int mask;138139if (clk->flags & CLK_HAS_CTRL) {140mask = in_be32(&clockctl->sccr[clk->reg]);141mask &= ~(1 << clk->bit);142out_be32(&clockctl->sccr[clk->reg], mask);143}144}145146static unsigned long mpc5121_clk_get_rate(struct clk *clk)147{148if (clk->flags & CLK_HAS_RATE)149return clk->rate;150else151return 0;152}153154static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)155{156return rate;157}158159static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)160{161return 0;162}163164static int clk_register(struct clk *clk)165{166mutex_lock(&clocks_mutex);167list_add(&clk->node, &clocks);168mutex_unlock(&clocks_mutex);169return 0;170}171172static unsigned long spmf_mult(void)173{174/*175* Convert spmf to multiplier176*/177static int spmf_to_mult[] = {17868, 1, 12, 16,17920, 24, 28, 32,18036, 40, 44, 48,18152, 56, 60, 64182};183int spmf = (clockctl->spmr >> 24) & 0xf;184return spmf_to_mult[spmf];185}186187static unsigned long sysdiv_div_x_2(void)188{189/*190* Convert sysdiv to divisor x 2191* Some divisors have fractional parts so192* multiply by 2 then divide by this value193*/194static int sysdiv_to_div_x_2[] = {1954, 5, 6, 7,1968, 9, 10, 14,19712, 16, 18, 22,19820, 24, 26, 30,19928, 32, 34, 38,20036, 40, 42, 46,20144, 48, 50, 54,20252, 56, 58, 62,20360, 64, 66,204};205int sysdiv = (clockctl->scfr2 >> 26) & 0x3f;206return sysdiv_to_div_x_2[sysdiv];207}208209static unsigned long ref_to_sys(unsigned long rate)210{211rate *= spmf_mult();212rate *= 2;213rate /= sysdiv_div_x_2();214215return rate;216}217218static unsigned long sys_to_ref(unsigned long rate)219{220rate *= sysdiv_div_x_2();221rate /= 2;222rate /= spmf_mult();223224return rate;225}226227static long ips_to_ref(unsigned long rate)228{229int ips_div = (clockctl->scfr1 >> 23) & 0x7;230231rate *= ips_div; /* csb_clk = ips_clk * ips_div */232rate *= 2; /* sys_clk = csb_clk * 2 */233return sys_to_ref(rate);234}235236static unsigned long devtree_getfreq(char *clockname)237{238struct device_node *np;239const unsigned int *prop;240unsigned int val = 0;241242np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");243if (np) {244prop = of_get_property(np, clockname, NULL);245if (prop)246val = *prop;247of_node_put(np);248}249return val;250}251252static void ref_clk_calc(struct clk *clk)253{254unsigned long rate;255256rate = devtree_getfreq("bus-frequency");257if (rate == 0) {258printk(KERN_ERR "No bus-frequency in dev tree\n");259clk->rate = 0;260return;261}262clk->rate = ips_to_ref(rate);263}264265static struct clk ref_clk = {266.name = "ref_clk",267.calc = ref_clk_calc,268};269270271static void sys_clk_calc(struct clk *clk)272{273clk->rate = ref_to_sys(ref_clk.rate);274}275276static struct clk sys_clk = {277.name = "sys_clk",278.calc = sys_clk_calc,279};280281static void diu_clk_calc(struct clk *clk)282{283int diudiv_x_2 = clockctl->scfr1 & 0xff;284unsigned long rate;285286rate = sys_clk.rate;287288rate *= 2;289rate /= diudiv_x_2;290291clk->rate = rate;292}293294static void viu_clk_calc(struct clk *clk)295{296unsigned long rate;297298rate = sys_clk.rate;299rate /= 2;300clk->rate = rate;301}302303static void half_clk_calc(struct clk *clk)304{305clk->rate = clk->parent->rate / 2;306}307308static void generic_div_clk_calc(struct clk *clk)309{310int div = (clockctl->scfr1 >> clk->div_shift) & 0x7;311312clk->rate = clk->parent->rate / div;313}314315static void unity_clk_calc(struct clk *clk)316{317clk->rate = clk->parent->rate;318}319320static struct clk csb_clk = {321.name = "csb_clk",322.calc = half_clk_calc,323.parent = &sys_clk,324};325326static void e300_clk_calc(struct clk *clk)327{328int spmf = (clockctl->spmr >> 16) & 0xf;329int ratex2 = clk->parent->rate * spmf;330331clk->rate = ratex2 / 2;332}333334static struct clk e300_clk = {335.name = "e300_clk",336.calc = e300_clk_calc,337.parent = &csb_clk,338};339340static struct clk ips_clk = {341.name = "ips_clk",342.calc = generic_div_clk_calc,343.parent = &csb_clk,344.div_shift = 23,345};346347/*348* Clocks controlled by SCCR1 (.reg = 0)349*/350static struct clk lpc_clk = {351.name = "lpc_clk",352.flags = CLK_HAS_CTRL,353.reg = 0,354.bit = 30,355.calc = generic_div_clk_calc,356.parent = &ips_clk,357.div_shift = 11,358};359360static struct clk nfc_clk = {361.name = "nfc_clk",362.flags = CLK_HAS_CTRL,363.reg = 0,364.bit = 29,365.calc = generic_div_clk_calc,366.parent = &ips_clk,367.div_shift = 8,368};369370static struct clk pata_clk = {371.name = "pata_clk",372.flags = CLK_HAS_CTRL,373.reg = 0,374.bit = 28,375.calc = unity_clk_calc,376.parent = &ips_clk,377};378379/*380* PSC clocks (bits 27 - 16)381* are setup elsewhere382*/383384static struct clk sata_clk = {385.name = "sata_clk",386.flags = CLK_HAS_CTRL,387.reg = 0,388.bit = 14,389.calc = unity_clk_calc,390.parent = &ips_clk,391};392393static struct clk fec_clk = {394.name = "fec_clk",395.flags = CLK_HAS_CTRL,396.reg = 0,397.bit = 13,398.calc = unity_clk_calc,399.parent = &ips_clk,400};401402static struct clk pci_clk = {403.name = "pci_clk",404.flags = CLK_HAS_CTRL,405.reg = 0,406.bit = 11,407.calc = generic_div_clk_calc,408.parent = &csb_clk,409.div_shift = 20,410};411412/*413* Clocks controlled by SCCR2 (.reg = 1)414*/415static struct clk diu_clk = {416.name = "diu_clk",417.flags = CLK_HAS_CTRL,418.reg = 1,419.bit = 31,420.calc = diu_clk_calc,421};422423static struct clk viu_clk = {424.name = "viu_clk",425.flags = CLK_HAS_CTRL,426.reg = 1,427.bit = 18,428.calc = viu_clk_calc,429};430431static struct clk axe_clk = {432.name = "axe_clk",433.flags = CLK_HAS_CTRL,434.reg = 1,435.bit = 30,436.calc = unity_clk_calc,437.parent = &csb_clk,438};439440static struct clk usb1_clk = {441.name = "usb1_clk",442.flags = CLK_HAS_CTRL,443.reg = 1,444.bit = 28,445.calc = unity_clk_calc,446.parent = &csb_clk,447};448449static struct clk usb2_clk = {450.name = "usb2_clk",451.flags = CLK_HAS_CTRL,452.reg = 1,453.bit = 27,454.calc = unity_clk_calc,455.parent = &csb_clk,456};457458static struct clk i2c_clk = {459.name = "i2c_clk",460.flags = CLK_HAS_CTRL,461.reg = 1,462.bit = 26,463.calc = unity_clk_calc,464.parent = &ips_clk,465};466467static struct clk mscan_clk = {468.name = "mscan_clk",469.flags = CLK_HAS_CTRL,470.reg = 1,471.bit = 25,472.calc = unity_clk_calc,473.parent = &ips_clk,474};475476static struct clk sdhc_clk = {477.name = "sdhc_clk",478.flags = CLK_HAS_CTRL,479.reg = 1,480.bit = 24,481.calc = unity_clk_calc,482.parent = &ips_clk,483};484485static struct clk mbx_bus_clk = {486.name = "mbx_bus_clk",487.flags = CLK_HAS_CTRL,488.reg = 1,489.bit = 22,490.calc = half_clk_calc,491.parent = &csb_clk,492};493494static struct clk mbx_clk = {495.name = "mbx_clk",496.flags = CLK_HAS_CTRL,497.reg = 1,498.bit = 21,499.calc = unity_clk_calc,500.parent = &csb_clk,501};502503static struct clk mbx_3d_clk = {504.name = "mbx_3d_clk",505.flags = CLK_HAS_CTRL,506.reg = 1,507.bit = 20,508.calc = generic_div_clk_calc,509.parent = &mbx_bus_clk,510.div_shift = 14,511};512513static void psc_mclk_in_calc(struct clk *clk)514{515clk->rate = devtree_getfreq("psc_mclk_in");516if (!clk->rate)517clk->rate = 25000000;518}519520static struct clk psc_mclk_in = {521.name = "psc_mclk_in",522.calc = psc_mclk_in_calc,523};524525static struct clk spdif_txclk = {526.name = "spdif_txclk",527.flags = CLK_HAS_CTRL,528.reg = 1,529.bit = 23,530};531532static struct clk spdif_rxclk = {533.name = "spdif_rxclk",534.flags = CLK_HAS_CTRL,535.reg = 1,536.bit = 23,537};538539static void ac97_clk_calc(struct clk *clk)540{541/* ac97 bit clock is always 24.567 MHz */542clk->rate = 24567000;543}544545static struct clk ac97_clk = {546.name = "ac97_clk_in",547.calc = ac97_clk_calc,548};549550struct clk *rate_clks[] = {551&ref_clk,552&sys_clk,553&diu_clk,554&viu_clk,555&csb_clk,556&e300_clk,557&ips_clk,558&fec_clk,559&sata_clk,560&pata_clk,561&nfc_clk,562&lpc_clk,563&mbx_bus_clk,564&mbx_clk,565&mbx_3d_clk,566&axe_clk,567&usb1_clk,568&usb2_clk,569&i2c_clk,570&mscan_clk,571&sdhc_clk,572&pci_clk,573&psc_mclk_in,574&spdif_txclk,575&spdif_rxclk,576&ac97_clk,577NULL578};579580static void rate_clk_init(struct clk *clk)581{582if (clk->calc) {583clk->calc(clk);584clk->flags |= CLK_HAS_RATE;585clk_register(clk);586} else {587printk(KERN_WARNING588"Could not initialize clk %s without a calc routine\n",589clk->name);590}591}592593static void rate_clks_init(void)594{595struct clk **cpp, *clk;596597cpp = rate_clks;598while ((clk = *cpp++))599rate_clk_init(clk);600}601602/*603* There are two clk enable registers with 32 enable bits each604* psc clocks and device clocks are all stored in dev_clks605*/606struct clk dev_clks[2][32];607608/*609* Given a psc number return the dev_clk610* associated with it611*/612static struct clk *psc_dev_clk(int pscnum)613{614int reg, bit;615struct clk *clk;616617reg = 0;618bit = 27 - pscnum;619620clk = &dev_clks[reg][bit];621clk->reg = 0;622clk->bit = bit;623return clk;624}625626/*627* PSC clock rate calculation628*/629static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)630{631unsigned long mclk_src = sys_clk.rate;632unsigned long mclk_div;633634/*635* Can only change value of mclk divider636* when the divider is disabled.637*638* Zero is not a valid divider so minimum639* divider is 1640*641* disable/set divider/enable642*/643out_be32(&clockctl->pccr[pscnum], 0);644out_be32(&clockctl->pccr[pscnum], 0x00020000);645out_be32(&clockctl->pccr[pscnum], 0x00030000);646647if (clockctl->pccr[pscnum] & 0x80) {648clk->rate = spdif_rxclk.rate;649return;650}651652switch ((clockctl->pccr[pscnum] >> 14) & 0x3) {653case 0:654mclk_src = sys_clk.rate;655break;656case 1:657mclk_src = ref_clk.rate;658break;659case 2:660mclk_src = psc_mclk_in.rate;661break;662case 3:663mclk_src = spdif_txclk.rate;664break;665}666667mclk_div = ((clockctl->pccr[pscnum] >> 17) & 0x7fff) + 1;668clk->rate = mclk_src / mclk_div;669}670671/*672* Find all psc nodes in device tree and assign a clock673* with name "psc%d_mclk" and dev pointing at the device674* returned from of_find_device_by_node675*/676static void psc_clks_init(void)677{678struct device_node *np;679const u32 *cell_index;680struct platform_device *ofdev;681682for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {683cell_index = of_get_property(np, "cell-index", NULL);684if (cell_index) {685int pscnum = *cell_index;686struct clk *clk = psc_dev_clk(pscnum);687688clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL;689ofdev = of_find_device_by_node(np);690clk->dev = &ofdev->dev;691/*692* AC97 is special rate clock does693* not go through normal path694*/695if (strcmp("ac97", np->name) == 0)696clk->rate = ac97_clk.rate;697else698psc_calc_rate(clk, pscnum, np);699sprintf(clk->name, "psc%d_mclk", pscnum);700clk_register(clk);701clk_enable(clk);702}703}704}705706static struct clk_interface mpc5121_clk_functions = {707.clk_get = mpc5121_clk_get,708.clk_enable = mpc5121_clk_enable,709.clk_disable = mpc5121_clk_disable,710.clk_get_rate = mpc5121_clk_get_rate,711.clk_put = mpc5121_clk_put,712.clk_round_rate = mpc5121_clk_round_rate,713.clk_set_rate = mpc5121_clk_set_rate,714.clk_set_parent = NULL,715.clk_get_parent = NULL,716};717718int __init mpc5121_clk_init(void)719{720struct device_node *np;721722np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");723if (np) {724clockctl = of_iomap(np, 0);725of_node_put(np);726}727728if (!clockctl) {729printk(KERN_ERR "Could not map clock control registers\n");730return 0;731}732733rate_clks_init();734psc_clks_init();735736/* leave clockctl mapped forever */737/*iounmap(clockctl); */738DEBUG_CLK_DUMP();739clocks_initialized++;740clk_functions = mpc5121_clk_functions;741return 0;742}743744745