Skip to content

Commit

Permalink
MIPS: Add initial support for the Atheros AR71XX/AR724X/AR931X SoCs
Browse files Browse the repository at this point in the history
This patch adds initial support for various Atheros SoCs based on the
MIPS 24Kc core. The following models are supported at the moment:

  - AR7130
  - AR7141
  - AR7161
  - AR9130
  - AR9132
  - AR7240
  - AR7241
  - AR7242

The current patch contains minimal support only, but the resulting
kernel can boot into user-space with using of an initramfs image on
various boards which are using these SoCs. Support for more built-in
devices and individual boards will be implemented in further patches.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: Luis R. Rodriguez <lrodriguez@atheros.com>
Cc: Cliff Holden <Cliff.Holden@Atheros.com>
Cc: Kathy Giori <Kathy.Giori@Atheros.com>
Patchwork: https://patchwork.linux-mips.org/patch/1947/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Gabor Juhos authored and Ralf Baechle committed Jan 18, 2011
1 parent 94bb0c1 commit d4a67d9
Show file tree
Hide file tree
Showing 20 changed files with 1,365 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/mips/Kbuild.platforms
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

platforms += alchemy
platforms += ar7
platforms += ath79
platforms += bcm47xx
platforms += bcm63xx
platforms += cavium-octeon
Expand Down
15 changes: 15 additions & 0 deletions arch/mips/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,20 @@ config AR7
Support for the Texas Instruments AR7 System-on-a-Chip
family: TNETD7100, 7200 and 7300.

config ATH79
bool "Atheros AR71XX/AR724X/AR913X based boards"
select BOOT_RAW
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
select IRQ_CPU
select SYS_HAS_CPU_MIPS32_R2
select SYS_HAS_EARLY_PRINTK
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
help
Support for the Atheros AR71XX/AR724X/AR913X SoCs.

config BCM47XX
bool "Broadcom BCM47XX based boards"
select CEVT_R4K
Expand Down Expand Up @@ -718,6 +732,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
endchoice

source "arch/mips/alchemy/Kconfig"
source "arch/mips/ath79/Kconfig"
source "arch/mips/bcm63xx/Kconfig"
source "arch/mips/jazz/Kconfig"
source "arch/mips/jz4740/Kconfig"
Expand Down
12 changes: 12 additions & 0 deletions arch/mips/ath79/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
if ATH79

config SOC_AR71XX
def_bool n

config SOC_AR724X
def_bool n

config SOC_AR913X
def_bool n

endif
18 changes: 18 additions & 0 deletions arch/mips/ath79/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#
# Makefile for the Atheros AR71XX/AR724X/AR913X specific parts of the kernel
#
# Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
# Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 as published
# by the Free Software Foundation.

obj-y := prom.o setup.o irq.o common.o clock.o

obj-$(CONFIG_EARLY_PRINTK) += early_printk.o

#
# Devices
#
obj-y += dev-common.o
7 changes: 7 additions & 0 deletions arch/mips/ath79/Platform
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#
# Atheros AR71xx/AR724x/AR913x
#

platform-$(CONFIG_ATH79) += ath79/
cflags-$(CONFIG_ATH79) += -I$(srctree)/arch/mips/include/asm/mach-ath79
load-$(CONFIG_ATH79) = 0xffffffff80060000
183 changes: 183 additions & 0 deletions arch/mips/ath79/clock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*
* Atheros AR71XX/AR724X/AR913X common routines
*
* Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/clk.h>

#include <asm/mach-ath79/ath79.h>
#include <asm/mach-ath79/ar71xx_regs.h>
#include "common.h"

#define AR71XX_BASE_FREQ 40000000
#define AR724X_BASE_FREQ 5000000
#define AR913X_BASE_FREQ 5000000

struct clk {
unsigned long rate;
};

