/*
- * Copyright (C) 2007 OpenWrt.org
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@openwrt.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
#define TNETD7200_DEF_USB_CLK 48000000
struct tnetd7300_clock {
- volatile u32 ctrl;
+ u32 ctrl;
#define PREDIV_MASK 0x001f0000
#define PREDIV_SHIFT 16
#define POSTDIV_MASK 0x0000001f
u32 unused1[3];
- volatile u32 pll;
+ u32 pll;
#define MUL_MASK 0x0000f000
#define MUL_SHIFT 12
#define PLL_MODE_MASK 0x00000001
#define PLL_DIV 0x00000002
#define PLL_STATUS 0x00000001
u32 unused2[3];
-} __attribute__ ((packed));
+};
struct tnetd7300_clocks {
struct tnetd7300_clock bus;
struct tnetd7300_clock cpu;
struct tnetd7300_clock usb;
struct tnetd7300_clock dsp;
-} __attribute__ ((packed));
+};
struct tnetd7200_clock {
- volatile u32 ctrl;
+ u32 ctrl;
u32 unused1[3];
#define DIVISOR_ENABLE_MASK 0x00008000
- volatile u32 mul;
- volatile u32 prediv;
- volatile u32 postdiv;
- volatile u32 postdiv2;
+ u32 mul;
+ u32 prediv;
+ u32 postdiv;
+ u32 postdiv2;
u32 unused2[6];
- volatile u32 cmd;
- volatile u32 status;
- volatile u32 cmden;
+ u32 cmd;
+ u32 status;
+ u32 cmden;
u32 padding[15];
-} __attribute__ ((packed));
+};
struct tnetd7200_clocks {
struct tnetd7200_clock cpu;
struct tnetd7200_clock dsp;
struct tnetd7200_clock usb;
-} __attribute__ ((packed));
+};
int ar7_cpu_clock = 150000000;
EXPORT_SYMBOL(ar7_cpu_clock);
int *postdiv, int *mul)
{
int i, j, k, freq, res = target;
- for (i = 1; i <= 16; i++) {
- for (j = 1; j <= 32; j++) {
+ for (i = 1; i <= 16; i++)
+ for (j = 1; j <= 32; j++)
for (k = 1; k <= 32; k++) {
freq = abs(base / j * i / k - target);
if (freq < res) {
*postdiv = k;
}
}
- }
- }
}
static void calculate(int base, int target, int *prediv, int *postdiv,
{
int product;
int base_clock = AR7_REF_CLOCK;
- u32 ctrl = clock->ctrl;
- u32 pll = clock->pll;
+ u32 ctrl = readl(&clock->ctrl);
+ u32 pll = readl(&clock->pll);
int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1;
int postdiv = (ctrl & POSTDIV_MASK) + 1;
int divisor = prediv * postdiv;
static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
u32 *bootcr, u32 frequency)
{
- u32 status;
int prediv, postdiv, mul;
int base_clock = ar7_bus_clock;
calculate(base_clock, frequency, &prediv, &postdiv, &mul);
- clock->ctrl = ((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1);
+ writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
mdelay(1);
- clock->pll = 4;
- do {
- status = clock->pll;
- } while (status & PLL_STATUS);
- clock->pll = ((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e;
+ writel(4, &clock->pll);
+ while (readl(&clock->pll) & PLL_STATUS);
+ writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
mdelay(75);
}
ar7_bus_clock = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
&clocks->bus, bootcr, AR7_AFE_CLOCK);
- if (*bootcr & BOOT_PLL_ASYNC_MODE) {
+ if (*bootcr & BOOT_PLL_ASYNC_MODE)
ar7_cpu_clock = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
&clocks->cpu, bootcr, AR7_AFE_CLOCK);
- } else {
+ else
ar7_cpu_clock = ar7_bus_clock;
- }
/*
tnetd7300_set_clock(USB_PLL_SOURCE_SHIFT, &clocks->usb,
bootcr, 48000000);
static int tnetd7200_get_clock(int base, struct tnetd7200_clock *clock,
u32 *bootcr, u32 bus_clock)
{
- int divisor = ((clock->prediv & 0x1f) + 1) *
- ((clock->postdiv & 0x1f) + 1);
+ int divisor = ((readl(&clock->prediv) & 0x1f) + 1) *
+ ((readl(&clock->postdiv) & 0x1f) + 1);
if (*bootcr & BOOT_PLL_BYPASS)
return base / divisor;
- return base * ((clock->mul & 0xf) + 1) / divisor;
+ return base * ((readl(&clock->mul) & 0xf) + 1) / divisor;
}
"postdiv = %d, postdiv2 = %d, mul = %d\n",
base, frequency, prediv, postdiv, postdiv2, mul);
- clock->ctrl = 0;
- clock->prediv = DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F);
- clock->mul = ((mul - 1) & 0xF);
+ writel(0, &clock->ctrl);
+ writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
+ writel((mul - 1) & 0xF, &clock->mul);
for (mul = 0; mul < 2000; mul++) /* nop */;
- while (clock->status & 0x1) /* nop */;
+ while (readl(&clock->status) & 0x1) /* nop */;
- clock->postdiv = DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F);
+ writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
- clock->cmden |= 1;
- clock->cmd |= 1;
+ writel(readl(&clock->cmden) | 1, &clock->cmden);
+ writel(readl(&clock->cmd) | 1, &clock->cmd);
- while (clock->status & 0x1) /* nop */;
+ while (readl(&clock->status) & 0x1) /* nop */;
- clock->postdiv2 = DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F);
+ writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
- clock->cmden |= 1;
- clock->cmd |= 1;
+ writel(readl(&clock->cmden) | 1, &clock->cmden);
+ writel(readl(&clock->cmd) | 1, &clock->cmd);
- while (clock->status & 0x1) /* nop */;
+ while (readl(&clock->status) & 0x1) /* nop */;
- clock->ctrl |= 1;
+ writel(readl(&clock->ctrl) | 1, &clock->ctrl);
}
static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr)
{
- if (*bootcr & BOOT_PLL_ASYNC_MODE) {
+ if (*bootcr & BOOT_PLL_ASYNC_MODE)
/* Async */
switch (clock_id) {
case TNETD7200_CLOCK_ID_DSP:
default:
return AR7_AFE_CLOCK;
}
- } else {
+ else
/* Sync */
- if (*bootcr & BOOT_PLL_2TO1_MODE) {
+ if (*bootcr & BOOT_PLL_2TO1_MODE)
/* 2:1 */
switch (clock_id) {
case TNETD7200_CLOCK_ID_DSP:
default:
return AR7_AFE_CLOCK;
}
- } else {
+ else
/* 1:1 */
return AR7_REF_CLOCK;
- }
- }
}
cpu_prediv, cpu_postdiv, -1, cpu_mul,
ar7_cpu_clock);
- } else {
+ } else
if (*bootcr & BOOT_PLL_2TO1_MODE) {
printk(KERN_INFO "Clocks: Sync 2:1 mode\n");
ar7_cpu_clock = ar7_bus_clock;
}
- }
printk(KERN_INFO "Clocks: Setting USB clock\n");
usb_base = ar7_bus_clock;