mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-11 15:49:56 +00:00
Merge ep93xx branch
This commit is contained in:
commit
c1e08adc86
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Makefile for the linux kernel.
|
# Makefile for the linux kernel.
|
||||||
#
|
#
|
||||||
obj-y := core.o
|
obj-y := core.o clock.o
|
||||||
obj-m :=
|
obj-m :=
|
||||||
obj-n :=
|
obj-n :=
|
||||||
obj- :=
|
obj- :=
|
||||||
|
156
arch/arm/mach-ep93xx/clock.c
Normal file
156
arch/arm/mach-ep93xx/clock.c
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* arch/arm/mach-ep93xx/clock.c
|
||||||
|
* Clock control for Cirrus EP93xx chips.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <asm/div64.h>
|
||||||
|
#include <asm/hardware.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
struct clk {
|
||||||
|
char *name;
|
||||||
|
unsigned long rate;
|
||||||
|
int users;
|
||||||
|
u32 enable_reg;
|
||||||
|
u32 enable_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk clk_pll1 = {
|
||||||
|
.name = "pll1",
|
||||||
|
};
|
||||||
|
static struct clk clk_f = {
|
||||||
|
.name = "fclk",
|
||||||
|
};
|
||||||
|
static struct clk clk_h = {
|
||||||
|
.name = "hclk",
|
||||||
|
};
|
||||||
|
static struct clk clk_p = {
|
||||||
|
.name = "pclk",
|
||||||
|
};
|
||||||
|
static struct clk clk_pll2 = {
|
||||||
|
.name = "pll2",
|
||||||
|
};
|
||||||
|
static struct clk clk_usb_host = {
|
||||||
|
.name = "usb_host",
|
||||||
|
.enable_reg = EP93XX_SYSCON_CLOCK_CONTROL,
|
||||||
|
.enable_mask = EP93XX_SYSCON_CLOCK_USH_EN,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct clk *clocks[] = {
|
||||||
|
&clk_pll1,
|
||||||
|
&clk_f,
|
||||||
|
&clk_h,
|
||||||
|
&clk_p,
|
||||||
|
&clk_pll2,
|
||||||
|
&clk_usb_host,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clk *clk_get(struct device *dev, const char *id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(clocks); i++) {
|
||||||
|
if (!strcmp(clocks[i]->name, id))
|
||||||
|
return clocks[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_PTR(-ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int clk_enable(struct clk *clk)
|
||||||
|
{
|
||||||
|
if (!clk->users++ && clk->enable_reg) {
|
||||||
|
u32 value;
|
||||||
|
|
||||||
|
value = __raw_readl(clk->enable_reg);
|
||||||
|
__raw_writel(value | clk->enable_mask, clk->enable_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clk_disable(struct clk *clk)
|
||||||
|
{
|
||||||
|
if (!--clk->users && clk->enable_reg) {
|
||||||
|
u32 value;
|
||||||
|
|
||||||
|
value = __raw_readl(clk->enable_reg);
|
||||||
|
__raw_writel(value & ~clk->enable_mask, clk->enable_reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long clk_get_rate(struct clk *clk)
|
||||||
|
{
|
||||||
|
return clk->rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clk_put(struct clk *clk)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
|
||||||
|
static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
|
||||||
|
static char pclk_divisors[] = { 1, 2, 4, 8 };
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
|
||||||
|
*/
|
||||||
|
static unsigned long calc_pll_rate(u32 config_word)
|
||||||
|
{
|
||||||
|
unsigned long long rate;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
rate = 14745600;
|
||||||
|
rate *= ((config_word >> 11) & 0x1f) + 1; /* X1FBD */
|
||||||
|
rate *= ((config_word >> 5) & 0x3f) + 1; /* X2FBD */
|
||||||
|
do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */
|
||||||
|
for (i = 0; i < ((config_word >> 16) & 3); i++) /* PS */
|
||||||
|
rate >>= 1;
|
||||||
|
|
||||||
|
return (unsigned long)rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ep93xx_clock_init(void)
|
||||||
|
{
|
||||||
|
u32 value;
|
||||||
|
|
||||||
|
value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1);
|
||||||
|
if (!(value & 0x00800000)) { /* PLL1 bypassed? */
|
||||||
|
clk_pll1.rate = 14745600;
|
||||||
|
} else {
|
||||||
|
clk_pll1.rate = calc_pll_rate(value);
|
||||||
|
}
|
||||||
|
clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];
|
||||||
|
clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];
|
||||||
|
clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];
|
||||||
|
|
||||||
|
value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2);
|
||||||
|
if (!(value & 0x00080000)) { /* PLL2 bypassed? */
|
||||||
|
clk_pll2.rate = 14745600;
|
||||||
|
} else if (value & 0x00040000) { /* PLL2 enabled? */
|
||||||
|
clk_pll2.rate = calc_pll_rate(value);
|
||||||
|
} else {
|
||||||
|
clk_pll2.rate = 0;
|
||||||
|
}
|
||||||
|
clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1);
|
||||||
|
|
||||||
|
printk(KERN_INFO "ep93xx: PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
|
||||||
|
clk_pll1.rate / 1000000, clk_pll2.rate / 1000000);
|
||||||
|
printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
|
||||||
|
clk_f.rate / 1000000, clk_h.rate / 1000000,
|
||||||
|
clk_p.rate / 1000000);
|
||||||
|
}
|
@ -433,10 +433,37 @@ static struct platform_device ep93xx_rtc_device = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct resource ep93xx_ohci_resources[] = {
|
||||||
|
[0] = {
|
||||||
|
.start = EP93XX_USB_PHYS_BASE,
|
||||||
|
.end = EP93XX_USB_PHYS_BASE + 0x0fff,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
[1] = {
|
||||||
|
.start = IRQ_EP93XX_USB,
|
||||||
|
.end = IRQ_EP93XX_USB,
|
||||||
|
.flags = IORESOURCE_IRQ,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device ep93xx_ohci_device = {
|
||||||
|
.name = "ep93xx-ohci",
|
||||||
|
.id = -1,
|
||||||
|
.dev = {
|
||||||
|
.dma_mask = (void *)0xffffffff,
|
||||||
|
.coherent_dma_mask = 0xffffffff,
|
||||||
|
},
|
||||||
|
.num_resources = ARRAY_SIZE(ep93xx_ohci_resources),
|
||||||
|
.resource = ep93xx_ohci_resources,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
void __init ep93xx_init_devices(void)
|
void __init ep93xx_init_devices(void)
|
||||||
{
|
{
|
||||||
unsigned int v;
|
unsigned int v;
|
||||||
|
|
||||||
|
ep93xx_clock_init();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disallow access to MaverickCrunch initially.
|
* Disallow access to MaverickCrunch initially.
|
||||||
*/
|
*/
|
||||||
@ -450,4 +477,5 @@ void __init ep93xx_init_devices(void)
|
|||||||
amba_device_register(&uart3_device, &iomem_resource);
|
amba_device_register(&uart3_device, &iomem_resource);
|
||||||
|
|
||||||
platform_device_register(&ep93xx_rtc_device);
|
platform_device_register(&ep93xx_rtc_device);
|
||||||
|
platform_device_register(&ep93xx_ohci_device);
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,8 @@
|
|||||||
#define EP93XX_SYSCON_CLOCK_USH_EN 0x10000000
|
#define EP93XX_SYSCON_CLOCK_USH_EN 0x10000000
|
||||||
#define EP93XX_SYSCON_HALT EP93XX_SYSCON_REG(0x08)
|
#define EP93XX_SYSCON_HALT EP93XX_SYSCON_REG(0x08)
|
||||||
#define EP93XX_SYSCON_STANDBY EP93XX_SYSCON_REG(0x0c)
|
#define EP93XX_SYSCON_STANDBY EP93XX_SYSCON_REG(0x0c)
|
||||||
|
#define EP93XX_SYSCON_CLOCK_SET1 EP93XX_SYSCON_REG(0x20)
|
||||||
|
#define EP93XX_SYSCON_CLOCK_SET2 EP93XX_SYSCON_REG(0x24)
|
||||||
#define EP93XX_SYSCON_DEVICE_CONFIG EP93XX_SYSCON_REG(0x80)
|
#define EP93XX_SYSCON_DEVICE_CONFIG EP93XX_SYSCON_REG(0x80)
|
||||||
#define EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE 0x00800000
|
#define EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE 0x00800000
|
||||||
#define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0)
|
#define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0)
|
||||||
|
@ -8,6 +8,7 @@ void ep93xx_map_io(void);
|
|||||||
void ep93xx_init_irq(void);
|
void ep93xx_init_irq(void);
|
||||||
void ep93xx_init_time(unsigned long);
|
void ep93xx_init_time(unsigned long);
|
||||||
void ep93xx_init_devices(void);
|
void ep93xx_init_devices(void);
|
||||||
|
void ep93xx_clock_init(void);
|
||||||
extern struct sys_timer ep93xx_timer;
|
extern struct sys_timer ep93xx_timer;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user