diff --git a/Documentation/boards.dox b/Documentation/boards.dox index 4070d31..1407479 100644 --- a/Documentation/boards.dox +++ b/Documentation/boards.dox @@ -45,6 +45,12 @@ @li @subpage generic_pc + +MIPS type: + +@li @subpage dlink_dir_320 +@li @subpage qemu_malta + */ /* TODO diff --git a/arch/architecture.dox b/arch/architecture.dox index 67e2c38..2d2cf05 100644 --- a/arch/architecture.dox +++ b/arch/architecture.dox @@ -86,6 +86,7 @@ @li @subpage dev_arm_mach @li @subpage dev_bf_mach +@li @subpage dev_mips_mach @li @subpage dev_ppc_mach @li @subpage dev_x86_mach diff --git a/arch/arm/boards/freescale-mx51-pdk/board.c b/arch/arm/boards/freescale-mx51-pdk/board.c index d6472df..646f807 100644 --- a/arch/arm/boards/freescale-mx51-pdk/board.c +++ b/arch/arm/boards/freescale-mx51-pdk/board.c @@ -71,6 +71,23 @@ MX51_PAD_CSPI1_SCLK__CSPI1_SCLK, MX51_PAD_EIM_A20__GPIO2_14, /* LAN8700 reset pin */ IOMUX_PAD(0x60C, 0x21C, 3, 0x0, 0, 0x85), /* FIXME: needed? */ + /* SD 1 */ + MX51_PAD_SD1_CMD__SD1_CMD, + MX51_PAD_SD1_CLK__SD1_CLK, + MX51_PAD_SD1_DATA0__SD1_DATA0, + MX51_PAD_SD1_DATA1__SD1_DATA1, + MX51_PAD_SD1_DATA2__SD1_DATA2, + MX51_PAD_SD1_DATA3__SD1_DATA3, + /* SD 2 */ + MX51_PAD_SD2_CMD__SD2_CMD, + MX51_PAD_SD2_CLK__SD2_CLK, + MX51_PAD_SD2_DATA0__SD2_DATA0, + MX51_PAD_SD2_DATA1__SD2_DATA1, + MX51_PAD_SD2_DATA2__SD2_DATA2, + MX51_PAD_SD2_DATA3__SD2_DATA3, + /* CD/WP gpio */ + MX51_PAD_GPIO1_6__GPIO1_6, + MX51_PAD_GPIO1_5__GPIO1_5, }; static int babbage_mem_init(void) diff --git a/arch/arm/boards/pcm038/pcm038.c b/arch/arm/boards/pcm038/pcm038.c index 4db50fe..6fee5c2 100644 --- a/arch/arm/boards/pcm038/pcm038.c +++ b/arch/arm/boards/pcm038/pcm038.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -213,6 +214,12 @@ PD23_AF_USBH2_DATA2, PD24_AF_USBH2_DATA1, PD26_AF_USBH2_DATA5, + /* I2C1 */ + PD17_PF_I2C_DATA | GPIO_PUEN, + PD18_PF_I2C_CLK, + /* I2C2 */ + PC5_PF_I2C2_SDA, + PC6_PF_I2C2_SCL, }; /* configure 16 bit nor flash on cs0 */ @@ -247,6 +254,10 @@ imx27_add_nand(&nand_info); imx27_add_fb(&pcm038_fb_data); + PCCR0 |= PCCR0_I2C1_EN | PCCR0_I2C2_EN; + imx27_add_i2c0(NULL); + imx27_add_i2c1(NULL); + #ifdef CONFIG_USB pcm038_usbh_init(); add_generic_usb_ehci_device(-1, IMX_OTG_BASE + 0x400, NULL); diff --git a/arch/arm/boards/pcm043/pcm043.c b/arch/arm/boards/pcm043/pcm043.c index 966899a..fbe8cea 100644 --- a/arch/arm/boards/pcm043/pcm043.c +++ b/arch/arm/boards/pcm043/pcm043.c @@ -124,9 +124,9 @@ uint32_t reg; /* CS0: Nor Flash */ - writel(0x0000cf03, CSCR_U(0)); - writel(0x10000d03, CSCR_L(0)); - writel(0x00720900, CSCR_A(0)); + writel(0x22C0CF00, CSCR_U(0)); + writel(0x75000D01, CSCR_L(0)); + writel(0x00000900, CSCR_A(0)); led_gpio_register(&led0); @@ -277,10 +277,6 @@ writel(0x0, IMX_MAX_BASE + 0xc00); /* for M4 */ writel(0x0, IMX_MAX_BASE + 0xd00); /* for M5 */ - writel(0x0000DCF6, CSCR_U(0)); /* CS0: NOR Flash */ - writel(0x444A4541, CSCR_L(0)); - writel(0x44443302, CSCR_A(0)); - /* * M3IF Control Register (M3IFCTL) * MRRP[0] = L2CC0 not on priority list (0 << 0) = 0x00000000 diff --git a/arch/arm/cpu/exceptions.S b/arch/arm/cpu/exceptions.S index 4741bb8..a879755 100644 --- a/arch/arm/cpu/exceptions.S +++ b/arch/arm/cpu/exceptions.S @@ -136,11 +136,6 @@ bl do_data_abort .align 5 -.globl not_used -not_used: - get_bad_stack - bad_save_user_regs - bl do_not_used .globl irq .globl fiq diff --git a/arch/arm/cpu/interrupts.c b/arch/arm/cpu/interrupts.c index 5168921..3d2077f 100644 --- a/arch/arm/cpu/interrupts.c +++ b/arch/arm/cpu/interrupts.c @@ -29,54 +29,6 @@ #include #include -void do_undefined_instruction (struct pt_regs *pt_regs); -void do_software_interrupt (struct pt_regs *pt_regs); -void do_prefetch_abort (struct pt_regs *pt_regs); -void do_data_abort (struct pt_regs *pt_regs); -void do_not_used (struct pt_regs *pt_regs); -void do_fiq (struct pt_regs *pt_regs); -void do_irq (struct pt_regs *pt_regs); - -#ifdef CONFIG_USE_IRQ -/* enable IRQ interrupts */ -void enable_interrupts (void) -{ - unsigned long temp; - __asm__ __volatile__("mrs %0, cpsr\n" - "bic %0, %0, #0x80\n" - "msr cpsr_c, %0" - : "=r" (temp) - : - : "memory"); -} - - -/* - * disable IRQ/FIQ interrupts - * returns true if interrupts had been enabled before we disabled them - */ -int disable_interrupts (void) -{ - unsigned long old,temp; - __asm__ __volatile__("mrs %0, cpsr\n" - "orr %1, %0, #0xc0\n" - "msr cpsr_c, %1" - : "=r" (old), "=r" (temp) - : - : "memory"); - return(old & 0x80) == 0; -} -#endif - -/** - * FIXME - */ -static void bad_mode (void) -{ - panic ("Resetting CPU ...\n"); - reset_cpu (0); -} - /** * Display current register set content * @param[in] regs Guess what @@ -121,6 +73,13 @@ #endif } +static void __noreturn do_exception(struct pt_regs *pt_regs) +{ + show_regs(pt_regs); + + panic(""); +} + /** * The CPU runs into an undefined instruction. That really should not happen! * @param[in] pt_regs Register set content when the accident happens @@ -128,85 +87,73 @@ void do_undefined_instruction (struct pt_regs *pt_regs) { printf ("undefined instruction\n"); - show_regs (pt_regs); - bad_mode (); + do_exception(pt_regs); } /** * The CPU catches a software interrupt * @param[in] pt_regs Register set content when the interrupt happens * - * There is not functione behind this feature. So what to do else than - * a reset? + * There is no function behind this feature. So what to do else than + * a reset? */ void do_software_interrupt (struct pt_regs *pt_regs) { printf ("software interrupt\n"); - show_regs (pt_regs); - bad_mode (); + do_exception(pt_regs); } /** * The CPU catches a prefetch abort. That really should not happen! * @param[in] pt_regs Register set content when the accident happens * - * FIXME: What does it mean, why is reset the only solution? + * instruction fetch from an unmapped area */ void do_prefetch_abort (struct pt_regs *pt_regs) { printf ("prefetch abort\n"); - show_regs (pt_regs); - bad_mode (); + do_exception(pt_regs); } /** * The CPU catches a data abort. That really should not happen! * @param[in] pt_regs Register set content when the accident happens * - * FIXME: What does it mean, why is reset the only solution? + * data fetch from an unmapped area */ void do_data_abort (struct pt_regs *pt_regs) { - printf ("data abort\n"); - show_regs (pt_regs); - bad_mode (); -} + u32 far; -/** - * The CPU catches a not-used(?) abort. - * @param[in] pt_regs Register set content when the accident happens - * - * FIXME: What does it mean, why is reset the only solution? - */ -void do_not_used (struct pt_regs *pt_regs) -{ - printf ("not used\n"); - show_regs (pt_regs); - bad_mode (); + asm volatile ("mrc p15, 0, %0, c6, c0, 0" : "=r" (far) : : "cc"); + + printf("unable to handle %s at address 0x%08x\n", + far < PAGE_SIZE ? "NULL pointer dereference" : + "paging request", far); + + do_exception(pt_regs); } /** * The CPU catches a fast interrupt request. * @param[in] pt_regs Register set content when the interrupt happens * - * FIXME: What does it mean, why is reset the only solution? + * We never enable FIQs, so this should not happen */ void do_fiq (struct pt_regs *pt_regs) { printf ("fast interrupt request\n"); - show_regs (pt_regs); - bad_mode (); + do_exception(pt_regs); } /** * The CPU catches a regular interrupt. * @param[in] pt_regs Register set content when the interrupt happens * - * FIXME: What does it mean, why is reset the only solution? + * We never enable interrupts, so this should not happen */ void do_irq (struct pt_regs *pt_regs) { printf ("interrupt request\n"); - show_regs (pt_regs); - bad_mode (); + do_exception(pt_regs); } diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c index 1f62d61..b669349 100644 --- a/arch/arm/cpu/mmu.c +++ b/arch/arm/cpu/mmu.c @@ -4,6 +4,7 @@ #include #include #include +#include static unsigned long *ttb; @@ -65,7 +66,7 @@ table = memalign(0x400, 0x400); - ttb[virt] = (unsigned long)table | PMD_TYPE_TABLE; + ttb[virt >> 20] = (unsigned long)table | PMD_TYPE_TABLE; for (i = 0; i < 256; i++) { table[i] = virt | PTE_TYPE_SMALL | PTE_FLAGS_UNCACHED; @@ -161,22 +162,46 @@ #define ARM_VECTORS_SIZE (sizeof(u32) * 8 * 2) /* - * Allocate a page, map it to the zero page and copy our exception - * vectors there. + * Map vectors and zero page */ static void vectors_init(void) { - u32 *exc; + u32 *exc, *zero = NULL; void *vectors; extern unsigned long exception_vectors; + u32 cr; - exc = arm_create_pte(0x0); + cr = get_cr(); + cr |= CR_V; + set_cr(cr); + cr = get_cr(); + + if (cr & CR_V) { + /* + * If we can use high vectors, create the second level + * page table for the high vectors and zero page + */ + exc = arm_create_pte(0xfff00000); + zero = arm_create_pte(0x0); + + /* Set the zero page to faulting */ + zero[0] = 0; + } else { + /* + * Otherwise map the vectors to the zero page. We have to + * live without being able to catch NULL pointer dereferences + */ + exc = arm_create_pte(0x0); + } vectors = xmemalign(PAGE_SIZE, PAGE_SIZE); memset(vectors, 0, PAGE_SIZE); memcpy(vectors, &exception_vectors, ARM_VECTORS_SIZE); - exc[0] = (u32)vectors | PTE_TYPE_SMALL | PTE_FLAGS_CACHED; + if (cr & CR_V) + exc[256 - 16] = (u32)vectors | PTE_TYPE_SMALL | PTE_FLAGS_CACHED; + else + exc[0] = (u32)vectors | PTE_TYPE_SMALL | PTE_FLAGS_CACHED; } /* diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c index f20ce74..5e09300 100644 --- a/arch/arm/cpu/start.c +++ b/arch/arm/cpu/start.c @@ -36,7 +36,7 @@ "ldr pc, =software_interrupt\n" /* software interrupt (SWI) */ "ldr pc, =prefetch_abort\n" /* prefetch abort */ "ldr pc, =data_abort\n" /* data abort */ - "ldr pc, =not_used\n" /* (reserved) */ + "1: bne 1b\n" /* (reserved) */ "ldr pc, =irq\n" /* irq (interrupt) */ "ldr pc, =fiq\n" /* fiq (fast interrupt) */ #else diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 77d6305..1d67492 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -59,7 +59,7 @@ static inline unsigned int get_cr(void) { unsigned int val; - asm("mrc p15, 0, %0, c1, c0, 0 @ get CR" : "=r" (val) : : "cc"); + asm volatile ("mrc p15, 0, %0, c1, c0, 0 @ get CR" : "=r" (val) : : "cc"); return val; } diff --git a/arch/arm/lib/bootz.c b/arch/arm/lib/bootz.c index cd8f495..13bed25 100644 --- a/arch/arm/lib/bootz.c +++ b/arch/arm/lib/bootz.c @@ -4,9 +4,11 @@ #include #include #include +#include #include #include #include +#include struct zimage_header { u32 unused[9]; @@ -20,9 +22,11 @@ static int do_bootz(struct command *cmdtp, int argc, char *argv[]) { int fd, ret, swap = 0; - struct zimage_header header; + struct zimage_header __header, *header; void *zimage; u32 end; + int usemap = 0; + struct arm_memory *mem = list_first_entry(&memory_list, struct arm_memory, list); if (argc != 2) { barebox_cmd_usage(cmdtp); @@ -35,13 +39,27 @@ return 1; } - ret = read(fd, &header, sizeof(header)); - if (ret < sizeof(header)) { - printf("could not read %s\n", argv[1]); - goto err_out; + /* + * We can save the memcpy of the zImage if it already is in + * the first 128MB of SDRAM. + */ + zimage = memmap(fd, PROT_READ); + if (zimage && (unsigned long)zimage >= mem->start && + (unsigned long)zimage < mem->start + SZ_128M) { + usemap = 1; + header = zimage; } - switch (header.magic) { + if (!usemap) { + header = &__header; + ret = read(fd, header, sizeof(header)); + if (ret < sizeof(*header)) { + printf("could not read %s\n", argv[1]); + goto err_out; + } + } + + switch (header->magic) { #ifdef CONFIG_BOOT_ENDIANNESS_SWITCH case swab32(ZIMAGE_MAGIC): swap = 1; @@ -50,22 +68,33 @@ case ZIMAGE_MAGIC: break; default: - printf("invalid magic 0x%08x\n", header.magic); + printf("invalid magic 0x%08x\n", header->magic); goto err_out; } - end = header.end; + end = header->end; if (swap) end = swab32(end); - zimage = xmalloc(end); - memcpy(zimage, &header, sizeof(header)); + if (!usemap) { + if (mem->size <= SZ_128M) { + zimage = xmalloc(end); + } else { + zimage = (void *)mem->start + SZ_8M; + if (mem->start + SZ_8M + end >= MALLOC_BASE) { + printf("won't overwrite malloc space with image\n"); + goto err_out1; + } + } - ret = read(fd, zimage + sizeof(header), end - sizeof(header)); - if (ret < end - sizeof(header)) { - printf("could not read %s\n", argv[1]); - goto err_out1; + memcpy(zimage, &header, sizeof(header)); + + ret = read(fd, zimage + sizeof(header), end - sizeof(header)); + if (ret < end - sizeof(header)) { + printf("could not read %s\n", argv[1]); + goto err_out1; + } } if (swap) { diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c index b4bf93b..8482b60 100644 --- a/arch/arm/mach-imx/boot.c +++ b/arch/arm/mach-imx/boot.c @@ -41,7 +41,7 @@ * Note also that I suspect that the boot source pins are only sampled at * power up. */ -static int imx_boot_save_loc(void) +static int imx_25_35_boot_save_loc(void) { const char *bareboxloc = NULL; uint32_t reg; @@ -86,10 +86,6 @@ return 0; } -/* - * This can only be called after env_push_context() has been called - * so it is a late_initcall. - */ -late_initcall(imx_boot_save_loc); +coredevice_initcall(imx_25_35_boot_save_loc); #endif diff --git a/arch/arm/mach-imx/imx51.c b/arch/arm/mach-imx/imx51.c index e7e7679..a42ff41 100644 --- a/arch/arm/mach-imx/imx51.c +++ b/arch/arm/mach-imx/imx51.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -89,3 +90,89 @@ return 0; } coredevice_initcall(imx51_init); + +/* + * Saves the boot source media into the $barebox_loc enviroment variable + * + * This information is useful for barebox init scripts as we can then easily + * use a kernel image stored on the same media that we launch barebox with + * (for example). + * + * imx25 and imx35 can boot into barebox from several media such as + * nand, nor, mmc/sd cards, serial roms. "mmc" is used to represent several + * sources as its impossible to distinguish between them. + * + * Some sources such as serial roms can themselves have 3 different boot + * possibilities (i2c1, i2c2 etc). It is assumed that any board will + * only be using one of these at any one time. + * + * Note also that I suspect that the boot source pins are only sampled at + * power up. + */ + +#define SRC_SBMR 0x4 +#define SBMR_BT_MEM_TYPE_SHIFT 7 +#define SBMR_BT_MEM_CTL_SHIFT 0 +#define SBMR_BMOD_SHIFT 14 + +static int imx51_boot_save_loc(void) +{ + const char *bareboxloc = NULL; + uint32_t reg; + unsigned int ctrl, type; + + /* [CTRL][TYPE] */ + const char *const locations[4][4] = { + { /* CTRL = WEIM */ + "nor", + NULL, + "onenand", + NULL, + }, { /* CTRL == NAND */ + "nand", + "nand", + "nand", + "nand", + }, { /* CTRL == reserved */ + NULL, + NULL, + NULL, + NULL, + }, { /* CTRL == expansion */ + "mmc", + NULL, + "i2c", + "spi", + } + }; + + reg = readl(MX51_SRC_BASE_ADDR + SRC_SBMR); + + switch ((reg >> SBMR_BMOD_SHIFT) & 0x3) { + case 0: + case 2: + /* internal boot */ + ctrl = (reg >> SBMR_BT_MEM_CTL_SHIFT) & 0x3; + type = (reg >> SBMR_BT_MEM_TYPE_SHIFT) & 0x3; + + bareboxloc = locations[ctrl][type]; + break; + case 1: + /* reserved */ + bareboxloc = "unknown"; + break; + case 3: + bareboxloc = "serial"; + break; + + } + + if (bareboxloc) { + setenv("barebox_loc", bareboxloc); + export("barebox_loc"); + } + + return 0; +} + +coredevice_initcall(imx51_boot_save_loc); diff --git a/arch/arm/mach-imx/include/mach/devices-imx27.h b/arch/arm/mach-imx/include/mach/devices-imx27.h index 0511eb5..3141d96 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx27.h +++ b/arch/arm/mach-imx/include/mach/devices-imx27.h @@ -6,11 +6,21 @@ return imx_add_spi((void *)IMX_SPI1_BASE, 0, pdata); } +static inline struct device_d *imx27_add_spi1(struct spi_imx_master *pdata) +{ + return imx_add_spi((void *)IMX_SPI2_BASE, 1, pdata); +} + static inline struct device_d *imx27_add_i2c0(struct i2c_platform_data *pdata) { return imx_add_i2c((void *)IMX_I2C1_BASE, 0, pdata); } +static inline struct device_d *imx27_add_i2c1(struct i2c_platform_data *pdata) +{ + return imx_add_i2c((void *)IMX_I2C2_BASE, 1, pdata); +} + static inline struct device_d *imx27_add_uart0(void) { return imx_add_uart((void *)IMX_UART1_BASE, 0); diff --git a/arch/arm/mach-imx/include/mach/imx27-regs.h b/arch/arm/mach-imx/include/mach/imx27-regs.h index 570b430..6754c5a 100644 --- a/arch/arm/mach-imx/include/mach/imx27-regs.h +++ b/arch/arm/mach-imx/include/mach/imx27-regs.h @@ -17,6 +17,7 @@ #define IMX_UART3_BASE (0x0c000 + IMX_IO_BASE) #define IMX_UART4_BASE (0x0d000 + IMX_IO_BASE) #define IMX_SPI1_BASE (0x0e000 + IMX_IO_BASE) +#define IMX_SPI2_BASE (0x0f000 + IMX_IO_BASE) #define IMX_I2C1_BASE (0x12000 + IMX_IO_BASE) #define IMX_GPIO_BASE (0x15000 + IMX_IO_BASE) #define IMX_TIM4_BASE (0x19000 + IMX_IO_BASE) diff --git a/arch/arm/mach-imx/include/mach/iomux-mx51.h b/arch/arm/mach-imx/include/mach/iomux-mx51.h index 16cb802..908d1b2 100644 --- a/arch/arm/mach-imx/include/mach/iomux-mx51.h +++ b/arch/arm/mach-imx/include/mach/iomux-mx51.h @@ -23,6 +23,10 @@ #define MX51_FEC_PAD_CTRL (PAD_CTL_DVS | PAD_CTL_DSE_HIGH) +#define MX51_SDHCI_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_PUE | \ + PAD_CTL_SRE_FAST | PAD_CTL_DVS) + /* * The naming convention for the pad modes is MX51_PAD___ * If or refers to a GPIO, it is named @@ -323,20 +327,20 @@ #define MX51_PAD_DISP2_DAT14__FEC_RDATA0 IOMUX_PAD(0x794, 0x38c, 2, 0x0958, 1, MX51_FEC_PAD_CTRL) #define MX51_PAD_DISP2_DAT15__DISP2_DAT15 IOMUX_PAD(0x798, 0x390, 0, 0x0, 0, NO_PAD_CTRL) #define MX51_PAD_DISP2_DAT15__FEC_TDATA0 IOMUX_PAD(0x798, 0x390, 2, 0x0, 0, MX51_FEC_PAD_CTRL) -#define MX51_PAD_SD1_CMD__SD1_CMD IOMUX_PAD(0x79C, 0x394, 0, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_SD1_CLK__SD1_CLK IOMUX_PAD(0x7A0, 0x398, 0, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_SD1_DATA0__SD1_DATA0 IOMUX_PAD(0x7A4, 0x39C, 0, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_SD1_DATA1__SD1_DATA1 IOMUX_PAD(0x7A8, 0x3A0, 0, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_SD1_DATA2__SD1_DATA2 IOMUX_PAD(0x7AC, 0x3A4, 0, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_SD1_DATA3__SD1_DATA3 IOMUX_PAD(0x7B0, 0x3A8, 0, 0x0, 0, NO_PAD_CTRL) +#define MX51_PAD_SD1_CMD__SD1_CMD IOMUX_PAD(0x79C, 0x394, 0x10, 0x0, 0, MX51_SDHCI_PAD_CTRL) +#define MX51_PAD_SD1_CLK__SD1_CLK IOMUX_PAD(0x7A0, 0x398, 0x10, 0x0, 0, MX51_SDHCI_PAD_CTRL) +#define MX51_PAD_SD1_DATA0__SD1_DATA0 IOMUX_PAD(0x7A4, 0x39C, 0x10, 0x0, 0, MX51_SDHCI_PAD_CTRL) +#define MX51_PAD_SD1_DATA1__SD1_DATA1 IOMUX_PAD(0x7A8, 0x3A0, 0x10, 0x0, 0, MX51_SDHCI_PAD_CTRL) +#define MX51_PAD_SD1_DATA2__SD1_DATA2 IOMUX_PAD(0x7AC, 0x3A4, 0x10, 0x0, 0, MX51_SDHCI_PAD_CTRL) +#define MX51_PAD_SD1_DATA3__SD1_DATA3 IOMUX_PAD(0x7B0, 0x3A8, 0x10, 0x0, 0, MX51_SDHCI_PAD_CTRL) #define MX51_PAD_GPIO1_0__GPIO1_0 IOMUX_PAD(0x7B4, 0x3AC, 0, 0x0, 0, NO_PAD_CTRL) #define MX51_PAD_GPIO1_1__GPIO1_1 IOMUX_PAD(0x7B8, 0x3B0, 0, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_SD2_CMD__SD2_CMD IOMUX_PAD(0x7BC, 0x3B4, 0, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_SD2_CLK__SD2_CLK IOMUX_PAD(0x7C0, 0x3B8, 0, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_SD2_DATA0__SD2_DATA0 IOMUX_PAD(0x7C4, 0x3BC, 0, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_SD2_DATA1__SD2_DATA1 IOMUX_PAD(0x7C8, 0x3C0, 0, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_SD2_DATA2__SD2_DATA2 IOMUX_PAD(0x7CC, 0x3C4, 0, 0x0, 0, NO_PAD_CTRL) -#define MX51_PAD_SD2_DATA3__SD2_DATA3 IOMUX_PAD(0x7D0, 0x3C8, 0, 0x0, 0, NO_PAD_CTRL) +#define MX51_PAD_SD2_CMD__SD2_CMD IOMUX_PAD(0x7BC, 0x3B4, 0x10, 0x0, 0, MX51_SDHCI_PAD_CTRL) +#define MX51_PAD_SD2_CLK__SD2_CLK IOMUX_PAD(0x7C0, 0x3B8, 0x10, 0x0, 0, MX51_SDHCI_PAD_CTRL) +#define MX51_PAD_SD2_DATA0__SD2_DATA0 IOMUX_PAD(0x7C4, 0x3BC, 0x10, 0x0, 0, MX51_SDHCI_PAD_CTRL) +#define MX51_PAD_SD2_DATA1__SD2_DATA1 IOMUX_PAD(0x7C8, 0x3C0, 0x10, 0x0, 0, MX51_SDHCI_PAD_CTRL) +#define MX51_PAD_SD2_DATA2__SD2_DATA2 IOMUX_PAD(0x7CC, 0x3C4, 0x10, 0x0, 0, MX51_SDHCI_PAD_CTRL) +#define MX51_PAD_SD2_DATA3__SD2_DATA3 IOMUX_PAD(0x7D0, 0x3C8, 0x10, 0x0, 0, MX51_SDHCI_PAD_CTRL) #define MX51_PAD_GPIO1_2__GPIO1_2 IOMUX_PAD(0x7D4, 0x3CC, 0, 0x0, 0, NO_PAD_CTRL) #define MX51_PAD_GPIO1_3__GPIO1_3 IOMUX_PAD(0x7D8, 0x3D0, 0, 0x0, 0, NO_PAD_CTRL) #define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ IOMUX_PAD(0x7FC, 0x3D4, 0, 0x0, 0, NO_PAD_CTRL) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig new file mode 100644 index 0000000..8970470 --- /dev/null +++ b/arch/mips/Kconfig @@ -0,0 +1,227 @@ +# +# +# +config MIPS + bool + select HAS_KALLSYMS + select HAVE_CONFIGURABLE_MEMORY_LAYOUT + select HAVE_CONFIGURABLE_TEXT_BASE + default y + +config SYS_SUPPORTS_BIG_ENDIAN + bool + +config SYS_SUPPORTS_LITTLE_ENDIAN + bool + +config CSRC_R4K_LIB + bool + +config GENERIC_LINKER_SCRIPT + bool + default y + +menu "Machine selection" + +choice + prompt "System type" + default MACH_MIPS_MALTA + +config MACH_MIPS_MALTA + bool "MIPS Malta" + select CSRC_R4K_LIB + select DRIVER_SERIAL_NS16550 + select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_CPU_MIPS32_R2 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select HAS_DEBUG_LL + +config MACH_MIPS_BCM47XX + bool "Broadcom BCM47xx-based boards" + select CSRC_R4K_LIB + select DRIVER_SERIAL_NS16550 + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select HAS_DEBUG_LL + +endchoice + +source arch/mips/mach-malta/Kconfig +source arch/mips/mach-bcm47xx/Kconfig + +endmenu + +# +# Endianess selection. Sufficiently obscure so many users don't know what to +# answer,so we try hard to limit the available choices. Also the use of a +# choice statement should be more obvious to the user. +# +choice + prompt "Endianess selection" + help + Some MIPS machines can be configured for either little or big endian + byte order. These modes require different barebox images. + In general there is one preferred byteorder for a + particular system but some systems are just as commonly used in the + one or the other endianness. + +config CPU_BIG_ENDIAN + bool "Big endian" + depends on SYS_SUPPORTS_BIG_ENDIAN + +config CPU_LITTLE_ENDIAN + bool "Little endian" + depends on SYS_SUPPORTS_LITTLE_ENDIAN + help + +endchoice + +menu "CPU selection" + +choice + prompt "CPU type" + default CPU_MIPS32_R2 + +config CPU_MIPS32_R1 + bool "MIPS32 Release 1" + depends on SYS_HAS_CPU_MIPS32_R1 + select CPU_SUPPORTS_32BIT_KERNEL + help + Choose this option to build a barebox for release 1 or later of the + MIPS32 architecture. Most modern embedded systems with a 32-bit + MIPS processor are based on a MIPS32 processor. If you know the + specific type of processor in your system, choose those that one + otherwise CPU_MIPS32_R1 is a safe bet for any MIPS32 system. + Release 2 of the MIPS32 architecture is available since several + years so chances are you even have a MIPS32 Release 2 processor + in which case you should choose CPU_MIPS32_R2 instead for better + performance. + +config CPU_MIPS32_R2 + bool "MIPS32 Release 2" + depends on SYS_HAS_CPU_MIPS32_R2 + select CPU_SUPPORTS_32BIT_KERNEL + help + Choose this option to build a barebox for release 2 or later of the + MIPS32 architecture. Most modern embedded systems with a 32-bit + MIPS processor are based on a MIPS32 processor. If you know the + specific type of processor in your system, choose those that one + otherwise CPU_MIPS32_R1 is a safe bet for any MIPS32 system. + +config CPU_MIPS64_R1 + bool "MIPS64 Release 1" + depends on SYS_HAS_CPU_MIPS64_R1 + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + help + Choose this option to build a barebox for release 1 or later of the + MIPS64 architecture. Many modern embedded systems with a 64-bit + MIPS processor are based on a MIPS64 processor. If you know the + specific type of processor in your system, choose those that one + otherwise CPU_MIPS64_R1 is a safe bet for any MIPS64 system. + Release 2 of the MIPS64 architecture is available since several + years so chances are you even have a MIPS64 Release 2 processor + in which case you should choose CPU_MIPS64_R2 instead for better + performance. + +config CPU_MIPS64_R2 + bool "MIPS64 Release 2" + depends on SYS_HAS_CPU_MIPS64_R2 + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + help + Choose this option to build a barebox for release 2 or later of the + MIPS64 architecture. Many modern embedded systems with a 64-bit + MIPS processor are based on a MIPS64 processor. If you know the + specific type of processor in your system, choose those that one + otherwise CPU_MIPS64_R1 is a safe bet for any MIPS64 system. + +endchoice + + +config SYS_HAS_CPU_MIPS32_R1 + bool + +config SYS_HAS_CPU_MIPS32_R2 + bool + +config SYS_HAS_CPU_MIPS64_R1 + bool + +config SYS_HAS_CPU_MIPS64_R2 + bool + +# +# These two indicate any level of the MIPS32 and MIPS64 architecture +# +config CPU_MIPS32 + bool + default y if CPU_MIPS32_R1 || CPU_MIPS32_R2 + +config CPU_MIPS64 + bool + default y if CPU_MIPS64_R1 || CPU_MIPS64_R2 + +# +# These two indicate the revision of the architecture, either Release 1 or Release 2 +# +config CPU_MIPSR1 + bool + default y if CPU_MIPS32_R1 || CPU_MIPS64_R1 + +config CPU_MIPSR2 + bool + default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 + +config SYS_SUPPORTS_32BIT_KERNEL + bool +config SYS_SUPPORTS_64BIT_KERNEL + bool +config CPU_SUPPORTS_32BIT_KERNEL + bool +config CPU_SUPPORTS_64BIT_KERNEL + bool + +endmenu + +choice + prompt "Barebox code model" + help + You should only select this option if you have a workload that + actually benefits from 64-bit processing or if your machine has + large memory. You will only be presented a single option in this + menu if your system does not support both 32-bit and 64-bit modes. + +config 32BIT + bool "32-bit barebox" + depends on CPU_SUPPORTS_32BIT_KERNEL && SYS_SUPPORTS_32BIT_KERNEL + help + Select this option if you want to build a 32-bit barebox. + +config 64BIT + bool "64-bit barebox" + depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL + help + Select this option if you want to build a 64-bit barebox. + +endchoice + +menu "MIPS specific settings " + +config CMD_MIPS_CPUINFO + bool "cpuinfo command" + default y + help + Say yes here to get a cpuinfo command to show some + information about the cpu model. + +endmenu + +source common/Kconfig +source commands/Kconfig +source net/Kconfig +source drivers/Kconfig +source fs/Kconfig +source lib/Kconfig diff --git a/arch/mips/Makefile b/arch/mips/Makefile new file mode 100644 index 0000000..43b8ae6 --- /dev/null +++ b/arch/mips/Makefile @@ -0,0 +1,105 @@ +# +# Select the object file format to substitute into the linker script. +# +ifdef CONFIG_CPU_LITTLE_ENDIAN +32bit-emul = elf32ltsmip +64bit-emul = elf64ltsmip +else +32bit-emul = elf32btsmip +64bit-emul = elf64btsmip +endif + +CPPFLAGS += -D__MIPS__ -fno-strict-aliasing -fno-merge-constants + +cflags-y += -G 0 -mno-abicalls -fno-pic -pipe +cflags-y += -Wall -Wmissing-prototypes -Wstrict-prototypes \ + -Wno-uninitialized -Wno-format -Wno-main + +ifdef CONFIG_32BIT +ld-emul = $(32bit-emul) +cflags-y += -mabi=32 +endif + +ifdef CONFIG_64BIT +ld-emul = $(64bit-emul) +cflags-y += -mabi=64 +endif + +undef-all += -UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__ +undef-all += -UMIPSEL -U_MIPSEL -U__MIPSEL -U__MIPSEL__ +predef-be += -DMIPSEB -D_MIPSEB -D__MIPSEB -D__MIPSEB__ +predef-le += -DMIPSEL -D_MIPSEL -D__MIPSEL -D__MIPSEL__ + +ifdef CONFIG_CPU_BIG_ENDIAN +cflags-y += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB $(undef-all) $(predef-be)) +ldflags-y += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB ) +endif + +ifdef CONFIG_CPU_LITTLE_ENDIAN +cflags-y += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL $(undef-all) $(predef-le)) +ldflags-y += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL ) +endif + +LDFLAGS += $(ldflags-y) -m $(ld-emul) + +# +# CPU-dependent compiler/assembler options for optimization. +# +cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) -Wa,-mips32 -Wa,--trap +cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) -Wa,-mips32r2 -Wa,--trap +cflags-$(CONFIG_CPU_MIPS64_R1) += $(call cc-option,-march=mips64,-mips64 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) -Wa,-mips64 -Wa,--trap +cflags-$(CONFIG_CPU_MIPS64_R2) += $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) -Wa,-mips64r2 -Wa,--trap + +CPPFLAGS += -DTEXT_BASE=$(CONFIG_TEXT_BASE) + +ifndef CONFIG_MODULES +# Add cleanup flags +CPPFLAGS += -fdata-sections -ffunction-sections +LDFLAGS_barebox += -static --gc-sections +endif + +LDFLAGS_barebox += -nostdlib + +machine-$(CONFIG_MACH_MIPS_MALTA) := malta +board-$(CONFIG_BOARD_QEMU_MALTA) := qemu-malta + +machine-$(CONFIG_MACH_MIPS_BCM47XX) := bcm47xx +board-$(CONFIG_BOARD_DLINK_DIR320) := dlink-dir-320 + +machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y)) + +ifeq ($(KBUILD_SRC),) +CPPFLAGS += $(patsubst %,-I%include,$(machdirs)) +else +CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs)) +endif + +ifeq ($(incdir-y),) +incdir-y := $(machine-y) +endif +INCDIR := arch-$(incdir-y) + +all: $(KBUILD_IMAGE) + +ifneq ($(board-y),) +BOARD := arch/mips/boards/$(board-y)/ +else +BOARD := +endif + +ifneq ($(machine-y),) +MACH := arch/mips/mach-$(machine-y)/ +else +MACH := +endif + +common-y += $(BOARD) $(MACH) +common-y += arch/mips/lib/ +common-y += arch/mips/boot/ + +CPPFLAGS += $(cflags-y) +CFLAGS += $(cflags-y) + +lds-$(CONFIG_GENERIC_LINKER_SCRIPT) := arch/mips/lib/barebox.lds + +CLEAN_FILES += arch/mips/lib/barebox.lds barebox.map barebox.S diff --git a/arch/mips/boards/dlink-dir-320/Kconfig b/arch/mips/boards/dlink-dir-320/Kconfig new file mode 100644 index 0000000..0393d04 --- /dev/null +++ b/arch/mips/boards/dlink-dir-320/Kconfig @@ -0,0 +1,6 @@ +if BOARD_DLINK_DIR320 + +config BOARDINFO + default "D-Link DIR-320" + +endif diff --git a/arch/mips/boards/dlink-dir-320/Makefile b/arch/mips/boards/dlink-dir-320/Makefile new file mode 100644 index 0000000..ff1a655 --- /dev/null +++ b/arch/mips/boards/dlink-dir-320/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_DRIVER_SERIAL_NS16550) += serial.o diff --git a/arch/mips/boards/dlink-dir-320/config.h b/arch/mips/boards/dlink-dir-320/config.h new file mode 100644 index 0000000..eb4ab08 --- /dev/null +++ b/arch/mips/boards/dlink-dir-320/config.h @@ -0,0 +1,19 @@ +/* + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/* nothing special yet */ diff --git a/arch/mips/boards/dlink-dir-320/dlink-dir-320.dox b/arch/mips/boards/dlink-dir-320/dlink-dir-320.dox new file mode 100644 index 0000000..d0f5869 --- /dev/null +++ b/arch/mips/boards/dlink-dir-320/dlink-dir-320.dox @@ -0,0 +1,38 @@ +/** @page dlink_dir_320 D-Link DIR-320 wireless router + +The router has +@li BCM5354 SoC; +@li 32 MiB SDRAM; +@li 4 MiB NOR type Flash Memory; +@li RS232 serial interface (LV-TTL levels on board!); +@li 1xUSB interface; +@li 4 + 1 ethernet interfaces; +@li 802.11b/g (WiFi) interface; +@li JTAG interface; +@li 5 LEDs; +@li 2 buttons. + +The router uses CFE as firmware. + +Barebox can be started from CFE using tftp. +You must setup tftp-server on host 192.168.0.1. +Put your barebox.bin to tftp-server directory +(usual /tftpboot or /srv/tftp). +Connect your DIR-320 to your tftp-server network via +one of four sockets. + +Next, setup network on DIR-320 and run barebox.bin, e.g.: +@verbatim +CFE> ifconfig eth0 -addr=192.168.0.99 +CFE> boot -tftp -addr=a0800000 -raw 192.168.0.1:barebox.bin +@endverbatim + +DIR-320 links: +@li http://www.dlink.com.au/products/?pid=768 +@li http://wiki.openwrt.org/toh/d-link/dir-320 + +CFE links: +@li http://www.broadcom.com/support/communications_processors/downloads.php#cfe +@li http://www.linux-mips.org/wiki/CFE + +*/ diff --git a/arch/mips/boards/dlink-dir-320/serial.c b/arch/mips/boards/dlink-dir-320/serial.c new file mode 100644 index 0000000..ebe8c06 --- /dev/null +++ b/arch/mips/boards/dlink-dir-320/serial.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2011 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct NS16550_plat serial_plat = { + .clock = 25804800, + .shift = 0, +}; + +static int dir320_console_init(void) +{ + /* Register the serial port */ + add_ns16550_device(-1, DEBUG_LL_UART_ADDR, 8, + IORESOURCE_MEM_8BIT, &serial_plat); + + return 0; +} +console_initcall(dir320_console_init); diff --git a/arch/mips/boards/qemu-malta/Kconfig b/arch/mips/boards/qemu-malta/Kconfig new file mode 100644 index 0000000..6d86c14 --- /dev/null +++ b/arch/mips/boards/qemu-malta/Kconfig @@ -0,0 +1,6 @@ +if BOARD_QEMU_MALTA + +config BOARDINFO + default "qemu malta" + +endif diff --git a/arch/mips/boards/qemu-malta/Makefile b/arch/mips/boards/qemu-malta/Makefile new file mode 100644 index 0000000..ff1a655 --- /dev/null +++ b/arch/mips/boards/qemu-malta/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_DRIVER_SERIAL_NS16550) += serial.o diff --git a/arch/mips/boards/qemu-malta/config.h b/arch/mips/boards/qemu-malta/config.h new file mode 100644 index 0000000..eb4ab08 --- /dev/null +++ b/arch/mips/boards/qemu-malta/config.h @@ -0,0 +1,19 @@ +/* + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/* nothing special yet */ diff --git a/arch/mips/boards/qemu-malta/qemu-malta.dox b/arch/mips/boards/qemu-malta/qemu-malta.dox new file mode 100644 index 0000000..2e03636 --- /dev/null +++ b/arch/mips/boards/qemu-malta/qemu-malta.dox @@ -0,0 +1,15 @@ +/** @page qemu_malta QEmu malta emulated board + +Specific to this emulated board is, it does not require any setup code to bring the SDRAM and RS232 up. + +Emulator run string: +@verbatim +qemu-system-mips -nodefaults -M malta -m 256 -nographic -serial stdio -monitor null -bios barebox.bin +@endverbatim + +Links: +@li http://www.mips.com/products/development-kits/malta/ +@li http://www.linux-mips.org/wiki/Mips_Malta +@li http://www.qemu.org/ + +*/ diff --git a/arch/mips/boards/qemu-malta/serial.c b/arch/mips/boards/qemu-malta/serial.c new file mode 100644 index 0000000..ef6be17 --- /dev/null +++ b/arch/mips/boards/qemu-malta/serial.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2011 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct NS16550_plat serial_plat = { + .clock = 1843200, /* no matter for emulated port */ + .shift = 0, +}; + +static int malta_console_init(void) +{ + /* Register the serial port */ + add_ns16550_device(-1, DEBUG_LL_UART_ADDR, 8, + IORESOURCE_MEM_8BIT, &serial_plat); + + return 0; +} +console_initcall(malta_console_init); diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile new file mode 100644 index 0000000..f9151d2 --- /dev/null +++ b/arch/mips/boot/Makefile @@ -0,0 +1 @@ +obj-y += start.o diff --git a/arch/mips/boot/start.S b/arch/mips/boot/start.S new file mode 100644 index 0000000..ad341f3 --- /dev/null +++ b/arch/mips/boot/start.S @@ -0,0 +1,143 @@ +/* + * Startup Code for MIPS CPU + * + * Copyright (C) 2011 Antony Pavlov + * Used code copyrighted (C) 2009 by Shinya Kuribayashi + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + + /* + * ADR macro instruction (inspired by ARM) + * + * ARM architecture doesn't have PC-relative jump instruction + * like MIPS' B/BAL insns. When ARM makes PC-relative jumps, + * it uses ADR insn. ADR is used to get a destination address + * of 'label' against current PC. With this, ARM can safely + * make PC-relative jumps. + */ + .macro ADR rd label temp + .set push + .set noreorder + move \temp, ra # preserve ra beforehand + bal _pc + nop +_pc: addiu \rd, ra, \label - _pc # label is assumed to be + move ra, \temp # within pc +/- 32KB + .set pop + .endm + + .set noreorder + .text + .section ".text_bare_init" + .align 4 + +EXPORT(_start) + /* disable watchpoints */ + mtc0 zero, CP0_WATCHLO + mtc0 zero, CP0_WATCHHI + + /* disable interrupts */ + mfc0 k0, CP0_STATUS + li k1, ~ST0_IE + and k0, k1 + mtc0 k0, CP0_STATUS + + /* copy barebox to link location */ + ADR a0, _start, t1 /* a0 <- pc-relative position of _start */ + + la a1, _start /* link (RAM) _start address */ + + beq a0, a1, clear_bss + nop + + la t0, _start + la t1, __bss_start + subu t2, t1, t0 /* t2 <- size of barebox */ + addu a2, a0, t2 /* a2 <- source end address */ + +#define LONGSIZE 4 + +copy_loop: + /* copy from source address [a0] */ + lw t4, LONGSIZE * 0(a0) + lw t5, LONGSIZE * 1(a0) + lw t6, LONGSIZE * 2(a0) + lw t7, LONGSIZE * 3(a0) + /* copy fo target address [a1] */ + sw t4, LONGSIZE * 0(a1) + sw t5, LONGSIZE * 1(a1) + sw t6, LONGSIZE * 2(a1) + sw t7, LONGSIZE * 3(a1) + addi a0, LONGSIZE * 4 + subu t3, a0, a2 + blez t3, copy_loop + addi a1, LONGSIZE * 4 + +clear_bss: + la t0, __bss_start + sw zero, (t0) + la t1, _end - 4 +1: + addiu t0, LONGSIZE + sw zero, (t0) + bne t0, t1, 1b + nop + + /* + * Dominic Sweetman, See MIPS Run, Morgan Kaufmann, 2nd edition, 2006 + * + * 11.2.2 Stack Argument Structure in o32 + * ... + * At the point where a function is called, sp must be + * eight-byte-aligned, matching the alignment of the largest + * basic types -- a long long integer or a floating-point double. + * The eight-byte alignment is not required by 32-bit MIPS integer + * hardware, but it's essential for compatibility with CPUs with + * 64-bit registers, and thus part of the rules. Subroutines fit + * in with this by always adjusting the stack pointer by a multiple + * of eight. + * ... + * SGI's n32 and n64 standards call for the stack to be maintained + * with 16-byte alignment. + * + */ + +#if (STACK_BASE + STACK_SIZE) % 16 != 0 +#error stack pointer must be 16-byte-aligned +#endif + +stack_setup: + la sp, STACK_BASE + STACK_SIZE + + /* reserve four 32-bit argument slots */ + addiu sp, -16 + + la v0, start_barebox + jal v0 + nop + + /* No return */ + +__error: + b __error + nop diff --git a/arch/mips/configs/dlink-dir-320_defconfig b/arch/mips/configs/dlink-dir-320_defconfig new file mode 100644 index 0000000..dbce0b9 --- /dev/null +++ b/arch/mips/configs/dlink-dir-320_defconfig @@ -0,0 +1,58 @@ +CONFIG_MACH_MIPS_BCM47XX=y +CONFIG_STACK_SIZE=0x7000 +CONFIG_BROKEN=y +CONFIG_EXPERIMENTAL=y +CONFIG_LONGHELP=y +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_HUSH_GETOPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_MENU=y +CONFIG_PARTITION=y +# CONFIG_DEFAULT_ENVIRONMENT is not set +CONFIG_POLLER=y +CONFIG_DEBUG_INFO=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_MENU=y +CONFIG_CMD_MENU_MANAGEMENT=y +CONFIG_CMD_PASSWD=y +CONFIG_CMD_TIME=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_LOADY=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_CRC=y +CONFIG_CMD_CRC_CMP=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_SHA1SUM=y +CONFIG_CMD_SHA256SUM=y +CONFIG_CMD_MTEST=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_BOOTM_ZLIB=y +CONFIG_CMD_BOOTM_BZLIB=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_UNLZO=y +CONFIG_NET=y +CONFIG_NET_DHCP=y +CONFIG_NET_NFS=y +CONFIG_NET_PING=y +CONFIG_NET_TFTP=y +CONFIG_NET_TFTP_PUSH=y +CONFIG_NET_NETCONSOLE=y +CONFIG_NET_RESOLV=y +# CONFIG_SPI is not set +CONFIG_MTD=y +CONFIG_FS_CRAMFS=y +CONFIG_FS_FAT=y +CONFIG_FS_FAT_WRITE=y +CONFIG_FS_FAT_LFN=y diff --git a/arch/mips/configs/qemu-malta_defconfig b/arch/mips/configs/qemu-malta_defconfig new file mode 100644 index 0000000..b6f53ca --- /dev/null +++ b/arch/mips/configs/qemu-malta_defconfig @@ -0,0 +1,57 @@ +CONFIG_STACK_SIZE=0x7000 +CONFIG_BROKEN=y +CONFIG_EXPERIMENTAL=y +CONFIG_LONGHELP=y +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_HUSH_GETOPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_MENU=y +CONFIG_PARTITION=y +# CONFIG_DEFAULT_ENVIRONMENT is not set +CONFIG_POLLER=y +CONFIG_DEBUG_INFO=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_MENU=y +CONFIG_CMD_MENU_MANAGEMENT=y +CONFIG_CMD_PASSWD=y +CONFIG_CMD_TIME=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_LOADY=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_CRC=y +CONFIG_CMD_CRC_CMP=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_SHA1SUM=y +CONFIG_CMD_SHA256SUM=y +CONFIG_CMD_MTEST=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_BOOTM_ZLIB=y +CONFIG_CMD_BOOTM_BZLIB=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_UNLZO=y +CONFIG_NET=y +CONFIG_NET_DHCP=y +CONFIG_NET_NFS=y +CONFIG_NET_PING=y +CONFIG_NET_TFTP=y +CONFIG_NET_TFTP_PUSH=y +CONFIG_NET_NETCONSOLE=y +CONFIG_NET_RESOLV=y +# CONFIG_SPI is not set +CONFIG_MTD=y +CONFIG_FS_CRAMFS=y +CONFIG_FS_FAT=y +CONFIG_FS_FAT_WRITE=y +CONFIG_FS_FAT_LFN=y diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h new file mode 100644 index 0000000..608cfcf --- /dev/null +++ b/arch/mips/include/asm/asm.h @@ -0,0 +1,409 @@ +/* + * 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, 1997, 1999, 2001 by Ralf Baechle + * Copyright (C) 1999 by Silicon Graphics, Inc. + * Copyright (C) 2001 MIPS Technologies, Inc. + * Copyright (C) 2002 Maciej W. Rozycki + * + * Some useful macros for MIPS assembler code + * + * Some of the routines below contain useless nops that will be optimized + * away by gas in -O mode. These nops are however required to fill delay + * slots in noreorder mode. + */ +#ifndef __ASM_ASM_H +#define __ASM_ASM_H + +#include + +#ifndef CAT +#ifdef __STDC__ +#define __CAT(str1, str2) str1##str2 +#else +#define __CAT(str1, str2) str1/**/str2 +#endif +#define CAT(str1, str2) __CAT(str1, str2) +#endif + +/* + * PIC specific declarations + * Not used for the kernel but here seems to be the right place. + */ +#ifdef __PIC__ +#define CPRESTORE(register) \ + .cprestore register +#define CPADD(register) \ + .cpadd register +#define CPLOAD(register) \ + .cpload register +#else +#define CPRESTORE(register) +#define CPADD(register) +#define CPLOAD(register) +#endif + +/* + * LEAF - declare leaf routine + */ +#define LEAF(symbol) \ + .globl symbol; \ + .align 2; \ + .type symbol, @function; \ + .ent symbol, 0; \ +symbol: .frame sp, 0, ra + +/* + * NESTED - declare nested routine entry point + */ +#define NESTED(symbol, framesize, rpc) \ + .globl symbol; \ + .align 2; \ + .type symbol, @function; \ + .ent symbol, 0; \ +symbol: .frame sp, framesize, rpc + +/* + * END - mark end of function + */ +#define END(function) \ + .end function; \ + .size function, .-function + +/* + * EXPORT - export definition of symbol + */ +#define EXPORT(symbol) \ + .globl symbol; \ +symbol: + +/* + * FEXPORT - export definition of a function symbol + */ +#define FEXPORT(symbol) \ + .globl symbol; \ + .type symbol, @function; \ +symbol: + +/* + * ABS - export absolute symbol + */ +#define ABS(symbol,value) \ + .globl symbol; \ +symbol = value + +#define PANIC(msg) \ + .set push; \ + .set reorder; \ + PTR_LA a0, 8f; \ + jal panic; \ +9: b 9b; \ + .set pop; \ + TEXT(msg) + +/* + * Print formatted string + */ +#ifdef CONFIG_PRINTK +#define PRINT(string) \ + .set push; \ + .set reorder; \ + PTR_LA a0, 8f; \ + jal printk; \ + .set pop; \ + TEXT(string) +#else +#define PRINT(string) +#endif + +#define TEXT(msg) \ + .pushsection .data; \ +8: .asciiz msg; \ + .popsection; + +/* + * Build text tables + */ +#define TTABLE(string) \ + .pushsection .text; \ + .word 1f; \ + .popsection \ + .pushsection .data; \ +1: .asciiz string; \ + .popsection + +/* + * MIPS IV pref instruction. + * Use with .set noreorder only! + * + * MIPS IV implementations are free to treat this as a nop. The R5000 + * is one of them. So we should have an option not to use this instruction. + */ +#ifdef CONFIG_CPU_HAS_PREFETCH + +#define PREF(hint,addr) \ + .set push; \ + .set mips4; \ + pref hint, addr; \ + .set pop + +#define PREFX(hint,addr) \ + .set push; \ + .set mips4; \ + prefx hint, addr; \ + .set pop + +#else /* !CONFIG_CPU_HAS_PREFETCH */ + +#define PREF(hint, addr) +#define PREFX(hint, addr) + +#endif /* !CONFIG_CPU_HAS_PREFETCH */ + +/* + * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs. + */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) +#define MOVN(rd, rs, rt) \ + .set push; \ + .set reorder; \ + beqz rt, 9f; \ + move rd, rs; \ + .set pop; \ +9: +#define MOVZ(rd, rs, rt) \ + .set push; \ + .set reorder; \ + bnez rt, 9f; \ + move rd, rs; \ + .set pop; \ +9: +#endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) +#define MOVN(rd, rs, rt) \ + .set push; \ + .set noreorder; \ + bnezl rt, 9f; \ + move rd, rs; \ + .set pop; \ +9: +#define MOVZ(rd, rs, rt) \ + .set push; \ + .set noreorder; \ + beqzl rt, 9f; \ + move rd, rs; \ + .set pop; \ +9: +#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS4 ) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64) +#define MOVN(rd, rs, rt) \ + movn rd, rs, rt +#define MOVZ(rd, rs, rt) \ + movz rd, rs, rt +#endif /* MIPS IV, MIPS V, MIPS32 or MIPS64 */ + +/* + * Stack alignment + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) +#define ALSZ 7 +#define ALMASK ~7 +#endif +#if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) +#define ALSZ 15 +#define ALMASK ~15 +#endif + +/* + * Macros to handle different pointer/register sizes for 32/64-bit code + */ + +/* + * Size of a register + */ +#ifdef __mips64 +#define SZREG 8 +#else +#define SZREG 4 +#endif + +/* + * Use the following macros in assemblercode to load/store registers, + * pointers etc. + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) +#define REG_S sw +#define REG_L lw +#define REG_SUBU subu +#define REG_ADDU addu +#endif +#if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) +#define REG_S sd +#define REG_L ld +#define REG_SUBU dsubu +#define REG_ADDU daddu +#endif + +/* + * How to add/sub/load/store/shift C int variables. + */ +#if (_MIPS_SZINT == 32) +#define INT_ADD add +#define INT_ADDU addu +#define INT_ADDI addi +#define INT_ADDIU addiu +#define INT_SUB sub +#define INT_SUBU subu +#define INT_L lw +#define INT_S sw +#define INT_SLL sll +#define INT_SLLV sllv +#define INT_SRL srl +#define INT_SRLV srlv +#define INT_SRA sra +#define INT_SRAV srav +#endif + +#if (_MIPS_SZINT == 64) +#define INT_ADD dadd +#define INT_ADDU daddu +#define INT_ADDI daddi +#define INT_ADDIU daddiu +#define INT_SUB dsub +#define INT_SUBU dsubu +#define INT_L ld +#define INT_S sd +#define INT_SLL dsll +#define INT_SLLV dsllv +#define INT_SRL dsrl +#define INT_SRLV dsrlv +#define INT_SRA dsra +#define INT_SRAV dsrav +#endif + +/* + * How to add/sub/load/store/shift C long variables. + */ +#if (_MIPS_SZLONG == 32) +#define LONG_ADD add +#define LONG_ADDU addu +#define LONG_ADDI addi +#define LONG_ADDIU addiu +#define LONG_SUB sub +#define LONG_SUBU subu +#define LONG_L lw +#define LONG_S sw +#define LONG_SLL sll +#define LONG_SLLV sllv +#define LONG_SRL srl +#define LONG_SRLV srlv +#define LONG_SRA sra +#define LONG_SRAV srav + +#define LONG .word +#define LONGSIZE 4 +#define LONGMASK 3 +#define LONGLOG 2 +#endif + +#if (_MIPS_SZLONG == 64) +#define LONG_ADD dadd +#define LONG_ADDU daddu +#define LONG_ADDI daddi +#define LONG_ADDIU daddiu +#define LONG_SUB dsub +#define LONG_SUBU dsubu +#define LONG_L ld +#define LONG_S sd +#define LONG_SLL dsll +#define LONG_SLLV dsllv +#define LONG_SRL dsrl +#define LONG_SRLV dsrlv +#define LONG_SRA dsra +#define LONG_SRAV dsrav + +#define LONG .dword +#define LONGSIZE 8 +#define LONGMASK 7 +#define LONGLOG 3 +#endif + +/* + * How to add/sub/load/store/shift pointers. + */ +#if (_MIPS_SZPTR == 32) +#define PTR_ADD add +#define PTR_ADDU addu +#define PTR_ADDI addi +#define PTR_ADDIU addiu +#define PTR_SUB sub +#define PTR_SUBU subu +#define PTR_L lw +#define PTR_S sw +#define PTR_LA la +#define PTR_LI li +#define PTR_SLL sll +#define PTR_SLLV sllv +#define PTR_SRL srl +#define PTR_SRLV srlv +#define PTR_SRA sra +#define PTR_SRAV srav + +#define PTR_SCALESHIFT 2 + +#define PTR .word +#define PTRSIZE 4 +#define PTRLOG 2 +#endif + +#if (_MIPS_SZPTR == 64) +#define PTR_ADD dadd +#define PTR_ADDU daddu +#define PTR_ADDI daddi +#define PTR_ADDIU daddiu +#define PTR_SUB dsub +#define PTR_SUBU dsubu +#define PTR_L ld +#define PTR_S sd +#define PTR_LA dla +#define PTR_LI dli +#define PTR_SLL dsll +#define PTR_SLLV dsllv +#define PTR_SRL dsrl +#define PTR_SRLV dsrlv +#define PTR_SRA dsra +#define PTR_SRAV dsrav + +#define PTR_SCALESHIFT 3 + +#define PTR .dword +#define PTRSIZE 8 +#define PTRLOG 3 +#endif + +/* + * Some cp0 registers were extended to 64bit for MIPS III. + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) +#define MFC0 mfc0 +#define MTC0 mtc0 +#endif +#if (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) +#define MFC0 dmfc0 +#define MTC0 dmtc0 +#endif + +#define SSNOP sll zero, zero, 1 + +#ifdef CONFIG_SGI_IP28 +/* Inhibit speculative stores to volatile (e.g.DMA) or invalid addresses. */ +#include +#define R10KCBARRIER(addr) cache Cache_Barrier, addr; +#else +#define R10KCBARRIER(addr) +#endif + +#endif /* __ASM_ASM_H */ diff --git a/arch/mips/include/asm/barebox.h b/arch/mips/include/asm/barebox.h new file mode 100644 index 0000000..b42c9ff --- /dev/null +++ b/arch/mips/include/asm/barebox.h @@ -0,0 +1,24 @@ +/* + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _ASM_MIPS_BAREBOX_H_ +#define _ASM_MIPS_BAREBOX_H_ + +/* nothing special yet */ + +#endif /* _ASM_MIPS_BAREBOX_H_ */ diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h new file mode 100644 index 0000000..36d34b6 --- /dev/null +++ b/arch/mips/include/asm/bitops.h @@ -0,0 +1,32 @@ +/* + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/** + * @file + * @brief mips bit operations + * + * This file is required only to make all sources happy including + * 'linux/bitops.h' + */ + +#ifndef _ASM_MIPS_BITOPS_H_ +#define _ASM_MIPS_BITOPS_H_ + +/* nothing special yet */ + +#endif /* _ASM_MIPS_BITOPS_H_ */ diff --git a/arch/mips/include/asm/bitsperlong.h b/arch/mips/include/asm/bitsperlong.h new file mode 100644 index 0000000..3e4c10a --- /dev/null +++ b/arch/mips/include/asm/bitsperlong.h @@ -0,0 +1,8 @@ +#ifndef __ASM_MIPS_BITSPERLONG_H +#define __ASM_MIPS_BITSPERLONG_H + +#define __BITS_PER_LONG _MIPS_SZLONG + +#include + +#endif /* __ASM_MIPS_BITSPERLONG_H */ diff --git a/arch/mips/include/asm/byteorder.h b/arch/mips/include/asm/byteorder.h new file mode 100644 index 0000000..9579051 --- /dev/null +++ b/arch/mips/include/asm/byteorder.h @@ -0,0 +1,19 @@ +/* + * 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) 1996, 99, 2003 by Ralf Baechle + */ +#ifndef _ASM_BYTEORDER_H +#define _ASM_BYTEORDER_H + +#if defined(__MIPSEB__) +#include +#elif defined(__MIPSEL__) +#include +#else +# error "MIPS, but neither __MIPSEB__, nor __MIPSEL__???" +#endif + +#endif /* _ASM_BYTEORDER_H */ diff --git a/arch/mips/include/asm/common.h b/arch/mips/include/asm/common.h new file mode 100644 index 0000000..e37b6c5 --- /dev/null +++ b/arch/mips/include/asm/common.h @@ -0,0 +1,29 @@ +/* + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/** + * @file + * @brief mips common declarations + */ + +#ifndef _ASM_MIPS_COMMON_H_ +#define _ASM_MIPS_COMMON_H_ + +/* nothing special yet */ + +#endif /* _ASM_MIPS_COMMON_H_ */ diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h new file mode 100644 index 0000000..b8b8219 --- /dev/null +++ b/arch/mips/include/asm/elf.h @@ -0,0 +1,52 @@ +/* + * 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. + * + * Much of this is taken from binutils and GNU libc ... + */ + +/** + * @file + * @brief mips specific elf information + * + */ + +#ifndef _ASM_MIPS_ELF_H +#define _ASM_MIPS_ELF_H + +#ifndef ELF_ARCH + +#ifdef CONFIG_32BIT + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(hdr) \ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 + +#endif /* CONFIG_32BIT */ + +#ifdef CONFIG_64BIT +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS64 + +#endif /* CONFIG_64BIT */ + +/* + * These are used to set parameters in the core dumps. + */ +#ifdef __MIPSEB__ +#define ELF_DATA ELFDATA2MSB +#elif defined(__MIPSEL__) +#define ELF_DATA ELFDATA2LSB +#endif +#define ELF_ARCH EM_MIPS + +#endif /* !defined(ELF_ARCH) */ +#endif /* _ASM_MIPS_ELF_H */ diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h new file mode 100644 index 0000000..5e12860 --- /dev/null +++ b/arch/mips/include/asm/io.h @@ -0,0 +1,74 @@ +/* + * Stolen from the linux-2.6/include/asm-generic/io.h + */ + +/** + * @file + * @brief mips IO access functions + */ + +#ifndef __ASM_MIPS_IO_H +#define __ASM_MIPS_IO_H + +#include +#include +#include + +/*****************************************************************************/ +/* + * readX/writeX() are used to access memory mapped devices. On some + * architectures the memory mapped IO stuff needs to be accessed + * differently. On the simple architectures, we just read/write the + * memory location directly. + */ +#ifndef __raw_readb +static inline u8 __raw_readb(const volatile void __iomem *addr) +{ + return *(const volatile u8 __force *) addr; +} +#endif + +#ifndef __raw_readw +static inline u16 __raw_readw(const volatile void __iomem *addr) +{ + return *(const volatile u16 __force *) addr; +} +#endif + +#ifndef __raw_readl +static inline u32 __raw_readl(const volatile void __iomem *addr) +{ + return *(const volatile u32 __force *) addr; +} +#endif + +#define readb __raw_readb +#define readw(addr) __le16_to_cpu(__raw_readw(addr)) +#define readl(addr) __le32_to_cpu(__raw_readl(addr)) + +#ifndef __raw_writeb +static inline void __raw_writeb(u8 b, volatile void __iomem *addr) +{ + *(volatile u8 __force *) addr = b; +} +#endif + +#ifndef __raw_writew +static inline void __raw_writew(u16 b, volatile void __iomem *addr) +{ + *(volatile u16 __force *) addr = b; +} +#endif + +#ifndef __raw_writel +static inline void __raw_writel(u32 b, volatile void __iomem *addr) +{ + *(volatile u32 __force *) addr = b; +} +#endif + +#define writeb __raw_writeb +#define writew(b,addr) __raw_writew(__cpu_to_le16(b),addr) +#define writel(b,addr) __raw_writel(__cpu_to_le32(b),addr) + +#endif /* __ASM_MIPS_IO_H */ diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h new file mode 100644 index 0000000..befccbb --- /dev/null +++ b/arch/mips/include/asm/mipsregs.h @@ -0,0 +1,948 @@ +/* + * 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) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle + * Copyright (C) 2000 Silicon Graphics, Inc. + * Modified for further R[236]000 support by Paul M. Antoine, 1996. + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000, 07 MIPS Technologies, Inc. + * Copyright (C) 2003, 2004 Maciej W. Rozycki + */ +#ifndef _ASM_MIPSREGS_H +#define _ASM_MIPSREGS_H + +/* + * The following macros are especially useful for __asm__ + * inline assembler. + */ +#ifndef __STR +#define __STR(x) #x +#endif +#ifndef STR +#define STR(x) __STR(x) +#endif + +/* + * Configure language + */ +#ifdef __ASSEMBLY__ +#define _ULCAST_ +#else +#define _ULCAST_ (unsigned long) +#endif + +/* + * Coprocessor 0 register names + */ +#define CP0_INDEX $0 +#define CP0_RANDOM $1 +#define CP0_ENTRYLO0 $2 +#define CP0_ENTRYLO1 $3 +#define CP0_CONF $3 +#define CP0_CONTEXT $4 +#define CP0_PAGEMASK $5 +#define CP0_WIRED $6 +#define CP0_INFO $7 +#define CP0_BADVADDR $8 +#define CP0_COUNT $9 +#define CP0_ENTRYHI $10 +#define CP0_COMPARE $11 +#define CP0_STATUS $12 +#define CP0_CAUSE $13 +#define CP0_EPC $14 +#define CP0_PRID $15 +#define CP0_CONFIG $16 +#define CP0_LLADDR $17 +#define CP0_WATCHLO $18 +#define CP0_WATCHHI $19 +#define CP0_XCONTEXT $20 +#define CP0_FRAMEMASK $21 +#define CP0_DIAGNOSTIC $22 +#define CP0_DEBUG $23 +#define CP0_DEPC $24 +#define CP0_PERFORMANCE $25 +#define CP0_ECC $26 +#define CP0_CACHEERR $27 +#define CP0_TAGLO $28 +#define CP0_TAGHI $29 +#define CP0_ERROREPC $30 +#define CP0_DESAVE $31 + +/* + * R4640/R4650 cp0 register names. These registers are listed + * here only for completeness; without MMU these CPUs are not useable + * by Linux. A future ELKS port might take make Linux run on them + * though ... + */ +#define CP0_IBASE $0 +#define CP0_IBOUND $1 +#define CP0_DBASE $2 +#define CP0_DBOUND $3 +#define CP0_CALG $17 +#define CP0_IWATCH $18 +#define CP0_DWATCH $19 + +/* + * Coprocessor 0 Set 1 register names + */ +#define CP0_S1_DERRADDR0 $26 +#define CP0_S1_DERRADDR1 $27 +#define CP0_S1_INTCONTROL $20 + +/* + * Coprocessor 0 Set 2 register names + */ +#define CP0_S2_SRSCTL $12 /* MIPSR2 */ + +/* + * Coprocessor 0 Set 3 register names + */ +#define CP0_S3_SRSMAP $12 /* MIPSR2 */ + +/* + * TX39 Series + */ +#define CP0_TX39_CACHE $7 + +/* + * Coprocessor 1 (FPU) register names + */ +#define CP1_REVISION $0 +#define CP1_STATUS $31 + +/* + * FPU Status Register Values + */ +/* + * Status Register Values + */ + +#define FPU_CSR_FLUSH 0x01000000 /* flush denormalised results to 0 */ +#define FPU_CSR_COND 0x00800000 /* $fcc0 */ +#define FPU_CSR_COND0 0x00800000 /* $fcc0 */ +#define FPU_CSR_COND1 0x02000000 /* $fcc1 */ +#define FPU_CSR_COND2 0x04000000 /* $fcc2 */ +#define FPU_CSR_COND3 0x08000000 /* $fcc3 */ +#define FPU_CSR_COND4 0x10000000 /* $fcc4 */ +#define FPU_CSR_COND5 0x20000000 /* $fcc5 */ +#define FPU_CSR_COND6 0x40000000 /* $fcc6 */ +#define FPU_CSR_COND7 0x80000000 /* $fcc7 */ + +/* + * Bits 18 - 20 of the FPU Status Register will be read as 0, + * and should be written as zero. + */ +#define FPU_CSR_RSVD 0x001c0000 + +/* + * X the exception cause indicator + * E the exception enable + * S the sticky/flag bit +*/ +#define FPU_CSR_ALL_X 0x0003f000 +#define FPU_CSR_UNI_X 0x00020000 +#define FPU_CSR_INV_X 0x00010000 +#define FPU_CSR_DIV_X 0x00008000 +#define FPU_CSR_OVF_X 0x00004000 +#define FPU_CSR_UDF_X 0x00002000 +#define FPU_CSR_INE_X 0x00001000 + +#define FPU_CSR_ALL_E 0x00000f80 +#define FPU_CSR_INV_E 0x00000800 +#define FPU_CSR_DIV_E 0x00000400 +#define FPU_CSR_OVF_E 0x00000200 +#define FPU_CSR_UDF_E 0x00000100 +#define FPU_CSR_INE_E 0x00000080 + +#define FPU_CSR_ALL_S 0x0000007c +#define FPU_CSR_INV_S 0x00000040 +#define FPU_CSR_DIV_S 0x00000020 +#define FPU_CSR_OVF_S 0x00000010 +#define FPU_CSR_UDF_S 0x00000008 +#define FPU_CSR_INE_S 0x00000004 + +/* Bits 0 and 1 of FPU Status Register specify the rounding mode */ +#define FPU_CSR_RM 0x00000003 +#define FPU_CSR_RN 0x0 /* nearest */ +#define FPU_CSR_RZ 0x1 /* towards zero */ +#define FPU_CSR_RU 0x2 /* towards +Infinity */ +#define FPU_CSR_RD 0x3 /* towards -Infinity */ + +/* + * Values for PageMask register + */ +#ifdef CONFIG_CPU_VR41XX + +/* Why doesn't stupidity hurt ... */ + +#define PM_1K 0x00000000 +#define PM_4K 0x00001800 +#define PM_16K 0x00007800 +#define PM_64K 0x0001f800 +#define PM_256K 0x0007f800 + +#else + +#define PM_4K 0x00000000 +#define PM_8K 0x00002000 +#define PM_16K 0x00006000 +#define PM_32K 0x0000e000 +#define PM_64K 0x0001e000 +#define PM_128K 0x0003e000 +#define PM_256K 0x0007e000 +#define PM_512K 0x000fe000 +#define PM_1M 0x001fe000 +#define PM_2M 0x003fe000 +#define PM_4M 0x007fe000 +#define PM_8M 0x00ffe000 +#define PM_16M 0x01ffe000 +#define PM_32M 0x03ffe000 +#define PM_64M 0x07ffe000 +#define PM_256M 0x1fffe000 +#define PM_1G 0x7fffe000 + +#endif + +/* + * Bitfields in the R4xx0 cp0 status register + */ +#define ST0_IE 0x00000001 +#define ST0_EXL 0x00000002 +#define ST0_ERL 0x00000004 +#define ST0_KSU 0x00000018 +# define KSU_USER 0x00000010 +# define KSU_SUPERVISOR 0x00000008 +# define KSU_KERNEL 0x00000000 +#define ST0_UX 0x00000020 +#define ST0_SX 0x00000040 +#define ST0_KX 0x00000080 +#define ST0_DE 0x00010000 +#define ST0_CE 0x00020000 + +/* + * Setting c0_status.co enables Hit_Writeback and Hit_Writeback_Invalidate + * cacheops in userspace. This bit exists only on RM7000 and RM9000 + * processors. + */ +#define ST0_CO 0x08000000 + +/* + * Bitfields in the R[23]000 cp0 status register. + */ +#define ST0_IEC 0x00000001 +#define ST0_KUC 0x00000002 +#define ST0_IEP 0x00000004 +#define ST0_KUP 0x00000008 +#define ST0_IEO 0x00000010 +#define ST0_KUO 0x00000020 +/* bits 6 & 7 are reserved on R[23]000 */ +#define ST0_ISC 0x00010000 +#define ST0_SWC 0x00020000 +#define ST0_CM 0x00080000 + +/* + * Bits specific to the R4640/R4650 + */ +#define ST0_UM (_ULCAST_(1) << 4) +#define ST0_IL (_ULCAST_(1) << 23) +#define ST0_DL (_ULCAST_(1) << 24) + +/* + * Enable the MIPS MDMX and DSP ASEs + */ +#define ST0_MX 0x01000000 + +/* + * Status register bits available in all MIPS CPUs. + */ +#define ST0_IM 0x0000ff00 +#define STATUSB_IP0 8 +#define STATUSF_IP0 (_ULCAST_(1) << 8) +#define STATUSB_IP1 9 +#define STATUSF_IP1 (_ULCAST_(1) << 9) +#define STATUSB_IP2 10 +#define STATUSF_IP2 (_ULCAST_(1) << 10) +#define STATUSB_IP3 11 +#define STATUSF_IP3 (_ULCAST_(1) << 11) +#define STATUSB_IP4 12 +#define STATUSF_IP4 (_ULCAST_(1) << 12) +#define STATUSB_IP5 13 +#define STATUSF_IP5 (_ULCAST_(1) << 13) +#define STATUSB_IP6 14 +#define STATUSF_IP6 (_ULCAST_(1) << 14) +#define STATUSB_IP7 15 +#define STATUSF_IP7 (_ULCAST_(1) << 15) +#define STATUSB_IP8 0 +#define STATUSF_IP8 (_ULCAST_(1) << 0) +#define STATUSB_IP9 1 +#define STATUSF_IP9 (_ULCAST_(1) << 1) +#define STATUSB_IP10 2 +#define STATUSF_IP10 (_ULCAST_(1) << 2) +#define STATUSB_IP11 3 +#define STATUSF_IP11 (_ULCAST_(1) << 3) +#define STATUSB_IP12 4 +#define STATUSF_IP12 (_ULCAST_(1) << 4) +#define STATUSB_IP13 5 +#define STATUSF_IP13 (_ULCAST_(1) << 5) +#define STATUSB_IP14 6 +#define STATUSF_IP14 (_ULCAST_(1) << 6) +#define STATUSB_IP15 7 +#define STATUSF_IP15 (_ULCAST_(1) << 7) +#define ST0_CH 0x00040000 +#define ST0_NMI 0x00080000 +#define ST0_SR 0x00100000 +#define ST0_TS 0x00200000 +#define ST0_BEV 0x00400000 +#define ST0_RE 0x02000000 +#define ST0_FR 0x04000000 +#define ST0_CU 0xf0000000 +#define ST0_CU0 0x10000000 +#define ST0_CU1 0x20000000 +#define ST0_CU2 0x40000000 +#define ST0_CU3 0x80000000 +#define ST0_XX 0x80000000 /* MIPS IV naming */ + +/* + * Bitfields and bit numbers in the coprocessor 0 IntCtl register. (MIPSR2) + * + * Refer to your MIPS R4xx0 manual, chapter 5 for explanation. + */ +#define INTCTLB_IPPCI 26 +#define INTCTLF_IPPCI (_ULCAST_(7) << INTCTLB_IPPCI) +#define INTCTLB_IPTI 29 +#define INTCTLF_IPTI (_ULCAST_(7) << INTCTLB_IPTI) + +/* + * Bitfields and bit numbers in the coprocessor 0 cause register. + * + * Refer to your MIPS R4xx0 manual, chapter 5 for explanation. + */ +#define CAUSEB_EXCCODE 2 +#define CAUSEF_EXCCODE (_ULCAST_(31) << 2) +#define CAUSEB_IP 8 +#define CAUSEF_IP (_ULCAST_(255) << 8) +#define CAUSEB_IP0 8 +#define CAUSEF_IP0 (_ULCAST_(1) << 8) +#define CAUSEB_IP1 9 +#define CAUSEF_IP1 (_ULCAST_(1) << 9) +#define CAUSEB_IP2 10 +#define CAUSEF_IP2 (_ULCAST_(1) << 10) +#define CAUSEB_IP3 11 +#define CAUSEF_IP3 (_ULCAST_(1) << 11) +#define CAUSEB_IP4 12 +#define CAUSEF_IP4 (_ULCAST_(1) << 12) +#define CAUSEB_IP5 13 +#define CAUSEF_IP5 (_ULCAST_(1) << 13) +#define CAUSEB_IP6 14 +#define CAUSEF_IP6 (_ULCAST_(1) << 14) +#define CAUSEB_IP7 15 +#define CAUSEF_IP7 (_ULCAST_(1) << 15) +#define CAUSEB_IV 23 +#define CAUSEF_IV (_ULCAST_(1) << 23) +#define CAUSEB_CE 28 +#define CAUSEF_CE (_ULCAST_(3) << 28) +#define CAUSEB_TI 30 +#define CAUSEF_TI (_ULCAST_(1) << 30) +#define CAUSEB_BD 31 +#define CAUSEF_BD (_ULCAST_(1) << 31) + +/* + * Bits in the coprocessor 0 config register. + */ +/* Generic bits. */ +#define CONF_CM_CACHABLE_NO_WA 0 +#define CONF_CM_CACHABLE_WA 1 +#define CONF_CM_UNCACHED 2 +#define CONF_CM_CACHABLE_NONCOHERENT 3 +#define CONF_CM_CACHABLE_CE 4 +#define CONF_CM_CACHABLE_COW 5 +#define CONF_CM_CACHABLE_CUW 6 +#define CONF_CM_CACHABLE_ACCELERATED 7 +#define CONF_CM_CMASK 7 +#define CONF_BE (_ULCAST_(1) << 15) + +/* Bits common to various processors. */ +#define CONF_CU (_ULCAST_(1) << 3) +#define CONF_DB (_ULCAST_(1) << 4) +#define CONF_IB (_ULCAST_(1) << 5) +#define CONF_DC (_ULCAST_(7) << 6) +#define CONF_IC (_ULCAST_(7) << 9) +#define CONF_EB (_ULCAST_(1) << 13) +#define CONF_EM (_ULCAST_(1) << 14) +#define CONF_SM (_ULCAST_(1) << 16) +#define CONF_SC (_ULCAST_(1) << 17) +#define CONF_EW (_ULCAST_(3) << 18) +#define CONF_EP (_ULCAST_(15)<< 24) +#define CONF_EC (_ULCAST_(7) << 28) +#define CONF_CM (_ULCAST_(1) << 31) + +/* Bits specific to the R4xx0. */ +#define R4K_CONF_SW (_ULCAST_(1) << 20) +#define R4K_CONF_SS (_ULCAST_(1) << 21) +#define R4K_CONF_SB (_ULCAST_(3) << 22) + +/* Bits specific to the R5000. */ +#define R5K_CONF_SE (_ULCAST_(1) << 12) +#define R5K_CONF_SS (_ULCAST_(3) << 20) + +/* Bits specific to the RM7000. */ +#define RM7K_CONF_SE (_ULCAST_(1) << 3) +#define RM7K_CONF_TE (_ULCAST_(1) << 12) +#define RM7K_CONF_CLK (_ULCAST_(1) << 16) +#define RM7K_CONF_TC (_ULCAST_(1) << 17) +#define RM7K_CONF_SI (_ULCAST_(3) << 20) +#define RM7K_CONF_SC (_ULCAST_(1) << 31) + +/* Bits specific to the R10000. */ +#define R10K_CONF_DN (_ULCAST_(3) << 3) +#define R10K_CONF_CT (_ULCAST_(1) << 5) +#define R10K_CONF_PE (_ULCAST_(1) << 6) +#define R10K_CONF_PM (_ULCAST_(3) << 7) +#define R10K_CONF_EC (_ULCAST_(15)<< 9) +#define R10K_CONF_SB (_ULCAST_(1) << 13) +#define R10K_CONF_SK (_ULCAST_(1) << 14) +#define R10K_CONF_SS (_ULCAST_(7) << 16) +#define R10K_CONF_SC (_ULCAST_(7) << 19) +#define R10K_CONF_DC (_ULCAST_(7) << 26) +#define R10K_CONF_IC (_ULCAST_(7) << 29) + +/* Bits specific to the R30xx. */ +#define R30XX_CONF_FDM (_ULCAST_(1) << 19) +#define R30XX_CONF_REV (_ULCAST_(1) << 22) +#define R30XX_CONF_AC (_ULCAST_(1) << 23) +#define R30XX_CONF_RF (_ULCAST_(1) << 24) +#define R30XX_CONF_HALT (_ULCAST_(1) << 25) +#define R30XX_CONF_FPINT (_ULCAST_(7) << 26) +#define R30XX_CONF_DBR (_ULCAST_(1) << 29) +#define R30XX_CONF_SB (_ULCAST_(1) << 30) +#define R30XX_CONF_LOCK (_ULCAST_(1) << 31) + +/* Bits specific to the TX49. */ +#define TX49_CONF_DC (_ULCAST_(1) << 16) +#define TX49_CONF_IC (_ULCAST_(1) << 17) /* conflict with CONF_SC */ +#define TX49_CONF_HALT (_ULCAST_(1) << 18) +#define TX49_CONF_CWFON (_ULCAST_(1) << 27) + +/* Bits specific to the MIPS32/64 PRA. */ +#define MIPS_CONF_MT (_ULCAST_(7) << 7) +#define MIPS_CONF_AR (_ULCAST_(7) << 10) +#define MIPS_CONF_AT (_ULCAST_(3) << 13) +#define MIPS_CONF_M (_ULCAST_(1) << 31) + +/* + * Bits in the MIPS32/64 PRA coprocessor 0 config registers 1 and above. + */ +#define MIPS_CONF1_FP (_ULCAST_(1) << 0) +#define MIPS_CONF1_EP (_ULCAST_(1) << 1) +#define MIPS_CONF1_CA (_ULCAST_(1) << 2) +#define MIPS_CONF1_WR (_ULCAST_(1) << 3) +#define MIPS_CONF1_PC (_ULCAST_(1) << 4) +#define MIPS_CONF1_MD (_ULCAST_(1) << 5) +#define MIPS_CONF1_C2 (_ULCAST_(1) << 6) +#define MIPS_CONF1_DA (_ULCAST_(7) << 7) +#define MIPS_CONF1_DL (_ULCAST_(7) << 10) +#define MIPS_CONF1_DS (_ULCAST_(7) << 13) +#define MIPS_CONF1_IA (_ULCAST_(7) << 16) +#define MIPS_CONF1_IL (_ULCAST_(7) << 19) +#define MIPS_CONF1_IS (_ULCAST_(7) << 22) +#define MIPS_CONF1_TLBS (_ULCAST_(63)<< 25) + +#define MIPS_CONF2_SA (_ULCAST_(15)<< 0) +#define MIPS_CONF2_SL (_ULCAST_(15)<< 4) +#define MIPS_CONF2_SS (_ULCAST_(15)<< 8) +#define MIPS_CONF2_SU (_ULCAST_(15)<< 12) +#define MIPS_CONF2_TA (_ULCAST_(15)<< 16) +#define MIPS_CONF2_TL (_ULCAST_(15)<< 20) +#define MIPS_CONF2_TS (_ULCAST_(15)<< 24) +#define MIPS_CONF2_TU (_ULCAST_(7) << 28) + +#define MIPS_CONF3_TL (_ULCAST_(1) << 0) +#define MIPS_CONF3_SM (_ULCAST_(1) << 1) +#define MIPS_CONF3_MT (_ULCAST_(1) << 2) +#define MIPS_CONF3_SP (_ULCAST_(1) << 4) +#define MIPS_CONF3_VINT (_ULCAST_(1) << 5) +#define MIPS_CONF3_VEIC (_ULCAST_(1) << 6) +#define MIPS_CONF3_LPA (_ULCAST_(1) << 7) +#define MIPS_CONF3_DSP (_ULCAST_(1) << 10) +#define MIPS_CONF3_ULRI (_ULCAST_(1) << 13) + +#define MIPS_CONF4_MMUSIZEEXT (_ULCAST_(255) << 0) +#define MIPS_CONF4_MMUEXTDEF (_ULCAST_(3) << 14) +#define MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT (_ULCAST_(1) << 14) + +#define MIPS_CONF7_WII (_ULCAST_(1) << 31) + +#define MIPS_CONF7_RPS (_ULCAST_(1) << 2) + + +/* + * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register. + */ +#define MIPS_FPIR_S (_ULCAST_(1) << 16) +#define MIPS_FPIR_D (_ULCAST_(1) << 17) +#define MIPS_FPIR_PS (_ULCAST_(1) << 18) +#define MIPS_FPIR_3D (_ULCAST_(1) << 19) +#define MIPS_FPIR_W (_ULCAST_(1) << 20) +#define MIPS_FPIR_L (_ULCAST_(1) << 21) +#define MIPS_FPIR_F64 (_ULCAST_(1) << 22) + +#ifndef __ASSEMBLY__ + +/* + * Macros to access the system control coprocessor + */ + +#define __read_32bit_c0_register(source, sel) \ +({ int __res; \ + if (sel == 0) \ + __asm__ __volatile__( \ + "mfc0\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips32\n\t" \ + "mfc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tmips0\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __read_64bit_c0_register(source, sel) \ +({ unsigned long long __res; \ + if (sizeof(unsigned long) == 4) \ + __res = __read_64bit_c0_split(source, sel); \ + else if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips3\n\t" \ + "dmfc0\t%0, " #source "\n\t" \ + ".set\tmips0" \ + : "=r" (__res)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmfc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tmips0" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __write_32bit_c0_register(register, sel, value) \ +do { \ + if (sel == 0) \ + __asm__ __volatile__( \ + "mtc0\t%z0, " #register "\n\t" \ + : : "Jr" ((unsigned int)(value))); \ + else \ + __asm__ __volatile__( \ + ".set\tmips32\n\t" \ + "mtc0\t%z0, " #register ", " #sel "\n\t" \ + ".set\tmips0" \ + : : "Jr" ((unsigned int)(value))); \ +} while (0) + +#define __write_64bit_c0_register(register, sel, value) \ +do { \ + if (sizeof(unsigned long) == 4) \ + __write_64bit_c0_split(register, sel, value); \ + else if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips3\n\t" \ + "dmtc0\t%z0, " #register "\n\t" \ + ".set\tmips0" \ + : : "Jr" (value)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmtc0\t%z0, " #register ", " #sel "\n\t" \ + ".set\tmips0" \ + : : "Jr" (value)); \ +} while (0) + +#define __read_ulong_c0_register(reg, sel) \ + ((sizeof(unsigned long) == 4) ? \ + (unsigned long) __read_32bit_c0_register(reg, sel) : \ + (unsigned long) __read_64bit_c0_register(reg, sel)) + +#define __write_ulong_c0_register(reg, sel, val) \ +do { \ + if (sizeof(unsigned long) == 4) \ + __write_32bit_c0_register(reg, sel, val); \ + else \ + __write_64bit_c0_register(reg, sel, val); \ +} while (0) + +/* + * On RM7000/RM9000 these are uses to access cop0 set 1 registers + */ +#define __read_32bit_c0_ctrl_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + "cfc0\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __write_32bit_c0_ctrl_register(register, value) \ +do { \ + __asm__ __volatile__( \ + "ctc0\t%z0, " #register "\n\t" \ + : : "Jr" ((unsigned int)(value))); \ +} while (0) + +/* + * These versions are only needed for systems with more than 38 bits of + * physical address space running the 32-bit kernel. That's none atm :-) + */ +#define __read_64bit_c0_split(source, sel) \ +({ \ + unsigned long long __val; \ + unsigned long __flags; \ + \ + local_irq_save(__flags); \ + if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmfc0\t%M0, " #source "\n\t" \ + "dsll\t%L0, %M0, 32\n\t" \ + "dsra\t%M0, %M0, 32\n\t" \ + "dsra\t%L0, %L0, 32\n\t" \ + ".set\tmips0" \ + : "=r" (__val)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dmfc0\t%M0, " #source ", " #sel "\n\t" \ + "dsll\t%L0, %M0, 32\n\t" \ + "dsra\t%M0, %M0, 32\n\t" \ + "dsra\t%L0, %L0, 32\n\t" \ + ".set\tmips0" \ + : "=r" (__val)); \ + local_irq_restore(__flags); \ + \ + __val; \ +}) + +#define __write_64bit_c0_split(source, sel, val) \ +do { \ + unsigned long __flags; \ + \ + local_irq_save(__flags); \ + if (sel == 0) \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dsll\t%L0, %L0, 32\n\t" \ + "dsrl\t%L0, %L0, 32\n\t" \ + "dsll\t%M0, %M0, 32\n\t" \ + "or\t%L0, %L0, %M0\n\t" \ + "dmtc0\t%L0, " #source "\n\t" \ + ".set\tmips0" \ + : : "r" (val)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips64\n\t" \ + "dsll\t%L0, %L0, 32\n\t" \ + "dsrl\t%L0, %L0, 32\n\t" \ + "dsll\t%M0, %M0, 32\n\t" \ + "or\t%L0, %L0, %M0\n\t" \ + "dmtc0\t%L0, " #source ", " #sel "\n\t" \ + ".set\tmips0" \ + : : "r" (val)); \ + local_irq_restore(__flags); \ +} while (0) + +#define read_c0_index() __read_32bit_c0_register($0, 0) +#define write_c0_index(val) __write_32bit_c0_register($0, 0, val) + +#define read_c0_random() __read_32bit_c0_register($1, 0) +#define write_c0_random(val) __write_32bit_c0_register($1, 0, val) + +#define read_c0_entrylo0() __read_ulong_c0_register($2, 0) +#define write_c0_entrylo0(val) __write_ulong_c0_register($2, 0, val) + +#define read_c0_entrylo1() __read_ulong_c0_register($3, 0) +#define write_c0_entrylo1(val) __write_ulong_c0_register($3, 0, val) + +#define read_c0_conf() __read_32bit_c0_register($3, 0) +#define write_c0_conf(val) __write_32bit_c0_register($3, 0, val) + +#define read_c0_context() __read_ulong_c0_register($4, 0) +#define write_c0_context(val) __write_ulong_c0_register($4, 0, val) + +#define read_c0_userlocal() __read_ulong_c0_register($4, 2) +#define write_c0_userlocal(val) __write_ulong_c0_register($4, 2, val) + +#define read_c0_pagemask() __read_32bit_c0_register($5, 0) +#define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val) + +#define read_c0_pagegrain() __read_32bit_c0_register($5, 1) +#define write_c0_pagegrain(val) __write_32bit_c0_register($5, 1, val) + +#define read_c0_wired() __read_32bit_c0_register($6, 0) +#define write_c0_wired(val) __write_32bit_c0_register($6, 0, val) + +#define read_c0_info() __read_32bit_c0_register($7, 0) + +#define read_c0_cache() __read_32bit_c0_register($7, 0) /* TX39xx */ +#define write_c0_cache(val) __write_32bit_c0_register($7, 0, val) + +#define read_c0_badvaddr() __read_ulong_c0_register($8, 0) +#define write_c0_badvaddr(val) __write_ulong_c0_register($8, 0, val) + +#define read_c0_count() __read_32bit_c0_register($9, 0) +#define write_c0_count(val) __write_32bit_c0_register($9, 0, val) + +#define read_c0_count2() __read_32bit_c0_register($9, 6) /* pnx8550 */ +#define write_c0_count2(val) __write_32bit_c0_register($9, 6, val) + +#define read_c0_count3() __read_32bit_c0_register($9, 7) /* pnx8550 */ +#define write_c0_count3(val) __write_32bit_c0_register($9, 7, val) + +#define read_c0_entryhi() __read_ulong_c0_register($10, 0) +#define write_c0_entryhi(val) __write_ulong_c0_register($10, 0, val) + +#define read_c0_compare() __read_32bit_c0_register($11, 0) +#define write_c0_compare(val) __write_32bit_c0_register($11, 0, val) + +#define read_c0_compare2() __read_32bit_c0_register($11, 6) /* pnx8550 */ +#define write_c0_compare2(val) __write_32bit_c0_register($11, 6, val) + +#define read_c0_compare3() __read_32bit_c0_register($11, 7) /* pnx8550 */ +#define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val) + +#define read_c0_status() __read_32bit_c0_register($12, 0) +#ifdef CONFIG_MIPS_MT_SMTC +#define write_c0_status(val) \ +do { \ + __write_32bit_c0_register($12, 0, val); \ + __ehb(); \ +} while (0) +#else +/* + * Legacy non-SMTC code, which may be hazardous + * but which might not support EHB + */ +#define write_c0_status(val) __write_32bit_c0_register($12, 0, val) +#endif /* CONFIG_MIPS_MT_SMTC */ + +#define read_c0_cause() __read_32bit_c0_register($13, 0) +#define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) + +#define read_c0_epc() __read_ulong_c0_register($14, 0) +#define write_c0_epc(val) __write_ulong_c0_register($14, 0, val) + +#define read_c0_prid() __read_32bit_c0_register($15, 0) + +#define read_c0_config() __read_32bit_c0_register($16, 0) +#define read_c0_config1() __read_32bit_c0_register($16, 1) +#define read_c0_config2() __read_32bit_c0_register($16, 2) +#define read_c0_config3() __read_32bit_c0_register($16, 3) +#define read_c0_config4() __read_32bit_c0_register($16, 4) +#define read_c0_config5() __read_32bit_c0_register($16, 5) +#define read_c0_config6() __read_32bit_c0_register($16, 6) +#define read_c0_config7() __read_32bit_c0_register($16, 7) +#define write_c0_config(val) __write_32bit_c0_register($16, 0, val) +#define write_c0_config1(val) __write_32bit_c0_register($16, 1, val) +#define write_c0_config2(val) __write_32bit_c0_register($16, 2, val) +#define write_c0_config3(val) __write_32bit_c0_register($16, 3, val) +#define write_c0_config4(val) __write_32bit_c0_register($16, 4, val) +#define write_c0_config5(val) __write_32bit_c0_register($16, 5, val) +#define write_c0_config6(val) __write_32bit_c0_register($16, 6, val) +#define write_c0_config7(val) __write_32bit_c0_register($16, 7, val) + +/* + * The WatchLo register. There may be up to 8 of them. + */ +#define read_c0_watchlo0() __read_ulong_c0_register($18, 0) +#define read_c0_watchlo1() __read_ulong_c0_register($18, 1) +#define read_c0_watchlo2() __read_ulong_c0_register($18, 2) +#define read_c0_watchlo3() __read_ulong_c0_register($18, 3) +#define read_c0_watchlo4() __read_ulong_c0_register($18, 4) +#define read_c0_watchlo5() __read_ulong_c0_register($18, 5) +#define read_c0_watchlo6() __read_ulong_c0_register($18, 6) +#define read_c0_watchlo7() __read_ulong_c0_register($18, 7) +#define write_c0_watchlo0(val) __write_ulong_c0_register($18, 0, val) +#define write_c0_watchlo1(val) __write_ulong_c0_register($18, 1, val) +#define write_c0_watchlo2(val) __write_ulong_c0_register($18, 2, val) +#define write_c0_watchlo3(val) __write_ulong_c0_register($18, 3, val) +#define write_c0_watchlo4(val) __write_ulong_c0_register($18, 4, val) +#define write_c0_watchlo5(val) __write_ulong_c0_register($18, 5, val) +#define write_c0_watchlo6(val) __write_ulong_c0_register($18, 6, val) +#define write_c0_watchlo7(val) __write_ulong_c0_register($18, 7, val) + +/* + * The WatchHi register. There may be up to 8 of them. + */ +#define read_c0_watchhi0() __read_32bit_c0_register($19, 0) +#define read_c0_watchhi1() __read_32bit_c0_register($19, 1) +#define read_c0_watchhi2() __read_32bit_c0_register($19, 2) +#define read_c0_watchhi3() __read_32bit_c0_register($19, 3) +#define read_c0_watchhi4() __read_32bit_c0_register($19, 4) +#define read_c0_watchhi5() __read_32bit_c0_register($19, 5) +#define read_c0_watchhi6() __read_32bit_c0_register($19, 6) +#define read_c0_watchhi7() __read_32bit_c0_register($19, 7) + +#define write_c0_watchhi0(val) __write_32bit_c0_register($19, 0, val) +#define write_c0_watchhi1(val) __write_32bit_c0_register($19, 1, val) +#define write_c0_watchhi2(val) __write_32bit_c0_register($19, 2, val) +#define write_c0_watchhi3(val) __write_32bit_c0_register($19, 3, val) +#define write_c0_watchhi4(val) __write_32bit_c0_register($19, 4, val) +#define write_c0_watchhi5(val) __write_32bit_c0_register($19, 5, val) +#define write_c0_watchhi6(val) __write_32bit_c0_register($19, 6, val) +#define write_c0_watchhi7(val) __write_32bit_c0_register($19, 7, val) + +#define read_c0_xcontext() __read_ulong_c0_register($20, 0) +#define write_c0_xcontext(val) __write_ulong_c0_register($20, 0, val) + +#define read_c0_intcontrol() __read_32bit_c0_ctrl_register($20) +#define write_c0_intcontrol(val) __write_32bit_c0_ctrl_register($20, val) + +#define read_c0_framemask() __read_32bit_c0_register($21, 0) +#define write_c0_framemask(val) __write_32bit_c0_register($21, 0, val) + +/* RM9000 PerfControl performance counter control register */ +#define read_c0_perfcontrol() __read_32bit_c0_register($22, 0) +#define write_c0_perfcontrol(val) __write_32bit_c0_register($22, 0, val) + +#define read_c0_diag() __read_32bit_c0_register($22, 0) +#define write_c0_diag(val) __write_32bit_c0_register($22, 0, val) + +#define read_c0_diag1() __read_32bit_c0_register($22, 1) +#define write_c0_diag1(val) __write_32bit_c0_register($22, 1, val) + +#define read_c0_diag2() __read_32bit_c0_register($22, 2) +#define write_c0_diag2(val) __write_32bit_c0_register($22, 2, val) + +#define read_c0_diag3() __read_32bit_c0_register($22, 3) +#define write_c0_diag3(val) __write_32bit_c0_register($22, 3, val) + +#define read_c0_diag4() __read_32bit_c0_register($22, 4) +#define write_c0_diag4(val) __write_32bit_c0_register($22, 4, val) + +#define read_c0_diag5() __read_32bit_c0_register($22, 5) +#define write_c0_diag5(val) __write_32bit_c0_register($22, 5, val) + +#define read_c0_debug() __read_32bit_c0_register($23, 0) +#define write_c0_debug(val) __write_32bit_c0_register($23, 0, val) + +#define read_c0_depc() __read_ulong_c0_register($24, 0) +#define write_c0_depc(val) __write_ulong_c0_register($24, 0, val) + +/* + * MIPS32 / MIPS64 performance counters + */ +#define read_c0_perfctrl0() __read_32bit_c0_register($25, 0) +#define write_c0_perfctrl0(val) __write_32bit_c0_register($25, 0, val) +#define read_c0_perfcntr0() __read_32bit_c0_register($25, 1) +#define write_c0_perfcntr0(val) __write_32bit_c0_register($25, 1, val) +#define read_c0_perfctrl1() __read_32bit_c0_register($25, 2) +#define write_c0_perfctrl1(val) __write_32bit_c0_register($25, 2, val) +#define read_c0_perfcntr1() __read_32bit_c0_register($25, 3) +#define write_c0_perfcntr1(val) __write_32bit_c0_register($25, 3, val) +#define read_c0_perfctrl2() __read_32bit_c0_register($25, 4) +#define write_c0_perfctrl2(val) __write_32bit_c0_register($25, 4, val) +#define read_c0_perfcntr2() __read_32bit_c0_register($25, 5) +#define write_c0_perfcntr2(val) __write_32bit_c0_register($25, 5, val) +#define read_c0_perfctrl3() __read_32bit_c0_register($25, 6) +#define write_c0_perfctrl3(val) __write_32bit_c0_register($25, 6, val) +#define read_c0_perfcntr3() __read_32bit_c0_register($25, 7) +#define write_c0_perfcntr3(val) __write_32bit_c0_register($25, 7, val) + +/* RM9000 PerfCount performance counter register */ +#define read_c0_perfcount() __read_64bit_c0_register($25, 0) +#define write_c0_perfcount(val) __write_64bit_c0_register($25, 0, val) + +#define read_c0_ecc() __read_32bit_c0_register($26, 0) +#define write_c0_ecc(val) __write_32bit_c0_register($26, 0, val) + +#define read_c0_derraddr0() __read_ulong_c0_register($26, 1) +#define write_c0_derraddr0(val) __write_ulong_c0_register($26, 1, val) + +#define read_c0_cacheerr() __read_32bit_c0_register($27, 0) + +#define read_c0_derraddr1() __read_ulong_c0_register($27, 1) +#define write_c0_derraddr1(val) __write_ulong_c0_register($27, 1, val) + +#define read_c0_taglo() __read_32bit_c0_register($28, 0) +#define write_c0_taglo(val) __write_32bit_c0_register($28, 0, val) + +#define read_c0_dtaglo() __read_32bit_c0_register($28, 2) +#define write_c0_dtaglo(val) __write_32bit_c0_register($28, 2, val) + +#define read_c0_ddatalo() __read_32bit_c0_register($28, 3) +#define write_c0_ddatalo(val) __write_32bit_c0_register($28, 3, val) + +#define read_c0_staglo() __read_32bit_c0_register($28, 4) +#define write_c0_staglo(val) __write_32bit_c0_register($28, 4, val) + +#define read_c0_taghi() __read_32bit_c0_register($29, 0) +#define write_c0_taghi(val) __write_32bit_c0_register($29, 0, val) + +#define read_c0_errorepc() __read_ulong_c0_register($30, 0) +#define write_c0_errorepc(val) __write_ulong_c0_register($30, 0, val) + +/* MIPSR2 */ +#define read_c0_hwrena() __read_32bit_c0_register($7, 0) +#define write_c0_hwrena(val) __write_32bit_c0_register($7, 0, val) + +#define read_c0_intctl() __read_32bit_c0_register($12, 1) +#define write_c0_intctl(val) __write_32bit_c0_register($12, 1, val) + +#define read_c0_srsctl() __read_32bit_c0_register($12, 2) +#define write_c0_srsctl(val) __write_32bit_c0_register($12, 2, val) + +#define read_c0_srsmap() __read_32bit_c0_register($12, 3) +#define write_c0_srsmap(val) __write_32bit_c0_register($12, 3, val) + +#define read_c0_ebase() __read_32bit_c0_register($15, 1) +#define write_c0_ebase(val) __write_32bit_c0_register($15, 1, val) + +/* BMIPS3300 */ +#define read_c0_brcm_config_0() __read_32bit_c0_register($22, 0) +#define write_c0_brcm_config_0(val) __write_32bit_c0_register($22, 0, val) + +#define read_c0_brcm_bus_pll() __read_32bit_c0_register($22, 4) +#define write_c0_brcm_bus_pll(val) __write_32bit_c0_register($22, 4, val) + +#define read_c0_brcm_reset() __read_32bit_c0_register($22, 5) +#define write_c0_brcm_reset(val) __write_32bit_c0_register($22, 5, val) + +/* BMIPS4380 */ +#define read_c0_brcm_cmt_intr() __read_32bit_c0_register($22, 1) +#define write_c0_brcm_cmt_intr(val) __write_32bit_c0_register($22, 1, val) + +#define read_c0_brcm_cmt_ctrl() __read_32bit_c0_register($22, 2) +#define write_c0_brcm_cmt_ctrl(val) __write_32bit_c0_register($22, 2, val) + +#define read_c0_brcm_cmt_local() __read_32bit_c0_register($22, 3) +#define write_c0_brcm_cmt_local(val) __write_32bit_c0_register($22, 3, val) + +#define read_c0_brcm_config_1() __read_32bit_c0_register($22, 5) +#define write_c0_brcm_config_1(val) __write_32bit_c0_register($22, 5, val) + +#define read_c0_brcm_cbr() __read_32bit_c0_register($22, 6) +#define write_c0_brcm_cbr(val) __write_32bit_c0_register($22, 6, val) + +/* BMIPS5000 */ +#define read_c0_brcm_config() __read_32bit_c0_register($22, 0) +#define write_c0_brcm_config(val) __write_32bit_c0_register($22, 0, val) + +#define read_c0_brcm_mode() __read_32bit_c0_register($22, 1) +#define write_c0_brcm_mode(val) __write_32bit_c0_register($22, 1, val) + +#define read_c0_brcm_action() __read_32bit_c0_register($22, 2) +#define write_c0_brcm_action(val) __write_32bit_c0_register($22, 2, val) + +#define read_c0_brcm_edsp() __read_32bit_c0_register($22, 3) +#define write_c0_brcm_edsp(val) __write_32bit_c0_register($22, 3, val) + +#define read_c0_brcm_bootvec() __read_32bit_c0_register($22, 4) +#define write_c0_brcm_bootvec(val) __write_32bit_c0_register($22, 4, val) + +#define read_c0_brcm_sleepcount() __read_32bit_c0_register($22, 7) +#define write_c0_brcm_sleepcount(val) __write_32bit_c0_register($22, 7, val) + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_MIPSREGS_H */ diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h new file mode 100644 index 0000000..3046220 --- /dev/null +++ b/arch/mips/include/asm/module.h @@ -0,0 +1,24 @@ +/* + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _ASM_MIPS_MODULE_H_ +#define _ASM_MIPS_MODULE_H_ + +/* nothing special yet */ + +#endif /* _ASM_MIPS_MODULE_H_ */ diff --git a/arch/mips/include/asm/posix_types.h b/arch/mips/include/asm/posix_types.h new file mode 100644 index 0000000..bbeb721 --- /dev/null +++ b/arch/mips/include/asm/posix_types.h @@ -0,0 +1,144 @@ +/* + * 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) 1996, 97, 98, 99, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_POSIX_TYPES_H +#define _ASM_POSIX_TYPES_H + +#include + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +#if (_MIPS_SZLONG == 32) +typedef unsigned long __kernel_nlink_t; +#endif +#if (_MIPS_SZLONG == 64) +typedef unsigned int __kernel_nlink_t; +#endif +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +#if (_MIPS_SZLONG == 32) +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +#endif +#if (_MIPS_SZLONG == 64) +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +#endif +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef long __kernel_daddr_t; +typedef char * __kernel_caddr_t; + +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; +typedef unsigned int __kernel_old_dev_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { +#if (_MIPS_SZLONG == 32) + long val[2]; +#endif +#if (_MIPS_SZLONG == 64) + int val[2]; +#endif +} __kernel_fsid_t; + +#if defined(__KERNEL__) + +#undef __FD_SET +static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp) +{ + unsigned long __tmp = __fd / __NFDBITS; + unsigned long __rem = __fd % __NFDBITS; + __fdsetp->fds_bits[__tmp] |= (1UL<<__rem); +} + +#undef __FD_CLR +static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp) +{ + unsigned long __tmp = __fd / __NFDBITS; + unsigned long __rem = __fd % __NFDBITS; + __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem); +} + +#undef __FD_ISSET +static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p) +{ + unsigned long __tmp = __fd / __NFDBITS; + unsigned long __rem = __fd % __NFDBITS; + return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0; +} + +/* + * This will unroll the loop for the normal constant case (8 ints, + * for a 256-bit fd_set) + */ +#undef __FD_ZERO +static __inline__ void __FD_ZERO(__kernel_fd_set *__p) +{ + unsigned long *__tmp = __p->fds_bits; + int __i; + + if (__builtin_constant_p(__FDSET_LONGS)) { + switch (__FDSET_LONGS) { + case 16: + __tmp[0] = 0; __tmp[1] = 0; + __tmp[2] = 0; __tmp[3] = 0; + __tmp[4] = 0; __tmp[5] = 0; + __tmp[6] = 0; __tmp[7] = 0; + __tmp[8] = 0; __tmp[9] = 0; + __tmp[10] = 0; __tmp[11] = 0; + __tmp[12] = 0; __tmp[13] = 0; + __tmp[14] = 0; __tmp[15] = 0; + return; + + case 8: + __tmp[0] = 0; __tmp[1] = 0; + __tmp[2] = 0; __tmp[3] = 0; + __tmp[4] = 0; __tmp[5] = 0; + __tmp[6] = 0; __tmp[7] = 0; + return; + + case 4: + __tmp[0] = 0; __tmp[1] = 0; + __tmp[2] = 0; __tmp[3] = 0; + return; + } + } + __i = __FDSET_LONGS; + while (__i) { + __i--; + *__tmp = 0; + __tmp++; + } +} + +#endif /* defined(__KERNEL__) */ + +#endif /* _ASM_POSIX_TYPES_H */ diff --git a/arch/mips/include/asm/regdef.h b/arch/mips/include/asm/regdef.h new file mode 100644 index 0000000..7c8ecb6 --- /dev/null +++ b/arch/mips/include/asm/regdef.h @@ -0,0 +1,100 @@ +/* + * 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) 1985 MIPS Computer Systems, Inc. + * Copyright (C) 1994, 95, 99, 2003 by Ralf Baechle + * Copyright (C) 1990 - 1992, 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_REGDEF_H +#define _ASM_REGDEF_H + +#include + +#if _MIPS_SIM == _MIPS_SIM_ABI32 + +/* + * Symbolic register names for 32 bit ABI + */ +#define zero $0 /* wired zero */ +#define AT $1 /* assembler temp - uppercase because of ".set at" */ +#define v0 $2 /* return value */ +#define v1 $3 +#define a0 $4 /* argument registers */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 /* caller saved */ +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 /* callee saved */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* caller saved */ +#define t9 $25 +#define jp $25 /* PIC jump register */ +#define k0 $26 /* kernel scratch */ +#define k1 $27 +#define gp $28 /* global pointer */ +#define sp $29 /* stack pointer */ +#define fp $30 /* frame pointer */ +#define s8 $30 /* same like fp! */ +#define ra $31 /* return address */ + +#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ + +#if _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 + +#define zero $0 /* wired zero */ +#define AT $at /* assembler temp - uppercase because of ".set at" */ +#define v0 $2 /* return value - caller saved */ +#define v1 $3 +#define a0 $4 /* argument registers */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define a4 $8 /* arg reg 64 bit; caller saved in 32 bit */ +#define ta0 $8 +#define a5 $9 +#define ta1 $9 +#define a6 $10 +#define ta2 $10 +#define a7 $11 +#define ta3 $11 +#define t0 $12 /* caller saved */ +#define t1 $13 +#define t2 $14 +#define t3 $15 +#define s0 $16 /* callee saved */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* caller saved */ +#define t9 $25 /* callee address for PIC/temp */ +#define jp $25 /* PIC jump register */ +#define k0 $26 /* kernel temporary */ +#define k1 $27 +#define gp $28 /* global pointer - caller saved for PIC */ +#define sp $29 /* stack pointer */ +#define fp $30 /* frame pointer */ +#define s8 $30 /* callee saved */ +#define ra $31 /* return address */ + +#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 */ + +#endif /* _ASM_REGDEF_H */ diff --git a/arch/mips/include/asm/sections.h b/arch/mips/include/asm/sections.h new file mode 100644 index 0000000..2b8c516 --- /dev/null +++ b/arch/mips/include/asm/sections.h @@ -0,0 +1 @@ +#include diff --git a/arch/mips/include/asm/sgidefs.h b/arch/mips/include/asm/sgidefs.h new file mode 100644 index 0000000..876442f --- /dev/null +++ b/arch/mips/include/asm/sgidefs.h @@ -0,0 +1,44 @@ +/* + * 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) 1996, 1999, 2001 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2001 MIPS Technologies, Inc. + */ +#ifndef __ASM_SGIDEFS_H +#define __ASM_SGIDEFS_H + +/* + * Using a Linux compiler for building Linux seems logic but not to + * everybody. + */ +#ifndef __linux__ +#error Use a Linux compiler or give up. +#endif + +/* + * Definitions for the ISA levels + * + * With the introduction of MIPS32 / MIPS64 instruction sets definitions + * MIPS ISAs are no longer subsets of each other. Therefore comparisons + * on these symbols except with == may result in unexpected results and + * are forbidden! + */ +#define _MIPS_ISA_MIPS1 1 +#define _MIPS_ISA_MIPS2 2 +#define _MIPS_ISA_MIPS3 3 +#define _MIPS_ISA_MIPS4 4 +#define _MIPS_ISA_MIPS5 5 +#define _MIPS_ISA_MIPS32 6 +#define _MIPS_ISA_MIPS64 7 + +/* + * Subprogram calling convention + */ +#define _MIPS_SIM_ABI32 1 +#define _MIPS_SIM_NABI32 2 +#define _MIPS_SIM_ABI64 3 + +#endif /* __ASM_SGIDEFS_H */ diff --git a/arch/mips/include/asm/string.h b/arch/mips/include/asm/string.h new file mode 100644 index 0000000..9e334a2 --- /dev/null +++ b/arch/mips/include/asm/string.h @@ -0,0 +1,31 @@ +/* + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/** + * @file + * @brief mips specific string optimizations + * + * Thanks to the Linux kernel here we can add many micro optimized string + * functions. But currently it makes no sense, to do so. + */ +#ifndef __ASM_MIPS_STRING_H +#define __ASM_MIPS_STRING_H + +/* nothing special yet */ + +#endif diff --git a/arch/mips/include/asm/swab.h b/arch/mips/include/asm/swab.h new file mode 100644 index 0000000..97c2f81 --- /dev/null +++ b/arch/mips/include/asm/swab.h @@ -0,0 +1,59 @@ +/* + * 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) 1996, 99, 2003 by Ralf Baechle + */ +#ifndef _ASM_SWAB_H +#define _ASM_SWAB_H + +#include +#include + +#define __SWAB_64_THRU_32__ + +#ifdef CONFIG_CPU_MIPSR2 + +static inline __attribute_const__ __u16 __arch_swab16(__u16 x) +{ + __asm__( + " wsbh %0, %1 \n" + : "=r" (x) + : "r" (x)); + + return x; +} +#define __arch_swab16 __arch_swab16 + +static inline __attribute_const__ __u32 __arch_swab32(__u32 x) +{ + __asm__( + " wsbh %0, %1 \n" + " rotr %0, %0, 16 \n" + : "=r" (x) + : "r" (x)); + + return x; +} +#define __arch_swab32 __arch_swab32 + +/* + * Having already checked for CONFIG_CPU_MIPSR2, enable the + * optimized version for 64-bit kernel on r2 CPUs. + */ +#ifdef CONFIG_64BIT +static inline __attribute_const__ __u64 __arch_swab64(__u64 x) +{ + __asm__( + " dsbh %0, %1\n" + " dshd %0, %0" + : "=r" (x) + : "r" (x)); + + return x; +} +#define __arch_swab64 __arch_swab64 +#endif /* CONFIG_64BIT */ +#endif /* CONFIG_CPU_MIPSR2 */ +#endif /* _ASM_SWAB_H */ diff --git a/arch/mips/include/asm/types.h b/arch/mips/include/asm/types.h new file mode 100644 index 0000000..f5373cc --- /dev/null +++ b/arch/mips/include/asm/types.h @@ -0,0 +1,59 @@ +/* + * 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) 1994, 1995, 1996, 1999 by Ralf Baechle + * Copyright (C) 2008 Wind River Systems, + * written by Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#ifndef _ASM_TYPES_H +#define _ASM_TYPES_H + +#include + +#if (defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) \ + || defined(CONFIG_64BIT) +typedef u64 dma_addr_t; +#else +typedef u32 dma_addr_t; +#endif +typedef u64 dma64_addr_t; + +/* + * We don't use int-l64.h for the kernel anymore but still use it for + * userspace to avoid code changes. + */ +#if (_MIPS_SZLONG == 64) && !defined(__KERNEL__) +# include +#else +# include +#endif + +#ifndef __ASSEMBLY__ + +typedef unsigned short umode_t; + +#endif /* __ASSEMBLY__ */ + +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +#ifdef __KERNEL__ +#ifndef __ASSEMBLY__ + +/* + * Don't use phys_t. You've been warned. + */ +#ifdef CONFIG_64BIT_PHYS_ADDR +typedef unsigned long long phys_t; +#else +typedef unsigned long phys_t; +#endif + +#endif /* __ASSEMBLY__ */ + +#endif /* __KERNEL__ */ + +#endif /* _ASM_TYPES_H */ diff --git a/arch/mips/include/asm/unaligned.h b/arch/mips/include/asm/unaligned.h new file mode 100644 index 0000000..42f66c3 --- /dev/null +++ b/arch/mips/include/asm/unaligned.h @@ -0,0 +1,28 @@ +/* + * 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) 2007 Ralf Baechle (ralf@linux-mips.org) + */ +#ifndef _ASM_MIPS_UNALIGNED_H +#define _ASM_MIPS_UNALIGNED_H + +#include +#if defined(__MIPSEB__) +# include +# include +# define get_unaligned __get_unaligned_be +# define put_unaligned __put_unaligned_be +#elif defined(__MIPSEL__) +# include +# include +# define get_unaligned __get_unaligned_le +# define put_unaligned __put_unaligned_le +#else +# error "MIPS, but neither __MIPSEB__, nor __MIPSEL__???" +#endif + +# include + +#endif /* _ASM_MIPS_UNALIGNED_H */ diff --git a/arch/mips/lib/.gitignore b/arch/mips/lib/.gitignore new file mode 100644 index 0000000..d116578 --- /dev/null +++ b/arch/mips/lib/.gitignore @@ -0,0 +1 @@ +barebox.lds diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile new file mode 100644 index 0000000..45fe920 --- /dev/null +++ b/arch/mips/lib/Makefile @@ -0,0 +1,8 @@ +extra-$(CONFIG_GENERIC_LINKER_SCRIPT) += barebox.lds +obj-$(CONFIG_CSRC_R4K_LIB) += csrc-r4k.o +obj-y += lshrdi3.o +obj-y += ashldi3.o +obj-y += ashrdi3.o +obj-y += memory.o + +obj-$(CONFIG_CMD_MIPS_CPUINFO) += cpuinfo.o diff --git a/arch/mips/lib/ashldi3.c b/arch/mips/lib/ashldi3.c new file mode 100644 index 0000000..cbdbcbb --- /dev/null +++ b/arch/mips/lib/ashldi3.c @@ -0,0 +1,28 @@ +#include + +#include "libgcc.h" + +long long __ashldi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + w.s.low = 0; + w.s.high = (unsigned int) uu.s.low << -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.low >> bm; + + w.s.low = (unsigned int) uu.s.low << b; + w.s.high = ((unsigned int) uu.s.high << b) | carries; + } + + return w.ll; +} +EXPORT_SYMBOL(__ashldi3); diff --git a/arch/mips/lib/ashrdi3.c b/arch/mips/lib/ashrdi3.c new file mode 100644 index 0000000..928d6d9 --- /dev/null +++ b/arch/mips/lib/ashrdi3.c @@ -0,0 +1,30 @@ +#include + +#include "libgcc.h" + +long long __ashrdi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + /* w.s.high = 1..1 or 0..0 */ + w.s.high = + uu.s.high >> 31; + w.s.low = uu.s.high >> -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.high << bm; + + w.s.high = uu.s.high >> b; + w.s.low = ((unsigned int) uu.s.low >> b) | carries; + } + + return w.ll; +} +EXPORT_SYMBOL(__ashrdi3); diff --git a/arch/mips/lib/barebox.lds.S b/arch/mips/lib/barebox.lds.S new file mode 100644 index 0000000..dd9eab7 --- /dev/null +++ b/arch/mips/lib/barebox.lds.S @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2011 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include + +OUTPUT_ARCH(mips) +ENTRY(_start) +SECTIONS +{ + . = TEXT_BASE; + + . = ALIGN(4); + .text : + { + _start = .; + *(.text_entry*) + _stext = .; + _text = .; + *(.text_bare_init*) + *(.text*) + } + + PRE_IMAGE + + . = ALIGN(4); + .rodata : { *(.rodata*) } + + _etext = .; /* End of text and rodata section */ + + . = ALIGN(4); + .data : { *(.data*) } + + . = ALIGN(4); + .got : { *(.got*) } + + . = .; + __barebox_cmd_start = .; + .barebox_cmd : { BAREBOX_CMDS } + __barebox_cmd_end = .; + + __barebox_initcalls_start = .; + .barebox_initcalls : { INITCALLS } + __barebox_initcalls_end = .; + + __usymtab_start = .; + __usymtab : { BAREBOX_SYMS } + __usymtab_end = .; + + __early_init_data_begin = .; + .early_init_data : { *(.early_init_data) } + __early_init_data_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss*) } + __bss_end = .; + _end = .; +} diff --git a/arch/mips/lib/cpuinfo.c b/arch/mips/lib/cpuinfo.c new file mode 100644 index 0000000..7bdb02b --- /dev/null +++ b/arch/mips/lib/cpuinfo.c @@ -0,0 +1,38 @@ +/* + * cpuinfo - show information about MIPS CPU + * + * Copyright (C) 2011 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +static int do_cpuinfo(struct command *cmdtp, int argc, char *argv[]) +{ + printf("CP0_PRID = 0x%08x\n", read_c0_prid()); + printf("CP0_CONFIG = 0x%08x\n", read_c0_config()); + + return 0; +} + +BAREBOX_CMD_START(cpuinfo) + .cmd = do_cpuinfo, + .usage = "Show info about CPU", +BAREBOX_CMD_END diff --git a/arch/mips/lib/csrc-r4k.c b/arch/mips/lib/csrc-r4k.c new file mode 100644 index 0000000..8e93e6f --- /dev/null +++ b/arch/mips/lib/csrc-r4k.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** + * @file + * @brief Clocksource based on MIPS CP0 timer + */ + +#include +#include +#include +#include + +static uint64_t c0_hpt_read(void) +{ + return read_c0_count(); +} + +static struct clocksource cs = { + .read = c0_hpt_read, + .mask = 0xffffffff, +}; + +static int clocksource_init(void) +{ + cs.mult = clocksource_hz2mult(100000000, cs.shift); + init_clock(&cs); + + return 0; +} +core_initcall(clocksource_init); diff --git a/arch/mips/lib/libgcc.h b/arch/mips/lib/libgcc.h new file mode 100644 index 0000000..05909d5 --- /dev/null +++ b/arch/mips/lib/libgcc.h @@ -0,0 +1,25 @@ +#ifndef __ASM_LIBGCC_H +#define __ASM_LIBGCC_H + +#include + +typedef int word_type __attribute__ ((mode (__word__))); + +#ifdef __BIG_ENDIAN +struct DWstruct { + int high, low; +}; +#elif defined(__LITTLE_ENDIAN) +struct DWstruct { + int low, high; +}; +#else +#error I feel sick. +#endif + +typedef union { + struct DWstruct s; + long long ll; +} DWunion; + +#endif /* __ASM_LIBGCC_H */ diff --git a/arch/mips/lib/lshrdi3.c b/arch/mips/lib/lshrdi3.c new file mode 100644 index 0000000..74a4846 --- /dev/null +++ b/arch/mips/lib/lshrdi3.c @@ -0,0 +1,28 @@ +#include + +#include "libgcc.h" + +long long __lshrdi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + w.s.high = 0; + w.s.low = (unsigned int) uu.s.high >> -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.high << bm; + + w.s.high = (unsigned int) uu.s.high >> b; + w.s.low = ((unsigned int) uu.s.low >> b) | carries; + } + + return w.ll; +} +EXPORT_SYMBOL(__lshrdi3); diff --git a/arch/mips/lib/memory.c b/arch/mips/lib/memory.c new file mode 100644 index 0000000..23a995c --- /dev/null +++ b/arch/mips/lib/memory.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2011 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +static int mips_mem_malloc_init(void) +{ + mem_malloc_init((void *)MALLOC_BASE, + (void *)(MALLOC_BASE + MALLOC_SIZE)); + return 0; +} +core_initcall(mips_mem_malloc_init); diff --git a/arch/mips/mach-bcm47xx/Kconfig b/arch/mips/mach-bcm47xx/Kconfig new file mode 100644 index 0000000..d0df0fd --- /dev/null +++ b/arch/mips/mach-bcm47xx/Kconfig @@ -0,0 +1,17 @@ +if MACH_MIPS_BCM47XX + +config ARCH_TEXT_BASE + hex + default 0xa0800000 + +choice + prompt "Board type" + +config BOARD_DLINK_DIR320 + bool "D-Link DIR-320" + +endchoice + +source arch/mips/boards/dlink-dir-320/Kconfig + +endif diff --git a/arch/mips/mach-bcm47xx/Makefile b/arch/mips/mach-bcm47xx/Makefile new file mode 100644 index 0000000..f3cc668 --- /dev/null +++ b/arch/mips/mach-bcm47xx/Makefile @@ -0,0 +1 @@ +obj-y += reset.o diff --git a/arch/mips/mach-bcm47xx/include/mach/debug_ll.h b/arch/mips/mach-bcm47xx/include/mach/debug_ll.h new file mode 100644 index 0000000..32d13c1 --- /dev/null +++ b/arch/mips/mach-bcm47xx/include/mach/debug_ll.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2011 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** @file + * This File contains declaration for early output support + */ +#ifndef __INCLUDE_ARCH_DEBUG_LL_H__ +#define __INCLUDE_ARCH_DEBUG_LL_H__ + +#include +#include + +#define rbr 0 +#define lsr 5 +#define LSR_THRE 0x20 /* Xmit holding register empty */ + +static __inline__ void putc(char ch) +{ + while (!(__raw_readb(DEBUG_LL_UART_ADDR + lsr) & LSR_THRE)); + __raw_writeb(ch, DEBUG_LL_UART_ADDR + rbr); +} + +#endif /* __INCLUDE_ARCH_DEBUG_LL_H__ */ diff --git a/arch/mips/mach-bcm47xx/include/mach/hardware.h b/arch/mips/mach-bcm47xx/include/mach/hardware.h new file mode 100644 index 0000000..703e7f7 --- /dev/null +++ b/arch/mips/mach-bcm47xx/include/mach/hardware.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2011 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __INCLUDE_ARCH_HARDWARE_H__ +#define __INCLUDE_ARCH_HARDWARE_H__ + +#define DEBUG_LL_UART_ADDR 0xb8000300 + +/* + * Reset register. + */ +#define SOFTRES_REG 0xbf000500 +#define GORESET 0x42 + +#endif /* __INCLUDE_ARCH_HARDWARE_H__ */ diff --git a/arch/mips/mach-bcm47xx/mach-bcm47xx.dox b/arch/mips/mach-bcm47xx/mach-bcm47xx.dox new file mode 100644 index 0000000..04ccf03 --- /dev/null +++ b/arch/mips/mach-bcm47xx/mach-bcm47xx.dox @@ -0,0 +1,7 @@ +/** @page dev_bcm47xx_mach BCM47xx in barebox + +@section bcm47xx_boards BCM47xx-based boards + +@li @subpage dlink_dir_320 + +*/ diff --git a/arch/mips/mach-bcm47xx/reset.c b/arch/mips/mach-bcm47xx/reset.c new file mode 100644 index 0000000..2818e7c --- /dev/null +++ b/arch/mips/mach-bcm47xx/reset.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2011 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** + * @file + * @brief Resetting an malta board + */ + +#include +#include +#include + +void __noreturn reset_cpu(ulong addr) +{ + __raw_writel(GORESET, (char *)SOFTRES_REG); + while (1); + /*NOTREACHED*/ +} +EXPORT_SYMBOL(reset_cpu); diff --git a/arch/mips/mach-malta/Kconfig b/arch/mips/mach-malta/Kconfig new file mode 100644 index 0000000..8e0666c --- /dev/null +++ b/arch/mips/mach-malta/Kconfig @@ -0,0 +1,17 @@ +if MACH_MIPS_MALTA + +config ARCH_TEXT_BASE + hex + default 0xa0800000 + +choice + prompt "Board type" + +config BOARD_QEMU_MALTA + bool "qemu malta" + +endchoice + +source arch/mips/boards/qemu-malta/Kconfig + +endif diff --git a/arch/mips/mach-malta/Makefile b/arch/mips/mach-malta/Makefile new file mode 100644 index 0000000..f3cc668 --- /dev/null +++ b/arch/mips/mach-malta/Makefile @@ -0,0 +1 @@ +obj-y += reset.o diff --git a/arch/mips/mach-malta/include/mach/debug_ll.h b/arch/mips/mach-malta/include/mach/debug_ll.h new file mode 100644 index 0000000..32d13c1 --- /dev/null +++ b/arch/mips/mach-malta/include/mach/debug_ll.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2011 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** @file + * This File contains declaration for early output support + */ +#ifndef __INCLUDE_ARCH_DEBUG_LL_H__ +#define __INCLUDE_ARCH_DEBUG_LL_H__ + +#include +#include + +#define rbr 0 +#define lsr 5 +#define LSR_THRE 0x20 /* Xmit holding register empty */ + +static __inline__ void putc(char ch) +{ + while (!(__raw_readb(DEBUG_LL_UART_ADDR + lsr) & LSR_THRE)); + __raw_writeb(ch, DEBUG_LL_UART_ADDR + rbr); +} + +#endif /* __INCLUDE_ARCH_DEBUG_LL_H__ */ diff --git a/arch/mips/mach-malta/include/mach/hardware.h b/arch/mips/mach-malta/include/mach/hardware.h new file mode 100644 index 0000000..f827cc3 --- /dev/null +++ b/arch/mips/mach-malta/include/mach/hardware.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2011 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __INCLUDE_ARCH_HARDWARE_H__ +#define __INCLUDE_ARCH_HARDWARE_H__ + +#define DEBUG_LL_UART_ADDR 0xb00003f8 + +/* + * Reset register. + */ +#define SOFTRES_REG 0xbf000500 +#define GORESET 0x42 + +#endif /* __INCLUDE_ARCH_HARDWARE_H__ */ diff --git a/arch/mips/mach-malta/mach-malta.dox b/arch/mips/mach-malta/mach-malta.dox new file mode 100644 index 0000000..85351e1 --- /dev/null +++ b/arch/mips/mach-malta/mach-malta.dox @@ -0,0 +1,7 @@ +/** @page dev_malta_mach MIPS Malta in barebox + +@section malta_boards MIPS Malta boards + +@li @subpage qemu_malta + +*/ diff --git a/arch/mips/mach-malta/reset.c b/arch/mips/mach-malta/reset.c new file mode 100644 index 0000000..2818e7c --- /dev/null +++ b/arch/mips/mach-malta/reset.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2011 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** + * @file + * @brief Resetting an malta board + */ + +#include +#include +#include + +void __noreturn reset_cpu(ulong addr) +{ + __raw_writel(GORESET, (char *)SOFTRES_REG); + while (1); + /*NOTREACHED*/ +} +EXPORT_SYMBOL(reset_cpu); diff --git a/arch/mips/mach-mips.dox b/arch/mips/mach-mips.dox new file mode 100644 index 0000000..9bcec13 --- /dev/null +++ b/arch/mips/mach-mips.dox @@ -0,0 +1,61 @@ +/* This document is intended to provide the developer with information + * how to integrate a new CPU (MACH) into this part of the barebox tree + */ + +/** @page dev_mips_mach MIPS based CPU (MACH) into the tree + +@section mach_mips_reset What's happens when the reset signal is gone + +Barebox normally must be linked to RAM region, cached region KSEG0 is preferred. +This make possible to run fast (because cache used) and skip MMU support. + +After reset MIPS CPU starting to fetch instructions from 0xBFC00000. + +@note Code running immediately after reset runs at an address it is not linked + to: "runtime address != link address". You should only use branches and + do not refer to fixed data. This implies the use of assembler code only. + After MIPS CPU reset cache and MMU are in random state. They are unusable. + +barebox MIPS initialisation sequence: + + * set the CP0 STATUS register to some known and sensible state. +Now you can load and store reliably in uncached space. + + * call a function \ (if not disabled). +do some special things required only on specific CPU + (e. g. init RAM controller, disable watchdog) + + * call a function \ (if not disable). +do some special things required only on specific board + (e. g. setup GPIO to required state). + + ** It is desirable to have some debug code to make some contact + with the outside world from assembler code +(e.g. debug_ll-like functions to write to rs232 console). + + * check integrity of barebox RAM execute location; + * copy barebox to RAM execute location; + + * configure cache; + + * setup stack; + + ** after this point you can call a standard C routine. + + * setup exception vectors in RAM; + * setup CP0 STATUS to switch exception vector address to RAM; + + * call start_barebox() + +Further reading: + * Dominic Sweetman, See MIPS Run, Morgan Kaufmann, 2nd edition, 2006 +ISBN-13: 978-0120884216 + +@subsection mach_mips_malta_info Malta boards + +@li @subpage dev_malta_mach + +@subsection mach_bcm47xx_info BCM47xx-based boards + +@li @subpage dev_bcm47xx_mach +*/ diff --git a/arch/nios2/include/asm/spi.h b/arch/nios2/include/asm/spi.h new file mode 100644 index 0000000..4e576b9 --- /dev/null +++ b/arch/nios2/include/asm/spi.h @@ -0,0 +1,21 @@ +#ifndef __ALTERA_SPI_H_ +#define __ALTERA_SPI_H_ + +#include + +struct spi_altera_master { + int num_chipselect; + int spi_mode; + int databits; + int speed; +}; + +struct altera_spi { + struct spi_master master; + int databits; + int speed; + int mode; + void __iomem *regs; +}; + +#endif /*__ALTERA_SPI_H_*/ diff --git a/commands/Kconfig b/commands/Kconfig index e922260..39bdb0f 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -203,12 +203,10 @@ prompt "loady" config CMD_LOADS - depends on BROKEN tristate prompt "loads" config CMD_SAVES - depends on BROKEN tristate depends on CMD_LOADS prompt "saves" diff --git a/commands/Makefile b/commands/Makefile index 7c88b48..40fb26c 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -5,7 +5,6 @@ obj-$(CONFIG_CMD_LOADS) += loads.o obj-$(CONFIG_CMD_ECHO) += echo.o obj-$(CONFIG_CMD_MEMORY) += mem.o -obj-$(CONFIG_CMD_LOADS) += s_record.o obj-$(CONFIG_CMD_MTEST) += memtest.o obj-$(CONFIG_CMD_EDIT) += edit.o obj-$(CONFIG_CMD_EXEC) += exec.o diff --git a/commands/loads.c b/commands/loads.c index c6617a4..68a44d4 100644 --- a/commands/loads.c +++ b/commands/loads.c @@ -26,32 +26,27 @@ */ #include #include +#include #include #include -#include #include -static ulong load_serial (ulong offset); -static int read_record (char *buf, ulong len); +static ulong load_serial(ulong offset); +static int read_record(char *buf, ulong len); static int do_echo = 1; -# if (CONFIG_COMMANDS & CFG_CMD_SAVES) -static int save_serial (ulong offset, ulong size); -static int write_record (char *buf); -# endif /* CFG_CMD_SAVES */ +#ifdef CONFIG_CMD_SAVES +static int save_serial(ulong offset, ulong size); +static int write_record(char *buf); +#endif /* CONFIG_CMD_SAVES */ -int do_load_serial(struct command *cmdtp, int argc, char *argv[]) +static int do_load_serial(struct command *cmdtp, int argc, char *argv[]) { ulong offset = 0; ulong addr; int i; - char *env_echo; + const char *env_echo; int rcode = 0; -#ifdef CFG_LOADS_BAUD_CHANGE - int load_baudrate, current_baudrate; - - load_baudrate = current_baudrate = gd->baudrate; -#endif if (((env_echo = getenv("loads_echo")) != NULL) && (*env_echo == '1')) { do_echo = 1; @@ -59,38 +54,13 @@ do_echo = 0; } -#ifdef CFG_LOADS_BAUD_CHANGE - if (argc >= 2) { - offset = simple_strtoul(argv[1], NULL, 16); - } - if (argc == 3) { - load_baudrate = (int)simple_strtoul(argv[2], NULL, 10); - - /* default to current baudrate */ - if (load_baudrate == 0) - load_baudrate = current_baudrate; - } - if (load_baudrate != current_baudrate) { - printf ("## Switch baudrate to %d bps and press ENTER ...\n", - load_baudrate); - udelay(50000); - gd->baudrate = load_baudrate; - serial_setbrg (); - udelay(50000); - for (;;) { - if (getc() == '\r') - break; - } - } -#else /* ! CFG_LOADS_BAUD_CHANGE */ if (argc == 2) { offset = simple_strtoul(argv[1], NULL, 16); } -#endif /* CFG_LOADS_BAUD_CHANGE */ printf ("## Ready for S-Record download ...\n"); - addr = load_serial (offset); + addr = load_serial(offset); /* * Gather any trailing characters (for instance, the ^D which @@ -105,32 +75,16 @@ } if (addr == ~0) { - printf ("## S-Record download aborted\n"); + printf("## S-Record download aborted\n"); rcode = 1; } else { - printf ("## Start Addr = 0x%08lX\n", addr); - load_addr = addr; + printf("## Start Addr = 0x%08lX\n", addr); } -#ifdef CFG_LOADS_BAUD_CHANGE - if (load_baudrate != current_baudrate) { - printf ("## Switch baudrate to %d bps and press ESC ...\n", - current_baudrate); - udelay (50000); - gd->baudrate = current_baudrate; - serial_setbrg (); - udelay (50000); - for (;;) { - if (getc() == 0x1B) /* ESC */ - break; - } - } -#endif return rcode; } -static ulong -load_serial (ulong offset) +static ulong load_serial(ulong offset) { char record[SREC_MAXRECLEN + 1]; /* buffer for one S-Record */ char binbuf[SREC_MAXBINLEN]; /* buffer for binary data */ @@ -145,53 +99,52 @@ int line_count = 0; while (read_record(record, SREC_MAXRECLEN + 1) >= 0) { - type = srec_decode (record, &binlen, &addr, binbuf); + type = srec_decode(record, &binlen, &addr, binbuf); if (type < 0) { - return (~0); /* Invalid S-Record */ + return ~0; /* Invalid S-Record */ } switch (type) { case SREC_DATA2: case SREC_DATA3: case SREC_DATA4: - store_addr = addr + offset; - memcpy ((char *)(store_addr), binbuf, binlen); - if ((store_addr) < start_addr) - start_addr = store_addr; - if ((store_addr + binlen - 1) > end_addr) - end_addr = store_addr + binlen - 1; - break; + store_addr = addr + offset; + memcpy((char *)(store_addr), binbuf, binlen); + if ((store_addr) < start_addr) + start_addr = store_addr; + if ((store_addr + binlen - 1) > end_addr) + end_addr = store_addr + binlen - 1; + break; case SREC_END2: case SREC_END3: case SREC_END4: - udelay (10000); - size = end_addr - start_addr + 1; - printf ("\n" + udelay(10000); + size = end_addr - start_addr + 1; + printf("\n" "## First Load Addr = 0x%08lX\n" "## Last Load Addr = 0x%08lX\n" "## Total Size = 0x%08lX = %ld Bytes\n", start_addr, end_addr, size, size - ); - sprintf(buf, "%lX", size); - setenv("filesize", buf); - return (addr); + ); + sprintf(buf, "%lX", size); + setenv("filesize", buf); + return addr; case SREC_START: - break; + break; default: - break; + break; } if (!do_echo) { /* print a '.' every 100 lines */ if ((++line_count % 100) == 0) - putc ('.'); + console_putc(CONSOLE_STDOUT, '.'); } } - return (~0); /* Download aborted */ + return ~0; /* Download aborted */ } -static int -read_record (char *buf, ulong len) +static int read_record(char *buf, ulong len) { char *p; char c; @@ -201,101 +154,51 @@ for (p=buf; p < buf+len; ++p) { c = getc(); /* read character */ if (do_echo) - putc (c); /* ... and echo it */ + console_putc(CONSOLE_STDOUT, c); switch (c) { case '\r': case '\n': *p = '\0'; - return (p - buf); + return p - buf; case '\0': case 0x03: /* ^C - Control C */ - return (-1); + return -1; default: *p = c; } - - /* Check for the console hangup (if any different from serial) */ - if (gd->jt[XF_getc] != getc) { - if (ctrlc()) { - return (-1); - } - } } /* line too long - truncate */ *p = '\0'; - return (p - buf); + return p - buf; } -#if (CONFIG_COMMANDS & CFG_CMD_SAVES) - -int do_save_serial(struct command *cmdtp, int flag, int argc, char *argv[]) +#ifdef CONFIG_CMD_SAVES +static int do_save_serial(struct command *cmdtp, int argc, char *argv[]) { ulong offset = 0; ulong size = 0; -#ifdef CFG_LOADS_BAUD_CHANGE - int save_baudrate, current_baudrate; - - save_baudrate = current_baudrate = gd->baudrate; -#endif if (argc >= 2) { offset = simple_strtoul(argv[1], NULL, 16); } -#ifdef CFG_LOADS_BAUD_CHANGE - if (argc >= 3) { - size = simple_strtoul(argv[2], NULL, 16); - } - if (argc == 4) { - save_baudrate = (int)simple_strtoul(argv[3], NULL, 10); - /* default to current baudrate */ - if (save_baudrate == 0) - save_baudrate = current_baudrate; - } - if (save_baudrate != current_baudrate) { - printf ("## Switch baudrate to %d bps and press ENTER ...\n", - save_baudrate); - udelay(50000); - gd->baudrate = save_baudrate; - serial_setbrg (); - udelay(50000); - for (;;) { - if (getc() == '\r') - break; - } - } -#else /* ! CFG_LOADS_BAUD_CHANGE */ if (argc == 3) { size = simple_strtoul(argv[2], NULL, 16); } -#endif /* CFG_LOADS_BAUD_CHANGE */ printf ("## Ready for S-Record upload, press ENTER to proceed ...\n"); for (;;) { if (getc() == '\r') break; } - if(save_serial (offset, size)) { - printf ("## S-Record upload aborted\n"); + if (save_serial(offset, size)) { + printf("## S-Record upload aborted\n"); } else { - printf ("## S-Record upload complete\n"); + printf("## S-Record upload complete\n"); } -#ifdef CFG_LOADS_BAUD_CHANGE - if (save_baudrate != current_baudrate) { - printf ("## Switch baudrate to %d bps and press ESC ...\n", - (int)current_baudrate); - udelay (50000); - gd->baudrate = current_baudrate; - serial_setbrg (); - udelay (50000); - for (;;) { - if (getc() == 0x1B) /* ESC */ - break; - } - } -#endif + return 0; } @@ -304,40 +207,42 @@ #define SREC3_END "S70500000000FA\n" #define SREC_BYTES_PER_RECORD 16 -static int save_serial (ulong address, ulong count) +static int save_serial(ulong address, ulong count) { int i, c, reclen, checksum, length; char *hex = "0123456789ABCDEF"; - char record[2*SREC_BYTES_PER_RECORD+16]; /* buffer for one S-Record */ - char data[2*SREC_BYTES_PER_RECORD+1]; /* buffer for hex data */ + char record[2*SREC_BYTES_PER_RECORD+16]; /* buffer for one S-Record */ + char data[2*SREC_BYTES_PER_RECORD+1]; /* buffer for hex data */ reclen = 0; - checksum = 0; + checksum = 0; - if(write_record(SREC3_START)) /* write the header */ - return (-1); + if (write_record(SREC3_START)) /* write the header */ + return -1; + do { - if(count) { /* collect hex data in the buffer */ + if (count) { /* collect hex data in the buffer */ c = *(volatile uchar*)(address + reclen); /* get one byte */ - checksum += c; /* accumulate checksum */ + checksum += c; /* accumulate checksum */ data[2*reclen] = hex[(c>>4)&0x0f]; data[2*reclen+1] = hex[c & 0x0f]; data[2*reclen+2] = '\0'; ++reclen; --count; } - if(reclen == SREC_BYTES_PER_RECORD || count == 0) { + + if (reclen == SREC_BYTES_PER_RECORD || count == 0) { /* enough data collected for one record: dump it */ - if(reclen) { /* build & write a data record: */ + if (reclen) { /* build & write a data record: */ /* address + data + checksum */ length = 4 + reclen + 1; /* accumulate length bytes into checksum */ - for(i = 0; i < 2; i++) + for (i = 0; i < 2; i++) checksum += (length >> (8*i)) & 0xff; /* accumulate address bytes into checksum: */ - for(i = 0; i < 4; i++) + for (i = 0; i < 4; i++) checksum += (address >> (8*i)) & 0xff; /* make proper checksum byte: */ @@ -345,76 +250,59 @@ /* output one record: */ sprintf(record, SREC3_FORMAT, length, address, data, checksum); - if(write_record(record)) - return (-1); + if (write_record(record)) + return -1; } address += reclen; /* increment address */ checksum = 0; reclen = 0; } - } - while(count); - if(write_record(SREC3_END)) /* write the final record */ - return (-1); - return(0); + } while (count); + + if (write_record(SREC3_END)) /* write the final record */ + return -1; + return 0; } -static int -write_record (char *buf) +static int write_record(char *buf) { char c; - while((c = *buf++)) - putc(c); + while ((c = *buf++)) + console_putc(CONSOLE_STDOUT, c); /* Check for the console hangup (if any different from serial) */ if (ctrlc()) { - return (-1); + return -1; } - return (0); + return 0; } -# endif /* CFG_CMD_SAVES */ +#endif /* CONFIG_CMD_SAVES */ -#ifdef CFG_LOADS_BAUD_CHANGE -BAREBOX_CMD( - loads, 3, 0, do_load_serial, - "loads - load S-Record file over serial line\n", - "[ off ] [ baud ]\n" - " - load S-Record file over serial line" - " with offset 'off' and baudrate 'baud'\n" -); - -#else /* ! CFG_LOADS_BAUD_CHANGE */ -BAREBOX_CMD( - loads, 2, 0, do_load_serial, - "loads - load S-Record file over serial line\n", +static const __maybe_unused char cmd_loads_help[] = "[ off ]\n" - " - load S-Record file over serial line with offset 'off'\n" -); -#endif /* CFG_LOADS_BAUD_CHANGE */ + " - load S-Record file over serial line with offset 'off'\n"; + +BAREBOX_CMD_START(loads) + .cmd = do_load_serial, + .usage = "load S-Record file over serial line", + BAREBOX_CMD_HELP(cmd_loads_help) +BAREBOX_CMD_END /* * SAVES always requires LOADS support, but not vice versa */ - -#if (CONFIG_COMMANDS & CFG_CMD_SAVES) -#ifdef CFG_LOADS_BAUD_CHANGE -BAREBOX_CMD( - saves, 4, 0, do_save_serial, - "saves - save S-Record file over serial line\n", - "[ off ] [size] [ baud ]\n" - " - save S-Record file over serial line" - " with offset 'off', size 'size' and baudrate 'baud'\n" -); -#else /* ! CFG_LOADS_BAUD_CHANGE */ -BAREBOX_CMD( - saves, 3, 0, do_save_serial, - "saves - save S-Record file over serial line\n", +#ifdef CONFIG_CMD_SAVES +static const __maybe_unused char cmd_saves_help[] = "[ off ] [size]\n" - " - save S-Record file over serial line with offset 'off' and size 'size'\n" -); -#endif /* CFG_LOADS_BAUD_CHANGE */ -#endif /* CFG_CMD_SAVES */ + " - save S-Record file over serial line with offset 'off' " + "and size 'size'\n"; +BAREBOX_CMD_START(saves) + .cmd = do_save_serial, + .usage = "save S-Record file over serial line", + BAREBOX_CMD_HELP(cmd_saves_help) +BAREBOX_CMD_END +#endif /* CONFIG_CMD_SAVES */ diff --git a/commands/login.c b/commands/login.c index 7d99b73..610fb9e 100644 --- a/commands/login.c +++ b/commands/login.c @@ -21,6 +21,7 @@ #include #include #include +#include #define PASSWD_MAX_LENGTH (128 + 1) @@ -35,16 +36,32 @@ static int do_login(struct command *cmdtp, int argc, char *argv[]) { unsigned char passwd[PASSWD_MAX_LENGTH]; - int passwd_len; + int passwd_len, opt; + int timeout = 0; + char *timeout_cmd = "boot"; if (!is_passwd_enable()) { puts("login: password not set\n"); return 0; } + while((opt = getopt(argc, argv, "t:")) > 0) { + switch(opt) { + case 't': + timeout = simple_strtoul(optarg, NULL, 10); + break; + } + } + + if (optind != argc) + timeout_cmd = argv[optind]; + do { puts("Password: "); - passwd_len = password(passwd, PASSWD_MAX_LENGTH, LOGIN_MODE); + passwd_len = password(passwd, PASSWD_MAX_LENGTH, LOGIN_MODE, timeout); + + if (passwd_len < 0) + run_command(timeout_cmd, 0); if (check_passwd(passwd, passwd_len)) return 0; @@ -54,7 +71,10 @@ } static const __maybe_unused char cmd_login_help[] = -""; +"Usage: login [[-t timeout] ]\n" +"If a timeout is specified and expired the command will be executed\n" +"by default boot\n" +; BAREBOX_CMD_START(login) .cmd = do_login, diff --git a/commands/passwd.c b/commands/passwd.c index 9435091..9a07873 100644 --- a/commands/passwd.c +++ b/commands/passwd.c @@ -42,13 +42,13 @@ int ret = 1; puts("Enter new password: "); - passwd1_len = password(passwd1, PASSWD_MAX_LENGTH, PASSWD_MODE); + passwd1_len = password(passwd1, PASSWD_MAX_LENGTH, PASSWD_MODE, 0); if (passwd1_len < 0) return 1; puts("Retype new password: "); - passwd2_len = password(passwd2, PASSWD_MAX_LENGTH, PASSWD_MODE); + passwd2_len = password(passwd2, PASSWD_MAX_LENGTH, PASSWD_MODE, 0); if (passwd2_len < 0) return 1; diff --git a/common/Makefile b/common/Makefile index 9fed2ae..74946e9 100644 --- a/common/Makefile +++ b/common/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_AUTO_COMPLETE) += complete.o obj-$(CONFIG_POLLER) += poller.o obj-$(CONFIG_BLOCK) += block.o +obj-$(CONFIG_CMD_LOADS) += s_record.o obj-y += memory.o obj-$(CONFIG_MALLOC_DLMALLOC) += dlmalloc.o diff --git a/common/console.c b/common/console.c index d60e57f..1f6ee93 100644 --- a/common/console.c +++ b/common/console.c @@ -132,6 +132,8 @@ dev->id = -1; strcpy(dev->name, "cs"); dev->type_data = newcdev; + if (newcdev->dev) + dev_add_child(newcdev->dev, dev); register_device(dev); if (newcdev->setbrg) { diff --git a/common/env.c b/common/env.c index 47cef05..defb26b 100644 --- a/common/env.c +++ b/common/env.c @@ -81,7 +81,7 @@ return 0; } -device_initcall(env_push_context); +postcore_initcall(env_push_context); /** * FIXME diff --git a/common/password.c b/common/password.c index 20e398f..ece7704 100644 --- a/common/password.c +++ b/common/password.c @@ -27,6 +27,7 @@ #include #include #include +#include #if defined(CONFIG_PASSWD_SUM_MD5) #define PASSWD_SUM "md5" @@ -36,56 +37,64 @@ #define PASSWD_SUM "sha256" #endif -int password(unsigned char *passwd, size_t length, int flags) +int password(unsigned char *passwd, size_t length, int flags, int timeout) { unsigned char *buf = passwd; int pos = 0; unsigned char ch; + uint64_t start, second; if (!passwd) return -EINVAL; + start = get_time_ns(); + second = start; + do { - ch = getc(); + if (tstc()) { + ch = getc(); - switch (ch) { - case '\r': - case '\n': - *buf = '\0'; - puts("\r\n"); - return pos; - case '\0': - case '\t': - continue; - case CTL_CH('c'): - passwd[0] = '\0'; - puts("\r\n"); - return 0; - case CTL_CH('h'): - case KEY_DEL7: - case KEY_DEL: - if (flags & STAR && pos > 0) - puts("\b \b"); - *buf = '\0'; - buf--; - pos--; - continue; - default: - if (pos < length - 1) { - if (flags & STAR) - putchar('*'); - else if (flags & CLEAR) - putchar(ch); + switch (ch) { + case '\r': + case '\n': + *buf = '\0'; + puts("\r\n"); + return pos; + case '\0': + case '\t': + continue; + case CTL_CH('c'): + passwd[0] = '\0'; + puts("\r\n"); + return 0; + case CTL_CH('h'): + case KEY_DEL7: + case KEY_DEL: + if (flags & STAR && pos > 0) + puts("\b \b"); + *buf = '\0'; + buf--; + pos--; + continue; + default: + if (pos < length - 1) { + if (flags & STAR) + putchar('*'); + else if (flags & CLEAR) + putchar(ch); - *buf = ch; - buf++; - pos++; - } else { - if (flags & STAR) - putchar('\a'); + *buf = ch; + buf++; + pos++; + } else { + if (flags & STAR) + putchar('\a'); + } } } - } while(1); + } while (!is_timeout(start, timeout * SECOND) || timeout == 0); + + return -1; } EXPORT_SYMBOL(password); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index b8b2f39..0b80103 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -283,32 +283,33 @@ } #ifdef CONFIG_CMD_DEVINFO -static int do_devinfo_subtree(struct device_d *dev, int depth, char edge) +static int do_devinfo_subtree(struct device_d *dev, int depth) { struct device_d *child; struct cdev *cdev; int i; for (i = 0; i < depth; i++) - printf("| "); + printf(" "); - printf("%c----%s", edge, dev_name(dev)); + printf("`---- %s", dev_name(dev)); if (!list_empty(&dev->cdevs)) { - printf(" ("); + printf("\n"); list_for_each_entry(cdev, &dev->cdevs, devices_list) { - printf("%s", cdev->name); - if (!list_is_last(&cdev->devices_list, &dev->cdevs)) - printf(", "); + for (i = 0; i < depth + 1; i++) + printf(" "); + printf("`---- 0x%08lx-0x%08lx: /dev/%s\n", + cdev->offset, + cdev->offset + cdev->size - 1, + cdev->name); } - printf(")"); + } else { + printf("\n"); } - printf("\n"); if (!list_empty(&dev->children)) { device_for_each_child(dev, child) { - do_devinfo_subtree(child, depth + 1, - list_is_last(&child->sibling, - &dev->children) ? '`' : '|'); + do_devinfo_subtree(child, depth + 1); } } @@ -328,7 +329,7 @@ for_each_device(dev) { if (!dev->parent) - do_devinfo_subtree(dev, 0, '|'); + do_devinfo_subtree(dev, 0); } printf("\ndrivers:\n"); diff --git a/drivers/mci/atmel_mci.c b/drivers/mci/atmel_mci.c index b4489dd..71aec16 100644 --- a/drivers/mci/atmel_mci.c +++ b/drivers/mci/atmel_mci.c @@ -449,6 +449,7 @@ host->mci.send_cmd = mci_request; host->mci.set_ios = mci_set_ios; host->mci.init = mci_reset; + host->mci.hw_dev = hw_dev; host->mci.host_caps = pd->host_caps; if (pd->bus_width >= 4) diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index e20b3b7..358f0dc 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -485,6 +485,7 @@ host->mci.set_ios = esdhc_set_ios; host->mci.init = esdhc_init; host->mci.host_caps = MMC_MODE_4BIT; + host->mci.hw_dev = dev; host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; diff --git a/drivers/mci/imx.c b/drivers/mci/imx.c index 1f96e96..905c251 100644 --- a/drivers/mci/imx.c +++ b/drivers/mci/imx.c @@ -492,6 +492,7 @@ host->mci.set_ios = mxcmci_set_ios; host->mci.init = mxcmci_init; host->mci.host_caps = MMC_MODE_4BIT; + host->mci.hw_dev = dev; host->base = dev_request_mem_region(dev, 0); diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index fea2691..681de0a 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -1177,6 +1177,7 @@ struct mci_host *host = GET_MCI_PDATA(mci_dev); struct ata_interface *p; int rc; + struct device_d *dev; /* start with a host interface reset */ rc = (host->init)(host, mci_dev); @@ -1228,7 +1229,8 @@ p->read = mci_sd_read; p->priv = mci_dev; - add_generic_device("disk", -1, NULL, 0, mci->capacity, IORESOURCE_MEM, p); + dev = add_generic_device("disk", -1, NULL, 0, mci->capacity, IORESOURCE_MEM, p); + dev_add_child(&host->dev, dev); pr_debug("SD Card successfully added\n"); @@ -1359,12 +1361,11 @@ */ int mci_register(struct mci_host *host) { - struct device_d *mci_dev; - - mci_dev = xzalloc(sizeof(struct device_d)); + struct device_d *mci_dev = &host->dev; strcpy(mci_dev->name, mci_driver.name); mci_dev->platform_data = (void*)host; + dev_add_child(host->hw_dev, mci_dev); return register_device(mci_dev); } diff --git a/drivers/mci/omap_hsmmc.c b/drivers/mci/omap_hsmmc.c index f47f190..5fdf445 100644 --- a/drivers/mci/omap_hsmmc.c +++ b/drivers/mci/omap_hsmmc.c @@ -557,6 +557,7 @@ hsmmc->mci.set_ios = mmc_set_ios; hsmmc->mci.init = mmc_init_setup; hsmmc->mci.host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS; + hsmmc->mci.hw_dev = dev; hsmmc->base = dev_request_mem_region(dev, 0); diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c index e7dabda..7e456c7 100644 --- a/drivers/net/altera_tse.c +++ b/drivers/net/altera_tse.c @@ -518,6 +518,7 @@ edev->halt = tse_eth_halt; edev->get_ethaddr = tse_get_ethaddr; edev->set_ethaddr = tse_set_ethaddr; + edev->parent = dev; #ifdef CONFIG_TSE_USE_DEDICATED_DESC_MEM tx_desc = dev_request_mem_region(dev, 3); @@ -548,6 +549,7 @@ miidev->write = tse_phy_write; miidev->flags = 0; miidev->edev = edev; + miidev->parent = dev; if (dev->platform_data != NULL) miidev->address = *((int8_t *)(dev->platform_data)); diff --git a/drivers/net/at91_ether.c b/drivers/net/at91_ether.c index d5e26a1..8d0b43b 100644 --- a/drivers/net/at91_ether.c +++ b/drivers/net/at91_ether.c @@ -272,6 +272,7 @@ edev->halt = at91rm9200_eth_halt; edev->get_ethaddr = at91rm9200_get_ethaddr; edev->set_ethaddr = at91rm9200_set_ethaddr; + edev->parent = dev; p_mac = AT91C_BASE_EMAC; diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c index d954e39..33afc5e 100644 --- a/drivers/net/cs8900.c +++ b/drivers/net/cs8900.c @@ -458,6 +458,7 @@ edev->halt = cs8900_halt; edev->get_ethaddr = cs8900_get_ethaddr; edev->set_ethaddr = cs8900_set_ethaddr; + edev->parent = dev; eth_register(edev); return 0; diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index be14317..e9ec61b 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -513,6 +513,7 @@ edev->halt = dm9000_eth_halt; edev->set_ethaddr = dm9000_set_ethaddr; edev->get_ethaddr = dm9000_get_ethaddr; + edev->parent = dev; /* RESET device */ dm9000_reset(priv); @@ -540,6 +541,7 @@ priv->miidev.address = 0; priv->miidev.flags = 0; priv->miidev.edev = edev; + priv->miidev.parent = dev; mii_register(&priv->miidev); eth_register(edev); diff --git a/drivers/net/ep93xx.c b/drivers/net/ep93xx.c index 7821cd2..954ec78 100644 --- a/drivers/net/ep93xx.c +++ b/drivers/net/ep93xx.c @@ -497,11 +497,13 @@ edev->halt = ep93xx_eth_halt; edev->get_ethaddr = ep93xx_eth_get_ethaddr; edev->set_ethaddr = ep93xx_eth_set_ethaddr; + edev->parent = dev; priv->miidev.read = ep93xx_phy_read; priv->miidev.write = ep93xx_phy_write; priv->miidev.address = 0; priv->miidev.flags = 0; + priv->miidev.parent = dev; priv->tx_dq.base = calloc(NUMTXDESC, sizeof(struct tx_descriptor)); diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c index 8b4f439..3b0f266 100644 --- a/drivers/net/fec_imx.c +++ b/drivers/net/fec_imx.c @@ -612,6 +612,7 @@ edev->halt = fec_halt; edev->get_ethaddr = fec_get_hwaddr; edev->set_ethaddr = fec_set_hwaddr; + edev->parent = dev; fec->regs = dev_request_mem_region(dev, 0); @@ -644,6 +645,7 @@ fec->miidev.address = pdata->phy_addr; fec->miidev.flags = pdata->xcv_type == MII10 ? MIIDEV_FORCE_10 : 0; fec->miidev.edev = edev; + fec->miidev.parent = dev; mii_register(&fec->miidev); } diff --git a/drivers/net/fec_mpc5200.c b/drivers/net/fec_mpc5200.c index 310d70d..403aad5 100644 --- a/drivers/net/fec_mpc5200.c +++ b/drivers/net/fec_mpc5200.c @@ -672,6 +672,7 @@ edev->halt = mpc5xxx_fec_halt; edev->get_ethaddr = mpc5xxx_fec_get_ethaddr; edev->set_ethaddr = mpc5xxx_fec_set_ethaddr; + edev->parent = dev; fec->eth = dev_request_mem_region(dev, 0); fec->tbdBase = (FEC_TBD *)FEC_BD_BASE; @@ -687,6 +688,7 @@ fec->miidev.address = CONFIG_PHY_ADDR; fec->miidev.flags = pdata->xcv_type == MII10 ? MIIDEV_FORCE_10 : 0; fec->miidev.edev = edev; + fec->miidev.parent = dev; mii_register(&fec->miidev); } diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 95ad3d7..898cf3d 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -433,6 +433,7 @@ edev->halt = macb_halt; edev->get_ethaddr = pdata->get_ethaddr ? pdata->get_ethaddr : macb_get_ethaddr; edev->set_ethaddr = macb_set_ethaddr; + edev->parent = dev; macb->miidev.read = macb_phy_read; macb->miidev.write = macb_phy_write; @@ -440,6 +441,7 @@ macb->miidev.flags = pdata->flags & AT91SAM_ETHER_FORCE_LINK ? MIIDEV_FORCE_LINK : 0; macb->miidev.edev = edev; + macb->miidev.parent = dev; macb->flags = pdata->flags; macb->rx_buffer = xmalloc(CFG_MACB_RX_BUFFER_SIZE); diff --git a/drivers/net/miidev.c b/drivers/net/miidev.c index fa9d79e..501a4f8 100644 --- a/drivers/net/miidev.c +++ b/drivers/net/miidev.c @@ -210,6 +210,8 @@ mdev->dev.priv = mdev; mdev->dev.id = -1; strcpy(mdev->dev.name, "miidev"); + if (mdev->parent) + dev_add_child(mdev->parent, &mdev->dev); return register_device(&mdev->dev); } diff --git a/drivers/net/netx_eth.c b/drivers/net/netx_eth.c index fd40f62..5503bc9 100644 --- a/drivers/net/netx_eth.c +++ b/drivers/net/netx_eth.c @@ -258,11 +258,13 @@ edev->halt = netx_eth_halt; edev->get_ethaddr = netx_eth_get_ethaddr; edev->set_ethaddr = netx_eth_set_ethaddr; + edev->parent = dev; priv->miidev.read = netx_miidev_read; priv->miidev.write = netx_miidev_write; priv->miidev.address = 0; priv->miidev.flags = 0; + priv->miidev.parent = dev; netx_eth_init_phy(); mii_register(&priv->miidev); diff --git a/drivers/net/smc91111.c b/drivers/net/smc91111.c index 1c1ffea..2313aae 100644 --- a/drivers/net/smc91111.c +++ b/drivers/net/smc91111.c @@ -1311,12 +1311,14 @@ edev->halt = smc91c111_eth_halt; edev->get_ethaddr = smc91c111_get_ethaddr; edev->set_ethaddr = smc91c111_set_ethaddr; + edev->parent = dev; priv->miidev.read = smc91c111_phy_read; priv->miidev.write = smc91c111_phy_write; priv->miidev.address = 0; priv->miidev.flags = 0; priv->miidev.edev = edev; + priv->miidev.parent = dev; priv->base = dev_request_mem_region(dev, 0); smc91c111_reset(edev); diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 8c6f9fc..fba61c4 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -725,12 +725,14 @@ edev->halt = smc911x_eth_halt; edev->get_ethaddr = smc911x_get_ethaddr; edev->set_ethaddr = smc911x_set_ethaddr; + edev->parent = dev; priv->miidev.read = smc911x_phy_read; priv->miidev.write = smc911x_phy_write; priv->miidev.address = 1; priv->miidev.flags = 0; priv->miidev.edev = edev; + priv->miidev.parent = dev; priv->base = base; smc911x_reset(edev); diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index d148925..be5a170 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -474,6 +474,7 @@ dev->miidev.address = asix_get_phy_addr(dev); dev->miidev.flags = 0; dev->miidev.edev = &dev->edev; + dev->miidev.parent = &dev->udev->dev; return mii_register(&dev->miidev); } diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index ae137fb..b518992 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -444,6 +444,7 @@ dev->miidev.address = 1; /* FIXME: asix_get_phy_addr(dev); */ dev->miidev.flags = 0; dev->miidev.edev = &dev->edev; + dev->miidev.parent = &dev->udev->dev; // dev->miidev.name = dev->edev.name; /* reset phy and wait for reset to complete */ diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index cd658ed..5ffd7a6 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -206,6 +206,7 @@ edev->recv = usbnet_recv, edev->halt = usbnet_halt, edev->priv = undev; + edev->parent = &usbdev->dev; info = (struct driver_info *)prod->driver_info; undev->driver_info = info; diff --git a/drivers/nor/Kconfig b/drivers/nor/Kconfig index 43a6b84..84ce0d0 100644 --- a/drivers/nor/Kconfig +++ b/drivers/nor/Kconfig @@ -1,14 +1,16 @@ menu "flash drivers " -config HAS_CFI - bool - -config DRIVER_CFI - bool "cfi flash driver" +menuconfig DRIVER_CFI + bool "CFI " help If you have NOR Flash devices connected to your system and wish to use them say yes here. +if DRIVER_CFI + +config HAS_CFI + bool + config DRIVER_CFI_INTEL default y depends on DRIVER_CFI @@ -55,4 +57,33 @@ bool "use cfi driver with buffer write" depends on DRIVER_CFI || DRIVER_CFI +endif + +config MTD_M25P80 + tristate "SPI Flash chips (AT26DF, M25P, W25X, ...)" + depends on SPI + help + This enables access to most modern SPI flash chips, used for + program and data storage. Series supported include Atmel AT26DF, + Spansion S25SL, SST 25VF, ST M25P, and Winbond W25X. Other chips + are supported as well. See the driver source for the current list, + or to add other chips. + + Note that the original DataFlash chips (AT45 series, not AT26DF), + need an entirely different driver. + + Set up your spi devices with the right board-specific platform data, + if you want to specify device partitioning or to use a device which + doesn't support the JEDEC ID instruction. + +config MTD_SST25L + tristate "Support SST25L (non JEDEC) SPI Flash chips" + depends on MTD_M25P80 + help + This enables access to the non JEDEC SST25L SPI flash chips, used + for program and data storage. + + Set up your spi devices with the right board-specific platform data, + if you want to specify device partitioning. + endmenu diff --git a/drivers/nor/Makefile b/drivers/nor/Makefile index d255043..d676c55 100644 --- a/drivers/nor/Makefile +++ b/drivers/nor/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_DRIVER_CFI) += cfi_flash.o obj-$(CONFIG_DRIVER_CFI_INTEL) += cfi_flash_intel.o obj-$(CONFIG_DRIVER_CFI_AMD) += cfi_flash_amd.o +obj-$(CONFIG_MTD_M25P80) += m25p80.o diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c index 461b0e6..7b25adb 100644 --- a/drivers/nor/cfi_flash.c +++ b/drivers/nor/cfi_flash.c @@ -820,20 +820,35 @@ /* * make a proper sized command based on the port and chip widths */ -void flash_make_cmd(struct flash_info *info, u8 cmd, cfiword_t *cmdbuf) +void flash_make_cmd(struct flash_info *info, u32 cmd, cfiword_t *cmdbuf) { - cfiword_t result = 0; - int i = info->portwidth / info->chipwidth; + int i; + int cp_offset; + int cword_offset; + uchar val; + uchar *cp; - while (i--) - result = (result << (8 * info->chipwidth)) | cmd; - *cmdbuf = result; + *cmdbuf = 0; + cp = (uchar *)cmdbuf; + + for (i = info->portwidth; i > 0; i--) { + cword_offset = (info->portwidth-i) % info->chipwidth; +#if __BYTE_ORDER == __LITTLE_ENDIAN + cp_offset = info->portwidth - i; + val = *((uchar *)&cmd + cword_offset); +#else + cp_offset = i - 1; + val = *((uchar *)&cmd + sizeof(u32) - cword_offset - 1); +#endif + cp[cp_offset] = (cword_offset >= sizeof(u32)) ? 0x00 : val; + } } /* * Write a proper sized command to the correct address */ -void flash_write_cmd (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd) +void flash_write_cmd(struct flash_info *info, flash_sect_t sect, + uint offset, u32 cmd) { uchar *addr; @@ -845,7 +860,8 @@ flash_write_word(info, cword, addr); } -int flash_isequal (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd) +int flash_isequal(struct flash_info *info, flash_sect_t sect, + uint offset, u32 cmd) { void *addr; cfiword_t cword; @@ -882,7 +898,8 @@ return retval; } -int flash_isset (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd) +int flash_isset(struct flash_info *info, flash_sect_t sect, + uint offset, u32 cmd) { void *addr = flash_make_addr (info, sect, offset); cfiword_t cword; diff --git a/drivers/nor/cfi_flash.h b/drivers/nor/cfi_flash.h index 9098021..32dcc8c 100644 --- a/drivers/nor/cfi_flash.h +++ b/drivers/nor/cfi_flash.h @@ -231,16 +231,19 @@ #define CFI_FLASH_SHIFT_WIDTH 3 /* Prototypes */ -int flash_isset (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd); -void flash_write_cmd (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd); +int flash_isset(struct flash_info *info, flash_sect_t sect, + uint offset, u32 cmd); +void flash_write_cmd(struct flash_info *info, flash_sect_t sect, + uint offset, u32 cmd); flash_sect_t find_sector (struct flash_info *info, ulong addr); int flash_status_check (struct flash_info *info, flash_sect_t sector, uint64_t tout, char *prompt); int flash_generic_status_check (struct flash_info *info, flash_sect_t sector, uint64_t tout, char *prompt); -int flash_isequal (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd); -void flash_make_cmd(struct flash_info *info, uchar cmd, cfiword_t *cmdbuf); +int flash_isequal(struct flash_info *info, flash_sect_t sect, + uint offset, u32 cmd); +void flash_make_cmd(struct flash_info *info, u32 cmd, cfiword_t *cmdbuf); static inline void flash_write8(u8 value, void *addr) { diff --git a/drivers/nor/cfi_flash_amd.c b/drivers/nor/cfi_flash_amd.c index b1d7070..45c59b9 100644 --- a/drivers/nor/cfi_flash_amd.c +++ b/drivers/nor/cfi_flash_amd.c @@ -142,28 +142,28 @@ if (bankwidth_is_1(info)) { cnt = len; - flash_write_cmd (info, sector, 0, (uchar) cnt - 1); + flash_write_cmd(info, sector, 0, (u32)cnt - 1); while (cnt-- > 0) { flash_write8(flash_read8(src), dst); src += 1, dst += 1; } } else if (bankwidth_is_2(info)) { cnt = len >> 1; - flash_write_cmd (info, sector, 0, (uchar) cnt - 1); + flash_write_cmd(info, sector, 0, (u32)cnt - 1); while (cnt-- > 0) { flash_write16(flash_read16(src), dst); src += 2, dst += 2; } } else if (bankwidth_is_4(info)) { cnt = len >> 2; - flash_write_cmd (info, sector, 0, (uchar) cnt - 1); + flash_write_cmd(info, sector, 0, (u32)cnt - 1); while (cnt-- > 0) { flash_write32(flash_read32(src), dst); src += 4, dst += 4; } } else if (bankwidth_is_8(info)) { cnt = len >> 3; - flash_write_cmd (info, sector, 0, (uchar) cnt - 1); + flash_write_cmd(info, sector, 0, (u32)cnt - 1); while (cnt-- > 0) { flash_write64(flash_read64(src), dst); src += 8, dst += 8; diff --git a/drivers/nor/cfi_flash_intel.c b/drivers/nor/cfi_flash_intel.c index c3cbad5..6318cfe 100644 --- a/drivers/nor/cfi_flash_intel.c +++ b/drivers/nor/cfi_flash_intel.c @@ -70,7 +70,7 @@ /* reduce the number of loops by the width of the port */ cnt = len >> (info->portwidth - 1); - flash_write_cmd (info, sector, 0, (uchar) cnt - 1); + flash_write_cmd(info, sector, 0, (u32)cnt - 1); while (cnt-- > 0) { if (bankwidth_is_1(info)) { flash_write8(flash_read8(src), dst); diff --git a/drivers/nor/m25p80.c b/drivers/nor/m25p80.c new file mode 100644 index 0000000..e6fe75e --- /dev/null +++ b/drivers/nor/m25p80.c @@ -0,0 +1,818 @@ +/* + * MTD SPI driver for ST M25Pxx (and similar) serial flash chips + * + * Author: Mike Lavender, mike@steroidmicros.com + * Copyright (c) 2005, Intec Automation Inc. + * + * Adapted to barebox : Franck JULLIEN + * Copyright (c) 2011 + * + * Some parts are based on lart.c by Abraham Van Der Merwe + * + * Cleaned up and generalized based on mtd_dataflash.c + * + * This code is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "m25p80.h" + +/****************************************************************************/ + +/* + * Internal helper functions + */ + +/* + * Read the status register, returning its value in the location + * Return the status register value. + * Returns negative if error occurred. + */ +static int read_sr(struct m25p *flash) +{ + ssize_t retval; + u8 code = OPCODE_RDSR; + u8 val; + + retval = spi_write_then_read(flash->spi, &code, 1, &val, 1); + + if (retval < 0) { + dev_err(&flash->spi->dev, "error %d reading SR\n", + (int) retval); + return retval; + } + + return val; +} + +/* + * Write status register 1 byte + * Returns negative if error occurred. + */ +static int write_sr(struct m25p *flash, u8 val) +{ + flash->command[0] = OPCODE_WRSR; + flash->command[1] = val; + + return spi_write(flash->spi, flash->command, 2); +} + +/* + * Set write enable latch with Write Enable command. + * Returns negative if error occurred. + */ +static inline int write_enable(struct m25p *flash) +{ + u8 code = OPCODE_WREN; + + return spi_write_then_read(flash->spi, &code, 1, NULL, 0); +} + +/* + * Send write disble instruction to the chip. + */ +static inline int write_disable(struct m25p *flash) +{ + u8 code = OPCODE_WRDI; + + return spi_write_then_read(flash->spi, &code, 1, NULL, 0); +} + +/* + * Enable/disable 4-byte addressing mode. + */ +static inline int set_4byte(struct m25p *flash, int enable) +{ + u8 code = enable ? OPCODE_EN4B : OPCODE_EX4B; + + return spi_write_then_read(flash->spi, &code, 1, NULL, 0); +} + +/* + * Service routine to read status register until ready, or timeout occurs. + * Returns non-zero if error. + */ +static int wait_till_ready(struct m25p *flash) +{ + int sr; + uint64_t timer_start; + + timer_start = get_time_ns(); + + do { + if ((sr = read_sr(flash)) < 0) + break; + else if (!(sr & SR_WIP)) + return 0; + + } while (!(is_timeout(timer_start, MAX_READY_WAIT * SECOND))); + + return -ETIMEDOUT; +} + +/* + * Erase the whole flash memory + * + * Returns 0 if successful, non-zero otherwise. + */ +static int erase_chip(struct m25p *flash) +{ + dev_dbg(&flash->spi->dev, "%s %lldKiB\n", + __func__, (long long)(flash->size >> 10)); + + /* Wait until finished previous write command. */ + if (wait_till_ready(flash)) + return -ETIMEDOUT; + + /* Send write enable, then erase commands. */ + write_enable(flash); + + /* Set up command buffer. */ + flash->command[0] = OPCODE_CHIP_ERASE; + + spi_write(flash->spi, flash->command, 1); + + return 0; +} + +static void m25p_addr2cmd(struct m25p *flash, unsigned int addr, u8 *cmd) +{ + /* opcode is in cmd[0] */ + cmd[1] = addr >> (flash->addr_width * 8 - 8); + cmd[2] = addr >> (flash->addr_width * 8 - 16); + cmd[3] = addr >> (flash->addr_width * 8 - 24); + cmd[4] = addr >> (flash->addr_width * 8 - 32); +} + +static int m25p_cmdsz(struct m25p *flash) +{ + return 1 + flash->addr_width; +} + +/* + * Erase one sector of flash memory at offset ``offset'' which is any + * address within the sector which should be erased. + * + * Returns 0 if successful, non-zero otherwise. + */ +static int erase_sector(struct m25p *flash, u32 offset) +{ + dev_dbg(&flash->spi->dev, "%s %dKiB at 0x%08x\n", + __func__, flash->erasesize / 1024, offset); + + /* Wait until finished previous write command. */ + if (wait_till_ready(flash)) + return -ETIMEDOUT; + + /* Send write enable, then erase commands. */ + write_enable(flash); + + /* Set up command buffer. */ + flash->command[0] = flash->erase_opcode; + m25p_addr2cmd(flash, offset, flash->command); + + spi_write(flash->spi, flash->command, m25p_cmdsz(flash)); + + return 0; +} + +/* + * Erase an address range on the flash chip. The address range may extend + * one or more erase sectors. Return an error is there is a problem erasing. + */ +static ssize_t m25p80_erase(struct cdev *cdev, size_t count, unsigned long offset) +{ + struct m25p *flash = cdev->priv; + u32 addr, len; + u32 start_sector; + u32 end_sector; + u32 progress = 0; + + dev_dbg(&flash->spi->dev, "%s %s 0x%llx, len %lld\n", + __func__, "at", (long long)offset, (long long)count); + + /* sanity checks */ + if (offset + count > flash->size) + return -EINVAL; + + addr = offset; + len = count; + + start_sector = offset / flash->erasesize; + end_sector = (offset + count - 1) / flash->erasesize; + init_progression_bar(end_sector - start_sector); + + /* whole-chip erase? */ + if (len == flash->size) { + + show_progress(start_sector); + if (erase_chip(flash)) + return -EIO; + show_progress(end_sector); + + /* REVISIT in some cases we could speed up erasing large regions + * by using OPCODE_SE instead of OPCODE_BE_4K. We may have set up + * to use "small sector erase", but that's not always optimal. + */ + + /* "sector"-at-a-time erase */ + } else { + while (len) { + if (erase_sector(flash, addr)) + return -EIO; + + addr += flash->erasesize; + len -= flash->erasesize; + show_progress(progress++); + } + } + + printf("\n"); + + return 0; +} + +ssize_t m25p80_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags) +{ + struct m25p *flash = cdev->priv; + struct spi_transfer t[2]; + struct spi_message m; + ssize_t retlen; + + /* sanity checks */ + if (!count) + return 0; + + if (offset + count > flash->size) + return -EINVAL; + + spi_message_init(&m); + memset(t, 0, (sizeof t)); + + /* NOTE: + * OPCODE_FAST_READ (if available) is faster. + * Should add 1 byte DUMMY_BYTE. + */ + t[0].tx_buf = flash->command; + t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE; + spi_message_add_tail(&t[0], &m); + + t[1].rx_buf = buf; + t[1].len = count; + spi_message_add_tail(&t[1], &m); + + /* Byte count starts at zero. */ + retlen = 0; + + /* Wait till previous write/erase is done. */ + if (wait_till_ready(flash)) + return -ETIMEDOUT; + + /* FIXME switch to OPCODE_FAST_READ. It's required for higher + * clocks; and at this writing, every chip this driver handles + * supports that opcode. + */ + + /* Set up the write data buffer. */ + flash->command[0] = OPCODE_READ; + m25p_addr2cmd(flash, offset, flash->command); + + spi_sync(flash->spi, &m); + + retlen = m.actual_length - m25p_cmdsz(flash) - FAST_READ_DUMMY_BYTE; + + return retlen; +} + +ssize_t m25p80_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags) +{ + struct m25p *flash = cdev->priv; + struct spi_transfer t[2]; + struct spi_message m; + ssize_t retlen = 0; + u32 page_offset, page_size; + + debug("m25p80_write %ld bytes at 0x%08lX\n", (unsigned long)count, offset); + + if (offset + count > flash->size) + return -EINVAL; + + spi_message_init(&m); + memset(t, 0, (sizeof t)); + + t[0].tx_buf = flash->command; + t[0].len = m25p_cmdsz(flash); + spi_message_add_tail(&t[0], &m); + + t[1].tx_buf = buf; + spi_message_add_tail(&t[1], &m); + + /* Wait until finished previous write command. */ + if (wait_till_ready(flash)) + return -ETIMEDOUT; + + write_enable(flash); + + /* Set up the opcode in the write buffer. */ + flash->command[0] = OPCODE_PP; + m25p_addr2cmd(flash, offset, flash->command); + + page_offset = offset & (flash->page_size - 1); + + /* do all the bytes fit onto one page? */ + if (page_offset + count <= flash->page_size) { + t[1].len = count; + + spi_sync(flash->spi, &m); + + retlen = m.actual_length - m25p_cmdsz(flash); + } else { + u32 i; + + /* the size of data remaining on the first page */ + page_size = flash->page_size - page_offset; + + t[1].len = page_size; + spi_sync(flash->spi, &m); + + retlen = m.actual_length - m25p_cmdsz(flash); + + /* write everything in flash->page_size chunks */ + for (i = page_size; i < count; i += page_size) { + page_size = count - i; + if (page_size > flash->page_size) + page_size = flash->page_size; + + /* write the next page to flash */ + m25p_addr2cmd(flash, offset + i, flash->command); + + t[1].tx_buf = buf + i; + t[1].len = page_size; + + wait_till_ready(flash); + + write_enable(flash); + + spi_sync(flash->spi, &m); + + retlen += m.actual_length - m25p_cmdsz(flash); + + } + } + + return retlen; +} +#ifdef CONFIG_MTD_SST25L +ssize_t sst_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags) +{ + struct m25p *flash = cdev->priv; + struct spi_transfer t[2]; + struct spi_message m; + size_t actual; + ssize_t retlen; + int cmd_sz, ret; + + debug("sst_write %ld bytes at 0x%08lX\n", (unsigned long)count, offset); + + retlen = 0; + + /* sanity checks */ + if (!count) + return 0; + + if (offset + count > flash->size) + return -EINVAL; + + spi_message_init(&m); + memset(t, 0, (sizeof t)); + + t[0].tx_buf = flash->command; + t[0].len = m25p_cmdsz(flash); + spi_message_add_tail(&t[0], &m); + + t[1].tx_buf = buf; + spi_message_add_tail(&t[1], &m); + + /* Wait until finished previous write command. */ + ret = wait_till_ready(flash); + if (ret) + goto time_out; + + write_enable(flash); + + actual = offset % 2; + /* Start write from odd address. */ + if (actual) { + flash->command[0] = OPCODE_BP; + m25p_addr2cmd(flash, offset, flash->command); + + /* write one byte. */ + t[1].len = 1; + spi_sync(flash->spi, &m); + ret = wait_till_ready(flash); + if (ret) + goto time_out; + retlen += m.actual_length - m25p_cmdsz(flash); + } + offset += actual; + + flash->command[0] = OPCODE_AAI_WP; + m25p_addr2cmd(flash, offset, flash->command); + + /* Write out most of the data here. */ + cmd_sz = m25p_cmdsz(flash); + for (; actual < count - 1; actual += 2) { + t[0].len = cmd_sz; + /* write two bytes. */ + t[1].len = 2; + t[1].tx_buf = buf + actual; + + spi_sync(flash->spi, &m); + ret = wait_till_ready(flash); + if (ret) + goto time_out; + retlen += m.actual_length - cmd_sz; + cmd_sz = 1; + offset += 2; + } + write_disable(flash); + ret = wait_till_ready(flash); + if (ret) + goto time_out; + + /* Write out trailing byte if it exists. */ + if (actual != count) { + write_enable(flash); + flash->command[0] = OPCODE_BP; + m25p_addr2cmd(flash, offset, flash->command); + t[0].len = m25p_cmdsz(flash); + t[1].len = 1; + t[1].tx_buf = buf + actual; + + spi_sync(flash->spi, &m); + ret = wait_till_ready(flash); + if (ret) + goto time_out; + retlen += m.actual_length - m25p_cmdsz(flash); + write_disable(flash); + } + +time_out: + return retlen; +} +#endif + +static void m25p80_info(struct device_d *dev) +{ + struct m25p *flash = dev->priv; + struct flash_info *info = flash->info; + + printf("Flash type : %s\n", flash->name); + printf("Size : %lldKiB\n", (long long)flash->size / 1024); + printf("Number of sectors : %d\n", info->n_sectors); + printf("Sector size : %dKiB\n", info->sector_size / 1024); + printf("\n"); +} + + +/****************************************************************************/ + +/* + * SPI device driver setup and teardown + */ + +#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ + ((unsigned long)&(struct flash_info) { \ + .jedec_id = (_jedec_id), \ + .ext_id = (_ext_id), \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = 256, \ + .flags = (_flags), \ + }) + +#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width) \ + ((unsigned long)&(struct flash_info) { \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = (_page_size), \ + .addr_width = (_addr_width), \ + .flags = M25P_NO_ERASE, \ + }) + +/* NOTE: double check command sets and memory organization when you add + * more flash chips. This current list focusses on newer chips, which + * have been converging on command sets which including JEDEC ID. + */ +static const struct spi_device_id m25p_ids[] = { + /* Atmel -- some are (confusingly) marketed as "DataFlash" */ + { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) }, + { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) }, + + { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) }, + { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) }, + + { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) }, + { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) }, + { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) }, + { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) }, + + /* EON -- en25xxx */ + { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) }, + { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, + { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, + + /* Intel/Numonyx -- xxxs33b */ + { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, + { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, + { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, + + /* Macronix */ + { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, + { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, + { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, + { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, + { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, + { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, + { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, + { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, + + /* Spansion -- single (large) sector size only, at least + * for the chips listed here (without boot sectors). + */ + { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, + { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, + { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, + { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, + { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SECT_4K) }, + { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, + { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, + { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, + { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, + { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, + { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, + { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, + + /* SST -- large erase sizes are "overlays", "sectors" are 4K */ + { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K) }, + { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K) }, + { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K) }, + { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K) }, + { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K) }, + { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K) }, + { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K) }, + { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K) }, + + /* ST Microelectronics -- newer production may have feature updates */ + { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) }, + { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) }, + { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) }, + { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) }, + { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) }, + { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) }, + { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, + { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, + { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, + + { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, + { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, + { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) }, + { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0) }, + { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0) }, + { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0) }, + { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0) }, + { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0) }, + { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0) }, + + { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) }, + { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) }, + { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) }, + + { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) }, + { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) }, + + { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) }, + + /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ + { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, + { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) }, + { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, + { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, + { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, + { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, + { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, + { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, + { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, + + /* Catalyst / On Semiconductor -- non-JEDEC */ + { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, + { "cat25c03", CAT25_INFO( 32, 8, 16, 2) }, + { "cat25c09", CAT25_INFO( 128, 8, 32, 2) }, + { "cat25c17", CAT25_INFO( 256, 8, 32, 2) }, + { "cat25128", CAT25_INFO(2048, 8, 64, 2) }, + { }, +}; + +static const struct spi_device_id *jedec_probe(struct spi_device *spi) +{ + int tmp; + u8 code = OPCODE_RDID; + u8 id[5]; + u32 jedec; + u16 ext_jedec; + struct flash_info *info; + + /* JEDEC also defines an optional "extended device information" + * string for after vendor-specific data, after the three bytes + * we use here. Supporting some chips might require using it. + */ + spi_write_then_read(spi, &code, 1, id, 5); + + jedec = id[0]; + jedec = jedec << 8; + jedec |= id[1]; + jedec = jedec << 8; + jedec |= id[2]; + + ext_jedec = id[3] << 8 | id[4]; + + for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) { + info = (void *)m25p_ids[tmp].driver_data; + if (info->jedec_id == jedec) { + if (info->ext_id != 0 && info->ext_id != ext_jedec) + continue; + return &m25p_ids[tmp]; + } + } + dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec); + + return NULL; +} + + +static struct file_operations m25p80_ops = { + .read = m25p80_read, + .write = m25p80_write, + .erase = m25p80_erase, + .lseek = dev_lseek_default, +}; + +/* + * board specific setup should have ensured the SPI clock used here + * matches what the READ command supports, at least until this driver + * understands FAST_READ (for clocks over 25 MHz). + */ +static int m25p_probe(struct device_d *dev) +{ + struct spi_device *spi = (struct spi_device *)dev->type_data; + const struct spi_device_id *id = NULL; + struct flash_info *info = NULL; + struct flash_platform_data *data; + struct m25p *flash; + unsigned i; + unsigned do_jdec_probe = 1; + + /* Platform data helps sort out which chip type we have, as + * well as how this board partitions it. If we don't have + * a chip ID, try the JEDEC id commands; they'll work for most + * newer chips, even if we don't recognize the particular chip. + */ + data = dev->platform_data; + + if (data && data->type) { + const struct spi_device_id *plat_id; + + for (i = 0; i < ARRAY_SIZE(m25p_ids) - 1; i++) { + plat_id = &m25p_ids[i]; + if (strcmp(data->type, plat_id->name)) + continue; + break; + } + + if (i < ARRAY_SIZE(m25p_ids) - 1) { + id = plat_id; + info = (void *)id->driver_data; + /* If flash type is provided but the memory is not + * JEDEC compliant, don't try to probe the JEDEC id */ + if (!info->jedec_id) + do_jdec_probe = 0; + } else + dev_warn(&spi->dev, "unrecognized id %s\n", data->type); + } + + if (do_jdec_probe) { + const struct spi_device_id *jid; + + jid = jedec_probe(spi); + if (!jid) { + return -ENODEV; + } else if (jid != id) { + + /* + * JEDEC knows better, so overwrite platform ID. We + * can't trust partitions any longer, but we'll let + * mtd apply them anyway, since some partitions may be + * marked read-only, and we don't want to lose that + * information, even if it's not 100% accurate. + */ + if (id) + dev_warn(dev, "found %s, expected %s\n", + jid->name, id->name); + + id = jid; + info = (void *)jid->driver_data; + } + } + + flash = xzalloc(sizeof *flash); + flash->command = xmalloc(MAX_CMD_SIZE + FAST_READ_DUMMY_BYTE); + + flash->spi = spi; + dev->priv = (void *)flash; + /* + * Atmel, SST and Intel/Numonyx serial flash tend to power + * up with the software protection bits set + */ + + if (info->jedec_id >> 16 == 0x1f || + info->jedec_id >> 16 == 0x89 || + info->jedec_id >> 16 == 0xbf) { + write_enable(flash); + write_sr(flash, 0); + } + + flash->name = (char *)id->name; + flash->info = info; + flash->size = info->sector_size * info->n_sectors; + flash->erasesize = info->sector_size; + flash->cdev.size = info->sector_size * info->n_sectors; + flash->cdev.dev = dev; + flash->cdev.ops = &m25p80_ops; + flash->cdev.priv = flash; + + if (data && data->name) + flash->cdev.name = asprintf("%s%d", data->name, dev->id); + else + flash->cdev.name = asprintf("%s", (char *)dev_name(&spi->dev)); + +#ifdef CONFIG_MTD_SST25L + /* sst flash chips use AAI word program */ + if (info->jedec_id >> 16 == 0xbf) + m25p80_ops.write = sst_write; + else +#endif + m25p80_ops.write = m25p80_write; + + /* prefer "small sector" erase if possible */ + if (info->flags & SECT_4K) + flash->erase_opcode = OPCODE_BE_4K; + else + flash->erase_opcode = OPCODE_SE; + + flash->page_size = info->page_size; + + if (info->addr_width) + flash->addr_width = info->addr_width; + else { + /* enable 4-byte addressing if the device exceeds 16MiB */ + if (flash->size > 0x1000000) { + flash->addr_width = 4; + set_4byte(flash, 1); + } else + flash->addr_width = 3; + } + + dev_info(dev, "%s (%lld Kbytes)\n", id->name, (long long)flash->size >> 10); + + devfs_create(&flash->cdev); + + return 0; +} + +static struct driver_d epcs_flash_driver = { + .name = "m25p", + .probe = m25p_probe, + .info = m25p80_info, +}; + +static int epcs_init(void) +{ + register_driver(&epcs_flash_driver); + return 0; +} + +device_initcall(epcs_init); diff --git a/drivers/nor/m25p80.h b/drivers/nor/m25p80.h new file mode 100644 index 0000000..3f9dd9c --- /dev/null +++ b/drivers/nor/m25p80.h @@ -0,0 +1,90 @@ +#ifndef _M25P80_H_ +#define _M25P80_H_ + +/* Flash opcodes. */ +#define OPCODE_WREN 0x06 /* Write enable */ +#define OPCODE_RDSR 0x05 /* Read status register */ +#define OPCODE_WRSR 0x01 /* Write status register 1 byte */ +#define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */ +#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ +#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ +#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ +#define OPCODE_BE_32K 0x52 /* Erase 32KiB block */ +#define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ +#define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ +#define OPCODE_RDID 0x9f /* Read JEDEC ID */ + +/* Used for SST flashes only. */ +#define OPCODE_BP 0x02 /* Byte program */ +#define OPCODE_WRDI 0x04 /* Write disable */ +#define OPCODE_AAI_WP 0xad /* Auto address increment word program */ + +/* Used for Macronix flashes only. */ +#define OPCODE_EN4B 0xb7 /* Enter 4-byte mode */ +#define OPCODE_EX4B 0xe9 /* Exit 4-byte mode */ + +/* Status Register bits. */ +#define SR_WIP 1 /* Write in progress */ +#define SR_WEL 2 /* Write enable latch */ +/* meaning of other SR_* bits may differ between vendors */ +#define SR_BP0 4 /* Block protect 0 */ +#define SR_BP1 8 /* Block protect 1 */ +#define SR_BP2 0x10 /* Block protect 2 */ +#define SR_SRWD 0x80 /* SR write protect */ + +/* Define max times to check status register before we give up. */ +#define MAX_READY_WAIT 40 /* M25P16 specs 40s max chip erase */ +#define MAX_CMD_SIZE 5 + +#ifdef CONFIG_M25PXX_USE_FAST_READ +#define OPCODE_READ OPCODE_FAST_READ +#define FAST_READ_DUMMY_BYTE 1 +#else +#define OPCODE_READ OPCODE_NORM_READ +#define FAST_READ_DUMMY_BYTE 0 +#endif + +#define SPI_NAME_SIZE 32 + +struct spi_device_id { + char name[SPI_NAME_SIZE]; + unsigned long driver_data; +}; + +struct m25p { + struct spi_device *spi; + struct flash_info *info; + struct mtd_info mtd; + struct cdev cdev; + char *name; + u32 erasesize; + u16 page_size; + u16 addr_width; + u8 erase_opcode; + u8 *command; + u32 size; +}; + +struct flash_info { + /* JEDEC id zero means "no ID" (most older chips); otherwise it has + * a high byte of zero plus three data bytes: the manufacturer id, + * then a two byte device id. + */ + u32 jedec_id; + u16 ext_id; + + /* The size listed here is what works with OPCODE_SE, which isn't + * necessarily called a "sector" by the vendor. + */ + unsigned sector_size; + u16 n_sectors; + + u16 page_size; + u16 addr_width; + + u16 flags; +#define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */ +#define M25P_NO_ERASE 0x02 /* No erase command needed */ +}; + +#endif diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 9ab03f6..c72493c 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -19,4 +19,9 @@ depends on ARCH_IMX51 || ARCH_IMX53 default y +config DRIVER_SPI_ALTERA + bool "Altera SPI Master driver" + depends on NIOS2 + depends on SPI + endmenu diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index b2b2f67..90e141d 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_SPI) += spi.o obj-$(CONFIG_DRIVER_SPI_IMX) += imx_spi.o +obj-$(CONFIG_DRIVER_SPI_ALTERA) += altera_spi.o diff --git a/drivers/spi/altera_spi.c b/drivers/spi/altera_spi.c new file mode 100644 index 0000000..2c02d7a --- /dev/null +++ b/drivers/spi/altera_spi.c @@ -0,0 +1,227 @@ +/* + * (C) Copyright 2011 - Franck JULLIEN + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include + +static int altera_spi_setup(struct spi_device *spi) +{ + struct spi_master *master = spi->master; + struct device_d spi_dev = spi->dev; + struct altera_spi *altera_spi = container_of(master, struct altera_spi, master); + + if (spi->bits_per_word != altera_spi->databits) { + dev_err(master->dev, " master doesn't support %d bits per word requested by %s\n", + spi->bits_per_word, spi_dev.name); + return -1; + } + + if ((spi->mode & (SPI_CPHA | SPI_CPOL)) != altera_spi->mode) { + dev_err(master->dev, " master doesn't support SPI_MODE%d requested by %s\n", + spi->mode & (SPI_CPHA | SPI_CPOL), spi_dev.name); + return -1; + } + + if (spi->max_speed_hz < altera_spi->speed) { + dev_err(master->dev, " frequency is too high for %s\n", spi_dev.name); + return -1; + } + + dev_dbg(master->dev, " mode 0x%08x, bits_per_word: %d, speed: %d\n", + spi->mode, spi->bits_per_word, altera_spi->speed); + + return 0; +} + + +static unsigned int altera_spi_xchg_single(struct altera_spi *altera_spi, unsigned int data) +{ + struct nios_spi *nios_spi = altera_spi->regs; + + while (!(readl(&nios_spi->status) & NIOS_SPI_TRDY)); + writel(data, &nios_spi->txdata); + + while (!(readl(&nios_spi->status) & NIOS_SPI_RRDY)); + + return readl(&nios_spi->rxdata); +} + +/* + * When using SPI_CS_HIGH devices, only one device is allowed to be + * connected to the Altera SPI master. This limitation is due to the + * emulation of an active high CS by writing 0 to the slaveselect register + * (this produce a '1' to all CS pins). + */ + +static void altera_spi_cs_active(struct spi_device *spi) +{ + struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master); + struct nios_spi *nios_spi = altera_spi->regs; + uint32_t tmp; + + if (spi->mode & SPI_CS_HIGH) { + tmp = readw(&nios_spi->control); + writew(tmp & ~NIOS_SPI_SSO, &nios_spi->control); + writel(0, &nios_spi->slaveselect); + } else { + writel(1 << spi->chip_select, &nios_spi->slaveselect); + tmp = readl(&nios_spi->control); + writel(tmp | NIOS_SPI_SSO, &nios_spi->control); + } +} + +static void altera_spi_cs_inactive(struct spi_device *spi) +{ + struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master); + struct nios_spi *nios_spi = altera_spi->regs; + uint32_t tmp; + + if (spi->mode & SPI_CS_HIGH) { + writel(1 << spi->chip_select, &nios_spi->slaveselect); + tmp = readl(&nios_spi->control); + writel(tmp | NIOS_SPI_SSO, &nios_spi->control); + } else { + tmp = readw(&nios_spi->control); + writew(tmp & ~NIOS_SPI_SSO, &nios_spi->control); + } +} + +static unsigned altera_spi_do_xfer(struct spi_device *spi, struct spi_transfer *t) +{ + struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master); + int word_len = spi->bits_per_word; + unsigned retval = 0; + u32 txval; + u32 rxval; + + word_len = spi->bits_per_word; + + if (word_len <= 8) { + const u8 *txbuf = t->tx_buf; + u8 *rxbuf = t->rx_buf; + int i = 0; + + while (i < t->len) { + txval = txbuf ? txbuf[i] : 0; + rxval = altera_spi_xchg_single(altera_spi, txval); + if (rxbuf) + rxbuf[i] = rxval; + i++; + retval++; + } + } else if (word_len <= 16) { + const u16 *txbuf = t->tx_buf; + u16 *rxbuf = t->rx_buf; + int i = 0; + + while (i < t->len >> 1) { + txval = txbuf ? txbuf[i] : 0; + rxval = altera_spi_xchg_single(altera_spi, txval); + if (rxbuf) + rxbuf[i] = rxval; + i++; + retval += 2; + } + } else if (word_len <= 32) { + const u32 *txbuf = t->tx_buf; + u32 *rxbuf = t->rx_buf; + int i = 0; + + while (i < t->len >> 2) { + txval = txbuf ? txbuf[i] : 0; + rxval = altera_spi_xchg_single(altera_spi, txval); + if (rxbuf) + rxbuf[i] = rxval; + i++; + retval += 4; + } + } + + return retval; +} + +static int altera_spi_transfer(struct spi_device *spi, struct spi_message *mesg) +{ + struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master); + struct nios_spi *nios_spi = altera_spi->regs; + struct spi_transfer *t; + + altera_spi_cs_active(spi); + + mesg->actual_length = 0; + + list_for_each_entry(t, &mesg->transfers, transfer_list) { + mesg->actual_length += altera_spi_do_xfer(spi, t); + } + + /* Wait the end of any pending transfer */ + while ((readl(&nios_spi->status) & NIOS_SPI_TMT) == 0); + + altera_spi_cs_inactive(spi); + + return 0; +} + +static int altera_spi_probe(struct device_d *dev) +{ + struct spi_master *master; + struct altera_spi *altera_spi; + struct spi_altera_master *pdata = dev->platform_data; + struct nios_spi *nios_spi; + + altera_spi = xzalloc(sizeof(*altera_spi)); + + master = &altera_spi->master; + master->dev = dev; + + master->setup = altera_spi_setup; + master->transfer = altera_spi_transfer; + master->num_chipselect = pdata->num_chipselect; + + altera_spi->regs = dev_request_mem_region(dev, 0); + altera_spi->databits = pdata->databits; + altera_spi->speed = pdata->speed; + altera_spi->mode = pdata->spi_mode; + + nios_spi = altera_spi->regs; + writel(0, &nios_spi->slaveselect); + writel(0, &nios_spi->control); + + spi_register_master(master); + + return 0; +} + +static struct driver_d altera_spi_driver = { + .name = "altera_spi", + .probe = altera_spi_probe, +}; + +static int altera_spi_driver_init(void) +{ + return register_driver(&altera_spi_driver); +} + +device_initcall(altera_spi_driver_init); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 8058694..b561f9d 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -79,6 +79,7 @@ proxy->dev.platform_data = chip->platform_data; strcpy(proxy->dev.name, chip->name); proxy->dev.type_data = proxy; + dev_add_child(master->dev, &proxy->dev); status = register_device(&proxy->dev); /* drivers may modify this initial i/o setup */ diff --git a/include/asm-generic/int-ll64.h b/include/asm-generic/int-ll64.h new file mode 100644 index 0000000..f394147 --- /dev/null +++ b/include/asm-generic/int-ll64.h @@ -0,0 +1,78 @@ +/* + * asm-generic/int-ll64.h + * + * Integer declarations for architectures which use "long long" + * for 64-bit types. + */ + +#ifndef _ASM_GENERIC_INT_LL64_H +#define _ASM_GENERIC_INT_LL64_H + +#include + +#ifndef __ASSEMBLY__ +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#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 + +#endif /* __ASSEMBLY__ */ + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + +#define S8_C(x) x +#define U8_C(x) x ## U +#define S16_C(x) x +#define U16_C(x) x ## U +#define S32_C(x) x +#define U32_C(x) x ## U +#define S64_C(x) x ## LL +#define U64_C(x) x ## ULL + +#else /* __ASSEMBLY__ */ + +#define S8_C(x) x +#define U8_C(x) x +#define S16_C(x) x +#define U16_C(x) x +#define S32_C(x) x +#define U32_C(x) x +#define S64_C(x) x +#define U64_C(x) x + +#endif /* __ASSEMBLY__ */ + +#endif /* __KERNEL__ */ + +#endif /* _ASM_GENERIC_INT_LL64_H */ diff --git a/include/mci.h b/include/mci.h index 8c669ca..69cffe8 100644 --- a/include/mci.h +++ b/include/mci.h @@ -194,6 +194,7 @@ /** host information */ struct mci_host { struct device_d *hw_dev; /**< the host MCI hardware device */ + struct device_d dev; /**< our device */ unsigned voltages; unsigned host_caps; /**< Host's interface capabilities, refer MMC_VDD_* */ unsigned f_min; /**< host interface lower limit */ diff --git a/include/miidev.h b/include/miidev.h index 6f653d9..21727ef 100644 --- a/include/miidev.h +++ b/include/miidev.h @@ -33,6 +33,7 @@ struct mii_device { struct device_d dev; + struct device_d *parent; int address; /* The address the phy has on the bus */ int (*read) (struct mii_device *dev, int addr, int reg); diff --git a/include/net.h b/include/net.h index 1272f23..d0f8341 100644 --- a/include/net.h +++ b/include/net.h @@ -43,6 +43,7 @@ void *priv; struct device_d dev; + struct device_d *parent; struct list_head list; }; diff --git a/include/password.h b/include/password.h index 32301eb..540ab05 100644 --- a/include/password.h +++ b/include/password.h @@ -28,7 +28,7 @@ #define STAR (1 << 1) #define CLEAR (1 << 2) -int password(unsigned char *passwd, size_t length, int flags); +int password(unsigned char *passwd, size_t length, int flags, int timeout); int read_passwd(unsigned char *sum, size_t length); int write_passwd(unsigned char *sum, size_t length); diff --git a/include/spi/flash.h b/include/spi/flash.h new file mode 100644 index 0000000..fe8d09b --- /dev/null +++ b/include/spi/flash.h @@ -0,0 +1,30 @@ +#ifndef LINUX_SPI_FLASH_H +#define LINUX_SPI_FLASH_H + +struct mtd_partition; + +/** + * struct flash_platform_data: board-specific flash data + * @name: optional flash device name (eg, as used with mtdparts=) + * @parts: optional array of mtd_partitions for static partitioning + * @nr_parts: number of mtd_partitions for static partitoning + * @type: optional flash device type (e.g. m25p80 vs m25p64), for use + * with chips that can't be queried for JEDEC or other IDs + * + * Board init code (in arch/.../mach-xxx/board-yyy.c files) can + * provide information about SPI flash parts (such as DataFlash) to + * help set up the device and its appropriate default partitioning. + * + * Note that for DataFlash, sizes for pages, blocks, and sectors are + * rarely powers of two; and partitions should be sector-aligned. + */ +struct flash_platform_data { + const char *name; + struct mtd_partition *parts; + unsigned int nr_parts; + char *type; + + /* we'll likely add more ... use JEDEC IDs, etc */ +}; + +#endif diff --git a/net/eth.c b/net/eth.c index 2a801f5..621cb59 100644 --- a/net/eth.c +++ b/net/eth.c @@ -199,6 +199,10 @@ strcpy(edev->dev.name, "eth"); edev->dev.id = -1; + + if (edev->parent) + dev_add_child(edev->parent, &edev->dev); + register_device(&edev->dev); dev->type_data = edev;