Commit 6969a434 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus

* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: (25 commits)
  MIPS: Use GCC __builtin_prefetch() to implement prefetch().
  MIPS: Octeon: Serial port fixes for OCTEON simulator.
  MIPS: Octeon: Get rid of early serial.
  MIPS: AR7: prevent race between clock initialization and devices registration
  MIPS: AR7: use ar7_has_high_vlynq() to determine watchdog base address
  MIPS: BCM63xx: Avoid namespace clash on GPIO_DIR_{IN,OUT}
  MIPS: MTX-1: Update defconfig
  MIPS: BCM47xx: Update defconfig
  MIPS: RB532: Update defconfig
  MIPS: AR7: Update defconfig
  RTC: rtc-cmos: Fix binary mode support
  MIPS: Oprofile: Loongson: Cleanup the comments
  MIPS: Oprofile: Loongson: Cleanup of the macros
  MIPS: Oprofile: Loongson: Remove unused variable from loongson2_cpu_setup()
  MIPS: Oprofile: Loongson: Remove useless parentheses
  MIPS: Oprofile: Loongson: Unify macro for setting events
  MIPS: nofpu and nodsp only affect CPU0
  MIPS: Clean up tables for bootmem allocation
  MIPS: Coding style cleanups of access of FCSR rounding mode bits
  MIPS: Loongson 2F: Add gpio/gpioilb support
  ...