static struct clk ath79_ref_clk;
static struct clk ath79_cpu_clk;
static struct clk ath79_ddr_clk;
static struct clk ath79_ahb_clk;
static struct clk ath79_wdt_clk;
static struct clk ath79_uart_clk;

static void __init ar71xx_clocks_init(void)
{
u32 pll;
u32 freq;
u32 div;

ath79_ref_clk.rate = AR71XX_BASE_FREQ;

pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG);

div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1;
freq = div * ath79_ref_clk.rate;

div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1;
ath79_cpu_clk.rate = freq / div;

div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1;
ath79_ddr_clk.rate = freq / div;

div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2;
ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;

ath79_wdt_clk.rate = ath79_ahb_clk.rate;
ath79_uart_clk.rate = ath79_ahb_clk.rate;
}

static void __init ar724x_clocks_init(void)
{
u32 pll;
u32 freq;
u32 div;

ath79_ref_clk.rate = AR724X_BASE_FREQ;
pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG);

div = ((pll >> AR724X_PLL_DIV_SHIFT) & AR724X_PLL_DIV_MASK);
freq = div * ath79_ref_clk.rate;

div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK);
freq *= div;

ath79_cpu_clk.rate = freq;

div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1;
ath79_ddr_clk.rate = freq / div;

div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2;
ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;

ath79_wdt_clk.rate = ath79_ahb_clk.rate;
ath79_uart_clk.rate = ath79_ahb_clk.rate;
}

static void __init ar913x_clocks_init(void)
{
u32 pll;
u32 freq;
u32 div;

ath79_ref_clk.rate = AR913X_BASE_FREQ;
pll = ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG);

div = ((pll >> AR913X_PLL_DIV_SHIFT) & AR913X_PLL_DIV_MASK);
freq = div * ath79_ref_clk.rate;

ath79_cpu_clk.rate = freq;

div = ((pll >> AR913X_DDR_DIV_SHIFT) & AR913X_DDR_DIV_MASK) + 1;
ath79_ddr_clk.rate = freq / div;

div = (((pll >> AR913X_AHB_DIV_SHIFT) & AR913X_AHB_DIV_MASK) + 1) * 2;
ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;

ath79_wdt_clk.rate = ath79_ahb_clk.rate;
ath79_uart_clk.rate = ath79_ahb_clk.rate;
}

void __init ath79_clocks_init(void)
{
if (soc_is_ar71xx())
ar71xx_clocks_init();
else if (soc_is_ar724x())
ar724x_clocks_init();
else if (soc_is_ar913x())
ar913x_clocks_init();
else
BUG();

pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, "
"Ref:%lu.%03luMHz",
ath79_cpu_clk.rate / 1000000,
(ath79_cpu_clk.rate / 1000) % 1000,
ath79_ddr_clk.rate / 1000000,
(ath79_ddr_clk.rate / 1000) % 1000,
ath79_ahb_clk.rate / 1000000,
(ath79_ahb_clk.rate / 1000) % 1000,
ath79_ref_clk.rate / 1000000,
(ath79_ref_clk.rate / 1000) % 1000);
}

/*
* Linux clock API
*/
struct clk *clk_get(struct device *dev, const char *id)
{
if (!strcmp(id, "ref"))
return &ath79_ref_clk;

if (!strcmp(id, "cpu"))
return &ath79_cpu_clk;

if (!strcmp(id, "ddr"))
return &ath79_ddr_clk;

if (!strcmp(id, "ahb"))
return &ath79_ahb_clk;

if (!strcmp(id, "wdt"))
return &ath79_wdt_clk;

if (!strcmp(id, "uart"))
return &ath79_uart_clk;

return ERR_PTR(-ENOENT);
}
EXPORT_SYMBOL(clk_get);

int clk_enable(struct clk *clk)
{
return 0;
}
EXPORT_SYMBOL(clk_enable);

void clk_disable(struct clk *clk)
{
}
EXPORT_SYMBOL(clk_disable);

