diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index d46f1da..c3a8bba 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -840,6 +840,21 @@ config SCHED_OMIT_FRAME_POINTER bool default y +config OMS400_PUSHSW + bool + depends on MIPS && MIPS_OMS400 + default y + +config OMS400_LED + bool + depends on MIPS && MIPS_OMS400 + default y + +config OMS400_DIO + bool + depends on MIPS && MIPS_OMS400 + default y + # # Select some configuration options automatically based on user selections. # diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig index 2a68be6..3d8fedf 100644 --- a/arch/mips/alchemy/Kconfig +++ b/arch/mips/alchemy/Kconfig @@ -71,6 +71,16 @@ config MIPS_DB1550 select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_HAS_EARLY_PRINTK +config MIPS_OMS400 + bool "Plat'Home Open Micro Server based on AU1550/400" + select ALCHEMY_GPIOINT_AU1000 + select HW_HAS_PCI + select DMA_NONCOHERENT + select MIPS_DISABLE_OBSOLETE_IDE + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_HAS_EARLY_PRINTK + config MIPS_MIRAGE bool "Alchemy Mirage board" select DMA_NONCOHERENT diff --git a/arch/mips/alchemy/Platform b/arch/mips/alchemy/Platform index 96e9e41..14cc64c 100644 --- a/arch/mips/alchemy/Platform +++ b/arch/mips/alchemy/Platform @@ -68,6 +68,13 @@ cflags-$(CONFIG_MIPS_DB1550) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 # +# Plathome OMS-AL400/128 +# +core-$(CONFIG_MIPS_OMS400) += arch/mips/alchemy/devboards/ +cflags-$(CONFIG_MIPS_OMS400) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 +load-$(CONFIG_MIPS_OMS400) += 0xffffffff80100000 + +# # AMD Alchemy Db1200 eval board # platform-$(CONFIG_MIPS_DB1200) += alchemy/devboards/ diff --git a/arch/mips/alchemy/devboards/Makefile b/arch/mips/alchemy/devboards/Makefile index 826449c..7dbc9fd 100644 --- a/arch/mips/alchemy/devboards/Makefile +++ b/arch/mips/alchemy/devboards/Makefile @@ -14,5 +14,6 @@ obj-$(CONFIG_MIPS_DB1100) += db1x00/ obj-$(CONFIG_MIPS_DB1200) += db1200/ obj-$(CONFIG_MIPS_DB1500) += db1x00/ obj-$(CONFIG_MIPS_DB1550) += db1x00/ +obj-$(CONFIG_MIPS_OMS400) += db1x00/ obj-$(CONFIG_MIPS_BOSPORUS) += db1x00/ obj-$(CONFIG_MIPS_MIRAGE) += db1x00/ diff --git a/arch/mips/alchemy/devboards/db1x00/board_setup.c b/arch/mips/alchemy/devboards/db1x00/board_setup.c index 7cd36e6..ca270fe 100644 --- a/arch/mips/alchemy/devboards/db1x00/board_setup.c +++ b/arch/mips/alchemy/devboards/db1x00/board_setup.c @@ -124,6 +124,9 @@ void __init board_setup(void) #ifdef CONFIG_MIPS_MIRAGE printk(KERN_INFO "AMD Alchemy Mirage Board\n"); #endif +#ifdef CONFIG_MIPS_OMS400 + printk("Plat'Home OMS-AL400/128 based on AMD Alchemy Au1550/400\n"); +#endif #ifdef CONFIG_MIPS_DB1550 printk(KERN_INFO "AMD Alchemy Au1550/Db1550 Board\n"); @@ -195,6 +198,15 @@ static int __init db1x00_init_irq(void) { #if defined(CONFIG_MIPS_MIRAGE) irq_set_irq_type(AU1500_GPIO7_INT, IRQF_TRIGGER_RISING); /* TS pendown */ +#elif defined(CONFIG_MIPS_OMS400) + irq_set_irq_type(AU1550_GPIO0_INT, IRQF_TRIGGER_LOW); /* CD0# */ + irq_set_irq_type(AU1550_GPIO1_INT, IRQF_TRIGGER_LOW); /* CD1# */ + irq_set_irq_type(AU1550_GPIO3_INT, IRQF_TRIGGER_LOW); /* CARD0# */ /* PCMCIA Card 0 IRQ# */ + irq_set_irq_type(AU1550_GPIO5_INT, IRQF_TRIGGER_LOW); /* CARD1# */ + irq_set_irq_type(AU1550_GPIO21_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */ + irq_set_irq_type(AU1550_GPIO22_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */ + irq_set_irq_type(AU1550_GPIO15_INT, IRQF_TRIGGER_HIGH); /* PUSH BUTTON IRQ# */ + irq_set_irq_type(AU1550_GPIO201_205_INT, (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)); /* DIO in */ #elif defined(CONFIG_MIPS_DB1550) irq_set_irq_type(AU1550_GPIO0_INT, IRQF_TRIGGER_LOW); /* CD0# */ irq_set_irq_type(AU1550_GPIO1_INT, IRQF_TRIGGER_LOW); /* CD1# */ diff --git a/arch/mips/alchemy/devboards/db1x00/platform.c b/arch/mips/alchemy/devboards/db1x00/platform.c index 9e6b3d4..bb990cd 100644 --- a/arch/mips/alchemy/devboards/db1x00/platform.c +++ b/arch/mips/alchemy/devboards/db1x00/platform.c @@ -76,6 +76,15 @@ struct pci_dev; #define DB1XXX_PCMCIA_CARD1 AU1550_GPIO5_INT #define BOARD_FLASH_SIZE 0x08000000 /* 128MB */ #define BOARD_FLASH_WIDTH 4 /* 32-bits */ +#elif defined(CONFIG_MIPS_OMS400) +#define DB1XXX_PCMCIA_CD0 AU1550_GPIO0_INT +#define DB1XXX_PCMCIA_STSCHG0 AU1550_GPIO21_INT +#define DB1XXX_PCMCIA_CARD0 AU1550_GPIO3_INT +#define DB1XXX_PCMCIA_CD1 AU1550_GPIO1_INT +#define DB1XXX_PCMCIA_STSCHG1 AU1550_GPIO22_INT +#define DB1XXX_PCMCIA_CARD1 AU1550_GPIO5_INT +#define BOARD_FLASH_SIZE 0x01000000 /* 16MB */ +#define BOARD_FLASH_WIDTH 2 /* 16-bits */ #else /* other board: no PCMCIA */ #undef DB1XXX_HAS_PCMCIA @@ -137,6 +146,51 @@ static int db1xxx_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin) } #endif +#ifdef CONFIG_MIPS_OMS400 +static int db1xxx_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin) +{ + if ((slot < 1) || (slot > 4) || pin == 0) + return -1; + /* External PCI slot */ + if (slot == 1) { + switch (pin) { + case 1: return AU1550_PCI_INTD; + case 2: return AU1550_PCI_INTD; + case 3: return AU1550_PCI_INTD; + case 4: return AU1550_PCI_INTD; + } + } + /* uPD720101 USB */ + if (slot == 2) { + switch (pin) { + case 1: return AU1550_PCI_INTC; + case 2: return AU1550_PCI_INTC; + case 3: return AU1550_PCI_INTC; + case 4: return 0xff; + } + } + /* E1000 GBEther */ + if (slot == 3) { + switch (pin) { + case 1: return AU1550_PCI_INTB; + case 2: return 0xff; + case 3: return 0xff; + case 4: return 0xff; + } + } + /* E1000 GBEther */ + if (slot == 4) { + switch (pin) { + case 1: return AU1550_PCI_INTA; + case 2: return 0xff; + case 3: return 0xff; + case 4: return 0xff; + } + } + return -1; +} +#endif + #ifdef CONFIG_MIPS_BOSPORUS static int db1xxx_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin) { @@ -291,6 +345,7 @@ static int __init db1xxx_dev_init(void) DB1XXX_PCMCIA_CARD0, DB1XXX_PCMCIA_CD0, /*DB1XXX_PCMCIA_STSCHG0*/0, 0, 0); +#ifndef CONFIG_MIPS_OMS400 db1x_register_pcmcia_socket( AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000, AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1, @@ -301,6 +356,7 @@ static int __init db1xxx_dev_init(void) DB1XXX_PCMCIA_CARD1, DB1XXX_PCMCIA_CD1, /*DB1XXX_PCMCIA_STSCHG1*/0, 0, 1); #endif +#endif #ifdef CONFIG_MIPS_DB1100 platform_device_register(&au1100_lcd_device); #endif diff --git a/arch/mips/alchemy/devboards/platform.c b/arch/mips/alchemy/devboards/platform.c index 49a4b32..fb5ae45 100644 --- a/arch/mips/alchemy/devboards/platform.c +++ b/arch/mips/alchemy/devboards/platform.c @@ -161,6 +161,15 @@ int __init db1x_register_norflash(unsigned long size, int width, * to swap the physical locations of the 2 NOR flash banks. */ i = 0; +#ifdef CONFIG_MIPS_OMS400 + { + /* first NOR chip */ + parts[i].offset = 0; + parts[i].name = "Firmware"; + parts[i].size = size - 0x00400000; + i++; + } +#else if (!swapped) { /* first NOR chip */ parts[i].offset = 0; @@ -173,13 +182,40 @@ int __init db1x_register_norflash(unsigned long size, int width, parts[i].name = "User FS 2"; parts[i].size = (size / 2) - (0x20000000 - 0x1fc00000); i++; +#endif parts[i].offset = MTDPART_OFS_APPEND; parts[i].name = "YAMON"; +#ifdef CONFIG_MIPS_OMS400 + parts[i].size = 0x0180000; +#else parts[i].size = YAMON_SIZE; +#endif parts[i].mask_flags = MTD_WRITEABLE; i++; +#ifdef CONFIG_MIPS_OMS400 + parts[i].offset = MTDPART_OFS_APPEND; + parts[i].name = "User Area"; + parts[i].size = 0x00200000; + i++; + + parts[i].offset = MTDPART_OFS_APPEND; + parts[i].name = "flashcfg save area"; + parts[i].size = 0x00040000; + i++; + + parts[i].offset = MTDPART_OFS_APPEND; + parts[i].name = "YAMON Params"; + parts[i].size = 0x00040000; + i++; + + parts[i].offset = 0x00000000; + parts[i].name = "Entire Flash ROM"; + parts[i].size = size; + parts[i].mask_flags = MTD_WRITEABLE; + i++; +#else parts[i].offset = MTDPART_OFS_APPEND; parts[i].name = "raw kernel"; parts[i].size = 0x00400000 - YAMON_SIZE - YAMON_ENV_SIZE; @@ -197,10 +233,16 @@ int __init db1x_register_norflash(unsigned long size, int width, parts[i].size = size / 2; i++; } +#endif pfd->width = width; pfd->parts = parts; + +#ifdef CONFIG_MIPS_OMS400 + pfd->nr_parts = i; +#else pfd->nr_parts = 5; +#endif pd->dev.platform_data = pfd; pd->resource = res; diff --git a/arch/mips/include/asm/dio_oms400.h b/arch/mips/include/asm/dio_oms400.h new file mode 100644 index 0000000..55ef266 --- /dev/null +++ b/arch/mips/include/asm/dio_oms400.h @@ -0,0 +1,20 @@ +/* + * 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) 1995, 1996, 2001 Ralf Baechle + * Copyright (C) 2001 MIPS Technologies, Inc. + */ +#ifndef _DIO_OMS400_H +#define _DIO_OMS400_H + +#include + +#define DIOIOC_RD_DIN _IOR('D', 0x31, int) +#define DIOIOC_WT_DOUT _IOW('D', 0x32, int) +#define DIOIOC_RD_DOUT _IOR('D', 0x33, int) +#define DIOIOC_WAITCHANGE _IOR('D', 0x34, int) +#define DIOIOC_GETWAITPID _IOR('D', 0x35, int) + +#endif /* _DOI_OMS400_H */ diff --git a/arch/mips/include/asm/mach-db1x00/bcsr.h b/arch/mips/include/asm/mach-db1x00/bcsr.h index 618d2de..a9e6ef9 100644 --- a/arch/mips/include/asm/mach-db1x00/bcsr.h +++ b/arch/mips/include/asm/mach-db1x00/bcsr.h @@ -91,6 +91,7 @@ enum bcsr_id { /* register "WHOAMI" bits 11:8 identify the board */ enum bcsr_whoami_boards { + BCSR_WHOAMI_OMS400 = 0, /* ???? */ BCSR_WHOAMI_PB1500 = 1, BCSR_WHOAMI_PB1500R2, BCSR_WHOAMI_PB1100, diff --git a/arch/mips/include/asm/mach-db1x00/db1x00.h b/arch/mips/include/asm/mach-db1x00/db1x00.h index a5affb0..76126ca 100644 --- a/arch/mips/include/asm/mach-db1x00/db1x00.h +++ b/arch/mips/include/asm/mach-db1x00/db1x00.h @@ -29,6 +29,7 @@ #include +#ifndef CONFIG_MIPS_OMS400 #ifdef CONFIG_MIPS_DB1550 #define DBDMA_AC97_TX_CHAN AU1550_DSCR_CMD0_PSC1_TX @@ -76,4 +77,9 @@ #define NAND_STTIME 0x00007774 /* valid for 396 MHz SD=2 only */ #define NAND_STADDR 0x12000FFF /* physical address 0x20000000 */ +#else + +#define SMBUS_PSC_BASE PSC0_BASE_ADDR + +#endif /* CONFIG_MIPS_OMS400 */ #endif /* __ASM_DB1X00_H */ diff --git a/arch/mips/include/asm/pushsw_oms400.h b/arch/mips/include/asm/pushsw_oms400.h new file mode 100644 index 0000000..a99505b --- /dev/null +++ b/arch/mips/include/asm/pushsw_oms400.h @@ -0,0 +1,19 @@ +/* + * Century + * - Century's push switch driver header + */ + +#include +#include +/* #include */ + +#define PUSHSW_MAJOR (MISC_MAJOR) + +#define PUSHSW_IOCTL_BASE 'P' + +#define PSWIOC_GETSTATUS _IOR(PUSHSW_IOCTL_BASE, 0, int) +#define PSWIOC_WAITPUSH _IOR(PUSHSW_IOCTL_BASE, 1, int) +#define PSWIOC_GETWAITPID _IOR(PUSHSW_IOCTL_BASE, 2, int) + +#define PSWIOF_PUSHED (1) +#define PSWIOF_NOTPUSHED (0) diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index d8dad53..f02eb6e 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h @@ -1029,10 +1029,9 @@ #define __NR_N32_Linux 6000 #define __NR_N32_Linux_syscalls 310 -#ifdef __KERNEL__ - #ifndef __ASSEMBLY__ +#ifdef __KERNEL__ #define __ARCH_OMIT_COMPAT_SYS_GETDENTS64 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c index 07fc524..adb2620 100644 --- a/arch/mips/kernel/reset.c +++ b/arch/mips/kernel/reset.c @@ -14,6 +14,12 @@ #include +#if defined(CONFIG_MIPS_OMS400) && defined(CONFIG_OMS400_LED) +#include +#define BLINK_MSEC (1000) +extern int obsled_out(int); +#endif + /* * Urgs ... Too many MIPS machines to handle this in a generic way. * So handle all using function pointers to machine specific @@ -41,4 +47,15 @@ void machine_power_off(void) { if (pm_power_off) pm_power_off(); + +#if defined(CONFIG_MIPS_OMS400) && defined(CONFIG_OMS400_LED) + while(1) { + obsled_out(7); + __asm__ volatile ("sync"); + mdelay(BLINK_MSEC); + obsled_out(0); + __asm__ volatile ("sync"); + mdelay(BLINK_MSEC); + } +#endif } diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index be281c6..3bf4057 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -124,6 +124,12 @@ SECTIONS __init_end = .; /* freed after init ends here */ +#ifdef CONFIG_MIPS_OMS400 + . = ALIGN(PAGE_SIZE); + .initrd_data : { *(.initrd_data) } + . = ALIGN(PAGE_SIZE); +#endif + BSS_SECTION(0, 0, 0) _end = . ; diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index b7ebc4f..fb4da79 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -437,7 +437,7 @@ void free_init_pages(const char *what, unsigned long begin, unsigned long end) ClearPageReserved(page); init_page_count(page); - memset(addr, POISON_FREE_INITMEM, PAGE_SIZE); + memset(addr, 0x00, PAGE_SIZE); __free_page(page); totalram_pages++; } diff --git a/drivers/Makefile b/drivers/Makefile index 1b31421..b7e92ba 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_FB_INTEL) += video/intelfb/ obj-$(CONFIG_PARPORT) += parport/ obj-y += base/ block/ misc/ mfd/ nfc/ obj-$(CONFIG_NUBUS) += nubus/ +obj-$(CONFIG_PCCARD) += pcmcia/ obj-y += macintosh/ obj-$(CONFIG_IDE) += ide/ obj-$(CONFIG_SCSI) += scsi/ @@ -60,7 +61,7 @@ obj-y += firewire/ obj-$(CONFIG_UIO) += uio/ obj-y += cdrom/ obj-y += auxdisplay/ -obj-$(CONFIG_PCCARD) += pcmcia/ +#obj-$(CONFIG_PCCARD) += pcmcia/ obj-$(CONFIG_DIO) += dio/ obj-$(CONFIG_SBUS) += sbus/ obj-$(CONFIG_ZORRO) += zorro/ diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 32762ba..13fb88d 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -49,6 +49,9 @@ obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o obj-$(CONFIG_GPIO_TB0219) += tb0219.o obj-$(CONFIG_TELCLOCK) += tlclk.o +obj-$(CONFIG_OMS400_PUSHSW) += pushsw_oms400.o +obj-$(CONFIG_OMS400_LED) += led_oms400.o +obj-$(CONFIG_OMS400_DIO) += dio_oms400.o obj-$(CONFIG_MWAVE) += mwave/ obj-$(CONFIG_AGP) += agp/ diff --git a/drivers/char/dio_oms400.c b/drivers/char/dio_oms400.c new file mode 100644 index 0000000..4c9272b --- /dev/null +++ b/drivers/char/dio_oms400.c @@ -0,0 +1,197 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DBGON(x) x +#define DBGOFF(x) + +#define DIO_VER "0.01" +#define DIO_IRQ AU1500_GPIO_201_205 + +/*---------------------------------------------------------------------------- + * Prototypes. + *----------------------------------------------------------------------------*/ +int dio_init(void); +irqreturn_t dio_isr(int irq, void *dev_id, struct pt_regs *regs); +static int dio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static int dio_open(struct inode *inode, struct file *file); +static int dio_release(struct inode *inode, struct file *file); + +/*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ +static struct file_operations dio_fops = { + owner: THIS_MODULE, + unlocked_ioctl: dio_ioctl, + open: dio_open, + release: dio_release, +}; +static struct miscdevice dio_miscdev = + { OMS400DIO_MINOR, "dio", &dio_fops }; +static DECLARE_WAIT_QUEUE_HEAD(dio_wait); + +/* used to allow only one process at a time to "own" the DIO */ +static pid_t dio_wait_pid = 0; +/*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ +int +dio_init(void) +{ + printk("DIO driver v%s\n", DIO_VER); + +#ifdef CONFIG_OMS400_DIO_ENABLE_IRQ + /* Install the DIO interrupt handler */ + if (request_irq(DIO_IRQ, dio_isr, IRQF_IRQPOLL, "dio", NULL)) { + printk("[dio_open] interrupt %u not free\n", DIO_IRQ); + return (-EIO); + } + DBGOFF(printk("[dio_init] DIO installed on interrupt %u\n", DIO_IRQ);) +#endif + misc_register(&dio_miscdev); + return (0); +} /* dio_init() */ + +/*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ +irqreturn_t +dio_isr(int irq, void *dev_id, struct pt_regs *regs) +{ + /* DBGOFF(printk(KERN_CRIT "p");) */ + wake_up_interruptible(&dio_wait); + return IRQ_HANDLED; +} /* dio_isr() */ + +/*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ +static int +dio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned long flags; + DEFINE_SPINLOCK(driver_lock); + int val, mask, err; + + if (MINOR(inode->i_rdev) != OMS400DIO_MINOR) { + return (-ENODEV); + } + + switch (cmd) { +#ifdef CONFIG_OMS400_DIO_ENABLE_IRQ + case DIOIOC_GETWAITPID: + return (put_user(dio_wait_pid, (int *) arg)); + case DIOIOC_WAITCHANGE: + /* protect dio_wait_pid */ + spin_lock_irqsave(&driver_lock, flags); + if (dio_wait_pid == 0) { + dio_wait_pid = current->pid; + spin_unlock_irqrestore(&driver_lock, flags); + DBGOFF(printk("[dio_ioctl] DIOIOC_WAITCHANGE pid %u\n", dio_wait_pid);) + /* block until DIN change */ + interruptible_sleep_on(&dio_wait); + spin_lock_irqsave(&driver_lock, flags); + dio_wait_pid = 0; + spin_unlock_irqrestore(&driver_lock, flags); + + DBGOFF(printk("[dio_ioctl] unblocked\n");) + if (signal_pending(current)) { + DBGOFF(printk("[dio_ioctl] sig\n");) + return (-ERESTARTSYS); + } + return (0); + } else { + spin_unlock_irqrestore(&driver_lock, flags); + return (-EBUSY); + } +#endif + case DIOIOC_RD_DIN: + return (put_user((au_readl(GPIO2_PINSTATE) >> 1) & 0x0f, (int *) arg)); + + case DIOIOC_WT_DOUT: + err = get_user(val, (int *) arg); + if (err) + return err; + mask = (val >> 16) & 0x0f; + val &= 0x0f; + au_writel ((val << 11) | (mask << 27), GPIO2_OUTPUT); + return 0; + case DIOIOC_RD_DOUT: + return (put_user((au_readl(GPIO2_PINSTATE) >> 11) & 0x0f, (int *) arg)); + default: + break; + } + return (-ENOIOCTLCMD); +} /* dio_ioctl() */ + +/*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ +static int +dio_open(struct inode *inode, struct file *file) +{ + switch (MINOR(inode->i_rdev)) { + case OMS400DIO_MINOR: +// MOD_INC_USE_COUNT; + return (0); + default: + return (-ENODEV); + } +} /* dio_open() */ + +/*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ +static int +dio_release(struct inode *inode, struct file *file) +{ + unsigned long flags; + DEFINE_SPINLOCK(driver_lock); + + DBGOFF(printk("[dio_release] ");) + if (MINOR(inode->i_rdev) == OMS400DIO_MINOR) { + DBGOFF(printk("by pid %u\n", current->pid);) + spin_lock_irqsave(&driver_lock, flags); + if (dio_wait_pid && (dio_wait_pid == current->pid)) { + dio_wait_pid = 0; + spin_unlock_irqrestore(&driver_lock, flags); + DBGOFF(printk("cleared\n");) + } else { + spin_unlock_irqrestore(&driver_lock, flags); + DBGOFF(if (dio_wait_pid) printk("dio_wait_pid %u, current->pid %u\n", dio_wait_pid, current->pid);) + } +// MOD_DEC_USE_COUNT; + } + return (0); +} /* dio_release() */ + +static void +dio_exit(void) +{ + misc_deregister(&dio_miscdev); +#ifdef CONFIG_OMS400_DIO_ENABLE_IRQ + free_irq(DIO_IRQ, NULL); +#endif +} /* cleanup_module() */ +module_init(dio_init); +module_exit(dio_exit); diff --git a/drivers/char/led_oms400.c b/drivers/char/led_oms400.c new file mode 100644 index 0000000..14285d9 --- /dev/null +++ b/drivers/char/led_oms400.c @@ -0,0 +1,147 @@ +/* + * FILE NAME au1000_gpio.c + * + * BRIEF MODULE DESCRIPTION + * Driver for Alchemy Au1000 GPIO. + * + * Author: MontaVista Software, Inc. + * Steve Longerbeam + * + * Copyright 2001 MontaVista Software 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VERSION "0.01" + +#define OMSLED_MINOR SEGLED_MINOR + +static int is_open = 0; + +/* + * Return the pin state. Pins configured as outputs will return + * the output state, and pins configured as inputs (tri-stated) + * will return input pin state. + */ +static int oms400led_in(u32 *val) +{ + *val = (inl(SYS_BASE + SYS_PINSTATERD) >> 6) & 0x07; + return 0; +} + +/* + * Set/clear GPIO pins. Only available GPIOs will be affected. + */ +static int oms400led_out(u32 data) +{ + int set, clr; + set = (data & 0x07) << 6; + clr = set ^ (0x07 << 6); + + if (set) + au_writel(set, (SYS_BASE + SYS_OUTPUTSET)); + if (clr) + au_writel(clr, (SYS_BASE + SYS_OUTPUTCLR)); + return 0; +} + +static int oms400led_open(struct inode *inode, struct file *file) +{ + is_open = 1; + return 0; +} + +static int oms400led_release(struct inode *inode, struct file *file) +{ + is_open = 0; + return 0; +} + +static ssize_t oms400led_write(struct file *file, const char *buf, size_t count, + loff_t *ppos) +{ + int err, i, led; + + if (count <= 0) + return 0; + + for (i = 0; i < count; i++) { + err = get_user(led, buf + i); + if (err) + return err; + if ((led < '0' ) || (led > '7')) + continue; + err = oms400led_out(led); + if (err) + return err; + } + return count; +} + +static struct file_operations oms400led_fops = +{ + .owner = THIS_MODULE, + .write = oms400led_write, + .open = oms400led_open, + .release = oms400led_release, +}; + + +static struct miscdevice oms400led_miscdev = +{ + OMSLED_MINOR, + "oms400 led", + &oms400led_fops +}; + +int __init oms400led_init(void) +{ + misc_register(&oms400led_miscdev); + printk("OMS-AL400 LED driver, version %s\n", VERSION); + return 0; +} + +void __exit oms400led_exit(void) +{ + misc_deregister(&oms400led_miscdev); +} + +module_init(oms400led_init); +module_exit(oms400led_exit); + +int obsled_out(int val) +{ + int err; + + err = oms400led_out(val & 0x07); + return err; +} diff --git a/drivers/char/pushsw_oms400.c b/drivers/char/pushsw_oms400.c new file mode 100644 index 0000000..83ac437 --- /dev/null +++ b/drivers/char/pushsw_oms400.c @@ -0,0 +1,192 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define USE_DIN + +#define DBGON(x) +#define DBGOFF(x) x + +#define PSW_VER "0.02" +#ifdef USE_DIN +#define PSW_IRQ AU1550_GPIO201_205_INT +#define DIO_MASK 2 +#define DIO_CHECKV 0 +#else +#define PSW_IRQ AU1550_GPIO15_INT +#endif + +/*---------------------------------------------------------------------------- + * Prototypes. + *----------------------------------------------------------------------------*/ +int psw_init(void); +irqreturn_t psw_isr(int irq, void *dev_id); +static int psw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static int psw_open(struct inode *inode, struct file *file); +static int psw_release(struct inode *inode, struct file *file); + +/*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ +static struct file_operations psw_fops = { + owner: THIS_MODULE, + unlocked_ioctl: psw_ioctl, + open: psw_open, + release: psw_release, +}; +static struct miscdevice psw_miscdev = + { PUSHSW_MINOR, "pushsw", &psw_fops }; +static DECLARE_WAIT_QUEUE_HEAD(psw_wait); + +/* used to allow only one process at a time to "own" the push switch */ +static pid_t psw_wait_pid = 0; +/*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ +int +psw_init(void) +{ + printk("Push switch driver v%s\n", PSW_VER); + + /* Install the push switch interrupt handler */ + if (request_irq(PSW_IRQ, psw_isr, IRQF_IRQPOLL, "push switch", NULL)) { + printk("[psw_open] interrupt %u not free\n", PSW_IRQ); + return (-EIO); + } + DBGOFF(printk("[psw_init] Push switch installed on interrupt %u\n", PSW_IRQ);) + misc_register(&psw_miscdev); + return (0); +} /* psw_init() */ + +/*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ +irqreturn_t +psw_isr(int irq, void *dev_id) +{ + /* DBGOFF(printk(KERN_CRIT "p");) */ + wake_up_interruptible(&psw_wait); + return IRQ_HANDLED; +} /* psw_isr() */ + +/*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ +static int +psw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned long flags; + DEFINE_SPINLOCK(driver_lock); + + if (MINOR(inode->i_rdev) != PUSHSW_MINOR) { + return (-ENODEV); + } + + switch (cmd) { + case PSWIOC_GETWAITPID: + return (put_user(psw_wait_pid, (int *) arg)); + case PSWIOC_WAITPUSH: + /* protect psw_wait_pid */ + spin_lock_irqsave(&driver_lock, flags); + if (psw_wait_pid == 0) { + psw_wait_pid = current->pid; + spin_unlock_irqrestore(&driver_lock, flags); + DBGOFF(printk("[psw_ioctl] PSWIOC_WAITPUSH pid %u\n", psw_wait_pid);) + /* block until switch pushed */ + while (1) { + interruptible_sleep_on(&psw_wait); +#ifdef USE_DIN + msleep(5); + if ((au_readl(GPIO2_PINSTATE) & DIO_MASK) == DIO_CHECKV) +#endif + break; + } + spin_lock_irqsave(&driver_lock, flags); + psw_wait_pid = 0; + spin_unlock_irqrestore(&driver_lock, flags); + + DBGOFF(printk("[psw_ioctl] unblocked\n");) + if (signal_pending(current)) { + DBGOFF(printk("[psw_ioctl] sig\n");) + return (-ERESTARTSYS); + } + return (0); + } else { + spin_unlock_irqrestore(&driver_lock, flags); + return (-EBUSY); + } + default: + break; + } + return (-ENOIOCTLCMD); +} /* psw_ioctl() */ + +/*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ +static int +psw_open(struct inode *inode, struct file *file) +{ + switch (MINOR(inode->i_rdev)) { + case PUSHSW_MINOR: +// MOD_INC_USE_COUNT; + return (0); + default: + return (-ENODEV); + } +} /* psw_open() */ + +/*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ +static int +psw_release(struct inode *inode, struct file *file) +{ + unsigned long flags; + DEFINE_SPINLOCK(driver_lock); + + DBGOFF(printk("[psw_release] ");) + if (MINOR(inode->i_rdev) == PUSHSW_MINOR) { + DBGOFF(printk("by pid %u\n", current->pid);) + spin_lock_irqsave(&driver_lock, flags); + if (psw_wait_pid && (psw_wait_pid == current->pid)) { + psw_wait_pid = 0; + spin_unlock_irqrestore(&driver_lock, flags); + DBGOFF(printk("cleared\n");) + } else { + spin_unlock_irqrestore(&driver_lock, flags); + DBGOFF(if (psw_wait_pid) printk("psw_wait_pid %u, current->pid %u\n", psw_wait_pid, current->pid);) + } +// MOD_DEC_USE_COUNT; + } + return (0); +} /* psw_release() */ + +static void +psw_exit(void) +{ + misc_deregister(&psw_miscdev); + free_irq(PSW_IRQ, NULL); +} /* cleanup_module() */ +module_init(psw_init); +module_exit(psw_exit); diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c index f314d7f..c1bb37d 100644 --- a/drivers/i2c/busses/i2c-au1550.c +++ b/drivers/i2c/busses/i2c-au1550.c @@ -347,6 +347,7 @@ i2c_au1550_probe(struct platform_device *pdev) priv->xfer_timeout = 200; priv->adap.nr = pdev->id; + priv->adap.class = I2C_CLASS_HWMON; priv->adap.algo = &au1550_algo; priv->adap.algo_data = priv; priv->adap.dev.parent = &pdev->dev; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 5664696..82e39c9 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -344,6 +344,18 @@ config ISL29020 This driver can also be built as a module. If so, the module will be called isl29020. +config OMS400_EEPROM + tristate "OMS400_EEPROM" + depends on I2C && MIPS_OMS400 + help + OMS-AL400/128 EEPROM driver. + +config OMS400_RTC + tristate "OMS400_RTC" + depends on I2C && MIPS_OMS400 + help + OMS-AL400/128 RTC driver. + config SENSORS_TSL2550 tristate "Taos TSL2550 ambient light sensor" depends on I2C && SYSFS diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index b26495a..fd47798 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -30,6 +30,8 @@ obj-$(CONFIG_APDS9802ALS) += apds9802als.o obj-$(CONFIG_ISL29003) += isl29003.o obj-$(CONFIG_ISL29020) += isl29020.o obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o +obj-$(CONFIG_OMS400_EEPROM) += eeprom-oms400.o +obj-$(CONFIG_OMS400_RTC) += r2025x-rtc.o obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o obj-$(CONFIG_DS1682) += ds1682.o obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o diff --git a/drivers/misc/eeprom-oms400.c b/drivers/misc/eeprom-oms400.c new file mode 100644 index 0000000..48029bc --- /dev/null +++ b/drivers/misc/eeprom-oms400.c @@ -0,0 +1,463 @@ +/* + * linux/drivers/misc/eeprom-oms400.c.c + * + * + * Copyright + * Author: 2002 AXE Inc. + * takawata@axe-inc.co.jp + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * TODO: + * - implement alarm and periodic IRQ support. + * + */ +/* + * Based On + * linux/drivers/char/x1226-rtc.c + * + * I2C Real Time Clock Client Driver for Xicor X1226 RTC/Calendar + * + * Copyright 2002 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * stevel@mvista.com or source@mvista.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. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * TODO: + * - implement alarm and periodic IRQ support. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EEPROM_MAJOR 240 +#define EEPROM_T_WR 10 +struct eepromi2c_private +{ + u8 ei2_addr; + int ei2_size; + int ei2_maxpage; + int use_count; + unsigned char *tmpbuf; + struct i2c_client *ei2_i2c; +}; + +static DEFINE_SPINLOCK(eeprom_state_lock); + +struct eepromi2c_private eepromi2c_conf[]= +{ + {0x50, 0x200, 16, 0, NULL, NULL, NULL}, +}; + +#define MAXEEPROMDEVS (sizeof(eepromi2c_conf)/ sizeof(struct eepromi2c_private)) +#ifndef I2C_M_WR +#define I2C_M_WR 0x0 +#endif + +#ifdef DEBUG_I2CEEPROM +#define dbg(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__, ## args) +#else +#define dbg(fmt, args...) +#endif + +#define I2CEEPROM_MODULE_NAME "LARGEEEPROM" +#define PFX I2CEEPROM_MODULE_NAME + +#define err(format, arg...) printk(KERN_ERR PFX ": " format , ## arg) +#define info(format, arg...) printk(KERN_INFO PFX ": " format , ## arg) +#define warn(format, arg...) printk(KERN_WARNING PFX ": " format , ## arg) +#define emerg(format, arg...) printk(KERN_EMERG PFX ": " format , ## arg) + +//yamamoto static struct i2c_driver i2ceeprom_driver; + +static int i2ceeprom_read(struct i2c_client *client, + u16 reg_offset, u8 *buf, int len) +{ + int ret; + u8 regbuf = reg_offset; + struct i2c_msg random_addr_read[2] = { + { + /* "Set Current Address" */ + client->addr, + client->flags | I2C_M_WR, + 1, + ®buf + }, + { + /* "Sequential Read" if len>1, + "Current Address Read" if len=1 */ + client->addr , + client->flags| I2C_M_RD , + len, + buf + } + }; + + random_addr_read[0].addr |= (reg_offset >> 8) &0x07;; + random_addr_read[1].addr |= (reg_offset >> 8) &0x07;; + + dbg("i2c_transfer %04x %04x\n",random_addr_read[0].addr,regbuf); + + if ((ret = i2c_transfer(client->adapter, random_addr_read, 2)) != 2) { + ret = -ENXIO; + dbg("i2c_transfer failed\n"); + } + + return ret; +} + +static int i2ceeprom_write(struct i2c_client *client, + u16 reg_offset, u8 *buf, int len) +{ + int ret; + u8* local_buf; + struct i2c_msg page_write = { + client->addr, + client->flags , + len + 1, + NULL + }; + + if ((local_buf = (u8*)kmalloc(len + 1, GFP_KERNEL)) == NULL) { + err("buffer alloc failed\n"); + return -ENOMEM; + } + + local_buf[0] = reg_offset; + memcpy(local_buf + 1, buf, len); + page_write.buf = local_buf; + + page_write.addr |= (reg_offset >> 8) &0x07; + dbg("i2c_transfer %04x %04x\n",page_write.addr,regbuf); + + if ((ret = i2c_transfer(client->adapter, &page_write, 1)) != 1) { + ret = -ENXIO; + dbg("i2c_transfer failed\n"); + } + + msleep(EEPROM_T_WR); + kfree(local_buf); + return ret; +} + +static long long eepromi2c_llseek(struct file *file, loff_t offset, int origin) +{ + int minor; + struct inode *minode = file->f_dentry->d_inode; + struct eepromi2c_private *pri; + + if ((minor = MINOR(minode->i_rdev)) >= MAXEEPROMDEVS) + return -ENXIO; + pri = &eepromi2c_conf[minor]; + switch (origin) { + case 0: + file->f_pos = offset; + return file->f_pos; + case 1: + file->f_pos += offset; + return file->f_pos; + case 2: + file->f_pos = pri->ei2_size - offset; + return file->f_pos; + default: + return -EINVAL; + } +} + +static ssize_t eepromi2c_read(struct file *file, char *buf, size_t count, + loff_t *ppos) +{ + int minor; + struct i2c_client *client; + struct eepromi2c_private *pri; + int offset, remaining, copysize; + struct inode *minode = file->f_dentry->d_inode; + if ((minor = MINOR(minode->i_rdev)) >= MAXEEPROMDEVS) + return -ENXIO; + pri = &eepromi2c_conf[minor]; + if (!(client = pri->ei2_i2c)) + return -ENXIO; + offset = *ppos; + offset += 16; + if ((offset + count) > pri->ei2_size) + count = pri->ei2_size - offset; + if (count <= 0) { + return 0; + } + remaining = count; + do { + copysize = (remaining > pri->ei2_maxpage) + ? pri->ei2_maxpage : remaining; + dbg("; copysize=%d\n", copysize); + i2ceeprom_read(client, offset, pri->tmpbuf, copysize); + if (copy_to_user(buf, pri->tmpbuf, copysize)) + return -EFAULT; + *ppos += copysize; + offset += copysize; + buf += copysize; + remaining -= copysize; + } while (remaining > 0); + return count; +} + +static ssize_t eepromi2c_write(struct file *file, const char *buf, size_t count, + loff_t *ppos) +{ + int minor; + struct i2c_client *client; + struct eepromi2c_private *pri; + int offset, remaining, copysize; + struct inode *minode = file->f_dentry->d_inode; + if ((minor = MINOR(minode->i_rdev)) >= MAXEEPROMDEVS) + return -ENXIO; + pri = &eepromi2c_conf[minor]; + if (!(client = pri->ei2_i2c)) + return -ENXIO; + offset = *ppos; + offset += 16; + if ((offset + count) > pri->ei2_size) + count = pri->ei2_size - offset; + if (count <= 0) { + return 0; + } + /*Write regeon should be aligned */ + copysize = (count > pri->ei2_maxpage) ? pri->ei2_maxpage : count; + if ((offset / pri->ei2_maxpage) != + ((offset + copysize) / pri->ei2_maxpage)) + copysize = pri->ei2_maxpage - (offset % pri->ei2_maxpage); + dbg("; offset=%d\n", offset); + remaining = count; + do { + dbg("; copysize=%d\n", copysize); + if (copy_from_user(pri->tmpbuf, buf, copysize)) { + return -EFAULT; + } + + i2ceeprom_write(client, offset, pri->tmpbuf, copysize); + *ppos += copysize; + offset += copysize; + buf += copysize; + remaining -= copysize; + copysize = (remaining > pri->ei2_maxpage) + ? pri->ei2_maxpage : remaining; + } while (remaining > 0); + return count; +} + +static int eepromi2c_open(struct inode *minode, struct file *mfile) +{ + int minor; + spin_lock(&eeprom_state_lock); + if ((minor = MINOR(minode->i_rdev)) >= MAXEEPROMDEVS) + return -ENXIO; + if (!eepromi2c_conf[minor].ei2_i2c) + return -ENXIO; + + if (eepromi2c_conf[minor].use_count) + return -EBUSY; + eepromi2c_conf[minor].use_count++; + spin_unlock(&eeprom_state_lock); + return 0; +} + +static int eepromi2c_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return -ENOTTY; +} + +static int eepromi2c_release(struct inode *inode, struct file *file) +{ + int minor; + spin_lock(&eeprom_state_lock); + if ((minor = MINOR(inode->i_rdev)) >= MAXEEPROMDEVS) + return -ENXIO; + eepromi2c_conf[minor].use_count--; + spin_unlock(&eeprom_state_lock); + return 0; +} + +static struct file_operations eepromi2c_fops = { + owner: THIS_MODULE, + llseek: eepromi2c_llseek, + read: eepromi2c_read, + write: eepromi2c_write, + unlocked_ioctl: eepromi2c_ioctl, + open: eepromi2c_open, + release: eepromi2c_release, +}; + +//yamamoto --> +//yamamoto static int i2ceeprom_probe(struct i2c_adapter *adap) +static int i2ceeprom_probe(struct i2c_client *client, const struct i2c_device_id *id) +//yamamoto <-- +{ + int res, i; + int ret = 1; +#if 0 + char nbuffer[15]; +#endif + unsigned char stat; + struct i2c_client *this_client; + + res = -ENXIO; + register_chrdev(EEPROM_MAJOR, "eeprom", &eepromi2c_fops); + + this_client = kmalloc(sizeof(*this_client), GFP_KERNEL); + + for (i = 0; i < MAXEEPROMDEVS; i++) { + if (this_client == NULL) { + break; + } + + memset(this_client, 0, sizeof(*this_client)); + +//yamamoto --> + this_client = client; +//yamamoto <-- + +//yamamoto strcpy(this_client->name, I2CEEPROM_MODULE_NAME); +//yamamoto this_client->flags = 0; +//yamamoto this_client->addr = eepromi2c_conf[i].ei2_addr; +//yamamoto this_client->adapter = adap; +//yamamoto this_client->driver = &i2ceeprom_driver; + + if ((res = i2ceeprom_read(this_client, 0, &stat, 1)) < 0) { + printk("Probe read %d\n", res); + continue; + } + + if ((eepromi2c_conf[i].tmpbuf = + kmalloc(eepromi2c_conf[i].ei2_size, GFP_KERNEL)) == NULL) { + continue; + } + + printk("Serial EEPROM FOUND at %x\n", this_client->addr); +//yamamoto if (i2c_attach_client(this_client)) { +//yamamoto continue; +//yamamoto } + eepromi2c_conf[i].ei2_i2c = this_client; + ret = 0; /*At least 1 dev found */ + this_client = kmalloc(sizeof(*this_client), GFP_KERNEL); + } + kfree(this_client); + return ret; +} + +//yamamoto --> +//yamamoto static int i2ceeprom_detach(struct i2c_client *client) +static int i2ceeprom_remove(struct i2c_client *client) +//yamamoto <-- +{ +//yamamoto i2c_detach_client(client); + + kfree(client); + + return 0; +} + +static int i2ceeprom_command(struct i2c_client *client, unsigned int cmd, + void *arg) +{ + + return -EINVAL; +} + +//yamamoto --> +static struct i2c_device_id i2ceeprom_idtable[] = { + { "i2ceeprom", 0 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, i2ceeprom_idtable); +//yamamoto <-- + +static struct i2c_driver i2ceeprom_driver = { + .driver = { + .name = I2CEEPROM_MODULE_NAME, + }, +//yamamoto --> + .id_table = i2ceeprom_idtable, + .probe = i2ceeprom_probe, + .remove = __devexit_p(i2ceeprom_remove), +//yamamoto .id = I2C_DRIVERID_LARGEEEPROM, +//yamamoto .attach_adapter = i2ceeprom_probe, +//yamamoto .detach_client = i2ceeprom_detach, +//yamamoto <-- + .command = i2ceeprom_command +}; + + +static __init int i2ceeprom_init(void) +{ + int ret; + + info("I2C based EEPROM driver.\n"); + ret = i2c_add_driver(&i2ceeprom_driver); + if (ret) { + err("Register I2C driver failed, errno is %d\n", ret); + return ret; + } + return 0; +} + +static void __exit i2ceeprom_exit(void) +{ + i2c_del_driver(&i2ceeprom_driver); +} + +module_init(i2ceeprom_init); +module_exit(i2ceeprom_exit); diff --git a/drivers/misc/r2025x-rtc.c b/drivers/misc/r2025x-rtc.c new file mode 100644 index 0000000..80439dd --- /dev/null +++ b/drivers/misc/r2025x-rtc.c @@ -0,0 +1,506 @@ +/* + * linux/drivers/misc/r2025x-rtc.c + * + * I2C Real Time Clock Client Driver for Xicor R2025x RTC/Calendar + * + * Copyright 2002 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * stevel@mvista.com or source@mvista.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. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * TODO: + * - implement alarm and periodic IRQ support. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG_R2025x +#define dbg(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__, ## args) +#else +#define dbg(fmt, args...) +#endif + +#define R2025x_MODULE_NAME "R2025x" +#define PFX R2025x_MODULE_NAME + +#define err(format, arg...) printk(KERN_ERR PFX ": " format , ## arg) +#define info(format, arg...) printk(KERN_INFO PFX ": " format , ## arg) +#define warn(format, arg...) printk(KERN_WARNING PFX ": " format , ## arg) +#define emerg(format, arg...) printk(KERN_EMERG PFX ": " format , ## arg) + + +#define R2025x_RTC_SR 0x3f +#define RTC_SR_RTCF (1) +#define RTC_SR_WEL (1<<1) +#define RTC_SR_RWEL (1<<2) + +#define R2025x_RTC_BASE 0x00 + +/* This is an image of the RTC registers starting at offset 0x30 */ +struct rtc_registers { + unsigned char secs; // 00 + unsigned char mins; // 01 + unsigned char hours; // 02 + unsigned char dayofweek;// 03 + unsigned char day; // 04 + unsigned char mon; // 05 + unsigned char year; // 06 + unsigned char adjust; // 07 + unsigned char almwmin; // 08 + unsigned char almwhours;// 09 + unsigned char almwdow; // 0a + unsigned char almdmin; // 0b + unsigned char almdhours;// 0c + unsigned char dummy; // 0d + unsigned char ctrl1; // 0e + unsigned char ctrl2; // 0f +}; + +#define RTC_ACCESS_WAIT 100 +#define DEVID_RTC 0x32 +#define SLAVE_READ 0x01 +#ifndef I2C_M_WR +#define I2C_M_WR 0x0 +#endif + +//yamamoto static struct i2c_driver r2025x_driver; + +static int r2025x_use_count = 0; + +static struct i2c_client *this_client = NULL; + +static int rtc_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data); + +static int r2025x_read (struct i2c_client *client, + u8 reg_offset, u8* buf, int len) +{ + u8* local_buf; + int ret; + struct i2c_msg random_addr_read; + + if (reg_offset > 15) + return -EINVAL; + if (reg_offset + len > 16) + return -EINVAL; + + if ((local_buf = (u8*)kmalloc(sizeof(struct rtc_registers) + 1, + GFP_KERNEL)) == NULL) { + err("buffer alloc failed\n"); + return -ENOMEM; + } + + random_addr_read.addr = client->addr; + random_addr_read.flags = client->flags| I2C_M_RD; + random_addr_read.len = 16; + random_addr_read.buf = local_buf; + + if ((ret = i2c_transfer(client->adapter, &random_addr_read, 1)) != 1) { + dbg("i2c_transfer failed %08x\n",ret); + ret = -ENXIO; + } + + local_buf[16] = local_buf[0]; + memcpy(buf, local_buf + 1 + reg_offset, len); + + kfree(local_buf); + udelay(RTC_ACCESS_WAIT); + return ret; +} + +static int r2025x_write (struct i2c_client *client, + u8 reg_offset, u8* buf, int len) +{ + int ret; + u8* local_buf; + struct i2c_msg page_write = { + client->addr, + client->flags , + len, + NULL + }; + + if (reg_offset > 15) + return -EINVAL; + if (reg_offset + len > 16) + return -EINVAL; + + if ((local_buf = (u8*)kmalloc(len + 1, + GFP_KERNEL)) == NULL) { + err("buffer alloc failed\n"); + return -ENOMEM; + } + + local_buf[0] = reg_offset; + memcpy(local_buf + 1, buf, len); + page_write.buf = local_buf; + + if ((ret = i2c_transfer(client->adapter, &page_write, 1)) != 1) { + ret = -ENXIO; + dbg("i2c_transfer failed\n"); + } + + kfree(local_buf); + udelay(RTC_ACCESS_WAIT); + return ret; +} + +static int +r2025x_get_time(struct i2c_client *client, struct rtc_time *tm) +{ + struct rtc_registers rtc; + int ret; + + /* read RTC registers */ + if ((ret = r2025x_read(client, R2025x_RTC_BASE, (u8*)&rtc, + sizeof(struct rtc_registers))) < 0) { + dbg("couldn't read RTC\n"); + return ret; + } + dbg("IN: year=%02x, mon=%02x, day=%02x, hour=%02x, " + "min=%02x, sec=%02x\n", + rtc.year, rtc.mon, rtc.day, rtc.hours, + rtc.mins, rtc.secs); + + tm->tm_year = ((rtc.year >>4 ) & 0xf) *10 + (rtc.year & 0x0f); + if (rtc.mon & 0x80) + tm->tm_year += 100; + tm->tm_mon = ((rtc.mon >>4 ) & 0x1) *10 + (rtc.mon & 0x0f); + tm->tm_mon--; /* tm_mon is 0 to 11 */ + tm->tm_mday = ((rtc.day >>4 ) & 0x3) *10 + (rtc.day & 0x0f); + tm->tm_hour = ((rtc.hours >>4 ) & 0x7) *10 + (rtc.hours & 0x0f); + if ((rtc.ctrl1 & 0x20) == 0) { + tm->tm_hour = ((rtc.hours >>4 ) & 0x1) *10 + (rtc.hours & 0x0f); + if (rtc.hours & 0x20) + tm->tm_hour += 12; + } else { + tm->tm_hour = ((rtc.hours >>4 ) & 0x3) *10 + (rtc.hours & 0x0f); + } + tm->tm_min = ((rtc.mins >>4 ) & 0x7) *10 + (rtc.mins & 0x0f); + tm->tm_sec = ((rtc.secs >>4 ) & 0x7) *10 + (rtc.secs & 0x0f); + + dbg("OUT: year=%d, mon=%d, day=%d, hour=%d, min=%d, sec=%d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, + tm->tm_min, tm->tm_sec); + + return 0; +} + +static int +r2025x_set_time(struct i2c_client *client, const struct rtc_time *tm) +{ + struct rtc_registers rtc; + int ret; + int tmpy; + + dbg("IN: year=%d, mon=%d, day=%d, hour=%d, min=%d, sec=%d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, + tm->tm_min, tm->tm_sec); + + tmpy = tm->tm_year % 100; + + rtc.year = (((tmpy / 10) << 4) | (tmpy % 10)); + rtc.mon = ((((tm->tm_mon + 1) / 10) << 4) | ((tm->tm_mon + 1) % 10)) & 0x3f; + if (tm->tm_year >= 100) + rtc.mon |= 0x80; + rtc.day = (((tm->tm_mday / 10) << 4) | (tm->tm_mday % 10)) & 0x3f; + rtc.dayofweek = 0; // ignore day of week + rtc.hours = (((tm->tm_hour / 10) << 4) | (tm->tm_hour % 10)) & 0x3f; + rtc.mins = (((tm->tm_min / 10) << 4) | (tm->tm_min % 10)) & 0x7f; + rtc.secs = (((tm->tm_sec / 10) << 4) | (tm->tm_sec % 10)) & 0x7f; + + dbg("OUT: year=%02x, mon=%02x, day=%02x, hour=%02x, " + "min=%02x, sec=%02x\n", + rtc.year, rtc.mon, rtc.day, rtc.hours, + rtc.mins, rtc.secs); + + /* write RTC registers */ + if ((ret = r2025x_write(client, R2025x_RTC_BASE, (u8*)&rtc, 8)) < 0) { + dbg("couldn't write RTC\n"); + return ret; + } + + return 0; +} + +//yamamoto --> +//yamamoto static int +//yamamoto r2025x_probe(struct i2c_adapter *adap) +static int r2025x_probe(struct i2c_client *client, const struct i2c_device_id *id) +//yamamoto <-- +{ + int ret; + struct rtc_registers rtc; + + if (this_client != NULL) + return -EBUSY; + + this_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (this_client == NULL) { + return -ENOMEM; + } + + memset(this_client, 0, sizeof(struct i2c_client)); + +//yamamoto --> + this_client = client; +//yamamoto <-- + +//yamamoto strcpy(this_client->name, R2025x_MODULE_NAME); +//yamamoto this_client->flags = 0; +//yamamoto this_client->addr = DEVID_RTC; +//yamamoto this_client->adapter = adap; +//yamamoto this_client->driver = &r2025x_driver; + + /* + * use r2025x_get_time() to probe for an R2025x on this bus. + */ + dbg("r2025x_probe Entry %08x\n",(u32)this_client); + if((ret = r2025x_read(this_client,R2025x_RTC_BASE, (u8 *)&rtc, + sizeof(struct rtc_registers)))< 0){ + dbg("r2025x_probe r2025x_read error\n"); + kfree(this_client); + this_client = NULL; + return ret; + } + +//yamamoto info("found R2025x on %s\n", adap->name); + +//yamamoto --> +//yamamoto /* attach it. */ +//yamamoto dbg("r2025x_probe i2c_attach_client call\n"); +//yamamoto ret = i2c_attach_client(this_client); +//yamamoto dbg("r2025x_probe i2c_attach_client call ret=%d\n",ret); +//yamamoto <-- + return ret; +} + +//yamamoto --> +//yamamoto static int +//yamamoto r2025x_detach(struct i2c_client *client) +static int r2025x_remove(struct i2c_client *client) +//yamamoto <-- +{ +//yamamoto i2c_detach_client(client); + + if (this_client != NULL) { + kfree(this_client); + this_client = NULL; + } + + return 0; +} + +int rtc_open(struct inode *minode, struct file *mfile) +{ + /*if(MOD_IN_USE)*/ + if(r2025x_use_count > 0) { + return -EBUSY; + } +// MOD_INC_USE_COUNT; + ++r2025x_use_count; + return 0; +} + +int rtc_release(struct inode *minode, struct file *mfile) +{ +// MOD_DEC_USE_COUNT; + --r2025x_use_count; + return 0; +} + +static loff_t rtc_llseek(struct file *mfile, loff_t offset, int origint) +{ + return -ESPIPE; +} + +static int +r2025x_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + return -EINVAL; +} + +static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct rtc_time rtc_tm; + int ret; + + switch (cmd) { + case RTC_RD_TIME: /* Read the time/date from RTC */ + if ((ret = r2025x_get_time(this_client, &rtc_tm)) < 0) + return ret; + return copy_to_user((void *)arg, &rtc_tm, sizeof(rtc_tm)) ? + -EFAULT : 0; + case RTC_SET_TIME: /* Set the RTC */ + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + if (copy_from_user(&rtc_tm, + (struct rtc_time *) arg, + sizeof(struct rtc_time))) + return -EFAULT; + + return r2025x_set_time(this_client, &rtc_tm); + default: + return -EINVAL; + } +} + +//yamamoto --> +static struct i2c_device_id r2025x_idtable[] = { + { "r2025x", 0 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, r2025x_idtable); +//yamamoto <-- + +static struct i2c_driver r2025x_driver = { + .driver = { + .name = R2025x_MODULE_NAME, + }, +//yamamoto --> + .id_table = r2025x_idtable, + .probe = r2025x_probe, + .remove = __devexit_p(r2025x_remove), +//yamamoto .id = I2C_DRIVERID_R2025x, +//yamamoto .attach_adapter = r2025x_probe, +//yamamoto .detach_client = r2025x_detach, +//yamamoto <-- + .command = r2025x_command +}; + +static struct file_operations rtc_fops = { + owner: THIS_MODULE, + llseek: rtc_llseek, + unlocked_ioctl: rtc_ioctl, + open: rtc_open, + release: rtc_release, +}; + +static struct miscdevice r2025xrtc_miscdev = { + RTC_MINOR, + "rtc", + &rtc_fops +}; + +static __init int r2025x_init(void) +{ + int ret; + + info("I2C based RTC driver.\n"); + ret = i2c_add_driver(&r2025x_driver); + dbg("r2025x_init i2c_add_driver call ret=%d\n",ret); + if (ret) { + err("Register I2C driver failed, errno is %d\n", ret); + return ret; + } + dbg("r2025x_init misc_register call\n"); + ret = misc_register(&r2025xrtc_miscdev); + dbg("r2025x_init misc_register call ret=%d\n",ret); + if (ret) { + err("Register misc driver failed, errno is %d\n", ret); + i2c_del_driver(&r2025x_driver); + return ret; + } + + create_proc_read_entry("driver/rtc", 0, 0, rtc_read_proc, NULL); + dbg("r2025x_init Success\n"); + return 0; +} + +static void __exit r2025x_exit(void) +{ + remove_proc_entry("driver/rtc", NULL); + misc_deregister(&r2025xrtc_miscdev); + i2c_del_driver(&r2025x_driver); +} + + +module_init(r2025x_init); +module_exit(r2025x_exit); + +/* + * Info exported via "/proc/driver/rtc". + */ + +static int rtc_proc_output(char *buf) +{ + char *p; + struct rtc_time tm; + int ret; + + if ((ret = r2025x_get_time(this_client, &tm)) < 0) + return ret; + + p = buf; + + /* + * There is no way to tell if the luser has the RTC set for local + * time or for Universal Standard Time (GMT). Probably local though. + */ + p += sprintf(p, + "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, + tm.tm_mday); + + return p - buf; +} + +static int rtc_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = rtc_proc_output(page); + if (len <= off + count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +MODULE_AUTHOR("Steve Longerbeam"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c index 6f6e8b6..9b3b7b1 100644 --- a/drivers/net/phy/lxt.c +++ b/drivers/net/phy/lxt.c @@ -99,6 +99,16 @@ static int lxt970_config_init(struct phy_device *phydev) return err; } +#ifdef CONFIG_MIPS_OMS400 +#define MII_LXT971A_CFG 16 /* PHY Configuration Register */ +static int lxt971_config_init(struct phy_device *phydev) +{ + int err; + + err = phy_write(phydev, MII_LXT971A_CFG, 0x0180); + return err; +} +#endif static int lxt971_ack_interrupt(struct phy_device *phydev) { @@ -169,6 +179,9 @@ static struct phy_driver lxt971_driver = { .phy_id_mask = 0xfffffff0, .features = PHY_BASIC_FEATURES, .flags = PHY_HAS_INTERRUPT, +#ifdef CONFIG_MIPS_OMS400 + .config_init = lxt971_config_init, +#endif .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, .ack_interrupt = lxt971_ack_interrupt, diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c index 3e49df6..408cea2 100644 --- a/drivers/pcmcia/db1xxx_ss.c +++ b/drivers/pcmcia/db1xxx_ss.c @@ -413,6 +413,7 @@ static int __devinit db1x_pcmcia_socket_probe(struct platform_device *pdev) case BCSR_WHOAMI_PB1100: sock->board_type = BOARD_TYPE_PB1100; break; + case BCSR_WHOAMI_OMS400: case BCSR_WHOAMI_DB1000 ... BCSR_WHOAMI_PB1550_SDR: sock->board_type = BOARD_TYPE_DEFAULT; break; diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index 33601f8..520b43b 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c @@ -91,7 +91,11 @@ static unsigned int skip_txen_test; /* force skip of txen test at init time */ * machine types want others as well - they're free * to redefine this in their header file. */ +#if defined(CONFIG_MIPS_OMS400) +#define is_real_interrupt(irq) ((irq) < 0x100) +#else #define is_real_interrupt(irq) ((irq) != 0) +#endif #ifdef CONFIG_SERIAL_8250_DETECT_IRQ #define CONFIG_SERIAL_DETECT_IRQ 1 diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index b65912d..13be77f 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -362,7 +362,13 @@ struct ehci_qh { * memory that is cache-inhibited (i.e. being used for DMA). * Spinlocks are used to protect all QH fields. */ +#ifdef CONFIG_MIPS_OMS400 + u8 __isolete_cache_1[1024]; u32 refcount; + u8 __isolate_cashe_2[1024]; +#else + u32 refcount; +#endif unsigned stamp; u8 needs_rescan; /* Dequeue during giveback */ diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 84458b0..bdaf3f2 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -131,6 +131,13 @@ extern void warn_slowpath_null(const char *file, const int line); #define WARN_TAINT(condition, taint, format...) WARN_ON(condition) +#ifndef WARN_RATELIMIT +#define WARN_RATELIMIT(condition, format...) ({ \ + int __ret_warn_on = !!(condition); \ + unlikely(__ret_warn_on); \ +}) +#endif + #endif #define WARN_ON_ONCE(condition) ({ \ diff --git a/include/asm-generic/int-ll64.h b/include/asm-generic/int-ll64.h index f394147..bb29a8b 100644 --- a/include/asm-generic/int-ll64.h +++ b/include/asm-generic/int-ll64.h @@ -25,13 +25,13 @@ typedef unsigned short __u16; typedef __signed__ int __s32; typedef unsigned int __u32; -#ifdef __GNUC__ +//#ifdef __GNUC__ __extension__ typedef __signed__ long long __s64; __extension__ typedef unsigned long long __u64; -#else -typedef __signed__ long long __s64; -typedef unsigned long long __u64; -#endif +//#else +//typedef __signed__ long long __s64; +//typedef unsigned long long __u64; +//#endif #endif /* __ASSEMBLY__ */ diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index c41d727..f829aa3 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -1,5 +1,11 @@ #ifndef _LINUX_MISCDEVICE_H #define _LINUX_MISCDEVICE_H + +/* + PlatHome + - Added PUSHSW_MINOR, SEGLED_MINOR for OpenBlockS +*/ + #include #include #include @@ -29,6 +35,10 @@ #define SGI_MMTIMER 153 #define STORE_QUEUE_MINOR 155 #define I2O_MINOR 166 +#define PUSHSW_MINOR 170 +#define SEGLED_MINOR 171 +#define OMS400TEMP_MINOR 172 +#define OMS400DIO_MINOR 173 #define MICROCODE_MINOR 184 #define TUN_MINOR 200 #define MWAVE_MINOR 219 /* ACP/Mwave Modem */ diff --git a/init/do_mounts.c b/init/do_mounts.c index d6c229f..82fe6b9 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -152,6 +152,17 @@ done: } #endif +#if defined(CONFIG_MIPS_OMS400) +int __initdata no_flashcfg; + +static int __init exec_flashcfg(char * str) +{ + no_flashcfg = simple_strtoul(str,NULL,0); + return 1; +} +__setup("noflashcfg=", exec_flashcfg); +#endif + /* * Convert a name into device number. We accept the following variants: * @@ -503,6 +514,10 @@ void __init prepare_namespace(void) { int is_floppy; +#if defined(CONFIG_MIPS_OMS400) + int real_root_mountflags = root_mountflags; +#endif + if (root_delay) { printk(KERN_INFO "Waiting %dsec before mounting root device...\n", root_delay); @@ -550,9 +565,33 @@ void __init prepare_namespace(void) if (is_floppy && rd_doload && rd_load_disk(0)) ROOT_DEV = Root_RAM0; +#if defined(CONFIG_MIPS_OMS400) + /* write able root mount if load user configuration from flash necessary. */ + if ((no_flashcfg == 0) && mount_initrd) { + root_mountflags &= ~MS_RDONLY; + } +#endif + mount_root(); out: devtmpfs_mount("dev"); sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot((const char __user __force *)"."); +#if defined(CONFIG_MIPS_OMS400) + if ((no_flashcfg == 0) && mount_initrd) { + root_mountflags = real_root_mountflags; + printk("[prepare_namespace] Executing flashcfg...\n"); + if ((MAJOR(ROOT_DEV) == RAMDISK_MAJOR) && (MINOR(ROOT_DEV) == 0)) { + int pid,i; + pid = kernel_thread(do_restore, "/usr/sbin/flashcfg", SIGCHLD); + if (pid > 0) { + while (pid != sys_wait4(-1, &i, 0, NULL)) + yield(); + } + else + printk("[prepare_namespace] Error starting restore thread!\n"); + } + printk("[prepare_namespace] Finished executing flashcfg\n"); + } +#endif } diff --git a/init/do_mounts.h b/init/do_mounts.h index f5b978a..884f516 100644 --- a/init/do_mounts.h +++ b/init/do_mounts.h @@ -55,6 +55,8 @@ static inline int rd_load_image(char *from) { return 0; } #endif +extern int __initdata mount_initrd; + #ifdef CONFIG_BLK_DEV_INITRD int __init initrd_load(void); @@ -74,3 +76,7 @@ void md_run_setup(void); static inline void md_run_setup(void) {} #endif + +#if defined(CONFIG_MIPS_OMS400) +int __init do_restore(void *shell); +#endif diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c index 3098a38..82ff0f4 100644 --- a/init/do_mounts_initrd.c +++ b/init/do_mounts_initrd.c @@ -10,11 +10,20 @@ #include "do_mounts.h" +/* + ozawa CONFIG_OBSS + PlatHome + - Added do_restore() + - write able root mount if load user configuration + in prepare_namespace() + - Added for CONFIG_MIPS_OMS400 +*/ + unsigned long initrd_start, initrd_end; int initrd_below_start_ok; unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */ static int __initdata old_fd, root_fd; -static int __initdata mount_initrd = 1; +int __initdata mount_initrd = 1; static int __init no_initrd(char *str) { @@ -124,3 +133,23 @@ int __init initrd_load(void) sys_unlink("/initrd.image"); return 0; } + +#if defined(CONFIG_MIPS_OMS400) +int __init do_restore(void *shell) +{ + static char *argv[] = { "flashcfg", + "-x", + NULL, }; + extern const char *envp_init[]; + + sys_close(old_fd);sys_close(root_fd); + sys_close(0);sys_close(1);sys_close(2); + sys_setsid(); + (void) sys_open("/dev/console",O_RDWR,0); + (void) sys_dup(0); + (void) sys_dup(0); + kernel_execve(shell, argv, envp_init); + printk("[do_restore] Error starting restore thread!\n"); + return (-1); +} +#endif diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index 887629e..a9a7e93 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -1,3 +1,11 @@ +/* + ozawa CONFIG_OBSS + PlatHome + - Added do_restore() + - write able root mount if load user configuration + in prepare_namespace() + - Added for CONFIG_MIPS_OMS400 +*/ #include #include @@ -173,7 +181,11 @@ int __init rd_load_image(char *from) { int res = 0; int in_fd, out_fd; +#if defined(CONFIG_MIPS_OMS400) + long rd_blocks, devblocks; +#else unsigned long rd_blocks, devblocks; +#endif int nblocks, i, disk; char *buf = NULL; unsigned short rotate = 0; diff --git a/init/main.c b/init/main.c index 7474450..1208994 100644 --- a/init/main.c +++ b/init/main.c @@ -7,6 +7,14 @@ * Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96 * Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96 * Simplified starting of init: Michael A. Griffith + * + * Century + * - Added LED display + * - Added recovery mode handling + * 2001-12-25 ozawa CONFIG_OBSS + * PlatHome + * - Added for OpenBlockS 266 + * */ #include @@ -109,6 +117,14 @@ bool early_boot_irqs_disabled __read_mostly; enum system_states system_state __read_mostly; EXPORT_SYMBOL(system_state); +#if defined(CONFIG_MIPS_OMS400) && defined(CONFIG_OMS400_LED) +#define STATUS_LED_OUT 1 +#endif + +#if defined(STATUS_LED_OUT) +extern int obsled_out(int); +#endif + /* * Boot command-line arguments */ @@ -470,6 +486,9 @@ asmlinkage void __init start_kernel(void) char * command_line; extern const struct kernel_param __start___param[], __stop___param[]; +#if defined(STATUS_LED_OUT) + obsled_out(1); +#endif smp_setup_processor_id(); /* @@ -496,6 +515,9 @@ asmlinkage void __init start_kernel(void) tick_init(); boot_cpu_init(); page_address_init(); +#if defined(STATUS_LED_OUT) + obsled_out(2); +#endif printk(KERN_NOTICE "%s", linux_banner); setup_arch(&command_line); mm_init_owner(&init_mm, &init_task); @@ -777,6 +799,9 @@ static noinline int init_post(void) * The Bourne shell can be used instead of init if we are * trying to recover a really broken machine. */ +#if defined(STATUS_LED_OUT) + obsled_out(6); +#endif if (execute_command) { run_init_process(execute_command); printk(KERN_WARNING "Failed to execute %s. Attempting " @@ -801,6 +826,9 @@ static int __init kernel_init(void * unused) /* Now the scheduler is fully set up and can do blocking allocations */ gfp_allowed_mask = __GFP_BITS_MASK; +#if defined(STATUS_LED_OUT) + obsled_out(3); +#endif /* * init can allocate pages on any node */ @@ -820,8 +848,15 @@ static int __init kernel_init(void * unused) smp_init(); sched_init_smp(); +#if defined(STATUS_LED_OUT) + obsled_out(4); +#endif do_basic_setup(); +#if defined(STATUS_LED_OUT) + obsled_out(5); +#endif + /* Open the /dev/console on the rootfs, this should never fail */ if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) printk(KERN_WARNING "Warning: unable to open an initial console.\n"); diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index e467a58..c464ba1 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2290,6 +2290,17 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, +{ + /* Creative Sound Blaster Degital Music LX */ + USB_DEVICE(0x041e, 0x3015), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + .vendor_name = "Creative Labs", + .product_name = "Sound Blaster Music LX", + .ifnum = QUIRK_NO_INTERFACE + } + +}, + /* Emagic devices */ { USB_DEVICE(0x086a, 0x0001), diff --git a/usr/Makefile b/usr/Makefile index 029ffe6..9a512af 100644 --- a/usr/Makefile +++ b/usr/Makefile @@ -67,3 +67,13 @@ $(obj)/initramfs_data.cpio$(suffix_y): $(obj)/gen_init_cpio $(deps_initramfs) kl $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.d $(call if_changed,initfs) +ifdef CONFIG_MIPS_OMS400 + +obj-y += initrd_data.o + +$(obj)/initrd_data.o: $(obj)/ramdisk.image.gz FORCE + +$(obj)/ramdisk.image.gz: + touch $(obj)/ramdisk.image.gz + +endif diff --git a/usr/initrd_data.S b/usr/initrd_data.S new file mode 100644 index 0000000..1161056 --- /dev/null +++ b/usr/initrd_data.S @@ -0,0 +1,7 @@ +.section .initrd_data,"a" +.global Initrd_Data +_initrdstart: +.incbin "usr/ramdisk.image.gz" +_initrdend: +Initrd_Data: +.word 0x494e5244 , _initrdstart , _initrdend