summaryrefslogtreecommitdiffstats
path: root/arch/mips/bcm63xx
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/bcm63xx')
-rw-r--r--arch/mips/bcm63xx/Makefile2
-rw-r--r--arch/mips/bcm63xx/boards/board_bcm963xx.c26
-rw-r--r--arch/mips/bcm63xx/clk.c21
-rw-r--r--arch/mips/bcm63xx/dev-usb-usbd.c65
-rw-r--r--arch/mips/bcm63xx/irq.c22
-rw-r--r--arch/mips/bcm63xx/setup.c6
6 files changed, 128 insertions, 14 deletions
diff --git a/arch/mips/bcm63xx/Makefile b/arch/mips/bcm63xx/Makefile
index 833af72c852a..9bbb30a9dc20 100644
--- a/arch/mips/bcm63xx/Makefile
+++ b/arch/mips/bcm63xx/Makefile
@@ -1,6 +1,6 @@
obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
dev-dsp.o dev-enet.o dev-flash.o dev-pcmcia.o dev-rng.o \
- dev-spi.o dev-uart.o dev-wdt.o
+ dev-spi.o dev-uart.o dev-wdt.o dev-usb-usbd.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c
index dd18e4b761a8..1cd4d73f23c7 100644
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -24,6 +24,7 @@
#include <bcm63xx_dev_flash.h>
#include <bcm63xx_dev_pcmcia.h>
#include <bcm63xx_dev_spi.h>
+#include <bcm63xx_dev_usb_usbd.h>
#include <board_bcm963xx.h>
#define PFX "board_bcm963xx: "
@@ -42,6 +43,12 @@ static struct board_info __initdata board_96328avng = {
.has_uart0 = 1,
.has_pci = 1,
+ .has_usbd = 0,
+
+ .usbd = {
+ .use_fullspeed = 0,
+ .port_no = 0,
+ },
.leds = {
{
@@ -713,7 +720,7 @@ const char *board_get_name(void)
*/
static int board_get_mac_address(u8 *mac)
{
- u8 *p;
+ u8 *oui;
int count;
if (mac_addr_used >= nvram.mac_addr_count) {
@@ -722,21 +729,23 @@ static int board_get_mac_address(u8 *mac)
}
memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
- p = mac + ETH_ALEN - 1;
+ 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 != mac);
- }
+ } while (p != oui);
- if (p == mac) {
- printk(KERN_ERR PFX "unable to fetch mac address\n");
- return -ENODEV;
+ if (p == oui) {
+ printk(KERN_ERR PFX "unable to fetch mac address\n");
+ return -ENODEV;
+ }
}
mac_addr_used++;
@@ -888,6 +897,9 @@ int __init board_register_devices(void)
!board_get_mac_address(board.enet1.mac_addr))
bcm63xx_enet_register(1, &board.enet1);
+ if (board.has_usbd)
+ bcm63xx_usbd_register(&board.usbd);
+
if (board.has_dsp)
bcm63xx_dsp_register(&board.dsp);
diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c
index 1db48adb543a..dff79ab6005e 100644
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -160,7 +160,9 @@ static struct clk clk_pcm = {
*/
static void usbh_set(struct clk *clk, int enable)
{
- if (BCMCPU_IS_6348())
+ 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_6368())
bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
@@ -171,6 +173,21 @@ static struct clk clk_usbh = {
};
/*
+ * 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_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)
@@ -284,6 +301,8 @@ struct clk *clk_get(struct device *dev, const char *id)
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, "xtm"))
diff --git a/arch/mips/bcm63xx/dev-usb-usbd.c b/arch/mips/bcm63xx/dev-usb-usbd.c
new file mode 100644
index 000000000000..508bd9d8df27
--- /dev/null
+++ b/arch/mips/bcm63xx/dev-usb-usbd.c
@@ -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);
+}
diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c
index 18e051ad18a5..da24c2bd9b7c 100644
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -56,8 +56,8 @@ static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
#define is_ext_irq_cascaded 0
#define ext_irq_start 0
#define ext_irq_end 0
-#define ext_irq_count 0
-#define ext_irq_cfg_reg1 0
+#define ext_irq_count 4
+#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6345
#define ext_irq_cfg_reg2 0
#endif
#ifdef CONFIG_BCM63XX_CPU_6348
@@ -143,11 +143,15 @@ static void bcm63xx_init_irq(void)
irq_stat_addr += PERF_IRQSTAT_6338_REG;
irq_mask_addr += PERF_IRQMASK_6338_REG;
irq_bits = 32;
+ ext_irq_count = 4;
+ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
break;
case BCM6345_CPU_ID:
irq_stat_addr += PERF_IRQSTAT_6345_REG;
irq_mask_addr += PERF_IRQMASK_6345_REG;
irq_bits = 32;
+ ext_irq_count = 4;
+ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
break;
case BCM6348_CPU_ID:
irq_stat_addr += PERF_IRQSTAT_6348_REG;
@@ -434,7 +438,8 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
reg = bcm_perf_readl(regaddr);
irq %= 4;
- if (BCMCPU_IS_6348()) {
+ switch (bcm63xx_get_cpu_id()) {
+ case BCM6348_CPU_ID:
if (levelsense)
reg |= EXTIRQ_CFG_LEVELSENSE_6348(irq);
else
@@ -447,9 +452,13 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
reg |= EXTIRQ_CFG_BOTHEDGE_6348(irq);
else
reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq);
- }
+ break;
- if (BCMCPU_IS_6338() || BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
+ case BCM6328_CPU_ID:
+ case BCM6338_CPU_ID:
+ case BCM6345_CPU_ID:
+ case BCM6358_CPU_ID:
+ case BCM6368_CPU_ID:
if (levelsense)
reg |= EXTIRQ_CFG_LEVELSENSE(irq);
else
@@ -462,6 +471,9 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
reg |= EXTIRQ_CFG_BOTHEDGE(irq);
else
reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
+ break;
+ default:
+ BUG();
}
bcm_perf_writel(reg, regaddr);
diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c
index 0e74a13639cd..314231be788c 100644
--- a/arch/mips/bcm63xx/setup.c
+++ b/arch/mips/bcm63xx/setup.c
@@ -74,6 +74,9 @@ void bcm63xx_machine_reboot(void)
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;
@@ -83,6 +86,9 @@ void bcm63xx_machine_reboot(void)
}
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;