unsigned long clk_get_rate(struct clk *clk)
{
return clk->rate;
}
EXPORT_SYMBOL(clk_get_rate);

void clk_put(struct clk *clk)
{
}
EXPORT_SYMBOL(clk_put);
97 changes: 97 additions & 0 deletions arch/mips/ath79/common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Atheros AR71XX/AR724X/AR913X common routines
*
* Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/spinlock.h>

#include <asm/mach-ath79/ath79.h>
#include <asm/mach-ath79/ar71xx_regs.h>
#include "common.h"

static DEFINE_SPINLOCK(ath79_device_reset_lock);

u32 ath79_cpu_freq;
EXPORT_SYMBOL_GPL(ath79_cpu_freq);

u32 ath79_ahb_freq;
EXPORT_SYMBOL_GPL(ath79_ahb_freq);

u32 ath79_ddr_freq;
EXPORT_SYMBOL_GPL(ath79_ddr_freq);

enum ath79_soc_type ath79_soc;

void __iomem *ath79_pll_base;
void __iomem *ath79_reset_base;
EXPORT_SYMBOL_GPL(ath79_reset_base);
void __iomem *ath79_ddr_base;

void ath79_ddr_wb_flush(u32 reg)
{
void __iomem *flush_reg = ath79_ddr_base + reg;

/* Flush the DDR write buffer. */
__raw_writel(0x1, flush_reg);
while (__raw_readl(flush_reg) & 0x1)
;

/* It must be run twice. */
__raw_writel(0x1, flush_reg);
while (__raw_readl(flush_reg) & 0x1)
;
}
EXPORT_SYMBOL_GPL(ath79_ddr_wb_flush);

void ath79_device_reset_set(u32 mask)
{
unsigned long flags;
u32 reg;
u32 t;

if (soc_is_ar71xx())
reg = AR71XX_RESET_REG_RESET_MODULE;
else if (soc_is_ar724x())
reg = AR724X_RESET_REG_RESET_MODULE;
else if (soc_is_ar913x())
reg = AR913X_RESET_REG_RESET_MODULE;
else
BUG();

spin_lock_irqsave(&ath79_device_reset_lock, flags);
t = ath79_reset_rr(reg);
ath79_reset_wr(reg, t | mask);
spin_unlock_irqrestore(&ath79_device_reset_lock, flags);
}
EXPORT_SYMBOL_GPL(ath79_device_reset_set);

void ath79_device_reset_clear(u32 mask)
{
unsigned long flags;
u32 reg;
u32 t;

if (soc_is_ar71xx())
reg = AR71XX_RESET_REG_RESET_MODULE;
else if (soc_is_ar724x())
reg = AR724X_RESET_REG_RESET_MODULE;
else if (soc_is_ar913x())
reg = AR913X_RESET_REG_RESET_MODULE;
else
BUG();

spin_lock_irqsave(&ath79_device_reset_lock, flags);
t = ath79_reset_rr(reg);
ath79_reset_wr(reg, t & ~mask);
spin_unlock_irqrestore(&ath79_device_reset_lock, flags);
}
EXPORT_SYMBOL_GPL(ath79_device_reset_clear);
26 changes: 26 additions & 0 deletions arch/mips/ath79/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Atheros AR71XX/AR724X/AR913X common definitions
*
* Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* Parts of this file are based on Atheros' 2.6.15 BSP
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/

#ifndef __ATH79_COMMON_H
#define __ATH79_COMMON_H

#include <linux/types.h>
#include <linux/init.h>

#define ATH79_MEM_SIZE_MIN (2 * 1024 * 1024)
#define ATH79_MEM_SIZE_MAX (128 * 1024 * 1024)

void ath79_clocks_init(void);
void ath79_ddr_wb_flush(unsigned int reg);

#endif /* __ATH79_COMMON_H */
Loading

0 comments on commit d4a67d9

Please sign in to comment.