mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-10-28 23:08:52 +01:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
44
arch/mips/bcm63xx/Kconfig
Normal file
44
arch/mips/bcm63xx/Kconfig
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
menu "CPU support"
|
||||
depends on BCM63XX
|
||||
|
||||
config BCM63XX_CPU_3368
|
||||
bool "support 3368 CPU"
|
||||
select SYS_HAS_CPU_BMIPS4350
|
||||
select HW_HAS_PCI
|
||||
|
||||
config BCM63XX_CPU_6328
|
||||
bool "support 6328 CPU"
|
||||
select SYS_HAS_CPU_BMIPS4350
|
||||
select HW_HAS_PCI
|
||||
|
||||
config BCM63XX_CPU_6338
|
||||
bool "support 6338 CPU"
|
||||
select SYS_HAS_CPU_BMIPS32_3300
|
||||
select HW_HAS_PCI
|
||||
|
||||
config BCM63XX_CPU_6345
|
||||
bool "support 6345 CPU"
|
||||
select SYS_HAS_CPU_BMIPS32_3300
|
||||
|
||||
config BCM63XX_CPU_6348
|
||||
bool "support 6348 CPU"
|
||||
select SYS_HAS_CPU_BMIPS32_3300
|
||||
select HW_HAS_PCI
|
||||
|
||||
config BCM63XX_CPU_6358
|
||||
bool "support 6358 CPU"
|
||||
select SYS_HAS_CPU_BMIPS4350
|
||||
select HW_HAS_PCI
|
||||
|
||||
config BCM63XX_CPU_6362
|
||||
bool "support 6362 CPU"
|
||||
select SYS_HAS_CPU_BMIPS4350
|
||||
select HW_HAS_PCI
|
||||
|
||||
config BCM63XX_CPU_6368
|
||||
bool "support 6368 CPU"
|
||||
select SYS_HAS_CPU_BMIPS4350
|
||||
select HW_HAS_PCI
|
||||
endmenu
|
||||
|
||||
source "arch/mips/bcm63xx/boards/Kconfig"
|
||||
7
arch/mips/bcm63xx/Makefile
Normal file
7
arch/mips/bcm63xx/Makefile
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o reset.o \
|
||||
setup.o timer.o dev-dsp.o dev-enet.o dev-flash.o \
|
||||
dev-pcmcia.o dev-rng.o dev-spi.o dev-hsspi.o dev-uart.o \
|
||||
dev-wdt.o dev-usb-usbd.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
|
||||
obj-y += boards/
|
||||
7
arch/mips/bcm63xx/Platform
Normal file
7
arch/mips/bcm63xx/Platform
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
# Broadcom BCM63XX boards
|
||||
#
|
||||
platform-$(CONFIG_BCM63XX) += bcm63xx/
|
||||
cflags-$(CONFIG_BCM63XX) += \
|
||||
-I$(srctree)/arch/mips/include/asm/mach-bcm63xx/
|
||||
load-$(CONFIG_BCM63XX) := 0xffffffff80010000
|
||||
11
arch/mips/bcm63xx/boards/Kconfig
Normal file
11
arch/mips/bcm63xx/boards/Kconfig
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
choice
|
||||
prompt "Board support"
|
||||
depends on BCM63XX
|
||||
default BOARD_BCM963XX
|
||||
|
||||
config BOARD_BCM963XX
|
||||
bool "Generic Broadcom 963xx boards"
|
||||
select SSB
|
||||
help
|
||||
|
||||
endchoice
|
||||
1
arch/mips/bcm63xx/boards/Makefile
Normal file
1
arch/mips/bcm63xx/boards/Makefile
Normal file
|
|
@ -0,0 +1 @@
|
|||
obj-$(CONFIG_BOARD_BCM963XX) += board_bcm963xx.o
|
||||
933
arch/mips/bcm63xx/boards/board_bcm963xx.c
Normal file
933
arch/mips/bcm63xx/boards/board_bcm963xx.c
Normal file
|
|
@ -0,0 +1,933 @@
|
|||
/*
|
||||
* 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/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/ssb/ssb.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <bcm63xx_board.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_dev_uart.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_nvram.h>
|
||||
#include <bcm63xx_dev_pci.h>
|
||||
#include <bcm63xx_dev_enet.h>
|
||||
#include <bcm63xx_dev_dsp.h>
|
||||
#include <bcm63xx_dev_flash.h>
|
||||
#include <bcm63xx_dev_hsspi.h>
|
||||
#include <bcm63xx_dev_pcmcia.h>
|
||||
#include <bcm63xx_dev_spi.h>
|
||||
#include <bcm63xx_dev_usb_usbd.h>
|
||||
#include <board_bcm963xx.h>
|
||||
|
||||
#include <uapi/linux/bcm933xx_hcs.h>
|
||||
|
||||
#define PFX "board_bcm963xx: "
|
||||
|
||||
#define HCS_OFFSET_128K 0x20000
|
||||
|
||||
static struct board_info board;
|
||||
|
||||
/*
|
||||
* known 3368 boards
|
||||
*/
|
||||
#ifdef CONFIG_BCM63XX_CPU_3368
|
||||
static struct board_info __initdata board_cvg834g = {
|
||||
.name = "CVG834G_E15R3921",
|
||||
.expected_cpu_id = 0x3368,
|
||||
|
||||
.has_uart0 = 1,
|
||||
.has_uart1 = 1,
|
||||
|
||||
.has_enet0 = 1,
|
||||
.has_pci = 1,
|
||||
|
||||
.enet0 = {
|
||||
.has_phy = 1,
|
||||
.use_internal_phy = 1,
|
||||
},
|
||||
|
||||
.leds = {
|
||||
{
|
||||
.name = "CVG834G:green:power",
|
||||
.gpio = 37,
|
||||
.default_trigger= "default-on",
|
||||
},
|
||||
},
|
||||
|
||||
.ephy_reset_gpio = 36,
|
||||
.ephy_reset_gpio_flags = GPIOF_INIT_HIGH,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* known 6328 boards
|
||||
*/
|
||||
#ifdef CONFIG_BCM63XX_CPU_6328
|
||||
static struct board_info __initdata board_96328avng = {
|
||||
.name = "96328avng",
|
||||
.expected_cpu_id = 0x6328,
|
||||
|
||||
.has_uart0 = 1,
|
||||
.has_pci = 1,
|
||||
.has_usbd = 0,
|
||||
|
||||
.usbd = {
|
||||
.use_fullspeed = 0,
|
||||
.port_no = 0,
|
||||
},
|
||||
|
||||
.leds = {
|
||||
{
|
||||
.name = "96328avng::ppp-fail",
|
||||
.gpio = 2,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "96328avng::power",
|
||||
.gpio = 4,
|
||||
.active_low = 1,
|
||||
.default_trigger = "default-on",
|
||||
},
|
||||
{
|
||||
.name = "96328avng::power-fail",
|
||||
.gpio = 8,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "96328avng::wps",
|
||||
.gpio = 9,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "96328avng::ppp",
|
||||
.gpio = 11,
|
||||
.active_low = 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* known 6338 boards
|
||||
*/
|
||||
#ifdef CONFIG_BCM63XX_CPU_6338
|
||||
static struct board_info __initdata board_96338gw = {
|
||||
.name = "96338GW",
|
||||
.expected_cpu_id = 0x6338,
|
||||
|
||||
.has_uart0 = 1,
|
||||
.has_enet0 = 1,
|
||||
.enet0 = {
|
||||
.force_speed_100 = 1,
|
||||
.force_duplex_full = 1,
|
||||
},
|
||||
|
||||
.has_ohci0 = 1,
|
||||
|
||||
.leds = {
|
||||
{
|
||||
.name = "adsl",
|
||||
.gpio = 3,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ses",
|
||||
.gpio = 5,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ppp-fail",
|
||||
.gpio = 4,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "power",
|
||||
.gpio = 0,
|
||||
.active_low = 1,
|
||||
.default_trigger = "default-on",
|
||||
},
|
||||
{
|
||||
.name = "stop",
|
||||
.gpio = 1,
|
||||
.active_low = 1,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static struct board_info __initdata board_96338w = {
|
||||
.name = "96338W",
|
||||
.expected_cpu_id = 0x6338,
|
||||
|
||||
.has_uart0 = 1,
|
||||
.has_enet0 = 1,
|
||||
.enet0 = {
|
||||
.force_speed_100 = 1,
|
||||
.force_duplex_full = 1,
|
||||
},
|
||||
|
||||
.leds = {
|
||||
{
|
||||
.name = "adsl",
|
||||
.gpio = 3,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ses",
|
||||
.gpio = 5,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ppp-fail",
|
||||
.gpio = 4,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "power",
|
||||
.gpio = 0,
|
||||
.active_low = 1,
|
||||
.default_trigger = "default-on",
|
||||
},
|
||||
{
|
||||
.name = "stop",
|
||||
.gpio = 1,
|
||||
.active_low = 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* known 6345 boards
|
||||
*/
|
||||
#ifdef CONFIG_BCM63XX_CPU_6345
|
||||
static struct board_info __initdata board_96345gw2 = {
|
||||
.name = "96345GW2",
|
||||
.expected_cpu_id = 0x6345,
|
||||
|
||||
.has_uart0 = 1,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* known 6348 boards
|
||||
*/
|
||||
#ifdef CONFIG_BCM63XX_CPU_6348
|
||||
static struct board_info __initdata board_96348r = {
|
||||
.name = "96348R",
|
||||
.expected_cpu_id = 0x6348,
|
||||
|
||||
.has_uart0 = 1,
|
||||
.has_enet0 = 1,
|
||||
.has_pci = 1,
|
||||
|
||||
.enet0 = {
|
||||
.has_phy = 1,
|
||||
.use_internal_phy = 1,
|
||||
},
|
||||
|
||||
.leds = {
|
||||
{
|
||||
.name = "adsl-fail",
|
||||
.gpio = 2,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ppp",
|
||||
.gpio = 3,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ppp-fail",
|
||||
.gpio = 4,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "power",
|
||||
.gpio = 0,
|
||||
.active_low = 1,
|
||||
.default_trigger = "default-on",
|
||||
|
||||
},
|
||||
{
|
||||
.name = "stop",
|
||||
.gpio = 1,
|
||||
.active_low = 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct board_info __initdata board_96348gw_10 = {
|
||||
.name = "96348GW-10",
|
||||
.expected_cpu_id = 0x6348,
|
||||
|
||||
.has_uart0 = 1,
|
||||
.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,
|
||||
|
||||
.has_dsp = 1,
|
||||
.dsp = {
|
||||
.gpio_rst = 6,
|
||||
.gpio_int = 34,
|
||||
.cs = 2,
|
||||
.ext_irq = 2,
|
||||
},
|
||||
|
||||
.leds = {
|
||||
{
|
||||
.name = "adsl-fail",
|
||||
.gpio = 2,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ppp",
|
||||
.gpio = 3,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ppp-fail",
|
||||
.gpio = 4,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "power",
|
||||
.gpio = 0,
|
||||
.active_low = 1,
|
||||
.default_trigger = "default-on",
|
||||
},
|
||||
{
|
||||
.name = "stop",
|
||||
.gpio = 1,
|
||||
.active_low = 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct board_info __initdata board_96348gw_11 = {
|
||||
.name = "96348GW-11",
|
||||
.expected_cpu_id = 0x6348,
|
||||
|
||||
.has_uart0 = 1,
|
||||
.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,
|
||||
|
||||
.leds = {
|
||||
{
|
||||
.name = "adsl-fail",
|
||||
.gpio = 2,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ppp",
|
||||
.gpio = 3,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ppp-fail",
|
||||
.gpio = 4,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "power",
|
||||
.gpio = 0,
|
||||
.active_low = 1,
|
||||
.default_trigger = "default-on",
|
||||
},
|
||||
{
|
||||
.name = "stop",
|
||||
.gpio = 1,
|
||||
.active_low = 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct board_info __initdata board_96348gw = {
|
||||
.name = "96348GW",
|
||||
.expected_cpu_id = 0x6348,
|
||||
|
||||
.has_uart0 = 1,
|
||||
.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_dsp = 1,
|
||||
.dsp = {
|
||||
.gpio_rst = 6,
|
||||
.gpio_int = 34,
|
||||
.ext_irq = 2,
|
||||
.cs = 2,
|
||||
},
|
||||
|
||||
.leds = {
|
||||
{
|
||||
.name = "adsl-fail",
|
||||
.gpio = 2,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ppp",
|
||||
.gpio = 3,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ppp-fail",
|
||||
.gpio = 4,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "power",
|
||||
.gpio = 0,
|
||||
.active_low = 1,
|
||||
.default_trigger = "default-on",
|
||||
},
|
||||
{
|
||||
.name = "stop",
|
||||
.gpio = 1,
|
||||
.active_low = 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct board_info __initdata board_FAST2404 = {
|
||||
.name = "F@ST2404",
|
||||
.expected_cpu_id = 0x6348,
|
||||
|
||||
.has_uart0 = 1,
|
||||
.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,
|
||||
};
|
||||
|
||||
static struct board_info __initdata board_rta1025w_16 = {
|
||||
.name = "RTA1025W_16",
|
||||
.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,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
static struct board_info __initdata board_DV201AMR = {
|
||||
.name = "DV201AMR",
|
||||
.expected_cpu_id = 0x6348,
|
||||
|
||||
.has_uart0 = 1,
|
||||
.has_pci = 1,
|
||||
.has_ohci0 = 1,
|
||||
|
||||
.has_enet0 = 1,
|
||||
.has_enet1 = 1,
|
||||
.enet0 = {
|
||||
.has_phy = 1,
|
||||
.use_internal_phy = 1,
|
||||
},
|
||||
.enet1 = {
|
||||
.force_speed_100 = 1,
|
||||
.force_duplex_full = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct board_info __initdata board_96348gw_a = {
|
||||
.name = "96348GW-A",
|
||||
.expected_cpu_id = 0x6348,
|
||||
|
||||
.has_uart0 = 1,
|
||||
.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,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* known 6358 boards
|
||||
*/
|
||||
#ifdef CONFIG_BCM63XX_CPU_6358
|
||||
static struct board_info __initdata board_96358vw = {
|
||||
.name = "96358VW",
|
||||
.expected_cpu_id = 0x6358,
|
||||
|
||||
.has_uart0 = 1,
|
||||
.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,
|
||||
|
||||
.leds = {
|
||||
{
|
||||
.name = "adsl-fail",
|
||||
.gpio = 15,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ppp",
|
||||
.gpio = 22,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ppp-fail",
|
||||
.gpio = 23,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "power",
|
||||
.gpio = 4,
|
||||
.default_trigger = "default-on",
|
||||
},
|
||||
{
|
||||
.name = "stop",
|
||||
.gpio = 5,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct board_info __initdata board_96358vw2 = {
|
||||
.name = "96358VW2",
|
||||
.expected_cpu_id = 0x6358,
|
||||
|
||||
.has_uart0 = 1,
|
||||
.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,
|
||||
|
||||
.leds = {
|
||||
{
|
||||
.name = "adsl",
|
||||
.gpio = 22,
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.name = "ppp-fail",
|
||||
.gpio = 23,
|
||||
},
|
||||
{
|
||||
.name = "power",
|
||||
.gpio = 5,
|
||||
.active_low = 1,
|
||||
.default_trigger = "default-on",
|
||||
},
|
||||
{
|
||||
.name = "stop",
|
||||
.gpio = 4,
|
||||
.active_low = 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct board_info __initdata board_AGPFS0 = {
|
||||
.name = "AGPF-S0",
|
||||
.expected_cpu_id = 0x6358,
|
||||
|
||||
.has_uart0 = 1,
|
||||
.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_ehci0 = 1,
|
||||
};
|
||||
|
||||
static struct board_info __initdata board_DWVS0 = {
|
||||
.name = "DWV-S0",
|
||||
.expected_cpu_id = 0x6358,
|
||||
|
||||
.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,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* all boards
|
||||
*/
|
||||
static const struct board_info __initconst *bcm963xx_boards[] = {
|
||||
#ifdef CONFIG_BCM63XX_CPU_3368
|
||||
&board_cvg834g,
|
||||
#endif
|
||||
#ifdef CONFIG_BCM63XX_CPU_6328
|
||||
&board_96328avng,
|
||||
#endif
|
||||
#ifdef CONFIG_BCM63XX_CPU_6338
|
||||
&board_96338gw,
|
||||
&board_96338w,
|
||||
#endif
|
||||
#ifdef CONFIG_BCM63XX_CPU_6345
|
||||
&board_96345gw2,
|
||||
#endif
|
||||
#ifdef CONFIG_BCM63XX_CPU_6348
|
||||
&board_96348r,
|
||||
&board_96348gw,
|
||||
&board_96348gw_10,
|
||||
&board_96348gw_11,
|
||||
&board_FAST2404,
|
||||
&board_DV201AMR,
|
||||
&board_96348gw_a,
|
||||
&board_rta1025w_16,
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BCM63XX_CPU_6358
|
||||
&board_96358vw,
|
||||
&board_96358vw2,
|
||||
&board_AGPFS0,
|
||||
&board_DWVS0,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Register a sane SPROMv2 to make the on-board
|
||||
* bcm4318 WLAN work
|
||||
*/
|
||||
#ifdef CONFIG_SSB_PCIHOST
|
||||
static struct ssb_sprom bcm63xx_sprom = {
|
||||
.revision = 0x02,
|
||||
.board_rev = 0x17,
|
||||
.country_code = 0x0,
|
||||
.ant_available_bg = 0x3,
|
||||
.pa0b0 = 0x15ae,
|
||||
.pa0b1 = 0xfa85,
|
||||
.pa0b2 = 0xfe8d,
|
||||
.pa1b0 = 0xffff,
|
||||
.pa1b1 = 0xffff,
|
||||
.pa1b2 = 0xffff,
|
||||
.gpio0 = 0xff,
|
||||
.gpio1 = 0xff,
|
||||
.gpio2 = 0xff,
|
||||
.gpio3 = 0xff,
|
||||
.maxpwr_bg = 0x004c,
|
||||
.itssi_bg = 0x00,
|
||||
.boardflags_lo = 0x2848,
|
||||
.boardflags_hi = 0x0000,
|
||||
};
|
||||
|
||||
int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
|
||||
{
|
||||
if (bus->bustype == SSB_BUSTYPE_PCI) {
|
||||
memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
|
||||
return 0;
|
||||
} else {
|
||||
printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* return board name for /proc/cpuinfo
|
||||
*/
|
||||
const char *board_get_name(void)
|
||||
{
|
||||
return board.name;
|
||||
}
|
||||
|
||||
/*
|
||||
* early init callback, read nvram data from flash and checksum it
|
||||
*/
|
||||
void __init board_prom_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
u8 *boot_addr, *cfe;
|
||||
char cfe_version[32];
|
||||
char *board_name = NULL;
|
||||
u32 val;
|
||||
struct bcm_hcs *hcs;
|
||||
|
||||
/* read base address of boot chip select (0)
|
||||
* 6328/6362 do not have MPI but boot from a fixed address
|
||||
*/
|
||||
if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) {
|
||||
val = 0x18000000;
|
||||
} else {
|
||||
val = bcm_mpi_readl(MPI_CSBASE_REG(0));
|
||||
val &= MPI_CSBASE_BASE_MASK;
|
||||
}
|
||||
boot_addr = (u8 *)KSEG1ADDR(val);
|
||||
|
||||
/* dump cfe version */
|
||||
cfe = boot_addr + BCM963XX_CFE_VERSION_OFFSET;
|
||||
if (!memcmp(cfe, "cfe-v", 5))
|
||||
snprintf(cfe_version, sizeof(cfe_version), "%u.%u.%u-%u.%u",
|
||||
cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]);
|
||||
else
|
||||
strcpy(cfe_version, "unknown");
|
||||
printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
|
||||
|
||||
bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET);
|
||||
|
||||
if (BCMCPU_IS_3368()) {
|
||||
hcs = (struct bcm_hcs *)boot_addr;
|
||||
board_name = hcs->filename;
|
||||
} else {
|
||||
board_name = bcm63xx_nvram_get_name();
|
||||
}
|
||||
/* find board by name */
|
||||
for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) {
|
||||
if (strncmp(board_name, bcm963xx_boards[i]->name, 16))
|
||||
continue;
|
||||
/* copy, board desc array is marked initdata */
|
||||
memcpy(&board, bcm963xx_boards[i], sizeof(board));
|
||||
break;
|
||||
}
|
||||
|
||||
/* bail out if board is not found, will complain later */
|
||||
if (!board.name[0]) {
|
||||
char name[17];
|
||||
memcpy(name, board_name, 16);
|
||||
name[16] = 0;
|
||||
printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",
|
||||
name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
if (board.has_pci) {
|
||||
bcm63xx_pci_enabled = 1;
|
||||
if (BCMCPU_IS_6348())
|
||||
val |= GPIO_MODE_6348_G2_PCI;
|
||||
}
|
||||
#endif
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
static struct gpio_led_platform_data bcm63xx_led_data;
|
||||
|
||||
static struct platform_device bcm63xx_gpio_leds = {
|
||||
.name = "leds-gpio",
|
||||
.id = 0,
|
||||
.dev.platform_data = &bcm63xx_led_data,
|
||||
};
|
||||
|
||||
/*
|
||||
* third stage init callback, register all board devices.
|
||||
*/
|
||||
int __init board_register_devices(void)
|
||||
{
|
||||
if (board.has_uart0)
|
||||
bcm63xx_uart_register(0);
|
||||
|
||||
if (board.has_uart1)
|
||||
bcm63xx_uart_register(1);
|
||||
|
||||
if (board.has_pccard)
|
||||
bcm63xx_pcmcia_register();
|
||||
|
||||
if (board.has_enet0 &&
|
||||
!bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
|
||||
bcm63xx_enet_register(0, &board.enet0);
|
||||
|
||||
if (board.has_enet1 &&
|
||||
!bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
|
||||
bcm63xx_enet_register(1, &board.enet1);
|
||||
|
||||
if (board.has_enetsw &&
|
||||
!bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
|
||||
bcm63xx_enetsw_register(&board.enetsw);
|
||||
|
||||
if (board.has_usbd)
|
||||
bcm63xx_usbd_register(&board.usbd);
|
||||
|
||||
if (board.has_dsp)
|
||||
bcm63xx_dsp_register(&board.dsp);
|
||||
|
||||
/* Generate MAC address for WLAN and register our SPROM,
|
||||
* do this after registering enet devices
|
||||
*/
|
||||
#ifdef CONFIG_SSB_PCIHOST
|
||||
if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
|
||||
memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
|
||||
memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
|
||||
if (ssb_arch_register_fallback_sprom(
|
||||
&bcm63xx_get_fallback_sprom) < 0)
|
||||
pr_err(PFX "failed to register fallback SPROM\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
bcm63xx_spi_register();
|
||||
|
||||
bcm63xx_hsspi_register();
|
||||
|
||||
bcm63xx_flash_register();
|
||||
|
||||
bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
|
||||
bcm63xx_led_data.leds = board.leds;
|
||||
|
||||
platform_device_register(&bcm63xx_gpio_leds);
|
||||
|
||||
if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags)
|
||||
gpio_request_one(board.ephy_reset_gpio,
|
||||
board.ephy_reset_gpio_flags, "ephy-reset");
|
||||
|
||||
return 0;
|
||||
}
|
||||
410
arch/mips/bcm63xx/clk.c
Normal file
410
arch/mips/bcm63xx/clk.c
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
/*
|
||||
* 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 <linux/delay.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
#include <bcm63xx_reset.h>
|
||||
|
||||
struct clk {
|
||||
void (*set)(struct clk *, int);
|
||||
unsigned int rate;
|
||||
unsigned int usage;
|
||||
int id;
|
||||
};
|
||||
|
||||
static 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_3368() || 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_3368() || BCMCPU_IS_6358())
|
||||
bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable);
|
||||
}
|
||||
|
||||
|
||||
static struct clk clk_ephy = {
|
||||
.set = ephy_set,
|
||||
};
|
||||
|
||||
/*
|
||||
* Ethernet switch clock
|
||||
*/
|
||||
static void enetsw_set(struct clk *clk, int enable)
|
||||
{
|
||||
if (BCMCPU_IS_6328())
|
||||
bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable);
|
||||
else if (BCMCPU_IS_6362())
|
||||
bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable);
|
||||
else if (BCMCPU_IS_6368())
|
||||
bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
|
||||
CKCTL_6368_SWPKT_USB_EN |
|
||||
CKCTL_6368_SWPKT_SAR_EN,
|
||||
enable);
|
||||
else
|
||||
return;
|
||||
|
||||
if (enable) {
|
||||
/* reset switch core afer clock change */
|
||||
bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
|
||||
msleep(10);
|
||||
bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
|
||||
msleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
static struct clk clk_enetsw = {
|
||||
.set = enetsw_set,
|
||||
};
|
||||
|
||||
/*
|
||||
* PCM clock
|
||||
*/
|
||||
static void pcm_set(struct clk *clk, int enable)
|
||||
{
|
||||
if (BCMCPU_IS_3368())
|
||||
bcm_hwclock_set(CKCTL_3368_PCM_EN, enable);
|
||||
if (BCMCPU_IS_6358())
|
||||
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_6328())
|
||||
bcm_hwclock_set(CKCTL_6328_USBH_EN, enable);
|
||||
else if (BCMCPU_IS_6348())
|
||||
bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
|
||||
else if (BCMCPU_IS_6362())
|
||||
bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
|
||||
else if (BCMCPU_IS_6368())
|
||||
bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
|
||||
}
|
||||
|
||||
static struct clk clk_usbh = {
|
||||
.set = usbh_set,
|
||||
};
|
||||
|
||||
/*
|
||||
* USB device clock
|
||||
*/
|
||||
static void usbd_set(struct clk *clk, int enable)
|
||||
{
|
||||
if (BCMCPU_IS_6328())
|
||||
bcm_hwclock_set(CKCTL_6328_USBD_EN, enable);
|
||||
else if (BCMCPU_IS_6362())
|
||||
bcm_hwclock_set(CKCTL_6362_USBD_EN, enable);
|
||||
else if (BCMCPU_IS_6368())
|
||||
bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
|
||||
}
|
||||
|
||||
static struct clk clk_usbd = {
|
||||
.set = usbd_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 if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
|
||||
mask = CKCTL_6358_SPI_EN;
|
||||
else if (BCMCPU_IS_6362())
|
||||
mask = CKCTL_6362_SPI_EN;
|
||||
else
|
||||
/* BCMCPU_IS_6368 */
|
||||
mask = CKCTL_6368_SPI_EN;
|
||||
bcm_hwclock_set(mask, enable);
|
||||
}
|
||||
|
||||
static struct clk clk_spi = {
|
||||
.set = spi_set,
|
||||
};
|
||||
|
||||
/*
|
||||
* HSSPI clock
|
||||
*/
|
||||
static void hsspi_set(struct clk *clk, int enable)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
if (BCMCPU_IS_6328())
|
||||
mask = CKCTL_6328_HSSPI_EN;
|
||||
else if (BCMCPU_IS_6362())
|
||||
mask = CKCTL_6362_HSSPI_EN;
|
||||
else
|
||||
return;
|
||||
|
||||
bcm_hwclock_set(mask, enable);
|
||||
}
|
||||
|
||||
static struct clk clk_hsspi = {
|
||||
.set = hsspi_set,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* XTM clock
|
||||
*/
|
||||
static void xtm_set(struct clk *clk, int enable)
|
||||
{
|
||||
if (!BCMCPU_IS_6368())
|
||||
return;
|
||||
|
||||
bcm_hwclock_set(CKCTL_6368_SAR_EN |
|
||||
CKCTL_6368_SWPKT_SAR_EN, enable);
|
||||
|
||||
if (enable) {
|
||||
/* reset sar core afer clock change */
|
||||
bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
|
||||
mdelay(1);
|
||||
bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
|
||||
mdelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct clk clk_xtm = {
|
||||
.set = xtm_set,
|
||||
};
|
||||
|
||||
/*
|
||||
* IPsec clock
|
||||
*/
|
||||
static void ipsec_set(struct clk *clk, int enable)
|
||||
{
|
||||
if (BCMCPU_IS_6362())
|
||||
bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable);
|
||||
else if (BCMCPU_IS_6368())
|
||||
bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
|
||||
}
|
||||
|
||||
static struct clk clk_ipsec = {
|
||||
.set = ipsec_set,
|
||||
};
|
||||
|
||||
/*
|
||||
* PCIe clock
|
||||
*/
|
||||
|
||||
static void pcie_set(struct clk *clk, int enable)
|
||||
{
|
||||
if (BCMCPU_IS_6328())
|
||||
bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
|
||||
else if (BCMCPU_IS_6362())
|
||||
bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
|
||||
}
|
||||
|
||||
static struct clk clk_pcie = {
|
||||
.set = pcie_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);
|
||||
|
||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_rate);
|
||||
|
||||
long clk_round_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_round_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, "enetsw"))
|
||||
return &clk_enetsw;
|
||||
if (!strcmp(id, "ephy"))
|
||||
return &clk_ephy;
|
||||
if (!strcmp(id, "usbh"))
|
||||
return &clk_usbh;
|
||||
if (!strcmp(id, "usbd"))
|
||||
return &clk_usbd;
|
||||
if (!strcmp(id, "spi"))
|
||||
return &clk_spi;
|
||||
if (!strcmp(id, "hsspi"))
|
||||
return &clk_hsspi;
|
||||
if (!strcmp(id, "xtm"))
|
||||
return &clk_xtm;
|
||||
if (!strcmp(id, "periph"))
|
||||
return &clk_periph;
|
||||
if ((BCMCPU_IS_3368() || BCMCPU_IS_6358()) && !strcmp(id, "pcm"))
|
||||
return &clk_pcm;
|
||||
if ((BCMCPU_IS_6362() || BCMCPU_IS_6368()) && !strcmp(id, "ipsec"))
|
||||
return &clk_ipsec;
|
||||
if ((BCMCPU_IS_6328() || BCMCPU_IS_6362()) && !strcmp(id, "pcie"))
|
||||
return &clk_pcie;
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(clk_get);
|
||||
|
||||
void clk_put(struct clk *clk)
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(clk_put);
|
||||
|
||||
#define HSSPI_PLL_HZ_6328 133333333
|
||||
#define HSSPI_PLL_HZ_6362 400000000
|
||||
|
||||
static int __init bcm63xx_clk_init(void)
|
||||
{
|
||||
switch (bcm63xx_get_cpu_id()) {
|
||||
case BCM6328_CPU_ID:
|
||||
clk_hsspi.rate = HSSPI_PLL_HZ_6328;
|
||||
break;
|
||||
case BCM6362_CPU_ID:
|
||||
clk_hsspi.rate = HSSPI_PLL_HZ_6362;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(bcm63xx_clk_init);
|
||||
385
arch/mips/bcm63xx/cpu.c
Normal file
385
arch/mips/bcm63xx/cpu.c
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
* 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) 2009 Florian Fainelli <florian@openwrt.org>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/cpu-info.h>
|
||||
#include <asm/mipsregs.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);
|
||||
|
||||
u16 bcm63xx_cpu_id __read_mostly;
|
||||
EXPORT_SYMBOL(bcm63xx_cpu_id);
|
||||
|
||||
static u8 bcm63xx_cpu_rev;
|
||||
static unsigned int bcm63xx_cpu_freq;
|
||||
static unsigned int bcm63xx_memory_size;
|
||||
|
||||
static const unsigned long bcm3368_regs_base[] = {
|
||||
__GEN_CPU_REGS_TABLE(3368)
|
||||
};
|
||||
|
||||
static const int bcm3368_irqs[] = {
|
||||
__GEN_CPU_IRQ_TABLE(3368)
|
||||
};
|
||||
|
||||
static const unsigned long bcm6328_regs_base[] = {
|
||||
__GEN_CPU_REGS_TABLE(6328)
|
||||
};
|
||||
|
||||
static const int bcm6328_irqs[] = {
|
||||
__GEN_CPU_IRQ_TABLE(6328)
|
||||
};
|
||||
|
||||
static const unsigned long bcm6338_regs_base[] = {
|
||||
__GEN_CPU_REGS_TABLE(6338)
|
||||
};
|
||||
|
||||
static const int bcm6338_irqs[] = {
|
||||
__GEN_CPU_IRQ_TABLE(6338)
|
||||
};
|
||||
|
||||
static const unsigned long bcm6345_regs_base[] = {
|
||||
__GEN_CPU_REGS_TABLE(6345)
|
||||
};
|
||||
|
||||
static const int bcm6345_irqs[] = {
|
||||
__GEN_CPU_IRQ_TABLE(6345)
|
||||
};
|
||||
|
||||
static const unsigned long bcm6348_regs_base[] = {
|
||||
__GEN_CPU_REGS_TABLE(6348)
|
||||
};
|
||||
|
||||
static const int bcm6348_irqs[] = {
|
||||
__GEN_CPU_IRQ_TABLE(6348)
|
||||
|
||||
};
|
||||
|
||||
static const unsigned long bcm6358_regs_base[] = {
|
||||
__GEN_CPU_REGS_TABLE(6358)
|
||||
};
|
||||
|
||||
static const int bcm6358_irqs[] = {
|
||||
__GEN_CPU_IRQ_TABLE(6358)
|
||||
|
||||
};
|
||||
|
||||
static const unsigned long bcm6362_regs_base[] = {
|
||||
__GEN_CPU_REGS_TABLE(6362)
|
||||
};
|
||||
|
||||
static const int bcm6362_irqs[] = {
|
||||
__GEN_CPU_IRQ_TABLE(6362)
|
||||
|
||||
};
|
||||
|
||||
static const unsigned long bcm6368_regs_base[] = {
|
||||
__GEN_CPU_REGS_TABLE(6368)
|
||||
};
|
||||
|
||||
static const int bcm6368_irqs[] = {
|
||||
__GEN_CPU_IRQ_TABLE(6368)
|
||||
|
||||
};
|
||||
|
||||
u8 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)
|
||||
{
|
||||
u16 cpu_id = bcm63xx_get_cpu_id();
|
||||
|
||||
switch (cpu_id) {
|
||||
case BCM3368_CPU_ID:
|
||||
return 300000000;
|
||||
|
||||
case BCM6328_CPU_ID:
|
||||
{
|
||||
unsigned int tmp, mips_pll_fcvo;
|
||||
|
||||
tmp = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
|
||||
mips_pll_fcvo = (tmp & STRAPBUS_6328_FCVO_MASK)
|
||||
>> STRAPBUS_6328_FCVO_SHIFT;
|
||||
|
||||
switch (mips_pll_fcvo) {
|
||||
case 0x12:
|
||||
case 0x14:
|
||||
case 0x19:
|
||||
return 160000000;
|
||||
case 0x1c:
|
||||
return 192000000;
|
||||
case 0x13:
|
||||
case 0x15:
|
||||
return 200000000;
|
||||
case 0x1a:
|
||||
return 384000000;
|
||||
case 0x16:
|
||||
return 400000000;
|
||||
default:
|
||||
return 320000000;
|
||||
}
|
||||
|
||||
}
|
||||
case BCM6338_CPU_ID:
|
||||
/* BCM6338 has a fixed 240 Mhz frequency */
|
||||
return 240000000;
|
||||
|
||||
case BCM6345_CPU_ID:
|
||||
/* BCM6345 has a fixed 140Mhz frequency */
|
||||
return 140000000;
|
||||
|
||||
case BCM6348_CPU_ID:
|
||||
{
|
||||
unsigned int tmp, n1, n2, m1;
|
||||
|
||||
/* 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;
|
||||
return (16 * 1000000 * n1 * n2) / m1;
|
||||
}
|
||||
|
||||
case BCM6358_CPU_ID:
|
||||
{
|
||||
unsigned int tmp, n1, n2, m1;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
case BCM6362_CPU_ID:
|
||||
{
|
||||
unsigned int tmp, mips_pll_fcvo;
|
||||
|
||||
tmp = bcm_misc_readl(MISC_STRAPBUS_6362_REG);
|
||||
mips_pll_fcvo = (tmp & STRAPBUS_6362_FCVO_MASK)
|
||||
>> STRAPBUS_6362_FCVO_SHIFT;
|
||||
switch (mips_pll_fcvo) {
|
||||
case 0x03:
|
||||
case 0x0b:
|
||||
case 0x13:
|
||||
case 0x1b:
|
||||
return 240000000;
|
||||
case 0x04:
|
||||
case 0x0c:
|
||||
case 0x14:
|
||||
case 0x1c:
|
||||
return 160000000;
|
||||
case 0x05:
|
||||
case 0x0e:
|
||||
case 0x16:
|
||||
case 0x1e:
|
||||
case 0x1f:
|
||||
return 400000000;
|
||||
case 0x06:
|
||||
return 440000000;
|
||||
case 0x07:
|
||||
case 0x17:
|
||||
return 384000000;
|
||||
case 0x15:
|
||||
case 0x1d:
|
||||
return 200000000;
|
||||
default:
|
||||
return 320000000;
|
||||
}
|
||||
}
|
||||
case BCM6368_CPU_ID:
|
||||
{
|
||||
unsigned int tmp, p1, p2, ndiv, m1;
|
||||
|
||||
/* (64MHz / P1) * P2 * NDIV / M1_CPU */
|
||||
tmp = bcm_ddr_readl(DDR_DMIPSPLLCFG_6368_REG);
|
||||
|
||||
p1 = (tmp & DMIPSPLLCFG_6368_P1_MASK) >>
|
||||
DMIPSPLLCFG_6368_P1_SHIFT;
|
||||
|
||||
p2 = (tmp & DMIPSPLLCFG_6368_P2_MASK) >>
|
||||
DMIPSPLLCFG_6368_P2_SHIFT;
|
||||
|
||||
ndiv = (tmp & DMIPSPLLCFG_6368_NDIV_MASK) >>
|
||||
DMIPSPLLCFG_6368_NDIV_SHIFT;
|
||||
|
||||
tmp = bcm_ddr_readl(DDR_DMIPSPLLDIV_6368_REG);
|
||||
m1 = (tmp & DMIPSPLLDIV_6368_MDIV_MASK) >>
|
||||
DMIPSPLLDIV_6368_MDIV_SHIFT;
|
||||
|
||||
return (((64 * 1000000) / p1) * p2 * ndiv) / m1;
|
||||
}
|
||||
|
||||
default:
|
||||
panic("Failed to detect clock for CPU with id=%04X\n", cpu_id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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_6328() || BCMCPU_IS_6362())
|
||||
return bcm_ddr_readl(DDR_CSEND_REG) << 24;
|
||||
|
||||
if (BCMCPU_IS_6345()) {
|
||||
val = bcm_sdram_readl(SDRAM_MBASE_REG);
|
||||
return (val * 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_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
|
||||
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;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
u32 chipid_reg;
|
||||
|
||||
/* soc registers location depends on cpu type */
|
||||
chipid_reg = 0;
|
||||
|
||||
switch (current_cpu_type()) {
|
||||
case CPU_BMIPS3300:
|
||||
if ((read_c0_prid() & PRID_IMP_MASK) != PRID_IMP_BMIPS3300_ALT)
|
||||
__cpu_name[cpu] = "Broadcom BCM6338";
|
||||
/* fall-through */
|
||||
case CPU_BMIPS32:
|
||||
chipid_reg = BCM_6345_PERF_BASE;
|
||||
break;
|
||||
case CPU_BMIPS4350:
|
||||
switch ((read_c0_prid() & PRID_REV_MASK)) {
|
||||
case 0x04:
|
||||
chipid_reg = BCM_3368_PERF_BASE;
|
||||
break;
|
||||
case 0x10:
|
||||
chipid_reg = BCM_6345_PERF_BASE;
|
||||
break;
|
||||
default:
|
||||
chipid_reg = BCM_6368_PERF_BASE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* really early to panic, but delaying panic would not help since we
|
||||
* will never get any working console
|
||||
*/
|
||||
if (!chipid_reg)
|
||||
panic("unsupported Broadcom CPU");
|
||||
|
||||
/* read out CPU type */
|
||||
tmp = bcm_readl(chipid_reg);
|
||||
bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
|
||||
bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT;
|
||||
|
||||
switch (bcm63xx_cpu_id) {
|
||||
case BCM3368_CPU_ID:
|
||||
bcm63xx_regs_base = bcm3368_regs_base;
|
||||
bcm63xx_irqs = bcm3368_irqs;
|
||||
break;
|
||||
case BCM6328_CPU_ID:
|
||||
bcm63xx_regs_base = bcm6328_regs_base;
|
||||
bcm63xx_irqs = bcm6328_irqs;
|
||||
break;
|
||||
case BCM6338_CPU_ID:
|
||||
bcm63xx_regs_base = bcm6338_regs_base;
|
||||
bcm63xx_irqs = bcm6338_irqs;
|
||||
break;
|
||||
case BCM6345_CPU_ID:
|
||||
bcm63xx_regs_base = bcm6345_regs_base;
|
||||
bcm63xx_irqs = bcm6345_irqs;
|
||||
break;
|
||||
case BCM6348_CPU_ID:
|
||||
bcm63xx_regs_base = bcm6348_regs_base;
|
||||
bcm63xx_irqs = bcm6348_irqs;
|
||||
break;
|
||||
case BCM6358_CPU_ID:
|
||||
bcm63xx_regs_base = bcm6358_regs_base;
|
||||
bcm63xx_irqs = bcm6358_irqs;
|
||||
break;
|
||||
case BCM6362_CPU_ID:
|
||||
bcm63xx_regs_base = bcm6362_regs_base;
|
||||
bcm63xx_irqs = bcm6362_irqs;
|
||||
break;
|
||||
case BCM6368_CPU_ID:
|
||||
bcm63xx_regs_base = bcm6368_regs_base;
|
||||
bcm63xx_irqs = bcm6368_irqs;
|
||||
break;
|
||||
default:
|
||||
panic("unsupported broadcom CPU %x", bcm63xx_cpu_id);
|
||||
break;
|
||||
}
|
||||
|
||||
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 MHz\n",
|
||||
bcm63xx_cpu_freq / 1000000);
|
||||
printk(KERN_INFO "%uMB of RAM installed\n",
|
||||
bcm63xx_memory_size >> 20);
|
||||
}
|
||||
144
arch/mips/bcm63xx/cs.c
Normal file
144
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);
|
||||
56
arch/mips/bcm63xx/dev-dsp.c
Normal file
56
arch/mips/bcm63xx/dev-dsp.c
Normal file
|
|
@ -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 = -1,
|
||||
.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);
|
||||
}
|
||||
311
arch/mips/bcm63xx/dev-enet.c
Normal file
311
arch/mips/bcm63xx/dev-enet.c
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
/*
|
||||
* 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 <linux/export.h>
|
||||
#include <bcm63xx_dev_enet.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
|
||||
static const unsigned long bcm6348_regs_enetdmac[] = {
|
||||
[ENETDMAC_CHANCFG] = ENETDMAC_CHANCFG_REG,
|
||||
[ENETDMAC_IR] = ENETDMAC_IR_REG,
|
||||
[ENETDMAC_IRMASK] = ENETDMAC_IRMASK_REG,
|
||||
[ENETDMAC_MAXBURST] = ENETDMAC_MAXBURST_REG,
|
||||
};
|
||||
|
||||
static const unsigned long bcm6345_regs_enetdmac[] = {
|
||||
[ENETDMAC_CHANCFG] = ENETDMA_6345_CHANCFG_REG,
|
||||
[ENETDMAC_IR] = ENETDMA_6345_IR_REG,
|
||||
[ENETDMAC_IRMASK] = ENETDMA_6345_IRMASK_REG,
|
||||
[ENETDMAC_MAXBURST] = ENETDMA_6345_MAXBURST_REG,
|
||||
[ENETDMAC_BUFALLOC] = ENETDMA_6345_BUFALLOC_REG,
|
||||
[ENETDMAC_RSTART] = ENETDMA_6345_RSTART_REG,
|
||||
[ENETDMAC_FC] = ENETDMA_6345_FC_REG,
|
||||
[ENETDMAC_LEN] = ENETDMA_6345_LEN_REG,
|
||||
};
|
||||
|
||||
const unsigned long *bcm63xx_regs_enetdmac;
|
||||
EXPORT_SYMBOL(bcm63xx_regs_enetdmac);
|
||||
|
||||
static __init void bcm63xx_enetdmac_regs_init(void)
|
||||
{
|
||||
if (BCMCPU_IS_6345())
|
||||
bcm63xx_regs_enetdmac = bcm6345_regs_enetdmac;
|
||||
else
|
||||
bcm63xx_regs_enetdmac = bcm6348_regs_enetdmac;
|
||||
}
|
||||
|
||||
static struct resource shared_res[] = {
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.end = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.end = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.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;
|
||||
|
||||
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 */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.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,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource enetsw_res[] = {
|
||||
{
|
||||
/* start & end filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
/* start filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
/* start filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct bcm63xx_enetsw_platform_data enetsw_pd;
|
||||
|
||||
static struct platform_device bcm63xx_enetsw_device = {
|
||||
.name = "bcm63xx_enetsw",
|
||||
.num_resources = ARRAY_SIZE(enetsw_res),
|
||||
.resource = enetsw_res,
|
||||
.dev = {
|
||||
.platform_data = &enetsw_pd,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init register_shared(void)
|
||||
{
|
||||
int ret, chan_count;
|
||||
|
||||
if (shared_device_registered)
|
||||
return 0;
|
||||
|
||||
bcm63xx_enetdmac_regs_init();
|
||||
|
||||
shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
|
||||
shared_res[0].end = shared_res[0].start;
|
||||
if (BCMCPU_IS_6345())
|
||||
shared_res[0].end += (RSET_6345_ENETDMA_SIZE) - 1;
|
||||
else
|
||||
shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
|
||||
|
||||
if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368())
|
||||
chan_count = 32;
|
||||
else if (BCMCPU_IS_6345())
|
||||
chan_count = 8;
|
||||
else
|
||||
chan_count = 16;
|
||||
|
||||
shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
|
||||
shared_res[1].end = shared_res[1].start;
|
||||
shared_res[1].end += RSET_ENETDMAC_SIZE(chan_count) - 1;
|
||||
|
||||
shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
|
||||
shared_res[2].end = shared_res[2].start;
|
||||
shared_res[2].end += RSET_ENETDMAS_SIZE(chan_count) - 1;
|
||||
|
||||
ret = platform_device_register(&bcm63xx_enet_shared_device);
|
||||
if (ret)
|
||||
return ret;
|
||||
shared_device_registered = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 (unit == 1 && (BCMCPU_IS_6338() || BCMCPU_IS_6345()))
|
||||
return -ENODEV;
|
||||
|
||||
ret = register_shared();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
dpd->dma_chan_en_mask = ENETDMAC_CHANCFG_EN_MASK;
|
||||
dpd->dma_chan_int_mask = ENETDMAC_IR_PKTDONE_MASK;
|
||||
if (BCMCPU_IS_6345()) {
|
||||
dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_CHAINING_MASK;
|
||||
dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_WRAP_EN_MASK;
|
||||
dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_FLOWC_EN_MASK;
|
||||
dpd->dma_chan_int_mask |= ENETDMA_IR_BUFDONE_MASK;
|
||||
dpd->dma_chan_int_mask |= ENETDMA_IR_NOTOWNER_MASK;
|
||||
dpd->dma_chan_width = ENETDMA_6345_CHAN_WIDTH;
|
||||
dpd->dma_desc_shift = ENETDMA_6345_DESC_SHIFT;
|
||||
} else {
|
||||
dpd->dma_has_sram = true;
|
||||
dpd->dma_chan_width = ENETDMA_CHAN_WIDTH;
|
||||
}
|
||||
|
||||
ret = platform_device_register(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init
|
||||
bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
|
||||
return -ENODEV;
|
||||
|
||||
ret = register_shared();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
enetsw_res[0].start = bcm63xx_regset_address(RSET_ENETSW);
|
||||
enetsw_res[0].end = enetsw_res[0].start;
|
||||
enetsw_res[0].end += RSET_ENETSW_SIZE - 1;
|
||||
enetsw_res[1].start = bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0);
|
||||
enetsw_res[2].start = bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0);
|
||||
if (!enetsw_res[2].start)
|
||||
enetsw_res[2].start = -1;
|
||||
|
||||
memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof(*pd));
|
||||
|
||||
if (BCMCPU_IS_6328())
|
||||
enetsw_pd.num_ports = ENETSW_PORTS_6328;
|
||||
else if (BCMCPU_IS_6362() || BCMCPU_IS_6368())
|
||||
enetsw_pd.num_ports = ENETSW_PORTS_6368;
|
||||
|
||||
enetsw_pd.dma_has_sram = true;
|
||||
enetsw_pd.dma_chan_width = ENETDMA_CHAN_WIDTH;
|
||||
enetsw_pd.dma_chan_en_mask = ENETDMAC_CHANCFG_EN_MASK;
|
||||
enetsw_pd.dma_chan_int_mask = ENETDMAC_IR_PKTDONE_MASK;
|
||||
|
||||
ret = platform_device_register(&bcm63xx_enetsw_device);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
130
arch/mips/bcm63xx/dev-flash.c
Normal file
130
arch/mips/bcm63xx/dev-flash.c
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Broadcom BCM63xx flash 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) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
* Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
|
||||
* Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_dev_flash.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
#include <bcm63xx_io.h>
|
||||
|
||||
static struct mtd_partition mtd_partitions[] = {
|
||||
{
|
||||
.name = "cfe",
|
||||
.offset = 0x0,
|
||||
.size = 0x40000,
|
||||
}
|
||||
};
|
||||
|
||||
static const char *bcm63xx_part_types[] = { "bcm63xxpart", NULL };
|
||||
|
||||
static struct physmap_flash_data flash_data = {
|
||||
.width = 2,
|
||||
.parts = mtd_partitions,
|
||||
.part_probe_types = bcm63xx_part_types,
|
||||
};
|
||||
|
||||
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 = "physmap-flash",
|
||||
.resource = mtd_resources,
|
||||
.num_resources = ARRAY_SIZE(mtd_resources),
|
||||
.dev = {
|
||||
.platform_data = &flash_data,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init bcm63xx_detect_flash_type(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
switch (bcm63xx_get_cpu_id()) {
|
||||
case BCM6328_CPU_ID:
|
||||
val = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
|
||||
if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
|
||||
return BCM63XX_FLASH_TYPE_SERIAL;
|
||||
else
|
||||
return BCM63XX_FLASH_TYPE_NAND;
|
||||
case BCM6338_CPU_ID:
|
||||
case BCM6345_CPU_ID:
|
||||
case BCM6348_CPU_ID:
|
||||
/* no way to auto detect so assume parallel */
|
||||
return BCM63XX_FLASH_TYPE_PARALLEL;
|
||||
case BCM3368_CPU_ID:
|
||||
case BCM6358_CPU_ID:
|
||||
val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
|
||||
if (val & STRAPBUS_6358_BOOT_SEL_PARALLEL)
|
||||
return BCM63XX_FLASH_TYPE_PARALLEL;
|
||||
else
|
||||
return BCM63XX_FLASH_TYPE_SERIAL;
|
||||
case BCM6362_CPU_ID:
|
||||
val = bcm_misc_readl(MISC_STRAPBUS_6362_REG);
|
||||
if (val & STRAPBUS_6362_BOOT_SEL_SERIAL)
|
||||
return BCM63XX_FLASH_TYPE_SERIAL;
|
||||
else
|
||||
return BCM63XX_FLASH_TYPE_NAND;
|
||||
case BCM6368_CPU_ID:
|
||||
val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
|
||||
switch (val & STRAPBUS_6368_BOOT_SEL_MASK) {
|
||||
case STRAPBUS_6368_BOOT_SEL_NAND:
|
||||
return BCM63XX_FLASH_TYPE_NAND;
|
||||
case STRAPBUS_6368_BOOT_SEL_SERIAL:
|
||||
return BCM63XX_FLASH_TYPE_SERIAL;
|
||||
case STRAPBUS_6368_BOOT_SEL_PARALLEL:
|
||||
return BCM63XX_FLASH_TYPE_PARALLEL;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int __init bcm63xx_flash_register(void)
|
||||
{
|
||||
int flash_type;
|
||||
u32 val;
|
||||
|
||||
flash_type = bcm63xx_detect_flash_type();
|
||||
|
||||
switch (flash_type) {
|
||||
case BCM63XX_FLASH_TYPE_PARALLEL:
|
||||
/* 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;
|
||||
|
||||
return platform_device_register(&mtd_dev);
|
||||
case BCM63XX_FLASH_TYPE_SERIAL:
|
||||
pr_warn("unsupported serial flash detected\n");
|
||||
return -ENODEV;
|
||||
case BCM63XX_FLASH_TYPE_NAND:
|
||||
pr_warn("unsupported NAND flash detected\n");
|
||||
return -ENODEV;
|
||||
default:
|
||||
pr_err("flash detection failed for BCM%x: %d\n",
|
||||
bcm63xx_get_cpu_id(), flash_type);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
47
arch/mips/bcm63xx/dev-hsspi.c
Normal file
47
arch/mips/bcm63xx/dev-hsspi.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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) 2012 Jonas Gorski <jonas.gorski@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_dev_hsspi.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 platform_device bcm63xx_hsspi_device = {
|
||||
.name = "bcm63xx-hsspi",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(spi_resources),
|
||||
.resource = spi_resources,
|
||||
};
|
||||
|
||||
int __init bcm63xx_hsspi_register(void)
|
||||
{
|
||||
if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362())
|
||||
return -ENODEV;
|
||||
|
||||
spi_resources[0].start = bcm63xx_regset_address(RSET_HSSPI);
|
||||
spi_resources[0].end = spi_resources[0].start;
|
||||
spi_resources[0].end += RSET_HSSPI_SIZE - 1;
|
||||
spi_resources[1].start = bcm63xx_get_irq_number(IRQ_HSSPI);
|
||||
|
||||
return platform_device_register(&bcm63xx_hsspi_device);
|
||||
}
|
||||
144
arch/mips/bcm63xx/dev-pcmcia.c
Normal file
144
arch/mips/bcm63xx/dev-pcmcia.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/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 & end 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 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 struct {
|
||||
unsigned int cs;
|
||||
unsigned int base;
|
||||
unsigned int size;
|
||||
} pcmcia_cs[3] __initconst = {
|
||||
{
|
||||
.cs = MPI_CS_PCMCIA_COMMON,
|
||||
.base = BCM_PCMCIA_COMMON_BASE_PA,
|
||||
.size = BCM_PCMCIA_COMMON_SIZE
|
||||
},
|
||||
{
|
||||
.cs = MPI_CS_PCMCIA_ATTR,
|
||||
.base = BCM_PCMCIA_ATTR_BASE_PA,
|
||||
.size = BCM_PCMCIA_ATTR_SIZE
|
||||
},
|
||||
{
|
||||
.cs = MPI_CS_PCMCIA_IO,
|
||||
.base = BCM_PCMCIA_IO_BASE_PA,
|
||||
.size = 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 +
|
||||
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].cs,
|
||||
pcmcia_cs[i].base,
|
||||
pcmcia_cs[i].size);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
return platform_device_register(&bcm63xx_pcmcia_device);
|
||||
|
||||
out_err:
|
||||
printk(KERN_ERR "unable to set pcmcia chip select\n");
|
||||
return ret;
|
||||
}
|
||||
40
arch/mips/bcm63xx/dev-rng.c
Normal file
40
arch/mips/bcm63xx/dev-rng.c
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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) 2011 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 rng_resources[] = {
|
||||
{
|
||||
.start = -1, /* filled at runtime */
|
||||
.end = -1, /* filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device bcm63xx_rng_device = {
|
||||
.name = "bcm63xx-rng",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(rng_resources),
|
||||
.resource = rng_resources,
|
||||
};
|
||||
|
||||
int __init bcm63xx_rng_register(void)
|
||||
{
|
||||
if (!BCMCPU_IS_6368())
|
||||
return -ENODEV;
|
||||
|
||||
rng_resources[0].start = bcm63xx_regset_address(RSET_RNG);
|
||||
rng_resources[0].end = rng_resources[0].start;
|
||||
rng_resources[0].end += RSET_RNG_SIZE - 1;
|
||||
|
||||
return platform_device_register(&bcm63xx_rng_device);
|
||||
}
|
||||
arch_initcall(bcm63xx_rng_register);
|
||||
98
arch/mips/bcm63xx/dev-spi.c
Normal file
98
arch/mips/bcm63xx/dev-spi.c
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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-2011 Florian Fainelli <florian@openwrt.org>
|
||||
* Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_dev_spi.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
|
||||
/*
|
||||
* register offsets
|
||||
*/
|
||||
static const unsigned long bcm6348_regs_spi[] = {
|
||||
__GEN_SPI_REGS_TABLE(6348)
|
||||
};
|
||||
|
||||
static const unsigned long bcm6358_regs_spi[] = {
|
||||
__GEN_SPI_REGS_TABLE(6358)
|
||||
};
|
||||
|
||||
const unsigned long *bcm63xx_regs_spi;
|
||||
EXPORT_SYMBOL(bcm63xx_regs_spi);
|
||||
|
||||
static __init void bcm63xx_spi_regs_init(void)
|
||||
{
|
||||
if (BCMCPU_IS_6338() || BCMCPU_IS_6348())
|
||||
bcm63xx_regs_spi = bcm6348_regs_spi;
|
||||
if (BCMCPU_IS_3368() || BCMCPU_IS_6358() ||
|
||||
BCMCPU_IS_6362() || BCMCPU_IS_6368())
|
||||
bcm63xx_regs_spi = bcm6358_regs_spi;
|
||||
}
|
||||
|
||||
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 = 8,
|
||||
};
|
||||
|
||||
static struct platform_device bcm63xx_spi_device = {
|
||||
.name = "bcm63xx-spi",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(spi_resources),
|
||||
.resource = spi_resources,
|
||||
.dev = {
|
||||
.platform_data = &spi_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
int __init bcm63xx_spi_register(void)
|
||||
{
|
||||
if (BCMCPU_IS_6328() || BCMCPU_IS_6345())
|
||||
return -ENODEV;
|
||||
|
||||
spi_resources[0].start = bcm63xx_regset_address(RSET_SPI);
|
||||
spi_resources[0].end = spi_resources[0].start;
|
||||
spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI);
|
||||
|
||||
if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
|
||||
spi_resources[0].end += BCM_6348_RSET_SPI_SIZE - 1;
|
||||
spi_pdata.fifo_size = SPI_6348_MSG_DATA_SIZE;
|
||||
spi_pdata.msg_type_shift = SPI_6348_MSG_TYPE_SHIFT;
|
||||
spi_pdata.msg_ctl_width = SPI_6348_MSG_CTL_WIDTH;
|
||||
}
|
||||
|
||||
if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6362() ||
|
||||
BCMCPU_IS_6368()) {
|
||||
spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1;
|
||||
spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE;
|
||||
spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT;
|
||||
spi_pdata.msg_ctl_width = SPI_6358_MSG_CTL_WIDTH;
|
||||
}
|
||||
|
||||
bcm63xx_spi_regs_init();
|
||||
|
||||
return platform_device_register(&bcm63xx_spi_device);
|
||||
}
|
||||
76
arch/mips/bcm63xx/dev-uart.c
Normal file
76
arch/mips/bcm63xx/dev-uart.c
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
static struct resource uart0_resources[] = {
|
||||
{
|
||||
/* start & end filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
/* start filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource uart1_resources[] = {
|
||||
{
|
||||
/* start & end filled at runtime */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
/* start filled at runtime */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device bcm63xx_uart_devices[] = {
|
||||
{
|
||||
.name = "bcm63xx_uart",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(uart0_resources),
|
||||
.resource = uart0_resources,
|
||||
},
|
||||
|
||||
{
|
||||
.name = "bcm63xx_uart",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(uart1_resources),
|
||||
.resource = uart1_resources,
|
||||
}
|
||||
};
|
||||
|
||||
int __init bcm63xx_uart_register(unsigned int id)
|
||||
{
|
||||
if (id >= ARRAY_SIZE(bcm63xx_uart_devices))
|
||||
return -ENODEV;
|
||||
|
||||
if (id == 1 && (!BCMCPU_IS_3368() && !BCMCPU_IS_6358() &&
|
||||
!BCMCPU_IS_6368()))
|
||||
return -ENODEV;
|
||||
|
||||
if (id == 0) {
|
||||
uart0_resources[0].start = bcm63xx_regset_address(RSET_UART0);
|
||||
uart0_resources[0].end = uart0_resources[0].start +
|
||||
RSET_UART_SIZE - 1;
|
||||
uart0_resources[1].start = bcm63xx_get_irq_number(IRQ_UART0);
|
||||
}
|
||||
|
||||
if (id == 1) {
|
||||
uart1_resources[0].start = bcm63xx_regset_address(RSET_UART1);
|
||||
uart1_resources[0].end = uart1_resources[0].start +
|
||||
RSET_UART_SIZE - 1;
|
||||
uart1_resources[1].start = bcm63xx_get_irq_number(IRQ_UART1);
|
||||
}
|
||||
|
||||
return platform_device_register(&bcm63xx_uart_devices[id]);
|
||||
}
|
||||
65
arch/mips/bcm63xx/dev-usb-usbd.c
Normal file
65
arch/mips/bcm63xx/dev-usb-usbd.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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) 2012 Kevin Cernekee <cernekee@gmail.com>
|
||||
* Copyright (C) 2012 Broadcom Corporation
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_dev_usb_usbd.h>
|
||||
|
||||
#define NUM_MMIO 2
|
||||
#define NUM_IRQ 7
|
||||
|
||||
static struct resource usbd_resources[NUM_MMIO + NUM_IRQ];
|
||||
|
||||
static u64 usbd_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct platform_device bcm63xx_usbd_device = {
|
||||
.name = "bcm63xx_udc",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(usbd_resources),
|
||||
.resource = usbd_resources,
|
||||
.dev = {
|
||||
.dma_mask = &usbd_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
};
|
||||
|
||||
int __init bcm63xx_usbd_register(const struct bcm63xx_usbd_platform_data *pd)
|
||||
{
|
||||
const int irq_list[NUM_IRQ] = { IRQ_USBD,
|
||||
IRQ_USBD_RXDMA0, IRQ_USBD_TXDMA0,
|
||||
IRQ_USBD_RXDMA1, IRQ_USBD_TXDMA1,
|
||||
IRQ_USBD_RXDMA2, IRQ_USBD_TXDMA2 };
|
||||
int i;
|
||||
|
||||
if (!BCMCPU_IS_6328() && !BCMCPU_IS_6368())
|
||||
return 0;
|
||||
|
||||
usbd_resources[0].start = bcm63xx_regset_address(RSET_USBD);
|
||||
usbd_resources[0].end = usbd_resources[0].start + RSET_USBD_SIZE - 1;
|
||||
usbd_resources[0].flags = IORESOURCE_MEM;
|
||||
|
||||
usbd_resources[1].start = bcm63xx_regset_address(RSET_USBDMA);
|
||||
usbd_resources[1].end = usbd_resources[1].start + RSET_USBDMA_SIZE - 1;
|
||||
usbd_resources[1].flags = IORESOURCE_MEM;
|
||||
|
||||
for (i = 0; i < NUM_IRQ; i++) {
|
||||
struct resource *r = &usbd_resources[NUM_MMIO + i];
|
||||
|
||||
r->start = r->end = bcm63xx_get_irq_number(irq_list[i]);
|
||||
r->flags = IORESOURCE_IRQ;
|
||||
}
|
||||
|
||||
platform_device_add_data(&bcm63xx_usbd_device, pd, sizeof(*pd));
|
||||
|
||||
return platform_device_register(&bcm63xx_usbd_device);
|
||||
}
|
||||
37
arch/mips/bcm63xx/dev-wdt.c
Normal file
37
arch/mips/bcm63xx/dev-wdt.c
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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 = -1,
|
||||
.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);
|
||||
}
|
||||
arch_initcall(bcm63xx_wdt_register);
|
||||
29
arch/mips/bcm63xx/early_printk.c
Normal file
29
arch/mips/bcm63xx/early_printk.c
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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 <bcm63xx_io.h>
|
||||
#include <linux/serial_bcm63xx.h>
|
||||
|
||||
static void 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 prom_putchar(char c)
|
||||
{
|
||||
wait_xfered();
|
||||
bcm_uart0_writel(c, UART_FIFO_REG);
|
||||
wait_xfered();
|
||||
}
|
||||
151
arch/mips/bcm63xx/gpio.c
Normal file
151
arch/mips/bcm63xx/gpio.c
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* 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-2011 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 u32 gpio_out_low_reg;
|
||||
|
||||
static void bcm63xx_gpio_out_low_reg_init(void)
|
||||
{
|
||||
switch (bcm63xx_get_cpu_id()) {
|
||||
case BCM6345_CPU_ID:
|
||||
gpio_out_low_reg = GPIO_DATA_LO_REG_6345;
|
||||
break;
|
||||
default:
|
||||
gpio_out_low_reg = GPIO_DATA_LO_REG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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_out_low_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_out_low_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 == BCM63XX_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, BCM63XX_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, BCM63XX_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_out_low_reg_init();
|
||||
|
||||
gpio_out_low = bcm_gpio_readl(gpio_out_low_reg);
|
||||
if (!BCMCPU_IS_6345())
|
||||
gpio_out_high = bcm_gpio_readl(GPIO_DATA_HI_REG);
|
||||
bcm63xx_gpio_chip.ngpio = bcm63xx_gpio_count();
|
||||
pr_info("registering %d GPIOs\n", bcm63xx_gpio_chip.ngpio);
|
||||
|
||||
return gpiochip_add(&bcm63xx_gpio_chip);
|
||||
}
|
||||
563
arch/mips/bcm63xx/irq.c
Normal file
563
arch/mips/bcm63xx/irq.c
Normal file
|
|
@ -0,0 +1,563 @@
|
|||
/*
|
||||
* 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 <linux/irq.h>
|
||||
#include <linux/spinlock.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>
|
||||
|
||||
|
||||
static DEFINE_SPINLOCK(ipic_lock);
|
||||
static DEFINE_SPINLOCK(epic_lock);
|
||||
|
||||
static u32 irq_stat_addr[2];
|
||||
static u32 irq_mask_addr[2];
|
||||
static void (*dispatch_internal)(int cpu);
|
||||
static int is_ext_irq_cascaded;
|
||||
static unsigned int ext_irq_count;
|
||||
static unsigned int ext_irq_start, ext_irq_end;
|
||||
static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2;
|
||||
static void (*internal_irq_mask)(struct irq_data *d);
|
||||
static void (*internal_irq_unmask)(struct irq_data *d, const struct cpumask *m);
|
||||
|
||||
|
||||
static inline u32 get_ext_irq_perf_reg(int irq)
|
||||
{
|
||||
if (irq < 4)
|
||||
return ext_irq_cfg_reg1;
|
||||
return ext_irq_cfg_reg2;
|
||||
}
|
||||
|
||||
static inline void handle_internal(int intbit)
|
||||
{
|
||||
if (is_ext_irq_cascaded &&
|
||||
intbit >= ext_irq_start && intbit <= ext_irq_end)
|
||||
do_IRQ(intbit - ext_irq_start + IRQ_EXTERNAL_BASE);
|
||||
else
|
||||
do_IRQ(intbit + IRQ_INTERNAL_BASE);
|
||||
}
|
||||
|
||||
static inline int enable_irq_for_cpu(int cpu, struct irq_data *d,
|
||||
const struct cpumask *m)
|
||||
{
|
||||
bool enable = cpu_online(cpu);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
if (m)
|
||||
enable &= cpu_isset(cpu, *m);
|
||||
else if (irqd_affinity_was_set(d))
|
||||
enable &= cpu_isset(cpu, *d->affinity);
|
||||
#endif
|
||||
return enable;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define BUILD_IPIC_INTERNAL(width) \
|
||||
void __dispatch_internal_##width(int cpu) \
|
||||
{ \
|
||||
u32 pending[width / 32]; \
|
||||
unsigned int src, tgt; \
|
||||
bool irqs_pending = false; \
|
||||
static unsigned int i[2]; \
|
||||
unsigned int *next = &i[cpu]; \
|
||||
unsigned long flags; \
|
||||
\
|
||||
/* read registers in reverse order */ \
|
||||
spin_lock_irqsave(&ipic_lock, flags); \
|
||||
for (src = 0, tgt = (width / 32); src < (width / 32); src++) { \
|
||||
u32 val; \
|
||||
\
|
||||
val = bcm_readl(irq_stat_addr[cpu] + src * sizeof(u32)); \
|
||||
val &= bcm_readl(irq_mask_addr[cpu] + src * sizeof(u32)); \
|
||||
pending[--tgt] = val; \
|
||||
\
|
||||
if (val) \
|
||||
irqs_pending = true; \
|
||||
} \
|
||||
spin_unlock_irqrestore(&ipic_lock, flags); \
|
||||
\
|
||||
if (!irqs_pending) \
|
||||
return; \
|
||||
\
|
||||
while (1) { \
|
||||
unsigned int to_call = *next; \
|
||||
\
|
||||
*next = (*next + 1) & (width - 1); \
|
||||
if (pending[to_call / 32] & (1 << (to_call & 0x1f))) { \
|
||||
handle_internal(to_call); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
static void __internal_irq_mask_##width(struct irq_data *d) \
|
||||
{ \
|
||||
u32 val; \
|
||||
unsigned irq = d->irq - IRQ_INTERNAL_BASE; \
|
||||
unsigned reg = (irq / 32) ^ (width/32 - 1); \
|
||||
unsigned bit = irq & 0x1f; \
|
||||
unsigned long flags; \
|
||||
int cpu; \
|
||||
\
|
||||
spin_lock_irqsave(&ipic_lock, flags); \
|
||||
for_each_present_cpu(cpu) { \
|
||||
if (!irq_mask_addr[cpu]) \
|
||||
break; \
|
||||
\
|
||||
val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
|
||||
val &= ~(1 << bit); \
|
||||
bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
|
||||
} \
|
||||
spin_unlock_irqrestore(&ipic_lock, flags); \
|
||||
} \
|
||||
\
|
||||
static void __internal_irq_unmask_##width(struct irq_data *d, \
|
||||
const struct cpumask *m) \
|
||||
{ \
|
||||
u32 val; \
|
||||
unsigned irq = d->irq - IRQ_INTERNAL_BASE; \
|
||||
unsigned reg = (irq / 32) ^ (width/32 - 1); \
|
||||
unsigned bit = irq & 0x1f; \
|
||||
unsigned long flags; \
|
||||
int cpu; \
|
||||
\
|
||||
spin_lock_irqsave(&ipic_lock, flags); \
|
||||
for_each_present_cpu(cpu) { \
|
||||
if (!irq_mask_addr[cpu]) \
|
||||
break; \
|
||||
\
|
||||
val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
|
||||
if (enable_irq_for_cpu(cpu, d, m)) \
|
||||
val |= (1 << bit); \
|
||||
else \
|
||||
val &= ~(1 << bit); \
|
||||
bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
|
||||
} \
|
||||
spin_unlock_irqrestore(&ipic_lock, flags); \
|
||||
}
|
||||
|
||||
BUILD_IPIC_INTERNAL(32);
|
||||
BUILD_IPIC_INTERNAL(64);
|
||||
|
||||
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_IP0)
|
||||
do_IRQ(0);
|
||||
if (cause & CAUSEF_IP1)
|
||||
do_IRQ(1);
|
||||
if (cause & CAUSEF_IP2)
|
||||
dispatch_internal(0);
|
||||
if (is_ext_irq_cascaded) {
|
||||
if (cause & CAUSEF_IP3)
|
||||
dispatch_internal(1);
|
||||
} else {
|
||||
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 void bcm63xx_internal_irq_mask(struct irq_data *d)
|
||||
{
|
||||
internal_irq_mask(d);
|
||||
}
|
||||
|
||||
static void bcm63xx_internal_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
internal_irq_unmask(d, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* external IRQs operations: mask/unmask and clear on PERF external
|
||||
* irq control register.
|
||||
*/
|
||||
static void bcm63xx_external_irq_mask(struct irq_data *d)
|
||||
{
|
||||
unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
|
||||
u32 reg, regaddr;
|
||||
unsigned long flags;
|
||||
|
||||
regaddr = get_ext_irq_perf_reg(irq);
|
||||
spin_lock_irqsave(&epic_lock, flags);
|
||||
reg = bcm_perf_readl(regaddr);
|
||||
|
||||
if (BCMCPU_IS_6348())
|
||||
reg &= ~EXTIRQ_CFG_MASK_6348(irq % 4);
|
||||
else
|
||||
reg &= ~EXTIRQ_CFG_MASK(irq % 4);
|
||||
|
||||
bcm_perf_writel(reg, regaddr);
|
||||
spin_unlock_irqrestore(&epic_lock, flags);
|
||||
|
||||
if (is_ext_irq_cascaded)
|
||||
internal_irq_mask(irq_get_irq_data(irq + ext_irq_start));
|
||||
}
|
||||
|
||||
static void bcm63xx_external_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
|
||||
u32 reg, regaddr;
|
||||
unsigned long flags;
|
||||
|
||||
regaddr = get_ext_irq_perf_reg(irq);
|
||||
spin_lock_irqsave(&epic_lock, flags);
|
||||
reg = bcm_perf_readl(regaddr);
|
||||
|
||||
if (BCMCPU_IS_6348())
|
||||
reg |= EXTIRQ_CFG_MASK_6348(irq % 4);
|
||||
else
|
||||
reg |= EXTIRQ_CFG_MASK(irq % 4);
|
||||
|
||||
bcm_perf_writel(reg, regaddr);
|
||||
spin_unlock_irqrestore(&epic_lock, flags);
|
||||
|
||||
if (is_ext_irq_cascaded)
|
||||
internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void bcm63xx_external_irq_clear(struct irq_data *d)
|
||||
{
|
||||
unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
|
||||
u32 reg, regaddr;
|
||||
unsigned long flags;
|
||||
|
||||
regaddr = get_ext_irq_perf_reg(irq);
|
||||
spin_lock_irqsave(&epic_lock, flags);
|
||||
reg = bcm_perf_readl(regaddr);
|
||||
|
||||
if (BCMCPU_IS_6348())
|
||||
reg |= EXTIRQ_CFG_CLEAR_6348(irq % 4);
|
||||
else
|
||||
reg |= EXTIRQ_CFG_CLEAR(irq % 4);
|
||||
|
||||
bcm_perf_writel(reg, regaddr);
|
||||
spin_unlock_irqrestore(&epic_lock, flags);
|
||||
}
|
||||
|
||||
static int bcm63xx_external_irq_set_type(struct irq_data *d,
|
||||
unsigned int flow_type)
|
||||
{
|
||||
unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
|
||||
u32 reg, regaddr;
|
||||
int levelsense, sense, bothedge;
|
||||
unsigned long flags;
|
||||
|
||||
flow_type &= IRQ_TYPE_SENSE_MASK;
|
||||
|
||||
if (flow_type == IRQ_TYPE_NONE)
|
||||
flow_type = IRQ_TYPE_LEVEL_LOW;
|
||||
|
||||
levelsense = sense = bothedge = 0;
|
||||
switch (flow_type) {
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
bothedge = 1;
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
sense = 1;
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
levelsense = 1;
|
||||
sense = 1;
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
levelsense = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "bogus flow type combination given !\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regaddr = get_ext_irq_perf_reg(irq);
|
||||
spin_lock_irqsave(&epic_lock, flags);
|
||||
reg = bcm_perf_readl(regaddr);
|
||||
irq %= 4;
|
||||
|
||||
switch (bcm63xx_get_cpu_id()) {
|
||||
case BCM6348_CPU_ID:
|
||||
if (levelsense)
|
||||
reg |= EXTIRQ_CFG_LEVELSENSE_6348(irq);
|
||||
else
|
||||
reg &= ~EXTIRQ_CFG_LEVELSENSE_6348(irq);
|
||||
if (sense)
|
||||
reg |= EXTIRQ_CFG_SENSE_6348(irq);
|
||||
else
|
||||
reg &= ~EXTIRQ_CFG_SENSE_6348(irq);
|
||||
if (bothedge)
|
||||
reg |= EXTIRQ_CFG_BOTHEDGE_6348(irq);
|
||||
else
|
||||
reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq);
|
||||
break;
|
||||
|
||||
case BCM3368_CPU_ID:
|
||||
case BCM6328_CPU_ID:
|
||||
case BCM6338_CPU_ID:
|
||||
case BCM6345_CPU_ID:
|
||||
case BCM6358_CPU_ID:
|
||||
case BCM6362_CPU_ID:
|
||||
case BCM6368_CPU_ID:
|
||||
if (levelsense)
|
||||
reg |= EXTIRQ_CFG_LEVELSENSE(irq);
|
||||
else
|
||||
reg &= ~EXTIRQ_CFG_LEVELSENSE(irq);
|
||||
if (sense)
|
||||
reg |= EXTIRQ_CFG_SENSE(irq);
|
||||
else
|
||||
reg &= ~EXTIRQ_CFG_SENSE(irq);
|
||||
if (bothedge)
|
||||
reg |= EXTIRQ_CFG_BOTHEDGE(irq);
|
||||
else
|
||||
reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
bcm_perf_writel(reg, regaddr);
|
||||
spin_unlock_irqrestore(&epic_lock, flags);
|
||||
|
||||
irqd_set_trigger_type(d, flow_type);
|
||||
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
__irq_set_handler_locked(d->irq, handle_level_irq);
|
||||
else
|
||||
__irq_set_handler_locked(d->irq, handle_edge_irq);
|
||||
|
||||
return IRQ_SET_MASK_OK_NOCOPY;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static int bcm63xx_internal_set_affinity(struct irq_data *data,
|
||||
const struct cpumask *dest,
|
||||
bool force)
|
||||
{
|
||||
if (!irqd_irq_disabled(data))
|
||||
internal_irq_unmask(data, dest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct irq_chip bcm63xx_internal_irq_chip = {
|
||||
.name = "bcm63xx_ipic",
|
||||
.irq_mask = bcm63xx_internal_irq_mask,
|
||||
.irq_unmask = bcm63xx_internal_irq_unmask,
|
||||
};
|
||||
|
||||
static struct irq_chip bcm63xx_external_irq_chip = {
|
||||
.name = "bcm63xx_epic",
|
||||
.irq_ack = bcm63xx_external_irq_clear,
|
||||
|
||||
.irq_mask = bcm63xx_external_irq_mask,
|
||||
.irq_unmask = bcm63xx_external_irq_unmask,
|
||||
|
||||
.irq_set_type = bcm63xx_external_irq_set_type,
|
||||
};
|
||||
|
||||
static struct irqaction cpu_ip2_cascade_action = {
|
||||
.handler = no_action,
|
||||
.name = "cascade_ip2",
|
||||
.flags = IRQF_NO_THREAD,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static struct irqaction cpu_ip3_cascade_action = {
|
||||
.handler = no_action,
|
||||
.name = "cascade_ip3",
|
||||
.flags = IRQF_NO_THREAD,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct irqaction cpu_ext_cascade_action = {
|
||||
.handler = no_action,
|
||||
.name = "cascade_extirq",
|
||||
.flags = IRQF_NO_THREAD,
|
||||
};
|
||||
|
||||
static void bcm63xx_init_irq(void)
|
||||
{
|
||||
int irq_bits;
|
||||
|
||||
irq_stat_addr[0] = bcm63xx_regset_address(RSET_PERF);
|
||||
irq_mask_addr[0] = bcm63xx_regset_address(RSET_PERF);
|
||||
irq_stat_addr[1] = bcm63xx_regset_address(RSET_PERF);
|
||||
irq_mask_addr[1] = bcm63xx_regset_address(RSET_PERF);
|
||||
|
||||
switch (bcm63xx_get_cpu_id()) {
|
||||
case BCM3368_CPU_ID:
|
||||
irq_stat_addr[0] += PERF_IRQSTAT_3368_REG;
|
||||
irq_mask_addr[0] += PERF_IRQMASK_3368_REG;
|
||||
irq_stat_addr[1] = 0;
|
||||
irq_mask_addr[1] = 0;
|
||||
irq_bits = 32;
|
||||
ext_irq_count = 4;
|
||||
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
|
||||
break;
|
||||
case BCM6328_CPU_ID:
|
||||
irq_stat_addr[0] += PERF_IRQSTAT_6328_REG(0);
|
||||
irq_mask_addr[0] += PERF_IRQMASK_6328_REG(0);
|
||||
irq_stat_addr[1] += PERF_IRQSTAT_6328_REG(1);
|
||||
irq_mask_addr[1] += PERF_IRQMASK_6328_REG(1);
|
||||
irq_bits = 64;
|
||||
ext_irq_count = 4;
|
||||
is_ext_irq_cascaded = 1;
|
||||
ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
|
||||
ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
|
||||
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
|
||||
break;
|
||||
case BCM6338_CPU_ID:
|
||||
irq_stat_addr[0] += PERF_IRQSTAT_6338_REG;
|
||||
irq_mask_addr[0] += PERF_IRQMASK_6338_REG;
|
||||
irq_stat_addr[1] = 0;
|
||||
irq_mask_addr[1] = 0;
|
||||
irq_bits = 32;
|
||||
ext_irq_count = 4;
|
||||
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
|
||||
break;
|
||||
case BCM6345_CPU_ID:
|
||||
irq_stat_addr[0] += PERF_IRQSTAT_6345_REG;
|
||||
irq_mask_addr[0] += PERF_IRQMASK_6345_REG;
|
||||
irq_stat_addr[1] = 0;
|
||||
irq_mask_addr[1] = 0;
|
||||
irq_bits = 32;
|
||||
ext_irq_count = 4;
|
||||
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
|
||||
break;
|
||||
case BCM6348_CPU_ID:
|
||||
irq_stat_addr[0] += PERF_IRQSTAT_6348_REG;
|
||||
irq_mask_addr[0] += PERF_IRQMASK_6348_REG;
|
||||
irq_stat_addr[1] = 0;
|
||||
irq_mask_addr[1] = 0;
|
||||
irq_bits = 32;
|
||||
ext_irq_count = 4;
|
||||
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
|
||||
break;
|
||||
case BCM6358_CPU_ID:
|
||||
irq_stat_addr[0] += PERF_IRQSTAT_6358_REG(0);
|
||||
irq_mask_addr[0] += PERF_IRQMASK_6358_REG(0);
|
||||
irq_stat_addr[1] += PERF_IRQSTAT_6358_REG(1);
|
||||
irq_mask_addr[1] += PERF_IRQMASK_6358_REG(1);
|
||||
irq_bits = 32;
|
||||
ext_irq_count = 4;
|
||||
is_ext_irq_cascaded = 1;
|
||||
ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
|
||||
ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
|
||||
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
|
||||
break;
|
||||
case BCM6362_CPU_ID:
|
||||
irq_stat_addr[0] += PERF_IRQSTAT_6362_REG(0);
|
||||
irq_mask_addr[0] += PERF_IRQMASK_6362_REG(0);
|
||||
irq_stat_addr[1] += PERF_IRQSTAT_6362_REG(1);
|
||||
irq_mask_addr[1] += PERF_IRQMASK_6362_REG(1);
|
||||
irq_bits = 64;
|
||||
ext_irq_count = 4;
|
||||
is_ext_irq_cascaded = 1;
|
||||
ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE;
|
||||
ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE;
|
||||
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
|
||||
break;
|
||||
case BCM6368_CPU_ID:
|
||||
irq_stat_addr[0] += PERF_IRQSTAT_6368_REG(0);
|
||||
irq_mask_addr[0] += PERF_IRQMASK_6368_REG(0);
|
||||
irq_stat_addr[1] += PERF_IRQSTAT_6368_REG(1);
|
||||
irq_mask_addr[1] += PERF_IRQMASK_6368_REG(1);
|
||||
irq_bits = 64;
|
||||
ext_irq_count = 6;
|
||||
is_ext_irq_cascaded = 1;
|
||||
ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE;
|
||||
ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE;
|
||||
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368;
|
||||
ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (irq_bits == 32) {
|
||||
dispatch_internal = __dispatch_internal_32;
|
||||
internal_irq_mask = __internal_irq_mask_32;
|
||||
internal_irq_unmask = __internal_irq_unmask_32;
|
||||
} else {
|
||||
dispatch_internal = __dispatch_internal_64;
|
||||
internal_irq_mask = __internal_irq_mask_64;
|
||||
internal_irq_unmask = __internal_irq_unmask_64;
|
||||
}
|
||||
}
|
||||
|
||||
void __init arch_init_irq(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
bcm63xx_init_irq();
|
||||
mips_cpu_irq_init();
|
||||
for (i = IRQ_INTERNAL_BASE; i < NR_IRQS; ++i)
|
||||
irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip,
|
||||
handle_level_irq);
|
||||
|
||||
for (i = IRQ_EXTERNAL_BASE; i < IRQ_EXTERNAL_BASE + ext_irq_count; ++i)
|
||||
irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip,
|
||||
handle_edge_irq);
|
||||
|
||||
if (!is_ext_irq_cascaded) {
|
||||
for (i = 3; i < 3 + ext_irq_count; ++i)
|
||||
setup_irq(MIPS_CPU_IRQ_BASE + i, &cpu_ext_cascade_action);
|
||||
}
|
||||
|
||||
setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action);
|
||||
#ifdef CONFIG_SMP
|
||||
if (is_ext_irq_cascaded) {
|
||||
setup_irq(MIPS_CPU_IRQ_BASE + 3, &cpu_ip3_cascade_action);
|
||||
bcm63xx_internal_irq_chip.irq_set_affinity =
|
||||
bcm63xx_internal_set_affinity;
|
||||
|
||||
cpumask_clear(irq_default_affinity);
|
||||
cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
127
arch/mips/bcm63xx/nvram.c
Normal file
127
arch/mips/bcm63xx/nvram.c
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* 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>
|
||||
* Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "bcm63xx_nvram: " fmt
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#include <bcm63xx_nvram.h>
|
||||
|
||||
/*
|
||||
* nvram structure
|
||||
*/
|
||||
struct bcm963xx_nvram {
|
||||
u32 version;
|
||||
u8 reserved1[256];
|
||||
u8 name[16];
|
||||
u32 main_tp_number;
|
||||
u32 psi_size;
|
||||
u32 mac_addr_count;
|
||||
u8 mac_addr_base[ETH_ALEN];
|
||||
u8 reserved2[2];
|
||||
u32 checksum_old;
|
||||
u8 reserved3[720];
|
||||
u32 checksum_high;
|
||||
};
|
||||
|
||||
#define BCM63XX_DEFAULT_PSI_SIZE 64
|
||||
|
||||
static struct bcm963xx_nvram nvram;
|
||||
static int mac_addr_used;
|
||||
|
||||
void __init bcm63xx_nvram_init(void *addr)
|
||||
{
|
||||
unsigned int check_len;
|
||||
u32 crc, expected_crc;
|
||||
u8 hcs_mac_addr[ETH_ALEN] = { 0x00, 0x10, 0x18, 0xff, 0xff, 0xff };
|
||||
|
||||
/* extract nvram data */
|
||||
memcpy(&nvram, addr, sizeof(nvram));
|
||||
|
||||
/* check checksum before using data */
|
||||
if (nvram.version <= 4) {
|
||||
check_len = offsetof(struct bcm963xx_nvram, reserved3);
|
||||
expected_crc = nvram.checksum_old;
|
||||
nvram.checksum_old = 0;
|
||||
} else {
|
||||
check_len = sizeof(nvram);
|
||||
expected_crc = nvram.checksum_high;
|
||||
nvram.checksum_high = 0;
|
||||
}
|
||||
|
||||
crc = crc32_le(~0, (u8 *)&nvram, check_len);
|
||||
|
||||
if (crc != expected_crc)
|
||||
pr_warn("nvram checksum failed, contents may be invalid (expected %08x, got %08x)\n",
|
||||
expected_crc, crc);
|
||||
|
||||
/* Cable modems have a different NVRAM which is embedded in the eCos
|
||||
* firmware and not easily extractible, give at least a MAC address
|
||||
* pool.
|
||||
*/
|
||||
if (BCMCPU_IS_3368()) {
|
||||
memcpy(nvram.mac_addr_base, hcs_mac_addr, ETH_ALEN);
|
||||
nvram.mac_addr_count = 2;
|
||||
}
|
||||
}
|
||||
|
||||
u8 *bcm63xx_nvram_get_name(void)
|
||||
{
|
||||
return nvram.name;
|
||||
}
|
||||
EXPORT_SYMBOL(bcm63xx_nvram_get_name);
|
||||
|
||||
int bcm63xx_nvram_get_mac_address(u8 *mac)
|
||||
{
|
||||
u8 *oui;
|
||||
int count;
|
||||
|
||||
if (mac_addr_used >= nvram.mac_addr_count) {
|
||||
pr_err("not enough mac addresses\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
|
||||
oui = mac + ETH_ALEN/2 - 1;
|
||||
count = mac_addr_used;
|
||||
|
||||
while (count--) {
|
||||
u8 *p = mac + ETH_ALEN - 1;
|
||||
|
||||
do {
|
||||
(*p)++;
|
||||
if (*p != 0)
|
||||
break;
|
||||
p--;
|
||||
} while (p != oui);
|
||||
|
||||
if (p == oui) {
|
||||
pr_err("unable to fetch mac address\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
mac_addr_used++;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
|
||||
|
||||
int bcm63xx_nvram_get_psi_size(void)
|
||||
{
|
||||
if (nvram.psi_size > 0)
|
||||
return nvram.psi_size;
|
||||
|
||||
return BCM63XX_DEFAULT_PSI_SIZE;
|
||||
}
|
||||
EXPORT_SYMBOL(bcm63xx_nvram_get_psi_size);
|
||||
100
arch/mips/bcm63xx/prom.c
Normal file
100
arch/mips/bcm63xx/prom.c
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* 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 <linux/smp.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/bmips.h>
|
||||
#include <asm/smp-ops.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <bcm63xx_board.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_regs.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_3368())
|
||||
mask = CKCTL_3368_ALL_SAFE_EN;
|
||||
else if (BCMCPU_IS_6328())
|
||||
mask = CKCTL_6328_ALL_SAFE_EN;
|
||||
else 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 if (BCMCPU_IS_6358())
|
||||
mask = CKCTL_6358_ALL_SAFE_EN;
|
||||
else if (BCMCPU_IS_6362())
|
||||
mask = CKCTL_6362_ALL_SAFE_EN;
|
||||
else if (BCMCPU_IS_6368())
|
||||
mask = CKCTL_6368_ALL_SAFE_EN;
|
||||
else
|
||||
mask = 0;
|
||||
|
||||
reg = bcm_perf_readl(PERF_CKCTL_REG);
|
||||
reg &= ~mask;
|
||||
bcm_perf_writel(reg, PERF_CKCTL_REG);
|
||||
|
||||
/* do low level board init */
|
||||
board_prom_init();
|
||||
|
||||
/* set up SMP */
|
||||
if (!register_bmips_smp_ops()) {
|
||||
/*
|
||||
* BCM6328 might not have its second CPU enabled, while BCM3368
|
||||
* and BCM6358 need special handling for their shared TLB, so
|
||||
* disable SMP for now.
|
||||
*/
|
||||
if (BCMCPU_IS_6328()) {
|
||||
reg = bcm_readl(BCM_6328_OTP_BASE +
|
||||
OTP_USER_BITS_6328_REG(3));
|
||||
|
||||
if (reg & OTP_6328_REG3_TP1_DISABLED)
|
||||
bmips_smp_enabled = 0;
|
||||
} else if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) {
|
||||
bmips_smp_enabled = 0;
|
||||
}
|
||||
|
||||
if (!bmips_smp_enabled)
|
||||
return;
|
||||
|
||||
/*
|
||||
* The bootloader has set up the CPU1 reset vector at
|
||||
* 0xa000_0200.
|
||||
* This conflicts with the special interrupt vector (IV).
|
||||
* The bootloader has also set up CPU1 to respond to the wrong
|
||||
* IPI interrupt.
|
||||
* Here we will start up CPU1 in the background and ask it to
|
||||
* reconfigure itself then go back to sleep.
|
||||
*/
|
||||
memcpy((void *)0xa0000200, &bmips_smp_movevec, 0x20);
|
||||
__sync();
|
||||
set_c0_cause(C_SW0);
|
||||
cpumask_set_cpu(1, &bmips_booted_mask);
|
||||
|
||||
/*
|
||||
* FIXME: we really should have some sort of hazard barrier here
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
void __init prom_free_prom_memory(void)
|
||||
{
|
||||
}
|
||||
218
arch/mips/bcm63xx/reset.c
Normal file
218
arch/mips/bcm63xx/reset.c
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* 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) 2012 Jonas Gorski <jonas.gorski@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
#include <bcm63xx_reset.h>
|
||||
|
||||
#define __GEN_RESET_BITS_TABLE(__cpu) \
|
||||
[BCM63XX_RESET_SPI] = BCM## __cpu ##_RESET_SPI, \
|
||||
[BCM63XX_RESET_ENET] = BCM## __cpu ##_RESET_ENET, \
|
||||
[BCM63XX_RESET_USBH] = BCM## __cpu ##_RESET_USBH, \
|
||||
[BCM63XX_RESET_USBD] = BCM## __cpu ##_RESET_USBD, \
|
||||
[BCM63XX_RESET_DSL] = BCM## __cpu ##_RESET_DSL, \
|
||||
[BCM63XX_RESET_SAR] = BCM## __cpu ##_RESET_SAR, \
|
||||
[BCM63XX_RESET_EPHY] = BCM## __cpu ##_RESET_EPHY, \
|
||||
[BCM63XX_RESET_ENETSW] = BCM## __cpu ##_RESET_ENETSW, \
|
||||
[BCM63XX_RESET_PCM] = BCM## __cpu ##_RESET_PCM, \
|
||||
[BCM63XX_RESET_MPI] = BCM## __cpu ##_RESET_MPI, \
|
||||
[BCM63XX_RESET_PCIE] = BCM## __cpu ##_RESET_PCIE, \
|
||||
[BCM63XX_RESET_PCIE_EXT] = BCM## __cpu ##_RESET_PCIE_EXT,
|
||||
|
||||
#define BCM3368_RESET_SPI SOFTRESET_3368_SPI_MASK
|
||||
#define BCM3368_RESET_ENET SOFTRESET_3368_ENET_MASK
|
||||
#define BCM3368_RESET_USBH 0
|
||||
#define BCM3368_RESET_USBD SOFTRESET_3368_USBS_MASK
|
||||
#define BCM3368_RESET_DSL 0
|
||||
#define BCM3368_RESET_SAR 0
|
||||
#define BCM3368_RESET_EPHY SOFTRESET_3368_EPHY_MASK
|
||||
#define BCM3368_RESET_ENETSW 0
|
||||
#define BCM3368_RESET_PCM SOFTRESET_3368_PCM_MASK
|
||||
#define BCM3368_RESET_MPI SOFTRESET_3368_MPI_MASK
|
||||
#define BCM3368_RESET_PCIE 0
|
||||
#define BCM3368_RESET_PCIE_EXT 0
|
||||
|
||||
#define BCM6328_RESET_SPI SOFTRESET_6328_SPI_MASK
|
||||
#define BCM6328_RESET_ENET 0
|
||||
#define BCM6328_RESET_USBH SOFTRESET_6328_USBH_MASK
|
||||
#define BCM6328_RESET_USBD SOFTRESET_6328_USBS_MASK
|
||||
#define BCM6328_RESET_DSL 0
|
||||
#define BCM6328_RESET_SAR SOFTRESET_6328_SAR_MASK
|
||||
#define BCM6328_RESET_EPHY SOFTRESET_6328_EPHY_MASK
|
||||
#define BCM6328_RESET_ENETSW SOFTRESET_6328_ENETSW_MASK
|
||||
#define BCM6328_RESET_PCM SOFTRESET_6328_PCM_MASK
|
||||
#define BCM6328_RESET_MPI 0
|
||||
#define BCM6328_RESET_PCIE \
|
||||
(SOFTRESET_6328_PCIE_MASK | \
|
||||
SOFTRESET_6328_PCIE_CORE_MASK | \
|
||||
SOFTRESET_6328_PCIE_HARD_MASK)
|
||||
#define BCM6328_RESET_PCIE_EXT SOFTRESET_6328_PCIE_EXT_MASK
|
||||
|
||||
#define BCM6338_RESET_SPI SOFTRESET_6338_SPI_MASK
|
||||
#define BCM6338_RESET_ENET SOFTRESET_6338_ENET_MASK
|
||||
#define BCM6338_RESET_USBH SOFTRESET_6338_USBH_MASK
|
||||
#define BCM6338_RESET_USBD SOFTRESET_6338_USBS_MASK
|
||||
#define BCM6338_RESET_DSL SOFTRESET_6338_ADSL_MASK
|
||||
#define BCM6338_RESET_SAR SOFTRESET_6338_SAR_MASK
|
||||
#define BCM6338_RESET_EPHY 0
|
||||
#define BCM6338_RESET_ENETSW 0
|
||||
#define BCM6338_RESET_PCM 0
|
||||
#define BCM6338_RESET_MPI 0
|
||||
#define BCM6338_RESET_PCIE 0
|
||||
#define BCM6338_RESET_PCIE_EXT 0
|
||||
|
||||
#define BCM6348_RESET_SPI SOFTRESET_6348_SPI_MASK
|
||||
#define BCM6348_RESET_ENET SOFTRESET_6348_ENET_MASK
|
||||
#define BCM6348_RESET_USBH SOFTRESET_6348_USBH_MASK
|
||||
#define BCM6348_RESET_USBD SOFTRESET_6348_USBS_MASK
|
||||
#define BCM6348_RESET_DSL SOFTRESET_6348_ADSL_MASK
|
||||
#define BCM6348_RESET_SAR SOFTRESET_6348_SAR_MASK
|
||||
#define BCM6348_RESET_EPHY 0
|
||||
#define BCM6348_RESET_ENETSW 0
|
||||
#define BCM6348_RESET_PCM 0
|
||||
#define BCM6348_RESET_MPI 0
|
||||
#define BCM6348_RESET_PCIE 0
|
||||
#define BCM6348_RESET_PCIE_EXT 0
|
||||
|
||||
#define BCM6358_RESET_SPI SOFTRESET_6358_SPI_MASK
|
||||
#define BCM6358_RESET_ENET SOFTRESET_6358_ENET_MASK
|
||||
#define BCM6358_RESET_USBH SOFTRESET_6358_USBH_MASK
|
||||
#define BCM6358_RESET_USBD 0
|
||||
#define BCM6358_RESET_DSL SOFTRESET_6358_ADSL_MASK
|
||||
#define BCM6358_RESET_SAR SOFTRESET_6358_SAR_MASK
|
||||
#define BCM6358_RESET_EPHY SOFTRESET_6358_EPHY_MASK
|
||||
#define BCM6358_RESET_ENETSW 0
|
||||
#define BCM6358_RESET_PCM SOFTRESET_6358_PCM_MASK
|
||||
#define BCM6358_RESET_MPI SOFTRESET_6358_MPI_MASK
|
||||
#define BCM6358_RESET_PCIE 0
|
||||
#define BCM6358_RESET_PCIE_EXT 0
|
||||
|
||||
#define BCM6362_RESET_SPI SOFTRESET_6362_SPI_MASK
|
||||
#define BCM6362_RESET_ENET 0
|
||||
#define BCM6362_RESET_USBH SOFTRESET_6362_USBH_MASK
|
||||
#define BCM6362_RESET_USBD SOFTRESET_6362_USBS_MASK
|
||||
#define BCM6362_RESET_DSL 0
|
||||
#define BCM6362_RESET_SAR SOFTRESET_6362_SAR_MASK
|
||||
#define BCM6362_RESET_EPHY SOFTRESET_6362_EPHY_MASK
|
||||
#define BCM6362_RESET_ENETSW SOFTRESET_6362_ENETSW_MASK
|
||||
#define BCM6362_RESET_PCM SOFTRESET_6362_PCM_MASK
|
||||
#define BCM6362_RESET_MPI 0
|
||||
#define BCM6362_RESET_PCIE (SOFTRESET_6362_PCIE_MASK | \
|
||||
SOFTRESET_6362_PCIE_CORE_MASK)
|
||||
#define BCM6362_RESET_PCIE_EXT SOFTRESET_6362_PCIE_EXT_MASK
|
||||
|
||||
#define BCM6368_RESET_SPI SOFTRESET_6368_SPI_MASK
|
||||
#define BCM6368_RESET_ENET 0
|
||||
#define BCM6368_RESET_USBH SOFTRESET_6368_USBH_MASK
|
||||
#define BCM6368_RESET_USBD SOFTRESET_6368_USBS_MASK
|
||||
#define BCM6368_RESET_DSL 0
|
||||
#define BCM6368_RESET_SAR SOFTRESET_6368_SAR_MASK
|
||||
#define BCM6368_RESET_EPHY SOFTRESET_6368_EPHY_MASK
|
||||
#define BCM6368_RESET_ENETSW 0
|
||||
#define BCM6368_RESET_PCM SOFTRESET_6368_PCM_MASK
|
||||
#define BCM6368_RESET_MPI SOFTRESET_6368_MPI_MASK
|
||||
#define BCM6368_RESET_PCIE 0
|
||||
#define BCM6368_RESET_PCIE_EXT 0
|
||||
|
||||
/*
|
||||
* core reset bits
|
||||
*/
|
||||
static const u32 bcm3368_reset_bits[] = {
|
||||
__GEN_RESET_BITS_TABLE(3368)
|
||||
};
|
||||
|
||||
static const u32 bcm6328_reset_bits[] = {
|
||||
__GEN_RESET_BITS_TABLE(6328)
|
||||
};
|
||||
|
||||
static const u32 bcm6338_reset_bits[] = {
|
||||
__GEN_RESET_BITS_TABLE(6338)
|
||||
};
|
||||
|
||||
static const u32 bcm6348_reset_bits[] = {
|
||||
__GEN_RESET_BITS_TABLE(6348)
|
||||
};
|
||||
|
||||
static const u32 bcm6358_reset_bits[] = {
|
||||
__GEN_RESET_BITS_TABLE(6358)
|
||||
};
|
||||
|
||||
static const u32 bcm6362_reset_bits[] = {
|
||||
__GEN_RESET_BITS_TABLE(6362)
|
||||
};
|
||||
|
||||
static const u32 bcm6368_reset_bits[] = {
|
||||
__GEN_RESET_BITS_TABLE(6368)
|
||||
};
|
||||
|
||||
const u32 *bcm63xx_reset_bits;
|
||||
static int reset_reg;
|
||||
|
||||
static int __init bcm63xx_reset_bits_init(void)
|
||||
{
|
||||
if (BCMCPU_IS_3368()) {
|
||||
reset_reg = PERF_SOFTRESET_6358_REG;
|
||||
bcm63xx_reset_bits = bcm3368_reset_bits;
|
||||
} else if (BCMCPU_IS_6328()) {
|
||||
reset_reg = PERF_SOFTRESET_6328_REG;
|
||||
bcm63xx_reset_bits = bcm6328_reset_bits;
|
||||
} else if (BCMCPU_IS_6338()) {
|
||||
reset_reg = PERF_SOFTRESET_REG;
|
||||
bcm63xx_reset_bits = bcm6338_reset_bits;
|
||||
} else if (BCMCPU_IS_6348()) {
|
||||
reset_reg = PERF_SOFTRESET_REG;
|
||||
bcm63xx_reset_bits = bcm6348_reset_bits;
|
||||
} else if (BCMCPU_IS_6358()) {
|
||||
reset_reg = PERF_SOFTRESET_6358_REG;
|
||||
bcm63xx_reset_bits = bcm6358_reset_bits;
|
||||
} else if (BCMCPU_IS_6362()) {
|
||||
reset_reg = PERF_SOFTRESET_6362_REG;
|
||||
bcm63xx_reset_bits = bcm6362_reset_bits;
|
||||
} else if (BCMCPU_IS_6368()) {
|
||||
reset_reg = PERF_SOFTRESET_6368_REG;
|
||||
bcm63xx_reset_bits = bcm6368_reset_bits;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(reset_mutex);
|
||||
|
||||
static void __bcm63xx_core_set_reset(u32 mask, int enable)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
if (!mask)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&reset_mutex, flags);
|
||||
val = bcm_perf_readl(reset_reg);
|
||||
|
||||
if (enable)
|
||||
val &= ~mask;
|
||||
else
|
||||
val |= mask;
|
||||
|
||||
bcm_perf_writel(val, reset_reg);
|
||||
spin_unlock_irqrestore(&reset_mutex, flags);
|
||||
}
|
||||
|
||||
void bcm63xx_core_set_reset(enum bcm63xx_core_reset core, int reset)
|
||||
{
|
||||
__bcm63xx_core_set_reset(bcm63xx_reset_bits[core], reset);
|
||||
}
|
||||
EXPORT_SYMBOL(bcm63xx_core_set_reset);
|
||||
|
||||
postcore_initcall(bcm63xx_reset_bits_init);
|
||||
170
arch/mips/bcm63xx/setup.c
Normal file
170
arch/mips/bcm63xx/setup.c
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* 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>
|
||||
#include <bcm63xx_gpio.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-resetting 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, perf_regs[2] = { 0, 0 };
|
||||
unsigned int i;
|
||||
|
||||
/* mask and clear all external irq */
|
||||
switch (bcm63xx_get_cpu_id()) {
|
||||
case BCM3368_CPU_ID:
|
||||
perf_regs[0] = PERF_EXTIRQ_CFG_REG_3368;
|
||||
break;
|
||||
case BCM6328_CPU_ID:
|
||||
perf_regs[0] = PERF_EXTIRQ_CFG_REG_6328;
|
||||
break;
|
||||
case BCM6338_CPU_ID:
|
||||
perf_regs[0] = PERF_EXTIRQ_CFG_REG_6338;
|
||||
break;
|
||||
case BCM6345_CPU_ID:
|
||||
perf_regs[0] = PERF_EXTIRQ_CFG_REG_6345;
|
||||
break;
|
||||
case BCM6348_CPU_ID:
|
||||
perf_regs[0] = PERF_EXTIRQ_CFG_REG_6348;
|
||||
break;
|
||||
case BCM6358_CPU_ID:
|
||||
perf_regs[0] = PERF_EXTIRQ_CFG_REG_6358;
|
||||
break;
|
||||
case BCM6362_CPU_ID:
|
||||
perf_regs[0] = PERF_EXTIRQ_CFG_REG_6362;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (!perf_regs[i])
|
||||
break;
|
||||
|
||||
reg = bcm_perf_readl(perf_regs[i]);
|
||||
if (BCMCPU_IS_6348()) {
|
||||
reg &= ~EXTIRQ_CFG_MASK_ALL_6348;
|
||||
reg |= EXTIRQ_CFG_CLEAR_ALL_6348;
|
||||
} else {
|
||||
reg &= ~EXTIRQ_CFG_MASK_ALL;
|
||||
reg |= EXTIRQ_CFG_CLEAR_ALL;
|
||||
}
|
||||
bcm_perf_writel(reg, perf_regs[i]);
|
||||
}
|
||||
|
||||
if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() == 0xa1))
|
||||
bcm6348_a1_reboot();
|
||||
|
||||
printk(KERN_INFO "triggering watchdog soft-reset...\n");
|
||||
if (BCMCPU_IS_6328()) {
|
||||
bcm_wdt_writel(1, WDT_SOFTRESET_REG);
|
||||
} else {
|
||||
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%02X)",
|
||||
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)
|
||||
{
|
||||
/* register gpiochip */
|
||||
bcm63xx_gpio_init();
|
||||
|
||||
return board_register_devices();
|
||||
}
|
||||
|
||||
arch_initcall(bcm63xx_register_devices);
|
||||
205
arch/mips/bcm63xx/timer.c
Normal file
205
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_RAW_SPINLOCK(timer_reg_lock);
|
||||
static DEFINE_RAW_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;
|
||||
|
||||
raw_spin_lock(&timer_reg_lock);
|
||||
stat = bcm_timer_readl(TIMER_IRQSTAT_REG);
|
||||
bcm_timer_writel(stat, TIMER_IRQSTAT_REG);
|
||||
raw_spin_unlock(&timer_reg_lock);
|
||||
|
||||
for (i = 0; i < BCM63XX_TIMER_COUNT; i++) {
|
||||
if (!(stat & TIMER_IRQSTAT_TIMER_CAUSE(i)))
|
||||
continue;
|
||||
|
||||
raw_spin_lock(&timer_data_lock);
|
||||
if (!timer_data[i].cb) {
|
||||
raw_spin_unlock(&timer_data_lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
timer_data[i].cb(timer_data[i].data);
|
||||
raw_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;
|
||||
|
||||
raw_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);
|
||||
|
||||
raw_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;
|
||||
|
||||
raw_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);
|
||||
|
||||
raw_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;
|
||||
raw_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:
|
||||
raw_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;
|
||||
|
||||
raw_spin_lock_irqsave(&timer_data_lock, flags);
|
||||
timer_data[id].cb = NULL;
|
||||
raw_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;
|
||||
|
||||
raw_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));
|
||||
|
||||
raw_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);
|
||||
Loading…
Add table
Add a link
Reference in a new issue