/*
* Alchemy clocks.
*
* Exposes all configurable internal clock sources to the clk framework.
*
* We have:
* - Root source, usually 12MHz supplied by an external crystal
* - 3 PLLs which generate multiples of root rate [AUX, CPU, AUX2]
*
* Dividers:
* - 6 clock dividers with:
* * selectable source [one of the PLLs],
* * output divided between [2 .. 512 in steps of 2] (!Au1300)
* or [1 .. 256 in steps of 1] (Au1300),
* * can be enabled individually.
*
* - up to 6 "internal" (fixed) consumers which:
* * take either AUXPLL or one of the above 6 dividers as input,
* * divide this input by 1, 2, or 4 (and 3 on Au1300).
* * can be disabled separately.
*
* Misc clocks:
* - sysbus clock: CPU core clock (CPUPLL) divided by 2, 3 or 4.
* depends on board design and should be set by bootloader, read-only.
* - peripheral clock: half the rate of sysbus clock, source for a lot
* of peripheral blocks, read-only.
* - memory clock: clk rate to main memory chips, depends on board
* design and is read-only,
* - lrclk: the static bus clock signal for synchronous operation.
* depends on board design, must be set by bootloader,
* but may be required to correctly configure devices attached to
* the static bus. The Au1000/1500/1100 manuals call it LCLK, on
* later models it's called RCLK.
*/
#include <linux/init.h>
#include <linux/io.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <asm/mach-au1x00/au1000.h>
/* Base clock: 12MHz is the default in all databooks, and I haven't
* found any board yet which uses a different rate.
*/
#define ALCHEMY_ROOTCLK_RATE 12000000
/*
* the internal sources which can be driven by the PLLs and dividers.
* Names taken from the databooks, refer to them for more information,
* especially which ones are share a clock line.
*/
static const char * const alchemy_au1300_intclknames[] = {
"lcd_intclk", "gpemgp_clk", "maempe_clk", "maebsa_clk",
"EXTCLK0", "EXTCLK1"
};
static const char * const alchemy_au1200_intclknames[] = {
"lcd_intclk", NULL, NULL, NULL, "EXTCLK0", "EXTCLK1"
};
static const char * const alchemy_au1550_intclknames[] = {
"usb_clk", "psc0_intclk", "psc1_intclk", "pci_clko",
"EXTCLK0", "EXTCLK1"
};
static const char * const alchemy_au1100_intclknames[] = {
"usb_clk", "lcd_intclk", NULL, "i2s_clk", "EXTCLK0", "EXTCLK1"
};
static const char * const alchemy_au1500_intclknames[] = {
NULL, "usbd_clk", "usbh_clk", "pci_clko", "EXTCLK0", "EXTCLK1"
};
static const char * const alchemy_au1000_intclknames[] = {
"irda_clk", "usbd_clk", "usbh_clk", "i2s_clk", "EXTCLK0",
"EXTCLK1"
};
/* aliases for a few on-chip sources which are either shared
* or have gone through name changes.
*/
static struct clk_aliastable {
char *alias;
char *base;
int cputype;
} alchemy_clk_aliases[] __initdata = {
{ "usbh_clk", "usb_clk", ALCHEMY_CPU_AU1100 },
{ "usbd_clk", "usb_clk", ALCHEMY_CPU_AU1100 },
{ "irda_clk", "usb_clk", ALCHEMY_CPU_AU1100 },
{ "usbh_clk", "usb_clk", ALCHEMY_CPU_AU1550 },
{ "usbd_clk", "usb_clk", ALCHEMY_CPU_AU1550 },
{ "psc2_intclk", "usb_clk", ALCHEMY_CPU_AU1550 },
{ "psc3_intclk", "EXTCLK0", ALCHEMY_CPU_AU1550 },
{ "psc0_intclk", "EXTCLK0", ALCHEMY_CPU_AU1200 },
{ "psc1_intclk", "EXTCLK1", ALCHEMY_CPU_AU1200 },
{ "psc0_intclk", "EXTCLK0", ALCHEMY_CPU_AU1300 },
{ "psc2_intclk", "EXTCLK0", ALCHEMY_CPU_AU1300 },
{ "psc1_intclk", "EXTCLK1", ALCHEMY_CPU_AU1300 },
{ "psc3_intclk", "EXTCLK1", ALCHEMY_CPU_AU1300 },
{ NULL, NULL, 0 },
};
#define IOMEM(x) ((void __iomem *)(KSEG1ADDR(CPHYSADDR(x))))
/* access locks to SYS_FREQCTRL0/1 and SYS_CLKSRC registers */
static spinlock_t alchemy_clk_fg0_lock;
static spinlock_t alchemy_clk_fg1_lock;
static spinlock_t alchemy_clk_csrc_lock;
/* CPU Core clock *****************************************************/
static unsigned long alchemy_clk_cpu_recalc(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long t;
/*
* On early Au1000, sys_cpupll was write-only. Since these
* silicon versions of Au1000 are not sold, we don't bend
* over backwards trying to determine the frequency.
*/
if (unlikely(au1xxx_cpu_has_pll_wo()))
t = 396000000;
else {
t = alchemy_rdsys(AU1000_SYS_CPUPLL) & 0x7f;
t *= parent_rate;
}
return t;
}
static struct clk_ops alchemy_clkops_cpu = {
.recalc_rate = alchemy_clk_cpu_recalc,
};
static