parents 0fc377bd 0453fb3c
......@@ -1075,6 +1075,8 @@ config CPU_LOONGSON2F
bool "Loongson 2F"
depends on SYS_HAS_CPU_LOONGSON2F
select CPU_LOONGSON2
select GENERIC_GPIO
select ARCH_REQUIRE_GPIOLIB
help
The Loongson 2F processor implements the MIPS III instruction set
with many extensions.
......
......@@ -36,6 +36,7 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/sysdev.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
......@@ -174,10 +175,6 @@ static dbdev_tab_t dbdev_tab[] = {
#define DBDEV_TAB_SIZE ARRAY_SIZE(dbdev_tab)
#ifdef CONFIG_PM
static u32 au1xxx_dbdma_pm_regs[NUM_DBDMA_CHANS + 1][6];
#endif
static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS];
......@@ -960,29 +957,37 @@ u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr)
return nbytes;
}
#ifdef CONFIG_PM
void au1xxx_dbdma_suspend(void)
struct alchemy_dbdma_sysdev {
struct sys_device sysdev;
u32 pm_regs[NUM_DBDMA_CHANS + 1][6];
};
static int alchemy_dbdma_suspend(struct sys_device *dev,
pm_message_t state)
{
struct alchemy_dbdma_sysdev *sdev =
container_of(dev, struct alchemy_dbdma_sysdev, sysdev);
int i;
u32 addr;
addr = DDMA_GLOBAL_BASE;
au1xxx_dbdma_pm_regs[0][0] = au_readl(addr + 0x00);
au1xxx_dbdma_pm_regs[0][1] = au_readl(addr + 0x04);
au1xxx_dbdma_pm_regs[0][2] = au_readl(addr + 0x08);
au1xxx_dbdma_pm_regs[0][3] = au_readl(addr + 0x0c);
sdev->pm_regs[0][0] = au_readl(addr + 0x00);
sdev->pm_regs[0][1] = au_readl(addr + 0x04);
sdev->pm_regs[0][2] = au_readl(addr + 0x08);
sdev->pm_regs[0][3] = au_readl(addr + 0x0c);
/* save channel configurations */
for (i = 1, addr = DDMA_CHANNEL_BASE; i <= NUM_DBDMA_CHANS; i++) {
au1xxx_dbdma_pm_regs[i][0] = au_readl(addr + 0x00);
au1xxx_dbdma_pm_regs[i][1] = au_readl(addr + 0x04);
au1xxx_dbdma_pm_regs[i][2] = au_readl(addr + 0x08);
au1xxx_dbdma_pm_regs[i][3] = au_readl(addr + 0x0c);
au1xxx_dbdma_pm_regs[i][4] = au_readl(addr + 0x10);
au1xxx_dbdma_pm_regs[i][5] = au_readl(addr + 0x14);
sdev->pm_regs[i][0] = au_readl(addr + 0x00);
sdev->pm_regs[i][1] = au_readl(addr + 0x04);
sdev->pm_regs[i][2] = au_readl(addr + 0x08);
sdev->pm_regs[i][3] = au_readl(addr + 0x0c);
sdev->pm_regs[i][4] = au_readl(addr + 0x10);
sdev->pm_regs[i][5] = au_readl(addr + 0x14);
/* halt channel */
au_writel(au1xxx_dbdma_pm_regs[i][0] & ~1, addr + 0x00);
au_writel(sdev->pm_regs[i][0] & ~1, addr + 0x00);
au_sync();
while (!(au_readl(addr + 0x14) & 1))
au_sync();
......@@ -992,32 +997,65 @@ void au1xxx_dbdma_suspend(void)
/* disable channel interrupts */
au_writel(0, DDMA_GLOBAL_BASE + 0x0c);
au_sync();
return 0;
}
void au1xxx_dbdma_resume(void)
static int alchemy_dbdma_resume(struct sys_device *dev)
{
struct alchemy_dbdma_sysdev *sdev =
container_of(dev, struct alchemy_dbdma_sysdev, sysdev);
int i;
u32 addr;
addr = DDMA_GLOBAL_BASE;
au_writel(au1xxx_dbdma_pm_regs[0][0], addr + 0x00);
au_writel(au1xxx_dbdma_pm_regs[0][1], addr + 0x04);
au_writel(au1xxx_dbdma_pm_regs[0][2], addr + 0x08);
au_writel(au1xxx_dbdma_pm_regs[0][3], addr + 0x0c);
au_writel(sdev->pm_regs[0][0], addr + 0x00);
au_writel(sdev->pm_regs[0][1], addr + 0x04);
au_writel(sdev->pm_regs[0][2], addr + 0x08);
au_writel(sdev->pm_regs[0][3], addr + 0x0c);
/* restore channel configurations */
for (i = 1, addr = DDMA_CHANNEL_BASE; i <= NUM_DBDMA_CHANS; i++) {
au_writel(au1xxx_dbdma_pm_regs[i][0], addr + 0x00);
au_writel(au1xxx_dbdma_pm_regs[i][1], addr + 0x04);
au_writel(au1xxx_dbdma_pm_regs[i][2], addr + 0x08);
au_writel(au1xxx_dbdma_pm_regs[i][3], addr + 0x0c);
au_writel(au1xxx_dbdma_pm_regs[i][4], addr + 0x10);
au_writel(au1xxx_dbdma_pm_regs[i][5], addr + 0x14);
au_writel(sdev->pm_regs[i][0], addr + 0x00);
au_writel(sdev->pm_regs[i][1], addr + 0x04);
au_writel(sdev->pm_regs[i][2], addr + 0x08);
au_writel(sdev->pm_regs[i][3], addr + 0x0c);
au_writel(sdev->pm_regs[i][4], addr + 0x10);
au_writel(sdev->pm_regs[i][5], addr + 0x14);
au_sync();
addr += 0x100; /* next channel base */
}
return 0;
}
static struct sysdev_class alchemy_dbdma_sysdev_class = {
.name = "dbdma",
.suspend = alchemy_dbdma_suspend,
.resume = alchemy_dbdma_resume,
};
static int __init alchemy_dbdma_sysdev_init(void)
{
struct alchemy_dbdma_sysdev *sdev;
int ret;
ret = sysdev_class_register(&alchemy_dbdma_sysdev_class);
if (ret)
return ret;
sdev = kzalloc(sizeof(struct alchemy_dbdma_sysdev), GFP_KERNEL);
if (!sdev)
return -ENOMEM;
sdev->sysdev.id = -1;
sdev->sysdev.cls = &alchemy_dbdma_sysdev_class;
ret = sysdev_register(&sdev->sysdev);
if (ret)
kfree(sdev);
return ret;
}
#endif /* CONFIG_PM */
static int __init au1xxx_dbdma_init(void)
{
......@@ -1046,6 +1084,11 @@ static int __init au1xxx_dbdma_init(void)
else {
dbdma_initialized = 1;
printk(KERN_INFO "Alchemy DBDMA initialized\n");
ret = alchemy_dbdma_sysdev_init();
if (ret) {
printk(KERN_ERR "DBDMA PM init failed\n");
ret = 0;
}
}
return ret;
......
......@@ -29,6 +29,8 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/sysdev.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
......@@ -216,90 +218,6 @@ struct au1xxx_irqmap au1200_irqmap[] __initdata = {
};
#ifdef CONFIG_PM
/*
* Save/restore the interrupt controller state.
* Called from the save/restore core registers as part of the
* au_sleep function in power.c.....maybe I should just pm_register()
* them instead?
*/
static unsigned int sleep_intctl_config0[2];
static unsigned int sleep_intctl_config1[2];
static unsigned int sleep_intctl_config2[2];
static unsigned int sleep_intctl_src[2];
static unsigned int sleep_intctl_assign[2];
static unsigned int sleep_intctl_wake[2];
static unsigned int sleep_intctl_mask[2];
void save_au1xxx_intctl(void)
{
sleep_intctl_config0[0] = au_readl(IC0_CFG0RD);
sleep_intctl_config1[0] = au_readl(IC0_CFG1RD);
sleep_intctl_config2[0] = au_readl(IC0_CFG2RD);
sleep_intctl_src[0] = au_readl(IC0_SRCRD);
sleep_intctl_assign[0] = au_readl(IC0_ASSIGNRD);
sleep_intctl_wake[0] = au_readl(IC0_WAKERD);
sleep_intctl_mask[0] = au_readl(IC0_MASKRD);
sleep_intctl_config0[1] = au_readl(IC1_CFG0RD);
sleep_intctl_config1[1] = au_readl(IC1_CFG1RD);
sleep_intctl_config2[1] = au_readl(IC1_CFG2RD);
sleep_intctl_src[1] = au_readl(IC1_SRCRD);
sleep_intctl_assign[1] = au_readl(IC1_ASSIGNRD);
sleep_intctl_wake[1] = au_readl(IC1_WAKERD);
sleep_intctl_mask[1] = au_readl(IC1_MASKRD);
}
/*
* For most restore operations, we clear the entire register and
* then set the bits we found during the save.
*/
void restore_au1xxx_intctl(void)
{
au_writel(0xffffffff, IC0_MASKCLR); au_sync();
au_writel(0xffffffff, IC0_CFG0CLR); au_sync();
au_writel(sleep_intctl_config0[0], IC0_CFG0SET); au_sync();
au_writel(0xffffffff, IC0_CFG1CLR); au_sync();
au_writel(sleep_intctl_config1[0], IC0_CFG1SET); au_sync();
au_writel(0xffffffff, IC0_CFG2CLR); au_sync();
au_writel(sleep_intctl_config2[0], IC0_CFG2SET); au_sync();
au_writel(0xffffffff, IC0_SRCCLR); au_sync();
au_writel(sleep_intctl_src[0], IC0_SRCSET); au_sync();
au_writel(0xffffffff, IC0_ASSIGNCLR); au_sync();
au_writel(sleep_intctl_assign[0], IC0_ASSIGNSET); au_sync();
au_writel(0xffffffff, IC0_WAKECLR); au_sync();
au_writel(sleep_intctl_wake[0], IC0_WAKESET); au_sync();
au_writel(0xffffffff, IC0_RISINGCLR); au_sync();
au_writel(0xffffffff, IC0_FALLINGCLR); au_sync();
au_writel(0x00000000, IC0_TESTBIT); au_sync();
au_writel(0xffffffff, IC1_MASKCLR); au_sync();
au_writel(0xffffffff, IC1_CFG0CLR); au_sync();
au_writel(sleep_intctl_config0[1], IC1_CFG0SET); au_sync();
au_writel(0xffffffff, IC1_CFG1CLR); au_sync();
au_writel(sleep_intctl_config1[1], IC1_CFG1SET); au_sync();
au_writel(0xffffffff, IC1_CFG2CLR); au_sync();
au_writel(sleep_intctl_config2[1], IC1_CFG2SET); au_sync();
au_writel(0xffffffff, IC1_SRCCLR); au_sync();
au_writel(sleep_intctl_src[1], IC1_SRCSET); au_sync();
au_writel(0xffffffff, IC1_ASSIGNCLR); au_sync();
au_writel(sleep_intctl_assign[1], IC1_ASSIGNSET); au_sync();
au_writel(0xffffffff, IC1_WAKECLR); au_sync();
au_writel(sleep_intctl_wake[1], IC1_WAKESET); au_sync();
au_writel(0xffffffff, IC1_RISINGCLR); au_sync();
au_writel(0xffffffff, IC1_FALLINGCLR); au_sync();
au_writel(0x00000000, IC1_TESTBIT); au_sync();
au_writel(sleep_intctl_mask[1], IC1_MASKSET); au_sync();
au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync();
}
#endif /* CONFIG_PM */
static void au1x_ic0_unmask(unsigned int irq_nr)
{
unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
......@@ -635,3 +553,91 @@ void __init arch_init_irq(void)
break;
}
}
struct alchemy_ic_sysdev {
struct sys_device sysdev;
void __iomem *base;
unsigned long pmdata[7];
};
static int alchemy_ic_suspend(struct sys_device *dev, pm_message_t state)
{
struct alchemy_ic_sysdev *icdev =
container_of(dev, struct alchemy_ic_sysdev, sysdev);
icdev->pmdata[0] = __raw_readl(icdev->base + IC_CFG0RD);
icdev->pmdata[1] = __raw_readl(icdev->base + IC_CFG1RD);
icdev->pmdata[2] = __raw_readl(icdev->base + IC_CFG2RD);
icdev->pmdata[3] = __raw_readl(icdev->base + IC_SRCRD);
icdev->pmdata[4] = __raw_readl(icdev->base + IC_ASSIGNRD);
icdev->pmdata[5] = __raw_readl(icdev->base + IC_WAKERD);
icdev->pmdata[6] = __raw_readl(icdev->base + IC_MASKRD);
return 0;
}
static int alchemy_ic_resume(struct sys_device *dev)
{
struct alchemy_ic_sysdev *icdev =
container_of(dev, struct alchemy_ic_sysdev, sysdev);
__raw_writel(0xffffffff, icdev->base + IC_MASKCLR);
__raw_writel(0xffffffff, icdev->base + IC_CFG0CLR);
__raw_writel(0xffffffff, icdev->base + IC_CFG1CLR);
__raw_writel(0xffffffff, icdev->base + IC_CFG2CLR);
__raw_writel(0xffffffff, icdev->base + IC_SRCCLR);
__raw_writel(0xffffffff, icdev->base + IC_ASSIGNCLR);
__raw_writel(0xffffffff, icdev->base + IC_WAKECLR);
__raw_writel(0xffffffff, icdev->base + IC_RISINGCLR);
__raw_writel(0xffffffff, icdev->base + IC_FALLINGCLR);
__raw_writel(0x00000000, icdev->base + IC_TESTBIT);
wmb();
__raw_writel(icdev->pmdata[0], icdev->base + IC_CFG0SET);
__raw_writel(icdev->pmdata[1], icdev->base + IC_CFG1SET);
__raw_writel(icdev->pmdata[2], icdev->base + IC_CFG2SET);
__raw_writel(icdev->pmdata[3], icdev->base + IC_SRCSET);
__raw_writel(icdev->pmdata[4], icdev->base + IC_ASSIGNSET);
__raw_writel(icdev->pmdata[5], icdev->base + IC_WAKESET);
wmb();
__raw_writel(icdev->pmdata[6], icdev->base + IC_MASKSET);
wmb();
return 0;
}
static struct sysdev_class alchemy_ic_sysdev_class = {
.name = "ic",
.suspend = alchemy_ic_suspend,
.resume = alchemy_ic_resume,
};
static int __init alchemy_ic_sysdev_init(void)
{
struct alchemy_ic_sysdev *icdev;
unsigned long icbase[2] = { IC0_PHYS_ADDR, IC1_PHYS_ADDR };
int err, i;
err = sysdev_class_register(&alchemy_ic_sysdev_class);
if (err)
return err;
for (i = 0; i < 2; i++) {
icdev = kzalloc(sizeof(struct alchemy_ic_sysdev), GFP_KERNEL);
if (!icdev)
return -ENOMEM;
icdev->base = ioremap(icbase[i], 0x1000);
icdev->sysdev.id = i;
icdev->sysdev.cls = &alchemy_ic_sysdev_class;
err = sysdev_register(&icdev->sysdev);
if (err) {
kfree(icdev);
return err;
}
}
return 0;
}
device_initcall(alchemy_ic_sysdev_init);
......@@ -36,9 +36,6 @@
#include <asm/uaccess.h>
#include <asm/mach-au1x00/au1000.h>
#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
#include <asm/mach-au1x00/au1xxx_dbdma.h>
#endif
#ifdef CONFIG_PM
......@@ -106,9 +103,6 @@ static void save_core_regs(void)
sleep_usb[1] = au_readl(0xb4020024); /* OTG_MUX */
#endif
/* Save interrupt controller state. */
save_au1xxx_intctl();
/* Clocks and PLLs. */
sleep_sys_clocks[0] = au_readl(SYS_FREQCTRL0);
sleep_sys_clocks[1] = au_readl(SYS_FREQCTRL1);
......@@ -132,10 +126,6 @@ static void save_core_regs(void)
sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3);
sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3);
sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3);
#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
au1xxx_dbdma_suspend();
#endif
}
static void restore_core_regs(void)
......@@ -199,12 +189,6 @@ static void restore_core_regs(void)
au_writel(sleep_uart0_linectl, UART0_ADDR + UART_LCR); au_sync();
au_writel(sleep_uart0_clkdiv, UART0_ADDR + UART_CLK); au_sync();
}
restore_au1xxx_intctl();
#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
au1xxx_dbdma_resume();
#endif
}
void au_sleep(void)
......
......@@ -27,8 +27,10 @@
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pm.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-pb1x00/pb1000.h>
#include <asm/reboot.h>
#include <prom.h>
#include "../platform.h"
......@@ -38,8 +40,16 @@ const char *get_system_type(void)
return "Alchemy Pb1000";
}
void board_reset(void)
static void board_reset(char *c)
{
asm volatile ("jr %0" : : "r" (0xbfc00000));
}
static void board_power_off(void)
{
printk(KERN_ALERT "It's now safe to remove power\n");
while (1)
asm volatile (".set mips3 ; wait ; .set mips1");
}
void __init board_setup(void)
......@@ -177,6 +187,10 @@ void __init board_setup(void)
au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
break;
}
pm_power_off = board_power_off;
_machine_halt = board_power_off;
_machine_restart = board_reset;
}
static int __init pb1000_init_irq(void)
......
......@@ -39,11 +39,6 @@ const char *get_system_type(void)
return "Alchemy Pb1100";
}
void board_reset(void)
{
bcsr_write(BCSR_SYSTEM, 0);
}
void __init board_setup(void)
{
volatile void __iomem *base = (volatile void __iomem *)0xac000000UL;
......
......@@ -48,12 +48,6 @@ const char *get_system_type(void)
return "Alchemy Pb1200";
}
void board_reset(void)
{
bcsr_write(BCSR_RESETS, 0);
bcsr_write(BCSR_SYSTEM, 0);
}
void __init board_setup(void)
{
printk(KERN_INFO "AMD Alchemy Pb1200 Board\n");
......
......@@ -45,11 +45,6 @@ const char *get_system_type(void)
return "Alchemy Pb1500";
}
void board_reset(void)
{
bcsr_write(BCSR_SYSTEM, 0);
}
void __init board_setup(void)
{
u32 pin_func;
......
......@@ -48,11 +48,6 @@ const char *get_system_type(void)
return "Alchemy Pb1550";
}
void board_reset(void)
{
bcsr_write(BCSR_SYSTEM, 0);
}
void __init board_setup(void)
{
u32 pin_func;
......
......@@ -576,7 +576,6 @@ static int __init ar7_register_devices(void)
{
void __iomem *bootcr;
u32 val;
u16 chip_id;
int res;
res = ar7_register_uarts();
......@@ -635,18 +634,10 @@ static int __init ar7_register_devices(void)
val = readl(bootcr);
iounmap(bootcr);
if (val & AR7_WDT_HW_ENA) {
chip_id = ar7_chip_id();
switch (chip_id) {
case AR7_CHIP_7100:
case AR7_CHIP_7200:
ar7_wdt_res.start = AR7_REGS_WDT;
break;
case AR7_CHIP_7300:
if (ar7_has_high_vlynq())
ar7_wdt_res.start = UR8_REGS_WDT;
break;
default:
break;
}
else
ar7_wdt_res.start = AR7_REGS_WDT;
ar7_wdt_res.end = ar7_wdt_res.start + 0x20;
res = platform_device_register(&ar7_wdt);
......@@ -656,4 +647,4 @@ static int __init ar7_register_devices(void)
return 0;
}
arch_initcall(ar7_register_devices);
device_initcall(ar7_register_devices);
......@@ -91,7 +91,7 @@ static int bcm63xx_gpio_set_direction(struct gpio_chip *chip,
spin_lock_irqsave(&bcm63xx_gpio_lock, flags);
tmp = bcm_gpio_readl(reg);
if (dir == GPIO_DIR_IN)
if (dir == BCM63XX_GPIO_DIR_IN)
tmp &= ~mask;
else
tmp |= mask;
......@@ -103,14 +103,14 @@ static int bcm63xx_gpio_set_direction(struct gpio_chip *chip,
static int bcm63xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
return bcm63xx_gpio_set_direction(chip, gpio, GPIO_DIR_IN);
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, GPIO_DIR_OUT);
return bcm63xx_gpio_set_direction(chip, gpio, BCM63XX_GPIO_DIR_OUT);
}
......
......@@ -65,6 +65,10 @@ static void __init octeon_uart_set_common(struct plat_serial8250_port *p)
p->type = PORT_OCTEON;
p->iotype = UPIO_MEM;
p->regshift = 3; /* I/O addresses are every 8 bytes */
if (octeon_is_simulation())
/* Make simulator output fast*/
p->uartclk = 115200 * 16;
else
p->uartclk = mips_hpt_frequency;
p->serial_in = octeon_serial_in;
p->serial_out = octeon_serial_out;
......
......@@ -403,7 +403,6 @@ void __init prom_init(void)
const int coreid = cvmx_get_core_num();
int i;
int argc;
struct uart_port octeon_port;
#ifdef CONFIG_CAVIUM_RESERVE32
int64_t addr = -1;
#endif
......@@ -610,30 +609,6 @@ void __init prom_init(void)
_machine_restart = octeon_restart;
_machine_halt = octeon_halt;
memset(&octeon_port, 0, sizeof(octeon_port));
/*
* For early_serial_setup we don't set the port type or
* UPF_FIXED_TYPE.
*/
octeon_port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ;
octeon_port.iotype = UPIO_MEM;
/* I/O addresses are every 8 bytes */
octeon_port.regshift = 3;
/* Clock rate of the chip */
octeon_port.uartclk = mips_hpt_frequency;
octeon_port.fifosize = 64;
octeon_port.mapbase = 0x0001180000000800ull + (1024 * octeon_uart);
octeon_port.membase = cvmx_phys_to_ptr(octeon_port.mapbase);
octeon_port.serial_in = octeon_serial_in;
octeon_port.serial_out = octeon_serial_out;
#ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL
octeon_port.line = 0;
#else
octeon_port.line = octeon_uart;
#endif
octeon_port.irq = 42 + octeon_uart;
early_serial_setup(&octeon_port);
octeon_user_io_init();
register_smp_ops(&octeon_smp_ops);
}
......@@ -727,7 +702,7 @@ int prom_putchar(char c)
} while ((lsrval & 0x20) == 0);
/* Write the byte */
cvmx_write_csr(CVMX_MIO_UARTX_THR(octeon_uart), c);
cvmx_write_csr(CVMX_MIO_UARTX_THR(octeon_uart), c & 0xffull);
return 1;
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -190,8 +190,6 @@ extern unsigned long au1xxx_calc_clock(void);
/* PM: arch/mips/alchemy/common/sleeper.S, power.c, irq.c */
void au1xxx_save_and_sleep(void);
void au_sleep(void);
void save_au1xxx_intctl(void);
void restore_au1xxx_intctl(void);
/* SOC Interrupt numbers */
......@@ -835,6 +833,38 @@ enum soc_au1200_ints {
#define MEM_STNAND_DATA 0x20
#endif
/* Interrupt Controller register offsets */
#define IC_CFG0RD 0x40
#define IC_CFG0SET 0x40
#define IC_CFG0CLR 0x44
#define IC_CFG1RD 0x48
#define IC_CFG1SET 0x48
#define IC_CFG1CLR 0x4C
#define IC_CFG2RD 0x50
#define IC_CFG2SET 0x50
#define IC_CFG2CLR 0x54
#define IC_REQ0INT 0x54
#define IC_SRCRD 0x58
#define IC_SRCSET 0x58
#define IC_SRCCLR 0x5C
#define IC_REQ1INT 0x5C
#define IC_ASSIGNRD 0x60
#define IC_ASSIGNSET 0x60
#define IC_ASSIGNCLR 0x64
#define IC_WAKERD 0x68
#define IC_WAKESET 0x68
#define IC_WAKECLR 0x6C
#define IC_MASKRD 0x70
#define IC_MASKSET 0x70
#define IC_MASKCLR 0x74
#define IC_RISINGRD 0x78
#define IC_RISINGCLR 0x78
#define IC_FALLINGRD 0x7C
#define IC_FALLINGCLR 0x7C
#define IC_TESTBIT 0x80
/* Interrupt Controller 0 */
#define IC0_CFG0RD 0xB0400040
#define IC0_CFG0SET 0xB0400040
......
......@@ -358,10 +358,6 @@ u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr);
u32 au1xxx_ddma_add_device(dbdev_tab_t *dev);
extern void au1xxx_ddma_del_device(u32 devid);
void *au1xxx_ddma_get_nextptr_virt(au1x_ddma_desc_t *dp);
#ifdef CONFIG_PM
void au1xxx_dbdma_suspend(void);
void au1xxx_dbdma_resume(void);
#endif
/*
* Flags for the put_source/put_dest functions.
......
......@@ -20,7 +20,7 @@ static inline unsigned long bcm63xx_gpio_count(void)
}
}
#define GPIO_DIR_OUT 0x0
#define GPIO_DIR_IN 0x1
#define BCM63XX_GPIO_DIR_OUT 0x0
#define BCM63XX_GPIO_DIR_IN 0x1
#endif /* !BCM63XX_GPIO_H */
......@@ -52,6 +52,8 @@
#define cpu_has_tx39_cache 0
#define cpu_has_userlocal 0
#define cpu_has_vce 0
#define cpu_has_veic 0
#define cpu_has_vint 0
#define cpu_has_vtag_icache 0
#define cpu_has_watch 1
......
/*
* STLS2F GPIO Support
*
* Copyright (c) 2008 Richard Liu, STMicroelectronics <richard.liu@st.com>
* Copyright (c) 2008-2010 Arnaud Patard <apatard@mandriva.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __STLS2F_GPIO_H
#define __STLS2F_GPIO_H
#include <asm-generic/gpio.h>
extern void gpio_set_value(unsigned gpio, int value);
extern int gpio_get_value(unsigned gpio);
extern int gpio_cansleep(unsigned gpio);
/* The chip can do interrupt
* but it has not been tested and doc not clear
*/
static inline int gpio_to_irq(int gpio)
{
return -EINVAL;
}
static inline int irq_to_gpio(int gpio)
{
return -EINVAL;
}
#endif /* __STLS2F_GPIO_H */
......@@ -344,16 +344,10 @@ unsigned long get_wchan(struct task_struct *p);
#ifdef CONFIG_CPU_HAS_PREFETCH
#define ARCH_HAS_PREFETCH
#define prefetch(x) __builtin_prefetch((x), 0, 1)
static inline void prefetch(const void *addr)
{
__asm__ __volatile__(
" .set mips4 \n"
" pref %0, (%1) \n"
" .set mips0 \n"
:
: "i" (Pref_Load), "r" (addr));
}
#define ARCH_HAS_PREFETCHW
#define prefetchw(x) __builtin_prefetch((x), 1, 1)
#endif
......
......@@ -125,6 +125,30 @@ static int __init wait_disable(char *s)
__setup("nowait", wait_disable);
static int __cpuinitdata mips_fpu_disabled;
static int __init fpu_disable(char *s)
{
cpu_data[0].options &= ~MIPS_CPU_FPU;
mips_fpu_disabled = 1;
return 1;
}
__setup("nofpu", fpu_disable);
int __cpuinitdata mips_dsp_disabled;
static int __init dsp_disable(char *s)
{
cpu_data[0].ases &= ~MIPS_ASE_DSP;
mips_dsp_disabled = 1;
return 1;
}
__setup("nodsp", dsp_disable);
void __init check_wait(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
......@@ -982,6 +1006,12 @@ __cpuinit void cpu_probe(void)
*/
BUG_ON(current_cpu_type() != c->cputype);
if (mips_fpu_disabled)
c->options &= ~MIPS_CPU_FPU;
if (mips_dsp_disabled)
c->ases &= ~MIPS_ASE_DSP;
if (c->options & MIPS_CPU_FPU) {
c->fpu_id = cpu_get_fpu_id();
......
......@@ -65,7 +65,7 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
return -ENODEV;
cpus_allowed = current->cpus_allowed;
set_cpus_allowed(current, cpumask_of_cpu(cpu));
set_cpus_allowed_ptr(current, cpumask_of(cpu));
if (cpufreq_frequency_table_target
(policy, &loongson2_clockmod_table[0], target_freq, relation,
......@@ -91,7 +91,7 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
/* notifiers */
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
set_cpus_allowed(current, cpus_allowed);
set_cpus_allowed_ptr(current, &cpus_allowed);
/* setting the cpu frequency */
clk_set_rate(cpuclk, freq);
......
......@@ -100,10 +100,10 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
if (test_ti_thread_flag(ti, TIF_FPUBOUND) &&
cpus_intersects(new_mask, mt_fpu_cpumask)) {
cpus_and(effective_mask, new_mask, mt_fpu_cpumask);
retval = set_cpus_allowed(p, effective_mask);
retval = set_cpus_allowed_ptr(p, &effective_mask);
} else {
clear_ti_thread_flag(ti, TIF_FPUBOUND);
retval = set_cpus_allowed(p, new_mask);
retval = set_cpus_allowed_ptr(p, &new_mask);
}
out_unlock:
......
......@@ -569,27 +569,6 @@ void __init setup_arch(char **cmdline_p)
plat_smp_setup();
}
static int __init fpu_disable(char *s)
{
int i;
for (i = 0; i < NR_CPUS; i++)
cpu_data[i].options &= ~MIPS_CPU_FPU;
return 1;
}
__setup("nofpu", fpu_disable);
static int __init dsp_disable(char *s)
{
cpu_data[0].ases &= ~MIPS_ASE_DSP;
return 1;
}
__setup("nodsp", dsp_disable);
unsigned long kernelsp[NR_CPUS];
unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
......
......@@ -867,7 +867,7 @@ static void mt_ase_fp_affinity(void)
= current->cpus_allowed;
cpus_and(tmask, current->cpus_allowed,
mt_fpu_cpumask);
set_cpus_allowed(current, tmask);
set_cpus_allowed_ptr(current, &tmask);
set_thread_flag(TIF_FPUBOUND);
}
}
......
......@@ -4,6 +4,7 @@
obj-y += setup.o init.o cmdline.o env.o time.o reset.o irq.o \
pci.o bonito-irq.o mem.o machtype.o platform.o
obj-$(CONFIG_GENERIC_GPIO) += gpio.o
#
# Serial port support
......
/*
* STLS2F GPIO Support
*
* Copyright (c) 2008 Richard Liu, STMicroelectronics <richard.liu@st.com>
* Copyright (c) 2008-2010 Arnaud Patard <apatard@mandriva.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/err.h>
#include <asm/types.h>
#include <loongson.h>
#include <linux/gpio.h>
#define STLS2F_N_GPIO 4
#define STLS2F_GPIO_IN_OFFSET 16
static DEFINE_SPINLOCK(gpio_lock);
int gpio_get_value(unsigned gpio)
{
u32 val;
u32 mask;
if (gpio >= STLS2F_N_GPIO)
return __gpio_get_value(gpio);
mask = 1 << (gpio + STLS2F_GPIO_IN_OFFSET);
spin_lock(&gpio_lock);
val = LOONGSON_GPIODATA;
spin_unlock(&gpio_lock);
return ((val & mask) != 0);
}
EXPORT_SYMBOL(gpio_get_value);
void gpio_set_value(unsigned gpio, int state)
{
u32 val;
u32 mask;
if (gpio >= STLS2F_N_GPIO) {
__gpio_set_value(gpio, state);
return ;
}
mask = 1 << gpio;
spin_lock(&gpio_lock);
val = LOONGSON_GPIODATA;
if (state)
val |= mask;
else
val &= (~mask);
LOONGSON_GPIODATA = val;
spin_unlock(&gpio_lock);
}
EXPORT_SYMBOL(gpio_set_value);
int gpio_cansleep(unsigned gpio)
{
if (gpio < STLS2F_N_GPIO)
return 0;
else
return __gpio_cansleep(gpio);
}
EXPORT_SYMBOL(gpio_cansleep);
static int ls2f_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
u32 temp;
u32 mask;
if (gpio >= STLS2F_N_GPIO)
return -EINVAL;
spin_lock(&gpio_lock);
mask = 1 << gpio;
temp = LOONGSON_GPIOIE;
temp |= mask;
LOONGSON_GPIOIE = temp;
spin_unlock(&gpio_lock);
return 0;
}
static int ls2f_gpio_direction_output(struct gpio_chip *chip,
unsigned gpio, int level)
{
u32 temp;
u32 mask;
if (gpio >= STLS2F_N_GPIO)
return -EINVAL;
gpio_set_value(gpio, level);
spin_lock(&gpio_lock);
mask = 1 << gpio;
temp = LOONGSON_GPIOIE;
temp &= (~mask);
LOONGSON_GPIOIE = temp;
spin_unlock(&gpio_lock);
return 0;
}
static int ls2f_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
return gpio_get_value(gpio);
}
static void ls2f_gpio_set_value(struct gpio_chip *chip,
unsigned gpio, int value)
{
gpio_set_value(gpio, value);
}
static struct gpio_chip ls2f_chip = {
.label = "ls2f",
.direction_input = ls2f_gpio_direction_input,
.get = ls2f_gpio_get_value,
.direction_output = ls2f_gpio_direction_output,
.set = ls2f_gpio_set_value,
.base = 0,
.ngpio = STLS2F_N_GPIO,
};
static int __init ls2f_gpio_setup(void)
{
return gpiochip_add(&ls2f_chip);
}
arch_initcall(ls2f_gpio_setup);
......@@ -354,7 +354,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
if (MIPSInst_RD(ir) == FPCREG_CSR) {
value = ctx->fcr31;
value = (value & ~0x3) | mips_rm[value & 0x3];
value = (value & ~FPU_CSR_RM) |
mips_rm[modeindex(value)];
#ifdef CSRTRACE
printk("%p gpr[%d]<-csr=%08x\n",
(void *) (xcp->cp0_epc),
......@@ -907,7 +908,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
ieee754sp fs;
SPFROMREG(fs, MIPSInst_FS(ir));
ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
rv.w = ieee754sp_tint(fs);
ieee754_csr.rm = oldrm;
rfmt = w_fmt;
......@@ -933,7 +934,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
ieee754sp fs;
SPFROMREG(fs, MIPSInst_FS(ir));
ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
rv.l = ieee754sp_tlong(fs);
ieee754_csr.rm = oldrm;
rfmt = l_fmt;
......@@ -1081,7 +1082,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
ieee754dp fs;
DPFROMREG(fs, MIPSInst_FS(ir));
ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
rv.w = ieee754dp_tint(fs);
ieee754_csr.rm = oldrm;
rfmt = w_fmt;
......@@ -1107,7 +1108,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
ieee754dp fs;
DPFROMREG(fs, MIPSInst_FS(ir));
ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
rv.l = ieee754dp_tlong(fs);
ieee754_csr.rm = oldrm;
rfmt = l_fmt;
......
......@@ -8,7 +8,6 @@
* 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.
*
*/
#include <linux/init.h>
#include <linux/oprofile.h>
......@@ -17,24 +16,18 @@
#include <loongson.h> /* LOONGSON2_PERFCNT_IRQ */
#include "op_impl.h"
/*
* a patch should be sent to oprofile with the loongson-specific support.
* otherwise, the oprofile tool will not recognize this and complain about
* "cpu_type 'unset' is not valid".
*/
#define LOONGSON2_CPU_TYPE "mips/loongson2"
#define LOONGSON2_COUNTER1_EVENT(event) ((event & 0x0f) << 5)
#define LOONGSON2_COUNTER2_EVENT(event) ((event & 0x0f) << 9)
#define LOONGSON2_PERFCNT_EXL (1UL << 0)
#define LOONGSON2_PERFCNT_KERNEL (1UL << 1)
#define LOONGSON2_PERFCNT_SUPERVISOR (1UL << 2)
#define LOONGSON2_PERFCNT_USER (1UL << 3)
#define LOONGSON2_PERFCNT_INT_EN (1UL << 4)
#define LOONGSON2_PERFCNT_OVERFLOW (1ULL << 31)
/* Loongson2 performance counter register */
#define LOONGSON2_PERFCTRL_EXL (1UL << 0)
#define LOONGSON2_PERFCTRL_KERNEL (1UL << 1)
#define LOONGSON2_PERFCTRL_SUPERVISOR (1UL << 2)
#define LOONGSON2_PERFCTRL_USER (1UL << 3)
#define LOONGSON2_PERFCTRL_ENABLE (1UL << 4)
#define LOONGSON2_PERFCTRL_EVENT(idx, event) \
(((event) & 0x0f) << ((idx) ? 9 : 5))
#define read_c0_perfctrl() __read_64bit_c0_register($24, 0)
#define write_c0_perfctrl(val) __write_64bit_c0_register($24, 0, val)
#define read_c0_perfcnt() __read_64bit_c0_register($25, 0)
......@@ -49,7 +42,6 @@ static struct loongson2_register_config {
static char *oprofid = "LoongsonPerf";
static irqreturn_t loongson2_perfcount_handler(int irq, void *dev_id);
/* Compute all of the registers in preparation for enabling profiling. */
static void loongson2_reg_setup(struct op_counter_config *cfg)
{
......@@ -57,41 +49,38 @@ static void loongson2_reg_setup(struct op_counter_config *cfg)
reg.reset_counter1 = 0;
reg.reset_counter2 = 0;
/* Compute the performance counter ctrl word. */
/* For now count kernel and user mode */
/*
* Compute the performance counter ctrl word.
* For now, count kernel and user mode.
*/
if (cfg[0].enabled) {
ctrl |= LOONGSON2_COUNTER1_EVENT(cfg[0].event);
ctrl |= LOONGSON2_PERFCTRL_EVENT(0, cfg[0].event);
reg.reset_counter1 = 0x80000000ULL - cfg[0].count;
}
if (cfg[1].enabled) {
ctrl |= LOONGSON2_COUNTER2_EVENT(cfg[1].event);
reg.reset_counter2 = (0x80000000ULL - cfg[1].count);
ctrl |= LOONGSON2_PERFCTRL_EVENT(1, cfg[1].event);
reg.reset_counter2 = 0x80000000ULL - cfg[1].count;
}
if (cfg[0].enabled || cfg[1].enabled) {
ctrl |= LOONGSON2_PERFCNT_EXL | LOONGSON2_PERFCNT_INT_EN;
ctrl |= LOONGSON2_PERFCTRL_EXL | LOONGSON2_PERFCTRL_ENABLE;
if (cfg[0].kernel || cfg[1].kernel)
ctrl |= LOONGSON2_PERFCNT_KERNEL;
ctrl |= LOONGSON2_PERFCTRL_KERNEL;
if (cfg[0].user || cfg[1].user)
ctrl |= LOONGSON2_PERFCNT_USER;
ctrl |= LOONGSON2_PERFCTRL_USER;
}
reg.ctrl = ctrl;
reg.cnt1_enabled = cfg[0].enabled;
reg.cnt2_enabled = cfg[1].enabled;
}
/* Program all of the registers in preparation for enabling profiling. */
static void loongson2_cpu_setup(void *args)
{
uint64_t perfcount;
perfcount = (reg.reset_counter2 << 32) | reg.reset_counter1;
write_c0_perfcnt(perfcount);
write_c0_perfcnt((reg.reset_counter2 << 32) | reg.reset_counter1);
}
static void loongson2_cpu_start(void *args)
......@@ -114,15 +103,8 @@ static irqreturn_t loongson2_perfcount_handler(int irq, void *dev_id)
struct pt_regs *regs = get_irq_regs();
int enabled;
/*
* LOONGSON2 defines two 32-bit performance counters.
* To avoid a race updating the registers we need to stop the counters
* while we're messing with
* them ...
*/
/* Check whether the irq belongs to me */
enabled = read_c0_perfctrl() & LOONGSON2_PERFCNT_INT_EN;
enabled = read_c0_perfctrl() & LOONGSON2_PERFCTRL_ENABLE;
if (!enabled)
return IRQ_NONE;
enabled = reg.cnt1_enabled | reg.cnt2_enabled;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Definitions for memory preallocations
*
* Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ARCH_MIPS_POWERTV_ASIC_PREALLOC_H
#define _ARCH_MIPS_POWERTV_ASIC_PREALLOC_H
#define KIBIBYTE(n) ((n) * 1024) /* Number of kibibytes */
#define MEBIBYTE(n) ((n) * KIBIBYTE(1024)) /* Number of mebibytes */
/* "struct resource" array element definition */
#define PREALLOC(NAME, START, END, FLAGS) { \
.name = (NAME), \
.start = (START), \
.end = (END), \
.flags = (FLAGS) \
},
/* Individual resources in the preallocated resource arrays are defined using
* macros. These macros are conditionally defined based on their
* corresponding kernel configuration flag:
* - CONFIG_PREALLOC_NORMAL: preallocate resources for a normal settop box
* - CONFIG_PREALLOC_TFTP: preallocate the TFTP download resource
* - CONFIG_PREALLOC_DOCSIS: preallocate the DOCSIS resource
* - CONFIG_PREALLOC_PMEM: reserve space for persistent memory
*/
#ifdef CONFIG_PREALLOC_NORMAL
#define PREALLOC_NORMAL(name, start, end, flags) \
PREALLOC(name, start, end, flags)
#else
#define PREALLOC_NORMAL(name, start, end, flags)
#endif
#ifdef CONFIG_PREALLOC_TFTP
#define PREALLOC_TFTP(name, start, end, flags) \
PREALLOC(name, start, end, flags)
#else
#define PREALLOC_TFTP(name, start, end, flags)
#endif
#ifdef CONFIG_PREALLOC_DOCSIS
#define PREALLOC_DOCSIS(name, start, end, flags) \
PREALLOC(name, start, end, flags)
#else
#define PREALLOC_DOCSIS(name, start, end, flags)
#endif
#ifdef CONFIG_PREALLOC_PMEM
#define PREALLOC_PMEM(name, start, end, flags) \
PREALLOC(name, start, end, flags)
#else
#define PREALLOC_PMEM(name, start, end, flags)
#endif
#endif
......@@ -238,8 +238,7 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
rtc_control = CMOS_READ(RTC_CONTROL);
spin_unlock_irq(&rtc_lock);
/* REVISIT this assumes PC style usage: always BCD */
if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
if (((unsigned)t->time.tm_sec) < 0x60)
t->time.tm_sec = bcd2bin(t->time.tm_sec);
else
......@@ -258,13 +257,15 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->time.tm_mday = bcd2bin(t->time.tm_mday);
else
t->time.tm_mday = -1;
if (cmos->mon_alrm) {
if (((unsigned)t->time.tm_mon) <= 0x12)
t->time.tm_mon = bcd2bin(t->time.tm_mon) - 1;
t->time.tm_mon = bcd2bin(t->time.tm_mon)-1;
else
t->time.tm_mon = -1;
}
}
}
t->time.tm_year = -1;
t->enabled = !!(rtc_control & RTC_AIE);
......@@ -322,29 +323,26 @@ static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask)
static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
unsigned char mon, mday, hrs, min, sec;
unsigned char mon, mday, hrs, min, sec, rtc_control;
if (!is_valid_irq(cmos->irq))
return -EIO;
/* REVISIT this assumes PC style usage: always BCD */
mon = t->time.tm_mon + 1;
mday = t->time.tm_mday;
hrs = t->time.tm_hour;
min = t->time.tm_min;
sec = t->time.tm_sec;
rtc_control = CMOS_READ(RTC_CONTROL);
if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
/* Writing 0xff means "don't care" or "match all". */
mon = t->time.tm_mon + 1;
mon = (mon <= 12) ? bin2bcd(mon) : 0xff;
mday = t->time.tm_mday;
mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff;
hrs = t->time.tm_hour;
hrs = (hrs < 24) ? bin2bcd(hrs) : 0xff;
min = t->time.tm_min;
min = (min < 60) ? bin2bcd(min) : 0xff;
sec = t->time.tm_sec;
sec = (sec < 60) ? bin2bcd(sec) : 0xff;
}
spin_lock_irq(&rtc_lock);
......@@ -478,7 +476,7 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq)
"update_IRQ\t: %s\n"
"HPET_emulated\t: %s\n"
// "square_wave\t: %s\n"
// "BCD\t\t: %s\n"
"BCD\t\t: %s\n"
"DST_enable\t: %s\n"
"periodic_freq\t: %d\n"
"batt_status\t: %s\n",
......@@ -486,7 +484,7 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq)
(rtc_control & RTC_UIE) ? "yes" : "no",
is_hpet_enabled() ? "yes" : "no",
// (rtc_control & RTC_SQWE) ? "yes" : "no",
// (rtc_control & RTC_DM_BINARY) ? "no" : "yes",
(rtc_control & RTC_DM_BINARY) ? "no" : "yes",
(rtc_control & RTC_DST_EN) ? "yes" : "no",
cmos->rtc->irq_freq,
(valid & RTC_VRT) ? "okay" : "dead");
......@@ -751,12 +749,11 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
spin_unlock_irq(&rtc_lock);
/* FIXME teach the alarm code how to handle binary mode;
/* FIXME:
* <asm-generic/rtc.h> doesn't know 12-hour mode either.
*/
if (is_valid_irq(rtc_irq) &&
(!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY)))) {
dev_dbg(dev, "only 24-hr BCD mode supported\n");
if (is_valid_irq(rtc_irq) && !(rtc_control & RTC_24H)) {
dev_warn(dev, "only 24-hr supported\n");
retval = -ENXIO;
goto cleanup1;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment