mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2025-04-21 12:27:27 +03:00
[brcm63xx] move files to files-2.6.30, to ease newer kernel integration
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@19471 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
35
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/Kconfig
Normal file
35
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/Kconfig
Normal file
@@ -0,0 +1,35 @@
|
||||
menu "CPU support"
|
||||
depends on BCM63XX
|
||||
|
||||
config BCM63XX_CPU_6338
|
||||
bool "support 6338 CPU"
|
||||
select HW_HAS_PCI
|
||||
select USB_ARCH_HAS_OHCI
|
||||
select USB_ARCH_HAS_UDC
|
||||
select USB_OHCI_BIG_ENDIAN_DESC
|
||||
select USB_OHCI_BIG_ENDIAN_MMIO
|
||||
|
||||
config BCM63XX_CPU_6345
|
||||
bool "support 6345 CPU"
|
||||
select USB_OHCI_BIG_ENDIAN_DESC
|
||||
select USB_OHCI_BIG_ENDIAN_MMIO
|
||||
|
||||
config BCM63XX_CPU_6348
|
||||
bool "support 6348 CPU"
|
||||
select HW_HAS_PCI
|
||||
select USB_ARCH_HAS_OHCI
|
||||
select USB_ARCH_HAS_UDC
|
||||
select USB_OHCI_BIG_ENDIAN_DESC
|
||||
select USB_OHCI_BIG_ENDIAN_MMIO
|
||||
|
||||
config BCM63XX_CPU_6358
|
||||
bool "support 6358 CPU"
|
||||
select HW_HAS_PCI
|
||||
select USB_ARCH_HAS_OHCI
|
||||
select USB_OHCI_BIG_ENDIAN_DESC
|
||||
select USB_OHCI_BIG_ENDIAN_MMIO
|
||||
select USB_ARCH_HAS_EHCI
|
||||
select USB_EHCI_BIG_ENDIAN_MMIO
|
||||
endmenu
|
||||
|
||||
source "arch/mips/bcm63xx/boards/Kconfig"
|
||||
@@ -0,0 +1,13 @@
|
||||
obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o
|
||||
obj-y += dev-uart.o
|
||||
obj-y += dev-pcmcia.o
|
||||
obj-y += dev-usb-ohci.o
|
||||
obj-y += dev-usb-ehci.o
|
||||
obj-y += dev-usb-udc.o
|
||||
obj-y += dev-enet.o
|
||||
obj-y += dev-wdt.o
|
||||
obj-y += dev-spi.o
|
||||
obj-y += dev-dsp.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
|
||||
obj-y += boards/
|
||||
@@ -0,0 +1,15 @@
|
||||
choice
|
||||
prompt "Board support"
|
||||
depends on BCM63XX
|
||||
default BOARD_BCM963XX
|
||||
|
||||
config BOARD_BCM963XX
|
||||
bool "Generic Broadcom 963xx boards"
|
||||
help
|
||||
|
||||
config BOARD_LIVEBOX
|
||||
bool "Inventel Livebox(es) boards"
|
||||
help
|
||||
Boards using RedBoot.
|
||||
|
||||
endchoice
|
||||
@@ -0,0 +1,2 @@
|
||||
obj-$(CONFIG_BOARD_BCM963XX) += board_bcm963xx.o
|
||||
obj-$(CONFIG_BOARD_LIVEBOX) += board_livebox.o
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <bcm63xx_board.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_board.h>
|
||||
#include <bcm63xx_dev_pci.h>
|
||||
#include <bcm63xx_dev_uart.h>
|
||||
#include <bcm63xx_dev_wdt.h>
|
||||
#include <bcm63xx_dev_enet.h>
|
||||
#include <bcm63xx_dev_pcmcia.h>
|
||||
#include <bcm63xx_dev_usb_ohci.h>
|
||||
#include <bcm63xx_dev_usb_ehci.h>
|
||||
#include <board_bcm963xx.h>
|
||||
|
||||
#define PFX "board_livebox: "
|
||||
|
||||
static unsigned int mac_addr_used = 0;
|
||||
static struct board_info board;
|
||||
|
||||
/*
|
||||
* known 6348 boards
|
||||
*/
|
||||
#ifdef CONFIG_BCM63XX_CPU_6348
|
||||
static struct board_info __initdata board_livebox = {
|
||||
.name = "Livebox",
|
||||
.expected_cpu_id = 0x6348,
|
||||
|
||||
.has_enet0 = 1,
|
||||
.has_enet1 = 1,
|
||||
.has_pci = 1,
|
||||
|
||||
.enet0 = {
|
||||
.has_phy = 1,
|
||||
.use_internal_phy = 1,
|
||||
},
|
||||
|
||||
.enet1 = {
|
||||
.force_speed_100 = 1,
|
||||
.force_duplex_full = 1,
|
||||
},
|
||||
|
||||
.has_ohci0 = 1,
|
||||
.has_pccard = 1,
|
||||
.has_ehci0 = 1,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* all boards
|
||||
*/
|
||||
static const struct board_info __initdata *bcm963xx_boards[] = {
|
||||
#ifdef CONFIG_BCM63XX_CPU_6348
|
||||
&board_livebox
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* early init callback
|
||||
*/
|
||||
void __init board_prom_init(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* read base address of boot chip select (0) */
|
||||
val = bcm_mpi_readl(MPI_CSBASE_REG(0));
|
||||
val &= MPI_CSBASE_BASE_MASK;
|
||||
|
||||
/* assume board is a Livebox */
|
||||
memcpy(&board, bcm963xx_boards[0], sizeof(board));
|
||||
|
||||
/* setup pin multiplexing depending on board enabled device,
|
||||
* this has to be done this early since PCI init is done
|
||||
* inside arch_initcall */
|
||||
val = 0;
|
||||
|
||||
if (board.has_pci) {
|
||||
bcm63xx_pci_enabled = 1;
|
||||
if (BCMCPU_IS_6348())
|
||||
val |= GPIO_MODE_6348_G2_PCI;
|
||||
}
|
||||
|
||||
if (board.has_pccard) {
|
||||
if (BCMCPU_IS_6348())
|
||||
val |= GPIO_MODE_6348_G1_MII_PCCARD;
|
||||
}
|
||||
|
||||
if (board.has_enet0 && !board.enet0.use_internal_phy) {
|
||||
if (BCMCPU_IS_6348())
|
||||
val |= GPIO_MODE_6348_G3_EXT_MII |
|
||||
GPIO_MODE_6348_G0_EXT_MII;
|
||||
}
|
||||
|
||||
if (board.has_enet1 && !board.enet1.use_internal_phy) {
|
||||
if (BCMCPU_IS_6348())
|
||||
val |= GPIO_MODE_6348_G3_EXT_MII |
|
||||
GPIO_MODE_6348_G0_EXT_MII;
|
||||
}
|
||||
|
||||
bcm_gpio_writel(val, GPIO_MODE_REG);
|
||||
}
|
||||
|
||||
/*
|
||||
* second stage init callback, good time to panic if we couldn't
|
||||
* identify on which board we're running since early printk is working
|
||||
*/
|
||||
void __init board_setup(void)
|
||||
{
|
||||
if (!board.name[0])
|
||||
panic("unable to detect bcm963xx board");
|
||||
printk(KERN_INFO PFX "board name: %s\n", board.name);
|
||||
|
||||
/* make sure we're running on expected cpu */
|
||||
if (bcm63xx_get_cpu_id() != board.expected_cpu_id)
|
||||
panic("unexpected CPU for bcm963xx board");
|
||||
}
|
||||
|
||||
/*
|
||||
* return board name for /proc/cpuinfo
|
||||
*/
|
||||
const char *board_get_name(void)
|
||||
{
|
||||
return board.name;
|
||||
}
|
||||
|
||||
/*
|
||||
* register & return a new board mac address
|
||||
*/
|
||||
|
||||
static int board_get_mac_address(u8 *mac)
|
||||
{
|
||||
u8 default_mac[ETH_ALEN] = {0x00, 0x07, 0x3A, 0x00, 0x00, 0x00};
|
||||
u8 *p;
|
||||
int count;
|
||||
|
||||
memcpy(mac, default_mac, ETH_ALEN);
|
||||
|
||||
p = mac + ETH_ALEN - 1;
|
||||
count = mac_addr_used;
|
||||
|
||||
while (count--) {
|
||||
do {
|
||||
(*p)++;
|
||||
if (*p != 0)
|
||||
break;
|
||||
p--;
|
||||
} while (p != mac);
|
||||
}
|
||||
|
||||
if (p == mac) {
|
||||
printk(KERN_ERR PFX "unable to fetch mac address\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
mac_addr_used++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct resource mtd_resources[] = {
|
||||
{
|
||||
.start = 0, /* filled at runtime */
|
||||
.end = 0, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device mtd_dev = {
|
||||
.name = "bcm963xx-flash",
|
||||
.resource = mtd_resources,
|
||||
.num_resources = ARRAY_SIZE(mtd_resources),
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* third stage init callback, register all board devices.
|
||||
*/
|
||||
int __init board_register_devices(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
bcm63xx_uart_register();
|
||||
bcm63xx_wdt_register();
|
||||
|
||||
if (board.has_pccard)
|
||||
bcm63xx_pcmcia_register();
|
||||
|
||||
if (board.has_enet0 &&
|
||||
!board_get_mac_address(board.enet0.mac_addr))
|
||||
bcm63xx_enet_register(0, &board.enet0);
|
||||
|
||||
if (board.has_enet1 &&
|
||||
!board_get_mac_address(board.enet1.mac_addr))
|
||||
bcm63xx_enet_register(1, &board.enet1);
|
||||
|
||||
if (board.has_ohci0)
|
||||
bcm63xx_ohci_register();
|
||||
|
||||
if (board.has_ehci0)
|
||||
bcm63xx_ehci_register();
|
||||
|
||||
|
||||
/* read base address of boot chip select (0) */
|
||||
val = bcm_mpi_readl(MPI_CSBASE_REG(0));
|
||||
val &= MPI_CSBASE_BASE_MASK;
|
||||
mtd_resources[0].start = val;
|
||||
mtd_resources[0].end = 0x1FFFFFFF;
|
||||
|
||||
platform_device_register(&mtd_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
249
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/clk.c
Normal file
249
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/clk.c
Normal file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
#include <bcm63xx_clk.h>
|
||||
|
||||
DEFINE_MUTEX(clocks_mutex);
|
||||
|
||||
|
||||
static void clk_enable_unlocked(struct clk *clk)
|
||||
{
|
||||
if (clk->set && (clk->usage++) == 0)
|
||||
clk->set(clk, 1);
|
||||
}
|
||||
|
||||
static void clk_disable_unlocked(struct clk *clk)
|
||||
{
|
||||
if (clk->set && (--clk->usage) == 0)
|
||||
clk->set(clk, 0);
|
||||
}
|
||||
|
||||
static void bcm_hwclock_set(u32 mask, int enable)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = bcm_perf_readl(PERF_CKCTL_REG);
|
||||
if (enable)
|
||||
reg |= mask;
|
||||
else
|
||||
reg &= ~mask;
|
||||
bcm_perf_writel(reg, PERF_CKCTL_REG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ethernet MAC "misc" clock: dma clocks and main clock on 6348
|
||||
*/
|
||||
static void enet_misc_set(struct clk *clk, int enable)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
if (BCMCPU_IS_6338())
|
||||
mask = CKCTL_6338_ENET_EN;
|
||||
else if (BCMCPU_IS_6345())
|
||||
mask = CKCTL_6345_ENET_EN;
|
||||
else if (BCMCPU_IS_6348())
|
||||
mask = CKCTL_6348_ENET_EN;
|
||||
else
|
||||
/* BCMCPU_IS_6358 */
|
||||
mask = CKCTL_6358_EMUSB_EN;
|
||||
bcm_hwclock_set(mask, enable);
|
||||
}
|
||||
|
||||
static struct clk clk_enet_misc = {
|
||||
.set = enet_misc_set,
|
||||
};
|
||||
|
||||
/*
|
||||
* Ethernet MAC clocks: only revelant on 6358, silently enable misc
|
||||
* clocks
|
||||
*/
|
||||
static void enetx_set(struct clk *clk, int enable)
|
||||
{
|
||||
if (enable)
|
||||
clk_enable_unlocked(&clk_enet_misc);
|
||||
else
|
||||
clk_disable_unlocked(&clk_enet_misc);
|
||||
|
||||
if (BCMCPU_IS_6358()) {
|
||||
u32 mask;
|
||||
|
||||
if (clk->id == 0)
|
||||
mask = CKCTL_6358_ENET0_EN;
|
||||
else
|
||||
mask = CKCTL_6358_ENET1_EN;
|
||||
bcm_hwclock_set(mask, enable);
|
||||
}
|
||||
}
|
||||
|
||||
static struct clk clk_enet0 = {
|
||||
.id = 0,
|
||||
.set = enetx_set,
|
||||
};
|
||||
|
||||
static struct clk clk_enet1 = {
|
||||
.id = 1,
|
||||
.set = enetx_set,
|
||||
};
|
||||
|
||||
/*
|
||||
* Ethernet PHY clock
|
||||
*/
|
||||
static void ephy_set(struct clk *clk, int enable)
|
||||
{
|
||||
if (!BCMCPU_IS_6358())
|
||||
return;
|
||||
bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable);
|
||||
}
|
||||
|
||||
|
||||
static struct clk clk_ephy = {
|
||||
.set = ephy_set,
|
||||
};
|
||||
|
||||
/*
|
||||
* PCM clock
|
||||
*/
|
||||
static void pcm_set(struct clk *clk, int enable)
|
||||
{
|
||||
if (!BCMCPU_IS_6358())
|
||||
return;
|
||||
bcm_hwclock_set(CKCTL_6358_PCM_EN, enable);
|
||||
}
|
||||
|
||||
static struct clk clk_pcm = {
|
||||
.set = pcm_set,
|
||||
};
|
||||
|
||||
/*
|
||||
* USB host clock
|
||||
*/
|
||||
static void usbh_set(struct clk *clk, int enable)
|
||||
{
|
||||
if (!BCMCPU_IS_6348())
|
||||
return;
|
||||
bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
|
||||
}
|
||||
|
||||
static struct clk clk_usbh = {
|
||||
.set = usbh_set,
|
||||
};
|
||||
|
||||
/*
|
||||
* USB slave clock
|
||||
*/
|
||||
static void usbs_set(struct clk *clk, int enable)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
switch(bcm63xx_get_cpu_id()) {
|
||||
case BCM6338_CPU_ID: mask = CKCTL_6338_USBS_EN; break;
|
||||
case BCM6345_CPU_ID: mask = CKCTL_6345_USBS_EN; break;
|
||||
case BCM6348_CPU_ID: mask = CKCTL_6348_USBS_EN; break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
bcm_hwclock_set(mask, enable);
|
||||
}
|
||||
|
||||
static struct clk clk_usbs = {
|
||||
.set = usbs_set,
|
||||
};
|
||||
|
||||
/*
|
||||
* SPI clock
|
||||
*/
|
||||
static void spi_set(struct clk *clk, int enable)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
if (BCMCPU_IS_6338())
|
||||
mask = CKCTL_6338_SPI_EN;
|
||||
else if (BCMCPU_IS_6348())
|
||||
mask = CKCTL_6348_SPI_EN;
|
||||
else
|
||||
/* BCMCPU_IS_6358 */
|
||||
mask = CKCTL_6358_SPI_EN;
|
||||
bcm_hwclock_set(mask, enable);
|
||||
}
|
||||
|
||||
static struct clk clk_spi = {
|
||||
.set = spi_set,
|
||||
};
|
||||
|
||||
/*
|
||||
* Internal peripheral clock
|
||||
*/
|
||||
static struct clk clk_periph = {
|
||||
.rate = (50 * 1000 * 1000),
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Linux clock API implementation
|
||||
*/
|
||||
int clk_enable(struct clk *clk)
|
||||
{
|
||||
mutex_lock(&clocks_mutex);
|
||||
clk_enable_unlocked(clk);
|
||||
mutex_unlock(&clocks_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(clk_enable);
|
||||
|
||||
void clk_disable(struct clk *clk)
|
||||
{
|
||||
mutex_lock(&clocks_mutex);
|
||||
clk_disable_unlocked(clk);
|
||||
mutex_unlock(&clocks_mutex);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(clk_disable);
|
||||
|
||||
unsigned long clk_get_rate(struct clk *clk)
|
||||
{
|
||||
return clk->rate;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(clk_get_rate);
|
||||
|
||||
struct clk *clk_get(struct device *dev, const char *id)
|
||||
{
|
||||
if (!strcmp(id, "enet0"))
|
||||
return &clk_enet0;
|
||||
if (!strcmp(id, "enet1"))
|
||||
return &clk_enet1;
|
||||
if (!strcmp(id, "ephy"))
|
||||
return &clk_ephy;
|
||||
if (!strcmp(id, "usbh"))
|
||||
return &clk_usbh;
|
||||
if (!strcmp(id, "usbs"))
|
||||
return &clk_usbs;
|
||||
if (!strcmp(id, "spi"))
|
||||
return &clk_spi;
|
||||
if (!strcmp(id, "periph"))
|
||||
return &clk_periph;
|
||||
if (BCMCPU_IS_6358() && !strcmp(id, "pcm"))
|
||||
return &clk_pcm;
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(clk_get);
|
||||
|
||||
void clk_put(struct clk *clk)
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(clk_put);
|
||||
398
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/cpu.c
Normal file
398
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/cpu.c
Normal file
@@ -0,0 +1,398 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
* 2009 Florian Fainelli <florian@openwrt.org>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_irq.h>
|
||||
|
||||
const unsigned long *bcm63xx_regs_base;
|
||||
EXPORT_SYMBOL(bcm63xx_regs_base);
|
||||
|
||||
const int *bcm63xx_irqs;
|
||||
EXPORT_SYMBOL(bcm63xx_irqs);
|
||||
|
||||
const unsigned long *bcm63xx_regs_spi;
|
||||
EXPORT_SYMBOL(bcm63xx_regs_spi);
|
||||
|
||||
static u16 bcm63xx_cpu_id;
|
||||
static u16 bcm63xx_cpu_rev;
|
||||
static unsigned int bcm63xx_cpu_freq;
|
||||
static unsigned int bcm63xx_memory_size;
|
||||
|
||||
/*
|
||||
* 6338 register sets and irqs
|
||||
*/
|
||||
|
||||
static const unsigned long bcm96338_regs_base[] = {
|
||||
[RSET_DSL_LMEM] = BCM_6338_DSL_LMEM_BASE,
|
||||
[RSET_PERF] = BCM_6338_PERF_BASE,
|
||||
[RSET_TIMER] = BCM_6338_TIMER_BASE,
|
||||
[RSET_WDT] = BCM_6338_WDT_BASE,
|
||||
[RSET_UART0] = BCM_6338_UART0_BASE,
|
||||
[RSET_GPIO] = BCM_6338_GPIO_BASE,
|
||||
[RSET_SPI] = BCM_6338_SPI_BASE,
|
||||
[RSET_OHCI0] = BCM_6338_OHCI0_BASE,
|
||||
[RSET_OHCI_PRIV] = BCM_6338_OHCI_PRIV_BASE,
|
||||
[RSET_USBH_PRIV] = BCM_6338_USBH_PRIV_BASE,
|
||||
[RSET_UDC0] = BCM_6338_UDC0_BASE,
|
||||
[RSET_MPI] = BCM_6338_MPI_BASE,
|
||||
[RSET_PCMCIA] = BCM_6338_PCMCIA_BASE,
|
||||
[RSET_SDRAM] = BCM_6338_SDRAM_BASE,
|
||||
[RSET_DSL] = BCM_6338_DSL_BASE,
|
||||
[RSET_ENET0] = BCM_6338_ENET0_BASE,
|
||||
[RSET_ENET1] = BCM_6338_ENET1_BASE,
|
||||
[RSET_ENETDMA] = BCM_6338_ENETDMA_BASE,
|
||||
[RSET_MEMC] = BCM_6338_MEMC_BASE,
|
||||
[RSET_DDR] = BCM_6338_DDR_BASE,
|
||||
};
|
||||
|
||||
static const int bcm96338_irqs[] = {
|
||||
[IRQ_TIMER] = BCM_6338_TIMER_IRQ,
|
||||
[IRQ_SPI] = BCM_6338_SPI_IRQ,
|
||||
[IRQ_UART0] = BCM_6338_UART0_IRQ,
|
||||
[IRQ_DSL] = BCM_6338_DSL_IRQ,
|
||||
[IRQ_UDC0] = BCM_6338_UDC0_IRQ,
|
||||
[IRQ_ENET0] = BCM_6338_ENET0_IRQ,
|
||||
[IRQ_ENET_PHY] = BCM_6338_ENET_PHY_IRQ,
|
||||
[IRQ_ENET0_RXDMA] = BCM_6338_ENET0_RXDMA_IRQ,
|
||||
[IRQ_ENET0_TXDMA] = BCM_6338_ENET0_TXDMA_IRQ,
|
||||
};
|
||||
|
||||
static const unsigned long bcm96338_regs_spi[] = {
|
||||
[SPI_CMD] = SPI_BCM_6338_SPI_CMD,
|
||||
[SPI_INT_STATUS] = SPI_BCM_6338_SPI_INT_STATUS,
|
||||
[SPI_INT_MASK_ST] = SPI_BCM_6338_SPI_MASK_INT_ST,
|
||||
[SPI_INT_MASK] = SPI_BCM_6338_SPI_INT_MASK,
|
||||
[SPI_ST] = SPI_BCM_6338_SPI_ST,
|
||||
[SPI_CLK_CFG] = SPI_BCM_6338_SPI_CLK_CFG,
|
||||
[SPI_FILL_BYTE] = SPI_BCM_6338_SPI_FILL_BYTE,
|
||||
[SPI_MSG_TAIL] = SPI_BCM_6338_SPI_MSG_TAIL,
|
||||
[SPI_RX_TAIL] = SPI_BCM_6338_SPI_RX_TAIL,
|
||||
[SPI_MSG_CTL] = SPI_BCM_6338_SPI_MSG_CTL,
|
||||
[SPI_MSG_DATA] = SPI_BCM_6338_SPI_MSG_DATA,
|
||||
[SPI_RX_DATA] = SPI_BCM_6338_SPI_RX_DATA,
|
||||
};
|
||||
|
||||
/*
|
||||
* 6345 register sets and irqs
|
||||
*/
|
||||
|
||||
static const unsigned long bcm96345_regs_base[] = {
|
||||
[RSET_DSL_LMEM] = BCM_6345_DSL_LMEM_BASE,
|
||||
[RSET_PERF] = BCM_6345_PERF_BASE,
|
||||
[RSET_TIMER] = BCM_6345_TIMER_BASE,
|
||||
[RSET_WDT] = BCM_6345_WDT_BASE,
|
||||
[RSET_UART0] = BCM_6345_UART0_BASE,
|
||||
[RSET_GPIO] = BCM_6345_GPIO_BASE,
|
||||
[RSET_SPI] = BCM_6345_SPI_BASE,
|
||||
[RSET_UDC0] = BCM_6345_UDC0_BASE,
|
||||
[RSET_OHCI0] = BCM_6345_OHCI0_BASE,
|
||||
[RSET_OHCI_PRIV] = BCM_6345_OHCI_PRIV_BASE,
|
||||
[RSET_USBH_PRIV] = BCM_6345_USBH_PRIV_BASE,
|
||||
[RSET_MPI] = BCM_6345_MPI_BASE,
|
||||
[RSET_PCMCIA] = BCM_6345_PCMCIA_BASE,
|
||||
[RSET_DSL] = BCM_6345_DSL_BASE,
|
||||
[RSET_ENET0] = BCM_6345_ENET0_BASE,
|
||||
[RSET_ENET1] = BCM_6345_ENET1_BASE,
|
||||
[RSET_ENETDMA] = BCM_6345_ENETDMA_BASE,
|
||||
[RSET_EHCI0] = BCM_6345_EHCI0_BASE,
|
||||
[RSET_SDRAM] = BCM_6345_SDRAM_BASE,
|
||||
[RSET_MEMC] = BCM_6345_MEMC_BASE,
|
||||
[RSET_DDR] = BCM_6345_DDR_BASE,
|
||||
};
|
||||
|
||||
static const int bcm96345_irqs[] = {
|
||||
[IRQ_TIMER] = BCM_6345_TIMER_IRQ,
|
||||
[IRQ_UART0] = BCM_6345_UART0_IRQ,
|
||||
[IRQ_DSL] = BCM_6345_DSL_IRQ,
|
||||
[IRQ_UDC0] = BCM_6345_UDC0_IRQ,
|
||||
[IRQ_ENET0] = BCM_6345_ENET0_IRQ,
|
||||
[IRQ_ENET_PHY] = BCM_6345_ENET_PHY_IRQ,
|
||||
[IRQ_ENET0_RXDMA] = BCM_6345_ENET0_RXDMA_IRQ,
|
||||
[IRQ_ENET0_TXDMA] = BCM_6345_ENET0_TXDMA_IRQ,
|
||||
};
|
||||
|
||||
/*
|
||||
* 6348 register sets and irqs
|
||||
*/
|
||||
static const unsigned long bcm96348_regs_base[] = {
|
||||
[RSET_DSL_LMEM] = BCM_6348_DSL_LMEM_BASE,
|
||||
[RSET_PERF] = BCM_6348_PERF_BASE,
|
||||
[RSET_TIMER] = BCM_6348_TIMER_BASE,
|
||||
[RSET_WDT] = BCM_6348_WDT_BASE,
|
||||
[RSET_UART0] = BCM_6348_UART0_BASE,
|
||||
[RSET_GPIO] = BCM_6348_GPIO_BASE,
|
||||
[RSET_SPI] = BCM_6348_SPI_BASE,
|
||||
[RSET_OHCI0] = BCM_6348_OHCI0_BASE,
|
||||
[RSET_OHCI_PRIV] = BCM_6348_OHCI_PRIV_BASE,
|
||||
[RSET_USBH_PRIV] = BCM_6348_USBH_PRIV_BASE,
|
||||
[RSET_UDC0] = BCM_6348_UDC0_BASE,
|
||||
[RSET_MPI] = BCM_6348_MPI_BASE,
|
||||
[RSET_PCMCIA] = BCM_6348_PCMCIA_BASE,
|
||||
[RSET_SDRAM] = BCM_6348_SDRAM_BASE,
|
||||
[RSET_DSL] = BCM_6348_DSL_BASE,
|
||||
[RSET_ENET0] = BCM_6348_ENET0_BASE,
|
||||
[RSET_ENET1] = BCM_6348_ENET1_BASE,
|
||||
[RSET_ENETDMA] = BCM_6348_ENETDMA_BASE,
|
||||
[RSET_MEMC] = BCM_6348_MEMC_BASE,
|
||||
[RSET_DDR] = BCM_6348_DDR_BASE,
|
||||
};
|
||||
|
||||
static const int bcm96348_irqs[] = {
|
||||
[IRQ_TIMER] = BCM_6348_TIMER_IRQ,
|
||||
[IRQ_SPI] = BCM_6348_SPI_IRQ,
|
||||
[IRQ_UART0] = BCM_6348_UART0_IRQ,
|
||||
[IRQ_DSL] = BCM_6348_DSL_IRQ,
|
||||
[IRQ_UDC0] = BCM_6348_UDC0_IRQ,
|
||||
[IRQ_ENET0] = BCM_6348_ENET0_IRQ,
|
||||
[IRQ_ENET1] = BCM_6348_ENET1_IRQ,
|
||||
[IRQ_ENET_PHY] = BCM_6348_ENET_PHY_IRQ,
|
||||
[IRQ_OHCI0] = BCM_6348_OHCI0_IRQ,
|
||||
[IRQ_PCMCIA] = BCM_6348_PCMCIA_IRQ,
|
||||
[IRQ_ENET0_RXDMA] = BCM_6348_ENET0_RXDMA_IRQ,
|
||||
[IRQ_ENET0_TXDMA] = BCM_6348_ENET0_TXDMA_IRQ,
|
||||
[IRQ_ENET1_RXDMA] = BCM_6348_ENET1_RXDMA_IRQ,
|
||||
[IRQ_ENET1_TXDMA] = BCM_6348_ENET1_TXDMA_IRQ,
|
||||
[IRQ_PCI] = BCM_6348_PCI_IRQ,
|
||||
};
|
||||
|
||||
static const unsigned long bcm96348_regs_spi[] = {
|
||||
[SPI_CMD] = SPI_BCM_6348_SPI_CMD,
|
||||
[SPI_INT_STATUS] = SPI_BCM_6348_SPI_INT_STATUS,
|
||||
[SPI_INT_MASK_ST] = SPI_BCM_6348_SPI_MASK_INT_ST,
|
||||
[SPI_INT_MASK] = SPI_BCM_6348_SPI_INT_MASK,
|
||||
[SPI_ST] = SPI_BCM_6348_SPI_ST,
|
||||
[SPI_CLK_CFG] = SPI_BCM_6348_SPI_CLK_CFG,
|
||||
[SPI_FILL_BYTE] = SPI_BCM_6348_SPI_FILL_BYTE,
|
||||
[SPI_MSG_TAIL] = SPI_BCM_6348_SPI_MSG_TAIL,
|
||||
[SPI_RX_TAIL] = SPI_BCM_6348_SPI_RX_TAIL,
|
||||
[SPI_MSG_CTL] = SPI_BCM_6348_SPI_MSG_CTL,
|
||||
[SPI_MSG_DATA] = SPI_BCM_6348_SPI_MSG_DATA,
|
||||
[SPI_RX_DATA] = SPI_BCM_6348_SPI_RX_DATA,
|
||||
};
|
||||
|
||||
/*
|
||||
* 6358 register sets and irqs
|
||||
*/
|
||||
static const unsigned long bcm96358_regs_base[] = {
|
||||
[RSET_DSL_LMEM] = BCM_6358_DSL_LMEM_BASE,
|
||||
[RSET_PERF] = BCM_6358_PERF_BASE,
|
||||
[RSET_TIMER] = BCM_6358_TIMER_BASE,
|
||||
[RSET_WDT] = BCM_6358_WDT_BASE,
|
||||
[RSET_UART0] = BCM_6358_UART0_BASE,
|
||||
[RSET_GPIO] = BCM_6358_GPIO_BASE,
|
||||
[RSET_SPI] = BCM_6358_SPI_BASE,
|
||||
[RSET_OHCI0] = BCM_6358_OHCI0_BASE,
|
||||
[RSET_EHCI0] = BCM_6358_EHCI0_BASE,
|
||||
[RSET_OHCI_PRIV] = BCM_6358_OHCI_PRIV_BASE,
|
||||
[RSET_USBH_PRIV] = BCM_6358_USBH_PRIV_BASE,
|
||||
[RSET_MPI] = BCM_6358_MPI_BASE,
|
||||
[RSET_PCMCIA] = BCM_6358_PCMCIA_BASE,
|
||||
[RSET_SDRAM] = BCM_6358_SDRAM_BASE,
|
||||
[RSET_DSL] = BCM_6358_DSL_BASE,
|
||||
[RSET_ENET0] = BCM_6358_ENET0_BASE,
|
||||
[RSET_ENET1] = BCM_6358_ENET1_BASE,
|
||||
[RSET_ENETDMA] = BCM_6358_ENETDMA_BASE,
|
||||
[RSET_MEMC] = BCM_6358_MEMC_BASE,
|
||||
[RSET_DDR] = BCM_6358_DDR_BASE,
|
||||
};
|
||||
|
||||
static const int bcm96358_irqs[] = {
|
||||
[IRQ_TIMER] = BCM_6358_TIMER_IRQ,
|
||||
[IRQ_SPI] = BCM_6358_SPI_IRQ,
|
||||
[IRQ_UART0] = BCM_6358_UART0_IRQ,
|
||||
[IRQ_DSL] = BCM_6358_DSL_IRQ,
|
||||
[IRQ_ENET0] = BCM_6358_ENET0_IRQ,
|
||||
[IRQ_ENET1] = BCM_6358_ENET1_IRQ,
|
||||
[IRQ_ENET_PHY] = BCM_6358_ENET_PHY_IRQ,
|
||||
[IRQ_OHCI0] = BCM_6358_OHCI0_IRQ,
|
||||
[IRQ_EHCI0] = BCM_6358_EHCI0_IRQ,
|
||||
[IRQ_PCMCIA] = BCM_6358_PCMCIA_IRQ,
|
||||
[IRQ_ENET0_RXDMA] = BCM_6358_ENET0_RXDMA_IRQ,
|
||||
[IRQ_ENET0_TXDMA] = BCM_6358_ENET0_TXDMA_IRQ,
|
||||
[IRQ_ENET1_RXDMA] = BCM_6358_ENET1_RXDMA_IRQ,
|
||||
[IRQ_ENET1_TXDMA] = BCM_6358_ENET1_TXDMA_IRQ,
|
||||
[IRQ_PCI] = BCM_6358_PCI_IRQ,
|
||||
};
|
||||
|
||||
static const unsigned long bcm96358_regs_spi[] = {
|
||||
[SPI_CMD] = SPI_BCM_6358_SPI_CMD,
|
||||
[SPI_INT_STATUS] = SPI_BCM_6358_SPI_INT_STATUS,
|
||||
[SPI_INT_MASK_ST] = SPI_BCM_6358_SPI_MASK_INT_ST,
|
||||
[SPI_INT_MASK] = SPI_BCM_6358_SPI_INT_MASK,
|
||||
[SPI_ST] = SPI_BCM_6358_SPI_STATUS,
|
||||
[SPI_CLK_CFG] = SPI_BCM_6358_SPI_CLK_CFG,
|
||||
[SPI_FILL_BYTE] = SPI_BCM_6358_SPI_FILL_BYTE,
|
||||
[SPI_MSG_TAIL] = SPI_BCM_6358_SPI_MSG_TAIL,
|
||||
[SPI_RX_TAIL] = SPI_BCM_6358_SPI_RX_TAIL,
|
||||
[SPI_MSG_CTL] = SPI_BCM_6358_MSG_CTL,
|
||||
[SPI_MSG_DATA] = SPI_BCM_6358_SPI_MSG_DATA,
|
||||
[SPI_RX_DATA] = SPI_BCM_6358_SPI_RX_DATA,
|
||||
};
|
||||
|
||||
u16 __bcm63xx_get_cpu_id(void)
|
||||
{
|
||||
return bcm63xx_cpu_id;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(__bcm63xx_get_cpu_id);
|
||||
|
||||
u16 bcm63xx_get_cpu_rev(void)
|
||||
{
|
||||
return bcm63xx_cpu_rev;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(bcm63xx_get_cpu_rev);
|
||||
|
||||
unsigned int bcm63xx_get_cpu_freq(void)
|
||||
{
|
||||
return bcm63xx_cpu_freq;
|
||||
}
|
||||
|
||||
unsigned int bcm63xx_get_memory_size(void)
|
||||
{
|
||||
return bcm63xx_memory_size;
|
||||
}
|
||||
|
||||
static unsigned int detect_cpu_clock(void)
|
||||
{
|
||||
unsigned int tmp, n1 = 0, n2 = 0, m1 = 0;
|
||||
|
||||
if (BCMCPU_IS_6338())
|
||||
return 240000000;
|
||||
|
||||
if (BCMCPU_IS_6345())
|
||||
return 140000000;
|
||||
|
||||
/*
|
||||
* frequency depends on PLL configuration:
|
||||
*/
|
||||
if (BCMCPU_IS_6348()) {
|
||||
/* 16MHz * (N1 + 1) * (N2 + 2) / (M1_CPU + 1) */
|
||||
tmp = bcm_perf_readl(PERF_MIPSPLLCTL_REG);
|
||||
n1 = (tmp & MIPSPLLCTL_N1_MASK) >> MIPSPLLCTL_N1_SHIFT;
|
||||
n2 = (tmp & MIPSPLLCTL_N2_MASK) >> MIPSPLLCTL_N2_SHIFT;
|
||||
m1 = (tmp & MIPSPLLCTL_M1CPU_MASK) >> MIPSPLLCTL_M1CPU_SHIFT;
|
||||
n1 += 1;
|
||||
n2 += 2;
|
||||
m1 += 1;
|
||||
}
|
||||
|
||||
if (BCMCPU_IS_6358()) {
|
||||
/* 16MHz * N1 * N2 / M1_CPU */
|
||||
tmp = bcm_ddr_readl(DDR_DMIPSPLLCFG_REG);
|
||||
n1 = (tmp & DMIPSPLLCFG_N1_MASK) >> DMIPSPLLCFG_N1_SHIFT;
|
||||
n2 = (tmp & DMIPSPLLCFG_N2_MASK) >> DMIPSPLLCFG_N2_SHIFT;
|
||||
m1 = (tmp & DMIPSPLLCFG_M1_MASK) >> DMIPSPLLCFG_M1_SHIFT;
|
||||
}
|
||||
|
||||
return (16 * 1000000 * n1 * n2) / m1;
|
||||
}
|
||||
|
||||
/*
|
||||
* attempt to detect the amount of memory installed
|
||||
*/
|
||||
static unsigned int detect_memory_size(void)
|
||||
{
|
||||
unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0;
|
||||
u32 val;
|
||||
|
||||
if (BCMCPU_IS_6345())
|
||||
return (8 * 1024 * 1024);
|
||||
|
||||
if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
|
||||
val = bcm_sdram_readl(SDRAM_CFG_REG);
|
||||
rows = (val & SDRAM_CFG_ROW_MASK) >> SDRAM_CFG_ROW_SHIFT;
|
||||
cols = (val & SDRAM_CFG_COL_MASK) >> SDRAM_CFG_COL_SHIFT;
|
||||
is_32bits = (val & SDRAM_CFG_32B_MASK) ? 1 : 0;
|
||||
banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1;
|
||||
}
|
||||
|
||||
if (BCMCPU_IS_6358()) {
|
||||
val = bcm_memc_readl(MEMC_CFG_REG);
|
||||
rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT;
|
||||
cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT;
|
||||
is_32bits = (val & MEMC_CFG_32B_MASK) ? 0 : 1;
|
||||
banks = 2;
|
||||
}
|
||||
|
||||
/* 0 => 11 address bits ... 2 => 13 address bits */
|
||||
rows += 11;
|
||||
|
||||
/* 0 => 8 address bits ... 2 => 10 address bits */
|
||||
cols += 8;
|
||||
|
||||
return 1 << (cols + rows + (is_32bits + 1) + banks);
|
||||
}
|
||||
|
||||
void __init bcm63xx_cpu_init(void)
|
||||
{
|
||||
unsigned int tmp, expected_cpu_id;
|
||||
struct cpuinfo_mips *c = ¤t_cpu_data;
|
||||
|
||||
/* soc registers location depends on cpu type */
|
||||
expected_cpu_id = 0;
|
||||
|
||||
switch (c->cputype) {
|
||||
case CPU_BCM3302:
|
||||
expected_cpu_id = BCM6338_CPU_ID;
|
||||
bcm63xx_regs_base = bcm96338_regs_base;
|
||||
bcm63xx_irqs = bcm96338_irqs;
|
||||
bcm63xx_regs_spi = bcm96338_regs_spi;
|
||||
break;
|
||||
case CPU_BCM6345:
|
||||
expected_cpu_id = BCM6345_CPU_ID;
|
||||
bcm63xx_regs_base = bcm96345_regs_base;
|
||||
bcm63xx_irqs = bcm96345_irqs;
|
||||
break;
|
||||
case CPU_BCM6348:
|
||||
expected_cpu_id = BCM6348_CPU_ID;
|
||||
bcm63xx_regs_base = bcm96348_regs_base;
|
||||
bcm63xx_irqs = bcm96348_irqs;
|
||||
bcm63xx_regs_spi = bcm96348_regs_spi;
|
||||
break;
|
||||
case CPU_BCM6358:
|
||||
expected_cpu_id = BCM6358_CPU_ID;
|
||||
bcm63xx_regs_base = bcm96358_regs_base;
|
||||
bcm63xx_irqs = bcm96358_irqs;
|
||||
bcm63xx_regs_spi = bcm96358_regs_spi;
|
||||
break;
|
||||
}
|
||||
|
||||
/* really early to panic, but delaying panic would not help
|
||||
* since we will never get any working console */
|
||||
if (!expected_cpu_id)
|
||||
panic("unsupported Broadcom CPU");
|
||||
|
||||
/*
|
||||
* bcm63xx_regs_base is set, we can access soc registers
|
||||
*/
|
||||
|
||||
/* double check CPU type */
|
||||
tmp = bcm_perf_readl(PERF_REV_REG);
|
||||
bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
|
||||
bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT;
|
||||
|
||||
if (bcm63xx_cpu_id != expected_cpu_id)
|
||||
panic("bcm63xx CPU id mismatch");
|
||||
|
||||
bcm63xx_cpu_freq = detect_cpu_clock();
|
||||
bcm63xx_memory_size = detect_memory_size();
|
||||
|
||||
printk(KERN_INFO "Detected Broadcom 0x%04x CPU revision %02x\n",
|
||||
bcm63xx_cpu_id, bcm63xx_cpu_rev);
|
||||
printk(KERN_INFO "CPU frequency is %u Hz\n",
|
||||
bcm63xx_cpu_freq);
|
||||
printk(KERN_INFO "%uMB of RAM installed\n",
|
||||
bcm63xx_memory_size >> 20);
|
||||
}
|
||||
144
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/cs.c
Normal file
144
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/cs.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/log2.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
#include <bcm63xx_cs.h>
|
||||
|
||||
static DEFINE_SPINLOCK(bcm63xx_cs_lock);
|
||||
|
||||
/*
|
||||
* check if given chip select exists
|
||||
*/
|
||||
static int is_valid_cs(unsigned int cs)
|
||||
{
|
||||
if (cs > 6)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure chipselect base address and size (bytes).
|
||||
* Size must be a power of two between 8k and 256M.
|
||||
*/
|
||||
int bcm63xx_set_cs_base(unsigned int cs, u32 base, unsigned int size)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
if (!is_valid_cs(cs))
|
||||
return -EINVAL;
|
||||
|
||||
/* sanity check on size */
|
||||
if (size != roundup_pow_of_two(size))
|
||||
return -EINVAL;
|
||||
|
||||
if (size < 8 * 1024 || size > 256 * 1024 * 1024)
|
||||
return -EINVAL;
|
||||
|
||||
val = (base & MPI_CSBASE_BASE_MASK);
|
||||
/* 8k => 0 - 256M => 15 */
|
||||
val |= (ilog2(size) - ilog2(8 * 1024)) << MPI_CSBASE_SIZE_SHIFT;
|
||||
|
||||
spin_lock_irqsave(&bcm63xx_cs_lock, flags);
|
||||
bcm_mpi_writel(val, MPI_CSBASE_REG(cs));
|
||||
spin_unlock_irqrestore(&bcm63xx_cs_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(bcm63xx_set_cs_base);
|
||||
|
||||
/*
|
||||
* configure chipselect timing (ns)
|
||||
*/
|
||||
int bcm63xx_set_cs_timing(unsigned int cs, unsigned int wait,
|
||||
unsigned int setup, unsigned int hold)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
if (!is_valid_cs(cs))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&bcm63xx_cs_lock, flags);
|
||||
val = bcm_mpi_readl(MPI_CSCTL_REG(cs));
|
||||
val &= ~(MPI_CSCTL_WAIT_MASK);
|
||||
val &= ~(MPI_CSCTL_SETUP_MASK);
|
||||
val &= ~(MPI_CSCTL_HOLD_MASK);
|
||||
val |= wait << MPI_CSCTL_WAIT_SHIFT;
|
||||
val |= setup << MPI_CSCTL_SETUP_SHIFT;
|
||||
val |= hold << MPI_CSCTL_HOLD_SHIFT;
|
||||
bcm_mpi_writel(val, MPI_CSCTL_REG(cs));
|
||||
spin_unlock_irqrestore(&bcm63xx_cs_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(bcm63xx_set_cs_timing);
|
||||
|
||||
/*
|
||||
* configure other chipselect parameter (data bus size, ...)
|
||||
*/
|
||||
int bcm63xx_set_cs_param(unsigned int cs, u32 params)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
if (!is_valid_cs(cs))
|
||||
return -EINVAL;
|
||||
|
||||
/* none of this fields apply to pcmcia */
|
||||
if (cs == MPI_CS_PCMCIA_COMMON ||
|
||||
cs == MPI_CS_PCMCIA_ATTR ||
|
||||
cs == MPI_CS_PCMCIA_IO)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&bcm63xx_cs_lock, flags);
|
||||
val = bcm_mpi_readl(MPI_CSCTL_REG(cs));
|
||||
val &= ~(MPI_CSCTL_DATA16_MASK);
|
||||
val &= ~(MPI_CSCTL_SYNCMODE_MASK);
|
||||
val &= ~(MPI_CSCTL_TSIZE_MASK);
|
||||
val &= ~(MPI_CSCTL_ENDIANSWAP_MASK);
|
||||
val |= params;
|
||||
bcm_mpi_writel(val, MPI_CSCTL_REG(cs));
|
||||
spin_unlock_irqrestore(&bcm63xx_cs_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(bcm63xx_set_cs_param);
|
||||
|
||||
/*
|
||||
* set cs status (enable/disable)
|
||||
*/
|
||||
int bcm63xx_set_cs_status(unsigned int cs, int enable)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
if (!is_valid_cs(cs))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&bcm63xx_cs_lock, flags);
|
||||
val = bcm_mpi_readl(MPI_CSCTL_REG(cs));
|
||||
if (enable)
|
||||
val |= MPI_CSCTL_ENABLE_MASK;
|
||||
else
|
||||
val &= ~MPI_CSCTL_ENABLE_MASK;
|
||||
bcm_mpi_writel(val, MPI_CSCTL_REG(cs));
|
||||
spin_unlock_irqrestore(&bcm63xx_cs_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(bcm63xx_set_cs_status);
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Broadcom BCM63xx VoIP DSP registration
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_dev_dsp.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
#include <bcm63xx_io.h>
|
||||
|
||||
static struct resource voip_dsp_resources[] = {
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.end = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device bcm63xx_voip_dsp_device = {
|
||||
.name = "bcm63xx-voip-dsp",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(voip_dsp_resources),
|
||||
.resource = voip_dsp_resources,
|
||||
};
|
||||
|
||||
int __init bcm63xx_dsp_register(const struct bcm63xx_dsp_platform_data *pd)
|
||||
{
|
||||
struct bcm63xx_dsp_platform_data *dpd;
|
||||
u32 val;
|
||||
|
||||
/* Get the memory window */
|
||||
val = bcm_mpi_readl(MPI_CSBASE_REG(pd->cs - 1));
|
||||
val &= MPI_CSBASE_BASE_MASK;
|
||||
voip_dsp_resources[0].start = val;
|
||||
voip_dsp_resources[0].end = val + 0xFFFFFFF;
|
||||
voip_dsp_resources[1].start = pd->ext_irq;
|
||||
|
||||
/* copy given platform data */
|
||||
dpd = bcm63xx_voip_dsp_device.dev.platform_data;
|
||||
memcpy(dpd, pd, sizeof (*pd));
|
||||
|
||||
return platform_device_register(&bcm63xx_voip_dsp_device);
|
||||
}
|
||||
161
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/dev-enet.c
Normal file
161
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/dev-enet.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <bcm63xx_dev_enet.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
|
||||
static struct resource shared_res[] = {
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.end = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device bcm63xx_enet_shared_device = {
|
||||
.name = "bcm63xx_enet_shared",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(shared_res),
|
||||
.resource = shared_res,
|
||||
};
|
||||
|
||||
static int shared_device_registered = 0;
|
||||
|
||||
static struct resource enet0_res[] = {
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.end = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.start = IRQ_ENET0_RXDMA,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.start = IRQ_ENET0_TXDMA,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct bcm63xx_enet_platform_data enet0_pd;
|
||||
|
||||
static struct platform_device bcm63xx_enet0_device = {
|
||||
.name = "bcm63xx_enet",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(enet0_res),
|
||||
.resource = enet0_res,
|
||||
.dev = {
|
||||
.platform_data = &enet0_pd,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource enet1_res[] = {
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.end = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct bcm63xx_enet_platform_data enet1_pd;
|
||||
|
||||
static struct platform_device bcm63xx_enet1_device = {
|
||||
.name = "bcm63xx_enet",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(enet1_res),
|
||||
.resource = enet1_res,
|
||||
.dev = {
|
||||
.platform_data = &enet1_pd,
|
||||
},
|
||||
};
|
||||
|
||||
int __init bcm63xx_enet_register(int unit,
|
||||
const struct bcm63xx_enet_platform_data *pd)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
struct bcm63xx_enet_platform_data *dpd;
|
||||
int ret;
|
||||
|
||||
if (unit > 1)
|
||||
return -ENODEV;
|
||||
|
||||
if (!shared_device_registered) {
|
||||
shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
|
||||
shared_res[0].end = shared_res[0].start;
|
||||
if (BCMCPU_IS_6338())
|
||||
shared_res[0].end += (RSET_ENETDMA_SIZE / 2) - 1;
|
||||
else
|
||||
shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
|
||||
|
||||
ret = platform_device_register(&bcm63xx_enet_shared_device);
|
||||
if (ret)
|
||||
return ret;
|
||||
shared_device_registered = 1;
|
||||
}
|
||||
|
||||
if (unit == 0) {
|
||||
enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
|
||||
enet0_res[0].end = enet0_res[0].start;
|
||||
enet0_res[0].end += RSET_ENET_SIZE - 1;
|
||||
enet0_res[1].start = bcm63xx_get_irq_number(IRQ_ENET0);
|
||||
enet0_res[2].start = bcm63xx_get_irq_number(IRQ_ENET0_RXDMA);
|
||||
enet0_res[3].start = bcm63xx_get_irq_number(IRQ_ENET0_TXDMA);
|
||||
pdev = &bcm63xx_enet0_device;
|
||||
} else {
|
||||
enet1_res[0].start = bcm63xx_regset_address(RSET_ENET1);
|
||||
enet1_res[0].end = enet1_res[0].start;
|
||||
enet1_res[0].end += RSET_ENET_SIZE - 1;
|
||||
enet1_res[1].start = bcm63xx_get_irq_number(IRQ_ENET1);
|
||||
enet1_res[2].start = bcm63xx_get_irq_number(IRQ_ENET1_RXDMA);
|
||||
enet1_res[3].start = bcm63xx_get_irq_number(IRQ_ENET1_TXDMA);
|
||||
pdev = &bcm63xx_enet1_device;
|
||||
}
|
||||
|
||||
/* copy given platform data */
|
||||
dpd = pdev->dev.platform_data;
|
||||
memcpy(dpd, pd, sizeof (*pd));
|
||||
|
||||
/* adjust them in case internal phy is used */
|
||||
if (dpd->use_internal_phy) {
|
||||
|
||||
/* internal phy only exists for enet0 */
|
||||
if (unit == 1)
|
||||
return -ENODEV;
|
||||
|
||||
dpd->phy_id = 1;
|
||||
dpd->has_phy_interrupt = 1;
|
||||
dpd->phy_interrupt = bcm63xx_get_irq_number(IRQ_ENET_PHY);
|
||||
}
|
||||
|
||||
ret = platform_device_register(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <bcm63xx_cs.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_dev_pcmcia.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
|
||||
static struct resource pcmcia_resources[] = {
|
||||
/* pcmcia registers */
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.end = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
|
||||
/* pcmcia memory zone resources */
|
||||
{
|
||||
.start = BCM_PCMCIA_COMMON_BASE_PA,
|
||||
.end = BCM_PCMCIA_COMMON_END_PA,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = BCM_PCMCIA_ATTR_BASE_PA,
|
||||
.end = BCM_PCMCIA_ATTR_END_PA,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = BCM_PCMCIA_IO_BASE_PA,
|
||||
.end = BCM_PCMCIA_IO_END_PA,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
|
||||
/* PCMCIA irq */
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
|
||||
/* declare PCMCIA IO resource also */
|
||||
{
|
||||
.start = BCM_PCMCIA_IO_BASE_PA,
|
||||
.end = BCM_PCMCIA_IO_END_PA,
|
||||
.flags = IORESOURCE_IO,
|
||||
},
|
||||
};
|
||||
|
||||
static struct bcm63xx_pcmcia_platform_data pd;
|
||||
|
||||
static struct platform_device bcm63xx_pcmcia_device = {
|
||||
.name = "bcm63xx_pcmcia",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(pcmcia_resources),
|
||||
.resource = pcmcia_resources,
|
||||
.dev = {
|
||||
.platform_data = &pd,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init config_pcmcia_cs(unsigned int cs,
|
||||
u32 base, unsigned int size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bcm63xx_set_cs_status(cs, 0);
|
||||
if (!ret)
|
||||
ret = bcm63xx_set_cs_base(cs, base, size);
|
||||
if (!ret)
|
||||
ret = bcm63xx_set_cs_status(cs, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const __initdata unsigned int pcmcia_cs[3][3] = {
|
||||
/* cs, base address, size */
|
||||
{ MPI_CS_PCMCIA_COMMON, BCM_PCMCIA_COMMON_BASE_PA,
|
||||
BCM_PCMCIA_COMMON_SIZE },
|
||||
|
||||
{ MPI_CS_PCMCIA_ATTR, BCM_PCMCIA_ATTR_BASE_PA,
|
||||
BCM_PCMCIA_ATTR_SIZE },
|
||||
|
||||
{ MPI_CS_PCMCIA_IO, BCM_PCMCIA_IO_BASE_PA,
|
||||
BCM_PCMCIA_IO_SIZE },
|
||||
};
|
||||
|
||||
int __init bcm63xx_pcmcia_register(void)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358())
|
||||
return 0;
|
||||
|
||||
/* use correct pcmcia ready gpio depending on processor */
|
||||
switch (bcm63xx_get_cpu_id()) {
|
||||
case BCM6348_CPU_ID:
|
||||
pd.ready_gpio = 22;
|
||||
break;
|
||||
|
||||
case BCM6358_CPU_ID:
|
||||
pd.ready_gpio = 18;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pcmcia_resources[0].start = bcm63xx_regset_address(RSET_PCMCIA);
|
||||
pcmcia_resources[0].end = pcmcia_resources[0].start;
|
||||
pcmcia_resources[0].end += RSET_PCMCIA_SIZE - 1;
|
||||
pcmcia_resources[4].start = bcm63xx_get_irq_number(IRQ_PCMCIA);
|
||||
|
||||
/* configure pcmcia chip selects */
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = config_pcmcia_cs(pcmcia_cs[i][0],
|
||||
pcmcia_cs[i][1],
|
||||
pcmcia_cs[i][2]);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
return platform_device_register(&bcm63xx_pcmcia_device);
|
||||
|
||||
out_err:
|
||||
printk(KERN_ERR "unable to set pcmcia chip select");
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_dev_spi.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
|
||||
static struct resource spi_resources[] = {
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.end = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct bcm63xx_spi_pdata spi_pdata = {
|
||||
.bus_num = 0,
|
||||
.num_chipselect = 4,
|
||||
.speed_hz = 50000000, /* Fclk */
|
||||
};
|
||||
|
||||
static struct platform_device bcm63xx_spi_device = {
|
||||
.name = "bcm63xx-spi",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(spi_resources),
|
||||
.resource = spi_resources,
|
||||
.dev = {
|
||||
.platform_data = &spi_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
int __init bcm63xx_spi_register(void)
|
||||
{
|
||||
spi_resources[0].start = bcm63xx_regset_address(RSET_SPI);
|
||||
spi_resources[0].end = spi_resources[0].start;
|
||||
spi_resources[0].end += RSET_SPI_SIZE - 1;
|
||||
spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI);
|
||||
|
||||
/* Fill in platform data */
|
||||
if (BCMCPU_IS_6338() || BCMCPU_IS_6348())
|
||||
spi_pdata.fifo_size = SPI_BCM_6338_SPI_MSG_DATA_SIZE;
|
||||
|
||||
if (BCMCPU_IS_6358())
|
||||
spi_pdata.fifo_size = SPI_BCM_6358_SPI_MSG_DATA_SIZE;
|
||||
|
||||
return platform_device_register(&bcm63xx_spi_device);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_dev_uart.h>
|
||||
|
||||
static struct resource uart_resources[] = {
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.end = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device bcm63xx_uart_device = {
|
||||
.name = "bcm63xx_uart",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(uart_resources),
|
||||
.resource = uart_resources,
|
||||
};
|
||||
|
||||
int __init bcm63xx_uart_register(void)
|
||||
{
|
||||
uart_resources[0].start = bcm63xx_regset_address(RSET_UART0);
|
||||
uart_resources[0].end = uart_resources[0].start;
|
||||
uart_resources[0].end += RSET_UART_SIZE - 1;
|
||||
uart_resources[1].start = bcm63xx_get_irq_number(IRQ_UART0);
|
||||
return platform_device_register(&bcm63xx_uart_device);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_dev_usb_ehci.h>
|
||||
|
||||
static struct resource ehci_resources[] = {
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.end = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static u64 ehci_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device bcm63xx_ehci_device = {
|
||||
.name = "bcm63xx_ehci",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(ehci_resources),
|
||||
.resource = ehci_resources,
|
||||
.dev = {
|
||||
.dma_mask = &ehci_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
};
|
||||
|
||||
int __init bcm63xx_ehci_register(void)
|
||||
{
|
||||
if (!BCMCPU_IS_6358())
|
||||
return 0;
|
||||
|
||||
ehci_resources[0].start = bcm63xx_regset_address(RSET_EHCI0);
|
||||
ehci_resources[0].end = ehci_resources[0].start;
|
||||
ehci_resources[0].end += RSET_EHCI_SIZE - 1;
|
||||
ehci_resources[1].start = bcm63xx_get_irq_number(IRQ_EHCI0);
|
||||
return platform_device_register(&bcm63xx_ehci_device);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_dev_usb_ohci.h>
|
||||
|
||||
static struct resource ohci_resources[] = {
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.end = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static u64 ohci_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device bcm63xx_ohci_device = {
|
||||
.name = "bcm63xx_ohci",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(ohci_resources),
|
||||
.resource = ohci_resources,
|
||||
.dev = {
|
||||
.dma_mask = &ohci_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
};
|
||||
|
||||
int __init bcm63xx_ohci_register(void)
|
||||
{
|
||||
if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358())
|
||||
return 0;
|
||||
|
||||
ohci_resources[0].start = bcm63xx_regset_address(RSET_OHCI0);
|
||||
ohci_resources[0].end = ohci_resources[0].start;
|
||||
ohci_resources[0].end += RSET_OHCI_SIZE - 1;
|
||||
ohci_resources[1].start = bcm63xx_get_irq_number(IRQ_OHCI0);
|
||||
return platform_device_register(&bcm63xx_ohci_device);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Henk Vergonet <Henk.Vergonet@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
|
||||
static struct resource udc_resources[] = {
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.end = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static u64 udc_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device bcm63xx_udc_device = {
|
||||
.name = "bcm63xx-udc",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(udc_resources),
|
||||
.resource = udc_resources,
|
||||
.dev = {
|
||||
.dma_mask = &udc_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
};
|
||||
|
||||
int __init bcm63xx_udc_register(void)
|
||||
{
|
||||
if (!BCMCPU_IS_6338() && !BCMCPU_IS_6345() && !BCMCPU_IS_6348())
|
||||
return 0;
|
||||
|
||||
udc_resources[0].start = bcm63xx_regset_address(RSET_UDC0);
|
||||
udc_resources[0].end = udc_resources[0].start;
|
||||
udc_resources[0].end += RSET_UDC_SIZE - 1;
|
||||
udc_resources[1].start = bcm63xx_get_irq_number(IRQ_UDC0);
|
||||
return platform_device_register(&bcm63xx_udc_device);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
|
||||
static struct resource wdt_resources[] = {
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.end = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device bcm63xx_wdt_device = {
|
||||
.name = "bcm63xx-wdt",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(wdt_resources),
|
||||
.resource = wdt_resources,
|
||||
};
|
||||
|
||||
int __init bcm63xx_wdt_register(void)
|
||||
{
|
||||
wdt_resources[0].start = bcm63xx_regset_address(RSET_WDT);
|
||||
wdt_resources[0].end = wdt_resources[0].start;
|
||||
wdt_resources[0].end += RSET_WDT_SIZE - 1;
|
||||
|
||||
return platform_device_register(&bcm63xx_wdt_device);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
|
||||
static void __init wait_xfered(void)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
/* wait for any previous char to be transmitted */
|
||||
do {
|
||||
val = bcm_uart0_readl(UART_IR_REG);
|
||||
if (val & UART_IR_STAT(UART_IR_TXEMPTY))
|
||||
break;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
void __init prom_putchar(char c)
|
||||
{
|
||||
wait_xfered();
|
||||
bcm_uart0_writel(c, UART_FIFO_REG);
|
||||
wait_xfered();
|
||||
}
|
||||
131
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/gpio.c
Normal file
131
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/gpio.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
* Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_gpio.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
|
||||
static DEFINE_SPINLOCK(bcm63xx_gpio_lock);
|
||||
static u32 gpio_out_low, gpio_out_high;
|
||||
|
||||
static void bcm63xx_gpio_set(struct gpio_chip *chip,
|
||||
unsigned gpio, int val)
|
||||
{
|
||||
u32 reg;
|
||||
u32 mask;
|
||||
u32 *v;
|
||||
unsigned long flags;
|
||||
|
||||
if (gpio >= chip->ngpio)
|
||||
BUG();
|
||||
|
||||
if (gpio < 32) {
|
||||
reg = GPIO_DATA_LO_REG;
|
||||
mask = 1 << gpio;
|
||||
v = &gpio_out_low;
|
||||
} else {
|
||||
reg = GPIO_DATA_HI_REG;
|
||||
mask = 1 << (gpio - 32);
|
||||
v = &gpio_out_high;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&bcm63xx_gpio_lock, flags);
|
||||
if (val)
|
||||
*v |= mask;
|
||||
else
|
||||
*v &= ~mask;
|
||||
bcm_gpio_writel(*v, reg);
|
||||
spin_unlock_irqrestore(&bcm63xx_gpio_lock, flags);
|
||||
}
|
||||
|
||||
static int bcm63xx_gpio_get(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
u32 reg;
|
||||
u32 mask;
|
||||
|
||||
if (gpio >= chip->ngpio)
|
||||
BUG();
|
||||
|
||||
if (gpio < 32) {
|
||||
reg = GPIO_DATA_LO_REG;
|
||||
mask = 1 << gpio;
|
||||
} else {
|
||||
reg = GPIO_DATA_HI_REG;
|
||||
mask = 1 << (gpio - 32);
|
||||
}
|
||||
|
||||
return !!(bcm_gpio_readl(reg) & mask);
|
||||
}
|
||||
|
||||
static int bcm63xx_gpio_set_direction(struct gpio_chip *chip,
|
||||
unsigned gpio, int dir)
|
||||
{
|
||||
u32 reg;
|
||||
u32 mask;
|
||||
u32 tmp;
|
||||
unsigned long flags;
|
||||
|
||||
if (gpio >= chip->ngpio)
|
||||
BUG();
|
||||
|
||||
if (gpio < 32) {
|
||||
reg = GPIO_CTL_LO_REG;
|
||||
mask = 1 << gpio;
|
||||
} else {
|
||||
reg = GPIO_CTL_HI_REG;
|
||||
mask = 1 << (gpio - 32);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&bcm63xx_gpio_lock, flags);
|
||||
tmp = bcm_gpio_readl(reg);
|
||||
if (dir == GPIO_DIR_IN)
|
||||
tmp &= ~mask;
|
||||
else
|
||||
tmp |= mask;
|
||||
bcm_gpio_writel(tmp, reg);
|
||||
spin_unlock_irqrestore(&bcm63xx_gpio_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm63xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
return bcm63xx_gpio_set_direction(chip, gpio, GPIO_DIR_IN);
|
||||
}
|
||||
|
||||
static int bcm63xx_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned gpio, int value)
|
||||
{
|
||||
bcm63xx_gpio_set(chip, gpio, value);
|
||||
return bcm63xx_gpio_set_direction(chip, gpio, GPIO_DIR_OUT);
|
||||
}
|
||||
|
||||
|
||||
static struct gpio_chip bcm63xx_gpio_chip = {
|
||||
.label = "bcm63xx-gpio",
|
||||
.direction_input = bcm63xx_gpio_direction_input,
|
||||
.direction_output = bcm63xx_gpio_direction_output,
|
||||
.get = bcm63xx_gpio_get,
|
||||
.set = bcm63xx_gpio_set,
|
||||
.base = 0,
|
||||
};
|
||||
|
||||
int __init bcm63xx_gpio_init(void)
|
||||
{
|
||||
bcm63xx_gpio_chip.ngpio = bcm63xx_gpio_count();
|
||||
printk(KERN_INFO "registering %d GPIOs\n", bcm63xx_gpio_chip.ngpio);
|
||||
return gpiochip_add(&bcm63xx_gpio_chip);
|
||||
}
|
||||
253
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/irq.c
Normal file
253
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/irq.c
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
* Copyright (C) 2008 Nicolas Schichan <nschichan@freebox.fr>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/irq_cpu.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_irq.h>
|
||||
|
||||
/*
|
||||
* dispatch internal devices IRQ (uart, enet, watchdog, ...). do not
|
||||
* prioritize any interrupt relatively to another. the static counter
|
||||
* will resume the loop where it ended the last time we left this
|
||||
* function.
|
||||
*/
|
||||
static void bcm63xx_irq_dispatch_internal(void)
|
||||
{
|
||||
u32 pending;
|
||||
static int i;
|
||||
|
||||
pending = bcm_perf_readl(PERF_IRQMASK_REG) &
|
||||
bcm_perf_readl(PERF_IRQSTAT_REG);
|
||||
|
||||
if (!pending)
|
||||
return ;
|
||||
|
||||
while (1) {
|
||||
int to_call = i;
|
||||
|
||||
i = (i + 1) & 0x1f;
|
||||
if (pending & (1 << to_call)) {
|
||||
do_IRQ(to_call + IRQ_INTERNAL_BASE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
asmlinkage void plat_irq_dispatch(void)
|
||||
{
|
||||
u32 cause;
|
||||
|
||||
do {
|
||||
cause = read_c0_cause() & read_c0_status() & ST0_IM;
|
||||
|
||||
if (!cause)
|
||||
break;
|
||||
|
||||
if (cause & CAUSEF_IP7)
|
||||
do_IRQ(7);
|
||||
if (cause & CAUSEF_IP2)
|
||||
bcm63xx_irq_dispatch_internal();
|
||||
if (cause & CAUSEF_IP3)
|
||||
do_IRQ(IRQ_EXT_0);
|
||||
if (cause & CAUSEF_IP4)
|
||||
do_IRQ(IRQ_EXT_1);
|
||||
if (cause & CAUSEF_IP5)
|
||||
do_IRQ(IRQ_EXT_2);
|
||||
if (cause & CAUSEF_IP6)
|
||||
do_IRQ(IRQ_EXT_3);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* internal IRQs operations: only mask/unmask on PERF irq mask
|
||||
* register.
|
||||
*/
|
||||
static inline void bcm63xx_internal_irq_mask(unsigned int irq)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
irq -= IRQ_INTERNAL_BASE;
|
||||
mask = bcm_perf_readl(PERF_IRQMASK_REG);
|
||||
mask &= ~(1 << irq);
|
||||
bcm_perf_writel(mask, PERF_IRQMASK_REG);
|
||||
}
|
||||
|
||||
static void bcm63xx_internal_irq_unmask(unsigned int irq)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
irq -= IRQ_INTERNAL_BASE;
|
||||
mask = bcm_perf_readl(PERF_IRQMASK_REG);
|
||||
mask |= (1 << irq);
|
||||
bcm_perf_writel(mask, PERF_IRQMASK_REG);
|
||||
}
|
||||
|
||||
static unsigned int bcm63xx_internal_irq_startup(unsigned int irq)
|
||||
{
|
||||
bcm63xx_internal_irq_unmask(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* external IRQs operations: mask/unmask and clear on PERF external
|
||||
* irq control register.
|
||||
*/
|
||||
static void bcm63xx_external_irq_mask(unsigned int irq)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
irq -= IRQ_EXT_BASE;
|
||||
reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
|
||||
reg &= ~EXTIRQ_CFG_MASK(irq);
|
||||
bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
|
||||
}
|
||||
|
||||
static void bcm63xx_external_irq_unmask(unsigned int irq)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
irq -= IRQ_EXT_BASE;
|
||||
reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
|
||||
reg |= EXTIRQ_CFG_MASK(irq);
|
||||
bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
|
||||
}
|
||||
|
||||
static void bcm63xx_external_irq_clear(unsigned int irq)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
irq -= IRQ_EXT_BASE;
|
||||
reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
|
||||
reg |= EXTIRQ_CFG_CLEAR(irq);
|
||||
bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
|
||||
}
|
||||
|
||||
static unsigned int bcm63xx_external_irq_startup(unsigned int irq)
|
||||
{
|
||||
set_c0_status(0x100 << (irq - IRQ_MIPS_BASE));
|
||||
irq_enable_hazard();
|
||||
bcm63xx_external_irq_unmask(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bcm63xx_external_irq_shutdown(unsigned int irq)
|
||||
{
|
||||
bcm63xx_external_irq_mask(irq);
|
||||
clear_c0_status(0x100 << (irq - IRQ_MIPS_BASE));
|
||||
irq_disable_hazard();
|
||||
}
|
||||
|
||||
static int bcm63xx_external_irq_set_type(unsigned int irq,
|
||||
unsigned int flow_type)
|
||||
{
|
||||
u32 reg;
|
||||
struct irq_desc *desc = irq_desc + irq;
|
||||
|
||||
irq -= IRQ_EXT_BASE;
|
||||
|
||||
flow_type &= IRQ_TYPE_SENSE_MASK;
|
||||
|
||||
if (flow_type == IRQ_TYPE_NONE)
|
||||
flow_type = IRQ_TYPE_LEVEL_LOW;
|
||||
|
||||
reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
|
||||
switch (flow_type) {
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
reg &= ~EXTIRQ_CFG_LEVELSENSE(irq);
|
||||
reg |= EXTIRQ_CFG_BOTHEDGE(irq);
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
reg &= ~EXTIRQ_CFG_LEVELSENSE(irq);
|
||||
reg |= EXTIRQ_CFG_SENSE(irq);
|
||||
reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
reg &= ~EXTIRQ_CFG_LEVELSENSE(irq);
|
||||
reg &= ~EXTIRQ_CFG_SENSE(irq);
|
||||
reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
reg |= EXTIRQ_CFG_LEVELSENSE(irq);
|
||||
reg |= EXTIRQ_CFG_SENSE(irq);
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
reg |= EXTIRQ_CFG_LEVELSENSE(irq);
|
||||
reg &= ~EXTIRQ_CFG_SENSE(irq);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "bogus flow type combination given !\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
|
||||
|
||||
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) {
|
||||
desc->status |= IRQ_LEVEL;
|
||||
desc->handle_irq = handle_level_irq;
|
||||
} else {
|
||||
desc->handle_irq = handle_edge_irq;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip bcm63xx_internal_irq_chip = {
|
||||
.name = "bcm63xx_ipic",
|
||||
.startup = bcm63xx_internal_irq_startup,
|
||||
.shutdown = bcm63xx_internal_irq_mask,
|
||||
|
||||
.mask = bcm63xx_internal_irq_mask,
|
||||
.mask_ack = bcm63xx_internal_irq_mask,
|
||||
.unmask = bcm63xx_internal_irq_unmask,
|
||||
};
|
||||
|
||||
static struct irq_chip bcm63xx_external_irq_chip = {
|
||||
.name = "bcm63xx_epic",
|
||||
.startup = bcm63xx_external_irq_startup,
|
||||
.shutdown = bcm63xx_external_irq_shutdown,
|
||||
|
||||
.ack = bcm63xx_external_irq_clear,
|
||||
|
||||
.mask = bcm63xx_external_irq_mask,
|
||||
.unmask = bcm63xx_external_irq_unmask,
|
||||
|
||||
.set_type = bcm63xx_external_irq_set_type,
|
||||
};
|
||||
|
||||
static struct irqaction cpu_ip2_cascade_action = {
|
||||
.handler = no_action,
|
||||
.name = "cascade_ip2",
|
||||
};
|
||||
|
||||
void __init arch_init_irq(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
mips_cpu_irq_init();
|
||||
for (i = IRQ_INTERNAL_BASE; i < NR_IRQS; ++i)
|
||||
set_irq_chip_and_handler(i, &bcm63xx_internal_irq_chip,
|
||||
handle_level_irq);
|
||||
|
||||
for (i = IRQ_EXT_BASE; i < IRQ_EXT_BASE + 4; ++i)
|
||||
set_irq_chip_and_handler(i, &bcm63xx_external_irq_chip,
|
||||
handle_edge_irq);
|
||||
|
||||
setup_irq(IRQ_MIPS_BASE + 2, &cpu_ip2_cascade_action);
|
||||
}
|
||||
55
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/prom.c
Normal file
55
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/prom.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <bcm63xx_board.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
#include <bcm63xx_gpio.h>
|
||||
|
||||
void __init prom_init(void)
|
||||
{
|
||||
u32 reg, mask;
|
||||
|
||||
bcm63xx_cpu_init();
|
||||
|
||||
/* stop any running watchdog */
|
||||
bcm_wdt_writel(WDT_STOP_1, WDT_CTL_REG);
|
||||
bcm_wdt_writel(WDT_STOP_2, WDT_CTL_REG);
|
||||
|
||||
/* disable all hardware blocks clock for now */
|
||||
if (BCMCPU_IS_6338())
|
||||
mask = CKCTL_6338_ALL_SAFE_EN;
|
||||
else if (BCMCPU_IS_6345())
|
||||
mask = CKCTL_6345_ALL_SAFE_EN;
|
||||
else if (BCMCPU_IS_6348())
|
||||
mask = CKCTL_6348_ALL_SAFE_EN;
|
||||
else
|
||||
/* BCMCPU_IS_6358() */
|
||||
mask = CKCTL_6358_ALL_SAFE_EN;
|
||||
|
||||
reg = bcm_perf_readl(PERF_CKCTL_REG);
|
||||
reg &= ~mask;
|
||||
bcm_perf_writel(reg, PERF_CKCTL_REG);
|
||||
|
||||
/* assign command line from kernel config */
|
||||
strcpy(arcs_cmdline, CONFIG_CMDLINE);
|
||||
|
||||
/* register gpiochip */
|
||||
bcm63xx_gpio_init();
|
||||
|
||||
/* do low level board init */
|
||||
board_prom_init();
|
||||
}
|
||||
|
||||
void __init prom_free_prom_memory(void)
|
||||
{
|
||||
}
|
||||
124
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/setup.c
Normal file
124
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/setup.c
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pm.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <bcm63xx_board.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
#include <bcm63xx_io.h>
|
||||
|
||||
void bcm63xx_machine_halt(void)
|
||||
{
|
||||
printk(KERN_INFO "System halted\n");
|
||||
while (1);
|
||||
}
|
||||
|
||||
static void bcm6348_a1_reboot(void)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
/* soft reset all blocks */
|
||||
printk(KERN_INFO "soft-reseting all blocks ...\n");
|
||||
reg = bcm_perf_readl(PERF_SOFTRESET_REG);
|
||||
reg &= ~SOFTRESET_6348_ALL;
|
||||
bcm_perf_writel(reg, PERF_SOFTRESET_REG);
|
||||
mdelay(10);
|
||||
|
||||
reg = bcm_perf_readl(PERF_SOFTRESET_REG);
|
||||
reg |= SOFTRESET_6348_ALL;
|
||||
bcm_perf_writel(reg, PERF_SOFTRESET_REG);
|
||||
mdelay(10);
|
||||
|
||||
/* Jump to the power on address. */
|
||||
printk(KERN_INFO "jumping to reset vector.\n");
|
||||
/* set high vectors (base at 0xbfc00000 */
|
||||
set_c0_status(ST0_BEV | ST0_ERL);
|
||||
/* run uncached in kseg0 */
|
||||
change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
|
||||
__flush_cache_all();
|
||||
/* remove all wired TLB entries */
|
||||
write_c0_wired(0);
|
||||
__asm__ __volatile__(
|
||||
"jr\t%0"
|
||||
:
|
||||
: "r" (0xbfc00000));
|
||||
while (1);
|
||||
}
|
||||
|
||||
void bcm63xx_machine_reboot(void)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
/* mask and clear all external irq */
|
||||
reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
|
||||
reg &= ~EXTIRQ_CFG_MASK_ALL;
|
||||
reg |= EXTIRQ_CFG_CLEAR_ALL;
|
||||
bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
|
||||
|
||||
if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() == 0xa1))
|
||||
bcm6348_a1_reboot();
|
||||
|
||||
printk(KERN_INFO "triggering watchdog soft-reset...\n");
|
||||
reg = bcm_perf_readl(PERF_SYS_PLL_CTL_REG);
|
||||
reg |= SYS_PLL_SOFT_RESET;
|
||||
bcm_perf_writel(reg, PERF_SYS_PLL_CTL_REG);
|
||||
while (1);
|
||||
}
|
||||
|
||||
static void __bcm63xx_machine_reboot(char *p)
|
||||
{
|
||||
bcm63xx_machine_reboot();
|
||||
}
|
||||
|
||||
/*
|
||||
* return system type in /proc/cpuinfo
|
||||
*/
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
static char buf[128];
|
||||
snprintf(buf, sizeof (buf), "bcm63xx/%s (0x%04x/0x%04X)",
|
||||
board_get_name(),
|
||||
bcm63xx_get_cpu_id(), bcm63xx_get_cpu_rev());
|
||||
return buf;
|
||||
}
|
||||
|
||||
void __init plat_time_init(void)
|
||||
{
|
||||
mips_hpt_frequency = bcm63xx_get_cpu_freq() / 2;
|
||||
}
|
||||
|
||||
void __init plat_mem_setup(void)
|
||||
{
|
||||
add_memory_region(0, bcm63xx_get_memory_size(), BOOT_MEM_RAM);
|
||||
|
||||
_machine_halt = bcm63xx_machine_halt;
|
||||
_machine_restart = __bcm63xx_machine_reboot;
|
||||
pm_power_off = bcm63xx_machine_halt;
|
||||
|
||||
set_io_port_base(0);
|
||||
ioport_resource.start = 0;
|
||||
ioport_resource.end = ~0;
|
||||
|
||||
board_setup();
|
||||
}
|
||||
|
||||
int __init bcm63xx_register_devices(void)
|
||||
{
|
||||
return board_register_devices();
|
||||
}
|
||||
|
||||
arch_initcall(bcm63xx_register_devices);
|
||||
205
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/timer.c
Normal file
205
target/linux/brcm63xx/files-2.6.30/arch/mips/bcm63xx/timer.c
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/clk.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_timer.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
|
||||
static DEFINE_SPINLOCK(timer_reg_lock);
|
||||
static DEFINE_SPINLOCK(timer_data_lock);
|
||||
static struct clk *periph_clk;
|
||||
|
||||
static struct timer_data {
|
||||
void (*cb)(void *);
|
||||
void *data;
|
||||
} timer_data[BCM63XX_TIMER_COUNT];
|
||||
|
||||
static irqreturn_t timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
u32 stat;
|
||||
int i;
|
||||
|
||||
spin_lock(&timer_reg_lock);
|
||||
stat = bcm_timer_readl(TIMER_IRQSTAT_REG);
|
||||
bcm_timer_writel(stat, TIMER_IRQSTAT_REG);
|
||||
spin_unlock(&timer_reg_lock);
|
||||
|
||||
for (i = 0; i < BCM63XX_TIMER_COUNT; i++) {
|
||||
if (!(stat & TIMER_IRQSTAT_TIMER_CAUSE(i)))
|
||||
continue;
|
||||
|
||||
spin_lock(&timer_data_lock);
|
||||
if (!timer_data[i].cb) {
|
||||
spin_unlock(&timer_data_lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
timer_data[i].cb(timer_data[i].data);
|
||||
spin_unlock(&timer_data_lock);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int bcm63xx_timer_enable(int id)
|
||||
{
|
||||
u32 reg;
|
||||
unsigned long flags;
|
||||
|
||||
if (id >= BCM63XX_TIMER_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&timer_reg_lock, flags);
|
||||
|
||||
reg = bcm_timer_readl(TIMER_CTLx_REG(id));
|
||||
reg |= TIMER_CTL_ENABLE_MASK;
|
||||
bcm_timer_writel(reg, TIMER_CTLx_REG(id));
|
||||
|
||||
reg = bcm_timer_readl(TIMER_IRQSTAT_REG);
|
||||
reg |= TIMER_IRQSTAT_TIMER_IR_EN(id);
|
||||
bcm_timer_writel(reg, TIMER_IRQSTAT_REG);
|
||||
|
||||
spin_unlock_irqrestore(&timer_reg_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(bcm63xx_timer_enable);
|
||||
|
||||
int bcm63xx_timer_disable(int id)
|
||||
{
|
||||
u32 reg;
|
||||
unsigned long flags;
|
||||
|
||||
if (id >= BCM63XX_TIMER_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&timer_reg_lock, flags);
|
||||
|
||||
reg = bcm_timer_readl(TIMER_CTLx_REG(id));
|
||||
reg &= ~TIMER_CTL_ENABLE_MASK;
|
||||
bcm_timer_writel(reg, TIMER_CTLx_REG(id));
|
||||
|
||||
reg = bcm_timer_readl(TIMER_IRQSTAT_REG);
|
||||
reg &= ~TIMER_IRQSTAT_TIMER_IR_EN(id);
|
||||
bcm_timer_writel(reg, TIMER_IRQSTAT_REG);
|
||||
|
||||
spin_unlock_irqrestore(&timer_reg_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(bcm63xx_timer_disable);
|
||||
|
||||
int bcm63xx_timer_register(int id, void (*callback)(void *data), void *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (id >= BCM63XX_TIMER_COUNT || !callback)
|
||||
return -EINVAL;
|
||||
|
||||
ret = 0;
|
||||
spin_lock_irqsave(&timer_data_lock, flags);
|
||||
if (timer_data[id].cb) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
timer_data[id].cb = callback;
|
||||
timer_data[id].data = data;
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&timer_data_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(bcm63xx_timer_register);
|
||||
|
||||
void bcm63xx_timer_unregister(int id)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (id >= BCM63XX_TIMER_COUNT)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&timer_data_lock, flags);
|
||||
timer_data[id].cb = NULL;
|
||||
spin_unlock_irqrestore(&timer_data_lock, flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(bcm63xx_timer_unregister);
|
||||
|
||||
unsigned int bcm63xx_timer_countdown(unsigned int countdown_us)
|
||||
{
|
||||
return (clk_get_rate(periph_clk) / (1000 * 1000)) * countdown_us;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(bcm63xx_timer_countdown);
|
||||
|
||||
int bcm63xx_timer_set(int id, int monotonic, unsigned int countdown_us)
|
||||
{
|
||||
u32 reg, countdown;
|
||||
unsigned long flags;
|
||||
|
||||
if (id >= BCM63XX_TIMER_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
countdown = bcm63xx_timer_countdown(countdown_us);
|
||||
if (countdown & ~TIMER_CTL_COUNTDOWN_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&timer_reg_lock, flags);
|
||||
reg = bcm_timer_readl(TIMER_CTLx_REG(id));
|
||||
|
||||
if (monotonic)
|
||||
reg &= ~TIMER_CTL_MONOTONIC_MASK;
|
||||
else
|
||||
reg |= TIMER_CTL_MONOTONIC_MASK;
|
||||
|
||||
reg &= ~TIMER_CTL_COUNTDOWN_MASK;
|
||||
reg |= countdown;
|
||||
bcm_timer_writel(reg, TIMER_CTLx_REG(id));
|
||||
|
||||
spin_unlock_irqrestore(&timer_reg_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(bcm63xx_timer_set);
|
||||
|
||||
int bcm63xx_timer_init(void)
|
||||
{
|
||||
int ret, irq;
|
||||
u32 reg;
|
||||
|
||||
reg = bcm_timer_readl(TIMER_IRQSTAT_REG);
|
||||
reg &= ~TIMER_IRQSTAT_TIMER0_IR_EN;
|
||||
reg &= ~TIMER_IRQSTAT_TIMER1_IR_EN;
|
||||
reg &= ~TIMER_IRQSTAT_TIMER2_IR_EN;
|
||||
bcm_timer_writel(reg, TIMER_IRQSTAT_REG);
|
||||
|
||||
periph_clk = clk_get(NULL, "periph");
|
||||
if (IS_ERR(periph_clk))
|
||||
return -ENODEV;
|
||||
|
||||
irq = bcm63xx_get_irq_number(IRQ_TIMER);
|
||||
ret = request_irq(irq, timer_interrupt, 0, "bcm63xx_timer", NULL);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "bcm63xx_timer: failed to register irq\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(bcm63xx_timer_init);
|
||||
Reference in New Issue
Block a user