mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-09 01:28:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
22
arch/mips/mti-sead3/Makefile
Normal file
22
arch/mips/mti-sead3/Makefile
Normal file
|
@ -0,0 +1,22 @@
|
|||
#
|
||||
# Carsten Langgaard, carstenl@mips.com
|
||||
# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
|
||||
#
|
||||
# Copyright (C) 2008 Wind River Systems, Inc.
|
||||
# written by Ralf Baechle <ralf@linux-mips.org>
|
||||
#
|
||||
# Copyright (C) 2012 MIPS Technoligies, Inc. All rights reserved.
|
||||
# Steven J. Hill <sjhill@mips.com>
|
||||
#
|
||||
obj-y := sead3-lcd.o sead3-display.o sead3-init.o \
|
||||
sead3-int.o sead3-mtd.o sead3-net.o \
|
||||
sead3-platform.o sead3-reset.o \
|
||||
sead3-setup.o sead3-time.o
|
||||
|
||||
obj-y += sead3-i2c-dev.o sead3-i2c.o \
|
||||
leds-sead3.o sead3-leds.o
|
||||
|
||||
obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o
|
||||
obj-$(CONFIG_USB_EHCI_HCD) += sead3-ehci.o
|
||||
|
||||
CFLAGS_sead3-setup.o = -I$(src)/../../../scripts/dtc/libfdt
|
7
arch/mips/mti-sead3/Platform
Normal file
7
arch/mips/mti-sead3/Platform
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
# MIPS SEAD-3 board
|
||||
#
|
||||
platform-$(CONFIG_MIPS_SEAD3) += mti-sead3/
|
||||
cflags-$(CONFIG_MIPS_SEAD3) += -I$(srctree)/arch/mips/include/asm/mach-sead3
|
||||
load-$(CONFIG_MIPS_SEAD3) += 0xffffffff80100000
|
||||
all-$(CONFIG_MIPS_SEAD3) := $(COMPRESSION_FNAME).srec
|
107
arch/mips/mti-sead3/leds-sead3.c
Normal file
107
arch/mips/mti-sead3/leds-sead3.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#define DRVNAME "sead3-led"
|
||||
|
||||
static struct platform_device *pdev;
|
||||
|
||||
static void sead3_pled_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness value)
|
||||
{
|
||||
pr_debug("sead3_pled_set\n");
|
||||
writel(value, (void __iomem *)0xBF000210); /* FIXME */
|
||||
}
|
||||
|
||||
static void sead3_fled_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness value)
|
||||
{
|
||||
pr_debug("sead3_fled_set\n");
|
||||
writel(value, (void __iomem *)0xBF000218); /* FIXME */
|
||||
}
|
||||
|
||||
static struct led_classdev sead3_pled = {
|
||||
.name = "sead3::pled",
|
||||
.brightness_set = sead3_pled_set,
|
||||
.flags = LED_CORE_SUSPENDRESUME,
|
||||
};
|
||||
|
||||
static struct led_classdev sead3_fled = {
|
||||
.name = "sead3::fled",
|
||||
.brightness_set = sead3_fled_set,
|
||||
.flags = LED_CORE_SUSPENDRESUME,
|
||||
};
|
||||
|
||||
static int sead3_led_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = led_classdev_register(&pdev->dev, &sead3_pled);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = led_classdev_register(&pdev->dev, &sead3_fled);
|
||||
if (ret < 0)
|
||||
led_classdev_unregister(&sead3_pled);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sead3_led_remove(struct platform_device *pdev)
|
||||
{
|
||||
led_classdev_unregister(&sead3_pled);
|
||||
led_classdev_unregister(&sead3_fled);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver sead3_led_driver = {
|
||||
.probe = sead3_led_probe,
|
||||
.remove = sead3_led_remove,
|
||||
.driver = {
|
||||
.name = DRVNAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init sead3_led_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&sead3_led_driver);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
|
||||
if (IS_ERR(pdev)) {
|
||||
ret = PTR_ERR(pdev);
|
||||
platform_driver_unregister(&sead3_led_driver);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit sead3_led_exit(void)
|
||||
{
|
||||
platform_device_unregister(pdev);
|
||||
platform_driver_unregister(&sead3_led_driver);
|
||||
}
|
||||
|
||||
module_init(sead3_led_init);
|
||||
module_exit(sead3_led_exit);
|
||||
|
||||
MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>");
|
||||
MODULE_DESCRIPTION("SEAD3 LED driver");
|
||||
MODULE_LICENSE("GPL");
|
46
arch/mips/mti-sead3/sead3-console.c
Normal file
46
arch/mips/mti-sead3/sead3-console.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#define SEAD_UART1_REGS_BASE 0xbf000800 /* ttyS1 = DB9 port */
|
||||
#define SEAD_UART0_REGS_BASE 0xbf000900 /* ttyS0 = USB port */
|
||||
#define PORT(base_addr, offset) ((unsigned int __iomem *)(base_addr+(offset)*4))
|
||||
|
||||
static char console_port = 1;
|
||||
|
||||
static inline unsigned int serial_in(int offset, unsigned int base_addr)
|
||||
{
|
||||
return __raw_readl(PORT(base_addr, offset)) & 0xff;
|
||||
}
|
||||
|
||||
static inline void serial_out(int offset, int value, unsigned int base_addr)
|
||||
{
|
||||
__raw_writel(value, PORT(base_addr, offset));
|
||||
}
|
||||
|
||||
void __init fw_init_early_console(char port)
|
||||
{
|
||||
console_port = port;
|
||||
}
|
||||
|
||||
int prom_putchar(char c)
|
||||
{
|
||||
unsigned int base_addr;
|
||||
|
||||
base_addr = console_port ? SEAD_UART1_REGS_BASE : SEAD_UART0_REGS_BASE;
|
||||
|
||||
while ((serial_in(UART_LSR, base_addr) & UART_LSR_THRE) == 0)
|
||||
;
|
||||
|
||||
serial_out(UART_TX, c, base_addr);
|
||||
|
||||
return 1;
|
||||
}
|
77
arch/mips/mti-sead3/sead3-display.c
Normal file
77
arch/mips/mti-sead3/sead3-display.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/timer.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/mips-boards/generic.h>
|
||||
|
||||
static unsigned int display_count;
|
||||
static unsigned int max_display_count;
|
||||
|
||||
#define LCD_DISPLAY_POS_BASE 0x1f000400
|
||||
#define DISPLAY_LCDINSTRUCTION (0*2)
|
||||
#define DISPLAY_LCDDATA (1*2)
|
||||
#define DISPLAY_CPLDSTATUS (2*2)
|
||||
#define DISPLAY_CPLDDATA (3*2)
|
||||
#define LCD_SETDDRAM 0x80
|
||||
#define LCD_IR_BF 0x80
|
||||
|
||||
const char display_string[] = " LINUX ON SEAD3 ";
|
||||
|
||||
static void scroll_display_message(unsigned long data);
|
||||
static DEFINE_TIMER(mips_scroll_timer, scroll_display_message, HZ, 0);
|
||||
|
||||
static void lcd_wait(unsigned int __iomem *display)
|
||||
{
|
||||
/* Wait for CPLD state machine to become idle. */
|
||||
do { } while (__raw_readl(display + DISPLAY_CPLDSTATUS) & 1);
|
||||
|
||||
do {
|
||||
__raw_readl(display + DISPLAY_LCDINSTRUCTION);
|
||||
|
||||
/* Wait for CPLD state machine to become idle. */
|
||||
do { } while (__raw_readl(display + DISPLAY_CPLDSTATUS) & 1);
|
||||
} while (__raw_readl(display + DISPLAY_CPLDDATA) & LCD_IR_BF);
|
||||
}
|
||||
|
||||
void mips_display_message(const char *str)
|
||||
{
|
||||
static unsigned int __iomem *display;
|
||||
char ch;
|
||||
int i;
|
||||
|
||||
if (unlikely(display == NULL))
|
||||
display = ioremap_nocache(LCD_DISPLAY_POS_BASE,
|
||||
(8 * sizeof(int)));
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (*str)
|
||||
ch = *str++;
|
||||
else
|
||||
ch = ' ';
|
||||
lcd_wait(display);
|
||||
__raw_writel((LCD_SETDDRAM | i),
|
||||
(display + DISPLAY_LCDINSTRUCTION));
|
||||
lcd_wait(display);
|
||||
__raw_writel(ch, display + DISPLAY_LCDDATA);
|
||||
}
|
||||
}
|
||||
|
||||
static void scroll_display_message(unsigned long data)
|
||||
{
|
||||
mips_display_message(&display_string[display_count++]);
|
||||
if (display_count == max_display_count)
|
||||
display_count = 0;
|
||||
mod_timer(&mips_scroll_timer, jiffies + HZ);
|
||||
}
|
||||
|
||||
void mips_scroll_message(void)
|
||||
{
|
||||
del_timer_sync(&mips_scroll_timer);
|
||||
max_display_count = strlen(display_string) + 1 - 16;
|
||||
mod_timer(&mips_scroll_timer, jiffies + 1);
|
||||
}
|
47
arch/mips/mti-sead3/sead3-ehci.c
Normal file
47
arch/mips/mti-sead3/sead3-ehci.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
struct resource ehci_resources[] = {
|
||||
{
|
||||
.start = 0x1b200000,
|
||||
.end = 0x1b200fff,
|
||||
.flags = IORESOURCE_MEM
|
||||
},
|
||||
{
|
||||
.start = MIPS_CPU_IRQ_BASE + 2,
|
||||
.flags = IORESOURCE_IRQ
|
||||
}
|
||||
};
|
||||
|
||||
u64 sead3_usbdev_dma_mask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct platform_device ehci_device = {
|
||||
.name = "sead3-ehci",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &sead3_usbdev_dma_mask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32)
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(ehci_resources),
|
||||
.resource = ehci_resources
|
||||
};
|
||||
|
||||
static int __init ehci_init(void)
|
||||
{
|
||||
return platform_device_register(&ehci_device);
|
||||
}
|
||||
|
||||
module_init(ehci_init);
|
||||
|
||||
MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("EHCI probe driver for SEAD3");
|
33
arch/mips/mti-sead3/sead3-i2c-dev.c
Normal file
33
arch/mips/mti-sead3/sead3-i2c-dev.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
static struct i2c_board_info __initdata sead3_i2c_devices[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("adt7476", 0x2c),
|
||||
.irq = 0,
|
||||
},
|
||||
{
|
||||
I2C_BOARD_INFO("m41t80", 0x68),
|
||||
.irq = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init sead3_i2c_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = i2c_register_board_info(0, sead3_i2c_devices,
|
||||
ARRAY_SIZE(sead3_i2c_devices));
|
||||
if (err < 0)
|
||||
pr_err("sead3-i2c-dev: cannot register board I2C devices\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
arch_initcall(sead3_i2c_init);
|
405
arch/mips/mti-sead3/sead3-i2c-drv.c
Normal file
405
arch/mips/mti-sead3/sead3-i2c-drv.c
Normal file
|
@ -0,0 +1,405 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define PIC32_I2CxCON 0x0000
|
||||
#define PIC32_I2CCON_ON (1<<15)
|
||||
#define PIC32_I2CCON_ACKDT (1<<5)
|
||||
#define PIC32_I2CCON_ACKEN (1<<4)
|
||||
#define PIC32_I2CCON_RCEN (1<<3)
|
||||
#define PIC32_I2CCON_PEN (1<<2)
|
||||
#define PIC32_I2CCON_RSEN (1<<1)
|
||||
#define PIC32_I2CCON_SEN (1<<0)
|
||||
#define PIC32_I2CxCONCLR 0x0004
|
||||
#define PIC32_I2CxCONSET 0x0008
|
||||
#define PIC32_I2CxSTAT 0x0010
|
||||
#define PIC32_I2CxSTATCLR 0x0014
|
||||
#define PIC32_I2CSTAT_ACKSTAT (1<<15)
|
||||
#define PIC32_I2CSTAT_TRSTAT (1<<14)
|
||||
#define PIC32_I2CSTAT_BCL (1<<10)
|
||||
#define PIC32_I2CSTAT_IWCOL (1<<7)
|
||||
#define PIC32_I2CSTAT_I2COV (1<<6)
|
||||
#define PIC32_I2CxBRG 0x0040
|
||||
#define PIC32_I2CxTRN 0x0050
|
||||
#define PIC32_I2CxRCV 0x0060
|
||||
|
||||
static DEFINE_SPINLOCK(pic32_bus_lock);
|
||||
|
||||
static void __iomem *bus_xfer = (void __iomem *)0xbf000600;
|
||||
static void __iomem *bus_status = (void __iomem *)0xbf000060;
|
||||
|
||||
#define DELAY() udelay(100)
|
||||
|
||||
static inline unsigned int ioready(void)
|
||||
{
|
||||
return readl(bus_status) & 1;
|
||||
}
|
||||
|
||||
static inline void wait_ioready(void)
|
||||
{
|
||||
do { } while (!ioready());
|
||||
}
|
||||
|
||||
static inline void wait_ioclear(void)
|
||||
{
|
||||
do { } while (ioready());
|
||||
}
|
||||
|
||||
static inline void check_ioclear(void)
|
||||
{
|
||||
if (ioready()) {
|
||||
do {
|
||||
(void) readl(bus_xfer);
|
||||
DELAY();
|
||||
} while (ioready());
|
||||
}
|
||||
}
|
||||
|
||||
static u32 pic32_bus_readl(u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 status, val;
|
||||
|
||||
spin_lock_irqsave(&pic32_bus_lock, flags);
|
||||
|
||||
check_ioclear();
|
||||
writel((0x01 << 24) | (reg & 0x00ffffff), bus_xfer);
|
||||
DELAY();
|
||||
wait_ioready();
|
||||
status = readl(bus_xfer);
|
||||
DELAY();
|
||||
val = readl(bus_xfer);
|
||||
wait_ioclear();
|
||||
|
||||
spin_unlock_irqrestore(&pic32_bus_lock, flags);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void pic32_bus_writel(u32 val, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 status;
|
||||
|
||||
spin_lock_irqsave(&pic32_bus_lock, flags);
|
||||
|
||||
check_ioclear();
|
||||
writel((0x10 << 24) | (reg & 0x00ffffff), bus_xfer);
|
||||
DELAY();
|
||||
writel(val, bus_xfer);
|
||||
DELAY();
|
||||
wait_ioready();
|
||||
status = readl(bus_xfer);
|
||||
wait_ioclear();
|
||||
|
||||
spin_unlock_irqrestore(&pic32_bus_lock, flags);
|
||||
}
|
||||
|
||||
struct pic32_i2c_platform_data {
|
||||
u32 base;
|
||||
struct i2c_adapter adap;
|
||||
u32 xfer_timeout;
|
||||
u32 ack_timeout;
|
||||
u32 ctl_timeout;
|
||||
};
|
||||
|
||||
static inline void pic32_i2c_start(struct pic32_i2c_platform_data *adap)
|
||||
{
|
||||
pic32_bus_writel(PIC32_I2CCON_SEN, adap->base + PIC32_I2CxCONSET);
|
||||
}
|
||||
|
||||
static inline void pic32_i2c_stop(struct pic32_i2c_platform_data *adap)
|
||||
{
|
||||
pic32_bus_writel(PIC32_I2CCON_PEN, adap->base + PIC32_I2CxCONSET);
|
||||
}
|
||||
|
||||
static inline void pic32_i2c_ack(struct pic32_i2c_platform_data *adap)
|
||||
{
|
||||
pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR);
|
||||
pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
|
||||
}
|
||||
|
||||
static inline void pic32_i2c_nack(struct pic32_i2c_platform_data *adap)
|
||||
{
|
||||
pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET);
|
||||
pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
|
||||
}
|
||||
|
||||
static inline int pic32_i2c_idle(struct pic32_i2c_platform_data *adap)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adap->ctl_timeout; i++) {
|
||||
if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) &
|
||||
(PIC32_I2CCON_ACKEN | PIC32_I2CCON_RCEN |
|
||||
PIC32_I2CCON_PEN | PIC32_I2CCON_RSEN |
|
||||
PIC32_I2CCON_SEN)) == 0) &&
|
||||
((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
|
||||
(PIC32_I2CSTAT_TRSTAT)) == 0))
|
||||
return 0;
|
||||
udelay(1);
|
||||
}
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static inline u32 pic32_i2c_master_write(struct pic32_i2c_platform_data *adap,
|
||||
u32 byte)
|
||||
{
|
||||
pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN);
|
||||
return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
|
||||
PIC32_I2CSTAT_IWCOL;
|
||||
}
|
||||
|
||||
static inline u32 pic32_i2c_master_read(struct pic32_i2c_platform_data *adap)
|
||||
{
|
||||
pic32_bus_writel(PIC32_I2CCON_RCEN, adap->base + PIC32_I2CxCONSET);
|
||||
while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & PIC32_I2CCON_RCEN)
|
||||
;
|
||||
pic32_bus_writel(PIC32_I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR);
|
||||
return pic32_bus_readl(adap->base + PIC32_I2CxRCV);
|
||||
}
|
||||
|
||||
static int pic32_i2c_address(struct pic32_i2c_platform_data *adap,
|
||||
unsigned int addr, int rd)
|
||||
{
|
||||
pic32_i2c_idle(adap);
|
||||
pic32_i2c_start(adap);
|
||||
pic32_i2c_idle(adap);
|
||||
|
||||
addr <<= 1;
|
||||
if (rd)
|
||||
addr |= 1;
|
||||
|
||||
if (pic32_i2c_master_write(adap, addr))
|
||||
return -EIO;
|
||||
pic32_i2c_idle(adap);
|
||||
if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
|
||||
PIC32_I2CSTAT_ACKSTAT)
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sead3_i2c_read(struct pic32_i2c_platform_data *adap,
|
||||
unsigned char *buf, unsigned int len)
|
||||
{
|
||||
u32 data;
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (i < len) {
|
||||
data = pic32_i2c_master_read(adap);
|
||||
buf[i++] = data;
|
||||
if (i < len)
|
||||
pic32_i2c_ack(adap);
|
||||
else
|
||||
pic32_i2c_nack(adap);
|
||||
}
|
||||
|
||||
pic32_i2c_stop(adap);
|
||||
pic32_i2c_idle(adap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sead3_i2c_write(struct pic32_i2c_platform_data *adap,
|
||||
unsigned char *buf, unsigned int len)
|
||||
{
|
||||
int i;
|
||||
u32 data;
|
||||
|
||||
i = 0;
|
||||
while (i < len) {
|
||||
data = buf[i];
|
||||
if (pic32_i2c_master_write(adap, data))
|
||||
return -EIO;
|
||||
pic32_i2c_idle(adap);
|
||||
if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
|
||||
PIC32_I2CSTAT_ACKSTAT)
|
||||
return -EIO;
|
||||
i++;
|
||||
}
|
||||
|
||||
pic32_i2c_stop(adap);
|
||||
pic32_i2c_idle(adap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sead3_pic32_platform_xfer(struct i2c_adapter *i2c_adap,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
struct pic32_i2c_platform_data *adap = i2c_adap->algo_data;
|
||||
struct i2c_msg *p;
|
||||
int i, err = 0;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
#define __BUFSIZE 80
|
||||
int ii;
|
||||
static char buf[__BUFSIZE];
|
||||
char *b = buf;
|
||||
|
||||
p = &msgs[i];
|
||||
b += sprintf(buf, " [%d bytes]", p->len);
|
||||
if ((p->flags & I2C_M_RD) == 0) {
|
||||
for (ii = 0; ii < p->len; ii++) {
|
||||
if (b < &buf[__BUFSIZE-4]) {
|
||||
b += sprintf(b, " %02x", p->buf[ii]);
|
||||
} else {
|
||||
strcat(b, "...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; !err && i < num; i++) {
|
||||
p = &msgs[i];
|
||||
err = pic32_i2c_address(adap, p->addr, p->flags & I2C_M_RD);
|
||||
if (err || !p->len)
|
||||
continue;
|
||||
if (p->flags & I2C_M_RD)
|
||||
err = sead3_i2c_read(adap, p->buf, p->len);
|
||||
else
|
||||
err = sead3_i2c_write(adap, p->buf, p->len);
|
||||
}
|
||||
|
||||
/* Return the number of messages processed, or the error code. */
|
||||
if (err == 0)
|
||||
err = num;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static u32 sead3_pic32_platform_func(struct i2c_adapter *adap)
|
||||
{
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm sead3_platform_algo = {
|
||||
.master_xfer = sead3_pic32_platform_xfer,
|
||||
.functionality = sead3_pic32_platform_func,
|
||||
};
|
||||
|
||||
static void sead3_i2c_platform_setup(struct pic32_i2c_platform_data *priv)
|
||||
{
|
||||
pic32_bus_writel(500, priv->base + PIC32_I2CxBRG);
|
||||
pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONCLR);
|
||||
pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONSET);
|
||||
pic32_bus_writel(PIC32_I2CSTAT_BCL | PIC32_I2CSTAT_IWCOL,
|
||||
priv->base + PIC32_I2CxSTATCLR);
|
||||
}
|
||||
|
||||
static int sead3_i2c_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct pic32_i2c_platform_data *priv;
|
||||
struct resource *r;
|
||||
int ret;
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!r) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv = kzalloc(sizeof(struct pic32_i2c_platform_data), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv->base = r->start;
|
||||
if (!priv->base) {
|
||||
ret = -EBUSY;
|
||||
goto out_mem;
|
||||
}
|
||||
|
||||
priv->xfer_timeout = 200;
|
||||
priv->ack_timeout = 200;
|
||||
priv->ctl_timeout = 200;
|
||||
|
||||
priv->adap.nr = pdev->id;
|
||||
priv->adap.algo = &sead3_platform_algo;
|
||||
priv->adap.algo_data = priv;
|
||||
priv->adap.dev.parent = &pdev->dev;
|
||||
strlcpy(priv->adap.name, "SEAD3 PIC32", sizeof(priv->adap.name));
|
||||
|
||||
sead3_i2c_platform_setup(priv);
|
||||
|
||||
ret = i2c_add_numbered_adapter(&priv->adap);
|
||||
if (ret == 0) {
|
||||
platform_set_drvdata(pdev, priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
out_mem:
|
||||
kfree(priv);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sead3_i2c_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
i2c_del_adapter(&priv->adap);
|
||||
kfree(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int sead3_i2c_platform_suspend(struct platform_device *pdev,
|
||||
pm_message_t state)
|
||||
{
|
||||
dev_dbg(&pdev->dev, "i2c_platform_disable\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sead3_i2c_platform_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev);
|
||||
|
||||
dev_dbg(&pdev->dev, "sead3_i2c_platform_setup\n");
|
||||
sead3_i2c_platform_setup(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define sead3_i2c_platform_suspend NULL
|
||||
#define sead3_i2c_platform_resume NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver sead3_i2c_platform_driver = {
|
||||
.driver = {
|
||||
.name = "sead3-i2c",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = sead3_i2c_platform_probe,
|
||||
.remove = sead3_i2c_platform_remove,
|
||||
.suspend = sead3_i2c_platform_suspend,
|
||||
.resume = sead3_i2c_platform_resume,
|
||||
};
|
||||
|
||||
static int __init sead3_i2c_platform_init(void)
|
||||
{
|
||||
return platform_driver_register(&sead3_i2c_platform_driver);
|
||||
}
|
||||
module_init(sead3_i2c_platform_init);
|
||||
|
||||
static void __exit sead3_i2c_platform_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&sead3_i2c_platform_driver);
|
||||
}
|
||||
module_exit(sead3_i2c_platform_exit);
|
||||
|
||||
MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC.");
|
||||
MODULE_DESCRIPTION("SEAD3 PIC32 I2C driver");
|
||||
MODULE_LICENSE("GPL");
|
31
arch/mips/mti-sead3/sead3-i2c.c
Normal file
31
arch/mips/mti-sead3/sead3-i2c.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
struct resource sead3_i2c_resources[] = {
|
||||
{
|
||||
.start = 0x805200,
|
||||
.end = 0x8053ff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device sead3_i2c_device = {
|
||||
.name = "sead3-i2c",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(sead3_i2c_resources),
|
||||
.resource = sead3_i2c_resources,
|
||||
};
|
||||
|
||||
static int __init sead3_i2c_init(void)
|
||||
{
|
||||
return platform_device_register(&sead3_i2c_device);
|
||||
}
|
||||
|
||||
device_initcall(sead3_i2c_init);
|
152
arch/mips/mti-sead3/sead3-init.c
Normal file
152
arch/mips/mti-sead3/sead3-init.c
Normal file
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/mips-boards/generic.h>
|
||||
#include <asm/fw/fw.h>
|
||||
|
||||
extern char except_vec_nmi;
|
||||
extern char except_vec_ejtag_debug;
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
static void __init console_config(void)
|
||||
{
|
||||
char console_string[40];
|
||||
int baud = 0;
|
||||
char parity = '\0', bits = '\0', flow = '\0';
|
||||
char *s;
|
||||
|
||||
if ((strstr(fw_getcmdline(), "console=")) == NULL) {
|
||||
s = fw_getenv("modetty0");
|
||||
if (s) {
|
||||
while (*s >= '0' && *s <= '9')
|
||||
baud = baud*10 + *s++ - '0';
|
||||
if (*s == ',')
|
||||
s++;
|
||||
if (*s)
|
||||
parity = *s++;
|
||||
if (*s == ',')
|
||||
s++;
|
||||
if (*s)
|
||||
bits = *s++;
|
||||
if (*s == ',')
|
||||
s++;
|
||||
if (*s == 'h')
|
||||
flow = 'r';
|
||||
}
|
||||
if (baud == 0)
|
||||
baud = 38400;
|
||||
if (parity != 'n' && parity != 'o' && parity != 'e')
|
||||
parity = 'n';
|
||||
if (bits != '7' && bits != '8')
|
||||
bits = '8';
|
||||
if (flow == '\0')
|
||||
flow = 'r';
|
||||
sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
|
||||
parity, bits, flow);
|
||||
strcat(fw_getcmdline(), console_string);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __init mips_nmi_setup(void)
|
||||
{
|
||||
void *base;
|
||||
|
||||
base = cpu_has_veic ?
|
||||
(void *)(CAC_BASE + 0xa80) :
|
||||
(void *)(CAC_BASE + 0x380);
|
||||
#ifdef CONFIG_CPU_MICROMIPS
|
||||
/*
|
||||
* Decrement the exception vector address by one for microMIPS.
|
||||
*/
|
||||
memcpy(base, (&except_vec_nmi - 1), 0x80);
|
||||
|
||||
/*
|
||||
* This is a hack. We do not know if the boot loader was built with
|
||||
* microMIPS instructions or not. If it was not, the NMI exception
|
||||
* code at 0x80000a80 will be taken in MIPS32 mode. The hand coded
|
||||
* assembly below forces us into microMIPS mode if we are a pure
|
||||
* microMIPS kernel. The assembly instructions are:
|
||||
*
|
||||
* 3C1A8000 lui k0,0x8000
|
||||
* 375A0381 ori k0,k0,0x381
|
||||
* 03400008 jr k0
|
||||
* 00000000 nop
|
||||
*
|
||||
* The mode switch occurs by jumping to the unaligned exception
|
||||
* vector address at 0x80000381 which would have been 0x80000380
|
||||
* in MIPS32 mode. The jump to the unaligned address transitions
|
||||
* us into microMIPS mode.
|
||||
*/
|
||||
if (!cpu_has_veic) {
|
||||
void *base2 = (void *)(CAC_BASE + 0xa80);
|
||||
*((unsigned int *)base2) = 0x3c1a8000;
|
||||
*((unsigned int *)base2 + 1) = 0x375a0381;
|
||||
*((unsigned int *)base2 + 2) = 0x03400008;
|
||||
*((unsigned int *)base2 + 3) = 0x00000000;
|
||||
flush_icache_range((unsigned long)base2,
|
||||
(unsigned long)base2 + 0x10);
|
||||
}
|
||||
#else
|
||||
memcpy(base, &except_vec_nmi, 0x80);
|
||||
#endif
|
||||
flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
|
||||
}
|
||||
|
||||
static void __init mips_ejtag_setup(void)
|
||||
{
|
||||
void *base;
|
||||
|
||||
base = cpu_has_veic ?
|
||||
(void *)(CAC_BASE + 0xa00) :
|
||||
(void *)(CAC_BASE + 0x300);
|
||||
#ifdef CONFIG_CPU_MICROMIPS
|
||||
/* Deja vu... */
|
||||
memcpy(base, (&except_vec_ejtag_debug - 1), 0x80);
|
||||
if (!cpu_has_veic) {
|
||||
void *base2 = (void *)(CAC_BASE + 0xa00);
|
||||
*((unsigned int *)base2) = 0x3c1a8000;
|
||||
*((unsigned int *)base2 + 1) = 0x375a0301;
|
||||
*((unsigned int *)base2 + 2) = 0x03400008;
|
||||
*((unsigned int *)base2 + 3) = 0x00000000;
|
||||
flush_icache_range((unsigned long)base2,
|
||||
(unsigned long)base2 + 0x10);
|
||||
}
|
||||
#else
|
||||
memcpy(base, &except_vec_ejtag_debug, 0x80);
|
||||
#endif
|
||||
flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
|
||||
}
|
||||
|
||||
void __init prom_init(void)
|
||||
{
|
||||
board_nmi_handler_setup = mips_nmi_setup;
|
||||
board_ejtag_handler_setup = mips_ejtag_setup;
|
||||
|
||||
fw_init_cmdline();
|
||||
#ifdef CONFIG_EARLY_PRINTK
|
||||
if ((strstr(fw_getcmdline(), "console=ttyS0")) != NULL)
|
||||
fw_init_early_console(0);
|
||||
else if ((strstr(fw_getcmdline(), "console=ttyS1")) != NULL)
|
||||
fw_init_early_console(1);
|
||||
#endif
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
if ((strstr(fw_getcmdline(), "console=")) == NULL)
|
||||
strcat(fw_getcmdline(), " console=ttyS0,38400n8r");
|
||||
console_config();
|
||||
#endif
|
||||
}
|
||||
|
||||
void prom_free_prom_memory(void)
|
||||
{
|
||||
}
|
157
arch/mips/mti-sead3/sead3-int.c
Normal file
157
arch/mips/mti-sead3/sead3-int.c
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/gic.h>
|
||||
#include <asm/irq_cpu.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include <asm/mips-boards/sead3int.h>
|
||||
|
||||
#define SEAD_CONFIG_GIC_PRESENT_SHF 1
|
||||
#define SEAD_CONFIG_GIC_PRESENT_MSK (1 << SEAD_CONFIG_GIC_PRESENT_SHF)
|
||||
#define SEAD_CONFIG_BASE 0x1b100110
|
||||
#define SEAD_CONFIG_SIZE 4
|
||||
|
||||
static unsigned long sead3_config_reg;
|
||||
|
||||
/*
|
||||
* This table defines the setup for each external GIC interrupt. It is
|
||||
* indexed by interrupt number.
|
||||
*/
|
||||
#define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
|
||||
static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
|
||||
{ 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
|
||||
{ 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
|
||||
{ 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
|
||||
{ 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
|
||||
{ 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
|
||||
{ 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
|
||||
{ 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
|
||||
{ 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
|
||||
{ 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
|
||||
{ GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
|
||||
{ GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
|
||||
{ GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
|
||||
{ GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
|
||||
{ GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
|
||||
{ GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
|
||||
{ GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
|
||||
};
|
||||
|
||||
asmlinkage void plat_irq_dispatch(void)
|
||||
{
|
||||
unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
|
||||
int irq;
|
||||
|
||||
irq = (fls(pending) - CAUSEB_IP - 1);
|
||||
if (irq >= 0)
|
||||
do_IRQ(MIPS_CPU_IRQ_BASE + irq);
|
||||
else
|
||||
spurious_interrupt();
|
||||
}
|
||||
|
||||
void __init arch_init_irq(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!cpu_has_veic) {
|
||||
mips_cpu_irq_init();
|
||||
|
||||
if (cpu_has_vint) {
|
||||
/* install generic handler */
|
||||
for (i = 0; i < 8; i++)
|
||||
set_vi_handler(i, plat_irq_dispatch);
|
||||
}
|
||||
}
|
||||
|
||||
sead3_config_reg = (unsigned long)ioremap_nocache(SEAD_CONFIG_BASE,
|
||||
SEAD_CONFIG_SIZE);
|
||||
gic_present = (REG32(sead3_config_reg) & SEAD_CONFIG_GIC_PRESENT_MSK) >>
|
||||
SEAD_CONFIG_GIC_PRESENT_SHF;
|
||||
pr_info("GIC: %spresent\n", (gic_present) ? "" : "not ");
|
||||
pr_info("EIC: %s\n",
|
||||
(current_cpu_data.options & MIPS_CPU_VEIC) ? "on" : "off");
|
||||
|
||||
if (gic_present)
|
||||
gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
|
||||
ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
|
||||
}
|
||||
|
||||
void gic_enable_interrupt(int irq_vec)
|
||||
{
|
||||
unsigned int i, irq_source;
|
||||
|
||||
/* enable all the interrupts associated with this vector */
|
||||
for (i = 0; i < gic_shared_intr_map[irq_vec].num_shared_intr; i++) {
|
||||
irq_source = gic_shared_intr_map[irq_vec].intr_list[i];
|
||||
GIC_SET_INTR_MASK(irq_source);
|
||||
}
|
||||
/* enable all local interrupts associated with this vector */
|
||||
if (gic_shared_intr_map[irq_vec].local_intr_mask) {
|
||||
GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0);
|
||||
GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_SMASK),
|
||||
gic_shared_intr_map[irq_vec].local_intr_mask);
|
||||
}
|
||||
}
|
||||
|
||||
void gic_disable_interrupt(int irq_vec)
|
||||
{
|
||||
unsigned int i, irq_source;
|
||||
|
||||
/* disable all the interrupts associated with this vector */
|
||||
for (i = 0; i < gic_shared_intr_map[irq_vec].num_shared_intr; i++) {
|
||||
irq_source = gic_shared_intr_map[irq_vec].intr_list[i];
|
||||
GIC_CLR_INTR_MASK(irq_source);
|
||||
}
|
||||
/* disable all local interrupts associated with this vector */
|
||||
if (gic_shared_intr_map[irq_vec].local_intr_mask) {
|
||||
GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0);
|
||||
GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_RMASK),
|
||||
gic_shared_intr_map[irq_vec].local_intr_mask);
|
||||
}
|
||||
}
|
||||
|
||||
void gic_irq_ack(struct irq_data *d)
|
||||
{
|
||||
GIC_CLR_INTR_MASK(d->irq - gic_irq_base);
|
||||
}
|
||||
|
||||
void gic_finish_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned int irq = (d->irq - gic_irq_base);
|
||||
unsigned int i, irq_source;
|
||||
|
||||
/* Clear edge detectors. */
|
||||
for (i = 0; i < gic_shared_intr_map[irq].num_shared_intr; i++) {
|
||||
irq_source = gic_shared_intr_map[irq].intr_list[i];
|
||||
if (gic_irq_flags[irq_source] & GIC_TRIG_EDGE)
|
||||
GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq_source);
|
||||
}
|
||||
|
||||
/* Enable interrupts. */
|
||||
GIC_SET_INTR_MASK(irq);
|
||||
}
|
||||
|
||||
void __init gic_platform_init(int irqs, struct irq_chip *irq_controller)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* For non-EIC mode, we want to setup the GIC in pass-through
|
||||
* mode, as if the GIC didn't exist. Do not map any interrupts
|
||||
* for an external interrupt controller.
|
||||
*/
|
||||
if (!cpu_has_veic)
|
||||
return;
|
||||
|
||||
for (i = gic_irq_base; i < (gic_irq_base + irqs); i++)
|
||||
irq_set_chip_and_handler(i, irq_controller, handle_percpu_irq);
|
||||
}
|
43
arch/mips/mti-sead3/sead3-lcd.c
Normal file
43
arch/mips/mti-sead3/sead3-lcd.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
static struct resource __initdata sead3_lcd_resource = {
|
||||
.start = 0x1f000400,
|
||||
.end = 0x1f00041f,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
static __init int sead3_lcd_add(void)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
int retval;
|
||||
|
||||
/* SEAD-3 and Cobalt platforms use same display type. */
|
||||
pdev = platform_device_alloc("cobalt-lcd", -1);
|
||||
if (!pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
retval = platform_device_add_resources(pdev, &sead3_lcd_resource, 1);
|
||||
if (retval)
|
||||
goto err_free_device;
|
||||
|
||||
retval = platform_device_add(pdev);
|
||||
if (retval)
|
||||
goto err_free_device;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_device:
|
||||
platform_device_put(pdev);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
device_initcall(sead3_lcd_add);
|
79
arch/mips/mti-sead3/sead3-leds.c
Normal file
79
arch/mips/mti-sead3/sead3-leds.c
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define LEDFLAGS(bits, shift) \
|
||||
((bits << 8) | (shift << 8))
|
||||
|
||||
#define LEDBITS(id, shift, bits) \
|
||||
.name = id #shift, \
|
||||
.flags = LEDFLAGS(bits, shift)
|
||||
|
||||
struct led_info led_data_info[] = {
|
||||
{ LEDBITS("bit", 0, 1) },
|
||||
{ LEDBITS("bit", 1, 1) },
|
||||
{ LEDBITS("bit", 2, 1) },
|
||||
{ LEDBITS("bit", 3, 1) },
|
||||
{ LEDBITS("bit", 4, 1) },
|
||||
{ LEDBITS("bit", 5, 1) },
|
||||
{ LEDBITS("bit", 6, 1) },
|
||||
{ LEDBITS("bit", 7, 1) },
|
||||
{ LEDBITS("all", 0, 8) },
|
||||
};
|
||||
|
||||
static struct led_platform_data led_data = {
|
||||
.num_leds = ARRAY_SIZE(led_data_info),
|
||||
.leds = led_data_info
|
||||
};
|
||||
|
||||
static struct resource pled_resources[] = {
|
||||
{
|
||||
.start = 0x1f000210,
|
||||
.end = 0x1f000217,
|
||||
.flags = IORESOURCE_MEM
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device pled_device = {
|
||||
.name = "sead3::pled",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &led_data,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(pled_resources),
|
||||
.resource = pled_resources
|
||||
};
|
||||
|
||||
|
||||
static struct resource fled_resources[] = {
|
||||
{
|
||||
.start = 0x1f000218,
|
||||
.end = 0x1f00021f,
|
||||
.flags = IORESOURCE_MEM
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device fled_device = {
|
||||
.name = "sead3::fled",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &led_data,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(fled_resources),
|
||||
.resource = fled_resources
|
||||
};
|
||||
|
||||
static int __init led_init(void)
|
||||
{
|
||||
platform_device_register(&pled_device);
|
||||
return platform_device_register(&fled_device);
|
||||
}
|
||||
|
||||
device_initcall(led_init);
|
53
arch/mips/mti-sead3/sead3-mtd.c
Normal file
53
arch/mips/mti-sead3/sead3-mtd.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
|
||||
static struct mtd_partition sead3_mtd_partitions[] = {
|
||||
{
|
||||
.name = "User FS",
|
||||
.offset = 0x00000000,
|
||||
.size = 0x01fc0000,
|
||||
}, {
|
||||
.name = "Board Config",
|
||||
.offset = 0x01fc0000,
|
||||
.size = 0x00040000,
|
||||
.mask_flags = MTD_WRITEABLE
|
||||
},
|
||||
};
|
||||
|
||||
static struct physmap_flash_data sead3_flash_data = {
|
||||
.width = 4,
|
||||
.nr_parts = ARRAY_SIZE(sead3_mtd_partitions),
|
||||
.parts = sead3_mtd_partitions
|
||||
};
|
||||
|
||||
static struct resource sead3_flash_resource = {
|
||||
.start = 0x1c000000,
|
||||
.end = 0x1dffffff,
|
||||
.flags = IORESOURCE_MEM
|
||||
};
|
||||
|
||||
static struct platform_device sead3_flash = {
|
||||
.name = "physmap-flash",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &sead3_flash_data,
|
||||
},
|
||||
.num_resources = 1,
|
||||
.resource = &sead3_flash_resource,
|
||||
};
|
||||
|
||||
static int __init sead3_mtd_init(void)
|
||||
{
|
||||
platform_device_register(&sead3_flash);
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(sead3_mtd_init);
|
51
arch/mips/mti-sead3/sead3-net.c
Normal file
51
arch/mips/mti-sead3/sead3-net.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/smsc911x.h>
|
||||
|
||||
static struct smsc911x_platform_config sead3_smsc911x_data = {
|
||||
.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
|
||||
.irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
|
||||
.flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
|
||||
.phy_interface = PHY_INTERFACE_MODE_MII,
|
||||
};
|
||||
|
||||
struct resource sead3_net_resourcess[] = {
|
||||
{
|
||||
.start = 0x1f010000,
|
||||
.end = 0x1f01ffff,
|
||||
.flags = IORESOURCE_MEM
|
||||
},
|
||||
{
|
||||
.start = MIPS_CPU_IRQ_BASE + 6,
|
||||
.flags = IORESOURCE_IRQ
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device sead3_net_device = {
|
||||
.name = "smsc911x",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &sead3_smsc911x_data,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(sead3_net_resourcess),
|
||||
.resource = sead3_net_resourcess
|
||||
};
|
||||
|
||||
static int __init sead3_net_init(void)
|
||||
{
|
||||
return platform_device_register(&sead3_net_device);
|
||||
}
|
||||
|
||||
module_init(sead3_net_init);
|
||||
|
||||
MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Network probe driver for SEAD-3");
|
45
arch/mips/mti-sead3/sead3-platform.c
Normal file
45
arch/mips/mti-sead3/sead3-platform.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serial_8250.h>
|
||||
|
||||
#define UART(base, int) \
|
||||
{ \
|
||||
.mapbase = base, \
|
||||
.irq = int, \
|
||||
.uartclk = 14745600, \
|
||||
.iotype = UPIO_MEM32, \
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \
|
||||
.regshift = 2, \
|
||||
}
|
||||
|
||||
static struct plat_serial8250_port uart8250_data[] = {
|
||||
UART(0x1f000900, MIPS_CPU_IRQ_BASE + 4), /* ttyS0 = USB */
|
||||
UART(0x1f000800, MIPS_CPU_IRQ_BASE + 4), /* ttyS1 = RS232 */
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_device uart8250_device = {
|
||||
.name = "serial8250",
|
||||
.id = PLAT8250_DEV_PLATFORM2,
|
||||
.dev = {
|
||||
.platform_data = uart8250_data,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init uart8250_init(void)
|
||||
{
|
||||
return platform_device_register(&uart8250_device);
|
||||
}
|
||||
|
||||
module_init(uart8250_init);
|
||||
|
||||
MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("8250 UART probe driver for SEAD3");
|
40
arch/mips/mti-sead3/sead3-reset.c
Normal file
40
arch/mips/mti-sead3/sead3-reset.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/io.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include <asm/reboot.h>
|
||||
|
||||
#define SOFTRES_REG 0x1f000050
|
||||
#define GORESET 0x4d
|
||||
|
||||
static void mips_machine_restart(char *command)
|
||||
{
|
||||
unsigned int __iomem *softres_reg =
|
||||
ioremap(SOFTRES_REG, sizeof(unsigned int));
|
||||
|
||||
__raw_writel(GORESET, softres_reg);
|
||||
}
|
||||
|
||||
static void mips_machine_halt(void)
|
||||
{
|
||||
unsigned int __iomem *softres_reg =
|
||||
ioremap(SOFTRES_REG, sizeof(unsigned int));
|
||||
|
||||
__raw_writel(GORESET, softres_reg);
|
||||
}
|
||||
|
||||
static int __init mips_reboot_setup(void)
|
||||
{
|
||||
_machine_restart = mips_machine_restart;
|
||||
_machine_halt = mips_machine_halt;
|
||||
pm_power_off = mips_machine_halt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(mips_reboot_setup);
|
45
arch/mips/mti-sead3/sead3-serial.c
Normal file
45
arch/mips/mti-sead3/sead3-serial.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serial_8250.h>
|
||||
|
||||
#define UART(base, int) \
|
||||
{ \
|
||||
.mapbase = base, \
|
||||
.irq = int, \
|
||||
.uartclk = 14745600, \
|
||||
.iotype = UPIO_MEM32, \
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \
|
||||
.regshift = 2, \
|
||||
}
|
||||
|
||||
static struct plat_serial8250_port uart8250_data[] = {
|
||||
UART(0x1f000900, MIPS_CPU_IRQ_BASE + 4), /* ttyS0 = USB */
|
||||
UART(0x1f000800, MIPS_CPU_IRQ_BASE + 4), /* ttyS1 = RS232 */
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_device uart8250_device = {
|
||||
.name = "serial8250",
|
||||
.id = PLAT8250_DEV_PLATFORM,
|
||||
.dev = {
|
||||
.platform_data = uart8250_data,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init uart8250_init(void)
|
||||
{
|
||||
return platform_device_register(&uart8250_device);
|
||||
}
|
||||
|
||||
module_init(uart8250_init);
|
||||
|
||||
MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("8250 UART probe driver for the SEAD-3 platform");
|
111
arch/mips/mti-sead3/sead3-setup.c
Normal file
111
arch/mips/mti-sead3/sead3-setup.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
* Copyright (C) 2013 Imagination Technologies Ltd.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_fdt.h>
|
||||
|
||||
#include <asm/prom.h>
|
||||
#include <asm/fw/fw.h>
|
||||
|
||||
#include <asm/mips-boards/generic.h>
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "MIPS SEAD3";
|
||||
}
|
||||
|
||||
static uint32_t get_memsize_from_cmdline(void)
|
||||
{
|
||||
int memsize = 0;
|
||||
char *p = arcs_cmdline;
|
||||
char *s = "memsize=";
|
||||
|
||||
p = strstr(p, s);
|
||||
if (p) {
|
||||
p += strlen(s);
|
||||
memsize = memparse(p, NULL);
|
||||
}
|
||||
|
||||
return memsize;
|
||||
}
|
||||
|
||||
static uint32_t get_memsize_from_env(void)
|
||||
{
|
||||
int memsize = 0;
|
||||
char *p;
|
||||
|
||||
p = fw_getenv("memsize");
|
||||
if (p)
|
||||
memsize = memparse(p, NULL);
|
||||
|
||||
return memsize;
|
||||
}
|
||||
|
||||
static uint32_t get_memsize(void)
|
||||
{
|
||||
uint32_t memsize;
|
||||
|
||||
memsize = get_memsize_from_cmdline();
|
||||
if (memsize)
|
||||
return memsize;
|
||||
|
||||
return get_memsize_from_env();
|
||||
}
|
||||
|
||||
static void __init parse_memsize_param(void)
|
||||
{
|
||||
int offset;
|
||||
const uint64_t *prop_value;
|
||||
int prop_len;
|
||||
uint32_t memsize = get_memsize();
|
||||
|
||||
if (!memsize)
|
||||
return;
|
||||
|
||||
offset = fdt_path_offset(__dtb_start, "/memory");
|
||||
if (offset > 0) {
|
||||
uint64_t new_value;
|
||||
/*
|
||||
* reg contains 2 32-bits BE values, offset and size. We just
|
||||
* want to replace the size value without affecting the offset
|
||||
*/
|
||||
prop_value = fdt_getprop(__dtb_start, offset, "reg", &prop_len);
|
||||
new_value = be64_to_cpu(*prop_value);
|
||||
new_value = (new_value & ~0xffffffffllu) | memsize;
|
||||
fdt_setprop_inplace_u64(__dtb_start, offset, "reg", new_value);
|
||||
}
|
||||
}
|
||||
|
||||
void __init plat_mem_setup(void)
|
||||
{
|
||||
/* allow command line/bootloader env to override memory size in DT */
|
||||
parse_memsize_param();
|
||||
|
||||
/*
|
||||
* Load the builtin devicetree. This causes the chosen node to be
|
||||
* parsed resulting in our memory appearing
|
||||
*/
|
||||
__dt_setup_arch(__dtb_start);
|
||||
}
|
||||
|
||||
void __init device_tree_init(void)
|
||||
{
|
||||
if (!initial_boot_params)
|
||||
return;
|
||||
|
||||
unflatten_and_copy_device_tree();
|
||||
}
|
||||
|
||||
static int __init customize_machine(void)
|
||||
{
|
||||
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(customize_machine);
|
113
arch/mips/mti-sead3/sead3-time.c
Normal file
113
arch/mips/mti-sead3/sead3-time.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mips-boards/generic.h>
|
||||
|
||||
static int mips_cpu_timer_irq;
|
||||
static int mips_cpu_perf_irq;
|
||||
|
||||
static void mips_timer_dispatch(void)
|
||||
{
|
||||
do_IRQ(mips_cpu_timer_irq);
|
||||
}
|
||||
|
||||
static void mips_perf_dispatch(void)
|
||||
{
|
||||
do_IRQ(mips_cpu_perf_irq);
|
||||
}
|
||||
|
||||
static void __iomem *status_reg = (void __iomem *)0xbf000410;
|
||||
|
||||
/*
|
||||
* Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect.
|
||||
*/
|
||||
static unsigned int __init estimate_cpu_frequency(void)
|
||||
{
|
||||
unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK);
|
||||
unsigned int tick = 0;
|
||||
unsigned int freq;
|
||||
unsigned int orig;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
orig = readl(status_reg) & 0x2; /* get original sample */
|
||||
/* wait for transition */
|
||||
while ((readl(status_reg) & 0x2) == orig)
|
||||
;
|
||||
orig = orig ^ 0x2; /* flip the bit */
|
||||
|
||||
write_c0_count(0);
|
||||
|
||||
/* wait 1 second (the sampling clock transitions every 10ms) */
|
||||
while (tick < 100) {
|
||||
/* wait for transition */
|
||||
while ((readl(status_reg) & 0x2) == orig)
|
||||
;
|
||||
orig = orig ^ 0x2; /* flip the bit */
|
||||
tick++;
|
||||
}
|
||||
|
||||
freq = read_c0_count();
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
mips_hpt_frequency = freq;
|
||||
|
||||
/* Adjust for processor */
|
||||
if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
|
||||
(prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
|
||||
freq *= 2;
|
||||
|
||||
freq += 5000; /* rounding */
|
||||
freq -= freq%10000;
|
||||
|
||||
return freq ;
|
||||
}
|
||||
|
||||
void read_persistent_clock(struct timespec *ts)
|
||||
{
|
||||
ts->tv_sec = 0;
|
||||
ts->tv_nsec = 0;
|
||||
}
|
||||
|
||||
static void __init plat_perf_setup(void)
|
||||
{
|
||||
if (cp0_perfcount_irq >= 0) {
|
||||
if (cpu_has_vint)
|
||||
set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
|
||||
mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int get_c0_compare_int(void)
|
||||
{
|
||||
if (cpu_has_vint)
|
||||
set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
|
||||
mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
|
||||
return mips_cpu_timer_irq;
|
||||
}
|
||||
|
||||
void __init plat_time_init(void)
|
||||
{
|
||||
unsigned int est_freq;
|
||||
|
||||
est_freq = estimate_cpu_frequency();
|
||||
|
||||
pr_debug("CPU frequency %d.%02d MHz\n", (est_freq / 1000000),
|
||||
(est_freq % 1000000) * 100 / 1000000);
|
||||
|
||||
mips_scroll_message();
|
||||
|
||||
plat_perf_setup();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue