diff options
Diffstat (limited to 'arch/mips/bcm63xx')
-rw-r--r-- | arch/mips/bcm63xx/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/bcm63xx/boards/board_bcm963xx.c | 26 | ||||
-rw-r--r-- | arch/mips/bcm63xx/clk.c | 21 | ||||
-rw-r--r-- | arch/mips/bcm63xx/dev-usb-usbd.c | 65 | ||||
-rw-r--r-- | arch/mips/bcm63xx/irq.c | 22 | ||||
-rw-r--r-- | arch/mips/bcm63xx/setup.c | 6 |
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; |