diff options
Diffstat (limited to 'arch/mips/alchemy/common')
-rw-r--r-- | arch/mips/alchemy/common/clock.c | 14 | ||||
-rw-r--r-- | arch/mips/alchemy/common/dbdma.c | 29 | ||||
-rw-r--r-- | arch/mips/alchemy/common/dma.c | 23 | ||||
-rw-r--r-- | arch/mips/alchemy/common/gpiolib.c | 4 | ||||
-rw-r--r-- | arch/mips/alchemy/common/platform.c | 18 | ||||
-rw-r--r-- | arch/mips/alchemy/common/prom.c | 26 | ||||
-rw-r--r-- | arch/mips/alchemy/common/setup.c | 53 | ||||
-rw-r--r-- | arch/mips/alchemy/common/time.c | 11 |
8 files changed, 96 insertions, 82 deletions
diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index a95a894aceaf..6c8996e20a7d 100644 --- a/arch/mips/alchemy/common/clock.c +++ b/arch/mips/alchemy/common/clock.c @@ -111,7 +111,7 @@ static struct clk_aliastable { /* access locks to SYS_FREQCTRL0/1 and SYS_CLKSRC registers */ static spinlock_t alchemy_clk_fg0_lock; static spinlock_t alchemy_clk_fg1_lock; -static spinlock_t alchemy_clk_csrc_lock; +static DEFINE_SPINLOCK(alchemy_clk_csrc_lock); /* CPU Core clock *****************************************************/ @@ -152,6 +152,7 @@ static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name, { struct clk_init_data id; struct clk_hw *h; + struct clk *clk; h = kzalloc(sizeof(*h), GFP_KERNEL); if (!h) @@ -164,7 +165,13 @@ static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name, id.ops = &alchemy_clkops_cpu; h->init = &id; - return clk_register(NULL, h); + clk = clk_register(NULL, h); + if (IS_ERR(clk)) { + pr_err("failed to register clock\n"); + kfree(h); + } + + return clk; } /* AUXPLLs ************************************************************/ @@ -764,7 +771,7 @@ static int __init alchemy_clk_init_fgens(int ctype) } id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE; - a = kzalloc((sizeof(*a)) * 6, GFP_KERNEL); + a = kcalloc(6, sizeof(*a), GFP_KERNEL); if (!a) return -ENOMEM; @@ -989,7 +996,6 @@ static int __init alchemy_clk_setup_imux(int ctype) if (!a) return -ENOMEM; - spin_lock_init(&alchemy_clk_csrc_lock); ret = 0; for (i = 0; i < 6; i++) { diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c index 4ca2c28878e0..6a3c890f7bbf 100644 --- a/arch/mips/alchemy/common/dbdma.c +++ b/arch/mips/alchemy/common/dbdma.c @@ -30,6 +30,7 @@ * */ +#include <linux/dma-map-ops.h> /* for dma_default_coherent */ #include <linux/init.h> #include <linux/kernel.h> #include <linux/slab.h> @@ -574,7 +575,7 @@ u32 au1xxx_dbdma_ring_alloc(u32 chanid, int entries) dp++; } - /* Make last descrptor point to the first. */ + /* Make last descriptor point to the first. */ dp--; dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(ctp->chan_desc_base)); ctp->get_ptr = ctp->put_ptr = ctp->cur_ptr = ctp->chan_desc_base; @@ -623,17 +624,18 @@ u32 au1xxx_dbdma_put_source(u32 chanid, dma_addr_t buf, int nbytes, u32 flags) dp->dscr_cmd0 &= ~DSCR_CMD0_IE; /* - * There is an errata on the Au1200/Au1550 parts that could result - * in "stale" data being DMA'ed. It has to do with the snoop logic on - * the cache eviction buffer. DMA_NONCOHERENT is on by default for - * these parts. If it is fixed in the future, these dma_cache_inv will - * just be nothing more than empty macros. See io.h. + * There is an erratum on certain Au1200/Au1550 revisions that could + * result in "stale" data being DMA'ed. It has to do with the snoop + * logic on the cache eviction buffer. dma_default_coherent is set + * to false on these parts. */ - dma_cache_wback_inv((unsigned long)buf, nbytes); + if (!dma_default_coherent) + dma_cache_wback_inv(KSEG0ADDR(buf), nbytes); dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ wmb(); /* drain writebuffer */ dma_cache_wback_inv((unsigned long)dp, sizeof(*dp)); ctp->chan_ptr->ddma_dbell = 0; + wmb(); /* force doorbell write out to dma engine */ /* Get next descriptor pointer. */ ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); @@ -685,17 +687,18 @@ u32 au1xxx_dbdma_put_dest(u32 chanid, dma_addr_t buf, int nbytes, u32 flags) dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1); #endif /* - * There is an errata on the Au1200/Au1550 parts that could result in - * "stale" data being DMA'ed. It has to do with the snoop logic on the - * cache eviction buffer. DMA_NONCOHERENT is on by default for these - * parts. If it is fixed in the future, these dma_cache_inv will just - * be nothing more than empty macros. See io.h. + * There is an erratum on certain Au1200/Au1550 revisions that could + * result in "stale" data being DMA'ed. It has to do with the snoop + * logic on the cache eviction buffer. dma_default_coherent is set + * to false on these parts. */ - dma_cache_inv((unsigned long)buf, nbytes); + if (!dma_default_coherent) + dma_cache_inv(KSEG0ADDR(buf), nbytes); dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ wmb(); /* drain writebuffer */ dma_cache_wback_inv((unsigned long)dp, sizeof(*dp)); ctp->chan_ptr->ddma_dbell = 0; + wmb(); /* force doorbell write out to dma engine */ /* Get next descriptor pointer. */ ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); diff --git a/arch/mips/alchemy/common/dma.c b/arch/mips/alchemy/common/dma.c index 973049b5bd61..44d8433b1f45 100644 --- a/arch/mips/alchemy/common/dma.c +++ b/arch/mips/alchemy/common/dma.c @@ -131,29 +131,6 @@ static const struct dma_dev dma_dev_table_bank2[DMA_NUM_DEV_BANK2] = { { AU1100_SD1_PHYS_ADDR + 0x04, DMA_DS | DMA_DW8 | DMA_DR } /* coherent */ }; -void dump_au1000_dma_channel(unsigned int dmanr) -{ - struct dma_chan *chan; - - if (dmanr >= NUM_AU1000_DMA_CHANNELS) - return; - chan = &au1000_dma_table[dmanr]; - - printk(KERN_INFO "Au1000 DMA%d Register Dump:\n", dmanr); - printk(KERN_INFO " mode = 0x%08x\n", - __raw_readl(chan->io + DMA_MODE_SET)); - printk(KERN_INFO " addr = 0x%08x\n", - __raw_readl(chan->io + DMA_PERIPHERAL_ADDR)); - printk(KERN_INFO " start0 = 0x%08x\n", - __raw_readl(chan->io + DMA_BUFFER0_START)); - printk(KERN_INFO " start1 = 0x%08x\n", - __raw_readl(chan->io + DMA_BUFFER1_START)); - printk(KERN_INFO " count0 = 0x%08x\n", - __raw_readl(chan->io + DMA_BUFFER0_COUNT)); - printk(KERN_INFO " count1 = 0x%08x\n", - __raw_readl(chan->io + DMA_BUFFER1_COUNT)); -} - /* * Finds a free channel, and binds the requested device to it. * Returns the allocated channel number, or negative on error. diff --git a/arch/mips/alchemy/common/gpiolib.c b/arch/mips/alchemy/common/gpiolib.c index 7d5da5edd74d..1b16daaa86ae 100644 --- a/arch/mips/alchemy/common/gpiolib.c +++ b/arch/mips/alchemy/common/gpiolib.c @@ -23,8 +23,6 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. * * Notes : - * This file must ONLY be built when CONFIG_GPIOLIB=y and - * CONFIG_ALCHEMY_GPIO_INDIRECT=n, otherwise compilation will fail! * au1000 SoC have only one GPIO block : GPIO1 * Au1100, Au15x0, Au12x0 have a second one : GPIO2 * Au1300 is totally different: 1 block with up to 128 GPIOs @@ -33,7 +31,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/types.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h> #include <asm/mach-au1x00/gpio-au1000.h> #include <asm/mach-au1x00/gpio-au1300.h> diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index b8f3397c59c9..da74cae6b43a 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c @@ -51,9 +51,9 @@ static void alchemy_8250_pm(struct uart_port *port, unsigned int state, #define PORT(_base, _irq) \ { \ .mapbase = _base, \ + .mapsize = 0x1000, \ .irq = _irq, \ .regshift = 2, \ - .iotype = UPIO_AU, \ .flags = UPF_SKIP_TEST | UPF_IOREMAP | \ UPF_FIXED_TYPE, \ .type = PORT_16550A, \ @@ -124,8 +124,14 @@ static void __init alchemy_setup_uarts(int ctype) au1xx0_uart_device.dev.platform_data = ports; /* Fill up uartclk. */ - for (s = 0; s < c; s++) + for (s = 0; s < c; s++) { ports[s].uartclk = uartclk; + if (au_platform_setup(&ports[s]) < 0) { + kfree(ports); + printk(KERN_INFO "Alchemy: missing support for UARTs\n"); + return; + } + } if (platform_device_register(&au1xx0_uart_device)) printk(KERN_INFO "Alchemy: failed to register UARTs\n"); } @@ -403,8 +409,8 @@ static void __init alchemy_setup_macs(int ctype) if (alchemy_get_macs(ctype) < 1) return; - macres = kmemdup(au1xxx_eth0_resources[ctype], - sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL); + macres = kmemdup_array(au1xxx_eth0_resources[ctype], MAC_RES_COUNT, + sizeof(*macres), GFP_KERNEL); if (!macres) { printk(KERN_INFO "Alchemy: no memory for MAC0 resources\n"); return; @@ -424,8 +430,8 @@ static void __init alchemy_setup_macs(int ctype) if (alchemy_get_macs(ctype) < 2) return; - macres = kmemdup(au1xxx_eth1_resources[ctype], - sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL); + macres = kmemdup_array(au1xxx_eth1_resources[ctype], MAC_RES_COUNT, + sizeof(*macres), GFP_KERNEL); if (!macres) { printk(KERN_INFO "Alchemy: no memory for MAC1 resources\n"); return; diff --git a/arch/mips/alchemy/common/prom.c b/arch/mips/alchemy/common/prom.c index af312b5e33f6..20d30f6265cd 100644 --- a/arch/mips/alchemy/common/prom.c +++ b/arch/mips/alchemy/common/prom.c @@ -34,9 +34,13 @@ */ #include <linux/init.h> +#include <linux/kernel.h> +#include <linux/memblock.h> +#include <linux/sizes.h> #include <linux/string.h> #include <asm/bootinfo.h> +#include <prom.h> int prom_argc; char **prom_argv; @@ -76,6 +80,24 @@ char *prom_getenv(char *envname) return NULL; } +void __init prom_init(void) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = (int)fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + + memsize_str = prom_getenv("memsize"); + if (!memsize_str || kstrtoul(memsize_str, 0, &memsize)) + memsize = SZ_64M; /* minimum memsize is 64MB RAM */ + + memblock_add(0, memsize); +} + static inline unsigned char str2hexnum(unsigned char c) { if (c >= '0' && c <= '9') @@ -122,7 +144,3 @@ int __init prom_get_ethernet_addr(char *ethernet_addr) return 0; } - -void __init prom_free_prom_memory(void) -{ -} diff --git a/arch/mips/alchemy/common/setup.c b/arch/mips/alchemy/common/setup.c index 7faaa6d593a7..a7a6d31a7a41 100644 --- a/arch/mips/alchemy/common/setup.c +++ b/arch/mips/alchemy/common/setup.c @@ -27,14 +27,30 @@ #include <linux/init.h> #include <linux/ioport.h> +#include <linux/mm.h> +#include <linux/dma-map-ops.h> /* for dma_default_coherent */ -#include <asm/dma-coherence.h> +#include <asm/bootinfo.h> #include <asm/mipsregs.h> #include <au1000.h> -extern void __init board_setup(void); -extern void __init alchemy_set_lpj(void); +static bool alchemy_dma_coherent(void) +{ + switch (alchemy_get_cputype()) { + case ALCHEMY_CPU_AU1000: + case ALCHEMY_CPU_AU1500: + case ALCHEMY_CPU_AU1100: + return false; + case ALCHEMY_CPU_AU1200: + /* Au1200 AB USB does not support coherent memory */ + if ((read_c0_prid() & PRID_REV_MASK) == 0) + return false; + return true; + default: + return true; + } +} void __init plat_mem_setup(void) { @@ -47,20 +63,7 @@ void __init plat_mem_setup(void) /* Clear to obtain best system bus performance */ clear_c0_config(1 << 19); /* Clear Config[OD] */ - hw_coherentio = 0; - coherentio = IO_COHERENCE_ENABLED; - switch (alchemy_get_cputype()) { - case ALCHEMY_CPU_AU1000: - case ALCHEMY_CPU_AU1500: - case ALCHEMY_CPU_AU1100: - coherentio = IO_COHERENCE_DISABLED; - break; - case ALCHEMY_CPU_AU1200: - /* Au1200 AB USB does not support coherent memory */ - if (0 == (read_c0_prid() & PRID_REV_MASK)) - coherentio = IO_COHERENCE_DISABLED; - break; - } + dma_default_coherent = alchemy_dma_coherent(); board_setup(); /* board specific setup */ @@ -72,9 +75,9 @@ void __init plat_mem_setup(void) iomem_resource.end = IOMEM_RESOURCE_END; } -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_PCI) +#ifdef CONFIG_MIPS_FIXUP_BIGPHYS_ADDR /* This routine should be valid for all Au1x based boards */ -phys_addr_t __fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size) +phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size) { unsigned long start = ALCHEMY_PCI_MEMWIN_START; unsigned long end = ALCHEMY_PCI_MEMWIN_END; @@ -90,5 +93,13 @@ phys_addr_t __fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size) /* default nop */ return phys_addr; } -EXPORT_SYMBOL(__fixup_bigphys_addr); -#endif + +int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long vaddr, + unsigned long pfn, unsigned long size, pgprot_t prot) +{ + phys_addr_t phys_addr = fixup_bigphys_addr(pfn << PAGE_SHIFT, size); + + return remap_pfn_range(vma, vaddr, phys_addr >> PAGE_SHIFT, size, prot); +} +EXPORT_SYMBOL(io_remap_pfn_range); +#endif /* CONFIG_MIPS_FIXUP_BIGPHYS_ADDR */ diff --git a/arch/mips/alchemy/common/time.c b/arch/mips/alchemy/common/time.c index 3a21a6a18da7..d794ffb67412 100644 --- a/arch/mips/alchemy/common/time.c +++ b/arch/mips/alchemy/common/time.c @@ -72,13 +72,6 @@ static struct clock_event_device au1x_rtcmatch2_clockdev = { .cpumask = cpu_possible_mask, }; -static struct irqaction au1x_rtcmatch2_irqaction = { - .handler = au1x_rtcmatch2_irq, - .flags = IRQF_TIMER, - .name = "timer", - .dev_id = &au1x_rtcmatch2_clockdev, -}; - static int __init alchemy_time_init(unsigned int m2int) { struct clock_event_device *cd = &au1x_rtcmatch2_clockdev; @@ -130,7 +123,9 @@ static int __init alchemy_time_init(unsigned int m2int) cd->min_delta_ns = clockevent_delta2ns(9, cd); cd->min_delta_ticks = 9; /* ~0.28ms */ clockevents_register_device(cd); - setup_irq(m2int, &au1x_rtcmatch2_irqaction); + if (request_irq(m2int, au1x_rtcmatch2_irq, IRQF_TIMER, "timer", + &au1x_rtcmatch2_clockdev)) + pr_err("Failed to register timer interrupt\n"); printk(KERN_INFO "Alchemy clocksource installed\n"); |